rofi  1.7.5
keyb.c
Go to the documentation of this file.
1 /*
2  * rofi
3  *
4  * MIT/X11 License
5  * Copyright © 2013-2022 Qball Cow <qball@gmpclient.org>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27 
28 #include <glib.h>
29 #include "nkutils-bindings.h"
30 #include "rofi.h"
31 #include "xrmoptions.h"
32 #include <string.h>
33 
34 typedef struct {
35  guint id;
36  guint scope;
37  char *name;
38  char *binding;
39  char *comment;
41 
46  {.id = PASTE_PRIMARY,
47  .name = "kb-primary-paste",
48  .binding = "Control+V,Shift+Insert",
49  .comment = "Paste primary selection"},
50  {.id = PASTE_SECONDARY,
51  .name = "kb-secondary-paste",
52  .binding = "Control+v,Insert",
53  .comment = "Paste clipboard"},
54  {.id = CLEAR_LINE,
55  .name = "kb-clear-line",
56  .binding = "Control+w",
57  .comment = "Clear input line"},
58  {.id = MOVE_FRONT,
59  .name = "kb-move-front",
60  .binding = "Control+a",
61  .comment = "Beginning of line"},
62  {.id = MOVE_END,
63  .name = "kb-move-end",
64  .binding = "Control+e",
65  .comment = "End of line"},
66  {.id = MOVE_WORD_BACK,
67  .name = "kb-move-word-back",
68  .binding = "Alt+b,Control+Left",
69  .comment = "Move back one word"},
70  {.id = MOVE_WORD_FORWARD,
71  .name = "kb-move-word-forward",
72  .binding = "Alt+f,Control+Right",
73  .comment = "Move forward one word"},
74  {.id = MOVE_CHAR_BACK,
75  .name = "kb-move-char-back",
76  .binding = "Left,Control+b",
77  .comment = "Move back one char"},
78  {.id = MOVE_CHAR_FORWARD,
79  .name = "kb-move-char-forward",
80  .binding = "Right,Control+f",
81  .comment = "Move forward one char"},
82  {.id = REMOVE_WORD_BACK,
83  .name = "kb-remove-word-back",
84  .binding = "Control+Alt+h,Control+BackSpace",
85  .comment = "Delete previous word"},
86  {.id = REMOVE_WORD_FORWARD,
87  .name = "kb-remove-word-forward",
88  .binding = "Control+Alt+d",
89  .comment = "Delete next word"},
90  {.id = REMOVE_CHAR_FORWARD,
91  .name = "kb-remove-char-forward",
92  .binding = "Delete,Control+d",
93  .comment = "Delete next char"},
94  {.id = REMOVE_CHAR_BACK,
95  .name = "kb-remove-char-back",
96  .binding = "BackSpace,Shift+BackSpace,Control+h",
97  .comment = "Delete previous char"},
98  {.id = REMOVE_TO_EOL,
99  .name = "kb-remove-to-eol",
100  .binding = "Control+k",
101  .comment = "Delete till the end of line"},
102  {.id = REMOVE_TO_SOL,
103  .name = "kb-remove-to-sol",
104  .binding = "Control+u",
105  .comment = "Delete till the start of line"},
106  {.id = ACCEPT_ENTRY,
107  .name = "kb-accept-entry",
108  .binding = "Control+j,Control+m,Return,KP_Enter",
109  .comment = "Accept entry"},
110  {.id = ACCEPT_CUSTOM,
111  .name = "kb-accept-custom",
112  .binding = "Control+Return",
113  .comment = "Use entered text as command (in ssh/run modes)"},
114  {.id = ACCEPT_CUSTOM_ALT,
115  .name = "kb-accept-custom-alt",
116  .binding = "Control+Shift+Return",
117  .comment = "Use entered text as command (in ssh/run modes)"},
118  {.id = ACCEPT_ALT,
119  .name = "kb-accept-alt",
120  .binding = "Shift+Return",
121  .comment = "Use alternate accept command."},
122  {.id = DELETE_ENTRY,
123  .name = "kb-delete-entry",
124  .binding = "Shift+Delete",
125  .comment = "Delete entry from history"},
126  {.id = MODE_NEXT,
127  .name = "kb-mode-next",
128  .binding = "Shift+Right,Control+Tab",
129  .comment = "Switch to the next mode."},
130  {.id = MODE_PREVIOUS,
131  .name = "kb-mode-previous",
132  .binding = "Shift+Left,Control+ISO_Left_Tab",
133  .comment = "Switch to the previous mode."},
134  {.id = MODE_COMPLETE,
135  .name = "kb-mode-complete",
136  .binding = "Control+l",
137  .comment = "Start completion for mode."},
138  {.id = ROW_LEFT,
139  .name = "kb-row-left",
140  .binding = "Control+Page_Up",
141  .comment = "Go to the previous column"},
142  {.id = ROW_RIGHT,
143  .name = "kb-row-right",
144  .binding = "Control+Page_Down",
145  .comment = "Go to the next column"},
146  {.id = ROW_UP,
147  .name = "kb-row-up",
148  .binding = "Up,Control+p",
149  .comment = "Select previous entry"},
150  {.id = ROW_DOWN,
151  .name = "kb-row-down",
152  .binding = "Down,Control+n",
153  .comment = "Select next entry"},
154  {.id = ROW_TAB,
155  .name = "kb-row-tab",
156  .binding = "",
157  .comment =
158  "Go to next row, if one left, accept it, if no left next mode."},
159  {.id = ELEMENT_NEXT,
160  .name = "kb-element-next",
161  .binding = "Tab",
162  .comment = "Go to next element (in logical order)."},
163  {.id = ELEMENT_PREV,
164  .name = "kb-element-prev",
165  .binding = "ISO_Left_Tab",
166  .comment = "Go to next previous element (in logical order)."},
167  {.id = PAGE_PREV,
168  .name = "kb-page-prev",
169  .binding = "Page_Up",
170  .comment = "Go to the previous page"},
171  {.id = PAGE_NEXT,
172  .name = "kb-page-next",
173  .binding = "Page_Down",
174  .comment = "Go to the next page"},
175  {.id = ROW_FIRST,
176  .name = "kb-row-first",
177  .binding = "Home,KP_Home",
178  .comment = "Go to the first entry"},
179  {.id = ROW_LAST,
180  .name = "kb-row-last",
181  .binding = "End,KP_End",
182  .comment = "Go to the last entry"},
183  {.id = ROW_SELECT,
184  .name = "kb-row-select",
185  .binding = "Control+space",
186  .comment = "Set selected item as input text"},
187  {.id = SCREENSHOT,
188  .name = "kb-screenshot",
189  .binding = "Alt+S",
190  .comment = "Take a screenshot of the rofi window"},
191  {.id = CHANGE_ELLIPSIZE,
192  .name = "kb-ellipsize",
193  .binding = "Alt+period",
194  .comment = "Toggle between ellipsize modes for displayed data"},
196  .name = "kb-toggle-case-sensitivity",
197  .binding = "grave,dead_grave",
198  .comment = "Toggle case sensitivity"},
199  {.id = TOGGLE_SORT,
200  .name = "kb-toggle-sort",
201  .binding = "Alt+grave",
202  .comment = "Toggle sort"},
203  {.id = CANCEL,
204  .name = "kb-cancel",
205  .binding = "Escape,Control+g,Control+bracketleft",
206  .comment = "Quit rofi"},
207  {.id = CUSTOM_1,
208  .name = "kb-custom-1",
209  .binding = "Alt+1",
210  .comment = "Custom keybinding 1"},
211  {.id = CUSTOM_2,
212  .name = "kb-custom-2",
213  .binding = "Alt+2",
214  .comment = "Custom keybinding 2"},
215  {.id = CUSTOM_3,
216  .name = "kb-custom-3",
217  .binding = "Alt+3",
218  .comment = "Custom keybinding 3"},
219  {.id = CUSTOM_4,
220  .name = "kb-custom-4",
221  .binding = "Alt+4",
222  .comment = "Custom keybinding 4"},
223  {.id = CUSTOM_5,
224  .name = "kb-custom-5",
225  .binding = "Alt+5",
226  .comment = "Custom Keybinding 5"},
227  {.id = CUSTOM_6,
228  .name = "kb-custom-6",
229  .binding = "Alt+6",
230  .comment = "Custom keybinding 6"},
231  {.id = CUSTOM_7,
232  .name = "kb-custom-7",
233  .binding = "Alt+7",
234  .comment = "Custom Keybinding 7"},
235  {.id = CUSTOM_8,
236  .name = "kb-custom-8",
237  .binding = "Alt+8",
238  .comment = "Custom keybinding 8"},
239  {.id = CUSTOM_9,
240  .name = "kb-custom-9",
241  .binding = "Alt+9",
242  .comment = "Custom keybinding 9"},
243  {.id = CUSTOM_10,
244  .name = "kb-custom-10",
245  .binding = "Alt+0",
246  .comment = "Custom keybinding 10"},
247  {.id = CUSTOM_11,
248  .name = "kb-custom-11",
249  .binding = "Alt+exclam",
250  .comment = "Custom keybinding 11"},
251  {.id = CUSTOM_12,
252  .name = "kb-custom-12",
253  .binding = "Alt+at",
254  .comment = "Custom keybinding 12"},
255  {.id = CUSTOM_13,
256  .name = "kb-custom-13",
257  .binding = "Alt+numbersign",
258  .comment = "Custom keybinding 13"},
259  {.id = CUSTOM_14,
260  .name = "kb-custom-14",
261  .binding = "Alt+dollar",
262  .comment = "Custom keybinding 14"},
263  {.id = CUSTOM_15,
264  .name = "kb-custom-15",
265  .binding = "Alt+percent",
266  .comment = "Custom keybinding 15"},
267  {.id = CUSTOM_16,
268  .name = "kb-custom-16",
269  .binding = "Alt+dead_circumflex",
270  .comment = "Custom keybinding 16"},
271  {.id = CUSTOM_17,
272  .name = "kb-custom-17",
273  .binding = "Alt+ampersand",
274  .comment = "Custom keybinding 17"},
275  {.id = CUSTOM_18,
276  .name = "kb-custom-18",
277  .binding = "Alt+asterisk",
278  .comment = "Custom keybinding 18"},
279  {.id = CUSTOM_19,
280  .name = "kb-custom-19",
281  .binding = "Alt+parenleft",
282  .comment = "Custom Keybinding 19"},
283  {.id = SELECT_ELEMENT_1,
284  .name = "kb-select-1",
285  .binding = "Super+1",
286  .comment = "Select row 1"},
287  {.id = SELECT_ELEMENT_2,
288  .name = "kb-select-2",
289  .binding = "Super+2",
290  .comment = "Select row 2"},
291  {.id = SELECT_ELEMENT_3,
292  .name = "kb-select-3",
293  .binding = "Super+3",
294  .comment = "Select row 3"},
295  {.id = SELECT_ELEMENT_4,
296  .name = "kb-select-4",
297  .binding = "Super+4",
298  .comment = "Select row 4"},
299  {.id = SELECT_ELEMENT_5,
300  .name = "kb-select-5",
301  .binding = "Super+5",
302  .comment = "Select row 5"},
303  {.id = SELECT_ELEMENT_6,
304  .name = "kb-select-6",
305  .binding = "Super+6",
306  .comment = "Select row 6"},
307  {.id = SELECT_ELEMENT_7,
308  .name = "kb-select-7",
309  .binding = "Super+7",
310  .comment = "Select row 7"},
311  {.id = SELECT_ELEMENT_8,
312  .name = "kb-select-8",
313  .binding = "Super+8",
314  .comment = "Select row 8"},
315  {.id = SELECT_ELEMENT_9,
316  .name = "kb-select-9",
317  .binding = "Super+9",
318  .comment = "Select row 9"},
319  {.id = SELECT_ELEMENT_10,
320  .name = "kb-select-10",
321  .binding = "Super+0",
322  .comment = "Select row 10"},
323 
324  /* Mouse-aware bindings */
325 
326  {.id = SCROLL_LEFT,
327  .scope = SCOPE_MOUSE_LISTVIEW,
328  .name = "ml-row-left",
329  .binding = "ScrollLeft",
330  .comment = "Go to the previous column"},
331  {.id = SCROLL_RIGHT,
332  .scope = SCOPE_MOUSE_LISTVIEW,
333  .name = "ml-row-right",
334  .binding = "ScrollRight",
335  .comment = "Go to the next column"},
336  {.id = SCROLL_UP,
337  .scope = SCOPE_MOUSE_LISTVIEW,
338  .name = "ml-row-up",
339  .binding = "ScrollUp",
340  .comment = "Select previous entry"},
341  {.id = SCROLL_DOWN,
342  .scope = SCOPE_MOUSE_LISTVIEW,
343  .name = "ml-row-down",
344  .binding = "ScrollDown",
345  .comment = "Select next entry"},
346 
347  {.id = SELECT_HOVERED_ENTRY,
349  .name = "me-select-entry",
350  .binding = "MousePrimary",
351  .comment = "Select hovered row"},
352  {.id = ACCEPT_HOVERED_ENTRY,
354  .name = "me-accept-entry",
355  .binding = "MouseDPrimary",
356  .comment = "Accept hovered row"},
357  {.id = ACCEPT_HOVERED_CUSTOM,
359  .name = "me-accept-custom",
360  .binding = "Control+MouseDPrimary",
361  .comment = "Accept hovered row with custom action"},
362 };
363 
365 static const gchar *mouse_default_bindings[] = {
366  [MOUSE_CLICK_DOWN] = "MousePrimary",
367  [MOUSE_CLICK_UP] = "!MousePrimary",
368  [MOUSE_DCLICK_DOWN] = "MouseDPrimary",
369  [MOUSE_DCLICK_UP] = "!MouseDPrimary",
370 };
371 
372 void setup_abe(void) {
373  for (gsize i = 0; i < G_N_ELEMENTS(rofi_bindings); ++i) {
375  b->binding = g_strdup(b->binding);
376  config_parser_add_option(xrm_String, b->name, (void **)&(b->binding),
377  b->comment);
378  }
379 }
380 
381 static gboolean binding_check_action(guint64 scope,
382  G_GNUC_UNUSED gpointer target,
383  gpointer user_data) {
385  GPOINTER_TO_UINT(user_data))
386  ? NK_BINDINGS_BINDING_TRIGGERED
387  : NK_BINDINGS_BINDING_NOT_TRIGGERED;
388 }
389 
390 static void binding_trigger_action(guint64 scope, G_GNUC_UNUSED gpointer target,
391  gpointer user_data) {
393  GPOINTER_TO_UINT(user_data));
394 }
395 
396 guint key_binding_get_action_from_name(const char *name) {
397  for (gsize i = 0; i < G_N_ELEMENTS(rofi_bindings); ++i) {
399  if (g_strcmp0(b->name, name) == 0) {
400  return b->id;
401  }
402  }
403  return UINT32_MAX;
404 }
405 
406 gboolean parse_keys_abe(NkBindings *bindings) {
407  GError *error = NULL;
408  GString *error_msg = g_string_new("");
409  for (gsize i = 0; i < G_N_ELEMENTS(rofi_bindings); ++i) {
411  char *keystr = g_strdup(b->binding);
412  char *sp = NULL;
413 
414  // Iter over bindings.
415  const char *const sep = ",";
416  for (char *entry = strtok_r(keystr, sep, &sp); entry != NULL;
417  entry = strtok_r(NULL, sep, &sp)) {
418  if (!nk_bindings_add_binding(bindings, b->scope, entry,
420  GUINT_TO_POINTER(b->id), NULL, &error)) {
421  char *str = g_markup_printf_escaped(
422  "Failed to set binding <i>%s</i> for: <i>%s (%s)</i>:\n\t<span "
423  "size=\"smaller\" style=\"italic\">%s</span>\n",
424  b->binding, b->comment, b->name, error->message);
425  g_string_append(error_msg, str);
426  g_free(str);
427  g_clear_error(&error);
428  }
429  }
430 
431  g_free(keystr);
432  }
433  if (error_msg->len > 0) {
434  // rofi_view_error_dialog ( error_msg->str, TRUE );
435  rofi_add_error_message(error_msg);
436  // g_string_free ( error_msg, TRUE );
437  return FALSE;
438  }
439 
440  for (gsize i = SCOPE_MIN_FIXED; i <= SCOPE_MAX_FIXED; ++i) {
441  for (gsize j = 1; j < G_N_ELEMENTS(mouse_default_bindings); ++j) {
442  nk_bindings_add_binding(bindings, i, mouse_default_bindings[j],
444  GSIZE_TO_POINTER(j), NULL, NULL);
445  }
446  }
447 
448  g_string_free(error_msg, TRUE);
449  return TRUE;
450 }
void config_parser_add_option(XrmOptionType type, const char *key, void **value, const char *comment)
Definition: xrmoptions.c:455
@ xrm_String
Definition: xrmoptions.h:74
gboolean parse_keys_abe(NkBindings *bindings)
Definition: keyb.c:406
guint key_binding_get_action_from_name(const char *name)
Definition: keyb.c:396
void setup_abe(void)
Definition: keyb.c:372
@ SCOPE_MOUSE_LISTVIEW_ELEMENT
Definition: keyb.h:46
@ SCOPE_MOUSE_LISTVIEW
Definition: keyb.h:45
@ ROW_LAST
Definition: keyb.h:109
@ CUSTOM_4
Definition: keyb.h:115
@ CUSTOM_17
Definition: keyb.h:128
@ CUSTOM_12
Definition: keyb.h:123
@ CUSTOM_9
Definition: keyb.h:120
@ REMOVE_TO_SOL
Definition: keyb.h:88
@ ROW_RIGHT
Definition: keyb.h:100
@ ROW_UP
Definition: keyb.h:101
@ CUSTOM_8
Definition: keyb.h:119
@ SELECT_ELEMENT_9
Definition: keyb.h:142
@ MOVE_FRONT
Definition: keyb.h:66
@ REMOVE_WORD_FORWARD
Definition: keyb.h:80
@ CHANGE_ELLIPSIZE
Definition: keyb.h:132
@ ACCEPT_CUSTOM_ALT
Definition: keyb.h:93
@ REMOVE_WORD_BACK
Definition: keyb.h:78
@ TOGGLE_SORT
Definition: keyb.h:133
@ ACCEPT_ENTRY
Definition: keyb.h:90
@ ROW_TAB
Definition: keyb.h:103
@ PAGE_NEXT
Definition: keyb.h:107
@ TOGGLE_CASE_SENSITIVITY
Definition: keyb.h:97
@ ELEMENT_NEXT
Definition: keyb.h:104
@ MOVE_CHAR_FORWARD
Definition: keyb.h:76
@ MOVE_WORD_FORWARD
Definition: keyb.h:72
@ MODE_COMPLETE
Definition: keyb.h:95
@ CUSTOM_1
Definition: keyb.h:112
@ SELECT_ELEMENT_6
Definition: keyb.h:139
@ CUSTOM_18
Definition: keyb.h:129
@ CUSTOM_15
Definition: keyb.h:126
@ CUSTOM_11
Definition: keyb.h:122
@ ACCEPT_CUSTOM
Definition: keyb.h:92
@ CUSTOM_5
Definition: keyb.h:116
@ CUSTOM_19
Definition: keyb.h:130
@ REMOVE_TO_EOL
Definition: keyb.h:86
@ SELECT_ELEMENT_3
Definition: keyb.h:136
@ ROW_SELECT
Definition: keyb.h:110
@ PASTE_PRIMARY
Definition: keyb.h:60
@ ROW_DOWN
Definition: keyb.h:102
@ CUSTOM_13
Definition: keyb.h:124
@ PASTE_SECONDARY
Definition: keyb.h:62
@ SELECT_ELEMENT_10
Definition: keyb.h:143
@ PAGE_PREV
Definition: keyb.h:106
@ CUSTOM_3
Definition: keyb.h:114
@ CUSTOM_7
Definition: keyb.h:118
@ SELECT_ELEMENT_5
Definition: keyb.h:138
@ ROW_FIRST
Definition: keyb.h:108
@ CUSTOM_6
Definition: keyb.h:117
@ ROW_LEFT
Definition: keyb.h:99
@ CUSTOM_14
Definition: keyb.h:125
@ SELECT_ELEMENT_4
Definition: keyb.h:137
@ MOVE_WORD_BACK
Definition: keyb.h:70
@ MOVE_END
Definition: keyb.h:68
@ CUSTOM_10
Definition: keyb.h:121
@ MODE_NEXT
Definition: keyb.h:94
@ REMOVE_CHAR_BACK
Definition: keyb.h:84
@ DELETE_ENTRY
Definition: keyb.h:98
@ SELECT_ELEMENT_1
Definition: keyb.h:134
@ CLEAR_LINE
Definition: keyb.h:64
@ CUSTOM_2
Definition: keyb.h:113
@ SELECT_ELEMENT_2
Definition: keyb.h:135
@ SCREENSHOT
Definition: keyb.h:131
@ CANCEL
Definition: keyb.h:111
@ ELEMENT_PREV
Definition: keyb.h:105
@ MODE_PREVIOUS
Definition: keyb.h:96
@ ACCEPT_ALT
Definition: keyb.h:91
@ SELECT_ELEMENT_7
Definition: keyb.h:140
@ MOVE_CHAR_BACK
Definition: keyb.h:74
@ SELECT_ELEMENT_8
Definition: keyb.h:141
@ REMOVE_CHAR_FORWARD
Definition: keyb.h:82
@ CUSTOM_16
Definition: keyb.h:127
@ ACCEPT_HOVERED_ENTRY
Definition: keyb.h:161
@ ACCEPT_HOVERED_CUSTOM
Definition: keyb.h:162
@ SELECT_HOVERED_ENTRY
Definition: keyb.h:160
@ SCROLL_LEFT
Definition: keyb.h:150
@ SCROLL_DOWN
Definition: keyb.h:152
@ SCROLL_RIGHT
Definition: keyb.h:151
@ SCROLL_UP
Definition: keyb.h:153
@ MOUSE_CLICK_DOWN
Definition: keyb.h:169
@ MOUSE_DCLICK_UP
Definition: keyb.h:172
@ MOUSE_CLICK_UP
Definition: keyb.h:170
@ MOUSE_DCLICK_DOWN
Definition: keyb.h:171
void rofi_add_error_message(GString *str)
Definition: rofi.c:90
RofiViewState * rofi_view_get_active(void)
Definition: view.c:549
void rofi_view_trigger_action(RofiViewState *state, BindingsScope scope, guint action)
Definition: view.c:1607
gboolean rofi_view_check_action(RofiViewState *state, BindingsScope scope, guint action)
Definition: view.c:1576
ActionBindingEntry rofi_bindings[]
Definition: keyb.c:45
static void binding_trigger_action(guint64 scope, G_GNUC_UNUSED gpointer target, gpointer user_data)
Definition: keyb.c:390
static gboolean binding_check_action(guint64 scope, G_GNUC_UNUSED gpointer target, gpointer user_data)
Definition: keyb.c:381
static const gchar * mouse_default_bindings[]
Definition: keyb.c:365
#define SCOPE_MAX_FIXED
Definition: keyb.h:52
#define SCOPE_MIN_FIXED
Definition: keyb.h:48
NkBindings * bindings
Definition: rofi.c:133
guint scope
Definition: keyb.c:36
char * name
Definition: keyb.c:37
char * comment
Definition: keyb.c:39
char * binding
Definition: keyb.c:38