[mutter/wip/wayland-display] MonitorManager: add support for backlight



commit 4c4db0fccf2fbf69b5d253d5f3b8d0c7116c504f
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Thu Jul 25 15:06:09 2013 +0200

    MonitorManager: add support for backlight
    
    GnomeRR needs that too.
    The backlight is exported as a normalized 0-100 value, or -1 if not
    supported. Clamping to HW limits is handled by the backend.
    Changing backlight uses a different method call, to avoid recomputing
    the full display configuration every time the user presses the
    backlight keys.

 src/core/monitor-private.h |    4 +
 src/core/monitor.c         |  178 +++++++++++++++++++++++++++++++++++++++++++-
 src/meta/atomnames.h       |    1 +
 src/xrandr.xml             |   16 ++++
 4 files changed, 195 insertions(+), 4 deletions(-)
---
diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h
index 9b9ee0b..5365a6f 100644
--- a/src/core/monitor-private.h
+++ b/src/core/monitor-private.h
@@ -91,6 +91,10 @@ struct _MetaOutput
   MetaOutput **possible_clones;
   unsigned int n_possible_clones;
 
+  int backlight;
+  int backlight_min;
+  int backlight_max;
+
   /* Used when changing configuration */
   gboolean dirty;
 
diff --git a/src/core/monitor.c b/src/core/monitor.c
index e80e51f..cdeff1f 100644
--- a/src/core/monitor.c
+++ b/src/core/monitor.c
@@ -261,6 +261,9 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
   manager->outputs[0].possible_crtcs[2] = &manager->crtcs[2];
   manager->outputs[0].n_possible_clones = 0;
   manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
+  manager->outputs[0].backlight = -1;
+  manager->outputs[0].backlight_min = 0;
+  manager->outputs[0].backlight_max = 0;
 
   manager->outputs[1].crtc = &manager->crtcs[0];
   manager->outputs[1].output_id = 7;
@@ -285,6 +288,9 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
   manager->outputs[1].possible_crtcs[2] = &manager->crtcs[2];
   manager->outputs[1].n_possible_clones = 0;
   manager->outputs[1].possible_clones = g_new0 (MetaOutput *, 0);
+  manager->outputs[1].backlight = -1;
+  manager->outputs[1].backlight_min = 0;
+  manager->outputs[1].backlight_max = 0;
 
   manager->outputs[2].crtc = NULL;
   manager->outputs[2].output_id = 8;
@@ -308,6 +314,9 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
   manager->outputs[2].possible_crtcs[2] = &manager->crtcs[2];
   manager->outputs[2].n_possible_clones = 0;
   manager->outputs[2].possible_clones = g_new0 (MetaOutput *, 0);
+  manager->outputs[2].backlight = -1;
+  manager->outputs[2].backlight_min = 0;
+  manager->outputs[2].backlight_max = 0;
 }
 
 #ifdef HAVE_RANDR
@@ -411,6 +420,74 @@ output_get_presentation_xrandr (MetaMonitorManager *manager,
 }
 
 static int
