Explorar o código

Add client user functions: swap/focus with direction and list (next/prev)

Martin Duquesnoy %!s(int64=12) %!d(string=hai) anos
pai
achega
0477c5a8d6
Modificáronse 7 ficheiros con 170 adicións e 29 borrados
  1. 98 15
      wmfs2/src/client.c
  2. 19 1
      wmfs2/src/client.h
  3. 12 1
      wmfs2/src/config.h
  4. 10 11
      wmfs2/src/event.c
  5. 3 0
      wmfs2/src/screen.c
  6. 9 0
      wmfs2/src/util.h
  7. 19 1
      wmfs2/wmfsrc2

+ 98 - 15
wmfs2/src/client.c

@@ -15,11 +15,27 @@
 
 #define CLIENT_MOUSE_MOD Mod1Mask
 
-#define CLIENT_RESIZE_DIR(d)                          \
-void uicb_client_resize_##d(Uicb cmd)                 \
+#define CLIENT_RESIZE_DIR(D)                          \
+void uicb_client_resize_##D(Uicb cmd)                 \
 {                                                     \
      if(W->client)                                    \
-          client_fac_resize(W->client, d, ATOI(cmd)); \
+          client_fac_resize(W->client, D, ATOI(cmd)); \
+}
+
+#define CLIENT_ACTION_DIR(A, D)                           \
+void uicb_client_##A##_##D(Uicb cmd)                      \
+{                                                         \
+     (void)cmd;                                           \
+     if(W->client)                                        \
+          client_##A(client_next_with_pos(W->client, D)); \
+}
+
+#define CLIENT_ACTION_LIST(A, L)             \
+void uicb_client_##A##_##L(Uicb cmd)         \
+{                                            \
+     (void)cmd;                              \
+     if(W->client)                           \
+          client_##A(client_##L(W->client)); \
 }
 
 /* uicb_client_resize_dir() */
@@ -28,6 +44,27 @@ CLIENT_RESIZE_DIR(Left)
 CLIENT_RESIZE_DIR(Top)
 CLIENT_RESIZE_DIR(Bottom)
 
+/* uicb_client_focus_dir() */
+CLIENT_ACTION_DIR(focus, Right)
+CLIENT_ACTION_DIR(focus, Left)
+CLIENT_ACTION_DIR(focus, Top)
+CLIENT_ACTION_DIR(focus, Bottom)
+
+/* uicb_client_swapsel_dir() */
+#define client_swapsel(c) client_swap(W->client, c)
+CLIENT_ACTION_DIR(swapsel, Right)
+CLIENT_ACTION_DIR(swapsel, Left)
+CLIENT_ACTION_DIR(swapsel, Top)
+CLIENT_ACTION_DIR(swapsel, Bottom)
+
+/* uicb_client_focus_next/prev() */
+CLIENT_ACTION_LIST(focus, next)
+CLIENT_ACTION_LIST(focus, prev)
+
+/* uicb_client_swapsel_next/prev() */
+CLIENT_ACTION_LIST(swapsel, next)
+CLIENT_ACTION_LIST(swapsel, prev)
+
 /** Send a ConfigureRequest event to the struct client
  * \param c struct client pointer
 */
@@ -52,6 +89,29 @@ client_configure(struct client *c)
      XSync(W->dpy, False);
 }
 
+struct client*
+client_next(struct client *c)
+{
+     struct client *next;
+
+     if(!(next = SLIST_NEXT(c, tnext)))
+          next = SLIST_FIRST(&c->tag->clients);
+
+     return next;
+}
+
+struct client*
+client_prev(struct client *c)
+{
+     struct client *cc;
+
+     SLIST_FOREACH(cc, &c->tag->clients, tnext)
+          if(SLIST_NEXT(cc, tnext) == c || !SLIST_NEXT(cc, tnext))
+               return cc;
+
+     return SLIST_FIRST(&c->tag->clients);
+}
+
 struct client*
 client_gb_win(Window w)
 {
@@ -111,6 +171,27 @@ client_next_with_pos(struct client *bc, Position p)
      return c;
 }
 
+void
+client_swap(struct client *c1, struct client *c2)
+{
+     struct tag *t;
+     struct geo g;
+
+     if(c1 == c2 || !c1 || !c2)
+          return;
+
+     t = c1->tag;
+     g = c1->geo;
+
+     swap_ptr((void**)&c1->screen, (void**)&c2->screen);
+
+     tag_client(c2->tag, c1);
+     tag_client(t, c2);
+
+     client_moveresize(c1, c2->geo);
+     client_moveresize(c2, g);
+}
+
 static void
 client_grabbuttons(struct client *c, bool focused)
 {
@@ -143,15 +224,15 @@ client_grabbuttons(struct client *c, bool focused)
 }
 
 static inline void
