[mutter] MonitorManager: add support for DPMS levels



commit e039add2404ace8c75c2115de0874acd736a0a4b
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Wed Jul 24 10:39:06 2013 +0200

    MonitorManager: add support for DPMS levels
    
    To the XRandR and dummy backend (and as usual the dummy backend
    has no effect)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=705670

 src/Makefile.am               |    1 +
 src/core/meta-xrandr-shared.h |   40 +++++++++++++
 src/core/monitor-private.h    |    1 +
 src/core/monitor.c            |  123 +++++++++++++++++++++++++++++++++++++++++
 src/xrandr.xml                |   30 ++++++++++
 5 files changed, 195 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index ac03bd4..3e2284e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -111,6 +111,7 @@ libmutter_la_SOURCES =                              \
        core/keybindings.c                      \
        core/keybindings-private.h              \
        core/main.c                             \
+       core/meta-xrandr-shared.h               \
        core/monitor.c                          \
        core/monitor-private.h                  \
        core/mutter-Xatomtype.h                 \
diff --git a/src/core/meta-xrandr-shared.h b/src/core/meta-xrandr-shared.h
new file mode 100644
index 0000000..c98f581
--- /dev/null
+++ b/src/core/meta-xrandr-shared.h
@@ -0,0 +1,40 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* 
+ * Copyright (C) 2013 Red Hat Inc.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+/* This file is shared between mutter (src/core/meta-xrandr-shared.h)
+   and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h).
+
+   The canonical place for all changes is mutter.
+
+   There should be no includes in this file.
+*/
+
+#ifndef META_XRANDR_SHARED_H
+#define META_XRANDR_SHARED_H
+
+typedef enum {
+  META_POWER_SAVE_UNKNOWN = -1,
+  META_POWER_SAVE_ON = 0,
+  META_POWER_SAVE_STANDBY,
+  META_POWER_SAVE_SUSPEND,
+  META_POWER_SAVE_OFF,
+} MetaPowerSave;
+
+#endif
diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h
index 21b4bd7..b2458ba 100644
--- a/src/core/monitor-private.h
+++ b/src/core/monitor-private.h
@@ -46,6 +46,7 @@
 #ifdef HAVE_WAYLAND
 #include <wayland-server.h>
 #endif
+#include "meta-xrandr-shared.h"
 
 #ifndef HAVE_WAYLAND
 enum wl_output_transform {
diff --git a/src/core/monitor.c b/src/core/monitor.c
index 3ff66ea..a930ba6 100644
--- a/src/core/monitor.c
+++ b/src/core/monitor.c
@@ -33,6 +33,7 @@
 
 #ifdef HAVE_RANDR
 #include <X11/extensions/Xrandr.h>
+#include <X11/extensions/dpms.h>
 #endif
 
 #include <meta/main.h>
@@ -62,6 +63,8 @@ struct _MetaMonitorManager
 
   unsigned int serial;
 
+  MetaPowerSave power_save_mode;
+
   int max_screen_width;
   int max_screen_height;
   int screen_width;
@@ -108,6 +111,12 @@ enum {
   SIGNALS_LAST
 };
 
+enum {
+  PROP_0,
+  PROP_POWER_SAVE_MODE,
+  PROP_LAST
+};
+
 static int signals[SIGNALS_LAST];
 
 static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface);
@@ -332,11 +341,40 @@ read_monitor_infos_from_xrandr (MetaMonitorManager *manager)
     unsigned int n_actual_outputs;
     int min_width, min_height;
     Screen *screen;
+    BOOL dpms_capable, dpms_enabled;
+    CARD16 dpms_state;
 
     if (manager->resources)
       XRRFreeScreenResources (manager->resources);
     manager->resources = NULL;
 
+    meta_error_trap_push (meta_get_display ());
+    dpms_capable = DPMSCapable (manager->xdisplay);
+    meta_error_trap_pop (meta_get_display ());
+
+    if (dpms_capable &&
+        DPMSInfo (manager->xdisplay, &dpms_state, &dpms_enabled) &&
+        dpms_enabled)
+      {
+        switch (dpms_state)
+          {
+          case DPMSModeOn:
+            manager->power_save_mode = META_POWER_SAVE_ON;
+          case DPMSModeStandby:
+            manager->power_save_mode = META_POWER_SAVE_STANDBY;
+          case DPMSModeSuspend:
+            manager->power_save_mode = META_POWER_SAVE_SUSPEND;
+          case DPMSModeOff:
+            manager->power_save_mode = META_POWER_SAVE_OFF;
+          default:
+            manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
+          }
+      }
+    else
+      {
+        manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
+      }
+
     XRRGetScreenSizeRange (manager->xdisplay, DefaultRootWindow (manager->xdisplay),
                            &min_width,
                            &min_height,
@@ -710,6 +748,49 @@ meta_monitor_manager_new (Display *display)
 }
 
 static void
