]> code.delx.au - spectrwm/blobdiff - spectrwm.c
avoid a free on an uninitialized variable by setting optval to NULL.
[spectrwm] / spectrwm.c
index 1522296d6037c10ac039b935b03b216cf1164b28..132743fa21014e43f26cda140826c1e5390477a2 100644 (file)
@@ -387,7 +387,7 @@ char                *bar_fonts;
 XftColor        bar_font_color;
 struct passwd  *pwd;
 char           *startup_exception;
-unsigned int   nr_exceptions = 0;
+unsigned int    nr_exceptions = 0;
 
 /* layout manager data */
 struct swm_geometry {
@@ -1055,8 +1055,8 @@ pid_t      window_get_pid(xcb_window_t);
 void    wkill(struct swm_region *, union arg *);
 void    workaround(void);
 void    xft_init(struct swm_region *);
-void   _add_startup_exception(const char *, va_list);
-void   add_startup_exception(const char *, ...);
+void    _add_startup_exception(const char *, va_list);
+void    add_startup_exception(const char *, ...);
 
 RB_PROTOTYPE(key_tree, key, entry, key_cmp);
 RB_GENERATE(key_tree, key, entry, key_cmp);
@@ -2539,7 +2539,8 @@ bar_setup(struct swm_region *r)
        r->bar->id = xcb_generate_id(conn);
        wa[0] = r->s->c[SWM_S_COLOR_BAR].pixel;
        wa[1] = r->s->c[SWM_S_COLOR_BAR_BORDER_UNFOCUS].pixel;
-       wa[2] = XCB_EVENT_MASK_EXPOSURE;
+       wa[2] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION |
+           XCB_EVENT_MASK_POINTER_MOTION_HINT;
 
        xcb_create_window(conn, XCB_COPY_FROM_PARENT, r->bar->id, r->s->root,
            X(r->bar), Y(r->bar), WIDTH(r->bar), HEIGHT(r->bar),
@@ -4723,7 +4724,7 @@ get_win_name(xcb_window_t win)
                        free(r);
                        /* Use WM_NAME instead; no UTF-8. */
                        c = xcb_get_property(conn, 0, win, XCB_ATOM_WM_NAME,
-                               XCB_GET_PROPERTY_TYPE_ANY, 0, UINT_MAX);
+                           XCB_GET_PROPERTY_TYPE_ANY, 0, UINT_MAX);
                        r = xcb_get_property_reply(conn, c, NULL);
 
                        if (!r)
@@ -4735,7 +4736,7 @@ get_win_name(xcb_window_t win)
                }
                if (r->length > 0)
                        name = strndup(xcb_get_property_value(r),
-                                  xcb_get_property_value_length(r));
+                           xcb_get_property_value_length(r));
 
                free(r);
        }
