Spiros Bousbouras writes: > On Wednesday 2017-01-25 Julien Pagès wrote : >> I would like to add some basic support to be able to switch frame using >> the mouse. It should be configurable, I do not intend to change the >> default behavior. I was thinking about a new variable, let's say >> 'mousefocuspolicy', which could take some values: >> >> - "none": this is the current behavior >> - "click": allow to select the frame under the mouse when the user click >> - "move": (maybe this can be done later, I am not sure of that yet) this >> would select the frame automatically under the mouse, when the user >> move it >> >> It could then be used easily in the configuration file: >> >> set mousefocuspolicy click > > BLASPHEMY ! HERESY ! ;-) > > No , actually this is a good idea ; I would find useful both the "click" and > "move" functionalities so I say go for it.
Excellent, you got me on the first line :D So I wrote a patch for the click feature. It seems to work pretty well, I tried it on a laptop connected to an external screen and it seems OK to me. Note that the frames are selected (not the windows) which I believe is better. I am not sure for the "mouse" policy, but I don't plan to do it right now - it seems to be a bit more complicated than what I expected :). Once you are happy with the attached patch (note it is also available on my github account, https://github.com/parkouss/ratpoison/commit/15c2a0ab6cfe944d65c3d0831cc7c01219ea1839), I would be happy to write another patch for the documentation/changelog (I am not sure what I should change yet, and I am not a native English speaker, but I would be glad to do my best!). Cheers,
>From 15c2a0ab6cfe944d65c3d0831cc7c01219ea1839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= <j.parko...@gmail.com> Date: Sun, 29 Jan 2017 14:23:47 +0100 Subject: [PATCH] add basic support for the mouse Basic support for the mouse is provided to be able to activate a frame when clicking on it. To activate the behavior, the mousefocuspolicy variable must be set: set mousefocuspolicy click Currently mousefocuspolicy only accept two values: none (no mouse support at all) and click (activate a frame on click). --- src/actions.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/data.h | 3 +++ src/events.c | 20 ++++++++++++++++++- src/globals.h | 4 ++++ src/main.c | 2 ++ src/screen.c | 2 +- src/split.c | 21 ++++++++++++++++++++ src/split.h | 1 + 8 files changed, 113 insertions(+), 2 deletions(-) diff --git a/src/actions.c b/src/actions.c index ef856cf..7a511ba 100644 --- a/src/actions.c +++ b/src/actions.c @@ -162,6 +162,7 @@ static cmdret * set_inputwidth (struct cmdarg **args); static cmdret * set_waitcursor (struct cmdarg **args); static cmdret * set_winfmt (struct cmdarg **args); static cmdret * set_winname (struct cmdarg **args); +static cmdret * set_mousefocuspolicy (struct cmdarg **args); static cmdret * set_framefmt (struct cmdarg **args); static cmdret * set_fgcolor (struct cmdarg **args); static cmdret * set_bgcolor (struct cmdarg **args); @@ -373,6 +374,7 @@ init_set_vars (void) add_set_var ("wingravity", set_wingravity, 1, "", arg_GRAVITY); add_set_var ("winliststyle", set_winliststyle, 1, "", arg_STRING); add_set_var ("winname", set_winname, 1, "", arg_STRING); + add_set_var ("mousefocuspolicy", set_mousefocuspolicy, 1, "", arg_STRING); } /* i_nrequired is the number required when called @@ -1258,6 +1260,30 @@ ungrab_rat (void) XUngrabPointer (dpy, CurrentTime); } +static void +grab_button (void) +{ + int j; + for (j=0; j<num_screens; j++) + { + rp_screen *screen = &screens[j]; + XGrabButton(dpy, AnyButton, AnyModifier, screen->root, + True, ButtonPressMask, + GrabModeSync, GrabModeAsync, None, None); + } +} + +static void +ungrab_button (void) +{ + int j; + for (j=0; j<num_screens; j++) + { + rp_screen *screen = &screens[j]; + XUngrabButton(dpy, AnyButton, AnyModifier, screen->root); + } +} + /* Unmanage window */ cmdret * cmd_unmanage (int interactive, struct cmdarg **args) @@ -4304,6 +4330,42 @@ set_winname (struct cmdarg **args) } static cmdret * +set_mousefocuspolicy(struct cmdarg **args) +{ + char *policy; + + if (args[0] == NULL) + switch (defaults.mouse_focus_policy) + { + case MOUSE_FOCUS_POLICY_NONE: + return cmdret_new (RET_SUCCESS, "none"); + case MOUSE_FOCUS_POLICY_CLICK: + return cmdret_new (RET_SUCCESS, "click"); + default: + PRINT_DEBUG (("Unknown mouse_focus_policy\n")); + return cmdret_new (RET_FAILURE, "unknown"); + } + + policy = ARG_STRING(0); + + if (!strncmp (policy, "none", sizeof ("none"))) + { + defaults.mouse_focus_policy = MOUSE_FOCUS_POLICY_NONE; + ungrab_button(); + } + else if (!strncmp (policy, "click", sizeof ("click"))) + { + defaults.mouse_focus_policy = MOUSE_FOCUS_POLICY_CLICK; + grab_button(); + } + else + return cmdret_new (RET_FAILURE, + "set mousefocuspolicy: invalid argument `%s'", policy); + + return cmdret_new (RET_SUCCESS, NULL); +} + +static cmdret * set_framefmt (struct cmdarg **args) { if (args[0] == NULL) diff --git a/src/data.h b/src/data.h index 52aaa42..da8cffa 100644 --- a/src/data.h +++ b/src/data.h @@ -275,6 +275,9 @@ struct rp_defaults /* Frame indicator format */ char *frame_fmt; + + /* Window focus policy for the mouse: none or click */ + int mouse_focus_policy; }; /* Information about a child process. */ diff --git a/src/events.c b/src/events.c index 814e1ef..fd96fcd 100644 --- a/src/events.c +++ b/src/events.c @@ -793,6 +793,19 @@ selection_clear (void) selection.len = 0; } +static void +button_press (XButtonEvent * ev) +{ + rp_frame * frame; + + if (defaults.mouse_focus_policy == MOUSE_FOCUS_POLICY_CLICK) + { + frame = find_frame_at_cursor_pos (ev->x_root, ev->y_root); + if (frame) + set_active_frame(frame, 1); + } +} + /* Given an event, call the correct function to handle it. */ static void delegate_event (XEvent *ev) @@ -871,7 +884,12 @@ delegate_event (XEvent *ev) PRINT_DEBUG (("--- Handling ConfigureNotify ---\n")); configure_notify( &ev->xconfigure ); break; - + + case ButtonPress: + XAllowEvents (dpy, ReplayPointer, CurrentTime); /* ReplayPointer resends the mouse event */ + button_press(&ev->xbutton); + break; + case MapNotify: case Expose: case MotionNotify: diff --git a/src/globals.h b/src/globals.h index 8f0d048..5b98f9b 100644 --- a/src/globals.h +++ b/src/globals.h @@ -57,6 +57,10 @@ #define WIN_NAME_RES_CLASS 1 #define WIN_NAME_RES_NAME 2 +/* Possible values for defaults.mouse_focus_policy */ +#define MOUSE_FOCUS_POLICY_NONE 0 +#define MOUSE_FOCUS_POLICY_CLICK 1 + /* Possible directions to traverse the completions list. */ #define COMPLETION_NEXT 0 #define COMPLETION_PREVIOUS 1 diff --git a/src/main.c b/src/main.c index 3c2b300..7175a0b 100644 --- a/src/main.c +++ b/src/main.c @@ -583,6 +583,8 @@ init_defaults (void) defaults.history_expansion = False; defaults.frame_selectors = xstrdup (""); defaults.maxundos = 20; + + defaults.mouse_focus_policy = MOUSE_FOCUS_POLICY_NONE; } int diff --git a/src/screen.c b/src/screen.c index 0afdee0..9e5866f 100644 --- a/src/screen.c +++ b/src/screen.c @@ -269,7 +269,7 @@ init_screen (rp_screen *s, int screen_num) XSelectInput(dpy, RootWindow (dpy, screen_num), PropertyChangeMask | ColormapChangeMask | SubstructureRedirectMask | SubstructureNotifyMask - | StructureNotifyMask); + | StructureNotifyMask | ButtonPressMask); XSync (dpy, False); /* Set the numset for the frames to our global numset. */ diff --git a/src/split.c b/src/split.c index b36b99e..4f95296 100644 --- a/src/split.c +++ b/src/split.c @@ -1088,3 +1088,24 @@ find_frame_number (int num) return NULL; } + +rp_frame * +find_frame_at_cursor_pos (int x, int y) +{ + int i; + rp_frame *cur; + + for (i=0; i<num_screens; i++) + { + rp_screen *s = &screens[i]; + + list_for_each_entry (cur, &s->frames, node) + { + if (x >= (s->left + cur->x) && x <= (s->left + cur->x + cur->width) + && y >= (s->top + cur->y) && y <= (s->top + cur->y + cur->height)) + return cur; + } + } + + return NULL; +} diff --git a/src/split.h b/src/split.h index 87bb660..a65fc91 100644 --- a/src/split.h +++ b/src/split.h @@ -56,5 +56,6 @@ rp_frame *find_last_frame (void); rp_frame * find_frame_number (int num); rp_frame *current_frame (void); +rp_frame *find_frame_at_cursor_pos (int x, int y); #endif -- 2.7.4
-- ~Julien
_______________________________________________ Ratpoison-devel mailing list Ratpoison-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/ratpoison-devel