JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
add majordomo
[spectrwm.git] / scrotwm.c
index 6c1fc24..12b4265 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -50,7 +50,7 @@
 
 static const char      *cvstag = "$scrotwm$";
 
-#define        SWM_VERSION     "0.9"
+#define        SWM_VERSION     "0.9.1"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -173,13 +173,14 @@ int                       bar_extra = 1;
 int                    bar_extra_running = 0;
 int                    bar_verbose = 1;
 int                    bar_height = 0;
+int                    clock_enabled = 1;
 pid_t                  bar_pid;
 GC                     bar_gc;
 XGCValues              bar_gcv;
 int                    bar_fidx = 0;
 XFontStruct            *bar_fs;
 char                   *bar_fonts[] = {
-                           "-*-terminus-*-*-*-*-*-*-*-*-*-*-*-*",
+                           "-*-terminus-medium-*-*-*-*-*-*-*-*-*-*-*",
                            "-*-times-medium-r-*-*-*-*-*-*-*-*-*-*",
                            NULL
 };
@@ -250,6 +251,7 @@ void        max_stack(struct workspace *, struct swm_geometry *);
 
 void   grabbuttons(struct ws_win *, int);
 void   new_region(struct swm_screen *, int, int, int, int);
+void   update_modkey(unsigned int);
 
 struct layout {
        void            (*l_stack)(struct workspace *, struct swm_geometry *);
@@ -375,6 +377,7 @@ void                        configurenotify(XEvent *);
 void                   destroynotify(XEvent *);
 void                   enternotify(XEvent *);
 void                   focusin(XEvent *);
+void                   focusout(XEvent *);
 void                   mappingnotify(XEvent *);
 void                   maprequest(XEvent *);
 void                   propertynotify(XEvent *);
@@ -390,6 +393,7 @@ void                        (*handler[LASTEvent])(XEvent *) = {
                                [DestroyNotify] = destroynotify,
                                [EnterNotify] = enternotify,
                                [FocusIn] = focusin,
+                               [FocusOut] = focusout,
                                [MappingNotify] = mappingnotify,
                                [MapRequest] = maprequest,
                                [PropertyNotify] = propertynotify,
@@ -502,6 +506,7 @@ conf_load(char *filename)
        char                    *line, *cp, *var, *val;
        size_t                  len, lineno = 0;
        int                     i, sc;
+       unsigned int            modkey;
 
        DNPRINTF(SWM_D_MISC, "conf_load: filename %s\n", filename);
 
@@ -550,7 +555,9 @@ conf_load(char *filename)
                        break;
 
                case 'c':
-                       if (!varmatch(var, "color_focus", &i))
+                       if (!strncmp(var, "clock_enabled", strlen("clock_enabled")))
+                               clock_enabled = atoi(val);
+                       else if (!varmatch(var, "color_focus", &i))
                                setscreencolor(val, i, SWM_S_COLOR_FOCUS);
                        else if (!varmatch(var, "color_unfocus", &i))
                                setscreencolor(val, i, SWM_S_COLOR_UNFOCUS);
@@ -572,6 +579,22 @@ conf_load(char *filename)
                                goto bad;
                        break;
 
+               case 'm':
+                       if (!strncmp(var, "modkey", strlen("modkey"))) {
+                               modkey = MODKEY;
+                               if (!strncmp(val, "Mod2", strlen("Mod2")))
+                                       modkey = Mod2Mask;
+                               else if (!strncmp(val, "Mod3", strlen("Mod3")))
+                                       modkey = Mod3Mask;
+                               else if (!strncmp(val, "Mod4", strlen("Mod4")))
+                                       modkey = Mod4Mask;
+                               else
+                                       modkey = Mod1Mask;
+                               update_modkey(modkey);
+                       } else
+                               goto bad;
+                       break;
+
                case 'r':
                        if (!strncmp(var, "region", strlen("region")))
                                custom_region(val);
@@ -677,14 +700,18 @@ bar_update(void)
        } else
                strlcpy(bar_ext, "", sizeof bar_ext);
 
-       time(&tmt);
-       localtime_r(&tmt, &tm);
-       strftime(s, sizeof s, "%a %b %d %R %Z %Y", &tm);
+       if (clock_enabled == 0)
+               strlcpy(s, "", sizeof s);
+       else {
+               time(&tmt);
+               localtime_r(&tmt, &tm);
+               strftime(s, sizeof s, "%a %b %d %R %Z %Y    ", &tm);
+       }
        for (i = 0; i < ScreenCount(display); i++) {
                x = 1;
                TAILQ_FOREACH(r, &screens[i].rl, entry) {
-                       snprintf(loc, sizeof loc, "%s     %d:%d    %s    %s",
-                           s, x++, r->ws->idx + 1, bar_ext, bar_vertext);
+                       snprintf(loc, sizeof loc, "%d:%d    %s%s    %s",
+                           x++, r->ws->idx + 1, s, bar_ext, bar_vertext);
                        bar_print(r, loc);
                }
        }
@@ -1044,6 +1071,28 @@ spawnmenu(struct swm_region *r, union arg *args)
 }
 
 void
