]> code.delx.au - spectrwm/blobdiff - spectrwm.c
add missing prototypes
[spectrwm] / spectrwm.c
index c69245b5b6db985a3f92242a8e3ea8bc15dd2638..9a31937db60526e1a0eccf15e35fba99e4cd9207 100644 (file)
@@ -90,6 +90,7 @@
 #include <util.h>
 #include <X11/cursorfont.h>
 #include <X11/extensions/Xrandr.h>
+#include <X11/Xcursor/Xcursor.h>
 #include <X11/Xft/Xft.h>
 #include <X11/Xlib-xcb.h>
 #include <xcb/xcb_atom.h>
@@ -672,44 +673,130 @@ struct ewmh_hint {
     {"_SWM_WM_STATE_MANUAL", XCB_ATOM_NONE},
 };
 
+/* Cursors */
+enum {
+       XC_FLEUR,
+       XC_LEFT_PTR,
+       XC_BOTTOM_LEFT_CORNER,
+       XC_BOTTOM_RIGHT_CORNER,
+       XC_SIZING,
+       XC_TOP_LEFT_CORNER,
+       XC_TOP_RIGHT_CORNER,
+       XC_MAX
+};
+
+struct cursors {
+       char            *name; /* Name used by Xcursor .*/
+       uint8_t         cf_char; /* cursorfont index. */
+       xcb_cursor_t    cid;
+} cursors[XC_MAX] =    {
+       {"fleur", XC_fleur, XCB_CURSOR_NONE},
+       {"left_ptr", XC_left_ptr, XCB_CURSOR_NONE},
+       {"bottom_left_corner", XC_bottom_left_corner, XCB_CURSOR_NONE},
+       {"bottom_right_corner", XC_bottom_right_corner, XCB_CURSOR_NONE},
+       {"sizing", XC_sizing, XCB_CURSOR_NONE},
+       {"top_left_corner", XC_top_left_corner, XCB_CURSOR_NONE},
+       {"top_right_corner", XC_top_right_corner, XCB_CURSOR_NONE},
+};
+
 /* function prototypes */
+void    adjust_font(struct ws_win *);
+void    bar_class_name(char *, size_t, struct swm_region *);
+void    bar_class_title_name(char *, size_t, struct swm_region *);
+void    bar_cleanup(struct swm_region *);
+void    bar_extra_stop(void);
+void    bar_fmt(const char *, char *, struct swm_region *, size_t);
+void    bar_fmt_expand(char *, size_t);
+void    bar_fmt_print(void);
+void    bar_print(struct swm_region *, const char *);
+void    bar_print_legacy(struct swm_region *, const char *);
+void    bar_refresh(void);
+void    bar_replace(char *, char *, struct swm_region *, size_t);
+void    bar_replace_pad(char *, int *, size_t);
+char *  bar_replace_seq(char *, char *, struct swm_region *, size_t *,
+            size_t);
+void    bar_setup(struct swm_region *);
+void    bar_signal(int);
+void    bar_title_name(char *, size_t, struct swm_region *);
+void    bar_toggle(struct swm_region *, union arg *);
+void    bar_update(void);
+void    bar_urgent(char *, size_t);
+void    bar_window_float(char *, size_t, struct swm_region *);
+void    bar_window_name(char *, size_t, struct swm_region *);
+void    bar_workspace_name(char *, size_t, struct swm_region *);
 void    buttonpress(xcb_button_press_event_t *);
 void    check_conn(void);
+void    clear_keys(void);
 void    clientmessage(xcb_client_message_event_t *);
-int     conf_load(char *, int);
+void    client_msg(struct ws_win *, xcb_atom_t, xcb_timestamp_t);
+int     conf_load(const char *, int);
 void    configurenotify(xcb_configure_notify_event_t *);
 void    configurerequest(xcb_configure_request_event_t *);
+void    config_win(struct ws_win *, xcb_configure_request_event_t *);
 void    constrain_window(struct ws_win *, struct swm_region *, int);
