diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h index 7d84c451f..b1dcc0e18 100644 --- a/src/core/monitor-private.h +++ b/src/core/monitor-private.h @@ -258,6 +258,12 @@ struct _MetaMonitorManagerClass MetaDBusDisplayConfigSkeletonClass parent_class; void (*read_current) (MetaMonitorManager *); + + char* (*get_edid_file) (MetaMonitorManager *, + MetaOutput *); + GBytes* (*read_edid) (MetaMonitorManager *, + MetaOutput *); + void (*apply_configuration) (MetaMonitorManager *, MetaCRTCInfo **, unsigned int , diff --git a/src/core/monitor-xrandr.c b/src/core/monitor-xrandr.c index 68ae61fdf..8f457a5da 100644 --- a/src/core/monitor-xrandr.c +++ b/src/core/monitor-xrandr.c @@ -466,6 +466,75 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) } } +static guint8 * +get_edid_property (Display *dpy, + RROutput output, + Atom atom, + gsize *len) +{ + unsigned char *prop; + int actual_format; + unsigned long nitems, bytes_after; + Atom actual_type; + guint8 *result; + + XRRGetOutputProperty (dpy, output, atom, + 0, 100, False, False, + AnyPropertyType, + &actual_type, &actual_format, + &nitems, &bytes_after, &prop); + + if (actual_type == XA_INTEGER && actual_format == 8) + { + result = g_memdup (prop, nitems); + if (len) + *len = nitems; + } + else + { + result = NULL; + } + + XFree (prop); + + return result; +} + +static GBytes * +meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager, + MetaOutput *output) +{ + MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); + Atom edid_atom; + guint8 *result; + gsize len; + + edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE); + result = get_edid_property (manager_xrandr->xdisplay, output->output_id, edid_atom, &len); + + if (!result) + { + edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE); + result = get_edid_property (manager_xrandr->xdisplay, output->output_id, edid_atom, &len); + } + + if (!result) + { + edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE); + result = get_edid_property (manager_xrandr->xdisplay, output->output_id, edid_atom, &len); + } + + if (result) + { + if (len > 0 && len % 128 == 0) + return g_bytes_new_take (result, len); + else + g_free (result); + } + + return NULL; +} + static void meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager, MetaPowerSave mode) @@ -766,6 +835,7 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) object_class->finalize = meta_monitor_manager_xrandr_finalize; manager_class->read_current = meta_monitor_manager_xrandr_read_current; + manager_class->read_edid = meta_monitor_manager_xrandr_read_edid; manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration; manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode; manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight; diff --git a/src/core/monitor.c b/src/core/monitor.c index 8e9d0bc11..ea592c414 100644 --- a/src/core/monitor.c +++ b/src/core/monitor.c @@ -339,6 +339,20 @@ apply_config_dummy (MetaMonitorManager *manager, invalidate_logical_config (manager); } +static GBytes * +read_edid_dummy (MetaMonitorManager *manager, + MetaOutput *output) +{ + return NULL; +} + +static char * +get_edid_file_dummy (MetaMonitorManager *manager, + MetaOutput *output) +{ + return NULL; +} + static void meta_monitor_manager_init (MetaMonitorManager *manager) { @@ -633,6 +647,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass) object_class->finalize = meta_monitor_manager_finalize; klass->read_current = read_current_dummy; + klass->read_edid = read_edid_dummy; + klass->get_edid_file = get_edid_file_dummy; klass->apply_configuration = apply_config_dummy; signals[MONITORS_CHANGED] = @@ -703,6 +719,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, GDBusMethodInvocation *invocation) { MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton); + MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (skeleton); GVariantBuilder crtc_builder, output_builder, mode_builder; unsigned int i, j; @@ -737,6 +754,8 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, { MetaOutput *output = &manager->outputs[i]; GVariantBuilder crtcs, modes, clones, properties; + GBytes *edid; + char *edid_file; g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au")); for (j = 0; j < output->n_possible_crtcs; j++) @@ -769,6 +788,25 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, g_variant_builder_add (&properties, "{sv}", "presentation", g_variant_new_boolean (output->is_presentation)); + edid_file = manager_class->get_edid_file (manager, output); + if (edid_file) + { + g_variant_builder_add (&properties, "{sv}", "edid-file", + g_variant_new_take_string (edid_file)); + } + else + { + edid = manager_class->read_edid (manager, output); + + if (edid) + { + g_variant_builder_add (&properties, "{sv}", "edid", + g_variant_new_from_bytes (G_VARIANT_TYPE ("ay"), + edid, TRUE)); + g_bytes_unref (edid); + } + } + g_variant_builder_add (&output_builder, "(uxiausauaua{sv})", i, /* ID */ output->output_id,