+unfocus_win(struct ws_win *win)
+{
+       if (win == NULL)
+               return;
+
+       if (win->ws->focus != win && win->ws->focus != NULL)
+               win->ws->focus_prev = win->ws->focus;
+
+       if (win->ws->r == NULL)
+               return;
+
+       grabbuttons(win, 0);
+       XSetWindowBorder(display, win->id,
+           win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
+       win->got_focus = 0;
+       if (win->ws->focus == win)
+               win->ws->focus = NULL;
+       if (cur_focus == win)
+               cur_focus = NULL;
+}
+
+void
 unfocus_all(void)
 {
        struct ws_win           *win;
@@ -1053,16 +1102,8 @@ unfocus_all(void)
 
        for (i = 0; i < ScreenCount(display); i++)
                for (j = 0; j < SWM_WS_MAX; j++)
-                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) {
-                               if (win->ws->r == NULL)
-                                       continue;
-                               grabbuttons(win, 0);
-                               XSetWindowBorder(display, win->id,
-                                   win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
-                               win->got_focus = 0;
-                               win->ws->focus = NULL;
-                               cur_focus = NULL;
-                       }
+                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+                               unfocus_win(win);
 }
 
 void
@@ -1073,10 +1114,14 @@ focus_win(struct ws_win *win)
        if (win == NULL)
                return;
 
-       if (win->ws->focus != win && win->ws->focus != NULL)
-               win->ws->focus_prev = win->ws->focus;
-
-       unfocus_all();
+       if (cur_focus)
+               unfocus_win(cur_focus);
+       if (win->ws->focus) {
+               /* probably shouldn't happen due to the previous unfocus_win */
+               DNPRINTF(SWM_D_FOCUS, "unfocusing win->ws->focus: %lu\n",
+                   win->ws->focus->id);
+               unfocus_win(win->ws->focus);
+       }
        win->ws->focus = win;
        if (win->ws->r != NULL) {
                cur_focus = win;
@@ -1131,6 +1176,8 @@ switchws(struct swm_region *r, union arg *args)
 
        ignore_enter = 1;
        /* set focus */
+       if (new_ws->focus == NULL)
+               new_ws->focus = TAILQ_FIRST(&new_ws->winlist);
        if (new_ws->focus)
                focus_win(new_ws->focus);
        stack();
@@ -2080,6 +2127,24 @@ struct button {
 };
 
 void
+update_modkey(unsigned int mod)
+{
+       int                     i;
+
+       for (i = 0; i < LENGTH(keys); i++)
+               if (keys[i].mod & ShiftMask)
+                       keys[i].mod = mod | ShiftMask;
+               else
+                       keys[i].mod = mod;
+
+       for (i = 0; i < LENGTH(buttons); i++)
+               if (buttons[i].mask & ShiftMask)
+                       buttons[i].mask = mod | ShiftMask;
+               else
+                       buttons[i].mask = mod;
+}
+
+void
 updatenumlockmask(void)
 {
        unsigned int            i, j;
@@ -2367,7 +2432,7 @@ unmanage_window(struct ws_win *win)
                ws->focus = TAILQ_FIRST(&ws->winlist);
        if (ws->focus == NULL || ws->focus == win) {
                ws->focus = NULL;
-               unfocus_all();
+               unfocus_win(win);
        } else
                focus_win(ws->focus);
        if (ws->focus_prev == win)
@@ -2450,13 +2515,15 @@ configurenotify(XEvent *e)
        DNPRINTF(SWM_D_EVENT, "configurenotify: window: %lu\n",
            e->xconfigure.window);
 
+       XMapWindow(display, e->xconfigure.window);
        win = find_window(e->xconfigure.window);
-       XMapWindow(display, win->id);
-       XGetWMNormalHints(display, win->id, &win->sh, &mask);
-       adjust_font(win);
-       XMapWindow(display, win->id);
-       if (font_adjusted)
-               stack();
+       if (win) {
+               XGetWMNormalHints(display, win->id, &win->sh, &mask);
+               adjust_font(win);
+               XMapWindow(display, win->id);
+               if (font_adjusted)
+                       stack();
+       }
 }
 
 void
@@ -2498,6 +2565,29 @@ focusin(XEvent *e)
 }
 
 void
+focusout(XEvent *e)
+{
+       DNPRINTF(SWM_D_EVENT, "focusout: window: %lu\n", e->xfocus.window);
+
+       if (cur_focus && cur_focus->ws->r &&
+           cur_focus->id == e->xfocus.window) {
+               struct swm_screen       *s = cur_focus->ws->r->s;
+               Window                  rr, cr;
+               int                     x, y, wx, wy;
+               unsigned int            mask;
+
+               /* Try to detect synergy hiding the cursor.  */
+               if (XQueryPointer(display, cur_focus->id, 
+                   &rr, &cr, &x, &y, &wx, &wy, &mask) != False &&
+                   cr == 0 && !mask &&
+                   x == DisplayWidth(display, s->idx)/2 &&
+                   y == DisplayHeight(display, s->idx)/2) {
+                       unfocus_win(cur_focus);
+               }
+       }
+}
+
+void
 mappingnotify(XEvent *e)
 {
        XMappingEvent           *ev = &e->xmapping;