diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 446 |
1 files changed, 271 insertions, 175 deletions
@@ -22,6 +22,7 @@ #include <dirent.h> #include <sys/select.h> #include <sys/stat.h> +#include <sys/time.h> #include <X11/Xlib.h> #include <X11/Xutil.h> @@ -29,15 +30,23 @@ #include "image.h" #include "options.h" +#include "thumbs.h" #include "util.h" #include "window.h" +typedef enum appmode_e { + MODE_NORMAL = 0, + MODE_THUMBS +} appmode_t; + void update_title(); int check_append(const char*); void read_dir_rec(const char*); void run(); +appmode_t mode; img_t img; +tns_t tns; win_t win; #define DNAME_CNT 512 @@ -54,6 +63,7 @@ void cleanup() { if (!in++) { img_free(&img); + tns_free(&tns, &win); win_close(&win); } } @@ -119,12 +129,21 @@ int main(int argc, char **argv) { win_open(&win); img_init(&img, &win); - load_image(); - img_render(&img, &win); - update_title(); + if (options->thumbnails) + tns_init(&tns, filecnt); - run(); + if (options->thumbnails == 2) { + mode = MODE_THUMBS; + win_clear(&win); + win_draw(&win); + } else { + mode = MODE_NORMAL; + load_image(); + img_render(&img, &win); + } + update_title(); + run(); cleanup(); return 0; @@ -135,15 +154,21 @@ void update_title() { float size; const char *unit; - if (img.valid) { - size = filesize; - size_readable(&size, &unit); - n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] <%d%%> (%.2f%s) %s", - fileidx + 1, filecnt, (int) (img.zoom * 100.0), size, unit, - filenames[fileidx]); + if (mode == MODE_THUMBS) { + n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] %s", + tns.cnt ? tns.sel + 1 : 0, tns.cnt, + tns.cnt ? filenames[tns.sel] : ""); } else { - n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] broken: %s", - fileidx + 1, filecnt, filenames[fileidx]); + if (img.valid) { + size = filesize; + size_readable(&size, &unit); + n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] <%d%%> (%.2f%s) %s", + fileidx + 1, filecnt, (int) (img.zoom * 100.0), size, unit, + filenames[fileidx]); + } else { + n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] broken: %s", + fileidx + 1, filecnt, filenames[fileidx]); + } } if (n >= TITLE_LEN) { @@ -233,12 +258,21 @@ void read_dir_rec(const char *dirname) { int timeout; int mox, moy; +void redraw() { + if (mode == MODE_NORMAL) + img_render(&img, &win); + else + tns_render(&tns, &win); + update_title(); + timeout = 0; +} + void on_keypress(XKeyEvent *kev) { int x, y; unsigned int w, h; char key; KeySym ksym; - int changed; + int changed, sel; if (!kev) return; @@ -246,6 +280,147 @@ void on_keypress(XKeyEvent *kev) { XLookupString(kev, &key, 1, &ksym, NULL); changed = 0; + if (mode == MODE_NORMAL) { + switch (ksym) { + /* navigate image list */ + case XK_n: + case XK_space: + if (fileidx + 1 < filecnt) { + ++fileidx; + changed = load_image(); + } + break; + case XK_p: + case XK_BackSpace: + if (fileidx > 0) { + --fileidx; + changed = load_image(); + } + break; + case XK_bracketleft: + if (fileidx != 0) { + fileidx = MAX(0, fileidx - 10); + changed = load_image(); + } + break; + case XK_bracketright: + if (fileidx != filecnt - 1) { + fileidx = MIN(fileidx + 10, filecnt - 1); + changed = load_image(); + } + break; + case XK_g: + if (fileidx != 0) { + fileidx = 0; + changed = load_image(); + } + break; + case XK_G: + if (fileidx != filecnt - 1) { + fileidx = filecnt - 1; + changed = load_image(); + } + break; + + /* zooming */ + case XK_plus: + case XK_equal: + changed = img_zoom_in(&img); + break; + case XK_minus: + changed = img_zoom_out(&img); + break; + case XK_0: + changed = img_zoom(&img, 1.0); + break; + case XK_w: + if ((changed = img_fit_win(&img, &win))) + img_center(&img, &win); + break; + + /* panning */ + case XK_h: + case XK_Left: + changed = img_pan(&img, &win, PAN_LEFT); + break; + case XK_j: + case XK_Down: + changed = img_pan(&img, &win, PAN_DOWN); + break; + case XK_k: + case XK_Up: + changed = img_pan(&img, &win, PAN_UP); + break; + case XK_l: + case XK_Right: + changed = img_pan(&img, &win, PAN_RIGHT); + break; + + /* rotation */ + case XK_less: + img_rotate_left(&img, &win); + changed = 1; + break; + case XK_greater: + img_rotate_right(&img, &win); + changed = 1; + break; + + /* control window */ + case XK_W: + x = win.x + img.x; + y = win.y + img.y; + w = img.w * img.zoom; + h = img.h * img.zoom; + if ((changed = win_moveresize(&win, x, y, w, h))) { + img.x = x - win.x; + img.y = y - win.y; + } + break; + + /* miscellaneous */ + case XK_a: + img_toggle_antialias(&img); + changed = 1; + break; + case XK_r: + changed = load_image(); + break; + } + } else { + /* thumbnail mode */ + sel = tns.sel; + + switch (ksym) { + /* open selected image */ + case XK_Return: + fileidx = sel; + load_image(); + mode = MODE_NORMAL; + changed = 1; + break; + + /* move selection */ + case XK_h: + case XK_Left: + tns_move_selection(&tns, &win, MOVE_LEFT); + break; + case XK_j: + case XK_Down: + tns_move_selection(&tns, &win, MOVE_DOWN); + break; + case XK_k: + case XK_Up: + tns_move_selection(&tns, &win, MOVE_UP); + break; + case XK_l: + case XK_Right: + tns_move_selection(&tns, &win, MOVE_RIGHT); + break; + } + } + + /* common key mappings */ switch (ksym) { case XK_Escape: cleanup(); @@ -253,126 +428,18 @@ void on_keypress(XKeyEvent *kev) { case XK_q: cleanup(); exit(0); - - /* navigate image list */ - case XK_n: - case XK_space: - if (fileidx + 1 < filecnt) { - ++fileidx; - changed = load_image(); - } - break; - case XK_p: - case XK_BackSpace: - if (fileidx > 0) { - --fileidx; - changed = load_image(); - } - break; - case XK_bracketleft: - if (fileidx != 0) { - fileidx = MAX(0, fileidx - 10); - changed = load_image(); - } - break; - case XK_bracketright: - if (fileidx != filecnt - 1) { - fileidx = MIN(fileidx + 10, filecnt - 1); - changed = load_image(); - } - break; - case XK_g: - if (fileidx != 0) { - fileidx = 0; - changed = load_image(); - } - break; - case XK_G: - if (fileidx != filecnt - 1) { - fileidx = filecnt - 1; - changed = load_image(); - } - break; - - /* zooming */ - case XK_plus: - case XK_equal: - changed = img_zoom_in(&img); - break; - case XK_minus: - changed = img_zoom_out(&img); - break; - case XK_0: - changed = img_zoom(&img, 1.0); - break; - case XK_w: - if ((changed = img_fit_win(&img, &win))) - img_center(&img, &win); - break; - - /* panning */ - case XK_h: - case XK_Left: - changed = img_pan(&img, &win, PAN_LEFT); - break; - case XK_j: - case XK_Down: - changed = img_pan(&img, &win, PAN_DOWN); - break; - case XK_k: - case XK_Up: - changed = img_pan(&img, &win, PAN_UP); - break; - case XK_l: - case XK_Right: - changed = img_pan(&img, &win, PAN_RIGHT); - break; - - /* rotation */ - case XK_less: - img_rotate_left(&img, &win); - changed = 1; - break; - case XK_greater: - img_rotate_right(&img, &win); - changed = 1; - break; - - /* control window */ case XK_f: win_toggle_fullscreen(&win); /* render on next configurenotify */ break; - case XK_W: - x = win.x + img.x; - y = win.y + img.y; - w = img.w * img.zoom; - h = img.h * img.zoom; - if ((changed = win_moveresize(&win, x, y, w, h))) { - img.x = x - win.x; - img.y = y - win.y; - } - break; - - /* miscellaneous */ - case XK_a: - img_toggle_antialias(&img); - changed = 1; - break; - case XK_r: - changed = load_image(); - break; } - if (changed) { - img_render(&img, &win); - update_title(); - timeout = 0; - } + if (changed) + redraw(); } void on_buttonpress(XButtonEvent *bev) { - int changed; + int changed, sel; unsigned int mask; if (!bev) @@ -381,53 +448,65 @@ void on_buttonpress(XButtonEvent *bev) { mask = CLEANMASK(bev->state); changed = 0; - switch (bev->button) { - case Button1: - if (fileidx + 1 < filecnt) { - ++fileidx; - changed = load_image(); - } - break; - case Button2: - mox = bev->x; - moy = bev->y; - win_set_cursor(&win, CURSOR_HAND); - break; - case Button3: - if (fileidx > 0) { - --fileidx; - changed = load_image(); - } - break; - case Button4: - if (mask == ControlMask) - changed = img_zoom_in(&img); - else if (mask == ShiftMask) + if (mode == MODE_NORMAL) { + switch (bev->button) { + case Button1: + if (fileidx + 1 < filecnt) { + ++fileidx; + changed = load_image(); + } + break; + case Button2: + mox = bev->x; + moy = bev->y; + win_set_cursor(&win, CURSOR_HAND); + break; + case Button3: + if (fileidx > 0) { + --fileidx; + changed = load_image(); + } + break; + case Button4: + if (mask == ControlMask) + changed = img_zoom_in(&img); + else if (mask == ShiftMask) + changed = img_pan(&img, &win, PAN_LEFT); + else + changed = img_pan(&img, &win, PAN_UP); + break; + case Button5: + if (mask == ControlMask) + changed = img_zoom_out(&img); + else if (mask == ShiftMask) + changed = img_pan(&img, &win, PAN_RIGHT); + else + changed = img_pan(&img, &win, PAN_DOWN); + break; + case 6: changed = img_pan(&img, &win, PAN_LEFT); - else - changed = img_pan(&img, &win, PAN_UP); - break; - case Button5: - if (mask == ControlMask) - changed = img_zoom_out(&img); - else if (mask == ShiftMask) + break; + case 7: changed = img_pan(&img, &win, PAN_RIGHT); - else - changed = img_pan(&img, &win, PAN_DOWN); - break; - case 6: - changed = img_pan(&img, &win, PAN_LEFT); - break; - case 7: - changed = img_pan(&img, &win, PAN_RIGHT); - break; + break; + } + } else { + /* thumbnail mode */ + switch (bev->button) { + case Button1: + if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) { + fileidx = sel; + load_image(); + mode = MODE_NORMAL; + changed = 1; + break; + } + break; + } } - if (changed) { - img_render(&img, &win); - update_title(); - timeout = 0; - } + if (changed) + redraw(); } void on_motionnotify(XMotionEvent *mev) { @@ -446,23 +525,39 @@ void on_motionnotify(XMotionEvent *mev) { void run() { int xfd; fd_set fds; - struct timeval t; + struct timeval t, t0; XEvent ev; timeout = 0; while (1) { - if (timeout) { + if (mode == MODE_THUMBS && tns.cnt < filecnt) { + win_set_cursor(&win, CURSOR_WATCH); + gettimeofday(&t0, 0); + + while (!XPending(win.env.dpy) && tns.cnt < filecnt) { + tns_load(&tns, &win, filenames[tns.cnt]); + gettimeofday(&t, 0); + if (TV_TO_DOUBLE(t) - TV_TO_DOUBLE(t0) >= 0.25) + break; + } + if (tns.cnt == filecnt) + win_set_cursor(&win, CURSOR_ARROW); + if (!XPending(win.env.dpy)) { + redraw(); + continue; + } else { + timeout = 75000; + } + } else if (timeout) { t.tv_sec = 0; t.tv_usec = timeout; xfd = ConnectionNumber(win.env.dpy); FD_ZERO(&fds); FD_SET(xfd, &fds); - - if (!XPending(win.env.dpy) && !select(xfd + 1, &fds, 0, 0, &t)) { - img_render(&img, &win); - timeout = 0; - } + + if (!XPending(win.env.dpy) && !select(xfd + 1, &fds, 0, 0, &t)) + redraw(); } if (!XNextEvent(win.env.dpy, &ev)) { @@ -482,8 +577,9 @@ void run() { break; case ConfigureNotify: if (win_configure(&win, &ev.xconfigure)) { - img.checkpan = 1; timeout = 75000; + if (mode == MODE_NORMAL) + img.checkpan = 1; } break; case ClientMessage: |