Feature: mouse bindings over container decorations
Patch status: superseded
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 container decorations. This behavior overrides the default button press action. The clicked container will be selected by criteria.
To apply this patch, use:
curl http://cr.i3wm.org/patch/564/raw.patch | git am
b/include/bindings.h
20 |
@@ -61,9 +61,10 @@ void switch_mode(const char *new_mode); |
21 |
void check_for_duplicate_bindings(struct context *context); |
22 |
|
23 |
/** |
24 |
- * Runs the given binding and handles parse errors. Returns a CommandResult for |
25 |
- * running the binding's command. Caller should render tree if |
26 |
- * needs_tree_render is true. Free with command_result_free(). |
27 |
+ * Runs the given binding and handles parse errors. If con is passed, it will |
28 |
+ * execute the command binding with that container selected by criteria. |
29 |
+ * Returns a CommandResult for running the binding's command. Caller should |
30 |
+ * render tree if needs_tree_render is true. Free with command_result_free(). |
31 |
* |
32 |
*/ |
33 |
-CommandResult *run_binding(Binding *bind); |
34 |
+CommandResult *run_binding(Binding *bind, Con *con); |
b/src/bindings.c
39 |
@@ -383,18 +383,25 @@ void check_for_duplicate_bindings(struct context *context) { |
40 |
} |
41 |
|
42 |
/* |
43 |
- * Runs the given binding and handles parse errors. Returns a CommandResult for |
44 |
- * running the binding's command. Caller should render tree if |
45 |
- * needs_tree_render is true. Free with command_result_free(). |
46 |
+ * Runs the given binding and handles parse errors. If con is passed, it will |
47 |
+ * execute the command binding with that container selected by criteria. |
48 |
+ * Returns a CommandResult for running the binding's command. Caller should |
49 |
+ * render tree if needs_tree_render is true. Free with command_result_free(). |
50 |
* |
51 |
*/ |
52 |
-CommandResult *run_binding(Binding *bind) { |
53 |
+CommandResult *run_binding(Binding *bind, Con *con) { |
54 |
+ char *command; |
55 |
+ |
56 |
/* We need to copy the command since “reload” may be part of the command, |
57 |
* and then the memory that bind->command points to may not contain the |
58 |
* same data anymore. */ |
59 |
- char *command_copy = sstrdup(bind->command); |
60 |
- CommandResult *result = parse_command(command_copy, NULL); |
61 |
- free(command_copy); |
62 |
+ if (con == NULL) |
63 |
+ command = sstrdup(bind->command); |
64 |
+ else |
65 |
+ sasprintf(&command, "[con_id=\"%d\"] %s", con, bind->command); |
66 |
+ |
67 |
+ CommandResult *result = parse_command(command, NULL); |
68 |
+ free(command); |
69 |
|
70 |
if (result->needs_tree_render) |
71 |
tree_render(); |
b/src/click.c
76 |
@@ -173,11 +173,26 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod |
77 |
|
78 |
/* if focus changes, we must rerender */ |
79 |
Con *initially_focused = focused; |
80 |
+ bool needs_tree_render = false; |
81 |
|
82 |
/* don’t handle dockarea cons, they must not be focused */ |
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) { |
89 |
+ /* TODO: bindings for clicking other parts of the con, like the window |
90 |
+ * area. */ |
91 |
+ Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); |
92 |
+ if (bind) { |
93 |
+ CommandResult *result = run_binding(bind, con); |
94 |
+ needs_tree_render = (needs_tree_render || result->needs_tree_render); |
95 |
+ command_result_free(result); |
96 |
+ goto done; |
97 |
+ } |
98 |
+ } |
99 |
+ |
100 |
/* Any click in a workspace should focus that workspace. If the |
101 |
* workspace is on another output we need to do a workspace_show in |
102 |
* order for i3bar (and others) to notice the change in workspace. */ |
103 |
@@ -301,7 +316,7 @@ done: |
104 |
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time); |
105 |
xcb_flush(conn); |
106 |
|
107 |
- if (initially_focused != focused) |
108 |
+ if (needs_tree_render || initially_focused != focused) |
109 |
tree_render(); |
110 |
|
111 |
return 0; |
b/src/key_press.c
116 |
@@ -30,7 +30,7 @@ void handle_key_press(xcb_key_press_event_t *event) { |
117 |
if (bind == NULL) |
118 |
return; |
119 |
|
120 |
- CommandResult *result = run_binding(bind); |
121 |
+ CommandResult *result = run_binding(bind, NULL); |
122 |
|
123 |
if (result->needs_tree_render) |
124 |
tree_render(); |