os: if inet_ntop() is available, use it for IPv4 addresses as well
[xserver.git] / Xext / dpms.c
blobb0dca98e1362d9d0e288c116667924159a4385eb
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>
31 #include <X11/X.h>
32 #include <X11/Xproto.h>
34 #include "os/screensaver.h"
36 #include "misc.h"
37 #include "os.h"
38 #include "dixstruct.h"
39 #include "extnsionst.h"
40 #include "opaque.h"
41 #include <X11/extensions/dpmsproto.h>
42 #include "dpmsproc.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;
53 Bool DPMSEnabled;
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 {
61 DPMSEventPtr next;
62 ClientPtr client;
63 XID clientResource;
64 unsigned int mask;
65 } DPMSEventRec;
67 /*ARGSUSED*/ static int
68 DPMSFreeClient(void *data, XID id)
70 DPMSEventPtr pEvent;
71 DPMSEventPtr *pHead, pCur, pPrev;
73 pEvent = (DPMSEventPtr) data;
74 dixLookupResourceByType((void *) &pHead, eventResource, DPMSEventType,
75 NullClient, DixUnknownAccess);
76 if (pHead) {
77 pPrev = 0;
78 for (pCur = *pHead; pCur && pCur != pEvent; pCur = pCur->next)
79 pPrev = pCur;
80 if (pCur) {
81 if (pPrev)
82 pPrev->next = pEvent->next;
83 else
84 *pHead = pEvent->next;
87 free((void *) pEvent);
88 return 1;
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) {
98 pNext = pCur->next;
99 FreeResource(pCur->clientResource, ClientType);
100 free((void *) pCur);
102 free((void *) pHead);
103 return 1;
106 static void
107 SDPMSInfoNotifyEvent(xGenericEvent * from,
108 xGenericEvent * to)
110 *to = *from;
111 swaps(&to->sequenceNumber);
112 swapl(&to->length);
113 swaps(&to->evtype);
114 if (from->evtype == DPMSInfoNotify) {
115 xDPMSInfoNotifyEvent *c = (xDPMSInfoNotifyEvent *) to;
116 swapl(&c->timestamp);
117 swaps(&c->power_level);
121 static int
122 ProcDPMSSelectInput(register ClientPtr client)
124 REQUEST(xDPMSSelectInputReq);
125 DPMSEventPtr pEvent, pNewEvent, *pHead;
126 XID clientResource;
127 int i;
129 REQUEST_SIZE_MATCH(xDPMSSelectInputReq);
130 i = dixLookupResourceByType((void **)&pHead, eventResource, DPMSEventType,
131 client,
132 DixWriteAccess);
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;
139 return Success;
144 /* build the entry */
145 pNewEvent = (DPMSEventPtr)malloc(sizeof(DPMSEventRec));
146 if (!pNewEvent)
147 return BadAlloc;
148 pNewEvent->next = 0;
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))
158 return BadAlloc;
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));
165 if (!pHead ||
166 !AddResource(eventResource, DPMSEventType, (void *)pHead)) {
167 FreeResource(clientResource, X11_RESTYPE_NONE);
168 return BadAlloc;
170 *pHead = 0;
172 pNewEvent->next = *pHead;
173 *pHead = pNewEvent;
175 else if (stuff->eventMask == 0) {
176 /* delete the interest */
177 if (i == Success && pHead) {
178 pNewEvent = 0;
179 for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
180 if (pEvent->client == client)
181 break;
182 pNewEvent = pEvent;
184 if (pEvent) {
185 FreeResource(pEvent->clientResource, ClientType);
186 if (pNewEvent)
187 pNewEvent->next = pEvent->next;
188 else
189 *pHead = pEvent->next;
190 free(pEvent);
194 else {
195 client->errorValue = stuff->eventMask;
196 return BadValue;
198 return Success;
201 static void
202 SendDPMSInfoNotify(void)
204 DPMSEventPtr *pHead, pEvent;
205 xDPMSInfoNotifyEvent se;
206 int i;
208 i = dixLookupResourceByType((void **)&pHead, eventResource, DPMSEventType,
209 serverClient,
210 DixReadAccess);
211 if (i != Success || !pHead)
212 return;
213 for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
214 if ((pEvent->mask & DPMSInfoNotifyMask) == 0)
215 continue;
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);
227 Bool
228 DPMSSupported(void)
230 int i;
232 /* For each screen, check if DPMS is supported */
233 for (i = 0; i < screenInfo.numScreens; i++)
234 if (screenInfo.screens[i]->DPMS != NULL)
235 return TRUE;
237 for (i = 0; i < screenInfo.numGPUScreens; i++)
238 if (screenInfo.gpuscreens[i]->DPMS != NULL)
239 return TRUE;
241 return FALSE;
244 static Bool
245 isUnblank(int mode)
247 switch (mode) {
248 case SCREEN_SAVER_OFF:
249 case SCREEN_SAVER_FORCER:
250 return TRUE;
251 case SCREEN_SAVER_ON:
252 case SCREEN_SAVER_CYCLE:
253 return FALSE;
254 default:
255 return TRUE;
260 DPMSSet(ClientPtr client, int level)
262 int rc, i;
263 int old_level = DPMSPowerLevel;
265 DPMSPowerLevel = level;
267 if (level != DPMSModeOn) {
268 if (isUnblank(screenIsSaved)) {
269 rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive);
270 if (rc != Success)
271 return rc;
273 } else if (!isUnblank(screenIsSaved)) {
274 rc = dixSaveScreens(client, SCREEN_SAVER_OFF, ScreenSaverReset);
275 if (rc != Success)
276 return rc;
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();
290 return Success;
293 static int
294 ProcDPMSGetVersion(ClientPtr client)
296 /* REQUEST(xDPMSGetVersionReq); */
297 xDPMSGetVersionReply rep = {
298 .type = X_Reply,
299 .sequenceNumber = client->sequence,
300 .length = 0,
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);
313 return Success;
316 static int
317 ProcDPMSCapable(ClientPtr client)
319 /* REQUEST(xDPMSCapableReq); */
320 xDPMSCapableReply rep = {
321 .type = X_Reply,
322 .sequenceNumber = client->sequence,
323 .length = 0,
324 .capable = TRUE
327 REQUEST_SIZE_MATCH(xDPMSCapableReq);
329 if (client->swapped) {
330 swaps(&rep.sequenceNumber);
332 WriteToClient(client, sizeof(xDPMSCapableReply), &rep);
333 return Success;
336 static int
337 ProcDPMSGetTimeouts(ClientPtr client)
339 /* REQUEST(xDPMSGetTimeoutsReq); */
340 xDPMSGetTimeoutsReply rep = {
341 .type = X_Reply,
342 .sequenceNumber = client->sequence,
343 .length = 0,
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);
353 swaps(&rep.standby);
354 swaps(&rep.suspend);
355 swaps(&rep.off);
357 WriteToClient(client, sizeof(xDPMSGetTimeoutsReply), &rep);
358 return Success;
361 static int
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;
370 return BadValue;
372 if ((stuff->suspend != 0) && (stuff->suspend < stuff->standby)) {
373 client->errorValue = stuff->suspend;
374 return BadValue;
377 DPMSStandbyTime = stuff->standby * MILLI_PER_SECOND;
378 DPMSSuspendTime = stuff->suspend * MILLI_PER_SECOND;
379 DPMSOffTime = stuff->off * MILLI_PER_SECOND;
380 SetScreenSaverTimer();
382 return Success;
385 static int
386 ProcDPMSEnable(ClientPtr client)
388 Bool was_enabled = DPMSEnabled;
390 REQUEST_SIZE_MATCH(xDPMSEnableReq);
392 DPMSEnabled = TRUE;
393 if (!was_enabled) {
394 SetScreenSaverTimer();
395 SendDPMSInfoNotify();
398 return Success;
401 static int
402 ProcDPMSDisable(ClientPtr client)
404 Bool was_enabled = DPMSEnabled;
406 /* REQUEST(xDPMSDisableReq); */
408 REQUEST_SIZE_MATCH(xDPMSDisableReq);
410 DPMSSet(client, DPMSModeOn);
412 DPMSEnabled = FALSE;
413 if (was_enabled)
414 SendDPMSInfoNotify();
416 return Success;
419 static int
420 ProcDPMSForceLevel(ClientPtr client)
422 REQUEST(xDPMSForceLevelReq);
424 REQUEST_SIZE_MATCH(xDPMSForceLevelReq);
426 if (!DPMSEnabled)
427 return BadMatch;
429 if (stuff->level != DPMSModeOn &&
430 stuff->level != DPMSModeStandby &&
431 stuff->level != DPMSModeSuspend && stuff->level != DPMSModeOff) {
432 client->errorValue = stuff->level;
433 return BadValue;
436 DPMSSet(client, stuff->level);
438 return Success;
441 static int
442 ProcDPMSInfo(ClientPtr client)
444 /* REQUEST(xDPMSInfoReq); */
445 xDPMSInfoReply rep = {
446 .type = X_Reply,
447 .sequenceNumber = client->sequence,
448 .length = 0,
449 .power_level = DPMSPowerLevel,
450 .state = DPMSEnabled
453 REQUEST_SIZE_MATCH(xDPMSInfoReq);
455 if (client->swapped) {
456 swaps(&rep.sequenceNumber);
457 swaps(&rep.power_level);
459 WriteToClient(client, sizeof(xDPMSInfoReply), &rep);
460 return Success;
463 static int
464 ProcDPMSDispatch(ClientPtr client)
466 REQUEST(xReq);
468 switch (stuff->data) {
469 case X_DPMSGetVersion:
470 return ProcDPMSGetVersion(client);
471 case X_DPMSCapable:
472 return ProcDPMSCapable(client);
473 case X_DPMSGetTimeouts:
474 return ProcDPMSGetTimeouts(client);
475 case X_DPMSSetTimeouts:
476 return ProcDPMSSetTimeouts(client);
477 case X_DPMSEnable:
478 return ProcDPMSEnable(client);
479 case X_DPMSDisable:
480 return ProcDPMSDisable(client);
481 case X_DPMSForceLevel:
482 return ProcDPMSForceLevel(client);
483 case X_DPMSInfo:
484 return ProcDPMSInfo(client);
485 case X_DPMSSelectInput:
486 return ProcDPMSSelectInput(client);
487 default:
488 return BadRequest;
492 static int _X_COLD
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);
504 static int _X_COLD
505 SProcDPMSCapable(ClientPtr client)
507 REQUEST(xDPMSCapableReq);
509 swaps(&stuff->length);
510 REQUEST_SIZE_MATCH(xDPMSCapableReq);
512 return ProcDPMSCapable(client);
515 static int _X_COLD
516 SProcDPMSGetTimeouts(ClientPtr client)
518 REQUEST(xDPMSGetTimeoutsReq);
520 swaps(&stuff->length);
521 REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq);
523 return ProcDPMSGetTimeouts(client);
526 static int _X_COLD
527 SProcDPMSSetTimeouts(ClientPtr client)
529 REQUEST(xDPMSSetTimeoutsReq);
531 swaps(&stuff->length);
532 REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq);
534 swaps(&stuff->standby);
535 swaps(&stuff->suspend);
536 swaps(&stuff->off);
537 return ProcDPMSSetTimeouts(client);
540 static int _X_COLD
541 SProcDPMSEnable(ClientPtr client)
543 REQUEST(xDPMSEnableReq);
545 swaps(&stuff->length);
546 REQUEST_SIZE_MATCH(xDPMSEnableReq);
548 return ProcDPMSEnable(client);
551 static int _X_COLD
552 SProcDPMSDisable(ClientPtr client)
554 REQUEST(xDPMSDisableReq);
556 swaps(&stuff->length);
557 REQUEST_SIZE_MATCH(xDPMSDisableReq);
559 return ProcDPMSDisable(client);
562 static int _X_COLD
563 SProcDPMSForceLevel(ClientPtr client)
565 REQUEST(xDPMSForceLevelReq);
567 swaps(&stuff->length);
568 REQUEST_SIZE_MATCH(xDPMSForceLevelReq);
570 swaps(&stuff->level);
572 return ProcDPMSForceLevel(client);
575 static int _X_COLD
576 SProcDPMSInfo(ClientPtr client)
578 REQUEST(xDPMSInfoReq);
580 swaps(&stuff->length);
581 REQUEST_SIZE_MATCH(xDPMSInfoReq);
583 return ProcDPMSInfo(client);
586 static int _X_COLD
587 SProcDPMSSelectInput(ClientPtr client)
589 REQUEST(xDPMSSelectInputReq);
590 swaps(&stuff->length);
591 REQUEST_SIZE_MATCH(xDPMSSelectInputReq);
592 swapl(&stuff->eventMask);
593 return ProcDPMSSelectInput(client);
598 static int _X_COLD
599 SProcDPMSDispatch(ClientPtr client)
601 REQUEST(xReq);
602 switch (stuff->data) {
603 case X_DPMSGetVersion:
604 return SProcDPMSGetVersion(client);
605 case X_DPMSCapable:
606 return SProcDPMSCapable(client);
607 case X_DPMSGetTimeouts:
608 return SProcDPMSGetTimeouts(client);
609 case X_DPMSSetTimeouts:
610 return SProcDPMSSetTimeouts(client);
611 case X_DPMSEnable:
612 return SProcDPMSEnable(client);
613 case X_DPMSDisable:
614 return SProcDPMSDisable(client);
615 case X_DPMSForceLevel:
616 return SProcDPMSForceLevel(client);
617 case X_DPMSInfo:
618 return SProcDPMSInfo(client);
619 case X_DPMSSelectInput:
620 return SProcDPMSSelectInput(client);
621 default:
622 return BadRequest;
626 static void
627 DPMSCloseDownExtension(ExtensionEntry *e)
629 DPMSSet(serverClient, DPMSModeOn);
632 void
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);