From 7a75c42b37b08f44c72f9a7c98eb6076967470fb Mon Sep 17 00:00:00 2001 From: N-R-K <79544946+N-R-K@users.noreply.github.com> Date: Mon, 10 Jan 2022 16:52:06 +0000 Subject: [PATCH] make thumbnail bindings configureable via config.h (#167) this allows for configuring thumbnail mode mouse bindings similar to image mode bindings. however we can't put the thumbnails bindings into the existing buttons[] array due to fallthrough. For example M3 would switch mode and then end up selecting an image. which is why thumbnail bindings have been put into it's own array `buttons_tns[]` and `buttons[]` has been renamed to `buttons_img[]` for consistency. Closes: https://github.com/nsxiv/nsxiv/issues/131 --- commands.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ commands.h | 6 ++++++ config.def.h | 13 ++++++++++- main.c | 61 ++++++++-------------------------------------------- 4 files changed, 82 insertions(+), 53 deletions(-) diff --git a/commands.c b/commands.c index a751c94..aafc510 100644 --- a/commands.c +++ b/commands.c @@ -42,6 +42,7 @@ extern appmode_t mode; extern img_t img; extern tns_t tns; extern win_t win; +extern const XButtonEvent *xbutton_ev; extern fileinfo_t *files; extern int filecnt, fileidx; @@ -436,3 +437,57 @@ bool ct_reload_all(arg_t _) tns.dirty = true; return true; } + +bool ct_scroll(arg_t dir) +{ + return tns_scroll(&tns, dir, false); +} + +bool ct_drag_mark_image(arg_t _) +{ + int sel; + + if ((sel = tns_translate(&tns, xbutton_ev->x, xbutton_ev->y)) >= 0) { + XEvent e; + bool on = !(files[sel].flags & FF_MARK); + + while (true) { + if (sel >= 0 && mark_image(sel, on)) + redraw(); + XMaskEvent(win.env.dpy, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e); + if (e.type == ButtonPress || e.type == ButtonRelease) + break; + while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e)); + sel = tns_translate(&tns, e.xbutton.x, e.xbutton.y); + } + } + + return false; +} + +bool ct_select(arg_t _) +{ + int sel; + bool dirty = false; + static Time firstclick; + + if ((sel = tns_translate(&tns, xbutton_ev->x, xbutton_ev->y)) >= 0) { + if (sel != fileidx) { + tns_highlight(&tns, fileidx, false); + tns_highlight(&tns, sel, true); + fileidx = sel; + firstclick = xbutton_ev->time; + dirty = true; + } else if (xbutton_ev->time - firstclick <= TO_DOUBLE_CLICK) { + mode = MODE_IMAGE; + set_timeout(reset_cursor, TO_CURSOR_HIDE, true); + load_image(fileidx); + dirty = true; + } else { + firstclick = xbutton_ev->time; + } + } + + return dirty; +} diff --git a/commands.h b/commands.h index 8935f22..70af13a 100644 --- a/commands.h +++ b/commands.h @@ -39,6 +39,9 @@ bool ci_toggle_antialias(arg_t); /* thumbnails mode */ bool ct_move_sel(arg_t); bool ct_reload_all(arg_t); +bool ct_scroll(arg_t); +bool ct_drag_mark_image(arg_t); +bool ct_select(arg_t); /* global */ #define g_change_gamma { cg_change_gamma, MODE_ALL } @@ -79,5 +82,8 @@ bool ct_reload_all(arg_t); /* thumbnails mode */ #define t_move_sel { ct_move_sel, MODE_THUMB } #define t_reload_all { ct_reload_all, MODE_THUMB } +#define t_scroll { ct_scroll, MODE_THUMB } +#define t_drag_mark_image { ct_drag_mark_image, MODE_THUMB } +#define t_select { ct_select, MODE_THUMB } #endif /* COMMANDS_H */ diff --git a/config.def.h b/config.def.h index 6e4b942..b328305 100644 --- a/config.def.h +++ b/config.def.h @@ -175,7 +175,7 @@ static const keymap_t keys[] = { }; /* mouse button mappings for image mode: */ -static const button_t buttons[] = { +static const button_t buttons_img[] = { /* modifiers button function argument */ { 0, 1, i_cursor_navigate, None }, { ControlMask, 1, i_drag, DRAG_RELATIVE }, @@ -185,6 +185,17 @@ static const button_t buttons[] = { { 0, 5, g_zoom, -1 }, }; +/* mouse button mappings for thumbnail mode: */ +static const button_t buttons_tns[] = { + /* modifiers button function argument */ + { 0, 1, t_select, None }, + { 0, 3, t_drag_mark_image, None }, + { 0, 4, t_scroll, DIR_UP }, + { 0, 5, t_scroll, DIR_DOWN }, + { ControlMask, 4, g_scroll_screen, DIR_UP }, + { ControlMask, 5, g_scroll_screen, DIR_DOWN }, +}; + /* true means NAV_WIDTH is relative (33%), false means absolute (33 pixels) */ static const bool NAV_IS_REL = true; /* width of navigation area, 0 disables cursor navigation, */ diff --git a/main.c b/main.c index f8c727f..efedfc6 100644 --- a/main.c +++ b/main.c @@ -57,6 +57,7 @@ arl_t arl; img_t img; tns_t tns; win_t win; +const XButtonEvent *xbutton_ev; fileinfo_t *files; int filecnt, fileidx; @@ -661,64 +662,19 @@ static void on_keypress(XKeyEvent *kev) prefix = 0; } -static void on_buttonpress(XButtonEvent *bev) +static void on_buttonpress(const XButtonEvent *bev) { - int sel; bool dirty = false; - static Time firstclick; if (mode == MODE_IMAGE) { set_timeout(reset_cursor, TO_CURSOR_HIDE, true); reset_cursor(); - dirty = process_bindings(buttons, ARRLEN(buttons), bev->button, bev->state, 0); - if (dirty) - redraw(); - } else { - /* thumbnail mode (hard-coded) */ - switch (bev->button) { - case Button1: - if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) { - if (sel != fileidx) { - tns_highlight(&tns, fileidx, false); - tns_highlight(&tns, sel, true); - fileidx = sel; - firstclick = bev->time; - redraw(); - } else if (bev->time - firstclick <= TO_DOUBLE_CLICK) { - mode = MODE_IMAGE; - set_timeout(reset_cursor, TO_CURSOR_HIDE, true); - load_image(fileidx); - redraw(); - } else { - firstclick = bev->time; - } - } - break; - case Button3: - if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) { - bool on = !(files[sel].flags & FF_MARK); - XEvent e; - - while (true) { - if (sel >= 0 && mark_image(sel, on)) - redraw(); - XMaskEvent(win.env.dpy, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e); - if (e.type == ButtonPress || e.type == ButtonRelease) - break; - while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e)); - sel = tns_translate(&tns, e.xbutton.x, e.xbutton.y); - } - } - break; - case Button4: - case Button5: - if (tns_scroll(&tns, bev->button == Button4 ? DIR_UP : DIR_DOWN, - (bev->state & ControlMask) != 0)) - redraw(); - break; - } + dirty = process_bindings(buttons_img, ARRLEN(buttons_img), bev->button, bev->state, 0); + } else { /* thumbnail mode */ + dirty = process_bindings(buttons_tns, ARRLEN(buttons_tns), bev->button, bev->state, 0); } + if (dirty) + redraw(); prefix = 0; } @@ -731,13 +687,14 @@ static void run(void) bool discard, init_thumb, load_thumb, to_set; XEvent ev, nextev; + xbutton_ev = &ev.xbutton; while (true) { to_set = check_timeouts(&timeout); init_thumb = mode == MODE_THUMB && tns.initnext < filecnt; load_thumb = mode == MODE_THUMB && tns.loadnext < tns.end; if ((init_thumb || load_thumb || to_set || info.fd != -1 || - arl.fd != -1) && XPending(win.env.dpy) == 0) + arl.fd != -1) && XPending(win.env.dpy) == 0) { if (load_thumb) { set_timeout(redraw, TO_REDRAW_THUMBS, false);