From 89589f17c4e8cd9dbab0ad79a34ee5edf2727fd8 Mon Sep 17 00:00:00 2001 From: "Andrew J. Hesford" Date: Tue, 7 May 2024 09:46:05 -0400 Subject: [PATCH] action: allow configurable policy in AutoPlace action Closes: #1784. --- docs/labwc-actions.5.scd | 9 ++++++--- include/config/rcxml.h | 3 ++- include/view.h | 8 ++++++-- src/action.c | 21 +++++++++++++++++---- src/config/rcxml.c | 7 ++----- src/view.c | 28 ++++++++++++++++++++++++---- src/xdg.c | 2 +- src/xwayland.c | 3 ++- 8 files changed, 60 insertions(+), 21 deletions(-) diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index db0ce5cd..097cd5c2 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -251,9 +251,12 @@ Actions are used in menus and keyboard/mouse bindings. *output_name* The name of virtual output. If not supplied, will remove the last virtual output added. -** - Use the automatic placement policy to move the active window to a - position on its output that will minimize overlap with other windows. +** + Reposition the window according to the desired placement policy. + + *policy* [automatic|cursor|center] Use the specified policy, which has + the same meaning as the corresponding value for **. + Default is automatic. **++ **++ diff --git a/include/config/rcxml.h b/include/config/rcxml.h index 80916ea1..d308daa6 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -16,7 +16,8 @@ #include "theme.h" enum view_placement_policy { - LAB_PLACE_CENTER = 0, + LAB_PLACE_INVALID = 0, + LAB_PLACE_CENTER, LAB_PLACE_CURSOR, LAB_PLACE_AUTOMATIC }; diff --git a/include/view.h b/include/view.h index cb7e70dc..b0e2a41e 100644 --- a/include/view.h +++ b/include/view.h @@ -456,10 +456,13 @@ int view_effective_height(struct view *view, bool use_pending); void view_center(struct view *view, const struct wlr_box *ref); /** - * view_place_initial - apply initial placement strategy to view + * view_place_by_policy - apply placement strategy to view * @view: view to be placed + * @allow_cursor: set to false to ignore center-on-cursor policy + * @policy: placement policy to apply */ -void view_place_initial(struct view *view, bool allow_cursor); +void view_place_by_policy(struct view *view, bool allow_cursor, + enum view_placement_policy); void view_constrain_size_to_that_of_usable_area(struct view *view); void view_restore_to(struct view *view, struct wlr_box geometry); @@ -525,6 +528,7 @@ struct output *view_get_adjacent_output(struct view *view, enum view_edge edge, bool wrap); enum view_axis view_axis_parse(const char *direction); enum view_edge view_edge_parse(const char *direction); +enum view_placement_policy view_placement_parse(const char *policy); /* xdg.c */ struct wlr_xdg_surface *xdg_surface_from_view(struct view *view); diff --git a/src/action.c b/src/action.c index 78c71d98..db2b7557 100644 --- a/src/action.c +++ b/src/action.c @@ -422,6 +422,19 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char goto cleanup; } break; + case ACTION_TYPE_AUTO_PLACE: + if (!strcmp(argument, "policy")) { + enum view_placement_policy policy = + view_placement_parse(content); + if (policy == LAB_PLACE_INVALID) { + wlr_log(WLR_ERROR, "Invalid argument for action %s: '%s' (%s)", + action_names[action->type], argument, content); + } else { + action_arg_add_int(action, argument, policy); + } + goto cleanup; + } + break; } wlr_log(WLR_ERROR, "Invalid argument for action %s: '%s'", @@ -1030,10 +1043,10 @@ actions_run(struct view *activator, struct server *server, break; case ACTION_TYPE_AUTO_PLACE: if (view) { - struct wlr_box geometry = view->pending; - if (placement_find_best(view, &geometry)) { - view_move(view, geometry.x, geometry.y); - } + 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: diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 9884d41a..164e329c 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -873,11 +873,8 @@ entry(xmlNode *node, char *nodename, char *content) } else if (!strcasecmp(nodename, "reuseOutputMode.core")) { set_bool(content, &rc.reuse_output_mode); } else if (!strcmp(nodename, "policy.placement")) { - if (!strcmp(content, "automatic")) { - rc.placement_policy = LAB_PLACE_AUTOMATIC; - } else if (!strcmp(content, "cursor")) { - rc.placement_policy = LAB_PLACE_CURSOR; - } else { + rc.placement_policy = view_placement_parse(content); + if (rc.placement_policy == LAB_PLACE_INVALID) { rc.placement_policy = LAB_PLACE_CENTER; } } else if (!strcmp(nodename, "name.theme")) { diff --git a/src/view.c b/src/view.c index ee76a746..ef44cbdb 100644 --- a/src/view.c +++ b/src/view.c @@ -833,12 +833,13 @@ view_center(struct view *view, const struct wlr_box *ref) } void -view_place_initial(struct view *view, bool allow_cursor) +view_place_by_policy(struct view *view, bool allow_cursor, + enum view_placement_policy policy) { - if (allow_cursor && rc.placement_policy == LAB_PLACE_CURSOR) { + if (allow_cursor && policy == LAB_PLACE_CURSOR) { view_move_to_cursor(view); return; - } else if (rc.placement_policy == LAB_PLACE_AUTOMATIC) { + } else if (policy == LAB_PLACE_AUTOMATIC) { struct wlr_box geometry = view->pending; if (placement_find_best(view, &geometry)) { view_move(view, geometry.x, geometry.y); @@ -1866,6 +1867,24 @@ view_edge_parse(const char *direction) } } +enum view_placement_policy +view_placement_parse(const char *policy) +{ + if (!policy) { + return LAB_PLACE_CENTER; + } + + if (!strcasecmp(policy, "automatic")) { + return LAB_PLACE_AUTOMATIC; + } else if (!strcasecmp(policy, "cursor")) { + return LAB_PLACE_CURSOR; + } else if (!strcasecmp(policy, "center")) { + return LAB_PLACE_CENTER; + } + + return LAB_PLACE_INVALID; +} + void view_snap_to_edge(struct view *view, enum view_edge edge, bool across_outputs, bool store_natural_geometry) @@ -1969,7 +1988,8 @@ view_move_to_output(struct view *view, struct output *output) struct wlr_box output_area = output_usable_area_in_layout_coords(output); view->pending.x = output_area.x; view->pending.y = output_area.y; - view_place_initial(view, /* allow_cursor */ false); + view_place_by_policy(view, + /* allow_cursor */ false, rc.placement_policy); } else if (view->maximized != VIEW_AXIS_NONE) { view_apply_maximized_geometry(view); } else if (view->tiled) { diff --git a/src/xdg.c b/src/xdg.c index 488f67fd..fd4e926f 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -530,7 +530,7 @@ set_initial_position(struct view *view) } /* All other views are placed according to a configured strategy */ - view_place_initial(view, /* allow_cursor */ true); + view_place_by_policy(view, /* allow_cursor */ true, rc.placement_policy); } static const char * diff --git a/src/xwayland.c b/src/xwayland.c index eda5aad7..073a9697 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -571,7 +571,8 @@ set_initial_position(struct view *view, view_constrain_size_to_that_of_usable_area(view); if (view_is_floating(view)) { - view_place_initial(view, /* allow_cursor */ true); + view_place_by_policy(view, + /* allow_cursor */ true, rc.placement_policy); } else { /* * View is maximized/fullscreen. Center the -- 2.52.0