1 /*****************************************************************
2
3 Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts.
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
18 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
19 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
20 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Digital Equipment Corporation
23 shall not be used in advertising or otherwise to promote the sale, use or other
24 dealings in this Software without prior written authorization from Digital
25 Equipment Corporation.
26
27 ******************************************************************/
28
29 #ifdef HAVE_DIX_CONFIG_H
30 #include <dix-config.h>
31 #endif
32
33 #include <X11/X.h>
34 #include <X11/Xproto.h>
35 #include "misc.h"
36 #include "os.h"
37 #include "dixstruct.h"
38 #include "extnsionst.h"
39 #include "opaque.h"
40 #include <X11/extensions/dpmsproto.h>
41 #include "dpmsproc.h"
42 #include "extinit.h"
43 #include "scrnintstr.h"
44 #include "windowstr.h"
45
46 CARD16 DPMSPowerLevel = 0;
47 Bool DPMSDisabledSwitch = FALSE;
48 CARD32 DPMSStandbyTime = -1;
49 CARD32 DPMSSuspendTime = -1;
50 CARD32 DPMSOffTime = -1;
51 Bool DPMSEnabled;
52
53 Bool
DPMSSupported(void)54 DPMSSupported(void)
55 {
56 int i;
57
58 /* For each screen, check if DPMS is supported */
59 for (i = 0; i < screenInfo.numScreens; i++)
60 if (screenInfo.screens[i]->DPMS != NULL)
61 return TRUE;
62
63 for (i = 0; i < screenInfo.numGPUScreens; i++)
64 if (screenInfo.gpuscreens[i]->DPMS != NULL)
65 return TRUE;
66
67 return FALSE;
68 }
69
70 static Bool
isUnblank(int mode)71 isUnblank(int mode)
72 {
73 switch (mode) {
74 case SCREEN_SAVER_OFF:
75 case SCREEN_SAVER_FORCER:
76 return TRUE;
77 case SCREEN_SAVER_ON:
78 case SCREEN_SAVER_CYCLE:
79 return FALSE;
80 default:
81 return TRUE;
82 }
83 }
84
85 int
DPMSSet(ClientPtr client,int level)86 DPMSSet(ClientPtr client, int level)
87 {
88 int rc, i;
89
90 DPMSPowerLevel = level;
91
92 if (level != DPMSModeOn) {
93 if (isUnblank(screenIsSaved)) {
94 rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive);
95 if (rc != Success)
96 return rc;
97 }
98 } else if (!isUnblank(screenIsSaved)) {
99 rc = dixSaveScreens(client, SCREEN_SAVER_OFF, ScreenSaverReset);
100 if (rc != Success)
101 return rc;
102 }
103
104 for (i = 0; i < screenInfo.numScreens; i++)
105 if (screenInfo.screens[i]->DPMS != NULL)
106 screenInfo.screens[i]->DPMS(screenInfo.screens[i], level);
107
108 for (i = 0; i < screenInfo.numGPUScreens; i++)
109 if (screenInfo.gpuscreens[i]->DPMS != NULL)
110 screenInfo.gpuscreens[i]->DPMS(screenInfo.gpuscreens[i], level);
111
112 return Success;
113 }
114
115 static int
ProcDPMSGetVersion(ClientPtr client)116 ProcDPMSGetVersion(ClientPtr client)
117 {
118 /* REQUEST(xDPMSGetVersionReq); */
119 xDPMSGetVersionReply rep = {
120 .type = X_Reply,
121 .sequenceNumber = client->sequence,
122 .length = 0,
123 .majorVersion = DPMSMajorVersion,
124 .minorVersion = DPMSMinorVersion
125 };
126
127 REQUEST_SIZE_MATCH(xDPMSGetVersionReq);
128
129 if (client->swapped) {
130 swaps(&rep.sequenceNumber);
131 swaps(&rep.majorVersion);
132 swaps(&rep.minorVersion);
133 }
134 WriteToClient(client, sizeof(xDPMSGetVersionReply), &rep);
135 return Success;
136 }
137
138 static int
ProcDPMSCapable(ClientPtr client)139 ProcDPMSCapable(ClientPtr client)
140 {
141 /* REQUEST(xDPMSCapableReq); */
142 xDPMSCapableReply rep = {
143 .type = X_Reply,
144 .sequenceNumber = client->sequence,
145 .length = 0,
146 .capable = TRUE
147 };
148
149 REQUEST_SIZE_MATCH(xDPMSCapableReq);
150
151 if (client->swapped) {
152 swaps(&rep.sequenceNumber);
153 }
154 WriteToClient(client, sizeof(xDPMSCapableReply), &rep);
155 return Success;
156 }
157
158 static int
ProcDPMSGetTimeouts(ClientPtr client)159 ProcDPMSGetTimeouts(ClientPtr client)
160 {
161 /* REQUEST(xDPMSGetTimeoutsReq); */
162 xDPMSGetTimeoutsReply rep = {
163 .type = X_Reply,
164 .sequenceNumber = client->sequence,
165 .length = 0,
166 .standby = DPMSStandbyTime / MILLI_PER_SECOND,
167 .suspend = DPMSSuspendTime / MILLI_PER_SECOND,
168 .off = DPMSOffTime / MILLI_PER_SECOND
169 };
170
171 REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq);
172
173 if (client->swapped) {
174 swaps(&rep.sequenceNumber);
175 swaps(&rep.standby);
176 swaps(&rep.suspend);
177 swaps(&rep.off);
178 }
179 WriteToClient(client, sizeof(xDPMSGetTimeoutsReply), &rep);
180 return Success;
181 }
182
183 static int
ProcDPMSSetTimeouts(ClientPtr client)184 ProcDPMSSetTimeouts(ClientPtr client)
185 {
186 REQUEST(xDPMSSetTimeoutsReq);
187
188 REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq);
189
190 if ((stuff->off != 0) && (stuff->off < stuff->suspend)) {
191 client->errorValue = stuff->off;
192 return BadValue;
193 }
194 if ((stuff->suspend != 0) && (stuff->suspend < stuff->standby)) {
195 client->errorValue = stuff->suspend;
196 return BadValue;
197 }
198
199 DPMSStandbyTime = stuff->standby * MILLI_PER_SECOND;
200 DPMSSuspendTime = stuff->suspend * MILLI_PER_SECOND;
201 DPMSOffTime = stuff->off * MILLI_PER_SECOND;
202 SetScreenSaverTimer();
203
204 return Success;
205 }
206
207 static int
ProcDPMSEnable(ClientPtr client)208 ProcDPMSEnable(ClientPtr client)
209 {
210 Bool was_enabled = DPMSEnabled;
211
212 REQUEST_SIZE_MATCH(xDPMSEnableReq);
213
214 DPMSEnabled = TRUE;
215 if (!was_enabled)
216 SetScreenSaverTimer();
217
218 return Success;
219 }
220
221 static int
ProcDPMSDisable(ClientPtr client)222 ProcDPMSDisable(ClientPtr client)
223 {
224 /* REQUEST(xDPMSDisableReq); */
225
226 REQUEST_SIZE_MATCH(xDPMSDisableReq);
227
228 DPMSSet(client, DPMSModeOn);
229
230 DPMSEnabled = FALSE;
231
232 return Success;
233 }
234
235 static int
ProcDPMSForceLevel(ClientPtr client)236 ProcDPMSForceLevel(ClientPtr client)
237 {
238 REQUEST(xDPMSForceLevelReq);
239
240 REQUEST_SIZE_MATCH(xDPMSForceLevelReq);
241
242 if (!DPMSEnabled)
243 return BadMatch;
244
245 if (stuff->level != DPMSModeOn &&
246 stuff->level != DPMSModeStandby &&
247 stuff->level != DPMSModeSuspend && stuff->level != DPMSModeOff) {
248 client->errorValue = stuff->level;
249 return BadValue;
250 }
251
252 DPMSSet(client, stuff->level);
253
254 return Success;
255 }
256
257 static int
ProcDPMSInfo(ClientPtr client)258 ProcDPMSInfo(ClientPtr client)
259 {
260 /* REQUEST(xDPMSInfoReq); */
261 xDPMSInfoReply rep = {
262 .type = X_Reply,
263 .sequenceNumber = client->sequence,
264 .length = 0,
265 .power_level = DPMSPowerLevel,
266 .state = DPMSEnabled
267 };
268
269 REQUEST_SIZE_MATCH(xDPMSInfoReq);
270
271 if (client->swapped) {
272 swaps(&rep.sequenceNumber);
273 swaps(&rep.power_level);
274 }
275 WriteToClient(client, sizeof(xDPMSInfoReply), &rep);
276 return Success;
277 }
278
279 static int
ProcDPMSDispatch(ClientPtr client)280 ProcDPMSDispatch(ClientPtr client)
281 {
282 REQUEST(xReq);
283
284 switch (stuff->data) {
285 case X_DPMSGetVersion:
286 return ProcDPMSGetVersion(client);
287 case X_DPMSCapable:
288 return ProcDPMSCapable(client);
289 case X_DPMSGetTimeouts:
290 return ProcDPMSGetTimeouts(client);
291 case X_DPMSSetTimeouts:
292 return ProcDPMSSetTimeouts(client);
293 case X_DPMSEnable:
294 return ProcDPMSEnable(client);
295 case X_DPMSDisable:
296 return ProcDPMSDisable(client);
297 case X_DPMSForceLevel:
298 return ProcDPMSForceLevel(client);
299 case X_DPMSInfo:
300 return ProcDPMSInfo(client);
301 default:
302 return BadRequest;
303 }
304 }
305
306 static int _X_COLD
SProcDPMSGetVersion(ClientPtr client)307 SProcDPMSGetVersion(ClientPtr client)
308 {
309 REQUEST(xDPMSGetVersionReq);
310
311 swaps(&stuff->length);
312 REQUEST_SIZE_MATCH(xDPMSGetVersionReq);
313 swaps(&stuff->majorVersion);
314 swaps(&stuff->minorVersion);
315 return ProcDPMSGetVersion(client);
316 }
317
318 static int _X_COLD
SProcDPMSCapable(ClientPtr client)319 SProcDPMSCapable(ClientPtr client)
320 {
321 REQUEST(xDPMSCapableReq);
322
323 swaps(&stuff->length);
324 REQUEST_SIZE_MATCH(xDPMSCapableReq);
325
326 return ProcDPMSCapable(client);
327 }
328
329 static int _X_COLD
SProcDPMSGetTimeouts(ClientPtr client)330 SProcDPMSGetTimeouts(ClientPtr client)
331 {
332 REQUEST(xDPMSGetTimeoutsReq);
333
334 swaps(&stuff->length);
335 REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq);
336
337 return ProcDPMSGetTimeouts(client);
338 }
339
340 static int _X_COLD
SProcDPMSSetTimeouts(ClientPtr client)341 SProcDPMSSetTimeouts(ClientPtr client)
342 {
343 REQUEST(xDPMSSetTimeoutsReq);
344
345 swaps(&stuff->length);
346 REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq);
347
348 swaps(&stuff->standby);
349 swaps(&stuff->suspend);
350 swaps(&stuff->off);
351 return ProcDPMSSetTimeouts(client);
352 }
353
354 static int _X_COLD
SProcDPMSEnable(ClientPtr client)355 SProcDPMSEnable(ClientPtr client)
356 {
357 REQUEST(xDPMSEnableReq);
358
359 swaps(&stuff->length);
360 REQUEST_SIZE_MATCH(xDPMSEnableReq);
361
362 return ProcDPMSEnable(client);
363 }
364
365 static int _X_COLD
SProcDPMSDisable(ClientPtr client)366 SProcDPMSDisable(ClientPtr client)
367 {
368 REQUEST(xDPMSDisableReq);
369
370 swaps(&stuff->length);
371 REQUEST_SIZE_MATCH(xDPMSDisableReq);
372
373 return ProcDPMSDisable(client);
374 }
375
376 static int _X_COLD
SProcDPMSForceLevel(ClientPtr client)377 SProcDPMSForceLevel(ClientPtr client)
378 {
379 REQUEST(xDPMSForceLevelReq);
380
381 swaps(&stuff->length);
382 REQUEST_SIZE_MATCH(xDPMSForceLevelReq);
383
384 swaps(&stuff->level);
385
386 return ProcDPMSForceLevel(client);
387 }
388
389 static int _X_COLD
SProcDPMSInfo(ClientPtr client)390 SProcDPMSInfo(ClientPtr client)
391 {
392 REQUEST(xDPMSInfoReq);
393
394 swaps(&stuff->length);
395 REQUEST_SIZE_MATCH(xDPMSInfoReq);
396
397 return ProcDPMSInfo(client);
398 }
399
400 static int _X_COLD
SProcDPMSDispatch(ClientPtr client)401 SProcDPMSDispatch(ClientPtr client)
402 {
403 REQUEST(xReq);
404 switch (stuff->data) {
405 case X_DPMSGetVersion:
406 return SProcDPMSGetVersion(client);
407 case X_DPMSCapable:
408 return SProcDPMSCapable(client);
409 case X_DPMSGetTimeouts:
410 return SProcDPMSGetTimeouts(client);
411 case X_DPMSSetTimeouts:
412 return SProcDPMSSetTimeouts(client);
413 case X_DPMSEnable:
414 return SProcDPMSEnable(client);
415 case X_DPMSDisable:
416 return SProcDPMSDisable(client);
417 case X_DPMSForceLevel:
418 return SProcDPMSForceLevel(client);
419 case X_DPMSInfo:
420 return SProcDPMSInfo(client);
421 default:
422 return BadRequest;
423 }
424 }
425
426 static void
DPMSCloseDownExtension(ExtensionEntry * e)427 DPMSCloseDownExtension(ExtensionEntry *e)
428 {
429 DPMSSet(serverClient, DPMSModeOn);
430 }
431
432 void
DPMSExtensionInit(void)433 DPMSExtensionInit(void)
434 {
435 #define CONDITIONALLY_SET_DPMS_TIMEOUT(_timeout_value_) \
436 if (_timeout_value_ == -1) { /* not yet set from config */ \
437 _timeout_value_ = ScreenSaverTime; \
438 }
439
440 CONDITIONALLY_SET_DPMS_TIMEOUT(DPMSStandbyTime)
441 CONDITIONALLY_SET_DPMS_TIMEOUT(DPMSSuspendTime)
442 CONDITIONALLY_SET_DPMS_TIMEOUT(DPMSOffTime)
443
444 DPMSPowerLevel = DPMSModeOn;
445 DPMSEnabled = DPMSSupported();
446
447 if (DPMSEnabled)
448 AddExtension(DPMSExtensionName, 0, 0,
449 ProcDPMSDispatch, SProcDPMSDispatch,
450 DPMSCloseDownExtension, StandardMinorOpcode);
451 }
452