diff --git a/etc/root-menu.plist b/etc/root-menu.plist index abeec8c..20d7f86 100644 --- a/etc/root-menu.plist +++ b/etc/root-menu.plist @@ -1,5 +1,6 @@ // Definition of root menu. Follows Window Maker plist order. ("Root Menu", + ("Launch Terminal", Execute, "/usr/bin/foot"), ("Previous Workspace", WorkspacePrevious), ("Next Workspace", WorkspaceNext), ("Lock", LockScreen), diff --git a/src/action.c b/src/action.c index 22cd394..b82c352 100644 --- a/src/action.c +++ b/src/action.c @@ -100,6 +100,7 @@ const wlmcfg_enum_desc_t wlmaker_action_desc[] = { WLMCFG_ENUM("InhibitLockBegin", WLMAKER_ACTION_LOCK_INHIBIT_BEGIN), WLMCFG_ENUM("InhibitLockEnd", WLMAKER_ACTION_LOCK_INHIBIT_END), WLMCFG_ENUM("LaunchTerminal", WLMAKER_ACTION_LAUNCH_TERMINAL), + WLMCFG_ENUM("Execute", WLMAKER_ACTION_EXECUTE), WLMCFG_ENUM("WorkspacePrevious", WLMAKER_ACTION_WORKSPACE_TO_PREVIOUS), WLMCFG_ENUM("WorkspaceNext", WLMAKER_ACTION_WORKSPACE_TO_NEXT), @@ -178,7 +179,8 @@ void wlmaker_action_unbind_keys(wlmaker_action_handle_t *handle_ptr) /* ------------------------------------------------------------------------- */ void wlmaker_action_execute(wlmaker_server_t *server_ptr, - wlmaker_action_t action) + wlmaker_action_t action, + void *arg_ptr) { wlmtk_workspace_t *workspace_ptr, *next_workspace_ptr; wlmtk_window_t *window_ptr; @@ -211,6 +213,14 @@ void wlmaker_action_execute(wlmaker_server_t *server_ptr, } break; + case WLMAKER_ACTION_EXECUTE: + if (NULL == arg_ptr) { + bs_log(BS_ERROR, "Invalid argument NULL for 'Execute'."); + } else if (0 == fork()) { + execl("/bin/sh", "/bin/sh", "-c", arg_ptr, (void *)NULL); + } + break; + case WLMAKER_ACTION_WORKSPACE_TO_PREVIOUS: wlmtk_root_switch_to_previous_workspace(server_ptr->root_ptr); break; @@ -523,7 +533,8 @@ bool _wlmaker_action_bound_callback(const wlmaker_key_combo_t *key_combo_ptr) wlmaker_action_execute( action_binding_ptr->handle_ptr->server_ptr, - action_binding_ptr->action); + action_binding_ptr->action, + NULL); return true; } diff --git a/src/action.h b/src/action.h index f76cd31..c686662 100644 --- a/src/action.h +++ b/src/action.h @@ -35,6 +35,7 @@ typedef enum { WLMAKER_ACTION_LOCK_INHIBIT_BEGIN, WLMAKER_ACTION_LOCK_INHIBIT_END, WLMAKER_ACTION_LAUNCH_TERMINAL, + WLMAKER_ACTION_EXECUTE, WLMAKER_ACTION_WORKSPACE_TO_PREVIOUS, WLMAKER_ACTION_WORKSPACE_TO_NEXT, @@ -104,10 +105,12 @@ void wlmaker_action_unbind_keys(wlmaker_action_handle_t *handle_ptr); * * @param server_ptr * @param action + * @param arg_ptr */ void wlmaker_action_execute( wlmaker_server_t *server_ptr, - wlmaker_action_t action); + wlmaker_action_t action, + void *arg_ptr); /** Unit test cases. */ extern const bs_test_case_t wlmaker_action_test_cases[]; diff --git a/src/action_item.c b/src/action_item.c index dd0ae13..38dbc5b 100644 --- a/src/action_item.c +++ b/src/action_item.c @@ -29,6 +29,8 @@ struct _wlmaker_action_item_t { /** Action to execute when triggered. */ wlmaker_action_t action; + /** Argument for the action. May be NULL. */ + char *action_arg_ptr; /** Back-link to @ref wlmaker_server_t, for executing the action. */ wlmaker_server_t *server_ptr; @@ -52,6 +54,7 @@ wlmaker_action_item_t *wlmaker_action_item_create( const char *text_ptr, const wlmtk_menu_item_style_t *style_ptr, wlmaker_action_t action, + const char *action_arg_ptr, wlmaker_server_t *server_ptr, wlmtk_env_t *env_ptr) { @@ -59,6 +62,13 @@ wlmaker_action_item_t *wlmaker_action_item_create( 1, sizeof(wlmaker_action_item_t)); if (NULL == action_item_ptr) return NULL; action_item_ptr->action = action; + if (NULL != action_arg_ptr) { + action_item_ptr->action_arg_ptr = logged_strdup(action_arg_ptr); + if (NULL == action_item_ptr->action_arg_ptr) { + wlmaker_action_item_destroy(action_item_ptr); + return NULL; + } + } action_item_ptr->server_ptr = server_ptr; action_item_ptr->menu_item_ptr = wlmtk_menu_item_create(style_ptr, env_ptr); @@ -95,6 +105,7 @@ wlmaker_action_item_t *wlmaker_action_item_create_from_desc( desc_ptr->text_ptr, style_ptr, desc_ptr->action, + NULL, server_ptr, env_ptr); if (NULL == action_item_ptr) return NULL; @@ -114,6 +125,11 @@ void wlmaker_action_item_destroy(wlmaker_action_item_t *action_item_ptr) wlmtk_menu_item_destroy(action_item_ptr->menu_item_ptr); action_item_ptr->menu_item_ptr = NULL; } + + if (NULL != action_item_ptr->action_arg_ptr) { + free(action_item_ptr->action_arg_ptr); + action_item_ptr->action_arg_ptr = NULL; + } free(action_item_ptr); } @@ -137,7 +153,8 @@ void _wlmaker_action_item_handle_triggered( wlmaker_action_execute( action_item_ptr->server_ptr, - action_item_ptr->action); + action_item_ptr->action, + action_item_ptr->action_arg_ptr); if (NULL != action_item_ptr->server_ptr->root_menu_ptr) { wlmtk_menu_set_open( @@ -178,7 +195,7 @@ const bs_test_case_t wlmaker_action_item_test_cases[] = { static const wlmtk_menu_style_t _wlmaker_action_item_menu_style = {}; /** Test data: Descriptor for the action item used in tests. */ static const wlmaker_action_item_desc_t _wlmaker_action_item_desc = { - "text", 42, 0 + "text", 42, NULL, 0 }; /* ------------------------------------------------------------------------- */ diff --git a/src/action_item.h b/src/action_item.h index c3472a2..d7fb985 100644 --- a/src/action_item.h +++ b/src/action_item.h @@ -37,6 +37,8 @@ typedef struct { const char *text_ptr; /** The action to trigger. */ wlmaker_action_t action; + /** Extra argument for @ref wlmaker_action_execute. */ + char *action_arg_ptr; /** * Where to store the @ref wlmaker_action_item_t, relative to the * `dest_ptr` argument of @ref wlmaker_action_item_create_from_desc. @@ -50,6 +52,7 @@ typedef struct { * @param text_ptr * @param style_ptr * @param action + * @param action_arg_ptr Extra argument. Will be duplicated. * @param server_ptr * @param env_ptr * @@ -59,6 +62,7 @@ wlmaker_action_item_t *wlmaker_action_item_create( const char *text_ptr, const wlmtk_menu_item_style_t *style_ptr, wlmaker_action_t action, + const char *action_arg_ptr, wlmaker_server_t *server_ptr, wlmtk_env_t *env_ptr); diff --git a/src/corner.c b/src/corner.c index b76c0a1..631e0a3 100644 --- a/src/corner.c +++ b/src/corner.c @@ -245,7 +245,7 @@ void _wlmaker_corner_clear(wlmaker_corner_t *corner_ptr) break; default: break; } - wlmaker_action_execute(corner_ptr->server_ptr, action); + wlmaker_action_execute(corner_ptr->server_ptr, action, NULL); corner_ptr->corner_triggered = false; } corner_ptr->current_corner = 0; @@ -349,7 +349,7 @@ int _wlmaker_corner_handle_timer(void *data_ptr) break; default: break; } - wlmaker_action_execute(corner_ptr->server_ptr, action); + wlmaker_action_execute(corner_ptr->server_ptr, action, NULL); return 0; } diff --git a/src/root_menu.c b/src/root_menu.c index 892a610..8d62e34 100644 --- a/src/root_menu.c +++ b/src/root_menu.c @@ -293,10 +293,16 @@ wlmaker_action_item_t *_wlmaker_root_menu_create_action_item_from_array( } } + const char *action_arg_ptr = NULL; + if (2 < wlmcfg_array_size(array_ptr)) { + action_arg_ptr = wlmcfg_array_string_value_at(array_ptr, 2); + } + wlmaker_action_item_t *action_item_ptr = wlmaker_action_item_create( name_ptr, &menu_style_ptr->item, action, + action_arg_ptr, server_ptr, server_ptr->env_ptr); if (NULL == action_item_ptr) { diff --git a/src/tl_menu.c b/src/tl_menu.c index d81b8f9..38a5020 100644 --- a/src/tl_menu.c +++ b/src/tl_menu.c @@ -103,42 +103,49 @@ static const wlmaker_action_item_desc_t _tl_menu_items[] = { { "Maximize", WLMAKER_ACTION_WINDOW_MAXIMIZE, + NULL, offsetof(wlmaker_tl_menu_t, maximize_ai_ptr) }, { "Unmaximize", WLMAKER_ACTION_WINDOW_UNMAXIMIZE, + NULL, offsetof(wlmaker_tl_menu_t, unmaximize_ai_ptr) }, { "Fullscreen", WLMAKER_ACTION_WINDOW_TOGGLE_FULLSCREEN, + NULL, offsetof(wlmaker_tl_menu_t, fullscreen_ai_ptr) }, { "Shade", WLMAKER_ACTION_WINDOW_SHADE, + NULL, offsetof(wlmaker_tl_menu_t, shade_ai_ptr) }, { "Unshade", WLMAKER_ACTION_WINDOW_UNSHADE, + NULL, offsetof(wlmaker_tl_menu_t, unshade_ai_ptr) }, { "Move to workspace ...", WLMAKER_ACTION_NONE, + NULL, offsetof(wlmaker_tl_menu_t, move_to_ws_ai_ptr) }, { "Close", WLMAKER_ACTION_WINDOW_CLOSE, + NULL, offsetof(wlmaker_tl_menu_t, close_ai_ptr) }, - { NULL, 0, 0 } // Sentinel. + { NULL, 0, NULL, 0 } // Sentinel. }; /* == Exported methods ===================================================== */