diff options
author | Quentin Glidic <sardemff7+git@sardemff7.net> | 2017-05-28 02:18:09 +0200 |
---|---|---|
committer | Quentin Glidic <sardemff7+git@sardemff7.net> | 2017-05-29 16:51:06 +0200 |
commit | a9199e3e1762182ddd8a19514a75f6c78c14481a (patch) | |
tree | 1ed440438f11206d7770159a1f30d60ea9dd7587 | |
parent | 6acf365420beb5219a4d8643d93bf74a479dd2e3 (diff) |
Use libnkutils for keybindings
Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
34 files changed, 640 insertions, 799 deletions
diff --git a/.gitmodules b/.gitmodules index b0c4f823..33114f8b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "libgwater"] path = subprojects/libgwater url = git://github.com/sardemff7/libgwater +[submodule "libnkutils"] + path = subprojects/libnkutils + url = https://github.com/sardemff7/libnkutils @@ -28,7 +28,7 @@ Rofi uses autotools (GNU Build system), for more information see * gmodule-2.0 * gio-unix-2.0 * libstartup-notification-1.0 -* libxkbcommon >= 0.5.0 +* libxkbcommon >= 0.4.1 * libxkbcommon-x11 * libxcb (sometimes split, you need libxcb, libxcb-xkb and libxcb-randr libxcb-xinerama) * xcb-util diff --git a/Makefile.am b/Makefile.am index 50afdddf..8aaad607 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,11 +1,15 @@ # Specify automake version. AUTOMAKE_OPTIONS = 1.11.3 -ACLOCAL_AMFLAGS = -I subprojects/libgwater ${ACLOCAL_FLAGS} +ACLOCAL_AMFLAGS = -I subprojects/libnkutils -I subprojects/libgwater ${ACLOCAL_FLAGS} AM_YFLAGS = -d noinst_LIBRARIES = +EXTRA_DIST= +check_PROGRAMS= +TESTS= +include $(top_srcdir)/subprojects/libnkutils/libnkutils-nolibtool.mk include $(top_srcdir)/libgwater-xcb-nolibtool.mk ## @@ -114,6 +118,7 @@ rofi_SOURCES=\ rofi_CFLAGS=\ $(AM_CFLAGS)\ $(glib_CFLAGS)\ + $(NKUTILS_CFLAGS)\ $(GW_XCB_CFLAGS)\ $(pango_CFLAGS)\ $(libsn_CFLAGS)\ @@ -132,6 +137,7 @@ rofi_CFLAGS=\ rofi_LDADD=\ $(glib_LIBS)\ + $(NKUTILS_LIBS)\ $(GW_XCB_LIBS)\ $(libsn_LIBS)\ $(pango_LIBS)\ @@ -197,7 +203,7 @@ theme_DATA=\ ## # Extra DIST ## -EXTRA_DIST=\ +EXTRA_DIST+=\ $(markdown_FILES)\ $(markdown_SC_FILES)\ Examples/i3_switch_workspaces.sh\ @@ -219,7 +225,7 @@ update-manpage: $(top_srcdir)/doc/rofi-manpage.markdown $(top_srcdir)/doc/rofi-t ## # Rofi test program ## -check_PROGRAMS=\ +check_PROGRAMS+=\ history_test\ textbox_test\ helper_test\ @@ -488,7 +494,7 @@ mode_test_SOURCES=\ include/mode-private.h endif -TESTS=\ +TESTS+=\ history_test\ helper_test\ helper_expand\ @@ -560,6 +566,7 @@ coverage-clean: EXTRA_DIST += \ doc/meson.build \ + subprojects/libnkutils/meson.build \ subprojects/libgwater/xcb/meson.build \ meson_options.txt \ meson.build diff --git a/configure.ac b/configure.ac index 0445e422..8dc4fb8e 100644 --- a/configure.ac +++ b/configure.ac @@ -116,9 +116,9 @@ PKG_PROG_PKG_CONFIG dnl --------------------------------------------------------------------- dnl PKG_CONFIG based dependencies dnl --------------------------------------------------------------------- +NK_INIT([bindings]) PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.40 gio-unix-2.0 gmodule-2.0]) -GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon >= 0.5.0 xkbcommon-x11 xcb-ewmh xcb-icccm xcb-xrm xcb-randr xcb-xinerama]) -PKG_CHECK_EXISTS([xkbcommon >= 0.7.0], [AC_DEFINE([XkBCOMMON_HAS_CONSUMED2], [1], [If xkbcommon has the consumed2 API])]) +GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-xrm xcb-randr xcb-xinerama]) PKG_CHECK_MODULES([pango], [pango pangocairo]) PKG_CHECK_MODULES([cairo], [cairo cairo-xcb]) PKG_CHECK_MODULES([libsn], [libstartup-notification-1.0 ]) diff --git a/include/keyb.h b/include/keyb.h index 37263a34..e33b00b0 100644 --- a/include/keyb.h +++ b/include/keyb.h @@ -28,19 +28,34 @@ #ifndef ROFI_KEYB_H #define ROFI_KEYB_H +#include "nkutils-bindings.h" + /** * @defgroup KEYB KeyboardBindings * * @{ */ +typedef enum +{ + SCOPE_GLOBAL, + SCOPE_MOUSE_LISTVIEW, + SCOPE_MOUSE_LISTVIEW_ELEMENT, + +#define SCOPE_MIN_FIXED SCOPE_MOUSE_EDITBOX + SCOPE_MOUSE_EDITBOX, + SCOPE_MOUSE_SCROLLBAR, + SCOPE_MOUSE_SIDEBAR_MODI, +#define SCOPE_MAX_FIXED SCOPE_MOUSE_SIDEBAR_MODI +} BindingsScope; + /** * List of all possible actions that can be triggered by a keybinding. */ typedef enum { /** Paste from primary clipboard */ - PASTE_PRIMARY = 0, + PASTE_PRIMARY = 1, /** Paste from secondary clipboard */ PASTE_SECONDARY, /** Clear the entry box. */ @@ -119,14 +134,36 @@ typedef enum SELECT_ELEMENT_8, SELECT_ELEMENT_9, SELECT_ELEMENT_10, - NUM_ABE } KeyBindingAction; +typedef enum +{ + SCROLL_LEFT = 1, + SCROLL_RIGHT, + SCROLL_DOWN, + SCROLL_UP, +} MouseBindingListviewAction; + +typedef enum +{ + SELECT_HOVERED_ENTRY = 1, + ACCEPT_HOVERED_ENTRY, + ACCEPT_HOVERED_CUSTOM, +} MouseBindingListviewElementAction; + +typedef enum +{ + MOUSE_CLICK_DOWN = 1, + MOUSE_CLICK_UP, + MOUSE_DCLICK_DOWN, + MOUSE_DCLICK_UP, +} MouseBindingMouseDefaultAction; + /** * Parse the keybindings. * This should be called after the setting system is initialized. */ -gboolean parse_keys_abe ( void ); +gboolean parse_keys_abe ( NkBindings *bindings ); /** * Setup the keybindings @@ -134,21 +171,5 @@ gboolean parse_keys_abe ( void ); */ void setup_abe ( void ); -/** - * Cleanup. - */ -void cleanup_abe ( void ); - -/** - * Find if a binding has been triggered. - * @returns NUM_ABE if no key combo matches, a valid action otherwise. - */ -KeyBindingAction abe_find_action ( unsigned int mask, xkb_keysym_t key ); - -/** - * Trigger keybinding on key release. - */ -void abe_trigger_release ( void ); - /*@}*/ #endif // ROFI_KEYB_H diff --git a/include/theme.h b/include/theme.h index 8bdeddc1..9b03b32c 100644 --- a/include/theme.h +++ b/include/theme.h @@ -37,19 +37,19 @@ typedef enum { /** no highlight */ - HL_NONE = 0, + HL_NONE = 0, /** bold */ - HL_BOLD = 1, + HL_BOLD = 1, /** underline */ - HL_UNDERLINE = 2, + HL_UNDERLINE = 2, /** strikethrough */ HL_STRIKETHROUGH = 16, /** small caps */ - HL_SMALL_CAPS = 32, + HL_SMALL_CAPS = 32, /** italic */ - HL_ITALIC = 4, + HL_ITALIC = 4, /** color */ - HL_COLOR = 8 + HL_COLOR = 8 } HighlightStyle; /** Style of line */ diff --git a/include/view-internal.h b/include/view-internal.h index e4cb619c..4271b90e 100644 --- a/include/view-internal.h +++ b/include/view-internal.h @@ -122,8 +122,14 @@ struct RofiViewState /** Y position of the view */ int y; + struct + { + int x; + int y; + } mouse; + /** Regexs used for matching */ - GRegex **tokens; + GRegex **tokens; }; /** @} */ #endif diff --git a/include/view.h b/include/view.h index cb5d45d1..a7f3ebbe 100644 --- a/include/view.h +++ b/include/view.h @@ -143,7 +143,7 @@ void rofi_view_restart ( RofiViewState *state ); * * @returns TRUE if action was handled. */ -gboolean rofi_view_trigger_action ( RofiViewState *state, KeyBindingAction action ); +gboolean rofi_view_trigger_action ( guint scope, gpointer user_data ); /** * @param state The handle to the view diff --git a/include/widgets/listview.h b/include/widgets/listview.h index 4373cc6b..81d705b1 100644 --- a/include/widgets/listview.h +++ b/include/widgets/listview.h @@ -66,7 +66,7 @@ typedef void ( *listview_update_callback )( textbox *tb, unsigned int entry, voi /** * Callback when a element is activated. */ -typedef void ( *listview_mouse_activated_cb )( listview *, xcb_button_press_event_t *, void * ); +typedef void ( *listview_mouse_activated_cb )( listview *, gboolean, void * ); /** * @param name The name of the to be created widget. diff --git a/include/widgets/scrollbar.h b/include/widgets/scrollbar.h index 75ecfbf9..50fb78bc 100644 --- a/include/widgets/scrollbar.h +++ b/include/widgets/scrollbar.h @@ -43,6 +43,7 @@ typedef struct _scrollbar { widget widget; + gboolean scrolling; unsigned int length; unsigned int pos; unsigned int pos_length; @@ -88,7 +89,7 @@ void scrollbar_set_max_value ( scrollbar *sb, unsigned int max ); * * Calculate the position of the click relative to the max value of bar */ -unsigned int scrollbar_clicked ( const scrollbar *sb, int y ); +unsigned int scrollbar_scroll ( const scrollbar *sb, int y ); /*@}*/ #endif // ROFI_SCROLLBAR_H diff --git a/include/widgets/textbox.h b/include/widgets/textbox.h index fc75baa7..2209de29 100644 --- a/include/widgets/textbox.h +++ b/include/widgets/textbox.h @@ -120,9 +120,10 @@ typedef enum * free with #widget_free * @returns a new #textbox */ -textbox* textbox_create ( const char *name, TextboxFlags flags, - TextBoxFontType tbft, - const char *text ); +textbox* textbox_create_full ( WidgetType type, const char *name, TextboxFlags flags, + TextBoxFontType tbft, + const char *text ); +#define textbox_create( n, f, tbft, t ) textbox_create_full ( WIDGET_TYPE_UNKNOWN, n, f, tbft, t ) /** * @param tb Handle to the textbox * @param tbft The style of font to render. diff --git a/include/widgets/widget-internal.h b/include/widgets/widget-internal.h index 0ac497d5..60e1d11c 100644 --- a/include/widgets/widget-internal.h +++ b/include/widgets/widget-internal.h @@ -34,63 +34,67 @@ */ struct _widget { + /** The type of the widget */ + WidgetType type; /** X position relative to parent */ - short x; + short x; /** Y position relative to parent */ - short y; + short y; /** Width of the widget */ - short w; + short w; /** Height of the widget */ - short h; + short h; /** Padding */ - Padding def_margin; - Padding def_padding; - Padding def_border; - Padding def_border_radius; - Padding margin; - Padding padding; - Padding border; - Padding border_radius; + Padding def_margin; + Padding def_padding; + Padding def_border; + Padding def_border_radius; + Padding margin; + Padding padding; + Padding border; + Padding border_radius; /** enabled or not */ - gboolean enabled; + gboolean enabled; /** Expand the widget when packed */ - gboolean expand; + gboolean expand; /*** The packing index */ - int index; + int index; /** Place widget at end of parent */ - gboolean end; + gboolean end; /** Parent widget */ - struct _widget *parent; + struct _widget *parent; /** Internal */ - gboolean need_redraw; + gboolean need_redraw; /** get width of widget implementation function */ - int ( *get_width )( struct _widget * ); + int ( *get_width )( struct _widget * ); /** get height of widget implementation function */ - int ( *get_height )( struct _widget * ); + int ( *get_height )( struct _widget * ); /** draw widget implementation function */ - void ( *draw )( struct _widget *widget, cairo_t *draw ); + void ( *draw )( struct _widget *widget, cairo_t *draw ); /** resize widget implementation function */ - void ( *resize )( struct _widget *, short, short ); + void ( *resize )( struct _widget *, short, short ); /** update widget implementation function */ - void ( *update )( struct _widget * ); + void ( *update )( struct _widget * ); /** Handle mouse motion, used for dragging */ - gboolean ( *motion_notify )( struct _widget *, xcb_motion_notify_event_t * ); + gboolean ( *motion_notify )( struct _widget *, xcb_motion_notify_event_t * ); - int ( *get_desired_height )( struct _widget * ); + int ( *get_desired_height )( struct _widget * ); - /** widget clicked callback */ - widget_clicked_cb clicked; - /** user data for clicked callback */ - void *clicked_cb_data; + /** widget find_mouse_target callback */ + widget_find_mouse_target_cb find_mouse_target; + /** widget trigger_action callback */ + widget_trigger_action_cb trigger_action; + /** user data for find_mouse_target and trigger_action callback */ + void *trigger_action_cb_data; /** Free widget callback */ - void ( *free )( struct _widget *widget ); + void ( *free )( struct _widget *widget ); /** Name of widget (used for theming) */ - char *name; - const char *state; + char *name; + const char *state; }; /** @@ -100,7 +104,7 @@ struct _widget * Initializes the widget structure. * */ -void widget_init ( widget *widget, const char *name ); +void widget_init ( widget *widget, WidgetType type, const char *name ); /** * @param widget The widget handle. diff --git a/include/widgets/widget.h b/include/widgets/widget.h index 990e50b4..dd3ea162 100644 --- a/include/widgets/widget.h +++ b/include/widgets/widget.h @@ -31,6 +31,7 @@ #include <cairo.h> #include <xcb/xcb.h> #include <xcb/xproto.h> +#include "keyb.h" /** * @defgroup widget widget * @@ -48,11 +49,18 @@ * Structure is elaborated in widget-internal.h */ typedef struct _widget widget; - -/** - * Callback for when widget is clicked. - */ -typedef gboolean ( *widget_clicked_cb )( widget *, xcb_button_press_event_t *, void * ); +typedef enum +{ + WIDGET_TYPE_UNKNOWN, + WIDGET_TYPE_LISTVIEW = SCOPE_MOUSE_LISTVIEW, + WIDGET_TYPE_LISTVIEW_ELEMENT = SCOPE_MOUSE_LISTVIEW_ELEMENT, + WIDGET_TYPE_EDITBOX = SCOPE_MOUSE_EDITBOX, + WIDGET_TYPE_SCROLLBAR = SCOPE_MOUSE_SCROLLBAR, + WIDGET_TYPE_SIDEBAR_MODI = SCOPE_MOUSE_SIDEBAR_MODI, +} WidgetType; + +typedef widget * ( *widget_find_mouse_target_cb )( widget *, WidgetType type, gint *x, gint *y ); +typedef gboolean ( *widget_trigger_action_cb )( widget *, guint action, gint x, gint y, void * ); /** Macro to get widget from an implementation (e.g. textbox/scrollbar) */ #define WIDGET( a ) ( (widget *) ( a ) ) @@ -80,6 +88,14 @@ void widget_move ( widget *widget, short x, short y ); /** * @param widget Handle to widget * + * Get the type of the widget. + * @returns The type of the widget. + */ +WidgetType widget_type ( widget *widget ); + +/** + * @param widget Handle to widget + * * Check if widget is enabled. * @returns TRUE when widget is enabled. */ @@ -172,24 +188,35 @@ gboolean widget_need_redraw ( widget *wid ); /** * @param wid The widget handle - * @param xbe The button press event + * @param x A pointer to the x coordinate of the mouse event + * @param y A pointer to the y coordinate of the mouse event + * + * Get the widget that should handle a mouse event. + * @x and @y are adjusted to be relative to the widget. * - * Signal the widget that it has been clicked, - * The click should have happened within the region of the widget, check with - * ::widget_intersect. + * @returns returns the widget that should handle the mouse event. + */ +widget *widget_find_mouse_target ( widget *wid, WidgetType type, gint *x, gint *y ); + +/** + * @param wid The widget handle + * @param action The action to trigger + * @param x A pointer to the x coordinate of the click + * @param y A pointer to the y coordinate of the click * - * @returns returns TRUE if click is handled. + * Trigger an action on widget. + * @x and @y are relative to the widget. */ -gboolean widget_clicked ( widget *wid, xcb_button_press_event_t *xbe ); +gboolean widget_trigger_action ( widget *wid, guint action, gint x, gint y ); /** * @param wid The widget handle - * @param cb The widget click callback + * @param cb The widget trigger action callback * @param udata the user data to pass to callback * - * Override the widget clicked handler on widget. + * Override the widget trigger action handler on widget. */ -void widget_set_clicked_handler ( widget *wid, widget_clicked_cb cb, void *udata ); +void widget_set_trigger_action_handler ( widget *wid, widget_trigger_action_cb cb, void *udata ); /** * @param wid The widget handle diff --git a/include/x11-helper.h b/include/x11-helper.h index 68ebde32..01b061e6 100644 --- a/include/x11-helper.h +++ b/include/x11-helper.h @@ -171,38 +171,12 @@ int take_keyboard ( xcb_window_t w, int iters ); int take_pointer ( xcb_window_t w, int iters ); /** - * @param mask The mask to canonilize - * - * @return The canonilized mask - */ -unsigned int x11_canonalize_mask ( unsigned int mask ); - -/** - * @param xkb the xkb structure. - * - * Calculates the mask of all active modifier keys. - * - * @returns the mask describing all active modifier keys. - */ -unsigned int x11_get_current_mask ( xkb_stuff *xkb ); - -/** - * @param combo String representing the key combo - * @param mod [out] The modifier specified (or AnyModifier if not specified) - * @param key [out] The key specified - * @param release [out] If it should react on key-release, not key-press - * - * Parse key from user input string. - */ -gboolean x11_parse_key ( const char *combo, unsigned int *mod, xkb_keysym_t *key, gboolean *release, GString * ); - -/** * Setup several items required. * * Error handling, * * Numlock detection * * Cache */ -void x11_setup ( xkb_stuff *xkb ); +void x11_setup ( void ); /** * Depth of visual @@ -250,16 +224,6 @@ void x11_build_monitor_layout ( void ); void x11_dump_monitor_layout ( void ); /** - * @param mask the mask to check for key - * @param key the key to check in mask - * - * Check if key is in the modifier mask. - * - * @returns TRUE if key is in the modifier mask - */ -int x11_modifier_active ( unsigned int mask, int key ); - -/** * @param window The X11 window to modify * * Set the right hints to disable the window decoration. diff --git a/include/xkb-internal.h b/include/xkb-internal.h index 0425baf0..2cbef99f 100644 --- a/include/xkb-internal.h +++ b/include/xkb-internal.h @@ -28,31 +28,18 @@ #ifndef ROFI_XKB_INTERNAL_H #define ROFI_XKB_INTERNAL_H +#include "nkutils-bindings.h" #include <xkbcommon/xkbcommon.h> -#include <xkbcommon/xkbcommon-compose.h> struct xkb_stuff { /** connection to the X server*/ - xcb_connection_t *xcb_connection; - /** Keyboard context */ - struct xkb_context *context; + xcb_connection_t *xcb_connection; /** Flag indicating first event */ - uint8_t first_event; + uint8_t first_event; /** Keyboard device id */ - int32_t device_id; - /** Current keymap */ - struct xkb_keymap *keymap; - /** Keyboard state */ - struct xkb_state *state; - /** Compose information */ - struct - { - /** Compose table */ - struct xkb_compose_table *table; - /** Compose state */ - struct xkb_compose_state * state; - } compose; + int32_t device_id; + NkBindings *bindings; }; #endif diff --git a/meson.build b/meson.build index 8aff4592..b832b05f 100644 --- a/meson.build +++ b/meson.build @@ -45,7 +45,7 @@ deps = [ dependency('cairo'), dependency('pango'), dependency('pangocairo'), - dependency('xkbcommon', version: '>= 0.5.0'), + dependency('xkbcommon'), c_compiler.find_library('m', required: false), ] @@ -101,6 +101,17 @@ header_conf.set_quoted('THEME_DIR', themedir) config_h = configure_file(output: 'config.h', configuration: header_conf) +nk_modules = [ + 'bindings=true', +] +nk = subproject('libnkutils', default_options: nk_modules) +nk_options = nk.get_variable('nk_options') +foreach o : nk_modules + nk_options + if not nk_modules.contains(o) or not nk_options.contains(o) + error('You must not change libnkutils options @0@ != @1@'.format('|'.join(nk_modules), '|'.join(nk_options))) + endif +endforeach +deps += nk.get_variable('libnkutils') install_headers([ 'include/mode.h', diff --git a/source/dialogs/ssh.c b/source/dialogs/ssh.c index 36392da4..96230bf8 100644 --- a/source/dialogs/ssh.c +++ b/source/dialogs/ssh.c @@ -206,7 +206,7 @@ static char **read_hosts_file ( char ** retv, unsigned int *length ) // Reading one line per time. while ( getline ( &buffer, &buffer_length, fd ) > 0 ) { // Evaluate one line. - unsigned int index = 0, ti = 0; + unsigned int index = 0, ti = 0; char *token = buffer; // Tokenize it. diff --git a/source/helper.c b/source/helper.c index 7fa07478..f6b3b74d 100644 --- a/source/helper.c +++ b/source/helper.c @@ -256,7 +256,7 @@ GRegex **tokenize ( const char *input, int case_sensitive ) } char *saveptr = NULL, *token; - GRegex **retv = NULL; + GRegex **retv = NULL; if ( !config.tokenize ) { retv = g_malloc0 ( sizeof ( GRegex* ) * 2 ); retv[0] = (GRegex *) create_regex ( input, case_sensitive ); @@ -885,8 +885,8 @@ int rofi_scorer_fuzzy_evaluate ( const char *pattern, glong plen, const char *st // uleft: value of the upper left cell; ulefts: maximum value of uleft and cells on the left. The arbitrary initial // values suppress warnings. int uleft = 0, ulefts = 0, left, lefts; - const gchar *pit = pattern, *sit; - enum CharClass prev = NON_WORD; + const gchar *pit = pattern, *sit; + enum CharClass prev = NON_WORD; for ( si = 0, sit = str; si < slen; si++, sit = g_utf8_next_char ( sit ) ) { enum CharClass cur = rofi_scorer_get_character_class ( g_utf8_get_char ( sit ) ); score[si] = rofi_scorer_get_score_for ( prev, cur ); diff --git a/source/keyb.c b/source/keyb.c index 1c5163f0..a9331d6a 100644 --- a/source/keyb.c +++ b/source/keyb.c @@ -28,146 +28,136 @@ #include <config.h> #include <string.h> #include "rofi.h" -#include "x11-helper.h" +#include "xkb.h" +#include "xkb-internal.h" +#include "nkutils-bindings.h" #include "xrmoptions.h" typedef struct { - unsigned int modmask; - xkb_keysym_t keysym; - gboolean release; -} KeyBinding; - -typedef struct -{ - const char *name; - char *keystr; - int num_bindings; - KeyBinding *kb; + guint id; + guint scope; + char *name; + char *binding; + char *comment; } ActionBindingEntry; -typedef struct -{ - KeyBindingAction id; - char *name; - char *keybinding; - char *comment; -} DefaultBinding; - /** * Data structure holding all the action keybinding. */ -ActionBindingEntry abe[NUM_ABE]; - -/** - * LIST OF DEFAULT SETTINGS - */ -DefaultBinding bindings[NUM_ABE] = +ActionBindingEntry rofi_bindings[] = { - { .id = PASTE_PRIMARY, .name = "kb-primary-paste", .keybinding = "Control+V,Shift+Insert", .comment = "Paste primary selection" }, - { .id = PASTE_SECONDARY, .name = "kb-secondary-paste", .keybinding = "Control+v,Insert", .comment = "Paste clipboard" }, - { .id = CLEAR_LINE, .name = "kb-clear-line", .keybinding = "Control+w", .comment = "Clear input line" |