From 6b26089353d7b82982d079a8dee81675dac8ec1a Mon Sep 17 00:00:00 2001 From: Quantum Date: Sat, 20 Feb 2021 22:48:48 -0500 Subject: [PATCH] [client] wayland: keep track of wl_output scale information This will later be used to control the size of the underlying EGL buffers in order to handle high DPI. --- client/displayservers/Wayland/CMakeLists.txt | 1 + client/displayservers/Wayland/output.c | 126 +++++++++++++++++++ client/displayservers/Wayland/registry.c | 6 +- client/displayservers/Wayland/wayland.c | 4 + client/displayservers/Wayland/wayland.h | 17 +++ 5 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 client/displayservers/Wayland/output.c diff --git a/client/displayservers/Wayland/CMakeLists.txt b/client/displayservers/Wayland/CMakeLists.txt index bfefd0c0..a4b496c6 100644 --- a/client/displayservers/Wayland/CMakeLists.txt +++ b/client/displayservers/Wayland/CMakeLists.txt @@ -15,6 +15,7 @@ add_library(displayserver_Wayland STATIC gl.c idle.c input.c + output.c poll.c state.c registry.c diff --git a/client/displayservers/Wayland/output.c b/client/displayservers/Wayland/output.c new file mode 100644 index 00000000..a13c380b --- /dev/null +++ b/client/displayservers/Wayland/output.c @@ -0,0 +1,126 @@ +/* +Looking Glass - KVM FrameRelay (KVMFR) Client +Copyright (C) 2021 Guanzhong Chen (quantum2048@gmail.com) +Copyright (C) 2021 Tudor Brindus (contact@tbrindus.ca) +https://looking-glass.io + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "wayland.h" + +#include +#include + +#include + +#include "common/debug.h" + +static void outputGeometryHandler(void * data, struct wl_output * output, int32_t x, int32_t y, + int32_t physical_width, int32_t physical_height, int32_t subpixel, const char * make, + const char * model, int32_t output_transform) +{ + // Do nothing. +} + +static void outputModeHandler(void * data, struct wl_output * wl_output, uint32_t flags, + int32_t width, int32_t height, int32_t refresh) +{ + // Do nothing. +} + +static void outputDoneHandler(void * data, struct wl_output * output) +{ + // Do nothing. +} + +static void outputScaleHandler(void * opaque, struct wl_output * output, int32_t scale) +{ + struct WaylandOutput * node = opaque; + node->scale = scale; +} + +static const struct wl_output_listener outputListener = { + .geometry = outputGeometryHandler, + .mode = outputModeHandler, + .done = outputDoneHandler, + .scale = outputScaleHandler, +}; + +bool waylandOutputInit(void) +{ + wl_list_init(&wlWm.outputs); + return true; +} + +void waylandOutputFree(void) +{ + struct WaylandOutput * node; + struct WaylandOutput * temp; + wl_list_for_each_safe(node, temp, &wlWm.outputs, link) + { + wl_output_release(node->output); + wl_list_remove(&node->link); + free(node); + } +} + +void waylandOutputBind(uint32_t name) +{ + struct WaylandOutput * node = malloc(sizeof(struct WaylandOutput)); + if (!node) + return; + + node->name = name; + node->scale = 0; + node->output = wl_registry_bind(wlWm.registry, name, + &wl_output_interface, 3); + + if (!node->output) + { + DEBUG_ERROR("Failed to bind to wl_output %u\n", name); + free(node); + return; + } + + wl_output_add_listener(node->output, &outputListener, node); + wl_list_insert(&wlWm.outputs, &node->link); +} + +void waylandOutputTryUnbind(uint32_t name) +{ + struct WaylandOutput * node; + + wl_list_for_each(node, &wlWm.outputs, link) + { + if (node->name == name) + { + wl_output_release(node->output); + wl_list_remove(&node->link); + free(node); + break; + } + } +} + +int32_t waylandOutputGetScale(struct wl_output * output) +{ + struct WaylandOutput * node; + + wl_list_for_each(node, &wlWm.outputs, link) + if (node->output == output) + return node->scale; + return 0; +} + diff --git a/client/displayservers/Wayland/registry.c b/client/displayservers/Wayland/registry.c index 1de13c18..ed526bf5 100644 --- a/client/displayservers/Wayland/registry.c +++ b/client/displayservers/Wayland/registry.c @@ -30,7 +30,9 @@ Place, Suite 330, Boston, MA 02111-1307 USA static void registryGlobalHandler(void * data, struct wl_registry * registry, uint32_t name, const char * interface, uint32_t version) { - if (!strcmp(interface, wl_seat_interface.name) && !wlWm.seat) + if (!strcmp(interface, wl_output_interface.name)) + waylandOutputBind(name); + else if (!strcmp(interface, wl_seat_interface.name) && !wlWm.seat) wlWm.seat = wl_registry_bind(wlWm.registry, name, &wl_seat_interface, 1); else if (!strcmp(interface, wl_shm_interface.name)) wlWm.shm = wl_registry_bind(wlWm.registry, name, &wl_shm_interface, 1); @@ -61,7 +63,7 @@ static void registryGlobalHandler(void * data, struct wl_registry * registry, static void registryGlobalRemoveHandler(void * data, struct wl_registry * registry, uint32_t name) { - // Do nothing. + waylandOutputTryUnbind(name); } static const struct wl_registry_listener registryListener = { diff --git a/client/displayservers/Wayland/wayland.c b/client/displayservers/Wayland/wayland.c index 7bdb7047..b6a1922c 100644 --- a/client/displayservers/Wayland/wayland.c +++ b/client/displayservers/Wayland/wayland.c @@ -97,6 +97,9 @@ static bool waylandInit(const LG_DSInitParams params) if (!waylandPollInit()) return false; + if (!waylandOutputInit()) + return false; + if (!waylandRegistryInit()) return false; @@ -139,6 +142,7 @@ static void waylandFree(void) waylandIdleFree(); waylandWindowFree(); waylandInputFree(); + waylandOutputFree(); waylandRegistryFree(); wl_display_disconnect(wlWm.display); } diff --git a/client/displayservers/Wayland/wayland.h b/client/displayservers/Wayland/wayland.h index 147f4e6a..b52686ad 100644 --- a/client/displayservers/Wayland/wayland.h +++ b/client/displayservers/Wayland/wayland.h @@ -51,6 +51,14 @@ struct WaylandPoll struct wl_list link; }; +struct WaylandOutput +{ + uint32_t name; + int32_t scale; + struct wl_output * output; + struct wl_list link; +}; + struct WaylandDSState { bool pointerGrabbed; @@ -108,6 +116,8 @@ struct WaylandDSState struct zwp_idle_inhibit_manager_v1 * idleInhibitManager; struct zwp_idle_inhibitor_v1 * idleInhibitor; + struct wl_list outputs; // WaylandOutput::link + struct wl_list poll; // WaylandPoll::link struct wl_list pollFree; // WaylandPoll::link LG_Lock pollLock; @@ -200,6 +210,13 @@ void waylandUngrabPointer(void); void waylandRealignPointer(void); void waylandWarpPointer(int x, int y, bool exiting); +// output module +bool waylandOutputInit(void); +void waylandOutputFree(void); +void waylandOutputBind(uint32_t name); +void waylandOutputTryUnbind(uint32_t name); +int32_t waylandOutputGetScale(struct wl_output * output); + // poll module bool waylandPollInit(void); void waylandWait(unsigned int time);