+int     count_win(struct workspace *, int);
+void    cursors_cleanup(void);
+void    cursors_load(void);
+void    custom_region(char *);
+void    cyclescr(struct swm_region *, union arg *);
+void    cyclews(struct swm_region *, union arg *);
+void    cycle_layout(struct swm_region *, union arg *);
 void    destroynotify(xcb_destroy_notify_event_t *);
+void    dumpwins(struct swm_region *, union arg *);
+int     enable_wm(void);
 void    enternotify(xcb_enter_notify_event_t *);
 void    event_drain(uint8_t);
 void    event_error(xcb_generic_error_t *);
 void    event_handle(xcb_generic_event_t *);
-char   *expand_tilde(char *);
+void    ewmh_autoquirk(struct ws_win *);
+void    ewmh_get_win_state(struct ws_win *);
+int     ewmh_set_win_fullscreen(struct ws_win *, int);
+void    ewmh_update_actions(struct ws_win *);
+void    ewmh_update_win_state(struct ws_win *, xcb_atom_t, long);
+char   *expand_tilde(const char *);
 void    expose(xcb_expose_event_t *);
+void    fake_keypress(struct ws_win *, xcb_keysym_t, uint16_t);
+struct pid_e   *find_pid(pid_t);
+struct ws_win  *find_unmanaged_window(xcb_window_t); 
 struct ws_win  *find_window(xcb_window_t);
+void    floating_toggle(struct swm_region *, union arg *);
 int     floating_toggle_win(struct ws_win *);
 void    focus(struct swm_region *, union arg *);
-void    focus_flush(void);
-struct ws_win  *get_focus_magic(struct ws_win *);
-struct ws_win  *get_focus_prev(struct ws_win *);
-void    focus_win(struct ws_win *);
 #ifdef SWM_DEBUG
 void    focusin(xcb_focus_in_event_t *);
+void    focusout(xcb_focus_out_event_t *);
 #endif
+void    focus_flush(void);
+void    focus_win(struct ws_win *);
+void    fontset_init(void);
+void    free_window(struct ws_win *);
 xcb_atom_t get_atom_from_string(const char *);
 #ifdef SWM_DEBUG
 char   *get_atom_name(xcb_atom_t);
+#endif
+struct ws_win   *get_focus_magic(struct ws_win *);
+struct ws_win   *get_focus_prev(struct ws_win *);
+#ifdef SWM_DEBUG
 char   *get_notify_detail_label(uint8_t);
 char   *get_notify_mode_label(uint8_t);
 #endif
 struct ws_win  *get_pointer_win(xcb_window_t);
 struct ws_win  *get_region_focus(struct swm_region *);
 xcb_screen_t   *get_screen(int);
+#ifdef SWM_DEBUG
+char   *get_stack_mode_name(uint8_t);
+#endif
+int32_t         get_swm_iconic(struct ws_win *);
 char   *get_win_name(xcb_window_t);
+int     get_ws_idx(xcb_window_t);
 uint32_t getstate(xcb_window_t);
 void    grabbuttons(struct ws_win *);
+void    grabkeys(void);
+void    grab_windows(void);
+void    iconify(struct swm_region *, union arg *);
+int     isxlfd(char *);
 void    keypress(xcb_key_press_event_t *);
+void    kill_refs(struct ws_win *);
 #ifdef SWM_DEBUG
 void    leavenotify(xcb_leave_notify_event_t *);
 #endif
@@ -719,21 +806,137 @@ void      map_window(struct ws_win *);
 void    mapnotify(xcb_map_notify_event_t *);
 void    mappingnotify(xcb_mapping_notify_event_t *);
 void    maprequest(xcb_map_request_event_t *);
+void    move(struct ws_win *, union arg *);
+void    move_step(struct swm_region *, union arg *);
+uint32_t name_to_pixel(const char *);
+void    name_workspace(struct swm_region *, union arg *);
 void    new_region(struct swm_screen *, int, int, int, int);
+int     parsekeys(char *, unsigned int, unsigned int *, KeySym *);
+int     parsequirks(char *, unsigned long *);
 int     parse_rgb(const char *, uint16_t *, uint16_t *, uint16_t *);
