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(); |