1 /*****************************************************************
3 Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts.
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.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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.
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.
27 ******************************************************************/
29 #include <dix-config.h>
32 #include <X11/Xproto.h>
34 #include "os/screensaver.h"
38 #include "dixstruct.h"
39 #include "extnsionst.h"
41 #include <X11/extensions/dpmsproto.h>
43 #include "extinit_priv.h"
44 #include "scrnintstr.h"
45 #include "windowstr.h"
46 #include "protocol-versions.h"
48 CARD16 DPMSPowerLevel
= 0;
49 Bool DPMSDisabledSwitch
= FALSE
;
50 CARD32 DPMSStandbyTime
= -1;
51 CARD32 DPMSSuspendTime
= -1;
52 CARD32 DPMSOffTime
= -1;
55 static int DPMSReqCode
= 0;
56 static RESTYPE ClientType
, DPMSEventType
; /* resource types for event masks */
57 static XID eventResource
;
59 typedef struct _DPMSEvent
*DPMSEventPtr
;
60 typedef struct _DPMSEvent
{
67 /*ARGSUSED*/ static int
68 DPMSFreeClient(void *data
, XID id
)
71 DPMSEventPtr
*pHead
, pCur
, pPrev
;
73 pEvent
= (DPMSEventPtr
) data
;
74 dixLookupResourceByType((void *) &pHead
, eventResource
, DPMSEventType
,
75 NullClient
, DixUnknownAccess
);
78 for (pCur
= *pHead
; pCur
&& pCur
!= pEvent
; pCur
= pCur
->next
)
82 pPrev
->next
= pEvent
->next
;
84 *pHead
= pEvent
->next
;
87 free((void *) pEvent
);
91 /*ARGSUSED*/ static int
92 DPMSFreeEvents(void *data
, XID id
)
94 DPMSEventPtr
*pHead
, pCur
, pNext
;
96 pHead
= (DPMSEventPtr
*) data
;
97 for (pCur
= *pHead
; pCur
; pCur
= pNext
) {
99 FreeResource(pCur
->clientResource
, ClientType
);
102 free((void *) pHead
);
107 SDPMSInfoNotifyEvent(xGenericEvent
* from
,
111 swaps(&to
->sequenceNumber
);
114 if (from
->evtype
== DPMSInfoNotify
) {
115 xDPMSInfoNotifyEvent
*c
= (xDPMSInfoNotifyEvent
*) to
;
116 swapl(&c
->timestamp
);
117 swaps(&c
->power_level
);
122 ProcDPMSSelectInput(register ClientPtr client
)
124 REQUEST(xDPMSSelectInputReq
);
125 DPMSEventPtr pEvent
, pNewEvent
, *pHead
;
129 REQUEST_SIZE_MATCH(xDPMSSelectInputReq
);
130 i
= dixLookupResourceByType((void **)&pHead
, eventResource
, DPMSEventType
,
133 if (stuff
->eventMask
== DPMSInfoNotifyMask
) {
134 if (i
== Success
&& pHead
) {
135 /* check for existing entry. */
136 for (pEvent
= *pHead
; pEvent
; pEvent
= pEvent
->next
) {
137 if (pEvent
->client
== client
) {
138 pEvent
->mask
= stuff
->eventMask
;
144 /* build the entry */
145 pNewEvent
= (DPMSEventPtr
)malloc(sizeof(DPMSEventRec
));
149 pNewEvent
->client
= client
;
150 pNewEvent
->mask
= stuff
->eventMask
;
152 * add a resource that will be deleted when
153 * the client goes away
155 clientResource
= FakeClientID(client
->index
);
156 pNewEvent
->clientResource
= clientResource
;
157 if (!AddResource(clientResource
, ClientType
, (void *)pNewEvent
))
160 * create a resource to contain a pointer to the list
161 * of clients selecting input
163 if (i
!= Success
|| !pHead
) {
164 pHead
= (DPMSEventPtr
*)malloc(sizeof(DPMSEventPtr
));
166 !AddResource(eventResource
, DPMSEventType
, (void *)pHead
)) {
167 FreeResource(clientResource
, X11_RESTYPE_NONE
);
172 pNewEvent
->next
= *pHead
;
175 else if (stuff
->eventMask
== 0) {
176 /* delete the interest */
177 if (i
== Success
&& pHead
) {
179 for (pEvent
= *pHead
; pEvent
; pEvent
= pEvent
->next
) {
180 if (pEvent
->client
== client
)
185 FreeResource(pEvent
->clientResource
, ClientType
);
187 pNewEvent
->next
= pEvent
->next
;
189 *pHead
= pEvent
->next
;
195 client
->errorValue
= stuff
->eventMask
;
202 SendDPMSInfoNotify(void)
204 DPMSEventPtr
*pHead
, pEvent
;
205 xDPMSInfoNotifyEvent se
;
208 i
= dixLookupResourceByType((void **)&pHead
, eventResource
, DPMSEventType
,
211 if (i
!= Success
|| !pHead
)
213 for (pEvent
= *pHead
; pEvent
; pEvent
= pEvent
->next
) {
214 if ((pEvent
->mask
& DPMSInfoNotifyMask
) == 0)
216 se
.type
= GenericEvent
;
217 se
.extension
= DPMSReqCode
;
218 se
.length
= (sizeof(xDPMSInfoNotifyEvent
) - 32) >> 2;
219 se
.evtype
= DPMSInfoNotify
;
220 se
.timestamp
= currentTime
.milliseconds
;
221 se
.power_level
= DPMSPowerLevel
;
222 se
.state
= DPMSEnabled
;
223 WriteEventsToClient(pEvent
->client
, 1, (xEvent
*)&se
);
232 /* For each screen, check if DPMS is supported */
233 for (i
= 0; i
< screenInfo
.numScreens
; i
++)
234 if (screenInfo
.screens
[i
]->DPMS
!= NULL
)
237 for (i
= 0; i
< screenInfo
.numGPUScreens
; i
++)
238 if (screenInfo
.gpuscreens
[i
]->DPMS
!= NULL
)
248 case SCREEN_SAVER_OFF
:
249 case SCREEN_SAVER_FORCER
:
251 case SCREEN_SAVER_ON
:
252 case SCREEN_SAVER_CYCLE
:
260 DPMSSet(ClientPtr client
, int level
)
263 int old_level
= DPMSPowerLevel
;
265 DPMSPowerLevel
= level
;
267 if (level
!= DPMSModeOn
) {
268 if (isUnblank(screenIsSaved
)) {
269 rc
= dixSaveScreens(client
, SCREEN_SAVER_FORCER
, ScreenSaverActive
);
273 } else if (!isUnblank(screenIsSaved
)) {
274 rc
= dixSaveScreens(client
, SCREEN_SAVER_OFF
, ScreenSaverReset
);
279 for (i
= 0; i
< screenInfo
.numScreens
; i
++)
280 if (screenInfo
.screens
[i
]->DPMS
!= NULL
)
281 screenInfo
.screens
[i
]->DPMS(screenInfo
.screens
[i
], level
);
283 for (i
= 0; i
< screenInfo
.numGPUScreens
; i
++)
284 if (screenInfo
.gpuscreens
[i
]->DPMS
!= NULL
)
285 screenInfo
.gpuscreens
[i
]->DPMS(screenInfo
.gpuscreens
[i
], level
);
287 if (DPMSPowerLevel
!= old_level
)
288 SendDPMSInfoNotify();
294 ProcDPMSGetVersion(ClientPtr client
)
296 /* REQUEST(xDPMSGetVersionReq); */
297 xDPMSGetVersionReply rep
= {
299 .sequenceNumber
= client
->sequence
,
301 .majorVersion
= SERVER_DPMS_MAJOR_VERSION
,
302 .minorVersion
= SERVER_DPMS_MINOR_VERSION
305 REQUEST_SIZE_MATCH(xDPMSGetVersionReq
);
307 if (client
->swapped
) {
308 swaps(&rep
.sequenceNumber
);
309 swaps(&rep
.majorVersion
);
310 swaps(&rep
.minorVersion
);
312 WriteToClient(client
, sizeof(xDPMSGetVersionReply
), &rep
);
317 ProcDPMSCapable(ClientPtr client
)
319 /* REQUEST(xDPMSCapableReq); */
320 xDPMSCapableReply rep
= {
322 .sequenceNumber
= client
->sequence
,
327 REQUEST_SIZE_MATCH(xDPMSCapableReq
);
329 if (client
->swapped
) {
330 swaps(&rep
.sequenceNumber
);
332 WriteToClient(client
, sizeof(xDPMSCapableReply
), &rep
);
337 ProcDPMSGetTimeouts(ClientPtr client
)
339 /* REQUEST(xDPMSGetTimeoutsReq); */
340 xDPMSGetTimeoutsReply rep
= {
342 .sequenceNumber
= client
->sequence
,
344 .standby
= DPMSStandbyTime
/ MILLI_PER_SECOND
,
345 .suspend
= DPMSSuspendTime
/ MILLI_PER_SECOND
,
346 .off
= DPMSOffTime
/ MILLI_PER_SECOND
349 REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq
);
351 if (client
->swapped
) {
352 swaps(&rep
.sequenceNumber
);
357 WriteToClient(client
, sizeof(xDPMSGetTimeoutsReply
), &rep
);
362 ProcDPMSSetTimeouts(ClientPtr client
)
364 REQUEST(xDPMSSetTimeoutsReq
);
366 REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq
);
368 if ((stuff
->off
!= 0) && (stuff
->off
< stuff
->suspend
)) {
369 client
->errorValue
= stuff
->off
;
372 if ((stuff
->suspend
!= 0) && (stuff
->suspend
< stuff
->standby
)) {
373 client
->errorValue
= stuff
->suspend
;
377 DPMSStandbyTime
= stuff
->standby
* MILLI_PER_SECOND
;
378 DPMSSuspendTime
= stuff
->suspend
* MILLI_PER_SECOND
;
379 DPMSOffTime
= stuff
->off
* MILLI_PER_SECOND
;
380 SetScreenSaverTimer();
386 ProcDPMSEnable(ClientPtr client
)
388 Bool was_enabled
= DPMSEnabled
;
390 REQUEST_SIZE_MATCH(xDPMSEnableReq
);
394 SetScreenSaverTimer();
395 SendDPMSInfoNotify();
402 ProcDPMSDisable(ClientPtr client
)
404 Bool was_enabled
= DPMSEnabled
;
406 /* REQUEST(xDPMSDisableReq); */
408 REQUEST_SIZE_MATCH(xDPMSDisableReq
);
410 DPMSSet(client
, DPMSModeOn
);
414 SendDPMSInfoNotify();
420 ProcDPMSForceLevel(ClientPtr client
)
422 REQUEST(xDPMSForceLevelReq
);
424 REQUEST_SIZE_MATCH(xDPMSForceLevelReq
);
429 if (stuff
->level
!= DPMSModeOn
&&
430 stuff
->level
!= DPMSModeStandby
&&
431 stuff
->level
!= DPMSModeSuspend
&& stuff
->level
!= DPMSModeOff
) {
432 client
->errorValue
= stuff
->level
;
436 DPMSSet(client
, stuff
->level
);
442 ProcDPMSInfo(ClientPtr client
)
444 /* REQUEST(xDPMSInfoReq); */
445 xDPMSInfoReply rep
= {
447 .sequenceNumber
= client
->sequence
,
449 .power_level
= DPMSPowerLevel
,
453 REQUEST_SIZE_MATCH(xDPMSInfoReq
);
455 if (client
->swapped
) {
456 swaps(&rep
.sequenceNumber
);
457 swaps(&rep
.power_level
);
459 WriteToClient(client
, sizeof(xDPMSInfoReply
), &rep
);
464 ProcDPMSDispatch(ClientPtr client
)
468 switch (stuff
->data
) {
469 case X_DPMSGetVersion
:
470 return ProcDPMSGetVersion(client
);
472 return ProcDPMSCapable(client
);
473 case X_DPMSGetTimeouts
:
474 return ProcDPMSGetTimeouts(client
);
475 case X_DPMSSetTimeouts
:
476 return ProcDPMSSetTimeouts(client
);
478 return ProcDPMSEnable(client
);
480 return ProcDPMSDisable(client
);
481 case X_DPMSForceLevel
:
482 return ProcDPMSForceLevel(client
);
484 return ProcDPMSInfo(client
);
485 case X_DPMSSelectInput
:
486 return ProcDPMSSelectInput(client
);
493 SProcDPMSGetVersion(ClientPtr client
)
495 REQUEST(xDPMSGetVersionReq
);
497 swaps(&stuff
->length
);
498 REQUEST_SIZE_MATCH(xDPMSGetVersionReq
);
499 swaps(&stuff
->majorVersion
);
500 swaps(&stuff
->minorVersion
);
501 return ProcDPMSGetVersion(client
);
505 SProcDPMSCapable(ClientPtr client
)
507 REQUEST(xDPMSCapableReq
);
509 swaps(&stuff
->length
);
510 REQUEST_SIZE_MATCH(xDPMSCapableReq
);
512 return ProcDPMSCapable(client
);
516 SProcDPMSGetTimeouts(ClientPtr client
)
518 REQUEST(xDPMSGetTimeoutsReq
);
520 swaps(&stuff
->length
);
521 REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq
);
523 return ProcDPMSGetTimeouts(client
);
527 SProcDPMSSetTimeouts(ClientPtr client
)
529 REQUEST(xDPMSSetTimeoutsReq
);
531 swaps(&stuff
->length
);
532 REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq
);
534 swaps(&stuff
->standby
);
535 swaps(&stuff
->suspend
);
537 return ProcDPMSSetTimeouts(client
);
541 SProcDPMSEnable(ClientPtr client
)
543 REQUEST(xDPMSEnableReq
);
545 swaps(&stuff
->length
);
546 REQUEST_SIZE_MATCH(xDPMSEnableReq
);
548 return ProcDPMSEnable(client
);
552 SProcDPMSDisable(ClientPtr client
)
554 REQUEST(xDPMSDisableReq
);
556 swaps(&stuff
->length
);
557 REQUEST_SIZE_MATCH(xDPMSDisableReq
);
559 return ProcDPMSDisable(client
);
563 SProcDPMSForceLevel(ClientPtr client
)
565 REQUEST(xDPMSForceLevelReq
);
567 swaps(&stuff
->length
);
568 REQUEST_SIZE_MATCH(xDPMSForceLevelReq
);
570 swaps(&stuff
->level
);
572 return ProcDPMSForceLevel(client
);
576 SProcDPMSInfo(ClientPtr client
)
578 REQUEST(xDPMSInfoReq
);
580 swaps(&stuff
->length
);
581 REQUEST_SIZE_MATCH(xDPMSInfoReq
);
583 return ProcDPMSInfo(client
);
587 SProcDPMSSelectInput(ClientPtr client
)
589 REQUEST(xDPMSSelectInputReq
);
590 swaps(&stuff
->length
);
591 REQUEST_SIZE_MATCH(xDPMSSelectInputReq
);
592 swapl(&stuff
->eventMask
);
593 return ProcDPMSSelectInput(client
);
599 SProcDPMSDispatch(ClientPtr client
)
602 switch (stuff
->data
) {
603 case X_DPMSGetVersion
:
604 return SProcDPMSGetVersion(client
);
606 return SProcDPMSCapable(client
);
607 case X_DPMSGetTimeouts
:
608 return SProcDPMSGetTimeouts(client
);
609 case X_DPMSSetTimeouts
:
610 return SProcDPMSSetTimeouts(client
);
612 return SProcDPMSEnable(client
);
614 return SProcDPMSDisable(client
);
615 case X_DPMSForceLevel
:
616 return SProcDPMSForceLevel(client
);
618 return SProcDPMSInfo(client
);
619 case X_DPMSSelectInput
:
620 return SProcDPMSSelectInput(client
);
627 DPMSCloseDownExtension(ExtensionEntry
*e
)
629 DPMSSet(serverClient
, DPMSModeOn
);
633 DPMSExtensionInit(void)
635 ExtensionEntry
*extEntry
;
637 #define CONDITIONALLY_SET_DPMS_TIMEOUT(_timeout_value_) \
638 if (_timeout_value_ == -1) { /* not yet set from config */ \
639 _timeout_value_ = ScreenSaverTime; \
642 CONDITIONALLY_SET_DPMS_TIMEOUT(DPMSStandbyTime
)
643 CONDITIONALLY_SET_DPMS_TIMEOUT(DPMSSuspendTime
)
644 CONDITIONALLY_SET_DPMS_TIMEOUT(DPMSOffTime
)
646 DPMSPowerLevel
= DPMSModeOn
;
647 DPMSEnabled
= DPMSSupported();
649 ClientType
= CreateNewResourceType(DPMSFreeClient
, "DPMSClient");
650 DPMSEventType
= CreateNewResourceType(DPMSFreeEvents
, "DPMSEvent");
651 eventResource
= FakeClientID(0);
653 if (DPMSEnabled
&& ClientType
&& DPMSEventType
&&
654 (extEntry
= AddExtension(DPMSExtensionName
, 0, 0,
655 ProcDPMSDispatch
, SProcDPMSDispatch
,
656 DPMSCloseDownExtension
, StandardMinorOpcode
))) {
657 DPMSReqCode
= extEntry
->base
;
658 GERegisterExtension(DPMSReqCode
, SDPMSInfoNotifyEvent
);