JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Only get xrandr extension data if xrandr is supported.
[spectrwm.git] / spectrwm.c
index e86f14b..ace7c52 100644 (file)
@@ -659,6 +659,7 @@ void         do_sync(void);
 void    enternotify(xcb_enter_notify_event_t *);
 void    event_error(xcb_generic_error_t *);
 void    event_handle(xcb_generic_event_t *);
+char   *expand_tilde(char *);
 void    expose(xcb_expose_event_t *);
 struct ws_win  *find_window(xcb_window_t);
 int     floating_toggle_win(struct ws_win *);
@@ -696,6 +697,49 @@ void        unmapnotify(xcb_unmap_notify_event_t *);
 void    update_window(struct ws_win *);
 /*void  visibilitynotify(xcb_visibility_notify_event_t *);*/
 
+char *
+expand_tilde(char *s)
+{
+       struct passwd           *pwd;
+       int                     i, max;
+       char                    *user;
+       const char              *sc = s;
+       char                    *result;
+
+       if (s == NULL)
+               errx(1, "expand_tilde: NULL string.");
+
+       if (s[0] != '~') {
+               result = strdup(sc);
+               goto out;
+       }
+
+       ++s;
+
+       if ((max = sysconf(_SC_LOGIN_NAME_MAX)) == -1)
+               errx(1, "expand_tilde: sysconf");
+
+       if ((user = calloc(1, max + 1)) == NULL)
+               errx(1, "expand_tilde: calloc");
+
+       for (i = 0; s[i] != '/' && s[i] != '\0'; ++i)
+               user[i] = s[i];
+       user[i] = '\0';
+       s = &s[i];
+
+       pwd = strlen(user) == 0 ? getpwuid(getuid()) : getpwnam(user);
+       if (pwd == NULL)
+               result = strdup(sc);
+       else
+               if (asprintf(&result, "%s%s", pwd->pw_dir, s) == -1)
+                       result = NULL;
+out:
+       if (result == NULL)
+               errx(1, "expand_tilde: failed to allocate memory.");
+
+       return result;
+}
+
 int
 parse_rgb(const char *rgb, uint16_t *rr, uint16_t *gg, uint16_t *bb)
 {
@@ -5122,12 +5166,17 @@ setspawn(char *name, char *args)
 int
 setconfspawn(char *selector, char *value, int flags)
 {
+       char *args;
+
        /* suppress unused warning since var is needed */
        (void)flags;
 
-       DNPRINTF(SWM_D_SPAWN, "setconfspawn: [%s] [%s]\n", selector, value);
+       args = expand_tilde(value);
+
+       DNPRINTF(SWM_D_SPAWN, "setconfspawn: [%s] [%s]\n", selector, args);
 
-       setspawn(selector, value);
+       setspawn(selector, args);
+       free(args);
 
        DNPRINTF(SWM_D_SPAWN, "setconfspawn: done\n");
        return (0);
@@ -5803,7 +5852,7 @@ setconfvalue(char *selector, char *value, int flags)
        switch (flags) {
        case SWM_S_BAR_ACTION:
                free(bar_argv[0]);
-               if ((bar_argv[0] = strdup(value)) == NULL)
+               if ((bar_argv[0] = expand_tilde(value)) == NULL)
                        err(1, "setconfvalue: bar_action");
                break;
        case SWM_S_BAR_AT_BOTTOM:
@@ -6463,7 +6512,6 @@ manage_window(xcb_window_t id)
        struct quirk            *qp;
        uint32_t                event_mask, i;
        xcb_icccm_get_wm_protocols_reply_t      wpr;
-       xcb_icccm_get_wm_class_reply_t          tmpch;
 
        if ((win = find_window(id)) != NULL)
                return (win);   /* already being managed */
@@ -6629,12 +6677,7 @@ manage_window(xcb_window_t id)
 
        if (xcb_icccm_get_wm_class_reply(conn,
            xcb_icccm_get_wm_class(conn, win->id),
-           &tmpch, NULL)) {
-               win->ch.class_name = tmpch.class_name;
-               win->ch.instance_name = tmpch.instance_name;
-
-               xcb_icccm_get_wm_class_reply_wipe(&tmpch);
-
+           &win->ch, NULL)) {
                DNPRINTF(SWM_D_CLASS, "manage_window: class: %s, name: %s\n",
                    win->ch.class_name, win->ch.instance_name);
 
@@ -6717,6 +6760,8 @@ free_window(struct ws_win *win)
        if (win->wa)
                free(win->wa);
 
+       xcb_icccm_get_wm_class_reply_wipe(&win->ch);
+
        kill_refs(win);
 
        /* paint memory */
@@ -7113,7 +7158,6 @@ enternotify(xcb_enter_notify_event_t *e)
 void
 leavenotify(xcb_leave_notify_event_t *e)
 {
-       struct ws_win           *win;
        DNPRINTF(SWM_D_FOCUS, "leavenotify: window: 0x%x, mode: %s(%d), "
            "detail: %s(%d), root: 0x%x, subwindow: 0x%x, same_screen_focus: "
            "%s, state: %d\n", e->event, get_notify_mode_label(e->mode),
@@ -7651,12 +7695,15 @@ setup_screens(void)
        c = xcb_randr_query_version(conn, 1, 1);
        r = xcb_randr_query_version_reply(conn, c, NULL);
        if (r) {
-               if (r->major_version >= 1)
-                       xrandr_support = 1;
+               if (r->major_version >= 1) {
+                       qep = xcb_get_extension_data(conn, &xcb_randr_id);
+                       if (qep) {
+                               xrandr_support = 1;
+                               xrandr_eventbase = qep->first_event;
+                       }
+               }
                free(r);
        }
-       qep = xcb_get_extension_data(conn, &xcb_randr_id);
-       xrandr_eventbase = qep->first_event;
 
        cursor_font = xcb_generate_id(conn);
        xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor");