JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Missed some more spaces...
[spectrwm.git] / scrotwm.c
index baf92d3..1880c6a 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -1,5 +1,4 @@
-/* cc -O2 -I /usr/X11R6/include/ scrotwm.c -L /usr/X11R6/lib/ -lX11 -o scrotwm */
-/* then add to .xinitrc */
+/* $scrotwm$ */
 /*
  * Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
  * Copyright (c) 2009 Ryan McBride <mcbride@countersiege.com>
 #define DNPRINTF(n,x...)       do { if (swm_debug & n) fprintf(stderr, x); } while(0)
 #define        SWM_D_EVENT             0x0001
 #define        SWM_D_WS                0x0002
+#define        SWM_D_FOCUS             0x0004
+#define        SWM_D_MISC              0x0008
 
 uint32_t               swm_debug = 0
                            | SWM_D_EVENT
                            | SWM_D_WS
+                           | SWM_D_FOCUS
+                           | SWM_D_MISC
                            ;
 #else
 #define DPRINTF(x...)
@@ -95,12 +98,18 @@ int                 width, height;
 int                    running = 1;
 int                    ignore_enter = 0;
 unsigned int           numlockmask = 0;
+unsigned long          col_focus = 0xff0000;   /* XXX should this be per ws? */
+unsigned long          col_unfocus = 0x888888;
 Display                        *display;
 Window                 root;
 
 struct ws_win {
        TAILQ_ENTRY(ws_win)     entry;
        Window                  id;
+       int                     x;
+       int                     y;
+       int                     width;
+       int                     height;
 };
 
 TAILQ_HEAD(ws_win_list, ws_win);
@@ -108,32 +117,33 @@ TAILQ_HEAD(ws_win_list, ws_win);
 /* define work spaces */
 #define SWM_WS_MAX             (10)
 struct workspace {
-       int                      visible;       /* workspace visible */
+       int                     visible;        /* workspace visible */
        struct ws_win           *focus;         /* which win has focus */
-       int                      winno;         /* total nr of windows */
-       struct ws_win_list       winlist;
+       int                     winno;          /* total nr of windows */
+       struct ws_win_list      winlist;
 } ws[SWM_WS_MAX];
 int                    current_ws = 0;
 
 /* args to functions */
 union arg {
-       int             id;
+       int                     id;
 #define SWM_ARG_ID_FOCUSNEXT   (0)
 #define SWM_ARG_ID_FOCUSPREV   (1)
 #define SWM_ARG_ID_FOCUSMAIN   (2)
+       char                    **argv;
 };
 
 void
 quit(union arg *args)
 {
+       DNPRINTF(SWM_D_MISC, "quit\n");
        running = 0;
 }
 
 void
 spawn(union arg *args)
 {
-       char                    *argv[] = { "xterm", NULL }; /* XXX make this in args */
-
+       DNPRINTF(SWM_D_MISC, "spawn: %s\n", args->argv[0]);
        /*
         * The double-fork construct avoids zombie processes and keeps the code
         * clean from stupid signal handlers.
@@ -143,7 +153,7 @@ spawn(union arg *args)
                        if(display)
                                close(ConnectionNumber(display));
                        setsid();
-                       execvp(argv[0], argv);
+                       execvp(args->argv[0], args->argv);
                        fprintf(stderr, "execvp failed\n");
                        perror(" failed");
                }
@@ -153,6 +163,24 @@ spawn(union arg *args)
 }
 
 void
+focus_win(struct ws_win *win)
+{
+       DNPRINTF(SWM_D_FOCUS, "focus_win: id: %d\n", win->id);
+       XSetWindowBorder(display, win->id, col_focus);
+       XSetInputFocus(display, win->id, RevertToPointerRoot, CurrentTime);
+       ws[current_ws].focus = win;
+}
+
+void
+unfocus_win(struct ws_win *win)
+{
+       DNPRINTF(SWM_D_FOCUS, "unfocus_win: id: %d\n", win->id);
+       XSetWindowBorder(display, win->id, col_unfocus);
+       if (ws[current_ws].focus == win)
+               ws[current_ws].focus = NULL;
+}
+
+void
 switchws(union arg *args)
 {
        int                     wsid = args->id;
@@ -176,23 +204,21 @@ switchws(union arg *args)
        current_ws = wsid;
 
        ignore_enter = 1;
-       if (ws[wsid].focus != NULL) {
-               DNPRINTF(SWM_D_WS, "switchws: focus %d\n", ws[wsid].focus);
-               XSetInputFocus(display, ws[wsid].focus->id, RevertToPointerRoot,
-                   CurrentTime);
-       }
+       if (ws[wsid].focus != NULL)
+               focus_win(ws[wsid].focus);
        XSync(display, False);
 }
 
 void
 focus(union arg *args)
 {
-       Window                  winfocus, winlostfocus;
+       struct ws_win           *winfocus, *winlostfocus;
 
+       DNPRINTF(SWM_D_FOCUS, "focus: id %d\n", args->id);
        if (ws[current_ws].focus == NULL || ws[current_ws].winno == 0)
                return;
 
-       winlostfocus = ws[current_ws].focus->id;
+       winlostfocus = ws[current_ws].focus;
 
        switch (args->id) {
        case SWM_ARG_ID_FOCUSPREV:
@@ -223,10 +249,9 @@ focus(union arg *args)
                return;
        }
 
-       winfocus = ws[current_ws].focus->id;
-       XSetWindowBorder(display, winlostfocus, 0x888888);
-       XSetWindowBorder(display, winfocus, 0xff0000);
-       XSetInputFocus(display, winfocus, RevertToPointerRoot, CurrentTime);
+       winfocus = ws[current_ws].focus;
+       unfocus_win(winlostfocus);
+       focus_win(winfocus);
        XSync(display, False);
 }
 
@@ -235,12 +260,13 @@ void
 stack(void)
 {
        XWindowChanges          wc;
-       struct ws_win           *win;
-       Window                  winfocus = root;
+       struct ws_win           wf, *win, *winfocus = &wf;
        int                     i, h, w, x, y, winno, hrh;
 
        DNPRINTF(SWM_D_EVENT, "stack: workspace: %d\n", current_ws);
 
+       winfocus->id = root;
+
        if (ws[current_ws].winno == 0)
                return;
 
@@ -282,23 +308,22 @@ stack(void)
                }
 
                bzero(&wc, sizeof wc);
-               wc.x = x;
-               wc.y = y;
-               wc.width = w;
-               wc.height = h;
+               win->x = wc.x = x;
+               win->y = wc.y = y;
+               win->width = wc.width = w;
+               win->height = wc.height = h;
                wc.border_width = 1;
                XConfigureWindow(display, win->id, CWX | CWY | CWWidth |
                    CWHeight | CWBorderWidth, &wc);
-               if (win == ws[current_ws].focus) {
-                       winfocus = win->id;
-                       XSetWindowBorder(display, win->id, 0xff0000);
-               } else
-                       XSetWindowBorder(display, win->id, 0x888888);
+               if (win == ws[current_ws].focus)
+                       winfocus = win;
+               else
+                       unfocus_win(win);
                XMapWindow(display, win->id);
                i++;
        }
 
-       XSetInputFocus(display, winfocus, RevertToPointerRoot, CurrentTime);
+       focus_win(winfocus); /* this has to be done outside of the loop */
        XSync(display, False);
 }
 
