X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=3b240f1052965fbd9531e37a1eb69ee0c1726f45;hb=1fa17c86c27db076578a215f9393663c083644cd;hp=8e94b163a7cd0d553f6bea8c4917f2399abd4a60;hpb=13f103ac8c4b74ea05658a6a71d03d98b22a7253;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index 8e94b16..3b240f1 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -648,29 +648,98 @@ struct ewmh_hint { }; /* function prototypes */ +void buttonpress(xcb_button_press_event_t *); +void check_conn(void); +void clientmessage(xcb_client_message_event_t *); int conf_load(char *, int); +void configurenotify(xcb_configure_notify_event_t *); +void configurerequest(xcb_configure_request_event_t *); void constrain_window(struct ws_win *, struct swm_region *, int); +void destroynotify(xcb_destroy_notify_event_t *); 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 *); void focus(struct swm_region *, union arg *); void focus_magic(struct ws_win *); +#ifdef SWM_DEBUG +void focusin(xcb_focus_in_event_t *); +#endif xcb_atom_t get_atom_from_string(const char *); +#ifdef SWM_DEBUG +char *get_atom_name(xcb_atom_t); +char *get_notify_detail_label(uint8_t); +char *get_notify_mode_label(uint8_t); +#endif xcb_screen_t *get_screen(int); char *get_win_name(xcb_window_t); uint32_t getstate(xcb_window_t); void grabbuttons(struct ws_win *, int); +void keypress(xcb_key_press_event_t *); +#ifdef SWM_DEBUG +void leavenotify(xcb_leave_notify_event_t *); +#endif void map_window_raised(xcb_window_t); +void mapnotify(xcb_map_notify_event_t *); +void mappingnotify(xcb_mapping_notify_event_t *); +void maprequest(xcb_map_request_event_t *); void new_region(struct swm_screen *, int, int, int, int); int parse_rgb(const char *, uint16_t *, uint16_t *, uint16_t *); +void propertynotify(xcb_property_notify_event_t *); void spawn_select(struct swm_region *, union arg *, char *, int *); +void screenchange(xcb_randr_screen_change_notify_event_t *); void store_float_geom(struct ws_win *, struct swm_region *); void unmanage_window(struct ws_win *); +void unmapnotify(xcb_unmap_notify_event_t *); void update_window(struct ws_win *); -#ifdef SWM_DEBUG -char *get_atom_name(xcb_atom_t); -#endif +/*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) @@ -690,12 +759,18 @@ parse_rgb(const char *rgb, uint16_t *rr, uint16_t *gg, uint16_t *bb) xcb_screen_t * get_screen(int screen) { - xcb_screen_iterator_t i; + const xcb_setup_t *r; + xcb_screen_iterator_t iter; + + if ((r = xcb_get_setup(conn)) == NULL) { + DNPRINTF(SWM_D_MISC, "get_screen: xcb_get_setup\n"); + check_conn(); + } - i = xcb_setup_roots_iterator(xcb_get_setup(conn)); - for (; i.rem; --screen, xcb_screen_next(&i)) + iter = xcb_setup_roots_iterator(r); + for (; iter.rem; --screen, xcb_screen_next(&iter)) if (screen == 0) - return (i.data); + return (iter.data); return (NULL); } @@ -1100,23 +1175,6 @@ dumpwins(struct swm_region *r, union arg *args) } #endif /* SWM_DEBUG */ -void event_error(xcb_generic_error_t *); -void expose(xcb_expose_event_t *); -void keypress(xcb_key_press_event_t *); -void buttonpress(xcb_button_press_event_t *); -void configurerequest(xcb_configure_request_event_t *); -void configurenotify(xcb_configure_notify_event_t *); -void destroynotify(xcb_destroy_notify_event_t *); -void enternotify(xcb_enter_notify_event_t *); -void mapnotify(xcb_map_notify_event_t *); -void mappingnotify(xcb_mapping_notify_event_t *); -void maprequest(xcb_map_request_event_t *); -void propertynotify(xcb_property_notify_event_t *); -void unmapnotify(xcb_unmap_notify_event_t *); -/*void visibilitynotify(xcb_visibility_notify_event_t *);*/ -void clientmessage(xcb_client_message_event_t *); -void screenchange(xcb_randr_screen_change_notify_event_t *); - void sighdlr(int sig) { @@ -1296,7 +1354,9 @@ custom_region(char *val) sidx, num_screens); sidx--; - screen = get_screen(sidx); + if ((screen = get_screen(sidx)) == NULL) + errx(1, "ERROR: can't get screen %d.", sidx); + if (w < 1 || h < 1) errx(1, "region %ux%u+%u+%u too small", w, h, x, y); @@ -1850,10 +1910,13 @@ bar_setup(struct swm_region *r) { char *font, *fontpos, *dup, *search; int count; - xcb_screen_t *screen = get_screen(r->s->idx); + xcb_screen_t *screen; uint32_t wa[3]; XRenderColor color; + if ((screen = get_screen(r->s->idx)) == NULL) + errx(1, "ERROR: can't get screen %d.", r->s->idx); + if (r->bar != NULL) return; @@ -1929,8 +1992,9 @@ bar_setup(struct swm_region *r) xcb_create_pixmap(conn, screen->root_depth, r->bar->buffer, r->bar->id, WIDTH(r->bar), HEIGHT(r->bar)); - xcb_randr_select_input(conn, r->bar->id, - XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE); + if (xrandr_support) + xcb_randr_select_input(conn, r->bar->id, + XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE); if (bar_enabled) map_window_raised(r->bar->id); @@ -5115,12 +5179,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); @@ -5796,7 +5865,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: @@ -6456,7 +6525,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 */ @@ -6622,12 +6690,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); @@ -6684,6 +6747,9 @@ manage_window(xcb_window_t id) event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY; +#ifdef SWM_DEBUG + event_mask |= XCB_EVENT_MASK_LEAVE_WINDOW; +#endif xcb_change_window_attributes(conn, id, XCB_CW_EVENT_MASK, &event_mask); @@ -6707,6 +6773,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 */ @@ -6800,6 +6868,16 @@ expose(xcb_expose_event_t *e) xcb_flush(conn); } +#ifdef SWM_DEBUG +void +focusin(xcb_focus_in_event_t *e) +{ + DNPRINTF(SWM_D_EVENT, "focusin: window: 0x%x, mode: %s(%u), " + "detail: %s(%u)\n", e->event, get_notify_mode_label(e->mode), + e->mode, get_notify_detail_label(e->detail), e->detail); +} +#endif + void keypress(xcb_key_press_event_t *e) { @@ -6990,13 +7068,78 @@ destroynotify(xcb_destroy_notify_event_t *e) free_window(win); } +#ifdef SWM_DEBUG +char * +get_notify_detail_label(uint8_t detail) +{ + char *label; + + switch (detail) { + case XCB_NOTIFY_DETAIL_ANCESTOR: + label = "Ancestor"; + break; + case XCB_NOTIFY_DETAIL_VIRTUAL: + label = "Virtual"; + break; + case XCB_NOTIFY_DETAIL_INFERIOR: + label = "Inferior"; + break; + case XCB_NOTIFY_DETAIL_NONLINEAR: + label = "Nonlinear"; + break; + case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL: + label = "NonlinearVirtual"; + break; + case XCB_NOTIFY_DETAIL_POINTER: + label = "Pointer"; + break; + case XCB_NOTIFY_DETAIL_POINTER_ROOT: + label = "PointerRoot"; + break; + case XCB_NOTIFY_DETAIL_NONE: + label = "None"; + break; + default: + label = "Unknown"; + } + + return label; +} + +char * +get_notify_mode_label(uint8_t mode) +{ + char *label; + + switch (mode) { + case XCB_NOTIFY_MODE_NORMAL: + label = "Normal"; + break; + case XCB_NOTIFY_MODE_GRAB: + label = "Grab"; + break; + case XCB_NOTIFY_MODE_UNGRAB: + label = "Ungrab"; + break; + case XCB_NOTIFY_MODE_WHILE_GRABBED: + label = "WhileGrabbed"; + break; + default: + label = "Unknown"; + } + + return label; +} +#endif + void enternotify(xcb_enter_notify_event_t *e) { struct ws_win *win; - DNPRINTF(SWM_D_FOCUS, "enternotify: window: 0x%x, mode: %d, detail: " - "%d, root: 0x%x, subwindow: 0x%x, same_screen_focus: %s, " - "state: %d\n", e->event, e->mode, e->detail, e->root, + DNPRINTF(SWM_D_FOCUS, "enternotify: 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), + e->mode, get_notify_detail_label(e->detail), e->detail, e->root, e->child, YESNO(e->same_screen_focus), e->state); if (e->mode != XCB_NOTIFY_MODE_NORMAL) { @@ -7024,6 +7167,18 @@ enternotify(xcb_enter_notify_event_t *e) xcb_flush(conn); } +#ifdef SWM_DEBUG +void +leavenotify(xcb_leave_notify_event_t *e) +{ + 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), + e->mode, get_notify_detail_label(e->detail), e->detail, e->root, + e->child, YESNO(e->same_screen_focus), e->state); +} +#endif + /* lets us use one switch statement for arbitrary mode/detail combinations */ #define MERGE_MEMBERS(a,b) (((a & 0xffff) << 16) | (b & 0xffff)) @@ -7252,6 +7407,45 @@ clientmessage(xcb_client_message_event_t *e) xcb_flush(conn); } +#ifdef XCB_CONN_ERROR +void +check_conn(void) +{ + int err = xcb_connection_has_error(conn); + char *s; + + switch (err) { + case XCB_CONN_ERROR: + s = "Socket error, pipe error or other stream error."; + break; + case XCB_CONN_CLOSED_EXT_NOTSUPPORTED: + s = "Extension not supported."; + break; + case XCB_CONN_CLOSED_MEM_INSUFFICIENT: + s = "Insufficient memory."; + break; + case XCB_CONN_CLOSED_REQ_LEN_EXCEED: + s = "Request length was exceeded."; + break; + case XCB_CONN_CLOSED_PARSE_ERR: + s = "Error parsing display string."; + break; + default: + s = "Unknown error."; + } + + if (err) + errx(err, "X CONNECTION ERROR: %s", s); +} +#else +void +check_conn(void) +{ + if (conn->has_error) + errx(1, "X CONNECTION ERROR"); +} +#endif + int enable_wm(void) { @@ -7264,7 +7458,8 @@ enable_wm(void) /* this causes an error if some other window manager is running */ num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); for (i = 0; i < num_screens; i++) { - sc = get_screen(i); + if ((sc = get_screen(i)) == NULL) + errx(1, "ERROR: can't get screen %d.", i); DNPRINTF(SWM_D_INIT, "enable_wm: screen %d, root: 0x%x\n", i, sc->root); wac = xcb_change_window_attributes_checked(conn, sc->root, @@ -7369,7 +7564,10 @@ scan_xrandr(int i) xcb_randr_get_crtc_info_cookie_t cic; xcb_randr_get_crtc_info_reply_t *cir = NULL; xcb_randr_crtc_t *crtc; - xcb_screen_t *screen = get_screen(i); + xcb_screen_t *screen; + + if ((screen = get_screen(i)) == NULL) + errx(1, "ERROR: can't get screen %d.", i); num_screens = xcb_setup_roots_length(xcb_get_setup(conn)); if (i >= num_screens) @@ -7537,6 +7735,7 @@ setup_screens(void) struct workspace *ws; 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; @@ -7550,15 +7749,18 @@ setup_screens(void) /* initial Xrandr setup */ xrandr_support = 0; - 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; - free(r); - } qep = xcb_get_extension_data(conn, &xcb_randr_id); - xrandr_eventbase = qep->first_event; + if (qep->present) { + 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; + xrandr_eventbase = qep->first_event; + } + free(r); + } + } cursor_font = xcb_generate_id(conn); xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor"); @@ -7574,7 +7776,9 @@ setup_screens(void) screens[i].idx = i; TAILQ_INIT(&screens[i].rl); TAILQ_INIT(&screens[i].orl); - screens[i].root = get_screen(i)->root; + if ((screen = get_screen(i)) == NULL) + errx(1, "ERROR: can't get screen %d.", i); + screens[i].root = screen->root; /* set default colors */ setscreencolor("red", i + 1, SWM_S_COLOR_FOCUS); @@ -7712,14 +7916,18 @@ event_handle(xcb_generic_event_t *evt) EVENT(XCB_DESTROY_NOTIFY, destroynotify); EVENT(XCB_ENTER_NOTIFY, enternotify); EVENT(XCB_EXPOSE, expose); - /*EVENT(XCB_FOCUS_IN, );*/ +#ifdef SWM_DEBUG + EVENT(XCB_FOCUS_IN, focusin); +#endif /*EVENT(XCB_FOCUS_OUT, );*/ /*EVENT(XCB_GRAPHICS_EXPOSURE, );*/ /*EVENT(XCB_GRAVITY_NOTIFY, );*/ EVENT(XCB_KEY_PRESS, keypress); /*EVENT(XCB_KEY_RELEASE, keypress);*/ /*EVENT(XCB_KEYMAP_NOTIFY, );*/ - /*EVENT(XCB_LEAVE_NOTIFY, );*/ +#ifdef SWM_DEBUG + EVENT(XCB_LEAVE_NOTIFY, leavenotify); +#endif EVENT(XCB_MAP_NOTIFY, mapnotify); EVENT(XCB_MAP_REQUEST, maprequest); EVENT(XCB_MAPPING_NOTIFY, mappingnotify);