~emersion/public-inbox

wlr-randr: Support wlr-output-management version 3 v1 SUPERSEDED

Isaac Freund: 1
 Support wlr-output-management version 3

 2 files changed, 161 insertions(+), 8 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~emersion/public-inbox/patches/32841/mbox | git am -3
Learn more about email & git

[PATCH wlr-randr] Support wlr-output-management version 3 Export this patch

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