+void    pressbutton(struct swm_region *, union arg *);
+void    priorws(struct swm_region *, union arg *);
+void    print_win_geom(xcb_window_t);
 void    propertynotify(xcb_property_notify_event_t *);
-void    spawn_select(struct swm_region *, union arg *, char *, int *);
+void    quirk_insert(const char *, const char *, unsigned long);
+void    quirk_remove(struct quirk *);
+void    quirk_replace(struct quirk *, const char *, const char *,
+            unsigned long);
+void    quit(struct swm_region *, union arg *);
+void    raise_toggle(struct swm_region *, union arg *);
+void    resize(struct ws_win *, union arg *);
+void    resize_step(struct swm_region *, union arg *);
+void    restart(struct swm_region *, union arg *);
+struct swm_region      *root_to_region(xcb_window_t, int);
 void    screenchange(xcb_randr_screen_change_notify_event_t *);
+void    scan_xrandr(int);
+void    search_do_resp(void);
+void    search_resp_name_workspace(const char *, unsigned long);
+void    search_resp_search_window(const char *);
+void    search_resp_search_workspace(const char *);
+void    search_resp_uniconify(const char *, unsigned long);
+void    search_win(struct swm_region *, union arg *);
+void    search_win_cleanup(void);
+void    search_workspace(struct swm_region *, union arg *);
+void    send_to_ws(struct swm_region *, union arg *);
+int     setautorun(char *, char *, int);
+int     setconfbinding(char *, char *, int);
+int     setconfcolor(char *, char *, int);
+int     setconfmodkey(char *, char *, int);
+int     setconfquirk(char *, char *, int);
+int     setconfregion(char *, char *, int);
+int     setconfspawn(char *, char *, int);
+int     setconfvalue(char *, char *, int);
+int     setkeymapping(char *, char *, int);
+int     setlayout(char *, char *, int);
+void    setquirk(const char *, const char *, unsigned long);
+void    setscreencolor(char *, int, int);
+void    setspawn(const char *, const char *);
+void    setup_ewmh(void);
+void    setup_globals(void);
+void    setup_keys(void);
+void    setup_quirks(void);
+void    setup_screens(void);
+void    setup_spawn(void);
+void    set_child_transient(struct ws_win *, xcb_window_t *);
+void    set_swm_iconic(struct ws_win *, int);
+void    set_win_state(struct ws_win *, uint16_t);
 void    shutdown_cleanup(void);
+void    sighdlr(int);
+void    socket_setnonblock(int);
+void    sort_windows(struct ws_win_list *);
+void    spawn(int, union arg *, int);
+void    spawn_custom(struct swm_region *, union arg *, const char *);
+int     spawn_expand(struct swm_region *, union arg *, const char *, char ***);
+void    spawn_insert(const char *, const char *);
+void    spawn_select(struct swm_region *, union arg *, const char *, int *);
+void    stack_config(struct swm_region *, union arg *);
+void    stack_floater(struct ws_win *, struct swm_region *);
+void    stack_master(struct workspace *, struct swm_geometry *, int, int);
 void    store_float_geom(struct ws_win *, struct swm_region *);
+char *  strdupsafe(const char *);
+void    swapwin(struct swm_region *, union arg *);
+void    switchws(struct swm_region *, union arg *);
+void    teardown_ewmh(void);
+void    unfocus_win(struct ws_win *);
+void    uniconify(struct swm_region *, union arg *);
 void    unmanage_window(struct ws_win *);
 void    unmapnotify(xcb_unmap_notify_event_t *);
-void    unfocus_win(struct ws_win *);
+void    unmap_all(void);
+void    unmap_window(struct ws_win *);
+void    updatenumlockmask(void);
+void    update_modkey(unsigned int);
 void    update_window(struct ws_win *);
+int     validate_win(struct ws_win *);
+int     validate_ws(struct workspace *);
 /*void  visibilitynotify(xcb_visibility_notify_event_t *);*/
+void    version(struct swm_region *, union arg *);
+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
+cursors_load(void)
+{
+       xcb_font_t      cf = XCB_NONE;
+       int             i;
+
+       for (i = 0; i < LENGTH(cursors); ++i) {
+               /* try to load Xcursor first. */
+               cursors[i].cid = XcursorLibraryLoadCursor(display,
+                   cursors[i].name);
+
+               /* fallback to cursorfont. */
+               if (cursors[i].cid == XCB_CURSOR_NONE) {
+                       if (cf == XCB_NONE) {
+                               cf = xcb_generate_id(conn);
+                               xcb_open_font(conn, cf, strlen("cursor"),
+                                   "cursor");
+                       }
+
+                       cursors[i].cid = xcb_generate_id(conn);
+                       xcb_create_glyph_cursor(conn, cursors[i].cid, cf, cf,
+                           cursors[i].cf_char, cursors[i].cf_char + 1, 0, 0, 0,
+                           0xffff, 0xffff, 0xffff);
+
+               }
+       }
+
+       if (cf != XCB_NONE)
+               xcb_close_font(conn, cf);
+}
+
+void
+cursors_cleanup(void)
+{
+       int     i;
+       for (i = 0; i < LENGTH(cursors); ++i)
+               xcb_free_cursor(conn, cursors[i].cid);
+}
 
 char *
-expand_tilde(char *s)
+expand_tilde(const char *s)
 {
        struct passwd           *ppwd;
        int                     i, max;
@@ -763,6 +966,8 @@ expand_tilde(char *s)
        s = &s[i];
 
        ppwd = strlen(user) == 0 ? getpwuid(getuid()) : getpwnam(user);
+       free(user);
+
        if (ppwd == NULL)
                result = strdup(sc);
        else
@@ -1983,7 +2188,7 @@ isxlfd(char *s)
 }
 
 void
-fontset_init()
+fontset_init(void)
 {
        char                    *default_string;
        char                    **missing_charsets;
@@ -4171,7 +4376,7 @@ get_win_name(xcb_window_t win)
                    xcb_get_property_value_length(r));
 
        free(r);
-       return name;
+       return (name);
 }
 
 void
@@ -4396,7 +4601,7 @@ search_win(struct swm_region *r, union arg *args)
 }
 
 void
-search_resp_uniconify(char *resp, unsigned long len)
+search_resp_uniconify(const char *resp, unsigned long len)
 {
        char                    *name;
        struct ws_win           *win;
@@ -4426,7 +4631,7 @@ search_resp_uniconify(char *resp, unsigned long len)
 }
 
 void
-search_resp_name_workspace(char *resp, unsigned long len)
+search_resp_name_workspace(const char *resp, unsigned long len)
 {
        struct workspace        *ws;
 
@@ -4452,7 +4657,7 @@ search_resp_name_workspace(char *resp, unsigned long len)
 }
 
 void
-search_resp_search_workspace(char *resp)
+search_resp_search_workspace(const char *resp)
 {
        char                    *p, *q;
        int                     ws_idx;
@@ -4483,7 +4688,7 @@ search_resp_search_workspace(char *resp)
 }
 
 void
