Implement key binds to control virtual outputs (#1287)

Add actions `VirtualOutputAdd` and `VirtualOutputRemove`
This commit is contained in:
kyak 2023-12-09 12:01:11 +03:00 committed by GitHub
parent e303281333
commit 111b955b53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 150 additions and 1 deletions

View file

@ -98,6 +98,8 @@ enum action_type {
ACTION_TYPE_FOCUS_OUTPUT,
ACTION_TYPE_IF,
ACTION_TYPE_FOR_EACH,
ACTION_TYPE_VIRTUAL_OUTPUT_ADD,
ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE,
};
const char *action_names[] = {
@ -142,6 +144,8 @@ const char *action_names[] = {
"FocusOutput",
"If",
"ForEach",
"VirtualOutputAdd",
"VirtualOutputRemove",
NULL
};
@ -363,6 +367,13 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
goto cleanup;
}
break;
case ACTION_TYPE_VIRTUAL_OUTPUT_ADD:
case ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE:
if (!strcmp(argument, "output_name")) {
action_arg_add_str(action, argument, content);
goto cleanup;
}
break;
}
wlr_log(WLR_ERROR, "Invalid argument for action %s: '%s'",
@ -915,6 +926,20 @@ actions_run(struct view *activator, struct server *server,
wl_array_release(&views);
}
break;
case ACTION_TYPE_VIRTUAL_OUTPUT_ADD:
{
const char *output_name = action_get_str(action, "output_name",
NULL);
output_add_virtual(server, output_name);
}
break;
case ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE:
{
const char *output_name = action_get_str(action, "output_name",
NULL);
output_remove_virtual(server, output_name);
}
break;
case ACTION_TYPE_INVALID:
wlr_log(WLR_ERROR, "Not executing unknown action");
break;

View file

@ -9,6 +9,8 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <strings.h>
#include <wlr/backend/drm.h>
#include <wlr/backend/headless.h>
#include <wlr/types/wlr_buffer.h>
#include <wlr/types/wlr_drm_lease_v1.h>
#include <wlr/types/wlr_output.h>
@ -172,6 +174,12 @@ new_output_notify(struct wl_listener *listener, void *data)
struct server *server = wl_container_of(listener, server, new_output);
struct wlr_output *wlr_output = data;
/* Name virtual output */
if (wlr_output_is_headless(wlr_output) && server->headless.pending_output_name[0] != '\0') {
wlr_output_set_name(wlr_output, server->headless.pending_output_name);
server->headless.pending_output_name[0] = '\0';
}
/*
* We offer any display as available for lease, some apps like
* gamescope, want to take ownership of a display when they can
@ -179,7 +187,7 @@ new_output_notify(struct wl_listener *listener, void *data)
* This is also useful for debugging the DRM parts of
* another compositor.
*/
if (server->drm_lease_manager) {
if (server->drm_lease_manager && wlr_output_is_drm(wlr_output)) {
wlr_drm_lease_v1_manager_offer_output(
server->drm_lease_manager, wlr_output);
}
@ -746,3 +754,56 @@ handle_output_power_manager_set_mode(struct wl_listener *listener, void *data)
break;
}
}
void
output_add_virtual(struct server *server, const char *output_name)
{
if (output_name) {
/* Prevent creating outputs with the same name */
struct output *output;
wl_list_for_each(output, &server->outputs, link) {
if (wlr_output_is_headless(output->wlr_output) &&
!strcmp(output->wlr_output->name, output_name)) {
wlr_log(WLR_DEBUG,
"refusing to create virtual output with duplicate name");
return;
}
}
strncpy(server->headless.pending_output_name, output_name,
sizeof(server->headless.pending_output_name));
} else {
server->headless.pending_output_name[0] = '\0';
}
/*
* Setting it to (0, 0) here disallows changing resolution from tools like
* wlr-randr (returns error)
*/
wlr_headless_add_output(server->headless.backend, 1920, 1080);
}
void
output_remove_virtual(struct server *server, const char *output_name)
{
struct output *output;
wl_list_for_each(output, &server->outputs, link) {
if (wlr_output_is_headless(output->wlr_output)) {
if (output_name) {
/*
* Given virtual output name, find and destroy virtual output by
* that name.
*/
if (!strcmp(output->wlr_output->name, output_name)) {
wlr_output_destroy(output->wlr_output);
return;
}
} else {
/*
* When virtual output name was no supplied by user, simply
* destroy the first virtual output found.
*/
wlr_output_destroy(output->wlr_output);
return;
}
}
}
}

View file

@ -3,6 +3,8 @@
#include "config.h"
#include <signal.h>
#include <sys/wait.h>
#include <wlr/backend/headless.h>
#include <wlr/backend/multi.h>
#include <wlr/types/wlr_data_control_v1.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_fractional_scale_v1.h>
@ -256,6 +258,22 @@ server_init(struct server *server)
exit(EXIT_FAILURE);
}
/* Create headless backend to enable adding virtual outputs later on */
server->headless.backend = wlr_headless_backend_create(server->wl_display);
if (!server->headless.backend) {
wlr_log(WLR_ERROR, "unable to create headless backend");
exit(EXIT_FAILURE);
}
wlr_multi_backend_add(server->backend, server->headless.backend);
/*
* If we don't populate headless backend with a virtual output (that we
* create and immediately destroy), then virtual outputs being added
* later do not work properly when overlaid on real output. Content is
* drawn on the virtual output, but not drawn on the real output.
*/
wlr_output_destroy(wlr_headless_add_output(server->headless.backend, 0, 0));
/*
* Autocreates a renderer, either Pixman, GLES2 or Vulkan for us. The
* user can also specify a renderer using the WLR_RENDERER env var.