From 0daab1844efe172318e68909520ec8b97a3acff9 Mon Sep 17 00:00:00 2001 From: Quentin Glidic Date: Fri, 11 Mar 2016 10:43:32 +0100 Subject: helper: Add execute helper Signed-off-by: Quentin Glidic --- include/helper.h | 14 +++++++++++++- source/dialogs/ssh.c | 19 ++----------------- source/helper.c | 37 ++++++++++++++++++++++++------------- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/include/helper.h b/include/helper.h index ab7fa1c2..de9419dd 100644 --- a/include/helper.h +++ b/include/helper.h @@ -39,6 +39,7 @@ * * @{ */ + /** * @param string The input string. * @param output Pointer to 2 dimensional array with parsed string. @@ -258,6 +259,17 @@ int rofi_scorer_fuzzy_evaluate ( const char *pattern, glong plen, const char *st */ int utf8_strncmp ( const char *a, const char* b, size_t n ) __attribute__( ( nonnull ( 1, 2 ) ) ); +/** + * @param args The arguments of the command to exec. + * @param error_precmd Prefix to error message command. + * @param error_cmd Error message command + * + * Executes the command + * + * @returns TRUE when successful, FALSE when failed. + */ +gboolean helper_execute ( const char *wd, char **args, const char *error_precmd, const char *error_cmd ); + /** * @param wd The work directory (optional) * @param cmd The cmd to execute @@ -267,7 +279,7 @@ int utf8_strncmp ( const char *a, const char* b, size_t n ) __attribute__( ( non * * @returns FALSE On failure, TRUE on success */ -int helper_execute_command ( const char *wd, const char *cmd, int run_in_term ); +gboolean helper_execute_command ( const char *wd, const char *cmd, int run_in_term ); /** * @param file The file path diff --git a/source/dialogs/ssh.c b/source/dialogs/ssh.c index 96230bf8..66fdc74a 100644 --- a/source/dialogs/ssh.c +++ b/source/dialogs/ssh.c @@ -78,25 +78,10 @@ static inline int execshssh ( const char *host ) { char **args = NULL; int argsv = 0; - helper_parse_setup ( config.ssh_command, &args, &argsv, "{host}", host, NULL ); - - GError *error = NULL; - g_spawn_async ( NULL, args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error ); - - if ( error != NULL ) { - char *msg = g_strdup_printf ( "Failed to execute: 'ssh %s'\nError: '%s'", host, error->message ); - rofi_view_error_dialog ( msg, FALSE ); - g_free ( msg ); - // print error. - g_error_free ( error ); - g_strfreev ( args ); - return FALSE; - } - // Free the args list. - g_strfreev ( args ); + helper_parse_setup ( config.ssh_command, &args, &argsv, "{host}", host, NULL ); - return TRUE; + return helper_execute ( NULL, args, "ssh ", host ); } /** diff --git a/source/helper.c b/source/helper.c index e0a0563e..ebcf783d 100644 --- a/source/helper.c +++ b/source/helper.c @@ -962,21 +962,17 @@ int utf8_strncmp ( const char* a, const char* b, size_t n ) return r; } -int helper_execute_command ( const char *wd, const char *cmd, int run_in_term ) +gboolean helper_execute ( const char *wd, char **args, const char *error_precmd, const char *error_cmd ) { - int retv = TRUE; - char **args = NULL; - int argc = 0; - if ( run_in_term ) { - helper_parse_setup ( config.run_shell_command, &args, &argc, "{cmd}", cmd, NULL ); - } - else { - helper_parse_setup ( config.run_command, &args, &argc, "{cmd}", cmd, NULL ); - } - GError *error = NULL; - g_spawn_async ( wd, args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error ); + gboolean retv = TRUE; + GError *error = NULL; + + GSpawnChildSetupFunc child_setup = NULL; + gpointer user_data = NULL; + + g_spawn_async ( wd, args, NULL, G_SPAWN_SEARCH_PATH, child_setup, user_data, NULL, &error ); if ( error != NULL ) { - char *msg = g_strdup_printf ( "Failed to execute: '%s'\nError: '%s'", cmd, error->message ); + char *msg = g_strdup_printf ( "Failed to execute: '%s%s'\nError: '%s'", error_precmd, error_cmd, error->message ); rofi_view_error_dialog ( msg, FALSE ); g_free ( msg ); // print error. @@ -989,6 +985,21 @@ int helper_execute_command ( const char *wd, const char *cmd, int run_in_term ) return retv; } +gboolean helper_execute_command ( const char *wd, const char *cmd, int run_in_term ) +{ + char **args = NULL; + int argc = 0; + + if ( run_in_term ) { + helper_parse_setup ( config.run_shell_command, &args, &argc, "{cmd}", cmd, NULL ); + } + else { + helper_parse_setup ( config.run_command, &args, &argc, "{cmd}", cmd, NULL ); + } + + return helper_execute ( wd, args, "", cmd ); +} + char *helper_get_theme_path ( const char *file ) { char *filename = rofi_expand_path ( file ); -- cgit v1.2.3 From dc1417ba724309955dd8d12bf38eaeccc106129d Mon Sep 17 00:00:00 2001 From: Quentin Glidic Date: Fri, 2 Jun 2017 14:27:47 +0200 Subject: drun: Fix thread function signature Signed-off-by: Quentin Glidic --- source/dialogs/drun.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index 83aabef4..51aba5e1 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -420,7 +420,7 @@ static void get_apps ( DRunModePrivateData *pd ) TICK_N ( "Get Desktop apps (system dirs)" ); } -static void drun_icon_fetch ( gpointer data ) +static gpointer drun_icon_fetch ( gpointer data ) { // as long as dr->icon is updated atomicly.. (is a pointer write atomic?) // this should be fine running in another thread. @@ -462,6 +462,7 @@ static void drun_icon_fetch ( gpointer data ) rofi_view_reload (); g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "elapsed: %f\n", g_timer_elapsed ( t, NULL ) ); g_timer_destroy ( t ); + return NULL; } static int drun_mode_init ( Mode *sw ) -- cgit v1.2.3 From 6fefbbf8ab47b87fc4cb4a70f82c7bcc0b91587b Mon Sep 17 00:00:00 2001 From: Quentin Glidic Date: Fri, 2 Jun 2017 14:28:22 +0200 Subject: drun: Keep the icon name around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don’t need to use it as the “we’ve search already” value since we know just look icons up in a single pass. Signed-off-by: Quentin Glidic --- source/dialogs/drun.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index 51aba5e1..b4834c4f 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -449,9 +449,6 @@ static gpointer drun_icon_fetch ( gpointer data ) } else { g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Icon type not yet supported: %s", icon_path ); - char *r = dr->icon_name; - dr->icon_name = NULL; - g_free ( r ); } g_free ( icon_path ); // if ( (i%100) == 99 ) -- cgit v1.2.3 From 51d34b662e95399ca23caededa9f61f7a7e1dca3 Mon Sep 17 00:00:00 2001 From: Quentin Glidic Date: Fri, 2 Jun 2017 14:54:21 +0200 Subject: helper: Add API to support startup notification Signed-off-by: Quentin Glidic --- include/display.h | 10 ++++++++++ include/helper.h | 28 ++++++++++++++++++++++++++-- source/dialogs/drun.c | 4 ++-- source/dialogs/run.c | 2 +- source/dialogs/ssh.c | 2 +- source/helper.c | 28 +++++++++++++++++++++++++--- source/xcb.c | 4 ++++ test/helper-config-cmdline-parser.c | 5 +++++ test/helper-expand.c | 5 +++++ test/helper-pidfile.c | 5 +++++ test/helper-test.c | 5 +++++ test/helper-tokenize.c | 5 +++++ test/mode-test.c | 6 ++++++ test/textbox-test.c | 5 +++++ test/theme-parser-test.c | 5 +++++ test/widget-test.c | 5 +++++ 16 files changed, 115 insertions(+), 9 deletions(-) diff --git a/include/display.h b/include/display.h index b0feb8c7..a6977808 100644 --- a/include/display.h +++ b/include/display.h @@ -29,6 +29,7 @@ #define ROFI_DISPLAY_H #include +#include "helper.h" #include "nkutils-bindings.h" /** @@ -63,4 +64,13 @@ void display_cleanup(void); */ void display_dump_monitor_layout ( void ); +/** + * @param context The startup notification context for the application to launch + * @param child_setup A pointer to return the child setup function + * @param user_data A pointer to return the child setup function user_data + * + * Provides the needed child setup function + */ +void display_startup_notification ( RofiHelperExecuteContext *context, GSpawnChildSetupFunc *child_setup, gpointer *user_data ); + #endif diff --git a/include/helper.h b/include/helper.h index de9419dd..1b75f6c8 100644 --- a/include/helper.h +++ b/include/helper.h @@ -259,27 +259,51 @@ int rofi_scorer_fuzzy_evaluate ( const char *pattern, glong plen, const char *st */ int utf8_strncmp ( const char *a, const char* b, size_t n ) __attribute__( ( nonnull ( 1, 2 ) ) ); +/** + * The startup notification context of the application to launch + */ +typedef struct +{ + /** The name of the application */ + const gchar *name; + /** The binary name of the application */ + const gchar *binary; + /** The description of the launch */ + const gchar *description; + /** The icon name of the application */ + const gchar *icon; + /** The application id (desktop file with the .desktop suffix) */ + const gchar *app_id; + /** The window manager class of the application */ + const gchar *wmclass; + /** The command we run */ + const gchar *command; +} RofiHelperExecuteContext; + /** * @param args The arguments of the command to exec. * @param error_precmd Prefix to error message command. * @param error_cmd Error message command + * @param context The startup notification context, if any * * Executes the command * * @returns TRUE when successful, FALSE when failed. */ -gboolean helper_execute ( const char *wd, char **args, const char *error_precmd, const char *error_cmd ); +gboolean helper_execute ( const char *wd, char **args, const char *error_precmd, const char *error_cmd, RofiHelperExecuteContext *context ); /** * @param wd The work directory (optional) * @param cmd The cmd to execute * @param run_in_term Indicate if command should be run in a terminal + * @param context The startup notification context, if any * * Execute command. + * If needed members of @param context are NULL, they will be filled. * * @returns FALSE On failure, TRUE on success */ -gboolean helper_execute_command ( const char *wd, const char *cmd, int run_in_term ); +gboolean helper_execute_command ( const char *wd, const char *cmd, gboolean run_in_term, RofiHelperExecuteContext *context ); /** * @param file The file path diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index b4834c4f..f9686b99 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -185,7 +185,7 @@ static void exec_cmd_entry ( DRunModeEntry *e ) // Returns false if not found, if key not found, we don't want run in terminal. gboolean terminal = g_key_file_get_boolean ( e->key_file, "Desktop Entry", "Terminal", NULL ); - if ( helper_execute_command ( exec_path, fp, terminal ) ) { + if ( helper_execute_command ( exec_path, fp, terminal, NULL ) ) { char *path = g_build_filename ( cache_dir, DRUN_CACHE_FILE, NULL ); char *key = g_strdup_printf ( "%s:::%s", e->root, e->path ); history_set ( path, key ); @@ -511,7 +511,7 @@ static ModeMode drun_mode_result ( Mode *sw, int mretv, char **input, unsigned i exec_cmd_entry ( &( rmpd->entry_list[selected_line] ) ); } else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) { - helper_execute_command ( NULL, *input, run_in_term ); + helper_execute_command ( NULL, *input, run_in_term, NULL ); } else if ( ( mretv & MENU_ENTRY_DELETE ) && selected_line < rmpd->cmd_list_length ) { if ( selected_line < rmpd->history_length ) { diff --git a/source/dialogs/run.c b/source/dialogs/run.c index 9a19d662..0acde0a2 100644 --- a/source/dialogs/run.c +++ b/source/dialogs/run.c @@ -92,7 +92,7 @@ static void exec_cmd ( const char *cmd, int run_in_term ) } char *path = g_build_filename ( cache_dir, RUN_CACHE_FILE, NULL ); - if ( helper_execute_command ( NULL, lf_cmd, run_in_term ) ) { + if ( helper_execute_command ( NULL, lf_cmd, run_in_term, NULL ) ) { /** * This happens in non-critical time (After launching app) * It is allowed to be a bit slower. diff --git a/source/dialogs/ssh.c b/source/dialogs/ssh.c index 66fdc74a..5be70221 100644 --- a/source/dialogs/ssh.c +++ b/source/dialogs/ssh.c @@ -81,7 +81,7 @@ static inline int execshssh ( const char *host ) helper_parse_setup ( config.ssh_command, &args, &argsv, "{host}", host, NULL ); - return helper_execute ( NULL, args, "ssh ", host ); + return helper_execute ( NULL, args, "ssh ", host, NULL ); } /** diff --git a/source/helper.c b/source/helper.c index ebcf783d..2eac638e 100644 --- a/source/helper.c +++ b/source/helper.c @@ -47,6 +47,7 @@ #include #include #include +#include "display.h" #include "xcb.h" #include "helper.h" #include "helper-theme.h" @@ -962,7 +963,7 @@ int utf8_strncmp ( const char* a, const char* b, size_t n ) return r; } -gboolean helper_execute ( const char *wd, char **args, const char *error_precmd, const char *error_cmd ) +gboolean helper_execute ( const char *wd, char **args, const char *error_precmd, const char *error_cmd, RofiHelperExecuteContext *context ) { gboolean retv = TRUE; GError *error = NULL; @@ -970,6 +971,8 @@ gboolean helper_execute ( const char *wd, char **args, const char *error_precmd, GSpawnChildSetupFunc child_setup = NULL; gpointer user_data = NULL; + display_startup_notification ( context, &child_setup, &user_data ); + g_spawn_async ( wd, args, NULL, G_SPAWN_SEARCH_PATH, child_setup, user_data, NULL, &error ); if ( error != NULL ) { char *msg = g_strdup_printf ( "Failed to execute: '%s%s'\nError: '%s'", error_precmd, error_cmd, error->message ); @@ -985,7 +988,7 @@ gboolean helper_execute ( const char *wd, char **args, const char *error_precmd, return retv; } -gboolean helper_execute_command ( const char *wd, const char *cmd, int run_in_term ) +gboolean helper_execute_command ( const char *wd, const char *cmd, gboolean run_in_term, RofiHelperExecuteContext *context ) { char **args = NULL; int argc = 0; @@ -997,7 +1000,26 @@ gboolean helper_execute_command ( const char *wd, const char *cmd, int run_in_te helper_parse_setup ( config.run_command, &args, &argc, "{cmd}", cmd, NULL ); } - return helper_execute ( wd, args, "", cmd ); + if ( context != NULL ) { + if ( context->name == NULL ) { + context->name = args[0]; + } + if ( context->binary == NULL ) { + context->binary = args[0]; + } + if ( context->description == NULL ) { + gsize l = strlen ( "Launching '' via rofi" ) + strlen ( cmd ) + 1; + gchar *description = g_newa ( gchar, l ); + + g_snprintf ( description, l, "Launching '%s' via rofi", cmd ); + context->description = description; + } + if ( context->command == NULL ) { + context->command = cmd; + } + } + + return helper_execute ( wd, args, "", cmd, context ); } char *helper_get_theme_path ( const char *file ) diff --git a/source/xcb.c b/source/xcb.c index 13dbdd6a..57130c5d 100644 --- a/source/xcb.c +++ b/source/xcb.c @@ -359,6 +359,10 @@ void display_dump_monitor_layout ( void ) } } +void display_startup_notification ( RofiHelperExecuteContext *context, GSpawnChildSetupFunc *child_setup, gpointer *user_data ) +{ +} + static int monitor_get_dimension ( int monitor_id, workarea *mon ) { memset ( mon, 0, sizeof ( workarea ) ); diff --git a/test/helper-config-cmdline-parser.c b/test/helper-config-cmdline-parser.c index 741230cb..3e1ddcb5 100644 --- a/test/helper-config-cmdline-parser.c +++ b/test/helper-config-cmdline-parser.c @@ -32,6 +32,7 @@ #include #include #include +#include "display.h" #include "xcb.h" #include "xcb-internal.h" #include "rofi.h" @@ -65,6 +66,10 @@ int monitor_active ( G_GNUC_UNUSED workarea *mon ) return 0; } +void display_startup_notification ( G_GNUC_UNUSED RofiHelperExecuteContext *context, G_GNUC_UNUSED GSpawnChildSetupFunc *child_setup, G_GNUC_UNUSED gpointer *user_data ) +{ +} + int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char ** argv ) { diff --git a/test/helper-expand.c b/test/helper-expand.c index 09760feb..628ffc7e 100644 --- a/test/helper-expand.c +++ b/test/helper-expand.c @@ -32,6 +32,7 @@ #include #include #include +#include "display.h" #include "xcb.h" #include "xcb-internal.h" #include "rofi.h" @@ -66,6 +67,10 @@ int monitor_active ( G_GNUC_UNUSED workarea *mon ) return 0; } +void display_startup_notification ( G_GNUC_UNUSED RofiHelperExecuteContext *context, G_GNUC_UNUSED GSpawnChildSetupFunc *child_setup, G_GNUC_UNUSED gpointer *user_data ) +{ +} + int main ( int argc, char ** argv ) { cmd_set_arguments ( argc, argv ); diff --git a/test/helper-pidfile.c b/test/helper-pidfile.c index d01b5a66..9a5470cd 100644 --- a/test/helper-pidfile.c +++ b/test/helper-pidfile.c @@ -32,6 +32,7 @@ #include #include #include +#include "display.h" #include "xcb.h" #include "xcb-internal.h" #include "rofi.h" @@ -56,6 +57,10 @@ int monitor_active ( G_GNUC_UNUSED workarea *mon ) return 0; } +void display_startup_notification ( G_GNUC_UNUSED RofiHelperExecuteContext *context, G_GNUC_UNUSED GSpawnChildSetupFunc *child_setup, G_GNUC_UNUSED gpointer *user_data ) +{ +} + int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char ** argv ) { if ( setlocale ( LC_ALL, "" ) == NULL ) { diff --git a/test/helper-test.c b/test/helper-test.c index 6a3cf2de..1ba581c8 100644 --- a/test/helper-test.c +++ b/test/helper-test.c @@ -32,6 +32,7 @@ #include #include #include +#include "display.h" #include "xcb.h" #include "xcb-internal.h" #include "rofi.h" @@ -75,6 +76,10 @@ int monitor_active ( G_GNUC_UNUSED workarea *mon ) return 0; } +void display_startup_notification ( G_GNUC_UNUSED RofiHelperExecuteContext *context, G_GNUC_UNUSED GSpawnChildSetupFunc *child_setup, G_GNUC_UNUSED gpointer *user_data ) +{ +} + int main ( int argc, char ** argv ) { cmd_set_arguments ( argc, argv ); diff --git a/test/helper-tokenize.c b/test/helper-tokenize.c index 87212955..c251f04e 100644 --- a/test/helper-tokenize.c +++ b/test/helper-tokenize.c @@ -32,6 +32,7 @@ #include #include #include +#include "display.h" #include "xcb.h" #include "xcb-internal.h" #include "rofi.h" @@ -56,6 +57,10 @@ int monitor_active ( G_GNUC_UNUSED workarea *mon ) return 0; } +void display_startup_notification ( G_GNUC_UNUSED RofiHelperExecuteContext *context, G_GNUC_UNUSED GSpawnChildSetupFunc *child_setup, G_GNUC_UNUSED gpointer *user_data ) +{ +} + int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char ** argv ) { if ( setlocale ( LC_ALL, "" ) == NULL ) { diff --git a/test/mode-test.c b/test/mode-test.c index 25f51cb1..00720d95 100644 --- a/test/mode-test.c +++ b/test/mode-test.c @@ -38,6 +38,7 @@ #include #include #include "rofi.h" +#include "display.h" #include "xcb.h" #include #include @@ -73,6 +74,11 @@ gboolean rofi_view_trigger_action ( G_GNUC_UNUSED RofiViewState *state, G_GNUC_U { return FALSE; } + +void display_startup_notification ( G_GNUC_UNUSED RofiHelperExecuteContext *context, G_GNUC_UNUSED GSpawnChildSetupFunc *child_setup, G_GNUC_UNUSED gpointer *user_data ) +{ +} + #ifndef _ck_assert_ptr_null /* Pointer against NULL comparison macros with improved output * compared to ck_assert(). */ diff --git a/test/textbox-test.c b/test/textbox-test.c index 539a6a54..edb2d0ff 100644 --- a/test/textbox-test.c +++ b/test/textbox-test.c @@ -37,6 +37,7 @@ #include #include #include +#include "display.h" #include "xcb.h" #include "settings.h" #include "xrmoptions.h" @@ -76,6 +77,10 @@ int monitor_active ( G_GNUC_UNUSED workarea *mon ) return 0; } +void display_startup_notification ( G_GNUC_UNUSED RofiHelperExecuteContext *context, G_GNUC_UNUSED GSpawnChildSetupFunc *child_setup, G_GNUC_UNUSED gpointer *user_data ) +{ +} + int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) { cairo_surface_t *surf = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, 100, 100 ); diff --git a/test/theme-parser-test.c b/test/theme-parser-test.c index 4707f8d3..c84bba61 100644 --- a/test/theme-parser-test.c +++ b/test/theme-parser-test.c @@ -35,6 +35,7 @@ #include "xcb-internal.h" #include "rofi.h" #include "settings.h" +#include "display.h" #include "xcb.h" #include "theme.h" #include "css-colors.h" @@ -70,6 +71,10 @@ int monitor_active ( G_GNUC_UNUSED workarea *mon ) return 0; } +void display_startup_notification ( G_GNUC_UNUSED RofiHelperExecuteContext *context, G_GNUC_UNUSED GSpawnChildSetupFunc *child_setup, G_GNUC_UNUSED gpointer *user_data ) +{ +} + #ifndef _ck_assert_ptr_null /* Pointer against NULL comparison macros with improved output * compared to ck_assert(). */ diff --git a/test/widget-test.c b/test/widget-test.c index 49c5b6ac..78cd4c4a 100644 --- a/test/widget-test.c +++ b/test/widget-test.c @@ -35,6 +35,7 @@ #include #include #include "rofi.h" +#include "display.h" #include "xrmoptions.h" #include "xcb.h" unsigned int test =0; @@ -66,6 +67,10 @@ int rofi_view_error_dialog ( const char *msg, G_GNUC_UNUSED int markup ) return FALSE; } +void display_startup_notification ( G_GNUC_UNUSED RofiHelperExecuteContext *context, G_GNUC_UNUSED GSpawnChildSetupFunc *child_setup, G_GNUC_UNUSED gpointer *user_data ) +{ +} + int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) { // box 20 by 40 -- cgit v1.2.3 From 22fbaa0b50bc65f531a177a324d63e89702051db Mon Sep 17 00:00:00 2001 From: Quentin Glidic Date: Fri, 2 Jun 2017 14:55:36 +0200 Subject: drun: Keep the app_id around Signed-off-by: Quentin Glidic --- source/dialogs/drun.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index f9686b99..eea2a9d6 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -66,6 +66,8 @@ typedef struct char *root; /* Path to desktop file */ char *path; + /* Application id (.desktop filename) */ + char *app_id; /* Icon stuff */ char *icon_name; cairo_surface_t *icon; @@ -199,7 +201,7 @@ static void exec_cmd_entry ( DRunModeEntry *e ) /** * This function absorbs/freeś path, so this is no longer available afterwards. */ -static gboolean read_desktop_file ( DRunModePrivateData *pd, const char *root, const char *path ) +static gboolean read_desktop_file ( DRunModePrivateData *pd, const char *root, const char *path, const gchar *basename ) { // Create ID on stack. // We know strlen (path ) > strlen(root)+1 @@ -275,8 +277,9 @@ static gboolean read_desktop_file ( DRunModePrivateData *pd, const char *root, c pd->cmd_list_length_actual += 256; pd->entry_list = g_realloc ( pd->entry_list, pd->cmd_list_length_actual * sizeof ( *( pd->entry_list ) ) ); } - pd->entry_list[pd->cmd_list_length].root = g_strdup ( root ); - pd->entry_list[pd->cmd_list_length].path = g_strdup ( path ); + pd->entry_list[pd->cmd_list_length].root = g_strdup ( root ); + pd->entry_list[pd->cmd_list_length].path = g_strdup ( path ); + pd->entry_list[pd->cmd_list_length].app_id = g_strndup ( basename, strlen ( basename ) - strlen ( ".desktop" ) ); gchar *n = g_key_file_get_locale_string ( kf, "Desktop Entry", "Name", NULL, NULL ); pd->entry_list[pd->cmd_list_length].name = n; gchar *gn = g_key_file_get_locale_string ( kf, "Desktop Entry", "GenericName", NULL, NULL ); @@ -353,7 +356,7 @@ static void walk_dir ( DRunModePrivateData *pd, const char *root, const char *di case DT_REG: // Skip files not ending on .desktop. if ( g_str_has_suffix ( file->d_name, ".desktop" ) ) { - read_desktop_file ( pd, root, filename ); + read_desktop_file ( pd, root, filename, file->d_name ); } break; case DT_DIR: @@ -388,7 +391,8 @@ static void get_apps_history ( DRunModePrivateData *pd ) for ( unsigned int index = 0; index < length; index++ ) { char **st = g_strsplit ( retv[index], ":::", 2 ); if ( st && st[0] && st[1] ) { - if ( !read_desktop_file ( pd, st[0], st[1] ) ) { + const gchar *basename = g_utf8_strrchr ( st[1], -1, G_DIR_SEPARATOR ); + if ( basename == NULL || !read_desktop_file ( pd, st[0], st[1], ++basename ) ) { history_remove ( path, retv[index] ); } } @@ -478,6 +482,7 @@ static void drun_entry_clear ( DRunModeEntry *e ) { g_free ( e->root ); g_free ( e->path ); + g_free ( e->app_id ); if ( e->icon != NULL ) { cairo_surface_destroy ( e->icon ); } -- cgit v1.2.3 From 0644f99b64ff150699bedd1a8263be66059530d7 Mon Sep 17 00:00:00 2001 From: Quentin Glidic Date: Fri, 2 Jun 2017 14:56:59 +0200 Subject: drun: Add startup notification support Signed-off-by: Quentin Glidic --- source/dialogs/drun.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index eea2a9d6..5360356c 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -185,15 +185,27 @@ static void exec_cmd_entry ( DRunModeEntry *e ) exec_path = NULL; } + RofiHelperExecuteContext context = { + .name = e->name, + .icon = e->icon_name, + .app_id = e->app_id, + }; + gboolean sn = g_key_file_get_boolean ( e->key_file, "Desktop Entry", "StartupNotify", NULL ); + gchar *wmclass = NULL; + if ( sn && g_key_file_has_key ( e->key_file, "Desktop Entry", "StartupWMClass", NULL ) ) { + context.wmclass = wmclass = g_key_file_get_string ( e->key_file, "Desktop Entry", "StartupWMClass", NULL ); + } + // Returns false if not found, if key not found, we don't want run in terminal. gboolean terminal = g_key_file_get_boolean ( e->key_file, "Desktop Entry", "Terminal", NULL ); - if ( helper_execute_command ( exec_path, fp, terminal, NULL ) ) { + if ( helper_execute_command ( exec_path, fp, terminal, sn ? &context : NULL ) ) { char *path = g_build_filename ( cache_dir, DRUN_CACHE_FILE, NULL ); char *key = g_strdup_printf ( "%s:::%s", e->root, e->path ); history_set ( path, key ); g_free ( key ); g_free ( path ); } + g_free ( wmclass ); g_free ( exec_path ); g_free ( str ); g_free ( fp ); @@ -516,7 +528,9 @@ static ModeMode drun_mode_result ( Mode *sw, int mretv, char **input, unsigned i exec_cmd_entry ( &( rmpd->entry_list[selected_line] ) ); } else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) { - helper_execute_command ( NULL, *input, run_in_term, NULL ); + RofiHelperExecuteContext context = { .name = NULL }; + // FIXME: We assume startup notification in terminals, not in others + helper_execute_command ( NULL, *input, run_in_term, run_in_term ? &context : NULL ); } else if ( ( mretv & MENU_ENTRY_DELETE ) && selected_line < rmpd->cmd_list_length ) { if ( selected_line < rmpd->history_length ) { -- cgit v1.2.3 From 3f8af0d7c5c200914252d51146e387226f5d240d Mon Sep 17 00:00:00 2001 From: Quentin Glidic Date: Fri, 2 Jun 2017 14:57:19 +0200 Subject: run: Add startup notification support Signed-off-by: Quentin Glidic --- source/dialogs/run.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/dialogs/run.c b/source/dialogs/run.c index 0acde0a2..8b20c290 100644 --- a/source/dialogs/run.c +++ b/source/dialogs/run.c @@ -92,7 +92,9 @@ static void exec_cmd ( const char *cmd, int run_in_term ) } char *path = g_build_filename ( cache_dir, RUN_CACHE_FILE, NULL ); - if ( helper_execute_command ( NULL, lf_cmd, run_in_term, NULL ) ) { + RofiHelperExecuteContext context = { .name = NULL }; + // FIXME: assume startup notification support for terminals + if ( helper_execute_command ( NULL, lf_cmd, run_in_term, run_in_term ? &context : NULL ) ) { /** * This happens in non-critical time (After launching app) * It is allowed to be a bit slower. -- cgit v1.2.3 From a6f51393d3c732e1de782784623661d5028e5c81 Mon Sep 17 00:00:00 2001 From: Quentin Glidic Date: Fri, 2 Jun 2017 14:57:28 +0200 Subject: ssh: Add startup notification support Signed-off-by: Quentin Glidic --- source/dialogs/ssh.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source/dialogs/ssh.c b/source/dialogs/ssh.c index 5be70221..ccba8eb9 100644 --- a/source/dialogs/ssh.c +++ b/source/dialogs/ssh.c @@ -81,7 +81,17 @@ static inline int execshssh ( const char *host ) helper_parse_setup ( config.ssh_command, &args, &argsv, "{host}", host, NULL ); - return helper_execute ( NULL, args, "ssh ", host, NULL ); + gsize l = strlen ( "Connecting to '' via rofi" ) + strlen ( host ) + 1; + gchar *desc = g_newa ( gchar, l ); + + g_snprintf ( desc, l, "Connecting to '%s' via rofi", host ); + + RofiHelperExecuteContext context = { + .name = "ssh", + .description = desc, + .command = "ssh", + }; + return helper_execute ( NULL, args, "ssh ", host, &context ); } /** -- cgit v1.2.3 From 76a6e312fe1d86c7a29e3839d1c0311e9c583c18 Mon Sep 17 00:00:00 2001 From: Quentin Glidic Date: Fri, 2 Jun 2017 14:57:51 +0200 Subject: xcb: Add startup notification support Signed-off-by: Quentin Glidic --- include/xcb-internal.h | 7 ++++--- source/xcb.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/include/xcb-internal.h b/include/xcb-internal.h index d01f110a..d03807bf 100644 --- a/include/xcb-internal.h +++ b/include/xcb-internal.h @@ -57,9 +57,10 @@ struct _xcb_stuff uint8_t first_event; /** Keyboard device id */ int32_t device_id; - } xkb; - NkBindingsSeat *bindings_seat; - gboolean mouse_seen; + } xkb; + xcb_timestamp_t last_timestamp; + NkBindingsSeat *bindings_seat; + gboolean mouse_seen; }; #endif diff --git a/source/xcb.c b/source/xcb.c index 57130c5d..7bc80a84 100644 --- a/source/xcb.c +++ b/source/xcb.c @@ -49,6 +49,10 @@ #include #include #include +#define SN_API_NOT_YET_FROZEN +/* This function is declared as sn_launcher_context_set_application_id but implemented as sn_launcher_set_application_id */ +#define sn_launcher_context_set_application_id sn_launcher_set_application_id +#include #include "display.h" #include "xcb-internal.h" #include "xcb.h" @@ -361,6 +365,41 @@ void display_dump_monitor_layout ( void ) void display_startup_notification ( RofiHelperExecuteContext *context, GSpawnChildSetupFunc *child_setup, gpointer *user_data ) { + if ( context == NULL ) { + return; + } + + SnLauncherContext *sncontext; + + sncontext = sn_launcher_context_new ( xcb->sndisplay, xcb->screen_nbr ); + + sn_launcher_context_set_name ( sncontext, context->name ); + sn_launcher_context_set_description ( sncontext, context->description ); + if ( context->binary != NULL ) { + sn_launcher_context_set_binary_name ( sncontext, context->binary ); + } + if ( context->icon != NULL ) { + sn_launcher_context_set_icon_name ( sncontext, context->icon ); + } + if ( context->app_id != NULL ) { + sn_launcher_context_set_application_id ( sncontext, context->app_id ); + } + if ( context->wmclass != NULL ) { + sn_launcher_context_set_wmclass ( sncontext, context->wmclass ); + } + + xcb_get_property_cookie_t c; + unsigned int current_desktop = 0; + + c = xcb_ewmh_get_current_desktop ( &xcb->ewmh, xcb->screen_nbr ); + if ( xcb_ewmh_get_current_desktop_reply ( &xcb->ewmh, c, ¤t_desktop, NULL ) ) { + sn_launcher_context_set_workspace ( sncontext, current_desktop ); + } + + sn_launcher_context_initiate ( sncontext, "rofi", context->command, xcb->last_timestamp ); + + *child_setup = (GSpawnChildSetupFunc) sn_launcher_context_setup_child_process; + *user_data = sncontext; } static int monitor_get_dimension ( int monitor_id, workarea *mon ) @@ -601,6 +640,7 @@ static void main_loop_x11_event_handler_view ( xcb_generic_event_t *event ) case XCB_BUTTON_PRESS: { xcb_button_press_event_t *bpe = (xcb_button_press_event_t *) event; + xcb->last_timestamp = bpe->time; rofi_view_handle_mouse_motion ( state, bpe->event_x, bpe->event_y ); nk_bindings_seat_handle_button ( xcb->bindings_seat, bpe->detail, NK_BINDINGS_BUTTON_STATE_PRESS, bpe->time ); break; @@ -608,6 +648,7 @@ static void main_loop_x11_event_handler_view ( xcb_generic_event_t *event ) case XCB_BUTTON_RELEASE: { xcb_button_release_event_t *bre = (xcb_button_release_event_t *) event; + xcb->last_timestamp = bre->time; nk_bindings_seat_handle_button ( xcb->bindings_seat, bre->detail, NK_BINDINGS_BUTTON_STATE_RELEASE, bre->time ); if ( config.click_to_exit == TRUE ) { if ( ! xcb->mouse_seen ) { @@ -639,8 +680,9 @@ static void main_loop_x11_event_handler_view ( xcb_generic_event_t *event ) xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) event; gchar *text; - text = nk_bindings_seat_handle_key ( xcb->bindings_seat, xkpe->detail, NK_BINDINGS_KEY_STATE_PRESS ); - if ( text != NULL ) { + xcb->last_timestamp = xkpe->time; + text = nk_bindings_seat_handle_key ( xcb->bindings_seat, xkpe->detail, NK_BINDINGS_KEY_STATE_PRESS ); + if ( text != NULL ) { rofi_view_handle_text ( state, text ); } break; @@ -648,6 +690,7 @@ static void main_loop_x11_event_handler_view ( xcb_generic_event_t *event ) case XCB_KEY_RELEASE: { xcb_key_release_event_t *xkre = (xcb_key_release_event_t *) event; + xcb->last_timestamp = xkre->time; nk_bindings_seat_handle_key ( xcb->bindings_seat, xkre->detail, NK_BINDINGS_KEY_STATE_RELEASE ); break; } -- cgit v1.2.3