]> git.mdlowis.com Git - proto/anvil.git/commitdiff
added keyboard shortcuts to switch workspaces and send windows to a workspace
authorMichael D. Lowis <mike.lowis@gentex.com>
Thu, 12 Mar 2020 20:22:46 +0000 (16:22 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Thu, 12 Mar 2020 20:22:46 +0000 (16:22 -0400)
anvil.c
anvil.h
client.c
keys.c [new file with mode: 0644]
mons.c

diff --git a/anvil.c b/anvil.c
index d7004678ffa2492475d25a485b557589c1118b81..0540e1e2e082af7081824672046587371c83a2c1 100644 (file)
--- a/anvil.c
+++ b/anvil.c
@@ -165,7 +165,7 @@ static void xexpose(XEvent* e)
 
 static void xkeypress(XEvent* e)
 {
-    (void)e;
+    keys_run(&(e->xkey));
 }
 
 int main(void)
@@ -184,6 +184,7 @@ int main(void)
     check_for_wm();
     mons_init();
     client_initall();
+    keys_init();
 
     /* setup event handlers */
     X.eventfns[ButtonPress] = xbtnpress;
diff --git a/anvil.h b/anvil.h
index 342ad9cee1ea4e35a38ae41aa2cb021e27e027a2..6812b1108d11321cc15a3dfeed4dcf49120c798e 100644 (file)
--- a/anvil.h
+++ b/anvil.h
@@ -1,9 +1,12 @@
 #include <X11/X.h>
 #include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/XKBlib.h>
 #include <X11/extensions/Xinerama.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <assert.h>
 
 #define min(a,b) (a < b ? a : b)
 #define max(a,b) (a > b ? a : b)
@@ -52,12 +55,27 @@ typedef struct Location {
     Client* client;
 } Location;
 
+typedef union {
+    int i;
+} Arg;
+
+typedef struct {
+    unsigned int mod;
+    KeySym keysym;
+    void (*func)(Arg* arg);
+    Arg arg;
+} Key;
+
 #define BORDER_WIDTH 5
 #define TITLE_HEIGHT 10
 
 /* anvil.c */
 extern XConf X;
 
+/* keys.c */
+void keys_init(void);
+void keys_run(XKeyEvent* ev);
+
 /* mons.c */
 extern Monitor* Monitors;
 void mons_init(void);
@@ -65,6 +83,8 @@ void mons_addclient(Client* c);
 void mons_delclient(Client* c);
 int mons_find(Window win, Location* loc);
 void mons_place(Client* c);
+void mons_wspace(int i);
+void mons_towspace(Client* c, int i);
 
 /* client.c */
 extern Client* Focused;
@@ -78,6 +98,7 @@ void client_move(Client* c, int xdiff, int ydiff);
 void client_resize(Client* c, int xdiff, int ydiff);
 void client_close(Client* c);
 void client_focus(Client* c);
+void client_show(Client* c, int show);
 
 /* error.c */
 extern int (*error_default)(Display* disp, XErrorEvent* ev);
index e961417433d8b163961dc21f734605599380ec43..09bfc14a53bf8be5d2a0416f8116692157d0662a 100644 (file)
--- a/client.c
+++ b/client.c
@@ -151,4 +151,18 @@ void client_focus(Client* c)
         client_draw(prev);
     }
     XSync(X.disp, False);
+}
+
+void client_show(Client* c, int show)
+{
+    if (show)
+    {
+        XMapWindow(X.disp, c->frame);
+        XMapWindow(X.disp, c->win);
+    }
+    else
+    {
+        XUnmapWindow(X.disp, c->frame);
+        XUnmapWindow(X.disp, c->win);
+    }
 }
\ No newline at end of file
diff --git a/keys.c b/keys.c
new file mode 100644 (file)
index 0000000..4a1c5f0
--- /dev/null
+++ b/keys.c
@@ -0,0 +1,69 @@
+#include "anvil.h"
+
+static void set_workspace(Arg* arg)
+{
+    mons_wspace(arg->i);
+}
+
+static void to_workspace(Arg* arg)
+{
+    mons_towspace(Focused, arg->i);
+}
+
+#define MODKEY Mod4Mask
+
+static Key keys[] = {
+    { MODKEY,   XK_1,   set_workspace,  {.i = 0 } },
+    { MODKEY,   XK_2,   set_workspace,  {.i = 1 } },
+    { MODKEY,   XK_3,   set_workspace,  {.i = 2 } },
+    { MODKEY,   XK_4,   set_workspace,  {.i = 3 } },
+    { MODKEY,   XK_5,   set_workspace,  {.i = 4 } },
+    { MODKEY,   XK_6,   set_workspace,  {.i = 5 } },
+    { MODKEY,   XK_7,   set_workspace,  {.i = 6 } },
+    { MODKEY,   XK_8,   set_workspace,  {.i = 7 } },
+    { MODKEY,   XK_9,   set_workspace,  {.i = 8 } },
+    { MODKEY,   XK_0,   set_workspace,  {.i = 9 } },
+
+    { MODKEY|ShiftMask,   XK_1,   to_workspace,  {.i = 0 } },
+    { MODKEY|ShiftMask,   XK_2,   to_workspace,  {.i = 1 } },
+    { MODKEY|ShiftMask,   XK_3,   to_workspace,  {.i = 2 } },
+    { MODKEY|ShiftMask,   XK_4,   to_workspace,  {.i = 3 } },
+    { MODKEY|ShiftMask,   XK_5,   to_workspace,  {.i = 4 } },
+    { MODKEY|ShiftMask,   XK_6,   to_workspace,  {.i = 5 } },
+    { MODKEY|ShiftMask,   XK_7,   to_workspace,  {.i = 6 } },
+    { MODKEY|ShiftMask,   XK_8,   to_workspace,  {.i = 7 } },
+    { MODKEY|ShiftMask,   XK_9,   to_workspace,  {.i = 8 } },
+    { MODKEY|ShiftMask,   XK_0,   to_workspace,  {.i = 9 } },
+};
+
+void keys_init(void)
+{
+    KeyCode code;
+    for (unsigned int i = 0; i < sizeof(keys)/sizeof(keys[0]); i++)
+    {
+        if ((code = XKeysymToKeycode(X.disp, keys[i].keysym)))
+        {
+            XGrabKey(X.disp, code, keys[i].mod, X.root, True, GrabModeAsync, GrabModeAsync);
+        }
+    }
+}
+
+void keys_run(XKeyEvent* ev)
+{
+    KeySym keysym = XkbKeycodeToKeysym(X.disp, ev->keycode, 0, 0);
+    for (unsigned int i = 0; i < sizeof(keys)/sizeof(keys[0]); i++)
+    {
+        printf("%d: (%d == %d) && (%d == %d)\n",
+            (int)i,
+            (int)keysym,
+            (int)keys[i].keysym,
+            (int)keys[i].mod,
+            (int)ev->state
+        );
+        if (keysym == keys[i].keysym && keys[i].mod == ev->state && keys[i].func)
+        {
+            keys[i].func(&(keys[i].arg));
+            break;
+        }
+    }
+}
diff --git a/mons.c b/mons.c
index ed6cebd4d97f5703421c23d546bd22ff478a206c..ff62381cf4e81b26256e1863559c771ccb2d6b7d 100644 (file)
--- a/mons.c
+++ b/mons.c
@@ -1,6 +1,11 @@
 #include "anvil.h"
 #include <math.h>
 
