Przeglądaj źródła

Manage focus/client buttons grabbing

Martin Duquesnoy 12 lat temu
rodzic
commit
350c789482
7 zmienionych plików z 117 dodań i 23 usunięć
  1. 64 9
      wmfs2/src/client.c
  2. 2 2
      wmfs2/src/event.c
  3. 0 1
      wmfs2/src/infobar.h
  4. 23 0
      wmfs2/src/tag.c
  5. 1 0
      wmfs2/src/tag.h
  6. 20 8
      wmfs2/src/wmfs.c
  7. 7 3
      wmfs2/src/wmfs.h

+ 64 - 9
wmfs2/src/client.c

@@ -6,6 +6,8 @@
 #include "client.h"
 #include "util.h"
 
+#define CLIENT_MOUSE_MOD Mod1Mask
+
 /** Send a ConfigureRequest event to the Client
  * \param c Client pointer
 */
@@ -58,25 +60,59 @@ client_unmap(Client *c)
      XUnmapWindow(W->dpy, c->win);
 }
 
+static void
+client_grabbuttons(Client *c, bool focused)
+{
+     int i, but[] = {Button1, Button2, Button3, Button4, Button5};
+
+    /* wmfs_numlockmask();*/
+
+     XUngrabButton(W->dpy, AnyButton, AnyModifier, c->win);
+
+     if(focused)
+     {
+          for(i = 0; i < LEN(but); ++i)
+          {
+               XGrabButton(W->dpy, but[i], CLIENT_MOUSE_MOD, c->win, False,
+                         ButtonMask, GrabModeAsync, GrabModeSync, None, None);
+               XGrabButton(W->dpy, but[i], CLIENT_MOUSE_MOD | LockMask, c->win, False,
+                         ButtonMask, GrabModeAsync, GrabModeSync, None, None);
+               XGrabButton(W->dpy, but[i], CLIENT_MOUSE_MOD | W->numlockmask, c->win, False,
+                         ButtonMask, GrabModeAsync, GrabModeSync, None, None);
+               XGrabButton(W->dpy, but[i], CLIENT_MOUSE_MOD | LockMask | W->numlockmask, c->win, False,
+                         ButtonMask, GrabModeAsync, GrabModeSync, None, None);
+          }
+
+          return;
+     }
+
+     XGrabButton(W->dpy, AnyButton, AnyModifier, c->win, False,
+               ButtonMask, GrabModeAsync, GrabModeSync, None, None);
+
+}
+
 void
 client_focus(Client *c)
 {
      /* Unfocus selected */
-     if(c->tag->sel && c->tag->sel != c)
+     if(W->client && W->client != c)
      {
-          XSetWindowBorder(W->dpy, c->win, 0xf0f0f0);
+          XSetWindowBorder(W->dpy, W->client->win, 0xfF0000);
+
+          client_grabbuttons(W->client, false);
      }
 
      /* Focus c */
-     if((c->tag->sel = c))
+     if((W->client = c))
      {
+          c->tag->sel = c;
+
           XSetWindowBorder(W->dpy, c->win, 0xffffff);
 
-          XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime);
+          client_grabbuttons(c, true);
 
-          XRaiseWindow(W->dpy, c->win);
+          XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime);
      }
-     /* Else, set input focus to root window */
      else
           XSetInputFocus(W->dpy, W->root, RevertToPointerRoot, CurrentTime);
 
@@ -152,9 +188,11 @@ client_new(Window w, XWindowAttributes *wa)
      /* C attributes */
      c->win    = w;
      c->screen = W->screen;
-     c->tag    = W->screen->seltag;
      c->flags  = 0;
 
+     /* Set tag */
+     tag_client(W->screen->seltag, c);
+
      /* Geometry */
      c->geo.x = wa->x;
      c->geo.y = wa->y;
@@ -166,16 +204,22 @@ client_new(Window w, XWindowAttributes *wa)
 
      XSetWindowBorder(W->dpy, w, 0xffffff);
      XSetWindowBorderWidth(W->dpy, w, 1);
+     client_grabbuttons(c, false);
 
      /* Attach */
      SLIST_INSERT_HEAD(&W->h.client, c, next);
 
+     XMoveResizeWindow(W->dpy, w,
+               c->screen->ugeo.x,
+               c->screen->ugeo.y,
+               c->screen->ugeo.w,
+               c->screen->ugeo.h);
+
+
      client_map(c);
 
-     XMoveResizeWindow(W->dpy, w, c->geo.x, c->geo.y, c->geo.w, c->geo.h);
      XRaiseWindow(W->dpy, w);
 
-     client_focus(c);
      client_configure(c);
 
      return c;