@@ -6018,15 +6019,25 @@ setspawn(const char *name, const char *args)
 int
 setconfspawn(char *selector, char *value, int flags)
 {
-       char *args;
-
-       /* suppress unused warning since var is needed */
-       (void)flags;
+       char            *args;
+       char            which[PATH_MAX];
+       size_t          i;
 
        args = expand_tilde(value);
 
        DNPRINTF(SWM_D_SPAWN, "setconfspawn: [%s] [%s]\n", selector, args);
 
+       /* verify we have the goods */
+       snprintf(which, sizeof which, "which %s", value);
+       for (i = strlen("which "); i < strlen(which); i++)
+               if (which[i] == ' ') {
+                       which[i] = '\0';
+                       break;
+               }
+       if (flags == 0 && system(which) != 0)
+               add_startup_exception("could not find %s",
+                   &which[strlen("which ")]);
+
        setspawn(selector, args);
        free(args);
 
@@ -6039,10 +6050,6 @@ setup_spawn(void)
 {
        setconfspawn("term",            "xterm",                0);
        setconfspawn("spawn_term",      "xterm",                0);
-       setconfspawn("screenshot_all",  "screenshot.sh full",   0);
-       setconfspawn("screenshot_wind", "screenshot.sh window", 0);
-       setconfspawn("lock",            "xlock",                0);
-       setconfspawn("initscr",         "initscreen.sh",        0);
        setconfspawn("menu",            "dmenu_run"
                                        " -fn $bar_font"
                                        " -nb $bar_color"
@@ -6064,9 +6071,11 @@ setup_spawn(void)
                                        " -sb $bar_border"
                                        " -sf $bar_color",      0);
 
-       /* only test dmenu for now, really should expand this */
-       if (system("dmenu -v") != 0)
-               add_startup_exception("you must install dmenu");
+       /* these are not verified for existence */
+       setconfspawn("lock",            "xlock",                1);
+       setconfspawn("screenshot_all",  "screenshot.sh full",   1);
+       setconfspawn("screenshot_wind", "screenshot.sh window", 1);
+       setconfspawn("initscr",         "initscreen.sh",        1);
 }
 
 /* key bindings */
@@ -7217,7 +7226,7 @@ int
 conf_load(const char *filename, int keymapping)
 {
        FILE                    *config;
-       char                    *line = NULL, *cp, *optsub, *optval;
+       char                    *line = NULL, *cp, *optsub, *optval = NULL;
        size_t                  linelen, lineno = 0;
        int                     wordlen, i, optidx;
        struct config_option    *opt = NULL;
@@ -7237,8 +7246,8 @@ conf_load(const char *filename, int keymapping)
                if (line)
                        free(line);
 
-               if ((line = fparseln(config, &linelen, &lineno, NULL, 0))
-                   == NULL) {
+               if ((line = fparseln(config, &linelen, &lineno, NULL,
+                   FPARSELN_UNESCCOMM | FPARSELN_UNESCCONT)) == NULL) {
                        if (ferror(config))
                                err(1, "%s", filename);
                        else
@@ -7307,6 +7316,12 @@ conf_load(const char *filename, int keymapping)
                cp += strspn(cp, "= \t\n"); /* eat trailing */
                /* get RHS value */
                optval = strdup(cp);
+               if (strlen(optval) == 0) {
+                       add_startup_exception("%s: line %zd: must supply value "
+                           "to %s", filename, lineno,
+                           configopt[optidx].optname);
+                       goto invalid;
+               }
                /* call function to deal with it all */
                if (configopt[optidx].func(optsub, optval,
                    configopt[optidx].funcflags) != 0) {
@@ -8194,7 +8209,7 @@ enternotify(xcb_enter_notify_event_t *e)
                        /* If no windows on pointer region, then focus root. */
                        r = root_to_region(e->root, SWM_CK_POINTER);
                        if (r == NULL) {
-                               DNPRINTF(SWM_D_EVENT, "enterntoify: "
+                               DNPRINTF(SWM_D_EVENT, "enternotify: "
                                    "NULL region; ignoring.\n");
                                return;
                        }
@@ -8209,7 +8224,7 @@ enternotify(xcb_enter_notify_event_t *e)
                focus_win(get_focus_magic(win));
        }
 
-       focus_flush();
+       xcb_flush(conn);
 }
 
 #ifdef SWM_DEBUG
@@ -8728,6 +8743,7 @@ scan_xrandr(int i)
        int                                             ncrtc = 0;
 #endif /* SWM_XRR_HAS_CRTC */
        struct swm_region                               *r;
+       struct ws_win                                   *win;
        int                                             num_screens;
        xcb_randr_get_screen_resources_current_cookie_t src;
        xcb_randr_get_screen_resources_current_reply_t  *srr;
@@ -8752,9 +8768,6 @@ scan_xrandr(int i)
                xcb_destroy_window(conn, r->id);
                TAILQ_REMOVE(&screens[i].rl, r, entry);
                TAILQ_INSERT_TAIL(&screens[i].orl, r, entry);
-
-               if (r->s->r_focus == r)
-                       r->s->r_focus = NULL;
        }
        outputs = 0;
 
@@ -8804,6 +8817,16 @@ scan_xrandr(int i)
                    screen->height_in_pixels);
 
 out:
+       /* Cleanup unused previously visible workspaces. */
+       TAILQ_FOREACH(r, &screens[i].orl, entry) {
+               TAILQ_FOREACH(win, &r->ws->winlist, entry)
+                       unmap_window(win);
+
+               /* The screen shouldn't focus on an unused region. */
+               if (screens[i].r_focus == r)
+                       screens[i].r_focus = NULL;
+       }
+
        DNPRINTF(SWM_D_MISC, "scan_xrandr: done.\n");
 }
 
@@ -8833,16 +8856,19 @@ screenchange(xcb_randr_screen_change_notify_event_t *e)
        for (i = 0; i < num_screens; i++) {
                TAILQ_FOREACH(r, &screens[i].rl, entry)
                        bar_setup(r);
+       }
 
-               if (screens[0].r_focus == NULL) {
-                       /* Focus on first region. */
-                       r = TAILQ_FIRST(&screens[0].rl);
-                       if (r)
+       stack();
+
+       /* Make sure a region has focus on each screen. */
+       for (i = 0; i < num_screens; i++) {
+               if (screens[i].r_focus == NULL) {
+                       r = TAILQ_FIRST(&screens[i].rl);
+                       if (r != NULL)
                                focus_region(r);
                }
        }
 
-       stack();
        bar_draw();
        focus_flush();
 }