X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=6a62c278dfe24f4e68df1d7efba8d3af979f75cf;hb=f2fa926aa1a0d2f1711671de27b2c4145b2408f9;hp=5559ee576d02637143f65cb58803cd5f2f39c846;hpb=b3ce153db74e7d9a961b0127e6439a79396f29e1;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index 5559ee5..6a62c27 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -245,8 +245,8 @@ u_int32_t swm_debug = 0 #define YESNO(x) ((x) ? "yes" : "no") #define SWM_FOCUS_DEFAULT (0) -#define SWM_FOCUS_SYNERGY (1) -#define SWM_FOCUS_FOLLOW (2) +#define SWM_FOCUS_FOLLOW (1) +#define SWM_FOCUS_MANUAL (2) #define SWM_CONF_DEFAULT (0) #define SWM_CONF_KEYMAPPING (1) @@ -673,7 +673,6 @@ 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_drain(uint8_t); void event_error(xcb_generic_error_t *); @@ -683,7 +682,9 @@ 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_flush(void); struct ws_win *focus_magic(struct ws_win *); +void focus_win(struct ws_win *); #ifdef SWM_DEBUG void focusin(xcb_focus_in_event_t *); #endif @@ -696,11 +697,12 @@ char *get_notify_mode_label(uint8_t); 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 grabbuttons(struct ws_win *); void keypress(xcb_key_press_event_t *); #ifdef SWM_DEBUG void leavenotify(xcb_leave_notify_event_t *); #endif +void load_float_geom(struct ws_win *, struct swm_region *); void map_window_raised(xcb_window_t); void mapnotify(xcb_map_notify_event_t *); void mappingnotify(xcb_mapping_notify_event_t *); @@ -795,17 +797,12 @@ get_screen(int screen) } void -do_sync(void) +focus_flush(void) { - xcb_get_input_focus_cookie_t c; - xcb_get_input_focus_reply_t *r; - - /* mimic XSync() */ - c = xcb_get_input_focus(conn); - xcb_flush(conn); - r = xcb_get_input_focus_reply(conn, c, NULL); - if (r) - free(r); + if (focus_mode == SWM_FOCUS_DEFAULT) + event_drain(XCB_ENTER_NOTIFY); + else + xcb_flush(conn); } void @@ -992,12 +989,7 @@ ewmh_set_win_fullscreen(struct ws_win *win, int fs) win->g = win->ws->r->g; win->bordered = 0; } else { - if (win->g_floatvalid) { - /* refloat at last floating relative position */ - win->g = win->g_float; - X(win) += X(win->ws->r); - Y(win) += Y(win->ws->r); - } + load_float_geom(win, win->ws->r); } return (1); @@ -1924,10 +1916,7 @@ bar_toggle(struct swm_region *r, union arg *args) /* must be after stack */ bar_update(); - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); } void @@ -2672,7 +2661,6 @@ unfocus_win(struct ws_win *win) win->ws->focus_prev = NULL; } - grabbuttons(win, 0); xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL, &win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].pixel); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root, @@ -2725,18 +2713,20 @@ focus_win(struct ws_win *win) cur_focus = r->focus; free(r); } - if ((cfw = find_window(cur_focus)) != NULL) + + cfw = find_window(cur_focus); + + if (cfw == win) { + if (win->ws->focus == win) { + DNPRINTF(SWM_D_FOCUS, "focus_win: already focused; " + "skipping.\n"); + return; + } else { + DNPRINTF(SWM_D_FOCUS, "focus_win: already has input " + "focus.\n"); + } + } else unfocus_win(cfw); - else { -#if 0 - /* use larger hammer since the window was killed somehow */ - TAILQ_FOREACH(cfw, &win->ws->winlist, entry) - if (cfw->ws && cfw->ws->r && cfw->ws->r->s) - xcb_change_window_attributes(conn, cfw->id, - XCB_CW_BORDER_PIXEL, - &cfw->ws->r->s->c[SWM_S_COLOR_UNFOCUS].pixel); -#endif - } win->ws->focus = win; @@ -2753,7 +2743,6 @@ focus_win(struct ws_win *win) if (win->java == 0) xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT, win->id, XCB_CURRENT_TIME); - grabbuttons(win, 1); xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL, &win->ws->r->s->c[SWM_S_COLOR_FOCUS].pixel); @@ -2807,7 +2796,8 @@ event_drain(uint8_t rt) { xcb_generic_event_t *evt; - xcb_flush(conn); + /* ensure all pending requests have been processed before filtering. */ + xcb_aux_sync(conn); while ((evt = xcb_poll_for_event(conn))) { if (XCB_EVENT_RESPONSE_TYPE(evt) != rt) event_handle(evt); @@ -2870,10 +2860,7 @@ switchws(struct swm_region *r, union arg *args) TAILQ_FOREACH(win, &old_ws->winlist, entry) unmap_window(win); - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); DNPRINTF(SWM_D_WS, "switchws: done\n"); } @@ -3083,10 +3070,7 @@ swapwin(struct swm_region *r, union arg *args) stack(); - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); } void @@ -3300,10 +3284,7 @@ cycle_layout(struct swm_region *r, union arg *args) a.id = SWM_ARG_ID_FOCUSCUR; focus(r, &a); - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); } void @@ -3366,6 +3347,9 @@ stack(void) { void store_float_geom(struct ws_win *win, struct swm_region *r) { + if (win == NULL || r == NULL) + return; + /* retain window geom and region geom */ win->g_float = win->g; win->g_float.x -= X(r); @@ -3378,6 +3362,25 @@ store_float_geom(struct ws_win *win, struct swm_region *r) } void +load_float_geom(struct ws_win *win, struct swm_region *r) +{ + if (win == NULL || r == NULL) + return; + + if (win->g_floatvalid) { + win->g = win->g_float; + X(win) += X(r); + Y(win) += Y(r); + DNPRINTF(SWM_D_MISC, "load_float_geom: window: 0x%x, g: (%d,%d)" + "%d x %d\n", win->id, X(win), Y(win), WIDTH(win), + HEIGHT(win)); + } else { + DNPRINTF(SWM_D_MISC, "load_float_geom: window: 0x%x, g_float " + "is not set.\n", win->id); + } +} + +void stack_floater(struct ws_win *win, struct swm_region *r) { if (win == NULL) @@ -3389,12 +3392,10 @@ stack_floater(struct ws_win *win, struct swm_region *r) * to allow windows to change their size (e.g. mplayer fs) only retrieve * geom on ws switches or return from max mode */ - if (win->g_floatvalid && (win->floatmaxed || (r != r->ws->old_r && - !(win->ewmh_flags & EWMH_F_FULLSCREEN)))) { - /* refloat at last floating relative position */ - win->g = win->g_float; - X(win) += X(r); - Y(win) += Y(r); + if (win->floatmaxed || (r != r->ws->old_r && + !(win->ewmh_flags & EWMH_F_FULLSCREEN))) { + /* update geometry for the new region */ + load_float_geom(win, r); } win->floatmaxed = 0; @@ -3406,7 +3407,7 @@ stack_floater(struct ws_win *win, struct swm_region *r) if (!win->g_floatvalid) store_float_geom(win, win->ws->r); - win->g = win->ws->r->g; + win->g = r->g; } /* @@ -3432,13 +3433,16 @@ stack_floater(struct ws_win *win, struct swm_region *r) HEIGHT(win) = (double)HEIGHT(r) * dialog_ratio; } - if (!win->manual) { + if (!win->manual && !(win->ewmh_flags & EWMH_F_FULLSCREEN) && + !(win->quirks & SWM_Q_ANYWHERE)) { /* - * floaters and transients are auto-centred unless moved - * or resized + * floaters and transients are auto-centred unless moved, + * resized or ANYWHERE quirk is set. */ X(win) = X(r) + (WIDTH(r) - WIDTH(win)) / 2 - BORDER(win); Y(win) = Y(r) + (HEIGHT(r) - HEIGHT(win)) / 2 - BORDER(win); + + store_float_geom(win, r); } /* keep window within region bounds */ @@ -3911,10 +3915,7 @@ send_to_ws(struct swm_region *r, union arg *args) stack(); bar_update(); - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); } void @@ -3944,10 +3945,7 @@ raise_toggle(struct swm_region *r, union arg *args) if (r->ws->always_raise == 0) stack(); - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); } void @@ -3968,10 +3966,7 @@ iconify(struct swm_region *r, union arg *args) a.id = SWM_ARG_ID_FOCUSCUR; focus(r, &a); - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); } char * @@ -4449,13 +4444,7 @@ floating_toggle_win(struct ws_win *win) } win->floating = 0; } else { - if (win->g_floatvalid) { - /* refloat at last floating relative position */ - X(win) = win->g_float.x + X(r); - Y(win) = win->g_float.y + Y(r); - WIDTH(win) = win->g_float.w; - HEIGHT(win) = win->g_float.h; - } + load_float_geom(win, r); win->floating = 1; } @@ -4476,6 +4465,9 @@ floating_toggle(struct swm_region *r, union arg *args) if (win == NULL) return; + if (win->ewmh_flags & EWMH_F_FULLSCREEN) + return; + ewmh_update_win_state(win, ewmh[_NET_WM_STATE_ABOVE].atom, _NET_WM_STATE_TOGGLE); @@ -4486,10 +4478,7 @@ floating_toggle(struct swm_region *r, union arg *args) focus(win->ws->r, &a); } - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); } void @@ -4595,10 +4584,7 @@ resize(struct ws_win *win, union arg *args) stack(); - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); switch (args->id) { case SWM_ARG_ID_WIDTHSHRINK: @@ -4718,8 +4704,8 @@ resize(struct ws_win *win, union arg *args) /* not free, don't sync more than 120 times / second */ if ((mne->time - timestamp) > (1000 / 120) ) { timestamp = mne->time; - do_sync(); update_window(win); + xcb_flush(conn); } break; default: @@ -4729,8 +4715,8 @@ resize(struct ws_win *win, union arg *args) free(evt); } if (timestamp) { - do_sync(); update_window(win); + xcb_flush(conn); } store_float_geom(win,r); @@ -4793,10 +4779,7 @@ move(struct ws_win *win, union arg *args) stack(); - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); move_step = 0; switch (args->id) { @@ -4865,8 +4848,8 @@ move(struct ws_win *win, union arg *args) /* not free, don't sync more than 120 times / second */ if ((mne->time - timestamp) > (1000 / 120) ) { timestamp = mne->time; - do_sync(); update_window(win); + xcb_flush(conn); } break; default: @@ -4876,8 +4859,8 @@ move(struct ws_win *win, union arg *args) free(evt); } if (timestamp) { - do_sync(); update_window(win); + xcb_flush(conn); } store_float_geom(win, r); free(qpr); @@ -5857,27 +5840,28 @@ grabkeys(void) } void -grabbuttons(struct ws_win *win, int focused) +grabbuttons(struct ws_win *win) { +#if 0 int i; +#endif + + DNPRINTF(SWM_D_MOUSE, "grabbuttons: win 0x%x\n", win->id); +#if 0 xcb_ungrab_button(conn, XCB_BUTTON_INDEX_ANY, win->id, XCB_BUTTON_MASK_ANY); - if (focused) { - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].action == client_click) - xcb_grab_button(conn, 0, win->id, - BUTTONMASK, - XCB_GRAB_MODE_ASYNC, - XCB_GRAB_MODE_SYNC, - XCB_WINDOW_NONE, - XCB_CURSOR_NONE, - buttons[i].button, - buttons[i].mask); - } else - xcb_grab_button(conn, 0, win->id, BUTTONMASK, - XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_WINDOW_NONE, - XCB_CURSOR_NONE, XCB_BUTTON_INDEX_ANY, XCB_BUTTON_MASK_ANY); + + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].action == client_click) + xcb_grab_button(conn, 0, win->id, BUTTONMASK, + XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, + XCB_WINDOW_NONE, XCB_CURSOR_NONE, + buttons[i].button, buttons[i].mask); +#endif + xcb_grab_button(conn, 0, win->id, BUTTONMASK, XCB_GRAB_MODE_SYNC, + XCB_GRAB_MODE_ASYNC, XCB_WINDOW_NONE, XCB_CURSOR_NONE, + XCB_BUTTON_INDEX_ANY, XCB_BUTTON_MASK_ANY); } const char *quirkname[] = { @@ -6202,8 +6186,8 @@ setconfvalue(char *selector, char *value, int flags) focus_mode = SWM_FOCUS_DEFAULT; else if (!strcmp(value, "follow_cursor")) focus_mode = SWM_FOCUS_FOLLOW; - else if (!strcmp(value, "synergy")) - focus_mode = SWM_FOCUS_SYNERGY; + else if (!strcmp(value, "manual")) + focus_mode = SWM_FOCUS_MANUAL; else errx(1, "focus_mode"); break; @@ -6457,10 +6441,7 @@ setlayout(char *selector, char *value, int flags) } } - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); return (0); } @@ -6812,11 +6793,12 @@ manage_window(xcb_window_t id) X(win) = win->wa->x + win->wa->border_width; Y(win) = win->wa->y + win->wa->border_width; win->bordered = 0; - win->g_floatvalid = 0; win->floatmaxed = 0; win->ewmh_flags = 0; win->s = r->s; /* this never changes */ + store_float_geom(win, r); + /* Get WM_SIZE_HINTS. */ xcb_icccm_get_wm_normal_hints_reply(conn, xcb_icccm_get_wm_normal_hints(conn, win->id), @@ -6891,6 +6873,8 @@ manage_window(xcb_window_t id) /* java is retarded so treat it special */ if (strstr(win->ch.instance_name, "sun-awt")) { + DNPRINTF(SWM_D_CLASS, "manage_window: java window " + "detected.\n"); win->java = 1; border_me = 1; } @@ -6923,16 +6907,16 @@ manage_window(xcb_window_t id) fake_keypress(win, XK_KP_Add, XCB_MOD_MASK_SHIFT); } - /* Make sure window is positioned inside its region, if its active. */ - if (win->ws->r) - constrain_window(win, win->ws->r, 0); - if (border_me) { win->bordered = 1; X(win) -= border_width; Y(win) -= border_width; } + /* Make sure window is positioned inside its region, if its active. */ + if (win->ws->r) + constrain_window(win, win->ws->r, 0); + if (win->ws->r || border_me) update_window(win); @@ -6943,7 +6927,8 @@ manage_window(xcb_window_t id) event_mask |= XCB_EVENT_MASK_LEAVE_WINDOW; #endif - xcb_change_window_attributes(conn, id, XCB_CW_EVENT_MASK, &event_mask); + xcb_change_window_attributes(conn, win->id, XCB_CW_EVENT_MASK, + &event_mask); out: /* Figure out where to stack the window in the workspace. */ @@ -6970,6 +6955,8 @@ out: /* Set initial _NET_WM_ALLOWED_ACTIONS */ ewmh_update_actions(win); + grabbuttons(win); + DNPRINTF(SWM_D_MISC, "manage_window: done. window: 0x%x, (x,y) w x h: " "(%d,%d) %d x %d, ws: %d, iconic: %s, transient: 0x%x\n", win->id, X(win), Y(win), WIDTH(win), HEIGHT(win), win->ws->idx, @@ -7083,7 +7070,7 @@ buttonpress(xcb_button_press_event_t *e) { struct ws_win *win; int i; - unsigned int action; + int handled = 0; DNPRINTF(SWM_D_EVENT, "buttonpress: window 0x%x, detail: %u\n", e->event, e->detail); @@ -7092,13 +7079,19 @@ buttonpress(xcb_button_press_event_t *e) return; focus_win(focus_magic(win)); - action = client_click; for (i = 0; i < LENGTH(buttons); i++) - if (action == buttons[i].action && buttons[i].func && + if (client_click == buttons[i].action && buttons[i].func && buttons[i].button == e->detail && - CLEANMASK(buttons[i].mask) == CLEANMASK(e->state)) + CLEANMASK(buttons[i].mask) == CLEANMASK(e->state)) { buttons[i].func(win, &buttons[i].args); + handled = 1; + } + + if (!handled) { + DNPRINTF(SWM_D_EVENT, "buttonpress: passing to window\n"); + xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, e->time); + } xcb_flush(conn); } @@ -7160,6 +7153,7 @@ void configurerequest(xcb_configure_request_event_t *e) { struct ws_win *win; + struct swm_region *r = NULL; int new = 0, i = 0; uint16_t mask = 0; uint32_t wc[7] = {0}; @@ -7167,6 +7161,7 @@ configurerequest(xcb_configure_request_event_t *e) if ((win = find_window(e->window)) == NULL) if ((win = find_unmanaged_window(e->window)) == NULL) new = 1; + #ifdef SWM_DEBUG if (swm_debug & SWM_D_EVENT) { print_win_geom(e->window); @@ -7227,20 +7222,24 @@ configurerequest(xcb_configure_request_event_t *e) xcb_configure_window(conn, e->window, mask, wc); } else if ((!win->manual || win->quirks & SWM_Q_ANYWHERE) && !(win->ewmh_flags & EWMH_F_FULLSCREEN)) { - if (e->value_mask & XCB_CONFIG_WINDOW_X) { - win->g_float.x = e->x; - if (win->ws->r) - win->g_float.x -= X(win->ws->r); - else if (win->ws->old_r) - win->g_float.x -= X(win->ws->old_r); - } + if (win->ws->r) + r = win->ws->r; + else if (win->ws->old_r) + r = win->ws->old_r; + + /* windows are centered unless ANYWHERE quirk is set. */ + if (win->quirks & SWM_Q_ANYWHERE) { + if (e->value_mask & XCB_CONFIG_WINDOW_X) { + win->g_float.x = e->x; + if (r) + win->g_float.x -= X(r); + } - if (e->value_mask & XCB_CONFIG_WINDOW_Y) { - win->g_float.y = e->y; - if (win->ws->r) - win->g_float.y -= Y(win->ws->r); - else if (win->ws->old_r) - win->g_float.y -= Y(win->ws->old_r); + if (e->value_mask & XCB_CONFIG_WINDOW_Y) { + win->g_float.y = e->y; + if (r) + win->g_float.y -= Y(r); + } } if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) @@ -7251,21 +7250,21 @@ configurerequest(xcb_configure_request_event_t *e) win->g_floatvalid = 1; - if (win->floating && win->ws->r) { - /* window is visible and floating; update position. */ - win->g = win->g_float; - X(win) += X(win->ws->r); - Y(win) += Y(win->ws->r); + if (win->floating && r) { + WIDTH(win) = win->g_float.w; + HEIGHT(win) = win->g_float.h; - update_window(win); + stack_floater(win, win->ws->r); + + focus_flush(); } else { config_win(win, e); + xcb_flush(conn); } } else { config_win(win, e); + xcb_flush(conn); } - - xcb_flush(conn); } void @@ -7311,10 +7310,7 @@ destroynotify(xcb_destroy_notify_event_t *e) stack(); - if (focus_mode == SWM_FOCUS_DEFAULT) - event_drain(XCB_ENTER_NOTIFY); - else - xcb_flush(conn); + focus_flush(); } #ifdef SWM_DEBUG @@ -7385,31 +7381,21 @@ void enternotify(xcb_enter_notify_event_t *e) { struct ws_win *win; + 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 0 - if (e->mode != XCB_NOTIFY_MODE_NORMAL) { - DNPRINTF(SWM_D_EVENT, "skip enternotify: generated by " - "cursor grab.\n"); + if (focus_mode == SWM_FOCUS_MANUAL && + e->mode == XCB_NOTIFY_MODE_NORMAL) { + DNPRINTF(SWM_D_EVENT, "enternotify: manual focus; ignoring.\n"); return; } -#endif - - switch (focus_mode) { - case SWM_FOCUS_DEFAULT: - break; - case SWM_FOCUS_FOLLOW: - break; - case SWM_FOCUS_SYNERGY: - break; - } if ((win = find_window(e->event)) == NULL) { - DNPRINTF(SWM_D_EVENT, "skip enternotify: window is NULL\n"); + DNPRINTF(SWM_D_EVENT, "enternotify: window is NULL; ignoring\n"); return; }