@@ -184,11 +228,22 @@ client_new(Window w, XWindowAttributes *wa)
 void
 client_remove(Client *c)
 {
+     Client *cc;
+
      XGrabServer(W->dpy);
      XSetErrorHandler(wmfs_error_handler_dummy);
 
+     if(W->client == c)
+          client_focus(NULL);
+
      SLIST_REMOVE(&W->h.client, c, Client, next);
 
+     if(c->tag->sel == c)
+          c->tag->sel = SLIST_FIRST(&c->tag->clients);
+
+     tag_client(NULL, c);
+
+     XSync(W->dpy, False);
      XUngrabServer(W->dpy);
      XSetErrorHandler(wmfs_error_handler);
 

+ 2 - 2
wmfs2/src/event.c

@@ -106,8 +106,8 @@ event_focusin(XEvent *e)
 {
      Client *c;
 
-     if((c = W->screen->seltag->sel) && e->xfocus.window != c->win)
-          client_focus(c);
+     if(W->client && e->xfocus.window != W->client->win)
+          client_focus(W->client);
 }
 
 static void

+ 0 - 1
wmfs2/src/infobar.h

@@ -36,7 +36,6 @@ infobar_placement(Infobar *i, Barpos p)
      i->geo = i->screen->ugeo;
      i->geo.h = i->theme->bars_width;
 
-     /* Top */
      switch(p)
      {
           case BarTop:

+ 23 - 0
wmfs2/src/tag.c

@@ -6,6 +6,7 @@
 #include "tag.h"
 #include "util.h"
 #include "infobar.h"
+#include "client.h"
 
 Tag*
 tag_new(Scr33n *s, char *name)
@@ -29,9 +30,31 @@ tag_screen(Scr33n *s, Tag *t)
 {
      s->seltag = t;
 
+     client_focus(t->sel);
+
      infobar_elem_screen_update(s, ElemTag);
 }
 
+void
+tag_client(Tag *t, Client *c)
+{
+     /* Remove client from its previous tag */
+     if(c->tag)
+     {
+          SLIST_REMOVE(&c->tag->clients, c, Client, tnext);
+
+          if(c->tag->sel == c)
+               c->tag->sel = NULL;
+     }
+
+     /* Case of client remove, t = NULL */
+     if(!(c->tag = t))
+          return;
+
+     /* Insert in new tag list */
+     SLIST_INSERT_HEAD(&t->clients, c, tnext);
+}
+
 
 void
 uicb_tag_set(Uicb cmd)

+ 1 - 0
wmfs2/src/tag.h

@@ -10,6 +10,7 @@
 
 Tag *tag_new(Scr33n *s, char *name);
 void tag_screen(Scr33n *s, Tag *t);
+void tag_client(Tag *t, Client *c);
 void tag_free(Scr33n *s);
 void uicb_tag_set(Uicb cmd);
 void uicb_tag_set_with_name(Uicb cmd);

+ 20 - 8
wmfs2/src/wmfs.c

@@ -57,6 +57,21 @@ wmfs_error_handler_dummy(Display *d, XErrorEvent *event)
      return 0;
 }
 
+void
+wmfs_numlockmask(void)
+{
+     int i, j;
+     XModifierKeymap *mm = XGetModifierMapping(W->dpy);
+
+     for(i = 0; i < 8; i++)
+          for(j = 0; j < mm->max_keypermod; ++j)
+               if(mm->modifiermap[i * mm->max_keypermod + j]
+                         == XKeysymToKeycode(W->dpy, XK_Num_Lock))
+                    W->numlockmask = (1 << i);
+
+     XFreeModifiermap(mm);
+}
+
 void
 wmfs_init_font(char *font, Theme *t)
 {
@@ -121,14 +136,7 @@ wmfs_xinit(void)
      /*
       * Keys
       */
-     mm = XGetModifierMapping(W->dpy);
-
-     for(i = 0; i < 8; i++)
-          for(j = 0; j < mm->max_keypermod; ++j)
-               if(mm->modifiermap[i * mm->max_keypermod + j]
-                         == XKeysymToKeycode(W->dpy, XK_Num_Lock))
-                    W->numlockmask = (1 << i);
-     XFreeModifiermap(mm);
+     wmfs_numlockmask();
 
      /*
       * Barwin linked list
@@ -144,6 +152,8 @@ wmfs_grab_keys(void)
      KeyCode c;
      Keybind *k;
 
+     wmfs_numlockmask();
+
      XUngrabKey(W->dpy, AnyKey, AnyModifier, W->root);
 
      SLIST_FOREACH(k, &W->h.keybind, next)
@@ -166,6 +176,8 @@ wmfs_scan(void)
      XWindowAttributes wa;
      Window usl, usl2, *w = NULL;
 
+     SLIST_INIT(&W->h.client);
+
      /*
         Atom rt;
         int s, rf, tag = -1, screen = -1, flags = -1, i;

+ 7 - 3
wmfs2/src/wmfs.h

@@ -110,6 +110,7 @@ struct Tag
      Scr33n *screen;
      Flags flags;
      Client *sel;
+     SLIST_HEAD(, Client) clients;
      TAILQ_ENTRY(Tag) next;
 };
 
@@ -122,7 +123,8 @@ struct Client
      Flags flags;
      char *title;
      Window win;
-     SLIST_ENTRY(Client) next;
+     SLIST_ENTRY(Client) next;  /* Global list */
+     SLIST_ENTRY(Client) tnext; /* Tag list */
 };
 
 /* Config */
@@ -197,15 +199,17 @@ struct Wmfs
      } h;
 
      /*
-      * Selected screen, from what you go everywhere; selected tag,
-      * and then selected client.
+      * Selected screen, client
       */
      Scr33n *screen;
+     Client *client;
+
 };
 
 int wmfs_error_handler(Display *d, XErrorEvent *event);
 int wmfs_error_handler_dummy(Display *d, XErrorEvent *event);
 void wmfs_grab_keys(void);
+void wmfs_numlockmask(void);
 void wmfs_init_font(char *font, Theme *t);
 void wmfs_quit(void);
 void uicb_reload(Uicb cmd);