From 884090ab78c06c6fb7b54153adc1ce07e8d1b3d1 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Tue, 13 Feb 2024 16:08:25 +1100 Subject: [PATCH] 146 capture and log xdg logical box (#157) * 138 add xdg-output-unstable-v1 and listen to output events * 138 handle zxdg-output lifecycle * 138 iwyu tweaking * 138 output logical size / position * 138 validate logical size / position * 147 bind and name the output managers * 147 validate logical size after success * 147 disambiguate names * 147 disambiguate names * 147 tidy * 147 remove debug logs and scale validation --- bld/vg.supp | 18 ++ inc/displ.h | 28 ++- inc/listeners.h | 15 +- inc/output.h | 38 +++ pro/xdg-output-unstable-v1.xml | 222 ++++++++++++++++++ src/displ.c | 19 +- src/info.c | 13 +- src/layout.c | 4 +- src/listener_registry.c | 75 ++++-- ...c => listener_zwlr_output_configuration.c} | 2 +- ...ner_head.c => listener_zwlr_output_head.c} | 6 +- ...nager.c => listener_zwlr_output_manager.c} | 14 +- ...ner_mode.c => listener_zwlr_output_mode.c} | 2 +- src/listener_zxdg_output.c | 64 +++++ src/output.c | 75 ++++++ src/server.c | 2 +- 16 files changed, 535 insertions(+), 62 deletions(-) create mode 100644 inc/output.h create mode 100644 pro/xdg-output-unstable-v1.xml rename src/{listener_output_configuration.c => listener_zwlr_output_configuration.c} (93%) rename src/{listener_head.c => listener_zwlr_output_head.c} (94%) rename src/{listener_output_manager.c => listener_zwlr_output_manager.c} (66%) rename src/{listener_mode.c => listener_zwlr_output_mode.c} (95%) create mode 100644 src/listener_zxdg_output.c create mode 100644 src/output.c diff --git a/bld/vg.supp b/bld/vg.supp index 6421f1ce..ce3f509f 100644 --- a/bld/vg.supp +++ b/bld/vg.supp @@ -24,6 +24,24 @@ fun:main } +{ + g_object_new_valist - from evdev + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:g_object_new_valist + fun:g_object_new + ... +} +{ + evdev_device_create + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:evdev_device_create + fun:device_added +} + { glib-g_malloc Memcheck:Leak diff --git a/inc/displ.h b/inc/displ.h index 1f7f6bb6..d66295b7 100644 --- a/inc/displ.h +++ b/inc/displ.h @@ -2,7 +2,11 @@ #define DISPL_H #include -#include + +// IWYU pragma: begin_keep +#include "wlr-output-management-unstable-v1.h" +#include "xdg-output-unstable-v1.h" +// IWYU pragma: end_keep enum ConfigState { IDLE = 0, @@ -14,17 +18,21 @@ enum ConfigState { struct Displ { // global - struct wl_display *display; struct wl_registry *registry; - uint32_t name; - - // output manager - struct zwlr_output_manager_v1 *output_manager; - uint32_t serial; - char *interface; - uint32_t output_manager_version; + struct wl_display *display; - bool have_fractional_scale_v1; + // wlroots output manager + struct zwlr_output_manager_v1 *zwlr_output_manager; + uint32_t zwlr_output_manager_name; + uint32_t zwlr_output_manager_version; + char *zwlr_output_manager_interface; + uint32_t zwlr_output_manager_serial; + + // wayland output manager + struct zxdg_output_manager_v1 *zxdg_output_manager; + uint32_t zxdg_output_manager_name; + uint32_t zxdg_output_manager_version; + char *zxdg_output_manager_interface; enum ConfigState config_state; }; diff --git a/inc/listeners.h b/inc/listeners.h index c8eff634..c60b1c2e 100644 --- a/inc/listeners.h +++ b/inc/listeners.h @@ -4,15 +4,16 @@ #define ZWLR_OUTPUT_MANAGER_V1_VERSION 4 #define ZWLR_OUTPUT_MANAGER_V1_VERSION_MIN 2 -// data const struct wl_registry_listener *registry_listener(void); -const struct zwlr_output_manager_v1_listener *output_manager_listener(void); -const struct zwlr_output_head_v1_listener *head_listener(void); -const struct zwlr_output_head_v1_listener *head_listener_min(void); -const struct zwlr_output_mode_v1_listener *mode_listener(void); -// config -const struct zwlr_output_configuration_v1_listener *output_configuration_listener(void); +const struct zwlr_output_manager_v1_listener *zwlr_output_manager_listener(void); +const struct zwlr_output_head_v1_listener *zwlr_output_head_listener(void); +const struct zwlr_output_head_v1_listener *zwlr_output_head_listener_min(void); +const struct zwlr_output_mode_v1_listener *zwlr_output_mode_listener(void); + +const struct zwlr_output_configuration_v1_listener *zwlr_output_configuration_listener(void); + +const struct zxdg_output_v1_listener *zxdg_output_listener(void); #endif // LISTENERS_H diff --git a/inc/output.h b/inc/output.h new file mode 100644 index 00000000..0f106806 --- /dev/null +++ b/inc/output.h @@ -0,0 +1,38 @@ +#ifndef OUTPUT_H +#define OUTPUT_H + +#include +#include + +#include "xdg-output-unstable-v1.h" + +struct Output { + struct wl_output *wl_output; + uint32_t wl_output_name; + + struct zxdg_output_v1 *zxdg_output; + + // wlr-output-management-unstable-v1.xml states that the names and descriptions must match hence we can map them + char *name; + char *description; + + int32_t logical_x; + int32_t logical_y; + int32_t logical_width; + int32_t logical_height; +}; + +// instantiate a new output and create an xdg output listener, appending to outputs +// NULL on failure to retrieve xdg output +struct Output *output_init(struct wl_output *wl_output, const uint32_t wl_output_name, struct zxdg_output_manager_v1 *zxdg_output_manager); + +// output matching (head) name +const struct Output *output_for_name(const char *name); + +// destroy all outputs, clearing outputs +void output_destroy_all(void); + +// destroy an output matching name, removing from outputs +void output_destroy_by_wl_output_name(const uint32_t wl_output_name); + +#endif // OUTPUT_H diff --git a/pro/xdg-output-unstable-v1.xml b/pro/xdg-output-unstable-v1.xml new file mode 100644 index 00000000..5d536aa9 --- /dev/null +++ b/pro/xdg-output-unstable-v1.xml @@ -0,0 +1,222 @@ + + + + + Copyright © 2017 Red Hat Inc. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This protocol aims at describing outputs in a way which is more in line + with the concept of an output on desktop oriented systems. + + Some information are more specific to the concept of an output for + a desktop oriented system and may not make sense in other applications, + such as IVI systems for example. + + Typically, the global compositor space on a desktop system is made of + a contiguous or overlapping set of rectangular regions. + + The logical_position and logical_size events defined in this protocol + might provide information identical to their counterparts already + available from wl_output, in which case the information provided by this + protocol should be preferred to their equivalent in wl_output. The goal is + to move the desktop specific concepts (such as output location within the + global compositor space, etc.) out of the core wl_output protocol. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible + changes may be added together with the corresponding interface + version bump. + Backward incompatible changes are done by bumping the version + number in the protocol and interface names and resetting the + interface version. Once the protocol is to be declared stable, + the 'z' prefix and the version number in the protocol and + interface names are removed and the interface version number is + reset. + + + + + A global factory interface for xdg_output objects. + + + + + Using this request a client can tell the server that it is not + going to use the xdg_output_manager object anymore. + + Any objects already created through this instance are not affected. + + + + + + This creates a new xdg_output object for the given wl_output. + + + + + + + + + An xdg_output describes part of the compositor geometry. + + This typically corresponds to a monitor that displays part of the + compositor space. + + For objects version 3 onwards, after all xdg_output properties have been + sent (when the object is created and when properties are updated), a + wl_output.done event is sent. This allows changes to the output + properties to be seen as atomic, even if they happen via multiple events. + + + + + Using this request a client can tell the server that it is not + going to use the xdg_output object anymore. + + + + + + The position event describes the location of the wl_output within + the global compositor space. + + The logical_position event is sent after creating an xdg_output + (see xdg_output_manager.get_xdg_output) and whenever the location + of the output changes within the global compositor space. + + + + + + + + The logical_size event describes the size of the output in the + global compositor space. + + Most regular Wayland clients should not pay attention to the + logical size and would rather rely on xdg_shell interfaces. + + Some clients such as Xwayland, however, need this to configure + their surfaces in the global compositor space as the compositor + may apply a different scale from what is advertised by the output + scaling property (to achieve fractional scaling, for example). + + For example, for a wl_output mode 3840×2160 and a scale factor 2: + + - A compositor not scaling the monitor viewport in its compositing space + will advertise a logical size of 3840×2160, + + - A compositor scaling the monitor viewport with scale factor 2 will + advertise a logical size of 1920×1080, + + - A compositor scaling the monitor viewport using a fractional scale of + 1.5 will advertise a logical size of 2560×1440. + + For example, for a wl_output mode 1920×1080 and a 90 degree rotation, + the compositor will advertise a logical size of 1080x1920. + + The logical_size event is sent after creating an xdg_output + (see xdg_output_manager.get_xdg_output) and whenever the logical + size of the output changes, either as a result of a change in the + applied scale or because of a change in the corresponding output + mode(see wl_output.mode) or transform (see wl_output.transform). + + + + + + + + This event is sent after all other properties of an xdg_output + have been sent. + + This allows changes to the xdg_output properties to be seen as + atomic, even if they happen via multiple events. + + For objects version 3 onwards, this event is deprecated. Compositors + are not required to send it anymore and must send wl_output.done + instead. + + + + + + + + Many compositors will assign names to their outputs, show them to the + user, allow them to be configured by name, etc. The client may wish to + know this name as well to offer the user similar behaviors. + + The naming convention is compositor defined, but limited to + alphanumeric characters and dashes (-). Each name is unique among all + wl_output globals, but if a wl_output global is destroyed the same name + may be reused later. The names will also remain consistent across + sessions with the same hardware and software configuration. + + Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do + not assume that the name is a reflection of an underlying DRM + connector, X11 connection, etc. + + The name event is sent after creating an xdg_output (see + xdg_output_manager.get_xdg_output). This event is only sent once per + xdg_output, and the name does not change over the lifetime of the + wl_output global. + + This event is deprecated, instead clients should use wl_output.name. + Compositors must still support this event. + + + + + + + Many compositors can produce human-readable descriptions of their + outputs. The client may wish to know this description as well, to + communicate the user for various purposes. + + The description is a UTF-8 string with no convention defined for its + contents. Examples might include 'Foocorp 11" Display' or 'Virtual X11 + output via :1'. + + The description event is sent after creating an xdg_output (see + xdg_output_manager.get_xdg_output) and whenever the description + changes. The description is optional, and may not be sent at all. + + For objects of version 2 and lower, this event is only sent once per + xdg_output, and the description does not change over the lifetime of + the wl_output global. + + This event is deprecated, instead clients should use + wl_output.description. Compositors must still support this event. + + + + + + diff --git a/src/displ.c b/src/displ.c index 2851b9cf..c5271e62 100644 --- a/src/displ.c +++ b/src/displ.c @@ -7,7 +7,10 @@ #include "global.h" #include "listeners.h" #include "log.h" +#include "output.h" #include "process.h" +#include "wlr-output-management-unstable-v1.h" +#include "xdg-output-unstable-v1.h" void displ_init(void) { @@ -29,7 +32,7 @@ void displ_init(void) { return; } - if (!displ->output_manager) { + if (!displ->zwlr_output_manager) { log_error("\ncompositor does not support WLR output manager protocol, exiting"); wd_exit(EXIT_FAILURE); return; @@ -38,15 +41,23 @@ void displ_init(void) { void displ_destroy(void) { - if (displ->output_manager) { - wl_proxy_destroy((struct wl_proxy*) displ->output_manager); + output_destroy_all(); + + if (displ->zwlr_output_manager) { + zwlr_output_manager_v1_destroy(displ->zwlr_output_manager); + } + + if (displ->zxdg_output_manager) { + zxdg_output_manager_v1_destroy(displ->zxdg_output_manager); } wl_registry_destroy(displ->registry); wl_display_disconnect(displ->display); - free(displ->interface); + free(displ->zwlr_output_manager_interface); + + free(displ->zxdg_output_manager_interface); free(displ); displ = NULL; diff --git a/src/info.c b/src/info.c index 0aa9543a..160c0868 100644 --- a/src/info.c +++ b/src/info.c @@ -8,9 +8,10 @@ #include "convert.h" #include "head.h" #include "lid.h" -#include "slist.h" #include "log.h" #include "mode.h" +#include "output.h" +#include "slist.h" #include "wlr-output-management-unstable-v1.h" void info_user_mode_string(struct UserMode *user_mode, char *buf, size_t nbuf) { @@ -295,12 +296,20 @@ void print_cfg_commands(enum LogThreshold t, struct Cfg *cfg) { } void print_head_current(enum LogThreshold t, struct Head *head) { + static const struct Output *output = NULL; + if (!head) return; if (head->current.enabled) { log_(t, " scale: %.3f (%.3f)", wl_fixed_to_double(head->current.scale), mode_scale(head->current.mode)); - log_(t, " position: %d,%d", head->current.x, head->current.y); + + if ((output = output_for_name(head->name))) { + log_(t, " size: %dx%d", output->logical_width, output->logical_height); + log_(t, " position: %d,%d", output->logical_x, output->logical_y); + } else { + log_(t, " position: %d,%d", head->current.x, head->current.y); + } if (head->current.transform) { log_(t, " transform: %s", transform_name(head->current.transform)); } diff --git a/src/layout.c b/src/layout.c index 4c24d08b..cb26990a 100644 --- a/src/layout.c +++ b/src/layout.c @@ -277,8 +277,8 @@ void apply(void) { return; // passed into our configuration listener - struct zwlr_output_configuration_v1 *zwlr_config = zwlr_output_manager_v1_create_configuration(displ->output_manager, displ->serial); - zwlr_output_configuration_v1_add_listener(zwlr_config, output_configuration_listener(), displ); + struct zwlr_output_configuration_v1 *zwlr_config = zwlr_output_manager_v1_create_configuration(displ->zwlr_output_manager, displ->zwlr_output_manager_serial); + zwlr_output_configuration_v1_add_listener(zwlr_config, zwlr_output_configuration_listener(), displ); if ((head_changing_mode = slist_find_val(heads, head_current_mode_not_desired))) { diff --git a/src/listener_registry.c b/src/listener_registry.c index afc04424..673f30d4 100644 --- a/src/listener_registry.c +++ b/src/listener_registry.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -9,10 +8,51 @@ #include "displ.h" #include "log.h" +#include "output.h" #include "process.h" #include "fractional-scale-v1.h" +#include "xdg-output-unstable-v1.h" #include "wlr-output-management-unstable-v1.h" +static void bind_zwlr_output_manager(struct Displ *displ, + struct wl_registry *wl_registry, + uint32_t name, + const char *interface, + uint32_t version) { + + displ->zwlr_output_manager_name = name; + displ->zwlr_output_manager_version = version; + displ->zwlr_output_manager_interface = strdup(interface); + displ->zwlr_output_manager = wl_registry_bind(wl_registry, name, &zwlr_output_manager_v1_interface, displ->zwlr_output_manager_version); + + zwlr_output_manager_v1_add_listener(displ->zwlr_output_manager, zwlr_output_manager_listener(), displ); +} + +static void bind_zxdg_output_manager(struct Displ *displ, + struct wl_registry *wl_registry, + uint32_t name, + const char *interface, + uint32_t version) { + + displ->zxdg_output_manager_name = name; + displ->zxdg_output_manager_version = version; + displ->zxdg_output_manager_interface = strdup(interface); + displ->zxdg_output_manager = wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, displ->zxdg_output_manager_version); +} + +static void bind_wl_output(struct Displ *displ, + struct wl_registry *wl_registry, + uint32_t name, + const char *interface, + uint32_t version) { + + struct wl_output *wl_output = wl_registry_bind(wl_registry, name, &wl_output_interface, version); + + if (!output_init(wl_output, name, displ->zxdg_output_manager)) { + wl_output_destroy(wl_output); + } +} + // Displ data static void global(void *data, @@ -20,27 +60,14 @@ static void global(void *data, uint32_t name, const char *interface, uint32_t version) { - struct Displ *displ = data; if (strcmp(interface, zwlr_output_manager_v1_interface.name) == 0) { - displ->name = name; - displ->interface = strdup(interface); - - if (version < ZWLR_OUTPUT_MANAGER_V1_VERSION_MIN) { - log_error("\nwlr-output-management version %d found, minimum %d required, exiting. Consider upgrading your compositor.", version, ZWLR_OUTPUT_MANAGER_V1_VERSION_MIN); - wd_exit(EXIT_FAILURE); - } else if (version < ZWLR_OUTPUT_MANAGER_V1_VERSION) { - log_warn("\nwlr-output-management version %d found; %d required for full functionality. Consider upgrading your compositor.", version, ZWLR_OUTPUT_MANAGER_V1_VERSION); - displ->output_manager_version = ZWLR_OUTPUT_MANAGER_V1_VERSION_MIN; - } else { - displ->output_manager_version = ZWLR_OUTPUT_MANAGER_V1_VERSION; - } - - displ->output_manager = wl_registry_bind(wl_registry, name, &zwlr_output_manager_v1_interface, displ->output_manager_version); - - zwlr_output_manager_v1_add_listener(displ->output_manager, output_manager_listener(), displ); + bind_zwlr_output_manager(data, wl_registry, name, interface, version); + } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { + bind_zxdg_output_manager(data, wl_registry, name, interface, version); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + bind_wl_output(data, wl_registry, name, interface, version); } else if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0) { - displ->have_fractional_scale_v1 = true; log_debug("\nCompositor supports %s version %d", interface, version); } } @@ -50,13 +77,13 @@ static void global_remove(void *data, uint32_t name) { struct Displ *displ = data; - // only interested in the WLR interface - if (!displ || displ->name != name) - return; + output_destroy_by_wl_output_name(name); // a "who cares?" situation in the WLR examples - log_info("\nDisplay's output manager has been removed, exiting"); - wd_exit(EXIT_SUCCESS); + if (displ && displ->zwlr_output_manager_name == name) { + log_info("\nDisplay's output manager has been removed, exiting"); + wd_exit(EXIT_SUCCESS); + } } static const struct wl_registry_listener listener = { diff --git a/src/listener_output_configuration.c b/src/listener_zwlr_output_configuration.c similarity index 93% rename from src/listener_output_configuration.c rename to src/listener_zwlr_output_configuration.c index d88743df..3c16d593 100644 --- a/src/listener_output_configuration.c +++ b/src/listener_zwlr_output_configuration.c @@ -47,7 +47,7 @@ static const struct zwlr_output_configuration_v1_listener listener = { .cancelled = cancelled, }; -const struct zwlr_output_configuration_v1_listener *output_configuration_listener(void) { +const struct zwlr_output_configuration_v1_listener *zwlr_output_configuration_listener(void) { return &listener; } diff --git a/src/listener_head.c b/src/listener_zwlr_output_head.c similarity index 94% rename from src/listener_head.c rename to src/listener_zwlr_output_head.c index 5c917e76..719b2c4c 100644 --- a/src/listener_head.c +++ b/src/listener_zwlr_output_head.c @@ -49,7 +49,7 @@ static void mode(void *data, slist_append(&head->modes, mode); - zwlr_output_mode_v1_add_listener(zwlr_output_mode_v1, mode_listener(), mode); + zwlr_output_mode_v1_add_listener(zwlr_output_mode_v1, zwlr_output_mode_listener(), mode); } static void enabled(void *data, @@ -183,11 +183,11 @@ static const struct zwlr_output_head_v1_listener listener = { .adaptive_sync = adaptive_sync, }; -const struct zwlr_output_head_v1_listener *head_listener_min(void) { +const struct zwlr_output_head_v1_listener *zwlr_output_head_listener_min(void) { return &listener_min; } -const struct zwlr_output_head_v1_listener *head_listener(void) { +const struct zwlr_output_head_v1_listener *zwlr_output_head_listener(void) { return &listener; } diff --git a/src/listener_output_manager.c b/src/listener_zwlr_output_manager.c similarity index 66% rename from src/listener_output_manager.c rename to src/listener_zwlr_output_manager.c index 7a06b1af..20d14200 100644 --- a/src/listener_output_manager.c +++ b/src/listener_zwlr_output_manager.c @@ -23,10 +23,10 @@ static void head(void *data, slist_append(&heads, head); slist_append(&heads_arrived, head); - if (displ->output_manager_version == ZWLR_OUTPUT_MANAGER_V1_VERSION_MIN) { - zwlr_output_head_v1_add_listener(zwlr_output_head_v1, head_listener_min(), head); + if (displ->zwlr_output_manager_version == ZWLR_OUTPUT_MANAGER_V1_VERSION_MIN) { + zwlr_output_head_v1_add_listener(zwlr_output_head_v1, zwlr_output_head_listener_min(), head); } else { - zwlr_output_head_v1_add_listener(zwlr_output_head_v1, head_listener(), head); + zwlr_output_head_v1_add_listener(zwlr_output_head_v1, zwlr_output_head_listener(), head); } } @@ -35,15 +35,15 @@ static void done(void *data, uint32_t serial) { struct Displ *displ = data; - displ->serial = serial; + displ->zwlr_output_manager_serial = serial; } static void finished(void *data, struct zwlr_output_manager_v1 *zwlr_output_manager_v1) { struct Displ *displ = data; - if (displ->output_manager) { - zwlr_output_manager_v1_destroy(displ->output_manager); + if (displ->zwlr_output_manager) { + zwlr_output_manager_v1_destroy(displ->zwlr_output_manager); } } @@ -53,7 +53,7 @@ static const struct zwlr_output_manager_v1_listener listener = { .finished = finished, }; -const struct zwlr_output_manager_v1_listener *output_manager_listener(void) { +const struct zwlr_output_manager_v1_listener *zwlr_output_manager_listener(void) { return &listener; } diff --git a/src/listener_mode.c b/src/listener_zwlr_output_mode.c similarity index 95% rename from src/listener_mode.c rename to src/listener_zwlr_output_mode.c index 8e09602c..cf4358c9 100644 --- a/src/listener_mode.c +++ b/src/listener_zwlr_output_mode.c @@ -66,7 +66,7 @@ static const struct zwlr_output_mode_v1_listener listener = { .finished = finished, }; -const struct zwlr_output_mode_v1_listener *mode_listener(void) { +const struct zwlr_output_mode_v1_listener *zwlr_output_mode_listener(void) { return &listener; } diff --git a/src/listener_zxdg_output.c b/src/listener_zxdg_output.c new file mode 100644 index 00000000..2c369ad6 --- /dev/null +++ b/src/listener_zxdg_output.c @@ -0,0 +1,64 @@ +#include +#include + +#include "listeners.h" + +#include "output.h" +#include "xdg-output-unstable-v1.h" + +// Output data + +void zxdg_output_logical_position(void *data, + struct zxdg_output_v1 *zxdg_output_v1, + int32_t x, + int32_t y) { + struct Output *output = data; + + output->logical_x = x; + output->logical_y = y; +} + +void zxdg_output_logical_size(void *data, + struct zxdg_output_v1 *zxdg_output_v1, + int32_t width, + int32_t height) { + struct Output *output = data; + + output->logical_width = width; + output->logical_height = height; +} + +// deprecated +void zxdg_output_done(void *data, + struct zxdg_output_v1 *zxdg_output_v1) { +} + +void zxdg_output_name(void *data, + struct zxdg_output_v1 *zxdg_output_v1, + const char *name) { + struct Output *output = data; + + output->name = strdup(name); +} + +void zxdg_output_description(void *data, + struct zxdg_output_v1 *zxdg_output_v1, + const char *description) { + + struct Output *output = data; + + output->description = strdup(description); +} + +static const struct zxdg_output_v1_listener listener = { + .logical_position = zxdg_output_logical_position, + .logical_size = zxdg_output_logical_size, + .done = zxdg_output_done, + .name = zxdg_output_name, + .description = zxdg_output_description, +}; + +const struct zxdg_output_v1_listener *zxdg_output_listener(void) { + return &listener; +} + diff --git a/src/output.c b/src/output.c new file mode 100644 index 00000000..d4859a70 --- /dev/null +++ b/src/output.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include + +#include "output.h" + +#include "listeners.h" +#include "itable.h" +#include "xdg-output-unstable-v1.h" + +const struct ITable *outputs; // by wl_output_name + +struct Output *output_init(struct wl_output *wl_output, const uint32_t wl_output_name, struct zxdg_output_manager_v1 *zxdg_output_manager) { + if (!wl_output || !zxdg_output_manager) + return NULL; + + struct zxdg_output_v1 *zxdg_output = zxdg_output_manager_v1_get_xdg_output(zxdg_output_manager, wl_output); + if (!zxdg_output) + return NULL; + + struct Output *output = calloc(1, sizeof(struct Output)); + output->wl_output = wl_output; + output->wl_output_name = wl_output_name; + output->zxdg_output = zxdg_output; + + if (!outputs) + outputs = itable_init(5, 5); + itable_put(outputs, wl_output_name, output); + + zxdg_output_v1_add_listener(zxdg_output, zxdg_output_listener(), output); + + return output; +} + +const struct Output *output_for_name(const char *name) { + const struct Output *output = NULL; + + const struct ITableIter *i = NULL; + for (i = itable_iter(outputs); i; i = itable_next(i)) { + output = i->val; + if (output && output->name && strcmp(output->name, name) == 0) { + break; + } else { + output = NULL; + } + } + itable_iter_free(i); + + return output; +} + +void destroy(const void *o) { + if (!o) + return; + + struct Output *output = (struct Output*)o; + + zxdg_output_v1_destroy(output->zxdg_output); + wl_output_destroy(output->wl_output); + + free(output->name); + free(output->description); + + free(output); +} + +void output_destroy_all(void) { + itable_free_vals(outputs, destroy); +} + +void output_destroy_by_wl_output_name(const uint32_t wl_output_name) { + destroy(itable_remove(outputs, wl_output_name)); +} + diff --git a/src/server.c b/src/server.c index bbd6fb70..67d17aec 100644 --- a/src/server.c +++ b/src/server.c @@ -164,7 +164,7 @@ int loop(void) { // always read and dispatch wayland events; stop the file descriptor from getting stale _wl_display_read_events(displ->display, FL); _wl_display_dispatch_pending(displ->display, FL); - if (!displ->output_manager) { + if (!displ->zwlr_output_manager) { log_info("\nDisplay's output manager has departed, exiting"); wd_exit(EXIT_SUCCESS); return EXIT_SUCCESS;