]> git.sur5r.net Git - i3/i3/blobdiff - i3bar/src/xcb.c
Add relative coordinates in JSON for i3bar click events (fixes #2767)
[i3/i3] / i3bar / src / xcb.c
index 98f0dcbe02296fdb49ee5af8495d17940871022f..542c86c3c645a4c117d15f22775d73fb900476f6 100644 (file)
@@ -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;
     }
 
@@ -1164,6 +1178,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 +1514,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 +1693,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.  */