ratpoison-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RP] adding some basic mouse support to switch frame


From: Julien Pagès
Subject: Re: [RP] adding some basic mouse support to switch frame
Date: Wed, 01 Feb 2017 15:01:27 +0100
User-agent: mu4e 0.9.17; emacs 25.1.1

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?= <address@hidden>
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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]