+normalize_backlight (MetaOutput *output,
+                     int         hw_value)
+{
+  return round((double)(hw_value - output->backlight_min) /
+               (output->backlight_max - output->backlight_min) * 100.0);
+}
+
+static int
+output_get_backlight_xrandr (MetaMonitorManager *manager,
+                             MetaOutput         *output)
+{
+  MetaDisplay *display = meta_get_display ();
+  gboolean value;
+  Atom actual_type;
+  int actual_format;
+  unsigned long nitems, bytes_after;
+  unsigned char *buffer;
+
+  XRRGetOutputProperty (manager->xdisplay,
+                        (XID)output->output_id,
+                        display->atom_BACKLIGHT,
+                        0, G_MAXLONG, False, False, XA_INTEGER,
+                        &actual_type, &actual_format,
+                        &nitems, &bytes_after, &buffer);
+
+  if (actual_type != XA_INTEGER || actual_format != 32 ||
+      nitems < 1)
+    return -1;
+
+  value = ((int*)buffer)[0];
+
+  XFree (buffer);
+  return normalize_backlight (output, value);
+}
+
+static void
+output_get_backlight_limits_xrandr (MetaMonitorManager *manager,
+                                    MetaOutput         *output)
+{
+  MetaDisplay *display = meta_get_display ();
+  XRRPropertyInfo *info;
+
+  meta_error_trap_push (display);
+  info = XRRQueryOutputProperty (manager->xdisplay,
+                                 (XID)output->output_id,
+                                 display->atom_BACKLIGHT);
+  meta_error_trap_pop (display);
+
+  if (info == NULL)
+    {
+      meta_warning ("could not get output property for %s\n", output->name);
+      return;
+    }
+
+  if (!info->range || info->num_values != 2)
+    {
+      meta_verbose ("backlight %s was not range\n", output->name);
+      goto out;
+    }
+
+  output->backlight_min = info->values[0];
+  output->backlight_max = info->values[1];
+
+out:
+  XFree (info);
+}
+
+static int
 compare_outputs (const void *one,
                  const void *two)
 {
@@ -618,6 +695,12 @@ read_monitor_infos_from_xrandr (MetaMonitorManager *manager)
 
             meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
             meta_output->is_presentation = output_get_presentation_xrandr (manager, meta_output);
+            output_get_backlight_limits_xrandr (manager, meta_output);
+
+            if (!(meta_output->backlight_min == 0 && meta_output->backlight_max == 0))
+              meta_output->backlight = output_get_backlight_xrandr (manager, meta_output);
+            else
+              meta_output->backlight = -1;
 
             n_actual_outputs++;
           }
@@ -1052,7 +1135,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
   unsigned int i, j;
 
   g_variant_builder_init (&crtc_builder, G_VARIANT_TYPE ("a(uxiiiiiuaua{sv})"));
-  g_variant_builder_init (&output_builder, G_VARIANT_TYPE ("a(uxiaussssauaua{sv})"));
+  g_variant_builder_init (&output_builder, G_VARIANT_TYPE ("a(uxiaussssauauia{sv})"));
   g_variant_builder_init (&mode_builder, G_VARIANT_TYPE ("a(uxuud)"));
 
   for (i = 0; i < manager->n_crtcs; i++)
@@ -1104,7 +1187,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
       g_variant_builder_add (&properties, "{sv}", "presentation",
                              g_variant_new_boolean (output->is_presentation));
 
-      g_variant_builder_add (&output_builder, "(uxiaussssauaua{sv})",
+      g_variant_builder_add (&output_builder, "(uxiaussssauauiia{sv})",
                              i, /* ID */
                              output->output_id,
                              (int)(output->crtc ? output->crtc - manager->crtcs : -1),
@@ -1115,6 +1198,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
                              output->serial,
                              &modes,
                              &clones,
+                             output->backlight,
                              &properties);
     }
       
@@ -1433,8 +1517,8 @@ meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
                                           MetaOutputInfo     **outputs,
                                           unsigned int         n_outputs)
 {
- if (manager->backend == META_BACKEND_XRANDR)
-   apply_config_xrandr (manager, crtcs, n_crtcs, outputs, n_outputs);
+  if (manager->backend == META_BACKEND_XRANDR)
+    apply_config_xrandr (manager, crtcs, n_crtcs, outputs, n_outputs);
   else
     apply_config_dummy (manager, crtcs, n_crtcs, outputs, n_outputs);
 }
@@ -1643,11 +1727,97 @@ meta_monitor_manager_handle_apply_configuration  (MetaDBusDisplayConfig *skeleto
   return TRUE;
 }
 
