diff --git a/src/action.c b/src/action.c
index c4fd131a..0d6f9e32 100644
--- a/src/action.c
+++ b/src/action.c
@@ -862,6 +862,488 @@ warp_cursor(struct server *server, struct view *view, const char *to, const char
cursor_update_focus(server);
}
+static void
+run_action(struct view *view, struct server *server, struct action *action,
+ struct cursor_context *ctx)
+{
+ switch (action->type) {
+ case ACTION_TYPE_CLOSE:
+ if (view) {
+ view_close(view);
+ }
+ break;
+ case ACTION_TYPE_KILL:
+ if (view) {
+ /* Send SIGTERM to the process associated with the surface */
+ assert(view->impl->get_pid);
+ pid_t pid = view->impl->get_pid(view);
+ if (pid == getpid()) {
+ wlr_log(WLR_ERROR, "Preventing sending SIGTERM to labwc");
+ } else if (pid > 0) {
+ kill(pid, SIGTERM);
+ }
+ }
+ break;
+ case ACTION_TYPE_DEBUG:
+ debug_dump_scene(server);
+ break;
+ case ACTION_TYPE_EXECUTE: {
+ struct buf cmd = BUF_INIT;
+ buf_add(&cmd, action_get_str(action, "command", NULL));
+ buf_expand_tilde(&cmd);
+ spawn_async_no_shell(cmd.data);
+ buf_reset(&cmd);
+ break;
+ }
+ case ACTION_TYPE_EXIT:
+ wl_display_terminate(server->wl_display);
+ break;
+ case ACTION_TYPE_MOVE_TO_EDGE:
+ if (view) {
+ /* Config parsing makes sure that direction is a valid direction */
+ enum view_edge edge = action_get_int(action, "direction", 0);
+ bool snap_to_windows = action_get_bool(action, "snapWindows", true);
+ view_move_to_edge(view, edge, snap_to_windows);
+ }
+ break;
+ case ACTION_TYPE_TOGGLE_SNAP_TO_EDGE:
+ case ACTION_TYPE_SNAP_TO_EDGE:
+ if (view) {
+ /* Config parsing makes sure that direction is a valid direction */
+ enum view_edge edge = action_get_int(action, "direction", 0);
+ if (action->type == ACTION_TYPE_TOGGLE_SNAP_TO_EDGE
+ && view->maximized == VIEW_AXIS_NONE
+ && !view->fullscreen
+ && view_is_tiled(view)
+ && view->tiled == edge) {
+ view_set_untiled(view);
+ view_apply_natural_geometry(view);
+ break;
+ }
+ view_snap_to_edge(view, edge,
+ /*across_outputs*/ true,
+ /*store_natural_geometry*/ true);
+ }
+ break;
+ case ACTION_TYPE_GROW_TO_EDGE:
+ if (view) {
+ /* Config parsing makes sure that direction is a valid direction */
+ enum view_edge edge = action_get_int(action, "direction", 0);
+ view_grow_to_edge(view, edge);
+ }
+ break;
+ case ACTION_TYPE_SHRINK_TO_EDGE:
+ if (view) {
+ /* Config parsing makes sure that direction is a valid direction */
+ enum view_edge edge = action_get_int(action, "direction", 0);
+ view_shrink_to_edge(view, edge);
+ }
+ break;
+ case ACTION_TYPE_NEXT_WINDOW:
+ if (server->input_mode == LAB_INPUT_STATE_WINDOW_SWITCHER) {
+ osd_cycle(server, LAB_CYCLE_DIR_FORWARD);
+ } else {
+ osd_begin(server, LAB_CYCLE_DIR_FORWARD);
+ }
+ break;
+ case ACTION_TYPE_PREVIOUS_WINDOW:
+ if (server->input_mode == LAB_INPUT_STATE_WINDOW_SWITCHER) {
+ osd_cycle(server, LAB_CYCLE_DIR_BACKWARD);
+ } else {
+ osd_begin(server, LAB_CYCLE_DIR_BACKWARD);
+ }
+ break;
+ case ACTION_TYPE_RECONFIGURE:
+ kill(getpid(), SIGHUP);
+ break;
+ case ACTION_TYPE_SHOW_MENU:
+ show_menu(server, view, ctx,
+ action_get_str(action, "menu", NULL),
+ action_get_bool(action, "atCursor", true),
+ action_get_str(action, "x.position", NULL),
+ action_get_str(action, "y.position", NULL));
+ break;
+ case ACTION_TYPE_TOGGLE_MAXIMIZE:
+ if (view) {
+ enum view_axis axis = action_get_int(action,
+ "direction", VIEW_AXIS_BOTH);
+ view_toggle_maximize(view, axis);
+ }
+ break;
+ case ACTION_TYPE_MAXIMIZE:
+ if (view) {
+ enum view_axis axis = action_get_int(action,
+ "direction", VIEW_AXIS_BOTH);
+ view_maximize(view, axis,
+ /*store_natural_geometry*/ true);
+ }
+ break;
+ case ACTION_TYPE_UNMAXIMIZE:
+ if (view) {
+ enum view_axis axis = action_get_int(action,
+ "direction", VIEW_AXIS_BOTH);
+ view_maximize(view, view->maximized & ~axis,
+ /*store_natural_geometry*/ true);
+ }
+ break;
+ case ACTION_TYPE_TOGGLE_FULLSCREEN:
+ if (view) {
+ view_toggle_fullscreen(view);
+ }
+ break;
+ case ACTION_TYPE_SET_DECORATIONS:
+ if (view) {
+ enum ssd_mode mode = action_get_int(action,
+ "decorations", LAB_SSD_MODE_FULL);
+ bool force_ssd = action_get_bool(action,
+ "forceSSD", false);
+ view_set_decorations(view, mode, force_ssd);
+ }
+ break;
+ case ACTION_TYPE_TOGGLE_DECORATIONS:
+ if (view) {
+ view_toggle_decorations(view);
+ }
+ break;
+ case ACTION_TYPE_TOGGLE_ALWAYS_ON_TOP:
+ if (view) {
+ view_toggle_always_on_top(view);
+ }
+ break;
+ case ACTION_TYPE_TOGGLE_ALWAYS_ON_BOTTOM:
+ if (view) {
+ view_toggle_always_on_bottom(view);
+ }
+ break;
+ case ACTION_TYPE_TOGGLE_OMNIPRESENT:
+ if (view) {
+ view_toggle_visible_on_all_workspaces(view);
+ }
+ break;
+ case ACTION_TYPE_FOCUS:
+ if (view) {
+ desktop_focus_view(view, /*raise*/ false);
+ }
+ break;
+ case ACTION_TYPE_UNFOCUS:
+ seat_focus_surface(&server->seat, NULL);
+ break;
+ case ACTION_TYPE_ICONIFY:
+ if (view) {
+ view_minimize(view, true);
+ }
+ break;
+ case ACTION_TYPE_MOVE:
+ if (view) {
+ interactive_begin(view, LAB_INPUT_STATE_MOVE, 0);
+ }
+ break;
+ case ACTION_TYPE_RAISE:
+ if (view) {
+ view_move_to_front(view);
+ }
+ break;
+ case ACTION_TYPE_LOWER:
+ if (view) {
+ view_move_to_back(view);
+ }
+ break;
+ case ACTION_TYPE_RESIZE:
+ if (view) {
+ uint32_t resize_edges = cursor_get_resize_edges(
+ server->seat.cursor, ctx);
+ interactive_begin(view, LAB_INPUT_STATE_RESIZE,
+ resize_edges);
+ }
+ break;
+ case ACTION_TYPE_RESIZE_RELATIVE:
+ if (view) {
+ int left = action_get_int(action, "left", 0);
+ int right = action_get_int(action, "right", 0);
+ int top = action_get_int(action, "top", 0);
+ int bottom = action_get_int(action, "bottom", 0);
+ view_resize_relative(view, left, right, top, bottom);
+ }
+ break;
+ case ACTION_TYPE_MOVETO:
+ if (view) {
+ int x = action_get_int(action, "x", 0);
+ int y = action_get_int(action, "y", 0);
+ struct border margin = ssd_thickness(view);
+ view_move(view, x + margin.left, y + margin.top);
+ }
+ break;
+ case ACTION_TYPE_RESIZETO:
+ if (view) {
+ int width = action_get_int(action, "width", 0);
+ int height = action_get_int(action, "height", 0);
+
+ /*
+ * To support only setting one of width/height
+ * in
+ * we fall back to current dimension when unset.
+ */
+ struct wlr_box box = {
+ .x = view->pending.x,
+ .y = view->pending.y,
+ .width = width ? : view->pending.width,
+ .height = height ? : view->pending.height,
+ };
+ view_set_shade(view, false);
+ view_move_resize(view, box);
+ }
+ break;
+ case ACTION_TYPE_MOVE_RELATIVE:
+ if (view) {
+ int x = action_get_int(action, "x", 0);
+ int y = action_get_int(action, "y", 0);
+ view_move_relative(view, x, y);
+ }
+ break;
+ case ACTION_TYPE_MOVETO_CURSOR:
+ wlr_log(WLR_ERROR,
+ "Action MoveToCursor is deprecated. To ensure your config works in future labwc "
+ "releases, please use ");
+ if (view) {
+ view_move_to_cursor(view);
+ }
+ break;
+ case ACTION_TYPE_SEND_TO_DESKTOP:
+ if (!view) {
+ break;
+ }
+ /* Falls through to GoToDesktop */
+ case ACTION_TYPE_GO_TO_DESKTOP: {
+ bool follow = true;
+ bool wrap = action_get_bool(action, "wrap", true);
+ const char *to = action_get_str(action, "to", NULL);
+ /*
+ * `to` is always != NULL here because otherwise we would have
+ * removed the action during the initial parsing step as it is
+ * a required argument for both SendToDesktop and GoToDesktop.
+ */
+ struct workspace *target_workspace = workspaces_find(
+ server->workspaces.current, to, wrap);
+ if (!target_workspace) {
+ break;
+ }
+ if (action->type == ACTION_TYPE_SEND_TO_DESKTOP) {
+ view_move_to_workspace(view, target_workspace);
+ follow = action_get_bool(action, "follow", true);
+
+ /* Ensure that the focus is not on another desktop */
+ if (!follow && server->active_view == view) {
+ desktop_focus_topmost_view(server);
+ }
+ }
+ if (follow) {
+ workspaces_switch_to(target_workspace,
+ /*update_focus*/ true);
+ }
+ break;
+ }
+ case ACTION_TYPE_MOVE_TO_OUTPUT: {
+ if (!view) {
+ break;
+ }
+ struct output *target_output =
+ get_target_output(view->output, server, action);
+ if (target_output) {
+ view_move_to_output(view, target_output);
+ }
+ break;
+ }
+ case ACTION_TYPE_FIT_TO_OUTPUT:
+ if (!view) {
+ break;
+ }
+ view_constrain_size_to_that_of_usable_area(view);
+ break;
+ case ACTION_TYPE_TOGGLE_SNAP_TO_REGION:
+ case ACTION_TYPE_SNAP_TO_REGION: {
+ if (!view) {
+ break;
+ }
+ struct output *output = view->output;
+ if (!output) {
+ break;
+ }
+ const char *region_name = action_get_str(action, "region", NULL);
+ struct region *region = regions_from_name(region_name, output);
+ if (region) {
+ if (action->type == ACTION_TYPE_TOGGLE_SNAP_TO_REGION
+ && view->maximized == VIEW_AXIS_NONE
+ && !view->fullscreen
+ && view_is_tiled(view)
+ && view->tiled_region == region) {
+ view_set_untiled(view);
+ view_apply_natural_geometry(view);
+ break;
+ }
+ view_snap_to_region(view, region,
+ /*store_natural_geometry*/ true);
+ } else {
+ wlr_log(WLR_ERROR, "Invalid SnapToRegion id: '%s'", region_name);
+ }
+ break;
+ }
+ case ACTION_TYPE_UNSNAP:
+ if (view && !view->fullscreen && !view_is_floating(view)) {
+ view_maximize(view, VIEW_AXIS_NONE,
+ /* store_natural_geometry */ false);
+ view_set_untiled(view);
+ view_apply_natural_geometry(view);
+ }
+ break;
+ case ACTION_TYPE_TOGGLE_KEYBINDS:
+ if (view) {
+ view_toggle_keybinds(view);
+ }
+ break;
+ case ACTION_TYPE_FOCUS_OUTPUT: {
+ struct output *output = output_nearest_to_cursor(server);
+ struct output *target_output =
+ get_target_output(output, server, action);
+ if (target_output) {
+ desktop_focus_output(target_output);
+ }
+ break;
+ }
+ case ACTION_TYPE_IF:
+ if (view) {
+ run_if_action(view, server, action);
+ }
+ break;
+ case ACTION_TYPE_FOR_EACH: {
+ struct wl_array views;
+ struct view **item;
+ bool matches = false;
+ wl_array_init(&views);
+ view_array_append(server, &views, LAB_VIEW_CRITERIA_NONE);
+ wl_array_for_each(item, &views) {
+ matches |= run_if_action(*item, server, action);
+ }
+ wl_array_release(&views);
+ if (!matches) {
+ struct wl_list *child_actions;
+ child_actions = action_get_actionlist(action, "none");
+ if (child_actions) {
+ actions_run(view, server, child_actions, NULL);
+ }
+ }
+ break;
+ }
+ case ACTION_TYPE_VIRTUAL_OUTPUT_ADD: {
+ /* TODO: rename this argument to "outputName" */
+ const char *output_name =
+ action_get_str(action, "output_name", NULL);
+ output_virtual_add(server, output_name,
+ /*store_wlr_output*/ NULL);
+ break;
+ }
+ case ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE: {
+ /* TODO: rename this argument to "outputName" */
+ const char *output_name =
+ action_get_str(action, "output_name", NULL);
+ output_virtual_remove(server, output_name);
+ break;
+ }
+ case ACTION_TYPE_AUTO_PLACE:
+ if (view) {
+ enum view_placement_policy policy =
+ action_get_int(action, "policy", LAB_PLACE_AUTOMATIC);
+ view_place_by_policy(view,
+ /* allow_cursor */ true, policy);
+ }
+ break;
+ case ACTION_TYPE_TOGGLE_TEARING:
+ if (view) {
+ switch (view->force_tearing) {
+ case LAB_STATE_UNSPECIFIED:
+ view->force_tearing =
+ output_get_tearing_allowance(view->output)
+ ? LAB_STATE_DISABLED : LAB_STATE_ENABLED;
+ break;
+ case LAB_STATE_DISABLED:
+ view->force_tearing = LAB_STATE_ENABLED;
+ break;
+ case LAB_STATE_ENABLED:
+ view->force_tearing = LAB_STATE_DISABLED;
+ break;
+ }
+ wlr_log(WLR_ERROR, "force tearing %sabled",
+ view->force_tearing == LAB_STATE_ENABLED
+ ? "en" : "dis");
+ }
+ break;
+ case ACTION_TYPE_TOGGLE_SHADE:
+ if (view) {
+ view_set_shade(view, !view->shaded);
+ }
+ break;
+ case ACTION_TYPE_SHADE:
+ if (view) {
+ view_set_shade(view, true);
+ }
+ break;
+ case ACTION_TYPE_UNSHADE:
+ if (view) {
+ view_set_shade(view, false);
+ }
+ break;
+ case ACTION_TYPE_ENABLE_SCROLL_WHEEL_EMULATION:
+ server->seat.cursor_scroll_wheel_emulation = true;
+ break;
+ case ACTION_TYPE_DISABLE_SCROLL_WHEEL_EMULATION:
+ server->seat.cursor_scroll_wheel_emulation = false;
+ break;
+ case ACTION_TYPE_TOGGLE_SCROLL_WHEEL_EMULATION:
+ server->seat.cursor_scroll_wheel_emulation =
+ !server->seat.cursor_scroll_wheel_emulation;
+ break;
+ case ACTION_TYPE_ENABLE_TABLET_MOUSE_EMULATION:
+ rc.tablet.force_mouse_emulation = true;
+ break;
+ case ACTION_TYPE_DISABLE_TABLET_MOUSE_EMULATION:
+ rc.tablet.force_mouse_emulation = false;
+ break;
+ case ACTION_TYPE_TOGGLE_TABLET_MOUSE_EMULATION:
+ rc.tablet.force_mouse_emulation = !rc.tablet.force_mouse_emulation;
+ break;
+ case ACTION_TYPE_TOGGLE_MAGNIFY:
+ magnifier_toggle(server);
+ break;
+ case ACTION_TYPE_ZOOM_IN:
+ magnifier_set_scale(server, MAGNIFY_INCREASE);
+ break;
+ case ACTION_TYPE_ZOOM_OUT:
+ magnifier_set_scale(server, MAGNIFY_DECREASE);
+ break;
+ case ACTION_TYPE_WARP_CURSOR: {
+ const char *to = action_get_str(action, "to", "output");
+ const char *x = action_get_str(action, "x", "center");
+ const char *y = action_get_str(action, "y", "center");
+ warp_cursor(server, view, to, x, y);
+ break;
+ }
+ case ACTION_TYPE_HIDE_CURSOR:
+ cursor_set_visible(&server->seat, false);
+ break;
+ case ACTION_TYPE_INVALID:
+ wlr_log(WLR_ERROR, "Not executing unknown action");
+ break;
+ 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)"
+ " This is a BUG. Please report.", action->type);
+ }
+}
+
void
actions_run(struct view *activator, struct server *server,
struct wl_list *actions, struct cursor_context *cursor_ctx)
@@ -898,481 +1380,6 @@ actions_run(struct view *activator, struct server *server,
*/
struct view *view = view_for_action(activator, server, action, &ctx);
- switch (action->type) {
- case ACTION_TYPE_CLOSE:
- if (view) {
- view_close(view);
- }
- break;
- case ACTION_TYPE_KILL:
- if (view) {
- /* Send SIGTERM to the process associated with the surface */
- assert(view->impl->get_pid);
- pid_t pid = view->impl->get_pid(view);
- if (pid == getpid()) {
- wlr_log(WLR_ERROR, "Preventing sending SIGTERM to labwc");
- } else if (pid > 0) {
- kill(pid, SIGTERM);
- }
- }
- break;
- case ACTION_TYPE_DEBUG:
- debug_dump_scene(server);
- break;
- case ACTION_TYPE_EXECUTE: {
- struct buf cmd = BUF_INIT;
- buf_add(&cmd, action_get_str(action, "command", NULL));
- buf_expand_tilde(&cmd);
- spawn_async_no_shell(cmd.data);
- buf_reset(&cmd);
- break;
- }
- case ACTION_TYPE_EXIT:
- wl_display_terminate(server->wl_display);
- break;
- case ACTION_TYPE_MOVE_TO_EDGE:
- if (view) {
- /* Config parsing makes sure that direction is a valid direction */
- enum view_edge edge = action_get_int(action, "direction", 0);
- bool snap_to_windows = action_get_bool(action, "snapWindows", true);
- view_move_to_edge(view, edge, snap_to_windows);
- }
- break;
- case ACTION_TYPE_TOGGLE_SNAP_TO_EDGE:
- case ACTION_TYPE_SNAP_TO_EDGE:
- if (view) {
- /* Config parsing makes sure that direction is a valid direction */
- enum view_edge edge = action_get_int(action, "direction", 0);
- if (action->type == ACTION_TYPE_TOGGLE_SNAP_TO_EDGE
- && view->maximized == VIEW_AXIS_NONE
- && !view->fullscreen
- && view_is_tiled(view)
- && view->tiled == edge) {
- view_set_untiled(view);
- view_apply_natural_geometry(view);
- break;
- }
- view_snap_to_edge(view, edge,
- /*across_outputs*/ true,
- /*store_natural_geometry*/ true);
- }
- break;
- case ACTION_TYPE_GROW_TO_EDGE:
- if (view) {
- /* Config parsing makes sure that direction is a valid direction */
- enum view_edge edge = action_get_int(action, "direction", 0);
- view_grow_to_edge(view, edge);
- }
- break;
- case ACTION_TYPE_SHRINK_TO_EDGE:
- if (view) {
- /* Config parsing makes sure that direction is a valid direction */
- enum view_edge edge = action_get_int(action, "direction", 0);
- view_shrink_to_edge(view, edge);
- }
- break;
- case ACTION_TYPE_NEXT_WINDOW:
- if (server->input_mode == LAB_INPUT_STATE_WINDOW_SWITCHER) {
- osd_cycle(server, LAB_CYCLE_DIR_FORWARD);
- } else {
- osd_begin(server, LAB_CYCLE_DIR_FORWARD);
- }
- break;
- case ACTION_TYPE_PREVIOUS_WINDOW:
- if (server->input_mode == LAB_INPUT_STATE_WINDOW_SWITCHER) {
- osd_cycle(server, LAB_CYCLE_DIR_BACKWARD);
- } else {
- osd_begin(server, LAB_CYCLE_DIR_BACKWARD);
- }
- break;
- case ACTION_TYPE_RECONFIGURE:
- kill(getpid(), SIGHUP);
- break;
- case ACTION_TYPE_SHOW_MENU:
- show_menu(server, view, &ctx,
- action_get_str(action, "menu", NULL),
- action_get_bool(action, "atCursor", true),
- action_get_str(action, "x.position", NULL),
- action_get_str(action, "y.position", NULL));
- break;
- case ACTION_TYPE_TOGGLE_MAXIMIZE:
- if (view) {
- enum view_axis axis = action_get_int(action,
- "direction", VIEW_AXIS_BOTH);
- view_toggle_maximize(view, axis);
- }
- break;
- case ACTION_TYPE_MAXIMIZE:
- if (view) {
- enum view_axis axis = action_get_int(action,
- "direction", VIEW_AXIS_BOTH);
- view_maximize(view, axis,
- /*store_natural_geometry*/ true);
- }
- break;
- case ACTION_TYPE_UNMAXIMIZE:
- if (view) {
- enum view_axis axis = action_get_int(action,
- "direction", VIEW_AXIS_BOTH);
- view_maximize(view, view->maximized & ~axis,
- /*store_natural_geometry*/ true);
- }
- break;
- case ACTION_TYPE_TOGGLE_FULLSCREEN:
- if (view) {
- view_toggle_fullscreen(view);
- }
- break;
- case ACTION_TYPE_SET_DECORATIONS:
- if (view) {
- enum ssd_mode mode = action_get_int(action,
- "decorations", LAB_SSD_MODE_FULL);
- bool force_ssd = action_get_bool(action,
- "forceSSD", false);
- view_set_decorations(view, mode, force_ssd);
- }
- break;
- case ACTION_TYPE_TOGGLE_DECORATIONS:
- if (view) {
- view_toggle_decorations(view);
- }
- break;
- case ACTION_TYPE_TOGGLE_ALWAYS_ON_TOP:
- if (view) {
- view_toggle_always_on_top(view);
- }
- break;
- case ACTION_TYPE_TOGGLE_ALWAYS_ON_BOTTOM:
- if (view) {
- view_toggle_always_on_bottom(view);
- }
- break;
- case ACTION_TYPE_TOGGLE_OMNIPRESENT:
- if (view) {
- view_toggle_visible_on_all_workspaces(view);
- }
- break;
- case ACTION_TYPE_FOCUS:
- if (view) {
- desktop_focus_view(view, /*raise*/ false);
- }
- break;
- case ACTION_TYPE_UNFOCUS:
- seat_focus_surface(&server->seat, NULL);
- break;
- case ACTION_TYPE_ICONIFY:
- if (view) {
- view_minimize(view, true);
- }
- break;
- case ACTION_TYPE_MOVE:
- if (view) {
- interactive_begin(view, LAB_INPUT_STATE_MOVE, 0);
- }
- break;
- case ACTION_TYPE_RAISE:
- if (view) {
- view_move_to_front(view);
- }
- break;
- case ACTION_TYPE_LOWER:
- if (view) {
- view_move_to_back(view);
- }
- break;
- case ACTION_TYPE_RESIZE:
- if (view) {
- uint32_t resize_edges = cursor_get_resize_edges(
- server->seat.cursor, &ctx);
- interactive_begin(view, LAB_INPUT_STATE_RESIZE,
- resize_edges);
- }
- break;
- case ACTION_TYPE_RESIZE_RELATIVE:
- if (view) {
- int left = action_get_int(action, "left", 0);
- int right = action_get_int(action, "right", 0);
- int top = action_get_int(action, "top", 0);
- int bottom = action_get_int(action, "bottom", 0);
- view_resize_relative(view, left, right, top, bottom);
- }
- break;
- case ACTION_TYPE_MOVETO:
- if (view) {
- int x = action_get_int(action, "x", 0);
- int y = action_get_int(action, "y", 0);
- struct border margin = ssd_thickness(view);
- view_move(view, x + margin.left, y + margin.top);
- }
- break;
- case ACTION_TYPE_RESIZETO:
- if (view) {
- int width = action_get_int(action, "width", 0);
- int height = action_get_int(action, "height", 0);
-
- /*
- * To support only setting one of width/height
- * in
- * we fall back to current dimension when unset.
- */
- struct wlr_box box = {
- .x = view->pending.x,
- .y = view->pending.y,
- .width = width ? : view->pending.width,
- .height = height ? : view->pending.height,
- };
- view_set_shade(view, false);
- view_move_resize(view, box);
- }
- break;
- case ACTION_TYPE_MOVE_RELATIVE:
- if (view) {
- int x = action_get_int(action, "x", 0);
- int y = action_get_int(action, "y", 0);
- view_move_relative(view, x, y);
- }
- break;
- case ACTION_TYPE_MOVETO_CURSOR:
- wlr_log(WLR_ERROR,
- "Action MoveToCursor is deprecated. To ensure your config works in future labwc "
- "releases, please use ");
- if (view) {
- view_move_to_cursor(view);
- }
- break;
- case ACTION_TYPE_SEND_TO_DESKTOP:
- if (!view) {
- break;
- }
- /* Falls through to GoToDesktop */
- case ACTION_TYPE_GO_TO_DESKTOP: {
- bool follow = true;
- bool wrap = action_get_bool(action, "wrap", true);
- const char *to = action_get_str(action, "to", NULL);
- /*
- * `to` is always != NULL here because otherwise we would have
- * removed the action during the initial parsing step as it is
- * a required argument for both SendToDesktop and GoToDesktop.
- */
- struct workspace *target_workspace = workspaces_find(
- server->workspaces.current, to, wrap);
- if (!target_workspace) {
- break;
- }
- if (action->type == ACTION_TYPE_SEND_TO_DESKTOP) {
- view_move_to_workspace(view, target_workspace);
- follow = action_get_bool(action, "follow", true);
-
- /* Ensure that the focus is not on another desktop */
- if (!follow && server->active_view == view) {
- desktop_focus_topmost_view(server);
- }
- }
- if (follow) {
- workspaces_switch_to(target_workspace,
- /*update_focus*/ true);
- }
- break;
- }
- case ACTION_TYPE_MOVE_TO_OUTPUT: {
- if (!view) {
- break;
- }
- struct output *target_output =
- get_target_output(view->output, server, action);
- if (target_output) {
- view_move_to_output(view, target_output);
- }
- break;
- }
- case ACTION_TYPE_FIT_TO_OUTPUT:
- if (!view) {
- break;
- }
- view_constrain_size_to_that_of_usable_area(view);
- break;
- case ACTION_TYPE_TOGGLE_SNAP_TO_REGION:
- case ACTION_TYPE_SNAP_TO_REGION: {
- if (!view) {
- break;
- }
- struct output *output = view->output;
- if (!output) {
- break;
- }
- const char *region_name = action_get_str(action, "region", NULL);
- struct region *region = regions_from_name(region_name, output);
- if (region) {
- if (action->type == ACTION_TYPE_TOGGLE_SNAP_TO_REGION
- && view->maximized == VIEW_AXIS_NONE
- && !view->fullscreen
- && view_is_tiled(view)
- && view->tiled_region == region) {
- view_set_untiled(view);
- view_apply_natural_geometry(view);
- break;
- }
- view_snap_to_region(view, region,
- /*store_natural_geometry*/ true);
- } else {
- wlr_log(WLR_ERROR, "Invalid SnapToRegion id: '%s'", region_name);
- }
- break;
- }
- case ACTION_TYPE_UNSNAP:
- if (view && !view->fullscreen && !view_is_floating(view)) {
- view_maximize(view, VIEW_AXIS_NONE,
- /* store_natural_geometry */ false);
- view_set_untiled(view);
- view_apply_natural_geometry(view);
- }
- break;
- case ACTION_TYPE_TOGGLE_KEYBINDS:
- if (view) {
- view_toggle_keybinds(view);
- }
- break;
- case ACTION_TYPE_FOCUS_OUTPUT: {
- struct output *output = output_nearest_to_cursor(server);
- struct output *target_output =
- get_target_output(output, server, action);
- if (target_output) {
- desktop_focus_output(target_output);
- }
- break;
- }
- case ACTION_TYPE_IF:
- if (view) {
- run_if_action(view, server, action);
- }
- break;
- case ACTION_TYPE_FOR_EACH: {
- struct wl_array views;
- struct view **item;
- bool matches = false;
- wl_array_init(&views);
- view_array_append(server, &views, LAB_VIEW_CRITERIA_NONE);
- wl_array_for_each(item, &views) {
- matches |= run_if_action(*item, server, action);
- }
- wl_array_release(&views);
- if (!matches) {
- struct wl_list *child_actions;
- child_actions = action_get_actionlist(action, "none");
- if (child_actions) {
- actions_run(view, server, child_actions, NULL);
- }
- }
- break;
- }
- case ACTION_TYPE_VIRTUAL_OUTPUT_ADD: {
- /* TODO: rename this argument to "outputName" */
- const char *output_name =
- action_get_str(action, "output_name", NULL);
- output_virtual_add(server, output_name,
- /*store_wlr_output*/ NULL);
- break;
- }
- case ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE: {
- /* TODO: rename this argument to "outputName" */
- const char *output_name =
- action_get_str(action, "output_name", NULL);
- output_virtual_remove(server, output_name);
- break;
- }
- case ACTION_TYPE_AUTO_PLACE:
- if (view) {
- enum view_placement_policy policy =
- action_get_int(action, "policy", LAB_PLACE_AUTOMATIC);
- view_place_by_policy(view,
- /* allow_cursor */ true, policy);
- }
- break;
- case ACTION_TYPE_TOGGLE_TEARING:
- if (view) {
- switch (view->force_tearing) {
- case LAB_STATE_UNSPECIFIED:
- view->force_tearing =
- output_get_tearing_allowance(view->output)
- ? LAB_STATE_DISABLED : LAB_STATE_ENABLED;
- break;
- case LAB_STATE_DISABLED:
- view->force_tearing = LAB_STATE_ENABLED;
- break;
- case LAB_STATE_ENABLED:
- view->force_tearing = LAB_STATE_DISABLED;
- break;
- }
- wlr_log(WLR_ERROR, "force tearing %sabled",
- view->force_tearing == LAB_STATE_ENABLED
- ? "en" : "dis");
- }
- break;
- case ACTION_TYPE_TOGGLE_SHADE:
- if (view) {
- view_set_shade(view, !view->shaded);
- }
- break;
- case ACTION_TYPE_SHADE:
- if (view) {
- view_set_shade(view, true);
- }
- break;
- case ACTION_TYPE_UNSHADE:
- if (view) {
- view_set_shade(view, false);
- }
- break;
- case ACTION_TYPE_ENABLE_SCROLL_WHEEL_EMULATION:
- server->seat.cursor_scroll_wheel_emulation = true;
- break;
- case ACTION_TYPE_DISABLE_SCROLL_WHEEL_EMULATION:
- server->seat.cursor_scroll_wheel_emulation = false;
- break;
- case ACTION_TYPE_TOGGLE_SCROLL_WHEEL_EMULATION:
- server->seat.cursor_scroll_wheel_emulation =
- !server->seat.cursor_scroll_wheel_emulation;
- break;
- case ACTION_TYPE_ENABLE_TABLET_MOUSE_EMULATION:
- rc.tablet.force_mouse_emulation = true;
- break;
- case ACTION_TYPE_DISABLE_TABLET_MOUSE_EMULATION:
- rc.tablet.force_mouse_emulation = false;
- break;
- case ACTION_TYPE_TOGGLE_TABLET_MOUSE_EMULATION:
- rc.tablet.force_mouse_emulation = !rc.tablet.force_mouse_emulation;
- break;
- case ACTION_TYPE_TOGGLE_MAGNIFY:
- magnifier_toggle(server);
- break;
- case ACTION_TYPE_ZOOM_IN:
- magnifier_set_scale(server, MAGNIFY_INCREASE);
- break;
- case ACTION_TYPE_ZOOM_OUT:
- magnifier_set_scale(server, MAGNIFY_DECREASE);
- break;
- case ACTION_TYPE_WARP_CURSOR: {
- const char *to = action_get_str(action, "to", "output");
- const char *x = action_get_str(action, "x", "center");
- const char *y = action_get_str(action, "y", "center");
- warp_cursor(server, view, to, x, y);
- break;
- }
- case ACTION_TYPE_HIDE_CURSOR:
- cursor_set_visible(&server->seat, false);
- break;
- case ACTION_TYPE_INVALID:
- wlr_log(WLR_ERROR, "Not executing unknown action");
- break;
- 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)"
- " This is a BUG. Please report.", action->type);
- }
+ run_action(view, server, action, &ctx);
}
}