-search_resp_search_window(char *resp)
+search_resp_search_window(const char *resp)
 {
        char                    *s;
        int                     idx;
@@ -4721,9 +4926,7 @@ resize(struct ws_win *win, union arg *args)
        struct swm_geometry     g;
        int                     top = 0, left = 0, resizing;
        int                     dx, dy;
-       unsigned int            shape; /* cursor style */
-       xcb_cursor_t            cursor;
-       xcb_font_t              cursor_font;
+       xcb_cursor_t                    cursor;
        xcb_query_pointer_reply_t       *xpr;
        xcb_generic_event_t             *evt;
        xcb_motion_notify_event_t       *mne;
@@ -4796,18 +4999,13 @@ resize(struct ws_win *win, union arg *args)
                top = 1;
 
        if (args->id == SWM_ARG_ID_CENTER)
-               shape = XC_sizing;
+               cursor = cursors[XC_SIZING].cid;
        else if (top)
-               shape = (left) ? XC_top_left_corner : XC_top_right_corner;
+               cursor = cursors[left ? XC_TOP_LEFT_CORNER :
+                   XC_TOP_RIGHT_CORNER].cid;
        else
-               shape = (left) ? XC_bottom_left_corner : XC_bottom_right_corner;
-
-       cursor_font = xcb_generate_id(conn);
-       xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor");
-
-       cursor = xcb_generate_id(conn);
-       xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font,
-           shape, shape + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff);
+               cursor = cursors[left ? XC_BOTTOM_LEFT_CORNER :
+                   XC_BOTTOM_RIGHT_CORNER].cid;
 
        xcb_grab_pointer(conn, 0, win->id, MOUSEMASK,
            XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_WINDOW_NONE, cursor,
@@ -4889,8 +5087,6 @@ resize(struct ws_win *win, union arg *args)
        store_float_geom(win,r);
 
        xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
-       xcb_free_cursor(conn, cursor);
-       xcb_close_font(conn, cursor_font);
        free(xpr);
        DNPRINTF(SWM_D_EVENT, "resize: done.\n");
 }
@@ -4917,8 +5113,6 @@ move(struct ws_win *win, union arg *args)
        xcb_timestamp_t         timestamp = 0;
        int                     move_step = 0, moving;
        struct swm_region       *r = NULL;
-       xcb_font_t                      cursor_font;
-       xcb_cursor_t                    cursor;
        xcb_query_pointer_reply_t       *qpr;
        xcb_generic_event_t             *evt;
        xcb_motion_notify_event_t       *mne;
@@ -4978,24 +5172,15 @@ move(struct ws_win *win, union arg *args)
                return;
        }
 
-       cursor_font = xcb_generate_id(conn);
-       xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor");
-
-       cursor = xcb_generate_id(conn);
-       xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font,
-               XC_fleur, XC_fleur + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff);
-
        xcb_grab_pointer(conn, 0, win->id, MOUSEMASK,
            XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
-           XCB_WINDOW_NONE, cursor, XCB_CURRENT_TIME);
+           XCB_WINDOW_NONE, cursors[XC_FLEUR].cid, XCB_CURRENT_TIME);
 
        /* get cursor offset from window root */
        qpr = xcb_query_pointer_reply(conn, xcb_query_pointer(conn, win->id),
                NULL);
        if (!qpr) {
                xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
-               xcb_free_cursor(conn, cursor);
-               xcb_close_font(conn, cursor_font);
                return;
        }
 
@@ -5033,8 +5218,6 @@ move(struct ws_win *win, union arg *args)
        }
        store_float_geom(win, r);
        free(qpr);
-       xcb_free_cursor(conn, cursor);
-       xcb_close_font(conn, cursor_font);
        xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
        DNPRINTF(SWM_D_EVENT, "move: done.\n");
 }
@@ -5326,7 +5509,7 @@ TAILQ_HEAD(spawn_list, spawn_prog);
 struct spawn_list              spawns = TAILQ_HEAD_INITIALIZER(spawns);
 
 int
