diff options
-rw-r--r-- | man/feh.pre | 124 | ||||
-rw-r--r-- | src/events.c | 177 | ||||
-rw-r--r-- | src/events.h | 2 | ||||
-rw-r--r-- | src/feh.h | 1 | ||||
-rw-r--r-- | src/help.raw | 24 | ||||
-rw-r--r-- | src/keyevents.c | 2 | ||||
-rw-r--r-- | src/main.c | 1 | ||||
-rw-r--r-- | src/options.c | 59 | ||||
-rw-r--r-- | src/options.h | 30 | ||||
-rw-r--r-- | src/structs.h | 2 |
10 files changed, 242 insertions, 180 deletions
diff --git a/man/feh.pre b/man/feh.pre index 5635fe8..b40510e 100644 --- a/man/feh.pre +++ b/man/feh.pre @@ -517,66 +517,6 @@ mode. .El . . -.Sh BUTTON OPTIONS -. -.Bl -tag -width indent -. -.It Cm -0 , --reload-button Ar int -. -Set button to reload the image -.Pq default: 0 . -. -.It Cm -1 , --pan-button Ar int -. -Set button to pan the image -.Pq hold button down and move mouse to move the image . -When the mouse is not moved, advances to the next image in slideshow mode. -.Pq default: 1 , usually the left button . -. -.It Cm -2 , --zoom-button Ar int -. -Set button to enable zoom mode -.Pq default: 2 , usually the middle button . -. -.It Cm -3 , --menu-button Ar int -. -Set button to activate the menu. -.Pq default: 3 , usually the right button . -. -.It Cm --menu-ctrl-mask -. -Require CTRL+Button for menu activation. -. -.It Cm -4 , --prev-button Ar int -. -Set button to switch to the previous image in slideshow mode -.Pq default: 4 , usually Aq mousewheel up . -. -.It Cm -5 , --next-button Ar int -. -Set button to switch to the next image in slideshow mode -.Pq default: 5 , usually Aq mousewheel down . -. -.It Cm -8 , --rotate-button Ar int -. -Use CTRL+Button to rotate the current image -.Pq default : 2 . -. -.It Cm --no-rotate-ctrl-mask -. -Don't require CTRL+Button for rotation - just use the button. -. -.It Cm -9 , --blur-button Ar int -. -Use CTRL+Button for blurring -.Pq default : 1 . -. -.It Cm --no-blur-ctrl-mask -. -Don't require CTRL+Button for blurring - just use the button. -.El -. -. .Sh MONTAGE MODE OPTIONS . These additional options can be used for index, montage and @@ -1167,6 +1107,70 @@ Select highlighted menu item .El . . +.Sh BUTTONS CONFIG SYNTAX +. +This works like the keys config file: the entries are of the form +.Qq Ar action Op Ar binding . +. +.Pp +. +Each +.Ar binding +is a button name. It may optionally start with modifiers for things like +Control, in which case +.Ar binding +looks like +.Ar mod Ns No - Ns Ar button +.Pq for example "C-1" for Ctrl + Left button . +. +.Pp +. +For the available modifiers, see +.Sx KEYS CONFIGURATION SYNTAX . +. +. +.Ss BUTTONS +. +In an image window, the following buttons may be used +.Pq The strings in Bo square brackets Bc are the config action names : +. +.Bl -tag -width indent +. +.It Bq reload +. +Reload current image +. +.It 1 Ao left mouse button Ac Bq pan +. +pan the current image +. +.It 2 Ao middle mouse button Ac Bq zoom +. +Zoom the current image +. +.It 3 Ao right mouse button Ac Bq menu +. +Toggle menu +. +.It 4 Ao mousewheel down Ac Bq prev +. +Show previous image +. +.It 5 Ao mousewheel up Ac Bq next +. +Show next image +. +.It Ctrl+1 Bq blur +. +Blur current image +. +.It Ctrl+2 Bq rotate +. +Rotate current image +. +.El +. +. .Sh MOUSE ACTIONS . When viewing an image, by default mouse button 1 pans diff --git a/src/events.c b/src/events.c index 2b8abdd..0d5e07d 100644 --- a/src/events.c +++ b/src/events.c @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "events.h" #include "thumbnail.h" +fehbb buttons; + feh_event_handler *ev_handler[LASTEvent]; static void feh_event_handle_ButtonPress(XEvent * ev); @@ -41,6 +43,129 @@ static void feh_event_handle_LeaveNotify(XEvent * ev); static void feh_event_handle_MotionNotify(XEvent * ev); static void feh_event_handle_ClientMessage(XEvent * ev); +static void feh_set_bb(fehbutton *bb, int modifier, char button) +{ + bb->modifier = modifier; + bb->button = button; +} + +static void feh_set_parse_bb_partial(fehbutton *button, char *binding) +{ + char *cur = binding; + int mod = 0; + + if (!*binding) { + button->button = 0; + return; + } + + while (cur[1] == '-') { + switch (cur[0]) { + case 'C': + mod |= ControlMask; + break; + case 'S': + mod |= ShiftMask; + break; + case '1': + mod |= Mod1Mask; + break; + case '4': + mod |= Mod4Mask; + break; + default: + weprintf("buttons: invalid modifier %c in \"%s\"", cur[0], binding); + break; + } + cur += 2; + } + + button->button = atoi(cur); + button->modifier = mod; +} + +void init_buttonbindings(void) +{ + char *home = NULL; + char *confhome = NULL; + char *confpath = NULL; + char line[128]; + char action[32], button[8]; + struct __fehbutton *cur_bb = NULL; + FILE *conf = NULL; + int read = 0; + + memset(&buttons, 0, sizeof(buttons)); + + feh_set_bb(&buttons.reload, 0, 0); + feh_set_bb(&buttons.pan, 0, 1); + feh_set_bb(&buttons.zoom, 0, 2); + feh_set_bb(&buttons.menu, 0, 3); + feh_set_bb(&buttons.prev, 0, 4); + feh_set_bb(&buttons.next, 0, 5); + feh_set_bb(&buttons.blur, 4, 1); + feh_set_bb(&buttons.rotate, 4, 2); + + home = getenv("HOME"); + if (!home) + eprintf("No HOME in environment"); + + confhome = getenv("XDG_CONFIG_HOME"); + + if (confhome) + confpath = estrjoin("/", confhome, "feh/buttons", NULL); + else + confpath = estrjoin("/", home, ".config/feh/buttons", NULL); + + conf = fopen(confpath, "r"); + + free(confpath); + + if (!conf && ((conf = fopen("/etc/feh/buttons", "r")) == NULL)) + return; + + while (fgets(line, sizeof(line), conf)) { + *action = '\0'; + *button = '\0'; + + read = sscanf(line, "%31s %7s\n", (char *) &action, (char *) &button); + + if ((read == EOF) || (read == 0) || (line[0] == '#')) + continue; + + if (!strcmp(action, "reload")) + cur_bb = &buttons.reload; + else if (!strcmp(action, "pan")) + cur_bb = &buttons.pan; + else if (!strcmp(action, "zoom")) + cur_bb = &buttons.zoom; + else if (!strcmp(action, "menu")) + cur_bb = &buttons.menu; + else if (!strcmp(action, "prev")) + cur_bb = &buttons.prev; + else if (!strcmp(action, "next")) + cur_bb = &buttons.next; + else if (!strcmp(action, "blur")) + cur_bb = &buttons.blur; + else if (!strcmp(action, "rotate")) + cur_bb = &buttons.rotate; + else + weprintf("buttons: Invalid action: %s", action); + + if (cur_bb) + feh_set_parse_bb_partial(cur_bb, button); + } + fclose(conf); +} + +static short feh_is_bb(fehbutton *bb, int button, int mod) +{ + if ((bb->modifier == mod) && (bb->button == button)) + return 1; + return 0; +} + + void feh_event_init(void) { int i; @@ -62,6 +187,7 @@ void feh_event_init(void) static void feh_event_handle_ButtonPress(XEvent * ev) { winwidget winwid = NULL; + int state, button; /* get the heck out if it's a mouse-click on the cover, we'll hide the menus on release */ @@ -74,31 +200,34 @@ static void feh_event_handle_ButtonPress(XEvent * ev) return; } - if (!opt.no_menus && EV_IS_MENU_BUTTON(ev)) { + state = ev->xbutton.state & (ControlMask | ShiftMask | Mod1Mask | Mod4Mask); + button = ev->xbutton.button; + + if (!opt.no_menus && feh_is_bb(&buttons.menu, button, state)) { D(("Menu Button Press event\n")); winwidget_show_menu(winwid); - } else if ((ev->xbutton.button == opt.rotate_button) - && (winwid->type != WIN_TYPE_THUMBNAIL) - && ((opt.no_rotate_ctrl_mask) - || (ev->xbutton.state & ControlMask))) { + + } else if (feh_is_bb(&buttons.rotate, button, state) + && (winwid->type != WIN_TYPE_THUMBNAIL)) { opt.mode = MODE_ROTATE; winwid->mode = MODE_ROTATE; D(("rotate starting at %d, %d\n", ev->xbutton.x, ev->xbutton.y)); - } else if ((ev->xbutton.button == opt.blur_button) - && (winwid->type != WIN_TYPE_THUMBNAIL) - && ((opt.no_blur_ctrl_mask) - || (ev->xbutton.state & ControlMask))) { + + } else if (feh_is_bb(&buttons.blur, button, state) + && (winwid->type != WIN_TYPE_THUMBNAIL)) { opt.mode = MODE_BLUR; winwid->mode = MODE_BLUR; D(("blur starting at %d, %d\n", ev->xbutton.x, ev->xbutton.y)); - } else if (ev->xbutton.button == opt.pan_button) { + + } else if (feh_is_bb(&buttons.pan, button, state)) { D(("Next button, but could be pan mode\n")); opt.mode = MODE_NEXT; winwid->mode = MODE_NEXT; D(("click offset is %d,%d\n", ev->xbutton.x, ev->xbutton.y)); winwid->click_offset_x = ev->xbutton.x - winwid->im_x; winwid->click_offset_y = ev->xbutton.y - winwid->im_y; - } else if (ev->xbutton.button == opt.zoom_button) { + + } else if (feh_is_bb(&buttons.zoom, button, state)) { D(("Zoom Button Press event\n")); opt.mode = MODE_ZOOM; winwid->mode = MODE_ZOOM; @@ -112,17 +241,21 @@ static void feh_event_handle_ButtonPress(XEvent * ev) - winwid->im_x) / winwid->old_zoom; winwid->im_click_offset_y = (winwid->click_offset_y - winwid->im_y) / winwid->old_zoom; - } else if (ev->xbutton.button == opt.reload_button) { + + } else if (feh_is_bb(&buttons.reload, button, state)) { D(("Reload Button Press event\n")); feh_reload_image(winwid, 0, 1); - } else if (ev->xbutton.button == opt.prev_button) { + + } else if (feh_is_bb(&buttons.prev, button, state)) { D(("Prev Button Press event\n")); if (winwid->type == WIN_TYPE_SLIDESHOW) slideshow_change_image(winwid, SLIDE_PREV, 1); - } else if (ev->xbutton.button == opt.next_button) { + + } else if (feh_is_bb(&buttons.next, button, state)) { D(("Next Button Press event\n")); if (winwid->type == WIN_TYPE_SLIDESHOW) slideshow_change_image(winwid, SLIDE_NEXT, 1); + } else { D(("Received other ButtonPress event\n")); } @@ -132,6 +265,8 @@ static void feh_event_handle_ButtonPress(XEvent * ev) static void feh_event_handle_ButtonRelease(XEvent * ev) { winwidget winwid = NULL; + int state = ev->xbutton.state & (ControlMask | ShiftMask | Mod1Mask | Mod4Mask); + int button = ev->xbutton.button; if (menu_root) { /* if menus are open, close them, and execute action if needed */ @@ -156,7 +291,7 @@ static void feh_event_handle_ButtonRelease(XEvent * ev) return; } - if (ev->xbutton.button == opt.pan_button) { + if (feh_is_bb(&buttons.pan, button, state)) { if (opt.mode == MODE_PAN) { D(("Disabling pan mode\n")); opt.mode = MODE_NORMAL; @@ -186,13 +321,14 @@ static void feh_event_handle_ButtonRelease(XEvent * ev) opt.mode = MODE_NORMAL; winwid->mode = MODE_NORMAL; } - } else if ((ev->xbutton.button == opt.rotate_button) - || (ev->xbutton.button == opt.zoom_button)) { + + } else if (feh_is_bb(&buttons.rotate, button, state) + || feh_is_bb(&buttons.zoom, button, state)) { D(("Disabling mode\n")); opt.mode = MODE_NORMAL; winwid->mode = MODE_NORMAL; - if ((ev->xbutton.button == opt.zoom_button) + if ((feh_is_bb(&buttons.zoom, button, state)) && (ev->xbutton.x == winwid->click_offset_x) && (ev->xbutton.y == winwid->click_offset_y)) { winwid->zoom = 1.0; @@ -201,9 +337,8 @@ static void feh_event_handle_ButtonRelease(XEvent * ev) winwidget_sanitise_offsets(winwid); winwidget_render_image(winwid, 0, 0); - } else if ((ev->xbutton.button == opt.blur_button) - && ((opt.no_blur_ctrl_mask) - || (ev->xbutton.state & ControlMask))) { + + } else if (feh_is_bb(&buttons.blur, button, state)) { D(("Disabling Blur mode\n")); opt.mode = MODE_NORMAL; winwid->mode = MODE_NORMAL; diff --git a/src/events.h b/src/events.h index 22abaf7..195f268 100644 --- a/src/events.h +++ b/src/events.h @@ -32,6 +32,4 @@ extern feh_event_handler *ev_handler[]; void feh_event_init(void); -#define EV_IS_MENU_BUTTON(ev) ((((ev)->xbutton.button == opt.menu_button) || (opt.menu_button == 0)) && (((!opt.menu_ctrl_mask) && (!((ev)->xbutton.state & ControlMask))) || (((ev)->xbutton.state & ControlMask) && (opt.menu_ctrl_mask)))) - #endif @@ -134,6 +134,7 @@ void slideshow_change_image(winwidget winwid, int change, int render); void slideshow_pause_toggle(winwidget w); char *slideshow_create_name(feh_file * file); void init_keyevents(void); +void init_buttonbindings(void); void feh_event_handle_keypress(XEvent * ev); void feh_action_run(feh_file * file, char *action); char *feh_printf(char *str, feh_file * file); diff --git a/src/help.raw b/src/help.raw index e8c848e..48c8a70 100644 --- a/src/help.raw +++ b/src/help.raw @@ -80,30 +80,6 @@ OPTIONS -B, --image-bg STYLE Set background for transparent images and the like. Accepted values: white, black, default -N, --no-menus Don't load or show any menus. - -0, --reload-button B Use button B to reload the image (defaults to 0) - -1, --pan-button B Use button B pan the image (hold button down, move - the mouse to move the image around. Advances to the - next image when the mouse is not moved (defaults to - 1, usually the left button). - -2, --zoom-button B Use button B to zoom the current image in any - mode (defaults to 2, usually the middle button). - -3, --menu-button B Click button B to activate the menu in any - mode. Set to 0 for any button. This option - is disabled if the -N or --no-menus option is set - (defaults to 3, usually the right button). - --menu-ctrl-mask Require CTRL+Button for menu activation - -4, --prev-button B Use button B to switch to the previous image - (defaults to 4, which usually is <mousewheel up>). - -5, --next-button B Use button B to switch to the next image - (defaults to 5, which usually is <mousewheel down>). - -8, --rotate-button B Use CTRL+Button B to rotate the current image in - any mode (default=2). - --no-rotate-ctrl-mask Don't require CTRL+Button for rotation in - any mode -- just use the button (default=off). - -9, --blur-button B Use CTRL+Button B to blur the current image in - any mode (default=1). - --no-blur-ctrl-mask Don't require CTRL+Button for blurring in - any mode -- just use the button (default=off). --no-xinerama Disable Xinerama support --no-screen-clip Do not limit window size to screen size -Y, --hide-pointer Hide the pointer diff --git a/src/keyevents.c b/src/keyevents.c index 942a88b..827ab24 100644 --- a/src/keyevents.c +++ b/src/keyevents.c @@ -154,7 +154,7 @@ void init_keyevents(void) { home = getenv("HOME"); if (!home) - eprintf("No HOME in environment\n"); + eprintf("No HOME in environment"); confhome = getenv("XDG_CONFIG_HOME"); @@ -47,6 +47,7 @@ int main(int argc, char **argv) if (opt.display) { init_x_and_imlib(); init_keyevents(); + init_buttonbindings(); } feh_event_init(); diff --git a/src/options.c b/src/options.c index def17f0..316f62d 100644 --- a/src/options.c +++ b/src/options.c @@ -61,19 +61,6 @@ void init_parse_options(int argc, char **argv) opt.menu_bg = estrdup(PREFIX "/share/feh/images/menubg_default.png"); opt.menu_style = estrdup(PREFIX "/share/feh/fonts/menu.style"); - opt.reload_button = 0; - opt.pan_button = 1; - opt.zoom_button = 2; - opt.menu_button = 3; - opt.menu_ctrl_mask = 0; - opt.prev_button = 4; - opt.next_button = 5; - - opt.rotate_button = 2; - opt.no_rotate_ctrl_mask = 0; - opt.blur_button = 1; - opt.no_blur_ctrl_mask = 0; - opt.start_list_at = NULL; opt.jump_on_resort = 1; @@ -315,7 +302,7 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) { static char stropts[] = "a:A:b:B:cC:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPqrR:sS:tT:uUvVwW:xXy:YzZ" - "0:1:2:4:5:8:9:.@:^:~:):|:+:"; + ".@:^:~:):|:+:"; /* (*name, has_arg, *flag, val) See: struct option in getopts.h */ static struct option lopts[] = { @@ -352,9 +339,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) {"cache-thumbnails", 0, 0, 'P'}, {"cycle-once" , 0, 0, 224}, {"no-xinerama" , 0, 0, 225}, - {"no-rotate-ctrl-mask", 0, 0, 226}, - {"no-blur-ctrl-mask", 0, 0, 227}, - {"menu-ctrl-mask", 0, 0, 228}, {"draw-tinted" , 0, 0, 229}, {"output" , 1, 0, 'o'}, @@ -381,14 +365,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) {"fontpath" , 1, 0, 'C'}, {"menu-bg" , 1, 0, ')'}, {"image-bg" , 1, 0, 'B'}, - {"reload-button" , 1, 0, '0'}, - {"pan-button" , 1, 0, '1'}, - {"zoom-button" , 1, 0, '2'}, - {"menu-button" , 1, 0, '3'}, - {"prev-button" , 1, 0, '4'}, - {"next-button" , 1, 0, '5'}, - {"rotate-button" , 1, 0, '8'}, - {"blur-button" , 1, 0, '9'}, {"start-at" , 1, 0, '|'}, {"debug" , 0, 0, '+'}, {"output-dir" , 1, 0, 'j'}, @@ -631,30 +607,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) else opt.filelistfile = estrdup(optarg); break; - case '0': - opt.reload_button = atoi(optarg); - break; - case '1': - opt.pan_button = atoi(optarg); - break; - case '2': - opt.zoom_button = atoi(optarg); - break; - case '3': - opt.menu_button = atoi(optarg); - break; - case '4': - opt.prev_button = atoi(optarg); - break; - case '5': - opt.next_button = atoi(optarg); - break; - case '8': - opt.rotate_button = atoi(optarg); - break; - case '9': - opt.blur_button = atoi(optarg); - break; case '|': opt.start_list_at = estrdup(optarg); break; @@ -746,15 +698,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) case 225: opt.xinerama = 0; break; - case 226: - opt.no_rotate_ctrl_mask = 1; - break; - case 227: - opt.no_blur_ctrl_mask = 1; - break; - case 228: - opt.menu_ctrl_mask = 1; - break; case 229: opt.text_bg = TEXT_BG_TINTED; break; diff --git a/src/options.h b/src/options.h index ae3a707..f1fe3c4 100644 --- a/src/options.h +++ b/src/options.h @@ -92,20 +92,6 @@ struct __fehoptions { gib_style *menu_style_l; - unsigned char pan_button; - unsigned char zoom_button; - unsigned char menu_button; - unsigned char menu_ctrl_mask; - unsigned char prev_button; - unsigned char next_button; - - unsigned char rotate_button; - unsigned char blur_button; - unsigned char reload_button; - unsigned char no_rotate_ctrl_mask; - unsigned char no_blur_ctrl_mask; - unsigned char no_pan_ctrl_mask; - int force_aliasing; int thumb_w; int thumb_h; @@ -199,6 +185,22 @@ struct __fehkb { struct __fehkey reload_plus; }; +struct __fehbutton { + int modifier; + char button; +}; + +struct __fehbb { + struct __fehbutton pan; + struct __fehbutton zoom; + struct __fehbutton reload; + struct __fehbutton prev; + struct __fehbutton next; + struct __fehbutton menu; + struct __fehbutton blur; + struct __fehbutton rotate; +}; + void init_parse_options(int argc, char **argv); char *feh_string_normalize(char *str); diff --git a/src/structs.h b/src/structs.h index 3942bc0..e1acf2d 100644 --- a/src/structs.h +++ b/src/structs.h @@ -36,5 +36,7 @@ typedef _winwidget *winwidget; typedef struct __fehoptions fehoptions; typedef struct __fehkey fehkey; typedef struct __fehkb fehkb; +typedef struct __fehbutton fehbutton; +typedef struct __fehbb fehbb; #endif |