Feature: implement mouse bindings
Patch status: needinfo
Patch by Tony Crisci
Long description:
A configured mouse binding (for example `bindsym button3 kill`) runs its command when the mouse button is pressed over parts of a container. If the binding has no modifer, it will only run when the button is clicked on the window titlebar. Otherwise if the binding has a modifier, it will run over the titlebar or any part of the contained window. fixes #558
To apply this patch, use:
curl http://cr.i3wm.org/patch/580/raw.patch | git am
b/include/bindings.h
26 |
@@ -61,9 +61,10 @@ void switch_mode(const char *new_mode); |
27 |
void check_for_duplicate_bindings(struct context *context); |
28 |
|
29 |
/** |
30 |
- * Runs the given binding and handles parse errors. Returns a CommandResult for |
31 |
- * running the binding's command. Caller should render tree if |
32 |
- * needs_tree_render is true. Free with command_result_free(). |
33 |
+ * Runs the given binding and handles parse errors. If con is passed, it will |
34 |
+ * execute the command binding with that container selected by criteria. |
35 |
+ * Returns a CommandResult for running the binding's command. Caller should |
36 |
+ * render tree if needs_tree_render is true. Free with command_result_free(). |
37 |
* |
38 |
*/ |
39 |
-CommandResult *run_binding(Binding *bind); |
40 |
+CommandResult *run_binding(Binding *bind, Con *con); |
b/src/bindings.c
45 |
@@ -379,18 +379,25 @@ void check_for_duplicate_bindings(struct context *context) { |
46 |
} |
47 |
|
48 |
/* |
49 |
- * Runs the given binding and handles parse errors. Returns a CommandResult for |
50 |
- * running the binding's command. Caller should render tree if |
51 |
- * needs_tree_render is true. Free with command_result_free(). |
52 |
+ * Runs the given binding and handles parse errors. If con is passed, it will |
53 |
+ * execute the command binding with that container selected by criteria. |
54 |
+ * Returns a CommandResult for running the binding's command. Caller should |
55 |
+ * render tree if needs_tree_render is true. Free with command_result_free(). |
56 |
* |
57 |
*/ |
58 |
-CommandResult *run_binding(Binding *bind) { |
59 |
+CommandResult *run_binding(Binding *bind, Con *con) { |
60 |
+ char *command; |
61 |
+ |
62 |
/* We need to copy the command since “reload” may be part of the command, |
63 |
* and then the memory that bind->command points to may not contain the |
64 |
* same data anymore. */ |
65 |
- char *command_copy = sstrdup(bind->command); |
66 |
- CommandResult *result = parse_command(command_copy, NULL); |
67 |
- free(command_copy); |
68 |
+ if (con == NULL) |
69 |
+ command = sstrdup(bind->command); |
70 |
+ else |
71 |
+ sasprintf(&command, "[con_id=\"%d\"] %s", con, bind->command); |
72 |
+ |
73 |
+ CommandResult *result = parse_command(command, NULL); |
74 |
+ free(command); |
75 |
|
76 |
if (result->needs_tree_render) |
77 |
tree_render(); |
b/src/click.c
82 |
@@ -177,6 +177,29 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod |
83 |
if (con->parent->type == CT_DOCKAREA) |
84 |
goto done; |
85 |
|
86 |
+ /* if the user has bound an action to this click, it should override the |
87 |
+ * default behavior. */ |
88 |
+ if (dest == CLICK_DECORATION || dest == CLICK_INSIDE) { |
89 |
+ Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); |
90 |
+ /* clicks over a window decoration will always trigger the binding and |
91 |
+ * clicks on the inside of the window will only trigger a binding if it |
92 |
+ * has modifiers. */ |
93 |
+ if (bind && (dest == CLICK_DECORATION || (bind->mods && dest == CLICK_INSIDE))) { |
94 |
+ CommandResult *result = run_binding(bind, con); |
95 |
+ |
96 |
+ /* ASYNC_POINTER eats the event */ |
97 |
+ xcb_allow_events(conn, XCB_ALLOW_ASYNC_POINTER, event->time); |
98 |
+ xcb_flush(conn); |
99 |
+ |
100 |
+ if (result->needs_tree_render) |
101 |
+ tree_render(); |
102 |
+ |
103 |
+ command_result_free(result); |
104 |
+ |
105 |
+ return 0; |
106 |
+ } |
107 |
+ } |
108 |
+ |
109 |
/* Any click in a workspace should focus that workspace. If the |
110 |
* workspace is on another output we need to do a workspace_show in |
111 |
* order for i3bar (and others) to notice the change in workspace. */ |
112 |
@@ -300,6 +323,7 @@ done: |
113 |
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time); |
114 |
xcb_flush(conn); |
115 |
tree_render(); |
116 |
+ |
117 |
return 0; |
118 |
} |
119 |
|
b/src/key_press.c
124 |
@@ -30,7 +30,7 @@ void handle_key_press(xcb_key_press_event_t *event) { |
125 |
if (bind == NULL) |
126 |
return; |
127 |
|
128 |
- CommandResult *result = run_binding(bind); |
129 |
+ CommandResult *result = run_binding(bind, NULL); |
130 |
|
131 |
if (result->needs_tree_render) |
132 |
tree_render(); |