[gtk/gtk-3-24: 1/2] gdk: x11: Fill GdkMonitor manufacturer with PNP id from EDID



commit 50a32b4b99dc7dfd261df129c64b5b2aaaf90b1f
Author: Priit Laes <priit laes paf com>
Date:   Thu May 16 11:22:03 2019 +0300

    gdk: x11: Fill GdkMonitor manufacturer with PNP id from EDID
    
    Previously, the manufacturer property of the GdkMonitor was NULL,
    and having at least PNP id at GdkMonitor.manufacturer makes it
    possible to distinguish between different monitors programmatically.

 gdk/gdkmonitor.c        |  7 ++++++-
 gdk/x11/gdkscreen-x11.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 1 deletion(-)
---
diff --git a/gdk/gdkmonitor.c b/gdk/gdkmonitor.c
index 9777cfcf85..4d413a5274 100644
--- a/gdk/gdkmonitor.c
+++ b/gdk/gdkmonitor.c
@@ -375,7 +375,12 @@ gdk_monitor_get_connector (GdkMonitor *monitor)
  * gdk_monitor_get_manufacturer:
  * @monitor: a #GdkMonitor
  *
- * Gets the name of the monitor's manufacturer, if available.
+ * Gets the name or PNP ID of the monitor's manufacturer, if available.
+ *
+ * Note that this value might also vary depending on actual
+ * display backend.
+ *
+ * PNP ID registry is located at https://uefi.org/pnp_id_list
  *
  * Returns: (transfer none) (nullable): the name of the manufacturer, or %NULL
  */
diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c
index 7c503b36a8..8939ae9fac 100644
--- a/gdk/x11/gdkscreen-x11.c
+++ b/gdk/x11/gdkscreen-x11.c
@@ -443,6 +443,7 @@ init_randr15 (GdkScreen *screen, gboolean *changed)
       GdkRectangle geometry;
       GdkRectangle newgeo;
       char *name;
+      char *manufacturer = NULL;
       int refresh_rate = 0;
 
       gdk_x11_display_error_trap_push (display);
@@ -497,6 +498,50 @@ init_randr15 (GdkScreen *screen, gboolean *changed)
           g_ptr_array_add (x11_display->monitors, monitor);
         }
 
+      /* Fetch minimal manufacturer information (PNP ID) from EDID */
+      {
+        #define EDID_LENGTH 128
+        Atom actual_type, edid_atom;
+        char tmp[3];
+        int actual_format;
+        unsigned char *prop;
+        unsigned long nbytes, bytes_left;
+        Display *disp = GDK_DISPLAY_XDISPLAY (x11_display);
+
+        edid_atom = XInternAtom (disp, RR_PROPERTY_RANDR_EDID, FALSE);
+
+        XRRGetOutputProperty (disp, output,
+                              edid_atom,
+                              0,
+                              EDID_LENGTH,
+                              FALSE,
+                              FALSE,
+                              AnyPropertyType,
+                              &actual_type,
+                              &actual_format,
+                              &nbytes,
+                              &bytes_left,
+                              &prop);
+
+        // Check partial EDID header (whole header: 00 ff ff ff ff ff ff 00)
+        if (nbytes >= EDID_LENGTH && prop[0] == 0x00 && prop[1] == 0xff)
+          {
+            /* decode the Vendor ID from three 5 bit words packed into 2 bytes
+             * /--08--\/--09--\
+             * 7654321076543210
+             * |\---/\---/\---/
+             * R  C1   C2   C3 */
+            tmp[0] = 'A' + ((prop[8] & 0x7c) / 4) - 1;
+            tmp[1] = 'A' + ((prop[8] & 0x3) * 8) + ((prop[9] & 0xe0) / 32) - 1;
+            tmp[2] = 'A' + (prop[9] & 0x1f) - 1;
+
+            manufacturer = g_strndup (tmp, sizeof (tmp));
+          }
+
+        XFree(prop);
+        #undef EDID_LENGTH
+      }
+
       gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry);
       name = g_strndup (output_info->name, output_info->nameLen);
 
@@ -525,6 +570,8 @@ init_randr15 (GdkScreen *screen, gboolean *changed)
       gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale);
       gdk_monitor_set_model (GDK_MONITOR (monitor), name);
       gdk_monitor_set_connector (GDK_MONITOR (monitor), name);
+      gdk_monitor_set_manufacturer (GDK_MONITOR (monitor), manufacturer);
+      g_free (manufacturer);
       g_free (name);
 
       if (rr_monitors[i].primary)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]