[PATCH weston v6 17/73] libweston: add weston_head_is_device_changed() API

Pekka Paalanen ppaalanen at gmail.com
Fri Feb 16 14:57:02 UTC 2018


From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>

Reacting to DRM hotplug events is racy. It is theoretically possible to
get hotplug events for a quick swap from one monitor to another and
process both only after the new monitor is connected. Hence it is
possible for display device information to change without going through
a disconnected state for the head.

To support such cases, add API to allow detecting it in the compositor.

v6:
- change str_null_neq() to str_null_eq()
- rename weston_head_condition_device_changed()
- move the condition from weston_head_set_device_changed() to the
callers

Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
 libweston/compositor.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++--
 libweston/compositor.h |  7 ++++
 2 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/libweston/compositor.c b/libweston/compositor.c
index d3c0d573..02d92faf 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -4715,6 +4715,28 @@ weston_head_release(struct weston_head *head)
 	wl_list_remove(&head->compositor_link);
 }
 
+static void
+weston_head_set_device_changed(struct weston_head *head)
+{
+	head->device_changed = true;
+
+	if (head->compositor)
+		weston_compositor_schedule_heads_changed(head->compositor);
+}
+
+/** String equal comparison with NULLs being equal */
+static bool
+str_null_eq(const char *a, const char *b)
+{
+	if (!a && !b)
+		return true;
+
+	if (!!a != !!b)
+		return false;
+
+	return strcmp(a, b) == 0;
+}
+
 /** Store monitor make, model and serial number
  *
  * \param head The head to modify.
@@ -4725,6 +4747,8 @@ weston_head_release(struct weston_head *head)
  * \param serialno The monitor serial number, a made-up string, or NULL for
  * none.
  *
+ * This may set the device_changed flag.
+ *
  * \memberof weston_head
  * \internal
  */
@@ -4734,6 +4758,11 @@ weston_head_set_monitor_strings(struct weston_head *head,
 				const char *model,
 				const char *serialno)
 {
+	if (str_null_eq(head->make, make) &&
+	    str_null_eq(head->model, model) &&
+	    str_null_eq(head->serial_number, serialno))
+		return;
+
 	free(head->make);
 	free(head->model);
 	free(head->serial_number);
@@ -4741,6 +4770,8 @@ weston_head_set_monitor_strings(struct weston_head *head,
 	head->make = make ? strdup(make) : NULL;
 	head->model = model ? strdup(model) : NULL;
 	head->serial_number = serialno ? strdup(serialno) : NULL;
+
+	weston_head_set_device_changed(head);
 }
 
 /** Store physical image size
@@ -4749,6 +4780,8 @@ weston_head_set_monitor_strings(struct weston_head *head,
  * \param mm_width Image area width in millimeters.
  * \param mm_height Image area height in millimeters.
  *
+ * This may set the device_changed flag.
+ *
  * \memberof weston_head
  * \internal
  */
@@ -4756,8 +4789,14 @@ WL_EXPORT void
 weston_head_set_physical_size(struct weston_head *head,
 			      int32_t mm_width, int32_t mm_height)
 {
+	if (head->mm_width == mm_width &&
+	    head->mm_height == mm_height)
+		return;
+
 	head->mm_width = mm_width;
 	head->mm_height = mm_height;
+
+	weston_head_set_device_changed(head);
 }
 
 /** Store monitor sub-pixel layout
@@ -4771,6 +4810,8 @@ weston_head_set_physical_size(struct weston_head *head,
  * - WL_OUTPUT_SUBPIXEL_VERTICAL_RGB,
  * - WL_OUTPUT_SUBPIXEL_VERTICAL_BGR
  *
+ * This may set the device_changed flag.
+ *
  * \memberof weston_head
  * \internal
  */
@@ -4778,7 +4819,12 @@ WL_EXPORT void
 weston_head_set_subpixel(struct weston_head *head,
 			 enum wl_output_subpixel sp)
 {
+	if (head->subpixel == sp)
+		return;
+
 	head->subpixel = sp;
+
+	weston_head_set_device_changed(head);
 }
 
 /** Mark the monitor as internal
@@ -4813,7 +4859,7 @@ weston_head_set_internal(struct weston_head *head)
  * connection to the parent display server.
  *
  * When the connection status changes, it schedules a call to the heads_changed
- * hook.
+ * hook and sets the device_changed flag.
  *
  * \sa weston_compositor_set_heads_changed_cb
  * \memberof weston_head
@@ -4827,8 +4873,7 @@ weston_head_set_connection_status(struct weston_head *head, bool connected)
 
 	head->connected = connected;
 
-	if (head->compositor)
-		weston_compositor_schedule_heads_changed(head->compositor);
+	weston_head_set_device_changed(head);
 }
 
 /** Is the head currently connected?
@@ -4872,6 +4917,44 @@ weston_head_is_enabled(struct weston_head *head)
 	return head->output->enabled;
 }
 
+/** Has the device information changed?
+ *
+ * \param head The head to query.
+ * \return True if the device information has changed since last reset.
+ *
+ * The information about the connected display device, e.g. a monitor, may
+ * change without being disconnected in between. Changing information
+ * causes a call to the heads_changed hook.
+ *
+ * The information includes make, model, serial number, physical size,
+ * and sub-pixel type. The connection status is also included.
+ *
+ * \sa weston_head_reset_device_changed, weston_compositor_set_heads_changed_cb
+ * \memberof weston_head
+ */
+WL_EXPORT bool
+weston_head_is_device_changed(struct weston_head *head)
+{
+	return head->device_changed;
+}
+
+/** Acknowledge device information change
+ *
+ * \param head The head to acknowledge.
+ *
+ * Clears the device changed flag on this head. When a compositor has processed
+ * device information, it should call this to be able to notice further
+ * changes.
+ *
+ * \sa weston_head_is_device_changed
+ * \memberof weston_head
+ */
+WL_EXPORT void
+weston_head_reset_device_changed(struct weston_head *head)
+{
+	head->device_changed = false;
+}
+
 /** Get the name of a head
  *
  * \param head The head to query.
diff --git a/libweston/compositor.h b/libweston/compositor.h
index 4a15502b..4b866932 100644
--- a/libweston/compositor.h
+++ b/libweston/compositor.h
@@ -170,6 +170,7 @@ struct weston_head {
 	char *serial_number;		/**< monitor serial */
 	uint32_t subpixel;		/**< enum wl_output_subpixel */
 	bool connection_internal;	/**< embedded monitor (e.g. laptop) */
+	bool device_changed;		/**< monitor information has changed */
 
 	char *name;			/**< head name, e.g. connector name */
 	bool connected;			/**< is physically connected */
@@ -2040,6 +2041,12 @@ weston_head_is_connected(struct weston_head *head);
 bool
 weston_head_is_enabled(struct weston_head *head);
 
+bool
+weston_head_is_device_changed(struct weston_head *head);
+
+void
+weston_head_reset_device_changed(struct weston_head *head);
+
 const char *
 weston_head_get_name(struct weston_head *head);
 
-- 
2.13.6



More information about the wayland-devel mailing list