diff options
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/core/meta-xrandr-shared.h | 40 | ||||
-rw-r--r-- | src/core/monitor-private.h | 1 | ||||
-rw-r--r-- | src/core/monitor.c | 123 | ||||
-rw-r--r-- | src/xrandr.xml | 30 |
5 files changed, 195 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index ac03bd4d3..3e2284e53 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 000000000..c98f58103 --- /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 21b4bd7c7..b2458ba0d 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 3ff66ea7c..a930ba633 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 f17a4c1fb..40c94ab84 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> |