labwc/src/action.c

261 lines
6 KiB
C
Raw Normal View History

2021-09-24 21:45:48 +01:00
// SPDX-License-Identifier: GPL-2.0-only
2020-09-25 19:42:40 +01:00
#include <strings.h>
#include <wlr/util/log.h>
#include <signal.h>
#include "common/spawn.h"
#include "common/zfree.h"
2020-09-25 20:05:20 +01:00
#include "labwc.h"
#include "menu/menu.h"
2022-01-26 02:54:03 +01:00
#include "ssd.h"
#include "action.h"
enum action_type {
ACTION_TYPE_NONE = 0,
ACTION_TYPE_CLOSE,
ACTION_TYPE_DEBUG,
ACTION_TYPE_EXECUTE,
ACTION_TYPE_EXIT,
ACTION_TYPE_MOVE_TO_EDGE,
ACTION_TYPE_SNAP_TO_EDGE,
ACTION_TYPE_NEXT_WINDOW,
ACTION_TYPE_PREVIOUS_WINDOW,
ACTION_TYPE_RECONFIGURE,
ACTION_TYPE_SHOW_MENU,
ACTION_TYPE_TOGGLE_MAXIMIZE,
ACTION_TYPE_TOGGLE_FULLSCREEN,
ACTION_TYPE_TOGGLE_DECORATIONS,
ACTION_TYPE_FOCUS,
ACTION_TYPE_ICONIFY,
ACTION_TYPE_MOVE,
ACTION_TYPE_RAISE,
ACTION_TYPE_RESIZE,
};
const char *action_names[] = {
"NoOp",
"Close",
"Debug",
"Execute",
"Exit",
"MoveToEdge",
"SnapToEdge",
"NextWindow",
"PreviousWindow",
"Reconfigure",
"ShowMenu",
"ToggleMaximize",
"ToggleFullscreen",
"ToggleDecorations",
"Focus",
"Iconify",
"Move",
"Raise",
"Resize",
NULL
};
static enum action_type
action_type_from_str(const char *action_name)
{
2022-01-05 21:23:01 +00:00
for (size_t i = 1; action_names[i] != NULL; i++) {
if (!strcasecmp(action_name, action_names[i])) {
return i;
}
}
wlr_log(WLR_ERROR, "Invalid action: %s", action_name);
return ACTION_TYPE_NONE;
}
struct action *
action_create(const char *action_name)
{
if (!action_name) {
wlr_log(WLR_ERROR, "action name not specified");
return NULL;
}
struct action *action = calloc(1, sizeof(struct action));
action->type = action_type_from_str(action_name);
return action;
}
void action_list_free(struct wl_list *action_list) {
struct action *action, *action_tmp;
wl_list_for_each_safe(action, action_tmp, action_list, link) {
wl_list_remove(&action->link);
zfree(action->arg);
zfree(action);
}
}
static void
2022-01-26 00:07:10 +01:00
show_menu(struct server *server, struct view *view, const char *menu_name)
{
2022-01-26 00:07:10 +01:00
struct menu *menu = NULL;
bool force_menu_top_left = false;
if (!menu_name) {
return;
}
2022-01-26 00:07:10 +01:00
if (!strcasecmp(menu_name, "root-menu")) {
menu = server->rootmenu;
server->windowmenu->visible = false;
} else if (!strcasecmp(menu_name, "client-menu") && view) {
menu = server->windowmenu;
server->rootmenu->visible = false;
2022-01-26 02:54:03 +01:00
enum ssd_part_type type = ssd_at(view, server->seat.cursor->x,
server->seat.cursor->y);
if (type == LAB_SSD_BUTTON_WINDOW_MENU) {
force_menu_top_left = true;
} else if (ssd_part_contains(LAB_SSD_PART_TITLEBAR, type)) {
force_menu_top_left = false;
} else {
force_menu_top_left = true;
}
2022-01-26 00:07:10 +01:00
} else {
return;
}
2022-01-26 00:07:10 +01:00
menu->visible = true;
server->input_mode = LAB_INPUT_STATE_MENU;
int x, y;
if (force_menu_top_left) {
x = view->x;
y = view->y;
} else {
x = server->seat.cursor->x;
y = server->seat.cursor->y;
}
menu_move(menu, x, y);
2021-01-09 22:51:20 +00:00
damage_all_outputs(server);
}
2020-06-18 20:18:01 +01:00
static struct view *
activator_or_focused_view(struct view *activator, struct server *server)
{
return activator ? activator : desktop_focused_view(server);
}
void
action(struct view *activator, struct server *server, struct wl_list *actions, uint32_t resize_edges)
2020-06-18 20:18:01 +01:00
{
if (!actions) {
wlr_log(WLR_ERROR, "empty actions");
2020-06-18 20:18:01 +01:00
return;
}
struct view *view;
struct action *action;
wl_list_for_each(action, actions, link) {
wlr_log(WLR_DEBUG, "Handling action %s (%u) with arg %s",
action_names[action->type], action->type, action->arg);
/* Refetch view because it may have been changed due to the previous action */
view = activator_or_focused_view(activator, server);
2022-01-05 21:23:01 +00:00
switch (action->type) {
case ACTION_TYPE_CLOSE:
if (view) {
view_close(view);
}
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_DEBUG:
/* nothing */
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_EXECUTE:
{
struct buf cmd;
buf_init(&cmd);
buf_add(&cmd, action->arg);
buf_expand_shell_variables(&cmd);
spawn_async_no_shell(cmd.buf);
free(cmd.buf);
}
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_EXIT:
wl_display_terminate(server->wl_display);
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_MOVE_TO_EDGE:
view_move_to_edge(view, action->arg);
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_SNAP_TO_EDGE:
view_snap_to_edge(view, action->arg);
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_NEXT_WINDOW:
server->cycle_view =
desktop_cycle_view(server, server->cycle_view, LAB_CYCLE_DIR_FORWARD);
osd_update(server);
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_PREVIOUS_WINDOW:
server->cycle_view =
desktop_cycle_view(server, server->cycle_view, LAB_CYCLE_DIR_BACKWARD);
osd_update(server);
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_RECONFIGURE:
kill(getpid(), SIGHUP);
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_SHOW_MENU:
2022-01-26 00:07:10 +01:00
show_menu(server, view, action->arg);
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_TOGGLE_MAXIMIZE:
if (view) {
view_toggle_maximize(view);
}
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_TOGGLE_FULLSCREEN:
if (view) {
view_toggle_fullscreen(view);
}
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_TOGGLE_DECORATIONS:
if (view) {
view_toggle_decorations(view);
}
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_FOCUS:
view = desktop_view_at_cursor(server);
if (view) {
desktop_focus_and_activate_view(&server->seat, view);
damage_all_outputs(server);
}
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_ICONIFY:
if (view) {
view_minimize(view, true);
}
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_MOVE:
view = desktop_view_at_cursor(server);
if (view) {
interactive_begin(view, LAB_INPUT_STATE_MOVE, 0);
}
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_RAISE:
if (view) {
desktop_move_to_front(view);
damage_all_outputs(server);
}
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_RESIZE:
view = desktop_view_at_cursor(server);
if (view) {
interactive_begin(view, LAB_INPUT_STATE_RESIZE, resize_edges);
}
break;
2022-01-05 21:23:01 +00:00
case ACTION_TYPE_NONE:
wlr_log(WLR_ERROR, "Not executing unknown action with arg %s", action->arg);
break;
2022-01-05 21:23:01 +00:00
default:
/*
* If we get here it must be a BUG caused most likely by
* action_names and action_type being out of sync or by
* adding a new action without installing a handler here.
*/
wlr_log(WLR_ERROR, "Not executing invalid action (%u) with arg %s"
2022-01-05 21:23:01 +00:00
" This is a BUG. Please report.", action->type, action->arg);
2021-07-13 21:54:22 +01:00
}
2020-06-18 20:18:01 +01:00
}
}