+meta_monitor_manager_set_power_save_mode (MetaMonitorManager *manager,
+                                          MetaPowerSave       mode)
+{
+  if (mode == manager->power_save_mode)
+    return;
+
+  if (manager->power_save_mode == META_POWER_SAVE_UNKNOWN ||
+      mode == META_POWER_SAVE_UNKNOWN)
+    return;
+
+#ifdef HAVE_RANDR
+  if (manager->backend == META_BACKEND_XRANDR)
+    {
+      CARD16 state;
+
+      switch (mode) {
+      case META_POWER_SAVE_ON:
+        state = DPMSModeOn;
+        break;
+      case META_POWER_SAVE_STANDBY:
+        state = DPMSModeStandby;
+        break;
+      case META_POWER_SAVE_SUSPEND:
+        state = DPMSModeSuspend;
+        break;
+      case META_POWER_SAVE_OFF:
+        state = DPMSModeOff;
+        break;
+      default:
+        return;
+      }
+
+      meta_error_trap_push (meta_get_display ());
+      DPMSForceLevel (manager->xdisplay, state);
+      DPMSSetTimeouts (manager->xdisplay, 0, 0, 0);
+      meta_error_trap_pop (meta_get_display ());
+    }
+#endif
+
+  manager->power_save_mode = mode;
+}
+
+static void
 free_output_array (MetaOutput *old_outputs,
                    int         n_old_outputs)
 {
@@ -757,10 +838,50 @@ meta_monitor_manager_dispose (GObject *object)
 }
 
 static void
+meta_monitor_manager_set_property (GObject      *object,
+                                   guint         prop_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  MetaMonitorManager *self = META_MONITOR_MANAGER (object);
+
+  switch (prop_id)
+    {
+    case PROP_POWER_SAVE_MODE:
+      meta_monitor_manager_set_power_save_mode (self, g_value_get_int (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+meta_monitor_manager_get_property (GObject      *object,
+                                   guint         prop_id,
+                                   GValue       *value,
+                                   GParamSpec   *pspec)
+{
+  MetaMonitorManager *self = META_MONITOR_MANAGER (object);
+
+  switch (prop_id)
+    {
+    case PROP_POWER_SAVE_MODE:
+      g_value_set_int (value, self->power_save_mode);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
 meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+  object_class->get_property = meta_monitor_manager_get_property;
+  object_class->set_property = meta_monitor_manager_set_property;
   object_class->dispose = meta_monitor_manager_dispose;
   object_class->finalize = meta_monitor_manager_finalize;
 
@@ -771,6 +892,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
                  0,
                   NULL, NULL, NULL,
                  G_TYPE_NONE, 0);
+
+  g_object_class_override_property (object_class, PROP_POWER_SAVE_MODE, "power-save-mode");
 }
 
 static const double known_diagonals[] = {
diff --git a/src/xrandr.xml b/src/xrandr.xml
index f17a4c1..40c94ab 100644
--- a/src/xrandr.xml
+++ b/src/xrandr.xml
@@ -194,5 +194,35 @@
       <arg name="crtcs" direction="in" type="a(uiiiuaua{sv})" />
       <arg name="outputs" direction="in" type="a(ua{sv})" />
     </method>
+
+    <!--
+        PowerSaveMode:
+
+       Contains the current power saving mode for the screen, and
+       allows changing it.
+
+        Possible values:
+       - 0: on
+       - 1: standby
+       - 2: suspend
+       - 3: off
+       - -1: unknown (unsupported)
+
+        A client should not attempt to change the powersave mode
+       from -1 (unknown) to any other value, and viceversa.
+       Note that the actual effects of the different values
+       depend on the hardware and the kernel driver in use, and
+       it's perfectly possible that all values different than on
+       have the same effect.
+       Also, setting the PowerSaveMode to 3 (off) may or may
+       not have the same effect as disabling all outputs by
+       setting no CRTC on them with ApplyConfiguration(), and
+       may or may not cause a configuration change.
+
+        Also note that this property might become out of date
+       if changed through different means (for example using the
+       XRandR interface directly).
+    -->
+    <property name="PowerSaveMode" type="i" access="readwrite" />
   </interface>
 </node>


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