xref: /OK3568_Linux_fs/external/xserver/hw/dmx/dmxdpms.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
3  *
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation on the rights to use, copy, modify, merge,
10  * publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial
16  * portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 /*
29  * Author:
30  *   Rickard E. (Rik) Faith <faith@redhat.com>
31  *
32  */
33 
34 /** \file
35  * Provides DPMS support and unifies all DPMS and other screen-saver
36  * support in one file.  If -dpms is given on the command line, or the
37  * Xdmx server is not compiled with DPMS support, then the DPMS extension
38  * does not work for clients, but DPMS on the backends is still disables
39  * (and restored at Xdmx server shutdown time).
40  */
41 
42 #ifdef HAVE_DMX_CONFIG_H
43 #include <dmx-config.h>
44 #endif
45 
46 #include "dmx.h"
47 #include "dmxdpms.h"
48 #include "dmxlog.h"
49 #include "dmxsync.h"
50 #ifdef DPMSExtension
51 #include "dpmsproc.h"
52 #endif
53 #include "windowstr.h"          /* For screenIsSaved */
54 #include <X11/extensions/dpms.h>
55 
56 static int
_dmxDPMSInit(DMXScreenInfo * dmxScreen)57 _dmxDPMSInit(DMXScreenInfo * dmxScreen)
58 {
59     int event_base, error_base;
60     int major, minor;
61     CARD16 level, standby, suspend, off;
62     BOOL state;
63     const char *monitor;
64 
65 #ifdef DPMSExtension
66     if (DPMSDisabledSwitch)
67         return FALSE;
68 #endif
69 
70     dmxScreen->dpmsCapable = 0;
71 
72     if (!dmxScreen->beDisplay) {
73         dmxLogOutput(dmxScreen,
74                      "Cannot determine if DPMS supported (detached screen)\n");
75         return FALSE;
76     }
77 
78     if (!DPMSQueryExtension(dmxScreen->beDisplay, &event_base, &error_base)) {
79         dmxLogOutput(dmxScreen, "DPMS not supported\n");
80         return FALSE;
81     }
82     if (!DPMSGetVersion(dmxScreen->beDisplay, &major, &minor)) {
83         dmxLogOutput(dmxScreen, "DPMS not supported\n");
84         return FALSE;
85     }
86     if (!DPMSCapable(dmxScreen->beDisplay)) {
87         dmxLogOutput(dmxScreen, "DPMS %d.%d (not DPMS capable)\n",
88                      major, minor);
89         return FALSE;
90     }
91 
92     DPMSInfo(dmxScreen->beDisplay, &level, &state);
93     DPMSGetTimeouts(dmxScreen->beDisplay, &standby, &suspend, &off);
94     DPMSSetTimeouts(dmxScreen->beDisplay, 0, 0, 0);
95     DPMSEnable(dmxScreen->beDisplay);
96     DPMSForceLevel(dmxScreen->beDisplay, DPMSModeOn);
97     dmxScreen->dpmsCapable = 1;
98     dmxScreen->dpmsEnabled = ! !state;
99     dmxScreen->dpmsStandby = standby;
100     dmxScreen->dpmsSuspend = suspend;
101     dmxScreen->dpmsOff = off;
102 
103     switch (level) {
104     case DPMSModeOn:
105         monitor = "on";
106         break;
107     case DPMSModeStandby:
108         monitor = "standby";
109         break;
110     case DPMSModeSuspend:
111         monitor = "suspend";
112         break;
113     case DPMSModeOff:
114         monitor = "off";
115         break;
116     default:
117         monitor = "unknown";
118         break;
119     }
120 
121     dmxLogOutput(dmxScreen,
122                  "DPMS %d.%d (%s, %s, %d %d %d)\n",
123                  major, minor, monitor, state ? "enabled" : "disabled",
124                  standby, suspend, off);
125     return TRUE;
126 }
127 
128 /** Initialize DPMS support.  We save the current settings and turn off
129  * DPMS.  The settings are restored in #dmxDPMSTerm. */
130 int
dmxDPMSInit(DMXScreenInfo * dmxScreen)131 dmxDPMSInit(DMXScreenInfo * dmxScreen)
132 {
133     int interval, preferBlanking, allowExposures;
134 
135     /* Turn off DPMS */
136     if (!_dmxDPMSInit(dmxScreen))
137         return FALSE;
138 
139     if (!dmxScreen->beDisplay)
140         return FALSE;
141 
142     /* Turn off screen saver */
143     XGetScreenSaver(dmxScreen->beDisplay, &dmxScreen->savedTimeout, &interval,
144                     &preferBlanking, &allowExposures);
145     XSetScreenSaver(dmxScreen->beDisplay, 0, interval,
146                     preferBlanking, allowExposures);
147     XResetScreenSaver(dmxScreen->beDisplay);
148     dmxSync(dmxScreen, FALSE);
149     return TRUE;
150 }
151 
152 /** Terminate DPMS support on \a dmxScreen.  We restore the settings
153  * saved in #dmxDPMSInit. */
154 void
dmxDPMSTerm(DMXScreenInfo * dmxScreen)155 dmxDPMSTerm(DMXScreenInfo * dmxScreen)
156 {
157     int timeout, interval, preferBlanking, allowExposures;
158 
159     if (!dmxScreen->beDisplay)
160         return;
161 
162     XGetScreenSaver(dmxScreen->beDisplay, &timeout, &interval,
163                     &preferBlanking, &allowExposures);
164     XSetScreenSaver(dmxScreen->beDisplay, dmxScreen->savedTimeout, interval,
165                     preferBlanking, allowExposures);
166     if (dmxScreen->dpmsCapable) {
167         /* Restore saved state */
168         DPMSForceLevel(dmxScreen->beDisplay, DPMSModeOn);
169         DPMSSetTimeouts(dmxScreen->beDisplay, dmxScreen->dpmsStandby,
170                         dmxScreen->dpmsSuspend, dmxScreen->dpmsOff);
171         if (dmxScreen->dpmsEnabled)
172             DPMSEnable(dmxScreen->beDisplay);
173         else
174             DPMSDisable(dmxScreen->beDisplay);
175     }
176     dmxSync(dmxScreen, FALSE);
177 }
178 
179 /** Called when activity is detected so that DPMS power-saving mode can
180  * be deactivated. */
181 void
dmxDPMSWakeup(void)182 dmxDPMSWakeup(void)
183 {
184     if (screenIsSaved == SCREEN_SAVER_ON)
185         dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
186 #ifdef DPMSExtension
187     if (DPMSPowerLevel)
188         DPMSSet(serverClient, 0);
189 #endif
190 }
191 
192 #ifdef DPMSExtension
193 void
dmxDPMSBackend(DMXScreenInfo * dmxScreen,int level)194 dmxDPMSBackend(DMXScreenInfo *dmxScreen, int level)
195 {
196     if (dmxScreen->beDisplay) {
197         DPMSForceLevel(dmxScreen->beDisplay, level);
198         dmxSync(dmxScreen, FALSE);
199     }
200 }
201 #endif
202