From ab3446091ba07387b1df9d6e717c06bd4179f96d Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 10 Mar 2019 12:18:22 +0100 Subject: [PATCH] output-management-v1: update protocol, add set_custom_mode --- .../wlr-output-management-unstable-v1.xml | 105 ++++++++++++------ rootston/output.c | 5 + types/wlr_output_management_v1.c | 33 +++++- 3 files changed, 108 insertions(+), 35 deletions(-) diff --git a/protocol/wlr-output-management-unstable-v1.xml b/protocol/wlr-output-management-unstable-v1.xml index 07586ca1..35f7ca4e 100644 --- a/protocol/wlr-output-management-unstable-v1.xml +++ b/protocol/wlr-output-management-unstable-v1.xml @@ -26,7 +26,7 @@ - This protocol exposes interfaces to get and change output device + This protocol exposes interfaces to obtain and modify output device configuration. Warning! The protocol described in this file is experimental and @@ -46,15 +46,23 @@ Output devices that display pixels (e.g. a physical monitor or a virtual output in a window) are represented as heads. Heads cannot be created nor - destroyed, but they can be enabled or disabled and their properties can be - changed. Each head may have one or more available modes. + destroyed by the client, but they can be enabled or disabled and their + properties can be changed. Each head may have one or more available modes. - Heads are advertised when the output manager is bound, and whenever they - appear. + Whenever a head appears (e.g. a monitor is plugged in), it will be + advertised via the head event. Immediately after the output manager is + bound, all current heads are advertised. - Whenever the number of heads or modes changes, the done event will be - sent. It carries a serial which can be used in a create_configuration - request to change heads properties. + Whenever a head's properties change, the relevant wlr_output_head events + will be sent. Not all head properties will be sent: only properties that + have changed need to. + + Whenever a head disappears (e.g. a monitor is unplugged), a + wlr_output_head.finished event will be sent. + + After one or more heads appear, change or disappear, the done event will + be sent. It carries a serial which can be used in a create_configuration + request to update heads properties. The information obtained from this protocol should only be used for output configuration purposes. This protocol is not designed to be a generic @@ -64,7 +72,9 @@ - This event introduces a new head. + This event introduces a new head. This happens whenever a new head + appears (e.g. a monitor is plugged in) or after the output manager is + bound. @@ -75,7 +85,8 @@ the output manager object and after any subsequent changes. This applies to child head and mode objects as well. In other words, this event is sent whenever a head or mode is created or destroyed and whenever one of - their properties has been changed. + their properties has been changed. Not all state is re-sent each time + the current configuration changes: only the actual changes are sent. This allows changes to the output configuration to be seen as atomic, even if they happen via multiple events. @@ -116,28 +127,21 @@ - A head is an output device. The difference with wl_output is that heads - are advertized even if they are turned off. A head object only advertises - properties and cannot be used directly to change them. In order to update - some properties, one needs to create a wlr_output_configuration object. + A head is an output device. The difference between a wl_output object and + a head is that heads are advertised even if they are turned off. A head + object only advertises properties and cannot be used directly to change + them. - A head has some read-only properties: mode, name, description and + A head has some read-only properties: modes, name, description and physical_size. These cannot be changed by clients. - enabled and current_mode are physical properties. Updating them might take - some time, depending on hardware limitations. + Other properties can be updated via a wlr_output_configuration object. - position, transform and scale are logical properties. They describe how - the output is mapped in the global compositor space. + Properties sent via this interface are applied atomically via the + wlr_output_manager.done event. No guarantees are made regarding the order + in which properties are sent. - - - If the head supports modes, this event is sent once per supported mode. - - - - This event describes the head name. @@ -168,7 +172,9 @@ 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'. + output via :1'. However, do not assume that the name is a reflection of + the make, model, serial of the underlying DRM connector or the display + name of the underlying X11 connection, etc. If the compositor implements xdg-output and this head is enabled, the xdg_output.description must report the same description. @@ -190,6 +196,14 @@ + + + This event introduces a mode for this head. It is sent once per + supported mode. + + + + This event describes whether the head is enabled. A disabled head is not @@ -204,7 +218,7 @@ This event describes the mode currently in use for this head. It is only - sent if the output is enabled and supports modes. + sent if the output is enabled. @@ -251,6 +265,10 @@ Some heads don't support output modes, in which case modes won't be advertised. + + Properties sent via this interface are applied atomically via the + wlr_output_manager.done event. No guarantees are made regarding the order + in which properties are sent. @@ -266,7 +284,8 @@ - This event describes the mode's fixed vertical refresh rate, if any. + This event describes the mode's fixed vertical refresh rate. It is only + sent if the mode has a fixed refresh rate. @@ -322,7 +341,7 @@ - Disable a head. The head's properties are irrelevant in this case. + Disable a head. @@ -363,6 +382,9 @@ tested them. Upon receiving this event, the client should destroy this object. + + If the current configuration has changed, events to describe the changes + will be sent followed by a wlr_output_manager.done event. @@ -404,12 +426,16 @@ This object is used by the client to update a single head's configuration. + + It is a protocol error to set the same property twice. - - - + + + + + @@ -419,6 +445,19 @@ + + + This request assigns a custom mode to the head. The size is given in + physical hardware units of the output device. If set to zero, the + refresh rate is unspecified. + + It is a protocol error to set both a mode and a custom mode. + + + + + + This request sets the head's position in the global compositor space. diff --git a/rootston/output.c b/rootston/output.c index 4afbfa7b..15737733 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -451,6 +451,11 @@ void handle_output_manager_apply(struct wl_listener *listener, void *data) { } if (config_head->state.mode != NULL) { ok &= wlr_output_set_mode(wlr_output, config_head->state.mode); + } else { + ok &= wlr_output_set_custom_mode(wlr_output, + config_head->state.custom_mode.width, + config_head->state.custom_mode.height, + config_head->state.custom_mode.refresh); } wlr_output_layout_add(desktop->layout, wlr_output, config_head->state.x, config_head->state.y); diff --git a/types/wlr_output_management_v1.c b/types/wlr_output_management_v1.c index f58273e9..f22fbc45 100644 --- a/types/wlr_output_management_v1.c +++ b/types/wlr_output_management_v1.c @@ -149,10 +149,11 @@ static void config_head_handle_set_mode(struct wl_client *client, } struct wlr_output_mode *mode = mode_from_resource(mode_resource); + struct wlr_output *output = config_head->state.output; - bool found = false; + bool found = (mode == NULL && wl_list_empty(&output->modes)); struct wlr_output_mode *m; - wl_list_for_each(m, &config_head->state.output->modes, link) { + wl_list_for_each(m, &output->modes, link) { if (mode == m) { found = true; break; @@ -167,6 +168,33 @@ static void config_head_handle_set_mode(struct wl_client *client, } config_head->state.mode = mode; + if (mode != NULL) { + config_head->state.custom_mode.width = 0; + config_head->state.custom_mode.height = 0; + config_head->state.custom_mode.refresh = 0; + } +} + +static void config_head_handle_set_custom_mode(struct wl_client *client, + struct wl_resource *config_head_resource, int32_t width, int32_t height, + int32_t refresh) { + struct wlr_output_configuration_head_v1 *config_head = + config_head_from_resource(config_head_resource); + if (config_head == NULL) { + return; + } + + if (width <= 0 || height <= 0 || refresh < 0) { + wl_resource_post_error(config_head_resource, + ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_CUSTOM_MODE, + "invalid custom mode"); + return; + } + + config_head->state.mode = NULL; + config_head->state.custom_mode.width = width; + config_head->state.custom_mode.height = height; + config_head->state.custom_mode.refresh = refresh; } static void config_head_handle_set_position(struct wl_client *client, @@ -221,6 +249,7 @@ static void config_head_handle_set_scale(struct wl_client *client, static const struct zwlr_output_configuration_head_v1_interface config_head_impl = { .set_mode = config_head_handle_set_mode, + .set_custom_mode = config_head_handle_set_custom_mode, .set_position = config_head_handle_set_position, .set_transform = config_head_handle_set_transform, .set_scale = config_head_handle_set_scale,