From c9701b2a9199ef7fe3348246232399449ca9416b Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Wed, 30 Jun 2021 13:29:54 +0200 Subject: [PATCH] [View] Add support for user timeout + keybinding action Configuration looks like: ```css configuration { timeout { delay: 15; action: "kb-cancel"; } } ``` Both delay and action need to be set. Action can be any of the keybindings as shown in `rofi -show keys`. (-timeout-delay 15 -timeout-action "kb-cancel" on commandline.). Fixes: #1066 --- include/keyb.h | 6 ++++++ source/keyb.c | 12 ++++++++++++ source/mode.c | 2 +- source/view.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/include/keyb.h b/include/keyb.h index 67c49432..1cf33254 100644 --- a/include/keyb.h +++ b/include/keyb.h @@ -186,5 +186,11 @@ gboolean parse_keys_abe ( NkBindings *bindings ); */ void setup_abe ( void ); +/** + * @param name Don't have the name. + * + * @returns id, or UINT32_MAX if not found. + */ +guint key_binding_get_action_from_name ( const char *name ); /**@}*/ #endif // ROFI_KEYB_H diff --git a/source/keyb.c b/source/keyb.c index edda3b75..04350bdf 100644 --- a/source/keyb.c +++ b/source/keyb.c @@ -147,6 +147,18 @@ static gboolean binding_trigger_action ( guint64 scope, G_GNUC_UNUSED gpointer t return rofi_view_trigger_action ( rofi_view_get_active (), scope, GPOINTER_TO_UINT ( user_data ) ); } +guint key_binding_get_action_from_name ( const char *name ) +{ + for ( gsize i = 0; i < G_N_ELEMENTS ( rofi_bindings ); ++i ) { + ActionBindingEntry *b = &rofi_bindings[i]; + if ( g_strcmp0(b->name, name) == 0 ){ + return b->id; + } + } + return UINT32_MAX; +} + + gboolean parse_keys_abe ( NkBindings *bindings ) { GError *error = NULL; diff --git a/source/mode.c b/source/mode.c index ae4b23be..5323cb25 100644 --- a/source/mode.c +++ b/source/mode.c @@ -157,7 +157,7 @@ const char *mode_get_display_name ( const Mode *mode ) ThemeWidget *wid = rofi_config_find_widget ( mode->name, NULL, TRUE ); if ( wid ) { /** Check string property */ - Property *p = rofi_theme_find_property ( wid, P_STRING, "display-name", FALSE ); + Property *p = rofi_theme_find_property ( wid, P_STRING, "display-name", TRUE ); if ( p != NULL && p->type == P_STRING ) { return p->value.s; } diff --git a/source/view.c b/source/view.c index 414603aa..656a4817 100644 --- a/source/view.c +++ b/source/view.c @@ -112,6 +112,8 @@ struct workarea mon; /** timeout for reloading */ guint idle_timeout; + /** timeout handling */ + guint user_timeout; /** debug counter for redraws */ unsigned long long count; /** redraw idle time. */ @@ -129,6 +131,7 @@ struct .flags = MENU_NORMAL, .views = G_QUEUE_INIT, .idle_timeout = 0, + .user_timeout = 0, .count = 0L, .repaint_source = 0, .fullscreen = FALSE, @@ -475,6 +478,48 @@ static gboolean rofi_view_reload_idle ( G_GNUC_UNUSED gpointer data ) CacheState.idle_timeout = 0; return G_SOURCE_REMOVE; } +static gboolean rofi_view_user_timeout ( G_GNUC_UNUSED gpointer data ) +{ + CacheState.user_timeout = 0; + ThemeWidget *wid = rofi_config_find_widget ( "timeout", NULL, TRUE ); + if ( wid ) { + /** Check string property */ + Property *p = rofi_theme_find_property ( wid, P_STRING, "action", TRUE); + if ( p != NULL && p->type == P_STRING ) { + const char *action = p->value.s; + guint id = key_binding_get_action_from_name(action); + if ( id != UINT32_MAX ) + { + rofi_view_trigger_action ( rofi_view_get_active (), SCOPE_GLOBAL, id); + } else { + g_warning("Failed to parse keybinding: %s\r\n", action); + } + } + } + return G_SOURCE_REMOVE; +} + +static void rofi_view_set_user_timeout ( G_GNUC_UNUSED gpointer data ) +{ + if ( CacheState.user_timeout > 0 ) { + g_source_remove ( CacheState.user_timeout ); + CacheState.user_timeout = 0; + } + { + /** Find the widget */ + ThemeWidget *wid = rofi_config_find_widget ( "timeout", NULL, TRUE ); + if ( wid ) { + /** Check string property */ + Property *p = rofi_theme_find_property ( wid, P_INTEGER, "delay", TRUE); + if ( p != NULL && p->type == P_INTEGER) { + int delay = p->value.i; + CacheState.user_timeout = g_timeout_add ( delay*1000 , rofi_view_user_timeout, NULL ); + } + } + } + +} + void rofi_view_reload ( void ) { @@ -1996,6 +2041,8 @@ RofiViewState *rofi_view_create ( Mode *sw, rofi_view_ping_mouse ( state ); xcb_flush ( xcb->connection ); + + rofi_view_set_user_timeout ( NULL ); /* When Override Redirect, the WM will not let us know we can take focus, so just steal it */ if ( ( ( menu_flags & MENU_NORMAL_WINDOW ) == 0 ) ) { rofi_xcb_set_input_focus ( CacheState.main_window ); @@ -2066,6 +2113,10 @@ void rofi_view_cleanup () g_source_remove ( CacheState.idle_timeout ); CacheState.idle_timeout = 0; } + if ( CacheState.user_timeout > 0 ) { + g_source_remove ( CacheState.user_timeout ); + CacheState.user_timeout = 0; + } if ( CacheState.repaint_source > 0 ) { g_source_remove ( CacheState.repaint_source ); CacheState.repaint_source = 0;