dpms: Add support for DPMSInfoNotify event from DPMS 1.2 (xorgproto)
This allows applications to respond to changes of power level of a monitor, e.g. an application may stop rendering and related calculations when the monitor is off. Related bug: https://bugs.freedesktop.org/57120 Signed-off-by: Alexander Volkov <avolkov@astralinux.ru>
This commit is contained in:
parent
1bf4d60acd
commit
62fec48a6b
222
Xext/dpms.c
222
Xext/dpms.c
|
@ -42,6 +42,7 @@ Equipment Corporation.
|
|||
#include "extinit.h"
|
||||
#include "scrnintstr.h"
|
||||
#include "windowstr.h"
|
||||
#include "protocol-versions.h"
|
||||
|
||||
CARD16 DPMSPowerLevel = 0;
|
||||
Bool DPMSDisabledSwitch = FALSE;
|
||||
|
@ -50,6 +51,178 @@ CARD32 DPMSSuspendTime = -1;
|
|||
CARD32 DPMSOffTime = -1;
|
||||
Bool DPMSEnabled;
|
||||
|
||||
static int DPMSReqCode = 0;
|
||||
static RESTYPE ClientType, DPMSEventType; /* resource types for event masks */
|
||||
static XID eventResource;
|
||||
|
||||
typedef struct _DPMSEvent *DPMSEventPtr;
|
||||
typedef struct _DPMSEvent {
|
||||
DPMSEventPtr next;
|
||||
ClientPtr client;
|
||||
XID clientResource;
|
||||
unsigned int mask;
|
||||
} DPMSEventRec;
|
||||
|
||||
/*ARGSUSED*/ static int
|
||||
DPMSFreeClient(void *data, XID id)
|
||||
{
|
||||
DPMSEventPtr pEvent;
|
||||
DPMSEventPtr *pHead, pCur, pPrev;
|
||||
|
||||
pEvent = (DPMSEventPtr) data;
|
||||
dixLookupResourceByType((void *) &pHead, eventResource, DPMSEventType,
|
||||
NullClient, DixUnknownAccess);
|
||||
if (pHead) {
|
||||
pPrev = 0;
|
||||
for (pCur = *pHead; pCur && pCur != pEvent; pCur = pCur->next)
|
||||
pPrev = pCur;
|
||||
if (pCur) {
|
||||
if (pPrev)
|
||||
pPrev->next = pEvent->next;
|
||||
else
|
||||
*pHead = pEvent->next;
|
||||
}
|
||||
}
|
||||
free((void *) pEvent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/ static int
|
||||
DPMSFreeEvents(void *data, XID id)
|
||||
{
|
||||
DPMSEventPtr *pHead, pCur, pNext;
|
||||
|
||||
pHead = (DPMSEventPtr *) data;
|
||||
for (pCur = *pHead; pCur; pCur = pNext) {
|
||||
pNext = pCur->next;
|
||||
FreeResource(pCur->clientResource, ClientType);
|
||||
free((void *) pCur);
|
||||
}
|
||||
free((void *) pHead);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
SDPMSInfoNotifyEvent(xGenericEvent * from,
|
||||
xGenericEvent * to)
|
||||
{
|
||||
*to = *from;
|
||||
swaps(&to->sequenceNumber);
|
||||
swapl(&to->length);
|
||||
swaps(&to->evtype);
|
||||
if (from->evtype == DPMSInfoNotify) {
|
||||
xDPMSInfoNotifyEvent *c = (xDPMSInfoNotifyEvent *) to;
|
||||
swapl(&c->timestamp);
|
||||
swaps(&c->power_level);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ProcDPMSSelectInput(register ClientPtr client)
|
||||
{
|
||||
REQUEST(xDPMSSelectInputReq);
|
||||
DPMSEventPtr pEvent, pNewEvent, *pHead;
|
||||
XID clientResource;
|
||||
int i;
|
||||
|
||||
REQUEST_SIZE_MATCH(xDPMSSelectInputReq);
|
||||
i = dixLookupResourceByType((void **)&pHead, eventResource, DPMSEventType,
|
||||
client,
|
||||
DixWriteAccess);
|
||||
if (stuff->eventMask == DPMSInfoNotifyMask) {
|
||||
if (i == Success && pHead) {
|
||||
/* check for existing entry. */
|
||||
for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
|
||||
if (pEvent->client == client) {
|
||||
pEvent->mask = stuff->eventMask;
|
||||
return Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* build the entry */
|
||||
pNewEvent = (DPMSEventPtr)malloc(sizeof(DPMSEventRec));
|
||||
if (!pNewEvent)
|
||||
return BadAlloc;
|
||||
pNewEvent->next = 0;
|
||||
pNewEvent->client = client;
|
||||
pNewEvent->mask = stuff->eventMask;
|
||||
/*
|
||||
* add a resource that will be deleted when
|
||||
* the client goes away
|
||||
*/
|
||||
clientResource = FakeClientID(client->index);
|
||||
pNewEvent->clientResource = clientResource;
|
||||
if (!AddResource(clientResource, ClientType, (void *)pNewEvent))
|
||||
return BadAlloc;
|
||||
/*
|
||||
* create a resource to contain a pointer to the list
|
||||
* of clients selecting input
|
||||
*/
|
||||
if (i != Success || !pHead) {
|
||||
pHead = (DPMSEventPtr *)malloc(sizeof(DPMSEventPtr));
|
||||
if (!pHead ||
|
||||
!AddResource(eventResource, DPMSEventType, (void *)pHead)) {
|
||||
FreeResource(clientResource, RT_NONE);
|
||||
return BadAlloc;
|
||||
}
|
||||
*pHead = 0;
|
||||
}
|
||||
pNewEvent->next = *pHead;
|
||||
*pHead = pNewEvent;
|
||||
}
|
||||
else if (stuff->eventMask == 0) {
|
||||
/* delete the interest */
|
||||
if (i == Success && pHead) {
|
||||
pNewEvent = 0;
|
||||
for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
|
||||
if (pEvent->client == client)
|
||||
break;
|
||||
pNewEvent = pEvent;
|
||||
}
|
||||
if (pEvent) {
|
||||
FreeResource(pEvent->clientResource, ClientType);
|
||||
if (pNewEvent)
|
||||
pNewEvent->next = pEvent->next;
|
||||
else
|
||||
*pHead = pEvent->next;
|
||||
free(pEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
client->errorValue = stuff->eventMask;
|
||||
return BadValue;
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
static void
|
||||
SendDPMSInfoNotify(void)
|
||||
{
|
||||
DPMSEventPtr *pHead, pEvent;
|
||||
xDPMSInfoNotifyEvent se;
|
||||
int i;
|
||||
|
||||
i = dixLookupResourceByType((void **)&pHead, eventResource, DPMSEventType,
|
||||
serverClient,
|
||||
DixReadAccess);
|
||||
if (i != Success || !pHead)
|
||||
return;
|
||||
for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
|
||||
if ((pEvent->mask & DPMSInfoNotifyMask) == 0)
|
||||
continue;
|
||||
se.type = GenericEvent;
|
||||
se.extension = DPMSReqCode;
|
||||
se.length = (sizeof(xDPMSInfoNotifyEvent) - 32) >> 2;
|
||||
se.evtype = DPMSInfoNotify;
|
||||
se.timestamp = currentTime.milliseconds;
|
||||
se.power_level = DPMSPowerLevel;
|
||||
se.state = DPMSEnabled;
|
||||
WriteEventsToClient(pEvent->client, 1, (xEvent *)&se);
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
DPMSSupported(void)
|
||||
{
|
||||
|
@ -86,6 +259,7 @@ int
|
|||
DPMSSet(ClientPtr client, int level)
|
||||
{
|
||||
int rc, i;
|
||||
int old_level = DPMSPowerLevel;
|
||||
|
||||
DPMSPowerLevel = level;
|
||||
|
||||
|
@ -109,6 +283,9 @@ DPMSSet(ClientPtr client, int level)
|
|||
if (screenInfo.gpuscreens[i]->DPMS != NULL)
|
||||
screenInfo.gpuscreens[i]->DPMS(screenInfo.gpuscreens[i], level);
|
||||
|
||||
if (DPMSPowerLevel != old_level)
|
||||
SendDPMSInfoNotify();
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
@ -120,8 +297,8 @@ ProcDPMSGetVersion(ClientPtr client)
|
|||
.type = X_Reply,
|
||||
.sequenceNumber = client->sequence,
|
||||
.length = 0,
|
||||
.majorVersion = DPMSMajorVersion,
|
||||
.minorVersion = DPMSMinorVersion
|
||||
.majorVersion = SERVER_DPMS_MAJOR_VERSION,
|
||||
.minorVersion = SERVER_DPMS_MINOR_VERSION
|
||||
};
|
||||
|
||||
REQUEST_SIZE_MATCH(xDPMSGetVersionReq);
|
||||
|
@ -212,8 +389,10 @@ ProcDPMSEnable(ClientPtr client)
|
|||
REQUEST_SIZE_MATCH(xDPMSEnableReq);
|
||||
|
||||
DPMSEnabled = TRUE;
|
||||
if (!was_enabled)
|
||||
if (!was_enabled) {
|
||||
SetScreenSaverTimer();
|
||||
SendDPMSInfoNotify();
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
@ -221,6 +400,8 @@ ProcDPMSEnable(ClientPtr client)
|
|||
static int
|
||||
ProcDPMSDisable(ClientPtr client)
|
||||
{
|
||||
Bool was_enabled = DPMSEnabled;
|
||||
|
||||
/* REQUEST(xDPMSDisableReq); */
|
||||
|
||||
REQUEST_SIZE_MATCH(xDPMSDisableReq);
|
||||
|
@ -228,6 +409,8 @@ ProcDPMSDisable(ClientPtr client)
|
|||
DPMSSet(client, DPMSModeOn);
|
||||
|
||||
DPMSEnabled = FALSE;
|
||||
if (was_enabled)
|
||||
SendDPMSInfoNotify();
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
@ -298,6 +481,8 @@ ProcDPMSDispatch(ClientPtr client)
|
|||
return ProcDPMSForceLevel(client);
|
||||
case X_DPMSInfo:
|
||||
return ProcDPMSInfo(client);
|
||||
case X_DPMSSelectInput:
|
||||
return ProcDPMSSelectInput(client);
|
||||
default:
|
||||
return BadRequest;
|
||||
}
|
||||
|
@ -397,6 +582,18 @@ SProcDPMSInfo(ClientPtr client)
|
|||
return ProcDPMSInfo(client);
|
||||
}
|
||||
|
||||
static int _X_COLD
|
||||
SProcDPMSSelectInput(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDPMSSelectInputReq);
|
||||
swaps(&stuff->length);
|
||||
REQUEST_SIZE_MATCH(xDPMSSelectInputReq);
|
||||
swapl(&stuff->eventMask);
|
||||
return ProcDPMSSelectInput(client);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int _X_COLD
|
||||
SProcDPMSDispatch(ClientPtr client)
|
||||
{
|
||||
|
@ -418,6 +615,8 @@ SProcDPMSDispatch(ClientPtr client)
|
|||
return SProcDPMSForceLevel(client);
|
||||
case X_DPMSInfo:
|
||||
return SProcDPMSInfo(client);
|
||||
case X_DPMSSelectInput:
|
||||
return SProcDPMSSelectInput(client);
|
||||
default:
|
||||
return BadRequest;
|
||||
}
|
||||
|
@ -432,6 +631,8 @@ DPMSCloseDownExtension(ExtensionEntry *e)
|
|||
void
|
||||
DPMSExtensionInit(void)
|
||||
{
|
||||
ExtensionEntry *extEntry;
|
||||
|
||||
#define CONDITIONALLY_SET_DPMS_TIMEOUT(_timeout_value_) \
|
||||
if (_timeout_value_ == -1) { /* not yet set from config */ \
|
||||
_timeout_value_ = ScreenSaverTime; \
|
||||
|
@ -444,8 +645,15 @@ DPMSExtensionInit(void)
|
|||
DPMSPowerLevel = DPMSModeOn;
|
||||
DPMSEnabled = DPMSSupported();
|
||||
|
||||
if (DPMSEnabled)
|
||||
AddExtension(DPMSExtensionName, 0, 0,
|
||||
ProcDPMSDispatch, SProcDPMSDispatch,
|
||||
DPMSCloseDownExtension, StandardMinorOpcode);
|
||||
ClientType = CreateNewResourceType(DPMSFreeClient, "DPMSClient");
|
||||
DPMSEventType = CreateNewResourceType(DPMSFreeEvents, "DPMSEvent");
|
||||
eventResource = FakeClientID(0);
|
||||
|
||||
if (DPMSEnabled && ClientType && DPMSEventType &&
|
||||
(extEntry = AddExtension(DPMSExtensionName, 0, 0,
|
||||
ProcDPMSDispatch, SProcDPMSDispatch,
|
||||
DPMSCloseDownExtension, StandardMinorOpcode))) {
|
||||
DPMSReqCode = extEntry->base;
|
||||
GERegisterExtension(DPMSReqCode, SDPMSInfoNotifyEvent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@
|
|||
#define SERVER_DAMAGE_MAJOR_VERSION 1
|
||||
#define SERVER_DAMAGE_MINOR_VERSION 1
|
||||
|
||||
/* DPMS */
|
||||
#define SERVER_DPMS_MAJOR_VERSION 1
|
||||
#define SERVER_DPMS_MINOR_VERSION 2
|
||||
|
||||
/* DRI3 */
|
||||
#define SERVER_DRI3_MAJOR_VERSION 1
|
||||
#define SERVER_DRI3_MINOR_VERSION 2
|
||||
|
|
|
@ -96,6 +96,7 @@ xf86vidmodeproto_dep = dependency('xf86vidmodeproto', version: '>= 2.2.99.1', fa
|
|||
applewmproto_dep = dependency('applewmproto', version: '>= 1.4', fallback: ['xorgproto', 'ext_xorgproto'], required: false)
|
||||
xshmfence_dep = dependency('xshmfence', version: '>= 1.1', required: false)
|
||||
xwaylandproto_dep = dependency('xwaylandproto', version: '>= 1.0', fallback: ['xorgproto', 'ext_xorgproto'], required: false)
|
||||
dpmsproto_dep = dependency('dpmsproto', version: '>= 1.2', required: get_option('dpms'))
|
||||
|
||||
pixman_dep = dependency('pixman-1')
|
||||
libbsd_dep = dependency('libbsd-overlay', required: false)
|
||||
|
@ -631,6 +632,7 @@ common_dep = [
|
|||
xf86dgaproto_dep,
|
||||
xf86vidmodeproto_dep,
|
||||
applewmproto_dep,
|
||||
dpmsproto_dep,
|
||||
|
||||
pixman_dep,
|
||||
libbsd_dep,
|
||||
|
|
Loading…
Reference in New Issue