[gnome-settings-daemon/gnome-3-12] common: Implement size matching on screen-integrated devices



commit da409a90112992a996cdad63ed8a4ade1a563909
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon May 26 20:36:25 2014 +0200

    common: Implement size matching on screen-integrated devices
    
    On these devices, attempt to find a match based on device WxH calculations
    and output size information from EDID. Allow for a certain error threshold
    as sizes don't exactly match.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=730583
    
    Conflicts:
        plugins/common/gsd-device-mapper.c

 plugins/common/gsd-device-mapper.c |   85 +++++++++++++++++++++++++++++++++++-
 plugins/common/gsd-input-helper.c  |   49 +++++++++++++++++++++
 plugins/common/gsd-input-helper.h  |    3 +
 3 files changed, 135 insertions(+), 2 deletions(-)
---
diff --git a/plugins/common/gsd-device-mapper.c b/plugins/common/gsd-device-mapper.c
index 6949cac..3280d0c 100644
--- a/plugins/common/gsd-device-mapper.c
+++ b/plugins/common/gsd-device-mapper.c
@@ -51,6 +51,7 @@ typedef enum {
 
 typedef enum {
        GSD_PRIO_BUILTIN,            /* Output is builtin, applies mainly to system-integrated devices */
+       GSD_PRIO_MATCH_SIZE,         /* Size from input device and output match */
        GSD_PRIO_EDID_MATCH_FULL,    /* Full EDID model match, eg. "Cintiq 12WX" */
        GSD_PRIO_EDID_MATCH_PARTIAL, /* Partial EDID model match, eg. "Cintiq" */
        GSD_PRIO_EDID_MATCH_VENDOR,  /* EDID vendor match, eg. "WAC" for Wacom */
@@ -120,6 +121,9 @@ enum {
        N_SIGNALS
 };
 
+static GnomeRROutput * input_info_find_size_match (GsdInputInfo  *input,
+                                                   GnomeRRScreen *rr_screen);
+
 static guint signals[N_SIGNALS] = { 0 };
 
 G_DEFINE_TYPE (GsdDeviceMapper, gsd_device_mapper, G_TYPE_OBJECT)
@@ -336,6 +340,11 @@ input_info_guess_candidates (GsdInputInfo  *input,
        gchar **split;
 
        name = gdk_device_get_name (input->device);
+
+       if (input->capabilities & GSD_INPUT_IS_SCREEN_INTEGRATED) {
+               outputs[GSD_PRIO_MATCH_SIZE] = input_info_find_size_match (input, input->mapper->rr_screen);
+       }
+
        split = g_strsplit (name, " ", -1);
 
        /* On Wacom devices that are integrated on a not-in-system screen (eg. Cintiqs),
@@ -355,10 +364,10 @@ input_info_guess_candidates (GsdInputInfo  *input,
 
                for (i = 0; i < G_N_ELEMENTS (edids); i++) {
                        /* i + 1 matches the desired priority, we skip GSD_PRIO_BUILTIN here */
-                       outputs[i + 1] =
+                       outputs[i + GSD_PRIO_EDID_MATCH_FULL] =
                                find_output_by_edid (input->mapper->rr_screen,
                                                     edids[i]);
-                       found |= outputs[i + 1] != NULL;
+                       found |= outputs[i + GSD_PRIO_EDID_MATCH_FULL] != NULL;
                }
 
                g_free (product);
@@ -593,6 +602,78 @@ monitor_for_output (GnomeRROutput *output)
        return gdk_screen_get_monitor_at_point (screen, x, y);
 }
 
+static gboolean
+output_get_dimensions (GnomeRROutput *output,
+                      guint         *width,
+                      guint         *height)
+{
+       GdkScreen *screen = gdk_screen_get_default ();
+       gint monitor_num;
+
+       monitor_num = monitor_for_output (output);
+
+       if (monitor_num < 0)
+               return FALSE;
+
+       *width = gdk_screen_get_monitor_width_mm (screen, monitor_num);
+       *height = gdk_screen_get_monitor_height_mm (screen, monitor_num);
+       return TRUE;
+}
+
+static GnomeRROutput *
+input_info_find_size_match (GsdInputInfo  *input,
+                           GnomeRRScreen *rr_screen)
+{
+       guint i, input_width, input_height, output_width, output_height;
+       gdouble min_width_diff, min_height_diff;
+       GnomeRROutput **outputs, *match = NULL;
+
+       g_return_val_if_fail (rr_screen != NULL, NULL);
+
+       if (!xdevice_get_dimensions (gdk_x11_device_get_id (input->device),
+                                    &input_width, &input_height))
+               return NULL;
+
+       /* Restrict the matches to be below a narrow percentage */
+       min_width_diff = min_height_diff = 0.05;
+
+       g_debug ("Input device '%s' has %dx%d mm",
+                gdk_device_get_name (input->device), input_width, input_height);
+
+       outputs = gnome_rr_screen_list_outputs (rr_screen);
+
+       for (i = 0; outputs[i] != NULL; i++) {
+               gdouble width_diff, height_diff;
+
+               if (!output_get_dimensions (outputs[i], &output_width, &output_height))
+                       continue;
+
+               width_diff = ABS (1 - ((gdouble) output_width / input_width));
+               height_diff = ABS (1 - ((gdouble) output_height / input_height));
+
+               g_debug ("Output '%s' has size %dx%d mm, deviation from "
+                        "input device size: %.2f width, %.2f height ",
+                        gnome_rr_output_get_name (outputs[i]),
+                        output_width, output_height, width_diff, height_diff);
+
+               if (width_diff <= min_width_diff && height_diff <= min_height_diff) {
+                       match = outputs[i];
+                       min_width_diff = width_diff;
+                       min_height_diff = height_diff;
+               }
+       }
+
+       if (match) {
+               g_debug ("Output '%s' is considered a best size match (%.2f / %.2f)",
+                        gnome_rr_output_get_name (match),
+                        min_width_diff, min_height_diff);
+       } else {
+               g_debug ("No input/output size match was found\n");
+       }
+
+       return match;
+}
+
 static void
 input_info_get_matrix (GsdInputInfo *input,
                       float         matrix[NUM_ELEMS_MATRIX])
diff --git a/plugins/common/gsd-input-helper.c b/plugins/common/gsd-input-helper.c
index 625d361..4872506 100644
--- a/plugins/common/gsd-input-helper.c
+++ b/plugins/common/gsd-input-helper.c
@@ -33,6 +33,11 @@
 #define INPUT_DEVICES_SCHEMA "org.gnome.settings-daemon.peripherals.input-devices"
 #define KEY_HOTPLUG_COMMAND  "hotplug-command"
 
+#define ABS_MT_X "Abs MT Position X"
+#define ABS_MT_Y "Abs MT Position Y"
+#define ABS_X "Abs X"
+#define ABS_Y "Abs Y"
+
 typedef gboolean (* InfoIdentifyFunc) (XDeviceInfo *device_info);
 typedef gboolean (* DeviceIdentifyFunc) (XDevice *xdevice);
 
@@ -626,3 +631,47 @@ xdevice_close (XDevice *xdevice)
     XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
     gdk_error_trap_pop_ignored();
 }
