Add "next"/"prev" output navigation to MoveToOutput action

Support "next" and "prev" as values for the `output` attribute in
`MoveToOutput`, cycling through `server.outputs` with wraparound.
This commit is contained in:
Kfiad 2026-05-05 22:19:15 +02:00
parent 0ff9af4ae0
commit 944abb0f0e
2 changed files with 24 additions and 5 deletions

View file

@ -294,9 +294,11 @@ Actions are used in menus and keyboard/mouse bindings.
fullscreen.
If *output* is specified, the window will be sent directly to the
specified output and *direction* is ignored. If *output* is omitted,
specified output and *direction* is ignored. *output* may also be
"next" or "prev" to move to the next or previous output in the
server.outputs list, with wraparound. If *output* is omitted,
*direction* may be one of "left", "right", "up" or "down" to indicate
that the window should be moved to the next output in that direction
that the window should be moved to the next output in the direction
(if one exists).
*wrap* [yes|no] When using the direction attribute, wrap around from

View file

@ -997,17 +997,34 @@ match_queries(struct view *view, struct action *action)
static struct output *
get_target_output(struct output *output, struct action *action)
{
const char *output_name = action_get_str(action, "output", NULL);
const char *output_arg = action_get_str(action, "output", NULL);
struct output *target = NULL;
if (output_name) {
target = output_from_name(output_name);
if (output_arg) {
if (!strcasecmp(output_arg, "next")) {
struct wl_list *list_item = output->link.next;
if (list_item == &server.outputs) {
list_item = server.outputs.next;
}
target = wl_container_of(list_item, target, link);
} else if (!strcasecmp(output_arg, "prev")) {
struct wl_list *list_item = output->link.prev;
if (list_item == &server.outputs) {
list_item = server.outputs.prev;
}
target = wl_container_of(list_item, target, link);
} else {
target = output_from_name(output_arg);
}
} else {
enum lab_edge edge =
action_get_int(action, "direction", LAB_EDGE_NONE);
bool wrap = action_get_bool(action, "wrap", false);
target = output_get_adjacent(output, edge, wrap);
}
if (!target || !output_is_usable(target)) {
target = NULL;
}
if (!target) {
wlr_log(WLR_DEBUG, "Invalid output");