-client_draw_bord(void)
+client_draw_bord(struct client *c)
 {
-     struct geo g = { 0, 0, W->screen->ugeo.w, W->screen->ugeo.h };
+     struct geo g = { 0, 0, c->screen->ugeo.w, c->screen->ugeo.h };
 
-     draw_rect(W->screen->seltag->frame, g, THEME_DEFAULT->client_n.bg);
+     draw_rect(c->tag->frame, g, THEME_DEFAULT->client_n.bg);
 
      /* Selected client's border */
      if(W->client)
-          draw_rect(W->client->tag->frame, W->client->geo, THEME_DEFAULT->client_s.bg);
+          draw_rect(c->tag->frame, c->tag->sel->geo, THEME_DEFAULT->client_s.bg);
 }
 
 
@@ -167,9 +248,10 @@ client_focus(struct client *c)
      {
           c->tag->sel = c;
 
-          client_draw_bord();
-
+          client_draw_bord(c);
           client_grabbuttons(c, true);
+
+          XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime);
      }
 }
 
@@ -286,19 +368,20 @@ client_moveresize(struct client *c, struct geo g)
 {
      int bord = THEME_DEFAULT->client_border_width;
 
-     c->geo = c->wgeo = g;
+     c->geo = g;
 
      /* Window geo */
-     c->wgeo.x += bord;
-     c->wgeo.y += bord ;
-     c->wgeo.w -= (bord << 1);
-     c->wgeo.h -= (bord << 1);
+     c->wgeo.x = g.x + bord;
+     c->wgeo.y = g.y + bord ;
+     c->wgeo.w = g.w - (bord << 1);
+     c->wgeo.h = g.h - (bord << 1);
 
      XMoveResizeWindow(W->dpy, c->win,
                        c->wgeo.x, c->wgeo.y,
                        c->wgeo.w, c->wgeo.h);
 
-     client_draw_bord();
+     client_draw_bord(c);
+     client_configure(c);
 }
 
 void

+ 19 - 1
wmfs2/src/client.h

@@ -10,9 +10,13 @@
 #include "layout.h"
 
 void client_configure(struct client *c);
+
+struct client *client_next(struct client *c);
+struct client *client_prev(struct client *c);
 struct client *client_gb_win(Window w);
-struct client* client_gb_pos(struct tag *t, int x, int y);
+struct client *client_gb_pos(struct tag *t, int x, int y);
 struct client *client_next_with_pos(struct client *bc, Position p);
+void client_swap(struct client *c1, struct client *c2);
 void client_focus(struct client *c);
 void client_get_name(struct client *c);
 void client_close(struct client *c);
@@ -23,10 +27,24 @@ void client_maximize(struct client *c);
 void client_fac_resize(struct client *c, Position p, int fac);
 void client_remove(struct client *c);
 void client_free(void);
+
+/* Generated */
 void uicb_client_resize_Right(Uicb);
 void uicb_client_resize_Left(Uicb);
 void uicb_client_resize_Top(Uicb);
 void uicb_client_resize_Bottom(Uicb);
+void uicb_client_focus_Right(Uicb);
+void uicb_client_focus_Left(Uicb);
+void uicb_client_focus_Top(Uicb);
+void uicb_client_focus_Bottom(Uicb);
+void uicb_client_swapsel_Right(Uicb);
+void uicb_client_swapsel_Left(Uicb);
+void uicb_client_swapsel_Top(Uicb);
+void uicb_client_swapsel_Bottom(Uicb);
+void uicb_client_focus_next(Uicb);
+void uicb_client_focus_prev(Uicb);
+void uicb_client_swapsel_next(Uicb);
+void uicb_client_swapsel_prev(Uicb);
 
 static inline bool
 client_fac_geo(struct client *c, Position p, int fac)

+ 12 - 1
wmfs2/src/config.h

@@ -36,7 +36,18 @@ static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] =
      { "client_resize_left",   uicb_client_resize_Left },
      { "client_resize_top",    uicb_client_resize_Top },
      { "client_resize_bottom", uicb_client_resize_Bottom },
-
+     { "client_focus_right",   uicb_client_focus_Right },
+     { "client_focus_left",    uicb_client_focus_Left },
+     { "client_focus_top",     uicb_client_focus_Top },
+     { "client_focus_bottom",  uicb_client_focus_Bottom },
+     { "client_swap_right",    uicb_client_swapsel_Right },
+     { "client_swap_left",     uicb_client_swapsel_Left },
+     { "client_swap_top",      uicb_client_swapsel_Top },
+     { "client_swap_bottom",   uicb_client_swapsel_Bottom },
+     { "client_focus_next",    uicb_client_focus_next },
+     { "client_focus_prev",    uicb_client_focus_prev },
+     { "client_swap_next",     uicb_client_swapsel_next },
+     { "client_swap_prev",     uicb_client_swapsel_prev },
      { NULL, NULL }
 };
 

+ 10 - 11
wmfs2/src/event.c

@@ -35,6 +35,7 @@ event_buttonpress(XEvent *e)
           }
 }
 
