X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=i3bar%2Fsrc%2Fxcb.c;h=7bfeb12e90dd7d8cd20e31e0a8e6accfba0fb745;hb=fe6b3b7474;hp=98f0dcbe02296fdb49ee5af8495d17940871022f;hpb=f6f198c3fed90cfc4672588cf3d6a8c712f06f97;p=i3%2Fi3 diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 98f0dcbe..7bfeb12e 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -79,7 +79,7 @@ int bar_height; /* These are only relevant for XKB, which we only need for grabbing modifiers */ int xkb_base; -int mod_pressed = 0; +bool mod_pressed = 0; /* Event watchers, to interact with the user */ ev_prepare *xcb_prep; @@ -439,6 +439,18 @@ void init_colors(const struct xcb_color_strings_t *new_colors) { xcb_flush(xcb_connection); } +static bool execute_custom_command(xcb_keycode_t input_code, bool event_is_release) { + binding_t *binding; + TAILQ_FOREACH(binding, &(config.bindings), bindings) { + if ((binding->input_code != input_code) || (binding->release != event_is_release)) + continue; + + i3_send_msg(I3_IPC_MESSAGE_TYPE_RUN_COMMAND, binding->command); + return true; + } + return false; +} + /* * Handle a button press event (i.e. a mouse click on one of our bars). * We determine, whether the click occurred on a workspace button or if the scroll- @@ -460,10 +472,16 @@ void handle_button(xcb_button_press_event_t *event) { return; } - int32_t x = event->event_x >= 0 ? event->event_x : 0; - DLOG("Got button %d\n", event->detail); + /* During button release events, only check for custom commands. */ + const bool event_is_release = (event->response_type & ~0x80) == XCB_BUTTON_RELEASE; + if (event_is_release) { + execute_custom_command(event->detail, event_is_release); + return; + } + + int32_t x = event->event_x >= 0 ? event->event_x : 0; int workspace_width = 0; i3_ws *cur_ws = NULL, *clicked_ws = NULL, *ws_walk; @@ -505,7 +523,8 @@ void handle_button(xcb_button_press_event_t *event) { block_x += render->width + render->x_offset + render->x_append + get_sep_offset(block) + sep_offset_remainder; if (statusline_x <= block_x && statusline_x >= last_block_x) { - send_block_clicked(event->detail, block->name, block->instance, event->root_x, event->root_y); + send_block_clicked(event->detail, block->name, block->instance, + event->root_x, event->root_y, statusline_x - last_block_x, event->event_y, block_x - last_block_x, bar_height); return; } @@ -516,12 +535,7 @@ void handle_button(xcb_button_press_event_t *event) { /* If a custom command was specified for this mouse button, it overrides * the default behavior. */ - binding_t *binding; - TAILQ_FOREACH(binding, &(config.bindings), bindings) { - if (binding->input_code != event->detail) - continue; - - i3_send_msg(I3_IPC_MESSAGE_TYPE_RUN_COMMAND, binding->command); + if (execute_custom_command(event->detail, event_is_release)) { return; } @@ -680,21 +694,12 @@ static void handle_client_message(xcb_client_message_event_t *event) { if (event->type == atoms[I3_SYNC]) { xcb_window_t window = event->data.data32[0]; uint32_t rnd = event->data.data32[1]; - DLOG("[i3 sync protocol] Forwarding random value %d, X11 window 0x%08x to i3\n", rnd, window); - - void *reply = scalloc(32, 1); - xcb_client_message_event_t *ev = reply; - - ev->response_type = XCB_CLIENT_MESSAGE; - ev->window = window; - ev->type = atoms[I3_SYNC]; - ev->format = 32; - ev->data.data32[0] = window; - ev->data.data32[1] = rnd; - - xcb_send_event(conn, false, xcb_root, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (char *)ev); - xcb_flush(conn); - free(reply); + /* Forward the request to i3 via the IPC interface so that all pending + * IPC messages are guaranteed to be handled. */ + char *payload = NULL; + sasprintf(&payload, "{\"rnd\":%d, \"window\":%d}", rnd, window); + i3_send_msg(I3_IPC_MESSAGE_TYPE_SYNC, payload); + free(payload); } else if (event->type == atoms[_NET_SYSTEM_TRAY_OPCODE] && event->format == 32) { DLOG("_NET_SYSTEM_TRAY_OPCODE received\n"); @@ -1103,49 +1108,15 @@ void xcb_prep_cb(struct ev_loop *loop, ev_prepare *watcher, int revents) { DLOG("received an xkb event\n"); xcb_xkb_state_notify_event_t *state = (xcb_xkb_state_notify_event_t *)event; + const uint32_t mod = (config.modifier & 0xFFFF); + mod_pressed = (mod != 0 && (state->mods & mod) == mod); if (state->xkbType == XCB_XKB_STATE_NOTIFY && config.modifier != XCB_NONE) { - int modstate = state->mods & config.modifier; - -#define DLOGMOD(modmask, status) \ - do { \ - switch (modmask) { \ - case ShiftMask: \ - DLOG("ShiftMask got " #status "!\n"); \ - break; \ - case ControlMask: \ - DLOG("ControlMask got " #status "!\n"); \ - break; \ - case Mod1Mask: \ - DLOG("Mod1Mask got " #status "!\n"); \ - break; \ - case Mod2Mask: \ - DLOG("Mod2Mask got " #status "!\n"); \ - break; \ - case Mod3Mask: \ - DLOG("Mod3Mask got " #status "!\n"); \ - break; \ - case Mod4Mask: \ - DLOG("Mod4Mask got " #status "!\n"); \ - break; \ - case Mod5Mask: \ - DLOG("Mod5Mask got " #status "!\n"); \ - break; \ - } \ - } while (0) - - if (modstate != mod_pressed) { - if (modstate == 0) { - DLOGMOD(config.modifier, released); - if (!activated_mode) - hide_bars(); - } else { - DLOGMOD(config.modifier, pressed); - activated_mode = false; - unhide_bars(); - } - mod_pressed = modstate; + if (mod_pressed) { + activated_mode = false; + unhide_bars(); + } else if (!activated_mode) { + hide_bars(); } -#undef DLOGMOD } free(event); @@ -1164,6 +1135,7 @@ void xcb_prep_cb(struct ev_loop *loop, ev_prepare *watcher, int revents) { } break; + case XCB_BUTTON_RELEASE: case XCB_BUTTON_PRESS: /* Button press events are mouse buttons clicked on one of our bars */ handle_button((xcb_button_press_event_t *)event); @@ -1499,16 +1471,7 @@ void init_tray_colors(void) { * */ void clean_xcb(void) { - i3_output *o_walk; - free_workspaces(); - SLIST_FOREACH(o_walk, outputs, slist) { - destroy_window(o_walk); - FREE(o_walk->trayclients); - FREE(o_walk->workspaces); - FREE(o_walk->name); - } - FREE_SLIST(outputs, i3_output); - FREE(outputs); + free_outputs(); free_font(); @@ -1687,7 +1650,8 @@ void reconfig_windows(bool redraw_bars) { * */ values[3] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | - XCB_EVENT_MASK_BUTTON_PRESS; + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE; if (config.hide_on_modifier == M_DOCK) { /* If the bar is normally visible, catch visibility change events to suspend * the status process when the bar is obscured by full-screened windows. */