JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
add majordomo
[spectrwm.git] / scrotwm.c
index ef373bb..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>
@@ -160,7 +160,7 @@ int                 font_adjusted = 0;
 /* dialog windows */
 double                 dialog_ratio = .6;
 /* status bar */
-#define SWM_BAR_MAX    (128)
+#define SWM_BAR_MAX    (256)
 char                   *bar_argv[] = { NULL, NULL };
 int                    bar_pipe[2];
 char                   bar_ext[SWM_BAR_MAX];
@@ -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
 };
@@ -249,6 +250,8 @@ void        horizontal_stack(struct workspace *, struct swm_geometry *);
 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 *);
@@ -353,6 +356,7 @@ struct quirk {
        { "OpenOffice.org 2.4", "VCLSalFrame",  SWM_Q_FLOAT },
        { "OpenOffice.org 3.0", "VCLSalFrame",  SWM_Q_FLOAT },
        { "Firefox-bin",        "firefox-bin",  SWM_Q_TRANSSZ },
+       { "Firefox",            "Dialog",       SWM_Q_FLOAT },
        { "Gimp",               "gimp",         SWM_Q_FLOAT | SWM_Q_ANYWHERE },
        { "XTerm",              "xterm",        SWM_Q_XTERM_FONTADJ },
        { "xine",               "Xine Window",  SWM_Q_FLOAT | SWM_Q_ANYWHERE },
@@ -373,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 *);
@@ -388,6 +393,7 @@ void                        (*handler[LASTEvent])(XEvent *) = {
                                [DestroyNotify] = destroynotify,
                                [EnterNotify] = enternotify,
                                [FocusIn] = focusin,
+                               [FocusOut] = focusout,
                                [MappingNotify] = mappingnotify,
                                [MapRequest] = maprequest,
                                [PropertyNotify] = propertynotify,
@@ -437,8 +443,6 @@ setscreencolor(char *val, int i, int c)
                    i, ScreenCount(display));
 }
 
-void           new_region(struct swm_screen *, int, int, int, int);
-
 void
 custom_region(char *val)
 {
@@ -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();
@@ -1289,6 +1336,10 @@ focus(struct swm_region *r, union arg *args)
 
        case SWM_ARG_ID_FOCUSMAIN:
                winfocus = TAILQ_FIRST(wl);
+               if (winfocus == cur_focus)
+                       winfocus = cur_focus->ws->focus_prev;
+               if (winfocus == NULL)
+                       return;
                break;
 
        default:
@@ -2076,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;
@@ -2363,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)
@@ -2446,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
@@ -2494,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;
@@ -2790,6 +2884,11 @@ screenchange(XEvent *e) {
        TAILQ_FOREACH(r, &screens[i].rl, entry)
                TAILQ_FOREACH(win, &r->ws->winlist, entry)
                        XUnmapWindow(display, win->id);
+
+       /* add bars to all regions */
+       for (i = 0; i < ScreenCount(display); i++)
+               TAILQ_FOREACH(r, &screens[i].rl, entry)
+                       bar_setup(r);
        stack();
 }
 
@@ -2889,6 +2988,26 @@ setup_screens(void)
        }
 }
 
+void
+workaround(void)
+{
+       int                     i;
+       Atom                    netwmcheck, netwmname, utf8_string;
+       Window                  root;
+
+       /* work around sun jdk bugs, code from wmname */
+       netwmcheck = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
+       netwmname = XInternAtom(display, "_NET_WM_NAME", False);
+       utf8_string = XInternAtom(display, "UTF8_STRING", False);
+       for (i = 0; i < ScreenCount(display); i++) {
+               root = screens[i].root;
+               XChangeProperty(display, root, netwmcheck, XA_WINDOW, 32,
+                   PropModeReplace, (unsigned char *)&root, 1);
+               XChangeProperty(display, root, netwmname, utf8_string, 8,
+                   PropModeReplace, "LG3D", strlen("LG3D"));
+       }
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -2942,7 +3061,8 @@ main(int argc, char *argv[])
                TAILQ_FOREACH(r, &screens[i].rl, entry)
                        bar_setup(r);
 
-       /* ws[0].focus = TAILQ_FIRST(&ws[0].winlist); */
+       /* set some values to work around bad programs */
+       workaround();
 
        grabkeys();
        stack();