+/*
 static void
 event_enternotify(XEvent *e)
 {
@@ -48,12 +49,13 @@ event_enternotify(XEvent *e)
      if((c = client_gb_win(ev->window)))
           client_focus(c);
 }
+*/
 
 static void
 event_clientmessageevent(XEvent *e)
 {
-     /*  XclientMessageEvent *ev = &e->xclient;
-       client *c;*/
+     /*  XClientMessageEvent *ev = &e->xclient;
+         client *c;*/
 }
 
 static void
@@ -184,15 +186,12 @@ event_unmapnotify(XEvent *e)
 static void
 event_motionnotify(XEvent *e)
 {
-    /*
-        XMotionEvent *ev = &e->xmotion;
-        client *c;
-
+     XMotionEvent *ev = &e->xmotion;
+     struct client *c;
 
-      * Option follow mouvement
-        if((c = client_gb_win(ev->subwindow)) && c != c->tag->sel)
-             client_focus(c);
-      */
+     /* Option follow mouvement */
+     if((c = client_gb_win(ev->subwindow)) && c != c->tag->sel)
+          client_focus(c);
 }
 
 static void
@@ -243,7 +242,7 @@ event_init(void)
      event_handle[ClientMessage]    = event_clientmessageevent;
      event_handle[ConfigureRequest] = event_configureevent;
      event_handle[DestroyNotify]    = event_destroynotify;
-     event_handle[EnterNotify]      = event_enternotify;
+     /*event_handle[EnterNotify]      = event_enternotify; use motion instead */
      event_handle[Expose]           = event_expose;
      event_handle[FocusIn]          = event_focusin;
      event_handle[KeyPress]         = event_keypress;

+ 3 - 0
wmfs2/src/screen.c

@@ -13,6 +13,7 @@
 #include "util.h"
 #include "tag.h"
 #include "infobar.h"
+#include "client.h"
 
 static struct screen*
 screen_new(struct geo *g, int id)
@@ -91,6 +92,8 @@ screen_update_sel(void)
                if(INAREA(x, y, s->geo))
                     break;
 
+          client_focus(s->seltag->sel);
+
           return (W->screen = s);
      }
 #endif /* HAVE_XINERAMA */

+ 9 - 0
wmfs2/src/util.h

@@ -44,6 +44,15 @@ color_atoh(const char *col)
      return (Color)strtol(col + shift, NULL, 16);
 }
 
+static inline void
+swap_ptr(void **x, void **y)
+{
+     void *t = *x;
+
+     *x = *y;
+     *y = t;
+}
+
 void *xmalloc(size_t nmemb, size_t size);
 void *xcalloc(size_t nmemb, size_t size);
 int xasprintf(char **strp, const char *fmt, ...);

+ 19 - 1
wmfs2/wmfsrc2

@@ -104,7 +104,7 @@
 
 [keys]
 
-  [key] mod = {"Control"} key = "Return" func = "spawn" cmd = "xterm" [/key]
+  [key] mod = {"Super"} key = "Return" func = "spawn" cmd = "xterm" [/key]
   [key] mod = {"Control","Alt"} key = "q" func = "quit" [/key]
   [key] mod = {"Super"} key = "1" func = "tag_set" cmd = "1" [/key]
   [key] mod = {"Super"} key = "2" func = "tag_set" cmd = "2" [/key]
@@ -113,6 +113,24 @@
   [key] mod = {"Super"} key = "a" func = "tag_prev" [/key]
   [key] mod = {"Super"} key = "z" func = "tag" cmd = "tag2" [/key]
 
+  [key] mod = {"Super"} key = "q" func = "client_close" [/key]
+
+  # Focus next / prev client
+  [key] mod = { "Alt" } key = "Tab" func = "client_focus_next" [/key]
+  [key] mod = { "Alt", "Shift" } key = "Tab" func = "client_focus_prev" [/key]
+
+  # Focus next client with direction
+  [key] mod = {"Alt"} key = "h" func = "client_focus_left"   [/key]
+  [key] mod = {"Alt"} key = "l" func = "client_focus_right"  [/key]
+  [key] mod = {"Alt"} key = "k" func = "client_focus_top"    [/key]
+  [key] mod = {"Alt"} key = "j" func = "client_focus_bottom" [/key]
+
+ # swap next client with direction:
+  [key] mod = {"Control", "Shift"} key = "h" func = "client_swap_left"   [/key]
+  [key] mod = {"Control", "Shift"} key = "l" func = "client_swap_right"  [/key]
+  [key] mod = {"Control", "Shift"} key = "k" func = "client_swap_top"    [/key]
+  [key] mod = {"Control", "Shift"} key = "j" func = "client_swap_bottom" [/key]
+
   # Resize selected tiled client with direction
   [key] mod = {"Super"} key = "h" func = "client_resize_left"   cmd = "20" [/key]
   [key] mod = {"Super"} key = "l" func = "client_resize_left"   cmd = "-20" [/key]