-spawn_expand(struct swm_region *r, union arg *args, char *spawn_name,
+spawn_expand(struct swm_region *r, union arg *args, const char *spawn_name,
     char ***ret_args)
 {
        struct spawn_prog       *prog = NULL;
@@ -5405,7 +5588,7 @@ spawn_expand(struct swm_region *r, union arg *args, char *spawn_name,
 }
 
 void
-spawn_custom(struct swm_region *r, union arg *args, char *spawn_name)
+spawn_custom(struct swm_region *r, union arg *args, const char *spawn_name)
 {
        union arg               a;
        char                    **real_args;
@@ -5423,7 +5606,8 @@ spawn_custom(struct swm_region *r, union arg *args, char *spawn_name)
 }
 
 void
-spawn_select(struct swm_region *r, union arg *args, char *spawn_name, int *pid)
+spawn_select(struct swm_region *r, union arg *args, const char *spawn_name,
+    int *pid)
 {
        union arg               a;
        char                    **real_args;
@@ -5465,7 +5649,7 @@ spawn_select(struct swm_region *r, union arg *args, char *spawn_name, int *pid)
 }
 
 void
-spawn_insert(char *name, char *args)
+spawn_insert(const char *name, const char *args)
 {
        char                    *arg, *cp, *ptr;
        struct spawn_prog       *sp;
@@ -5516,7 +5700,7 @@ spawn_remove(struct spawn_prog *sp)
 }
 
 void
-spawn_replace(struct spawn_prog *sp, char *name, char *args)
+spawn_replace(struct spawn_prog *sp, const char *name, const char *args)
 {
        DNPRINTF(SWM_D_SPAWN, "spawn_replace: %s [%s]\n", sp->name, name);
 
@@ -5527,7 +5711,7 @@ spawn_replace(struct spawn_prog *sp, char *name, char *args)
 }
 
 void
-setspawn(char *name, char *args)
+setspawn(const char *name, const char *args)
 {
        struct spawn_prog       *sp;
 
@@ -5659,7 +5843,7 @@ parsekeys(char *keystr, unsigned int currmod, unsigned int *mod, KeySym *ks)
 }
 
 char *
-strdupsafe(char *str)
+strdupsafe(const char *str)
 {
        if (str == NULL)
                return (NULL);
@@ -5668,7 +5852,8 @@ strdupsafe(char *str)
 }
 
 void
-key_insert(unsigned int mod, KeySym ks, enum keyfuncid kfid, char *spawn_name)
+key_insert(unsigned int mod, KeySym ks, enum keyfuncid kfid,
+    const char *spawn_name)
 {
        struct key              *kp;
 
@@ -5712,7 +5897,7 @@ key_remove(struct key *kp)
 
 void
 key_replace(struct key *kp, unsigned int mod, KeySym ks, enum keyfuncid kfid,
-    char *spawn_name)
+    const char *spawn_name)
 {
        DNPRINTF(SWM_D_KEY, "key_replace: %s [%s]\n", keyfuncs[kp->funcid].name,
            spawn_name);
@@ -5725,7 +5910,7 @@ key_replace(struct key *kp, unsigned int mod, KeySym ks, enum keyfuncid kfid,
 
 void
 setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid,
-    char *spawn_name)
+    const char *spawn_name)
 {
        struct key              *kp;
 
@@ -6127,6 +6312,7 @@ setquirk(const char *class, const char *name, unsigned long quirk)
        DNPRINTF(SWM_D_QUIRK, "setquirk: enter %s:%s [%lu]\n", class, name,
           quirk);
 
+       /* Remove/replace existing quirk. */
        TAILQ_FOREACH(qp, &quirks, entry) {
                if (!strcmp(qp->class, class) && !strcmp(qp->name, name)) {
                        if (!quirk)
@@ -6137,12 +6323,11 @@ setquirk(const char *class, const char *name, unsigned long quirk)
                        return;
                }
        }
-       if (!quirk) {
-               warnx("error: setquirk: cannot find class/name combination");
-               return;
-       }
 
-       quirk_insert(class, name, quirk);
+       /* Only insert if quirk is not NONE. */
+       if (quirk)
+               quirk_insert(class, name, quirk);
+
        DNPRINTF(SWM_D_QUIRK, "setquirk: leave\n");
 }
 
@@ -6458,7 +6643,7 @@ setautorun(char *selector, char *value, int flags)
 {
        int                     ws_id;
        char                    s[1024];
-       char                    *ap, *sp = s;
+       char                    *ap, *sp;
        union arg               a;
        int                     argc = 0;
        pid_t                   pid;
@@ -6478,6 +6663,8 @@ setautorun(char *selector, char *value, int flags)
        if (ws_id < 0 || ws_id >= workspace_limit)
                errx(1, "autorun: invalid workspace %d", ws_id + 1);
 
+       sp = expand_tilde((char *)&s);
+
        /*
         * This is a little intricate
         *
@@ -6495,6 +6682,7 @@ setautorun(char *selector, char *value, int flags)
                        err(1, "setautorun: realloc");
                a.argv[argc - 1] = ap;
        }
+       free(sp);
 
        if ((a.argv = realloc(a.argv, (argc + 1) * sizeof(char *))) == NULL)
                err(1, "setautorun: realloc");
@@ -6661,7 +6849,7 @@ struct config_option configopt[] = {
 };
 
 int
-conf_load(char *filename, int keymapping)
+conf_load(const char *filename, int keymapping)
 {
        FILE                    *config;
        char                    *line, *cp, *optsub, *optval;
@@ -8126,6 +8314,8 @@ scan_xrandr(int i)
        xcb_randr_crtc_t                                *crtc;
        xcb_screen_t                                    *screen;
 
+       DNPRINTF(SWM_D_MISC, "scan_xrandr: screen: %d\n", i);
+
        if ((screen = get_screen(i)) == NULL)
                errx(1, "ERROR: can't get screen %d.", i);
 
@@ -8153,7 +8343,7 @@ scan_xrandr(int i)
                        new_region(&screens[i], 0, 0,
                            screen->width_in_pixels,
                            screen->height_in_pixels);
-                       return;
+                       goto out;
                } else
                        ncrtc = srr->num_crtcs;
 
@@ -8179,12 +8369,16 @@ scan_xrandr(int i)
                        free(cir);
                }
                free(srr);
-       } else
+       }
 #endif /* SWM_XRR_HAS_CRTC */
-       {
+
+       /* If detection failed, create a single region that spans the screen. */
+       if (TAILQ_EMPTY(&screens[i].rl))
                new_region(&screens[i], 0, 0, screen->width_in_pixels,
                    screen->height_in_pixels);
-       }
+
+out:
+       DNPRINTF(SWM_D_MISC, "scan_xrandr: done.\n");
 }
 
 void
@@ -8289,7 +8483,6 @@ grab_windows(void)
                                free(r);
                                continue;
                        }
-                       free(r);
 
                        state = getstate(wins[j]);
                        manage = state != XCB_ICCCM_WM_STATE_WITHDRAWN;
@@ -8298,6 +8491,7 @@ grab_windows(void)
                        if (xcb_icccm_get_wm_transient_for_reply(conn, pc,
                            &trans, NULL) && manage)
                                manage_window(wins[j], mapped);
+                       free(r);
                }
                free(qtr);
        }
@@ -8312,8 +8506,6 @@ setup_screens(void)
        uint32_t                gcv[1], wa[1];
        const xcb_query_extension_reply_t *qep;
        xcb_screen_t                            *screen;
-       xcb_cursor_t                            cursor;
-       xcb_font_t                              cursor_font;
        xcb_randr_query_version_cookie_t        c;
        xcb_randr_query_version_reply_t         *r;
 
@@ -8338,13 +8530,7 @@ setup_screens(void)
                }
        }
 
-       cursor_font = xcb_generate_id(conn);
-       xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor");
-
-       cursor = xcb_generate_id(conn);
-       xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font,
-           XC_left_ptr, XC_left_ptr + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff);
-       wa[0] = cursor;
+       wa[0] = cursors[XC_LEFT_PTR].cid;
 
        /* map physical screens */
        for (i = 0; i < num_screens; i++) {
@@ -8401,8 +8587,6 @@ setup_screens(void)
                        xcb_randr_select_input(conn, screens[i].root,
                            XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
        }
-       xcb_free_cursor(conn, cursor);
-       xcb_close_font(conn, cursor_font);
 }
 
 void
@@ -8471,6 +8655,8 @@ shutdown_cleanup(void)
        bar_extra = 1;
        unmap_all();
 
+       cursors_cleanup();
+
        teardown_ewmh();
 
        num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
@@ -8627,6 +8813,9 @@ main(int argc, char *argv[])
        if (enable_wm() != 0)
                errx(1, "another window manager is currently running");
 
+       /* Load Xcursors and/or cursorfont glyph cursors. */
+       cursors_load();
+
        xcb_aux_sync(conn);
 
        setup_globals();