+#ifdef HAVE_RANDR
+static void
+handle_change_backlight_xrandr (MetaMonitorManager *manager,
+                                MetaOutput         *output,
+                                gint                value)
+{
+  MetaDisplay *display = meta_get_display ();
+  int hw_value;
+
+  hw_value = round((double)value / 100.0 * output->backlight_max + output->backlight_min);
+
+  meta_error_trap_push (display);
+  XRRChangeOutputProperty (manager->xdisplay,
+                           (XID)output->output_id,
+                           display->atom_BACKLIGHT,
+                           XA_INTEGER, 32, PropModeReplace,
+                           (unsigned char *) &hw_value, 1);
+  meta_error_trap_pop (display);
+
+  /* We're not selecting for property notifies, so update the value immediately */
+  output->backlight = normalize_backlight (output, hw_value);
+}
+#endif
+
+static void
+handle_change_backlight_dummy (MetaMonitorManager *manager,
+                               MetaOutput         *output,
+                               gint                value)
+{
+  g_assert_not_reached ();
+}
+
+static gboolean
+meta_monitor_manager_handle_change_backlight  (MetaDBusDisplayConfig *skeleton,
+                                               GDBusMethodInvocation *invocation,
+                                               guint                  serial,
+                                               guint                  output_id,
+                                               gint                   value)
+{
+  MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
+  MetaOutput *output;
+
+  if (serial != manager->serial)
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                             G_DBUS_ERROR_ACCESS_DENIED,
+                                             "The requested configuration is based on stale information");
+      return TRUE;
+    }
+
+  if (output_id < 0 || output_id >= manager->n_outputs)
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                             G_DBUS_ERROR_INVALID_ARGS,
+                                             "Invalid output id");
+      return TRUE;
+    }
+  output = &manager->outputs[output_id];
+
+  if (value < 0 || value > 100)
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                             G_DBUS_ERROR_INVALID_ARGS,
+                                             "Invalid backlight value");
+      return TRUE;
+    }
+
+  if (output->backlight == -1 ||
+      (output->backlight_min == 0 && output->backlight_max == 0))
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                             G_DBUS_ERROR_INVALID_ARGS,
+                                             "Output does not support changing backlight");
+      return TRUE;
+    }
+
+  if (manager->backend == META_BACKEND_XRANDR)
+    handle_change_backlight_xrandr (manager, output, value);
+  else
+    handle_change_backlight_dummy (manager, output, value);
+
+  meta_dbus_display_config_complete_change_backlight (skeleton, invocation);
+  return TRUE;
+}
+
 static void
 meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface)
 {
   iface->handle_get_resources = meta_monitor_manager_handle_get_resources;
   iface->handle_apply_configuration = meta_monitor_manager_handle_apply_configuration;
+  iface->handle_change_backlight = meta_monitor_manager_handle_change_backlight;
 }
 
 static void
diff --git a/src/meta/atomnames.h b/src/meta/atomnames.h
index 4aa54fe..74e3bce 100644
--- a/src/meta/atomnames.h
+++ b/src/meta/atomnames.h
@@ -82,6 +82,7 @@ item(MULTIPLE)
 item(TIMESTAMP)
 item(VERSION)
 item(ATOM_PAIR)
+item(BACKLIGHT)
 
 /* Oddities: These are used, and we need atoms for them,
  * but when we need all _NET_WM hints (i.e. when we're making
diff --git a/src/xrandr.xml b/src/xrandr.xml
index 9309929..e63606e 100644
--- a/src/xrandr.xml
+++ b/src/xrandr.xml
@@ -80,6 +80,7 @@
        * s vendor: the human readable name of the manufacturer
        * s product: the human readable name of the display model
        * s serial: the serial number of this particular hardward part
+       * i backlight: the backlight value as a percentage (-1 if not supported)
        * au modes: valid modes for this output
        * au clones: valid clones for this output, ie other outputs that
                     can be assigned the same CRTC as this one; if you
@@ -193,6 +194,21 @@
     </method>
 
     <!--
+        ChangeBacklight:
+       @serial: configuration serial
+       @output: the API id of the output
+       @value: the new backlight value
+
+       Changes the backlight of @output to @value, which is
+       expressed as a percentage and rounded to the HW limits.
+    -->
+    <method name="ChangeBacklight">
+      <arg name="serial" direction="in" type="u" />
+      <arg name="output" direction="in" type="u" />
+      <arg name="value" direction="in" type="i" />
+    </method>
+
+    <!--
         PowerSaveMode:
 
        Contains the current power saving mode for the screen, and


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