This implements version 3 of wlr-output-management-unstable-v1.
This adds the --adaptive-sync option and prints the output head's
make/model/serial if the server advertises a new enough protocol
version.
---
main.c | 65 ++++++++++-
.../wlr-output-management-unstable-v1.xml | 104 +++++++++++++++++-
2 files changed, 161 insertions(+), 8 deletions(-)
diff --git a/main.c b/main.c
index 5dc4456..260a0f3 100644
--- a/main.c
+++ b/main.c
@@ -29,6 +29,7 @@ struct randr_head {
struct wl_list link;
char *name, *description;
+ char *make, *model, *serial_number;
int32_t phys_width, phys_height; // mm
struct wl_list modes;
@@ -41,6 +42,7 @@ struct randr_head {
int32_t x, y;
enum wl_output_transform transform;
double scale;
+ bool adaptive_sync;
};
struct randr_state {
@@ -67,11 +69,20 @@ static void print_state(struct randr_state *state) {
struct randr_head *head;
wl_list_for_each(head, &state->heads, link) {
printf("%s \"%s\"\n", head->name, head->description);
+
+ if (zwlr_output_manager_v1_get_version(state->output_manager) >= 2) {
+ printf(" Make: %s\n", head->make);
+ printf(" Model: %s\n", head->model);
+ printf(" Serial: %s\n", head->serial_number);
+ }
+
if (head->phys_width > 0 && head->phys_height > 0) {
printf(" Physical size: %dx%d mm\n",
head->phys_width, head->phys_height);
}
+
printf(" Enabled: %s\n", head->enabled ? "yes" : "no");
+
if (!wl_list_empty(&head->modes)) {
printf(" Modes:\n");
struct randr_mode *mode;
@@ -105,6 +116,11 @@ static void print_state(struct randr_state *state) {
printf(" Position: %d,%d\n", head->x, head->y);
printf(" Transform: %s\n", output_transform_map[head->transform]);
printf(" Scale: %f\n", head->scale);
+
+ if (zwlr_output_manager_v1_get_version(state->output_manager) >= 3) {
+ printf(" Adaptive Sync: %s\n",
+ head->adaptive_sync ? "enabled" : "disabled");
+ }
}
state->running = false;
@@ -172,6 +188,11 @@ static void apply_state(struct randr_state *state, bool dry_run) {
head->transform);
zwlr_output_configuration_head_v1_set_scale(config_head,
wl_fixed_from_double(head->scale));
+
+ if (zwlr_output_manager_v1_get_version(state->output_manager) >= 3) {
+ zwlr_output_configuration_head_v1_set_adaptive_sync(config_head,
+ head->adaptive_sync);
+ }
}
if (dry_run) {
@@ -300,6 +321,30 @@ static void head_handle_finished(void *data,
free(head);
}
+static void head_handle_make(void *data,
+ struct zwlr_output_head_v1 *wlr_head, const char *make) {
+ struct randr_head *head = data;
+ head->make = strdup(make);
+}
+
+static void head_handle_model(void *data,
+ struct zwlr_output_head_v1 *wlr_head, const char *model) {
+ struct randr_head *head = data;
+ head->model = strdup(model);
+}
+
+static void head_handle_serial_number(void *data,
+ struct zwlr_output_head_v1 *wlr_head, const char *serial_number) {
+ struct randr_head *head = data;
+ head->serial_number = strdup(serial_number);
+}
+
+static void head_handle_adaptive_sync(void *data,
+ struct zwlr_output_head_v1 *wlr_head, int32_t enabled) {
+ struct randr_head *head = data;
+ head->adaptive_sync = !!enabled;
+}
+
static const struct zwlr_output_head_v1_listener head_listener = {
.name = head_handle_name,
.description = head_handle_description,
@@ -311,6 +356,10 @@ static const struct zwlr_output_head_v1_listener head_listener = {
.transform = head_handle_transform,
.scale = head_handle_scale,
.finished = head_handle_finished,
+ .make = head_handle_make,
+ .model = head_handle_model,
+ .serial_number = head_handle_serial_number,
+ .adaptive_sync = head_handle_adaptive_sync,
};
static void output_manager_handle_head(void *data,
@@ -350,8 +399,9 @@ static void registry_handle_global(void *data, struct wl_registry *registry,
struct randr_state *state = data;
if (strcmp(interface, zwlr_output_manager_v1_interface.name) == 0) {
+ uint32_t version_to_bind = version <= 3 ? version : 3;
state->output_manager = wl_registry_bind(registry, name,
- &zwlr_output_manager_v1_interface, 1);
+ &zwlr_output_manager_v1_interface, version_to_bind);
zwlr_output_manager_v1_add_listener(state->output_manager,
&output_manager_listener, state);
}
@@ -380,6 +430,7 @@ static const struct option long_options[] = {
{"pos", required_argument, 0, 0},
{"transform", required_argument, 0, 0},
{"scale", required_argument, 0, 0},
+ {"adaptive-sync", required_argument, 0, 0},
{0},
};
@@ -571,6 +622,15 @@ static bool parse_output_arg(struct randr_head *head,
}
head->scale = scale;
+ } else if (strcmp(name, "adaptive-sync") == 0) {
+ if (strcmp(value, "enabled") == 0) {
+ head->adaptive_sync = true;
+ } else if (strcmp(value, "disabed") == 0) {
+ head->adaptive_sync = false;
+ } else {
+ fprintf(stderr, "invalid adaptive sync state: %s\n", value);
+ return false;
+ }
} else {
fprintf(stderr, "invalid option: %s\n", name);
return false;
@@ -591,7 +651,8 @@ static const char usage[] =
" --preferred\n"
" --pos <x>,<y>\n"
" --transform normal|90|180|270|flipped|flipped-90|flipped-180|flipped-270\n"
- " --scale <factor>\n";
+ " --scale <factor>\n"
+ " --adaptive-sync enabled|disabled\n";
int main(int argc, char *argv[]) {
struct randr_state state = { .running = true };
diff --git a/protocol/wlr-output-management-unstable-v1.xml b/protocol/wlr-output-management-unstable-v1.xml
index 35f7ca4..c645614 100644
--- a/protocol/wlr-output-management-unstable-v1.xml
+++ b/protocol/wlr-output-management-unstable-v1.xml
@@ -39,7 +39,7 @@
interface version number is reset.
</description>
- <interface name="zwlr_output_manager_v1" version="1">
+ <interface name="zwlr_output_manager_v1" version="3">
<description summary="output device configuration manager">
This interface is a manager that allows reading and writing the current
output device configuration.
@@ -115,7 +115,7 @@
</description>
</request>
- <event name="finished">
+ <event name="finished" type="destructor">
<description summary="the compositor has finished with the manager">
This event indicates that the compositor is done sending manager events.
The compositor will destroy the object immediately after sending this
@@ -125,7 +125,7 @@
</event>
</interface>
- <interface name="zwlr_output_head_v1" version="1">
+ <interface name="zwlr_output_head_v1" version="3">
<description summary="output device">
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
@@ -257,9 +257,91 @@
resources associated with it.
</description>
</event>
+
+ <!-- Version 2 additions -->
+ <event name="make" since="2">
+ <description summary="head manufacturer">
+ This event describes the manufacturer of the head.
+
+ This must report the same make as the wl_output interface does in its
+ geometry event.
+
+ Together with the model and serial_number events the purpose is to
+ allow clients to recognize heads from previous sessions and for example
+ load head-specific configurations back.
+
+ It is not guaranteed this event will be ever sent. A reason for that
+ can be that the compositor does not have information about the make of
+ the head or the definition of a make is not sensible in the current
+ setup, for example in a virtual session. Clients can still try to
+ identify the head by available information from other events but should
+ be aware that there is an increased risk of false positives.
+
+ It is not recommended to display the make string in UI to users. For
+ that the string provided by the description event should be preferred.
+ </description>
+ <arg name="make" type="string"/>
+ </event>
+
+ <event name="model" since="2">
+ <description summary="head model">
+ This event describes the model of the head.
+
+ This must report the same model as the wl_output interface does in its
+ geometry event.
+
+ Together with the make and serial_number events the purpose is to
+ allow clients to recognize heads from previous sessions and for example
+ load head-specific configurations back.
+
+ It is not guaranteed this event will be ever sent. A reason for that
+ can be that the compositor does not have information about the model of
+ the head or the definition of a model is not sensible in the current
+ setup, for example in a virtual session. Clients can still try to
+ identify the head by available information from other events but should
+ be aware that there is an increased risk of false positives.
+
+ It is not recommended to display the model string in UI to users. For
+ that the string provided by the description event should be preferred.
+ </description>
+ <arg name="model" type="string"/>
+ </event>
+
+ <event name="serial_number" since="2">
+ <description summary="head serial number">
+ This event describes the serial number of the head.
+
+ Together with the make and model events the purpose is to allow clients
+ to recognize heads from previous sessions and for example load head-
+ specific configurations back.
+
+ It is not guaranteed this event will be ever sent. A reason for that
+ can be that the compositor does not have information about the serial
+ number of the head or the definition of a serial number is not sensible
+ in the current setup. Clients can still try to identify the head by
+ available information from other events but should be aware that there
+ is an increased risk of false positives.
+
+ It is not recommended to display the serial_number string in UI to
+ users. For that the string provided by the description event should be
+ preferred.
+ </description>
+ <arg name="serial_number" type="string"/>
+ </event>
+
+ <!-- Version 3 additions -->
+
+ <event name="adaptive_sync" since="3">
+ <description summary="current adaptive sync state">
+ This event describes whether adaptive sync is currently enabled for
+ the head or not. Adaptive sync is also known as Variable Refresh
+ Rate or VRR.
+ </description>
+ <arg name="enabled" type="int" summary="zero if disabled, non-zero if enabled"/>
+ </event>
</interface>
- <interface name="zwlr_output_mode_v1" version="1">
+ <interface name="zwlr_output_mode_v1" version="2">
<description summary="output mode">
This object describes an output mode.
@@ -305,7 +387,7 @@
</event>
</interface>
- <interface name="zwlr_output_configuration_v1" version="1">
+ <interface name="zwlr_output_configuration_v1" version="3">
<description summary="output configuration">
This object is used by the client to describe a full output configuration.
@@ -423,7 +505,7 @@
</request>
</interface>
- <interface name="zwlr_output_configuration_head_v1" version="1">
+ <interface name="zwlr_output_configuration_head_v1" version="3">
<description summary="head configuration">
This object is used by the client to update a single head's configuration.
@@ -479,5 +561,15 @@
</description>
<arg name="scale" type="fixed"/>
</request>
+
+ <!-- Version 3 additions -->
+
+ <request name="set_adaptive_sync" since="3">
+ <description summary="enable/disable adaptive sync">
+ This request enables/disables adaptive sync. Adaptive sync is also
+ known as Variable Refresh Rate or VRR.
+ </description>
+ <arg name="enabled" type="int" summary="zero to disable, non-zero to enable"/>
+ </request>
</interface>
</protocol>
--
2.36.1