+static Monitor* pickmon(void);
+static Workspace* pickws(Monitor* mon, int wsid);
+static Client* delclient(Client* list, Client* dead);
+static void client_visibility(Workspace* wspace, int show);
+
 Monitor* Monitors = NULL;
 
 void mons_init(void)
@@ -11,7 +16,12 @@ void mons_init(void)
     for (int i = 0; i < nmons; i++)
     {
         Monitor* m = ecalloc(1, sizeof(Monitor));
-        m->wspaces = ecalloc(1, sizeof(Workspace));
+        for (int i = 0; i < 10; i++)
+        {
+            Workspace* wspace = ecalloc(1, sizeof(Workspace));
+            wspace->next = m->wspaces;
+            m->wspaces = wspace;
+        }
         m->cspace = m->wspaces;
         m->x = mons[i].x_org;
         m->y = mons[i].y_org;
@@ -35,19 +45,6 @@ void mons_addclient(Client* c)
     mons_place(c);
 }
 
-Client* delclient(Client* list, Client* dead)
-{
-    if (list == dead)
-    {
-        list = list->next;
-    }
-    else
-    {
-        list->next = delclient(list->next, dead);
-    }
-    return list;
-}
-
 void mons_delclient(Client* c)
 {
     Location loc = {0};
@@ -117,4 +114,86 @@ void mons_place(Client* c)
             closest->cspace->floating = c;
         }
     }
-}
\ No newline at end of file
+}
+
+void mons_wspace(int wsid)
+{
+    Monitor* mon = pickmon();
+    Workspace* wspace = pickws(mon, wsid);
+    if (mon->cspace != wspace)
+    {
+        client_visibility(mon->cspace, 0);
+        client_visibility(wspace, 1);
+        mon->cspace = wspace;
+    }
+}
+
+void mons_towspace(Client* c, int wsid)
+{
+    Location loc;
+    printf("%p to %d\n", c, wsid);
+    if (mons_find(c->win, &loc))
+    {
+        Workspace* wspace = pickws(loc.monitor, wsid);
+        if (wspace != loc.workspace)
+        {
+            client_show(c, 0);
+            loc.workspace->floating = delclient(loc.workspace->floating, c);
+            c->next = wspace->floating;
+            wspace->floating = c;
+        }
+    }
+}
+
+static Monitor* pickmon(void)
+{
+    Window root = 0, child = 0;
+    int ptrx = 0, ptry = 0, winx = 0, winy = 0, mask = 0;
+    XQueryPointer(X.disp, X.root, &root, &child, &ptrx, &ptry, &winx, &winy, (unsigned int*)&mask);
+    Monitor* mon = Monitors;
+    for (; mon; mon = mon->next)
+    {
+        if ((mon->x <= ptrx && ptrx < mon->x+mon->w) && (mon->y <= ptry && ptry < mon->y+mon->h))
+        {
+            break;
+        }
+    }
+    assert(mon);
+    return mon;
+}
+
+static Workspace* pickws(Monitor* mon, int wsid)
+{
+    Workspace* wspace = mon->wspaces;
+    int i = 0;
+    for (; wspace; wspace = wspace->next, i++)
+    {
+        if (i == wsid)
+        {
+            break;
+        }
+    }
+    return wspace;
+}
+
+static Client* delclient(Client* list, Client* dead)
+{
+    if (list == dead)
+    {
+        list = list->next;
+    }
+    else
+    {
+        list->next = delclient(list->next, dead);
+    }
+    return list;
+}
+
+static void client_visibility(Workspace* wspace, int show)
+{
+    for (Client* client = wspace->floating; client; client = client->next)
+    {
+        client_show(client, show);
+    }
+    XSync(X.disp, False);
+}