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



commit f43d344aa39e0872449840690ea2981f46bc67cb
Author: Priit Laes <priit laes paf com>
Date:   Tue Aug 6 09:16:01 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 2d27c29972..37e2c872eb 100644
--- a/gdk/gdkmonitor.c
+++ b/gdk/gdkmonitor.c
@@ -401,7 +401,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 cda654f04e..ffba0708f7 100644
--- a/gdk/x11/gdkscreen-x11.c
+++ b/gdk/x11/gdkscreen-x11.c
@@ -354,6 +354,7 @@ init_randr15 (GdkX11Screen *x11_screen, gboolean *changed)
       GdkRectangle geometry;
       GdkRectangle newgeo;
       char *name;
+      char *manufacturer = NULL;
       int refresh_rate = 0;
 
       gdk_x11_display_error_trap_push (display);
@@ -405,6 +406,50 @@ init_randr15 (GdkX11Screen *x11_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);
 
@@ -433,6 +478,8 @@ init_randr15 (GdkX11Screen *x11_screen, gboolean *changed)
       gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->surface_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]