rofi  1.5.4
keyb.c
Go to the documentation of this file.
1 /*
2  * rofi
3  *
4  * MIT/X11 License
5  * Copyright © 2013-2017 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 <config.h>
29 #include <string.h>
30 #include "rofi.h"
31 #include "nkutils-bindings.h"
32 #include "xrmoptions.h"
33 
34 typedef struct
35 {
36  guint id;
37  guint scope;
38  char *name;
39  char *binding;
40  char *comment;
42 
47 {
48  { .id = PASTE_PRIMARY, .name = "kb-primary-paste", .binding = "Control+V,Shift+Insert", .comment = "Paste primary selection" },
49  { .id = PASTE_SECONDARY, .name = "kb-secondary-paste", .binding = "Control+v,Insert", .comment = "Paste clipboard" },
50  { .id = CLEAR_LINE, .name = "kb-clear-line", .binding = "Control+w", .comment = "Clear input line" },
51  { .id = MOVE_FRONT, .name = "kb-move-front", .binding = "Control+a", .comment = "Beginning of line" },
52  { .id = MOVE_END, .name = "kb-move-end", .binding = "Control+e", .comment = "End of line" },
53  { .id = MOVE_WORD_BACK, .name = "kb-move-word-back", .binding = "Alt+b,Control+Left", .comment = "Move back one word" },
54  { .id = MOVE_WORD_FORWARD, .name = "kb-move-word-forward", .binding = "Alt+f,Control+Right", .comment = "Move forward one word" },
55  { .id = MOVE_CHAR_BACK, .name = "kb-move-char-back", .binding = "Left,Control+b", .comment = "Move back one char" },
56  { .id = MOVE_CHAR_FORWARD, .name = "kb-move-char-forward", .binding = "Right,Control+f", .comment = "Move forward one char" },
57  { .id = REMOVE_WORD_BACK, .name = "kb-remove-word-back", .binding = "Control+Alt+h,Control+BackSpace", .comment = "Delete previous word" },
58  { .id = REMOVE_WORD_FORWARD, .name = "kb-remove-word-forward", .binding = "Control+Alt+d", .comment = "Delete next word" },
59  { .id = REMOVE_CHAR_FORWARD, .name = "kb-remove-char-forward", .binding = "Delete,Control+d", .comment = "Delete next char" },
60  { .id = REMOVE_CHAR_BACK, .name = "kb-remove-char-back", .binding = "BackSpace,Shift+BackSpace,Control+h", .comment = "Delete previous char" },
61  { .id = REMOVE_TO_EOL, .name = "kb-remove-to-eol", .binding = "Control+k", .comment = "Delete till the end of line" },
62  { .id = REMOVE_TO_SOL, .name = "kb-remove-to-sol", .binding = "Control+u", .comment = "Delete till the start of line" },
63  { .id = ACCEPT_ENTRY, .name = "kb-accept-entry", .binding = "Control+j,Control+m,Return,KP_Enter", .comment = "Accept entry" },
64  { .id = ACCEPT_CUSTOM, .name = "kb-accept-custom", .binding = "Control+Return", .comment = "Use entered text as command (in ssh/run modi)" },
65  { .id = ACCEPT_ALT, .name = "kb-accept-alt", .binding = "Shift+Return", .comment = "Use alternate accept command." },
66  { .id = DELETE_ENTRY, .name = "kb-delete-entry", .binding = "Shift+Delete", .comment = "Delete entry from history" },
67  { .id = MODE_NEXT, .name = "kb-mode-next", .binding = "Shift+Right,Control+Tab", .comment = "Switch to the next mode." },
68  { .id = MODE_PREVIOUS, .name = "kb-mode-previous", .binding = "Shift+Left,Control+ISO_Left_Tab", .comment = "Switch to the previous mode." },
69  { .id = ROW_LEFT, .name = "kb-row-left", .binding = "Control+Page_Up", .comment = "Go to the previous column" },
70  { .id = ROW_RIGHT, .name = "kb-row-right", .binding = "Control+Page_Down", .comment = "Go to the next column" },
71  { .id = ROW_UP, .name = "kb-row-up", .binding = "Up,Control+p,ISO_Left_Tab", .comment = "Select previous entry" },
72  { .id = ROW_DOWN, .name = "kb-row-down", .binding = "Down,Control+n", .comment = "Select next entry" },
73  { .id = ROW_TAB, .name = "kb-row-tab", .binding = "Tab", .comment = "Go to next row, if one left, accept it, if no left next mode." },
74  { .id = PAGE_PREV, .name = "kb-page-prev", .binding = "Page_Up", .comment = "Go to the previous page" },
75  { .id = PAGE_NEXT, .name = "kb-page-next", .binding = "Page_Down", .comment = "Go to the next page" },
76  { .id = ROW_FIRST, .name = "kb-row-first", .binding = "Home,KP_Home", .comment = "Go to the first entry" },
77  { .id = ROW_LAST, .name = "kb-row-last", .binding = "End,KP_End", .comment = "Go to the last entry" },
78  { .id = ROW_SELECT, .name = "kb-row-select", .binding = "Control+space", .comment = "Set selected item as input text" },
79  { .id = SCREENSHOT, .name = "kb-screenshot", .binding = "Alt+S", .comment = "Take a screenshot of the rofi window" },
80  { .id = CHANGE_ELLIPSIZE, .name = "kb-ellipsize", .binding = "Alt+period", .comment = "Toggle between ellipsize modes for displayed data" },
81  { .id = TOGGLE_CASE_SENSITIVITY, .name = "kb-toggle-case-sensitivity", .binding = "grave,dead_grave", .comment = "Toggle case sensitivity" },
82  { .id = TOGGLE_SORT, .name = "kb-toggle-sort", .binding = "Alt+grave", .comment = "Toggle sort" },
83  { .id = CANCEL, .name = "kb-cancel", .binding = "Escape,Control+g,Control+bracketleft", .comment = "Quit rofi" },
84  { .id = CUSTOM_1, .name = "kb-custom-1", .binding = "Alt+1", .comment = "Custom keybinding 1" },
85  { .id = CUSTOM_2, .name = "kb-custom-2", .binding = "Alt+2", .comment = "Custom keybinding 2" },
86  { .id = CUSTOM_3, .name = "kb-custom-3", .binding = "Alt+3", .comment = "Custom keybinding 3" },
87  { .id = CUSTOM_4, .name = "kb-custom-4", .binding = "Alt+4", .comment = "Custom keybinding 4" },
88  { .id = CUSTOM_5, .name = "kb-custom-5", .binding = "Alt+5", .comment = "Custom Keybinding 5" },
89  { .id = CUSTOM_6, .name = "kb-custom-6", .binding = "Alt+6", .comment = "Custom keybinding 6" },
90  { .id = CUSTOM_7, .name = "kb-custom-7", .binding = "Alt+7", .comment = "Custom Keybinding 7" },
91  { .id = CUSTOM_8, .name = "kb-custom-8", .binding = "Alt+8", .comment = "Custom keybinding 8" },
92  { .id = CUSTOM_9, .name = "kb-custom-9", .binding = "Alt+9", .comment = "Custom keybinding 9" },
93  { .id = CUSTOM_10, .name = "kb-custom-10", .binding = "Alt+0", .comment = "Custom keybinding 10" },
94  { .id = CUSTOM_11, .name = "kb-custom-11", .binding = "Alt+exclam", .comment = "Custom keybinding 11" },
95  { .id = CUSTOM_12, .name = "kb-custom-12", .binding = "Alt+at", .comment = "Custom keybinding 12" },
96  { .id = CUSTOM_13, .name = "kb-custom-13", .binding = "Alt+numbersign", .comment = "Csutom keybinding 13" },
97  { .id = CUSTOM_14, .name = "kb-custom-14", .binding = "Alt+dollar", .comment = "Custom keybinding 14" },
98  { .id = CUSTOM_15, .name = "kb-custom-15", .binding = "Alt+percent", .comment = "Custom keybinding 15" },
99  { .id = CUSTOM_16, .name = "kb-custom-16", .binding = "Alt+dead_circumflex", .comment = "Custom keybinding 16" },
100  { .id = CUSTOM_17, .name = "kb-custom-17", .binding = "Alt+ampersand", .comment = "Custom keybinding 17" },
101  { .id = CUSTOM_18, .name = "kb-custom-18", .binding = "Alt+asterisk", .comment = "Custom keybinding 18" },
102  { .id = CUSTOM_19, .name = "kb-custom-19", .binding = "Alt+parenleft", .comment = "Custom Keybinding 19" },
103  { .id = SELECT_ELEMENT_1, .name = "kb-select-1", .binding = "Super+1", .comment = "Select row 1" },
104  { .id = SELECT_ELEMENT_2, .name = "kb-select-2", .binding = "Super+2", .comment = "Select row 2" },
105  { .id = SELECT_ELEMENT_3, .name = "kb-select-3", .binding = "Super+3", .comment = "Select row 3" },
106  { .id = SELECT_ELEMENT_4, .name = "kb-select-4", .binding = "Super+4", .comment = "Select row 4" },
107  { .id = SELECT_ELEMENT_5, .name = "kb-select-5", .binding = "Super+5", .comment = "Select row 5" },
108  { .id = SELECT_ELEMENT_6, .name = "kb-select-6", .binding = "Super+6", .comment = "Select row 6" },
109  { .id = SELECT_ELEMENT_7, .name = "kb-select-7", .binding = "Super+7", .comment = "Select row 7" },
110  { .id = SELECT_ELEMENT_8, .name = "kb-select-8", .binding = "Super+8", .comment = "Select row 8" },
111  { .id = SELECT_ELEMENT_9, .name = "kb-select-9", .binding = "Super+9", .comment = "Select row 9" },
112  { .id = SELECT_ELEMENT_10, .name = "kb-select-10", .binding = "Super+0", .comment = "Select row 10" },
113 
114  /* Mouse-aware bindings */
115 
116  { .id = SCROLL_LEFT, .scope = SCOPE_MOUSE_LISTVIEW, .name = "ml-row-left", .binding = "ScrollLeft", .comment = "Go to the previous column" },
117  { .id = SCROLL_RIGHT, .scope = SCOPE_MOUSE_LISTVIEW, .name = "ml-row-right", .binding = "ScrollRight", .comment = "Go to the next column" },
118  { .id = SCROLL_UP, .scope = SCOPE_MOUSE_LISTVIEW, .name = "ml-row-up", .binding = "ScrollUp", .comment = "Select previous entry" },
119  { .id = SCROLL_DOWN, .scope = SCOPE_MOUSE_LISTVIEW, .name = "ml-row-down", .binding = "ScrollDown", .comment = "Select next entry" },
120 
121  { .id = SELECT_HOVERED_ENTRY, .scope = SCOPE_MOUSE_LISTVIEW_ELEMENT, .name = "me-select-entry", .binding = "MousePrimary", .comment = "Select hovered row" },
122  { .id = ACCEPT_HOVERED_ENTRY, .scope = SCOPE_MOUSE_LISTVIEW_ELEMENT, .name = "me-accept-entry", .binding = "MouseDPrimary", .comment = "Accept hovered row" },
123  { .id = ACCEPT_HOVERED_CUSTOM, .scope = SCOPE_MOUSE_LISTVIEW_ELEMENT, .name = "me-accept-custom", .binding = "Control+MouseDPrimary", .comment = "Accept hovered row with custom action"},
124 };
125 
127 static const gchar *mouse_default_bindings[] = {
128  [MOUSE_CLICK_DOWN] = "MousePrimary",
129  [MOUSE_CLICK_UP] = "!MousePrimary",
130  [MOUSE_DCLICK_DOWN] = "MouseDPrimary",
131  [MOUSE_DCLICK_UP] = "!MouseDPrimary",
132 };
133 
134 void setup_abe ( void )
135 {
136  for ( gsize i = 0; i < G_N_ELEMENTS ( rofi_bindings ); ++i ) {
138  b->binding = g_strdup ( b->binding );
139  config_parser_add_option ( xrm_String, b->name, (void * *) &( b->binding ), b->comment );
140  }
141 }
142 
143 static gboolean binding_trigger_action ( guint64 scope, G_GNUC_UNUSED gpointer target, gpointer user_data )
144 {
145  return rofi_view_trigger_action ( rofi_view_get_active (), scope, GPOINTER_TO_UINT ( user_data ) );
146 }
147 
148 gboolean parse_keys_abe ( NkBindings *bindings )
149 {
150  GError *error = NULL;
151  GString *error_msg = g_string_new ( "" );
152  for ( gsize i = 0; i < G_N_ELEMENTS ( rofi_bindings ); ++i ) {
154  char *keystr = g_strdup ( b->binding );
155  char *sp = NULL;
156 
157  // Iter over bindings.
158  const char *const sep = ",";
159  for ( char *entry = strtok_r ( keystr, sep, &sp ); entry != NULL; entry = strtok_r ( NULL, sep, &sp ) ) {
160  if ( !nk_bindings_add_binding ( bindings, b->scope, entry, binding_trigger_action, GUINT_TO_POINTER ( b->id ), NULL, &error ) ) {
161  char *str = g_markup_printf_escaped ( "Failed to set binding <i>%s</i> for: <i>%s (%s)</i>:\n\t<span size=\"smaller\" style=\"italic\">%s</span>\n",
162  b->binding, b->comment, b->name, error->message );
163  g_string_append ( error_msg, str );
164  g_free ( str );
165  g_clear_error ( &error );
166  }
167  }
168 
169  g_free ( keystr );
170  }
171  if ( error_msg->len > 0 ) {
172  //rofi_view_error_dialog ( error_msg->str, TRUE );
173  rofi_add_error_message ( error_msg );
174 // g_string_free ( error_msg, TRUE );
175  return FALSE;
176  }
177 
178  for ( gsize i = SCOPE_MIN_FIXED; i <= SCOPE_MAX_FIXED; ++i ) {
179  for ( gsize j = 1; j < G_N_ELEMENTS ( mouse_default_bindings ); ++j ) {
180  nk_bindings_add_binding ( bindings, i, mouse_default_bindings[j], binding_trigger_action, GSIZE_TO_POINTER ( j ), NULL, NULL );
181  }
182  }
183 
184  g_string_free ( error_msg, TRUE );
185  return TRUE;
186 }
SELECT_ELEMENT_5
@ SELECT_ELEMENT_5
Definition: keyb.h:135
PASTE_SECONDARY
@ PASTE_SECONDARY
Definition: keyb.h:63
REMOVE_WORD_BACK
@ REMOVE_WORD_BACK
Definition: keyb.h:79
SELECT_ELEMENT_9
@ SELECT_ELEMENT_9
Definition: keyb.h:139
ActionBindingEntry::scope
guint scope
Definition: keyb.c:37
CANCEL
@ CANCEL
Definition: keyb.h:108
MOVE_CHAR_BACK
@ MOVE_CHAR_BACK
Definition: keyb.h:75
ACCEPT_ENTRY
@ ACCEPT_ENTRY
Definition: keyb.h:91
xrmoptions.h
CUSTOM_17
@ CUSTOM_17
Definition: keyb.h:125
REMOVE_WORD_FORWARD
@ REMOVE_WORD_FORWARD
Definition: keyb.h:81
parse_keys_abe
gboolean parse_keys_abe(NkBindings *bindings)
Definition: keyb.c:148
CUSTOM_6
@ CUSTOM_6
Definition: keyb.h:114
ROW_LAST
@ ROW_LAST
Definition: keyb.h:106
ROW_LEFT
@ ROW_LEFT
Definition: keyb.h:98
SELECT_ELEMENT_7
@ SELECT_ELEMENT_7
Definition: keyb.h:137
SCOPE_MIN_FIXED
#define SCOPE_MIN_FIXED
Definition: keyb.h:48
CUSTOM_9
@ CUSTOM_9
Definition: keyb.h:117
PAGE_NEXT
@ PAGE_NEXT
Definition: keyb.h:104
rofi_bindings
ActionBindingEntry rofi_bindings[]
Definition: keyb.c:46
MOUSE_CLICK_UP
@ MOUSE_CLICK_UP
Definition: keyb.h:170
ActionBindingEntry::id
guint id
Definition: keyb.c:36
REMOVE_TO_EOL
@ REMOVE_TO_EOL
Definition: keyb.h:87
SELECT_ELEMENT_10
@ SELECT_ELEMENT_10
Definition: keyb.h:140
rofi_view_get_active
RofiViewState * rofi_view_get_active(void)
Definition: view.c:447
MODE_PREVIOUS
@ MODE_PREVIOUS
Definition: keyb.h:95
CUSTOM_10
@ CUSTOM_10
Definition: keyb.h:118
MOUSE_DCLICK_UP
@ MOUSE_DCLICK_UP
Definition: keyb.h:172
SELECT_ELEMENT_1
@ SELECT_ELEMENT_1
Definition: keyb.h:131
MOUSE_CLICK_DOWN
@ MOUSE_CLICK_DOWN
Definition: keyb.h:169
CUSTOM_11
@ CUSTOM_11
Definition: keyb.h:119
ROW_RIGHT
@ ROW_RIGHT
Definition: keyb.h:99
binding_trigger_action
static gboolean binding_trigger_action(guint64 scope, G_GNUC_UNUSED gpointer target, gpointer user_data)
Definition: keyb.c:143
MOVE_WORD_FORWARD
@ MOVE_WORD_FORWARD
Definition: keyb.h:73
CLEAR_LINE
@ CLEAR_LINE
Definition: keyb.h:65
ActionBindingEntry::binding
char * binding
Definition: keyb.c:39
CUSTOM_13
@ CUSTOM_13
Definition: keyb.h:121
CUSTOM_5
@ CUSTOM_5
Definition: keyb.h:113
SELECT_ELEMENT_6
@ SELECT_ELEMENT_6
Definition: keyb.h:136
REMOVE_TO_SOL
@ REMOVE_TO_SOL
Definition: keyb.h:89
ROW_DOWN
@ ROW_DOWN
Definition: keyb.h:101
ROW_TAB
@ ROW_TAB
Definition: keyb.h:102
CHANGE_ELLIPSIZE
@ CHANGE_ELLIPSIZE
Definition: keyb.h:129
SELECT_ELEMENT_4
@ SELECT_ELEMENT_4
Definition: keyb.h:134
SCOPE_MOUSE_LISTVIEW_ELEMENT
@ SCOPE_MOUSE_LISTVIEW_ELEMENT
Definition: keyb.h:46
CUSTOM_12
@ CUSTOM_12
Definition: keyb.h:120
CUSTOM_1
@ CUSTOM_1
Definition: keyb.h:109
MOVE_END
@ MOVE_END
Definition: keyb.h:69
DELETE_ENTRY
@ DELETE_ENTRY
Definition: keyb.h:97
CUSTOM_7
@ CUSTOM_7
Definition: keyb.h:115
SELECT_HOVERED_ENTRY
@ SELECT_HOVERED_ENTRY
Definition: keyb.h:159
MOUSE_DCLICK_DOWN
@ MOUSE_DCLICK_DOWN
Definition: keyb.h:171
CUSTOM_15
@ CUSTOM_15
Definition: keyb.h:123
SCREENSHOT
@ SCREENSHOT
Definition: keyb.h:128
SCROLL_UP
@ SCROLL_UP
Definition: keyb.h:151
CUSTOM_3
@ CUSTOM_3
Definition: keyb.h:111
ACCEPT_HOVERED_CUSTOM
@ ACCEPT_HOVERED_CUSTOM
Definition: keyb.h:161
CUSTOM_19
@ CUSTOM_19
Definition: keyb.h:127
PASTE_PRIMARY
@ PASTE_PRIMARY
Definition: keyb.h:61
rofi.h
SELECT_ELEMENT_3
@ SELECT_ELEMENT_3
Definition: keyb.h:133
CUSTOM_14
@ CUSTOM_14
Definition: keyb.h:122
config_parser_add_option
void config_parser_add_option(XrmOptionType type, const char *key, void **value, const char *comment)
Definition: xrmoptions.c:230
SCROLL_RIGHT
@ SCROLL_RIGHT
Definition: keyb.h:149
ActionBindingEntry
Definition: keyb.c:35
rofi_add_error_message
void rofi_add_error_message(GString *str)
Definition: rofi.c:90
ROW_SELECT
@ ROW_SELECT
Definition: keyb.h:107
MOVE_FRONT
@ MOVE_FRONT
Definition: keyb.h:67
TOGGLE_CASE_SENSITIVITY
@ TOGGLE_CASE_SENSITIVITY
Definition: keyb.h:96
xrm_String
@ xrm_String
Definition: xrmoptions.h:72
SCROLL_DOWN
@ SCROLL_DOWN
Definition: keyb.h:150
TOGGLE_SORT
@ TOGGLE_SORT
Definition: keyb.h:130
MODE_NEXT
@ MODE_NEXT
Definition: keyb.h:94
CUSTOM_2
@ CUSTOM_2
Definition: keyb.h:110
ACCEPT_CUSTOM
@ ACCEPT_CUSTOM
Definition: keyb.h:93
bindings
NkBindings * bindings
Definition: rofi.c:112
mouse_default_bindings
static const gchar * mouse_default_bindings[]
Definition: keyb.c:127
CUSTOM_8
@ CUSTOM_8
Definition: keyb.h:116
SELECT_ELEMENT_2
@ SELECT_ELEMENT_2
Definition: keyb.h:132
SCROLL_LEFT
@ SCROLL_LEFT
Definition: keyb.h:148
PAGE_PREV
@ PAGE_PREV
Definition: keyb.h:103
CUSTOM_18
@ CUSTOM_18
Definition: keyb.h:126
SCOPE_MOUSE_LISTVIEW
@ SCOPE_MOUSE_LISTVIEW
Definition: keyb.h:45
SELECT_ELEMENT_8
@ SELECT_ELEMENT_8
Definition: keyb.h:138
MOVE_WORD_BACK
@ MOVE_WORD_BACK
Definition: keyb.h:71
CUSTOM_16
@ CUSTOM_16
Definition: keyb.h:124
rofi_view_trigger_action
gboolean rofi_view_trigger_action(RofiViewState *state, BindingsScope scope, guint action)
Definition: view.c:1358
setup_abe
void setup_abe(void)
Definition: keyb.c:134
SCOPE_MAX_FIXED
#define SCOPE_MAX_FIXED
Definition: keyb.h:52
MOVE_CHAR_FORWARD
@ MOVE_CHAR_FORWARD
Definition: keyb.h:77
REMOVE_CHAR_FORWARD
@ REMOVE_CHAR_FORWARD
Definition: keyb.h:83
ActionBindingEntry::name
char * name
Definition: keyb.c:38
ACCEPT_HOVERED_ENTRY
@ ACCEPT_HOVERED_ENTRY
Definition: keyb.h:160
ActionBindingEntry::comment
char * comment
Definition: keyb.c:40
ROW_UP
@ ROW_UP
Definition: keyb.h:100
ACCEPT_ALT
@ ACCEPT_ALT
Definition: keyb.h:92
ROW_FIRST
@ ROW_FIRST
Definition: keyb.h:105
REMOVE_CHAR_BACK
@ REMOVE_CHAR_BACK
Definition: keyb.h:85
CUSTOM_4
@ CUSTOM_4
Definition: keyb.h:112