+
+gboolean
+xdevice_get_dimensions (int    deviceid,
+                        guint *width,
+                        guint *height)
+{
+        GdkDisplay *display = gdk_display_get_default ();
+        XIDeviceInfo *info;
+        guint *value, w, h;
+        int i, n_info;
+
+        info = XIQueryDevice (GDK_DISPLAY_XDISPLAY (display), deviceid, &n_info);
+        *width = *height = w = h = 0;
+
+        if (!info)
+                return FALSE;
+
+        for (i = 0; i < info->num_classes; i++) {
+                XIValuatorClassInfo *valuator_info;
+
+                if (info->classes[i]->type != XIValuatorClass)
+                        continue;
+
+                valuator_info = (XIValuatorClassInfo *) info->classes[i];
+
+                if (valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_X) ||
+                    valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_MT_X))
+                        value = &w;
+                else if (valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_Y) ||
+                         valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_MT_Y))
+                        value = &h;
+                else
+                        continue;
+
+                *value = (valuator_info->max -  valuator_info->min) * 1000 / valuator_info->resolution;
+        }
+
+        *width = w;
+        *height = h;
+
+        XIFreeDeviceInfo (info);
+
+        return (w != 0 && h != 0);
+}
diff --git a/plugins/common/gsd-input-helper.h b/plugins/common/gsd-input-helper.h
index 702a15a..85e8492 100644
--- a/plugins/common/gsd-input-helper.h
+++ b/plugins/common/gsd-input-helper.h
@@ -80,6 +80,9 @@ gboolean  run_custom_command      (GdkDevice              *device,
 GList *   get_disabled_devices     (GdkDeviceManager       *manager);
 char *    xdevice_get_device_node  (int                     deviceid);
 int       xdevice_get_last_tool_id (int                     deviceid);
+gboolean  xdevice_get_dimensions   (int                     deviceid,
+                                    guint                  *width,
+                                    guint                  *height);
 void      xdevice_close      (XDevice                *xdevice);
 
 const char * xdevice_get_wacom_tool_type (int               deviceid);


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