@@ -307,6 +332,7 @@ swap_to_main(union arg *args)
 {
        struct ws_win           *tmpwin = TAILQ_FIRST(&ws[current_ws].winlist);
 
+       DNPRINTF(SWM_D_MISC, "swap_to_main: win: %d\n", ws[current_ws].focus->id);
        TAILQ_REMOVE(&ws[current_ws].winlist, tmpwin, entry);
        TAILQ_INSERT_AFTER(&ws[current_ws].winlist, ws[current_ws].focus,
            tmpwin, entry);
@@ -317,6 +343,9 @@ swap_to_main(union arg *args)
        stack();
 }
 
+/* terminal + args */
+char                           *term[] = { "xterm", NULL };
+
 /* key definitions */
 struct key {
        unsigned int            mod;
@@ -326,7 +355,7 @@ struct key {
 } keys[] = {
        /* modifier             key     function                argument */
        { MODKEY,               XK_Return,      swap_to_main,   {0} },
-       { MODKEY | ShiftMask,   XK_Return,      spawn,          {0} },
+       { MODKEY | ShiftMask,   XK_Return,      spawn,          {.argv = term } },
        { MODKEY | ShiftMask,   XK_q,           quit,           {0} },
        { MODKEY,               XK_m,           focus,          {.id = SWM_ARG_ID_FOCUSMAIN} },
        { MODKEY,               XK_1,           switchws,       {.id = 0} },
@@ -349,6 +378,7 @@ updatenumlockmask(void)
        unsigned int            i, j;
        XModifierKeymap         *modmap;
 
+       DNPRINTF(SWM_D_MISC, "updatenumlockmask\n");
        numlockmask = 0;
        modmap = XGetModifierMapping(display);
        for (i = 0; i < 8; i++)
@@ -368,6 +398,7 @@ grabkeys(void)
        unsigned int            modifiers[] =
            { 0, LockMask, numlockmask, numlockmask | LockMask };
 
+       DNPRINTF(SWM_D_MISC, "grabkeys\n");
        updatenumlockmask();
 
        XUngrabKey(display, AnyKey, AnyModifier, root);
@@ -416,7 +447,7 @@ buttonpress(XEvent *e)
                return;
        if (ev->window == ws[current_ws].focus->id)
                return;
-
+#if 0
        TAILQ_FOREACH(win, &ws[current_ws].winlist, entry)
                if (win->id == ev->window) {
                        /* focus in the clicked window */
@@ -429,6 +460,7 @@ buttonpress(XEvent *e)
                        XSync(display, False);
                        break;
        }
+#endif
 }
 
 void
@@ -463,14 +495,13 @@ configurenotify(XEvent *e)
 void
 destroynotify(XEvent *e)
 {
-       size_t                   sz;
+       size_t                  sz;
        struct ws_win           *win;
        XDestroyWindowEvent     *ev = &e->xdestroywindow;
 
        DNPRINTF(SWM_D_EVENT, "destroynotify: window %d\n", ev->window);
 
        TAILQ_FOREACH (win, &ws[current_ws].winlist, entry) {
-               DNPRINTF(SWM_D_EVENT, "trying: %x\n", win->id);
                if (ev->window == win->id) {
                        /* find a window to focus */
                        ws[current_ws].focus =
@@ -506,13 +537,10 @@ enternotify(XEvent *e)
                return;
        }
        TAILQ_FOREACH (win, &ws[current_ws].winlist, entry) {
-               if (win->id == ev->window) {
-                       XSetInputFocus(display, ev->window, RevertToPointerRoot,
-                           CurrentTime);
-                       XSetWindowBorder(display, ev->window, 0xff0000);
-                       ws[current_ws].focus = win;
-               } else
-                       XSetWindowBorder(display, win->id, 0x888888);
+               if (win->id == ev->window)
+                       focus_win(win);
+               else
+                       unfocus_win(win);
        }
 }