mirror of
https://github.com/labwc/labwc.git
synced 2026-04-13 08:21:15 -04:00
Implement key binds to control virtual outputs
It is now possible to use keybinds to add and remove virtual outputs (also called headless backend in wlroots terminology).
This commit is contained in:
parent
5d2f594626
commit
45012d322a
5 changed files with 149 additions and 1 deletions
75
src/action.c
75
src/action.c
|
|
@ -5,6 +5,7 @@
|
|||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <wlr/backend/headless.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "action.h"
|
||||
#include "common/macros.h"
|
||||
|
|
@ -98,6 +99,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 +145,8 @@ const char *action_names[] = {
|
|||
"FocusOutput",
|
||||
"If",
|
||||
"ForEach",
|
||||
"VirtualOutputAdd",
|
||||
"VirtualOutputRemove",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -363,6 +368,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'",
|
||||
|
|
@ -617,6 +629,57 @@ run_if_action(struct view *view, struct server *server, struct action *action)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
virtual_output_add(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)) {
|
||||
if (!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';
|
||||
}
|
||||
wlr_headless_add_output(server->headless.backend, 1920, 1080);
|
||||
}
|
||||
|
||||
static void
|
||||
virtual_output_remove(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actions_run(struct view *activator, struct server *server,
|
||||
struct wl_list *actions, uint32_t resize_edges)
|
||||
|
|
@ -915,6 +978,18 @@ 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);
|
||||
virtual_output_add(server, output_name);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE:
|
||||
{
|
||||
const char *output_name = action_get_str(action, "output_name", NULL);
|
||||
virtual_output_remove(server, output_name);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_INVALID:
|
||||
wlr_log(WLR_ERROR, "Not executing unknown action");
|
||||
break;
|
||||
|
|
|
|||
11
src/output.c
11
src/output.c
|
|
@ -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>
|
||||
|
|
@ -194,6 +196,13 @@ 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 outputs.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* We offer any display as available for lease, some apps like
|
||||
* gamescope, want to take ownership of a display when they can
|
||||
|
|
@ -201,7 +210,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);
|
||||
}
|
||||
|
|
|
|||
20
src/server.c
20
src/server.c
|
|
@ -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,24 @@ 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, "failed to create virtual output");
|
||||
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 overlayed 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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue