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
220
Xext/dpms.c
220
Xext/dpms.c
|
@ -42,6 +42,7 @@ Equipment Corporation.
|
||||||
#include "extinit.h"
|
#include "extinit.h"
|
||||||
#include "scrnintstr.h"
|
#include "scrnintstr.h"
|
||||||
#include "windowstr.h"
|
#include "windowstr.h"
|
||||||
|
#include "protocol-versions.h"
|
||||||
|
|
||||||
CARD16 DPMSPowerLevel = 0;
|
CARD16 DPMSPowerLevel = 0;
|
||||||
Bool DPMSDisabledSwitch = FALSE;
|
Bool DPMSDisabledSwitch = FALSE;
|
||||||
|
@ -50,6 +51,178 @@ CARD32 DPMSSuspendTime = -1;
|
||||||
CARD32 DPMSOffTime = -1;
|
CARD32 DPMSOffTime = -1;
|
||||||
Bool DPMSEnabled;
|
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
|
Bool
|
||||||
DPMSSupported(void)
|
DPMSSupported(void)
|
||||||
{
|
{
|
||||||
|
@ -86,6 +259,7 @@ int
|
||||||
DPMSSet(ClientPtr client, int level)
|
DPMSSet(ClientPtr client, int level)
|
||||||
{
|
{
|
||||||
int rc, i;
|
int rc, i;
|
||||||
|
int old_level = DPMSPowerLevel;
|
||||||
|
|
||||||
DPMSPowerLevel = level;
|
DPMSPowerLevel = level;
|
||||||
|
|
||||||
|
@ -109,6 +283,9 @@ DPMSSet(ClientPtr client, int level)
|
||||||
if (screenInfo.gpuscreens[i]->DPMS != NULL)
|
if (screenInfo.gpuscreens[i]->DPMS != NULL)
|
||||||
screenInfo.gpuscreens[i]->DPMS(screenInfo.gpuscreens[i], level);
|
screenInfo.gpuscreens[i]->DPMS(screenInfo.gpuscreens[i], level);
|
||||||
|
|
||||||
|
if (DPMSPowerLevel != old_level)
|
||||||
|
SendDPMSInfoNotify();
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,8 +297,8 @@ ProcDPMSGetVersion(ClientPtr client)
|
||||||
.type = X_Reply,
|
.type = X_Reply,
|
||||||
.sequenceNumber = client->sequence,
|
.sequenceNumber = client->sequence,
|
||||||
.length = 0,
|
.length = 0,
|
||||||
.majorVersion = DPMSMajorVersion,
|
.majorVersion = SERVER_DPMS_MAJOR_VERSION,
|
||||||
.minorVersion = DPMSMinorVersion
|
.minorVersion = SERVER_DPMS_MINOR_VERSION
|
||||||
};
|
};
|
||||||
|
|
||||||
REQUEST_SIZE_MATCH(xDPMSGetVersionReq);
|
REQUEST_SIZE_MATCH(xDPMSGetVersionReq);
|
||||||
|
@ -212,8 +389,10 @@ ProcDPMSEnable(ClientPtr client)
|
||||||
REQUEST_SIZE_MATCH(xDPMSEnableReq);
|
REQUEST_SIZE_MATCH(xDPMSEnableReq);
|
||||||
|
|
||||||
DPMSEnabled = TRUE;
|
DPMSEnabled = TRUE;
|
||||||
if (!was_enabled)
|
if (!was_enabled) {
|
||||||
SetScreenSaverTimer();
|
SetScreenSaverTimer();
|
||||||
|
SendDPMSInfoNotify();
|
||||||
|
}
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
@ -221,6 +400,8 @@ ProcDPMSEnable(ClientPtr client)
|
||||||
static int
|
static int
|
||||||
ProcDPMSDisable(ClientPtr client)
|
ProcDPMSDisable(ClientPtr client)
|
||||||
{
|
{
|
||||||
|
Bool was_enabled = DPMSEnabled;
|
||||||
|
|
||||||
/* REQUEST(xDPMSDisableReq); */
|
/* REQUEST(xDPMSDisableReq); */
|
||||||
|
|
||||||
REQUEST_SIZE_MATCH(xDPMSDisableReq);
|
REQUEST_SIZE_MATCH(xDPMSDisableReq);
|
||||||
|
@ -228,6 +409,8 @@ ProcDPMSDisable(ClientPtr client)
|
||||||
DPMSSet(client, DPMSModeOn);
|
DPMSSet(client, DPMSModeOn);
|
||||||
|
|
||||||
DPMSEnabled = FALSE;
|
DPMSEnabled = FALSE;
|
||||||
|
if (was_enabled)
|
||||||
|
SendDPMSInfoNotify();
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
@ -298,6 +481,8 @@ ProcDPMSDispatch(ClientPtr client)
|
||||||
return ProcDPMSForceLevel(client);
|
return ProcDPMSForceLevel(client);
|
||||||
case X_DPMSInfo:
|
case X_DPMSInfo:
|
||||||
return ProcDPMSInfo(client);
|
return ProcDPMSInfo(client);
|
||||||
|
case X_DPMSSelectInput:
|
||||||
|
return ProcDPMSSelectInput(client);
|
||||||
default:
|
default:
|
||||||
return BadRequest;
|
return BadRequest;
|
||||||
}
|
}
|
||||||
|
@ -397,6 +582,18 @@ SProcDPMSInfo(ClientPtr client)
|
||||||
return ProcDPMSInfo(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
|
static int _X_COLD
|
||||||
SProcDPMSDispatch(ClientPtr client)
|
SProcDPMSDispatch(ClientPtr client)
|
||||||
{
|
{
|
||||||
|
@ -418,6 +615,8 @@ SProcDPMSDispatch(ClientPtr client)
|
||||||
return SProcDPMSForceLevel(client);
|
return SProcDPMSForceLevel(client);
|
||||||
case X_DPMSInfo:
|
case X_DPMSInfo:
|
||||||
return SProcDPMSInfo(client);
|
return SProcDPMSInfo(client);
|
||||||
|
case X_DPMSSelectInput:
|
||||||
|
return SProcDPMSSelectInput(client);
|
||||||
default:
|
default:
|
||||||
return BadRequest;
|
return BadRequest;
|
||||||
}
|
}
|
||||||
|
@ -432,6 +631,8 @@ DPMSCloseDownExtension(ExtensionEntry *e)
|
||||||
void
|
void
|
||||||
DPMSExtensionInit(void)
|
DPMSExtensionInit(void)
|
||||||
{
|
{
|
||||||
|
ExtensionEntry *extEntry;
|
||||||
|
|
||||||
#define CONDITIONALLY_SET_DPMS_TIMEOUT(_timeout_value_) \
|
#define CONDITIONALLY_SET_DPMS_TIMEOUT(_timeout_value_) \
|
||||||
if (_timeout_value_ == -1) { /* not yet set from config */ \
|
if (_timeout_value_ == -1) { /* not yet set from config */ \
|
||||||
_timeout_value_ = ScreenSaverTime; \
|
_timeout_value_ = ScreenSaverTime; \
|
||||||
|
@ -444,8 +645,15 @@ DPMSExtensionInit(void)
|
||||||
DPMSPowerLevel = DPMSModeOn;
|
DPMSPowerLevel = DPMSModeOn;
|
||||||
DPMSEnabled = DPMSSupported();
|
DPMSEnabled = DPMSSupported();
|
||||||
|
|
||||||
if (DPMSEnabled)
|
ClientType = CreateNewResourceType(DPMSFreeClient, "DPMSClient");
|
||||||
AddExtension(DPMSExtensionName, 0, 0,
|
DPMSEventType = CreateNewResourceType(DPMSFreeEvents, "DPMSEvent");
|
||||||
|
eventResource = FakeClientID(0);
|
||||||
|
|
||||||
|
if (DPMSEnabled && ClientType && DPMSEventType &&
|
||||||
|
(extEntry = AddExtension(DPMSExtensionName, 0, 0,
|
||||||
ProcDPMSDispatch, SProcDPMSDispatch,
|
ProcDPMSDispatch, SProcDPMSDispatch,
|
||||||
DPMSCloseDownExtension, StandardMinorOpcode);
|
DPMSCloseDownExtension, StandardMinorOpcode))) {
|
||||||
|
DPMSReqCode = extEntry->base;
|
||||||
|
GERegisterExtension(DPMSReqCode, SDPMSInfoNotifyEvent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,10 @@
|
||||||
#define SERVER_DAMAGE_MAJOR_VERSION 1
|
#define SERVER_DAMAGE_MAJOR_VERSION 1
|
||||||
#define SERVER_DAMAGE_MINOR_VERSION 1
|
#define SERVER_DAMAGE_MINOR_VERSION 1
|
||||||
|
|
||||||
|
/* DPMS */
|
||||||
|
#define SERVER_DPMS_MAJOR_VERSION 1
|
||||||
|
#define SERVER_DPMS_MINOR_VERSION 2
|
||||||
|
|
||||||
/* DRI3 */
|
/* DRI3 */
|
||||||
#define SERVER_DRI3_MAJOR_VERSION 1
|
#define SERVER_DRI3_MAJOR_VERSION 1
|
||||||
#define SERVER_DRI3_MINOR_VERSION 2
|
#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)
|
applewmproto_dep = dependency('applewmproto', version: '>= 1.4', fallback: ['xorgproto', 'ext_xorgproto'], required: false)
|
||||||
xshmfence_dep = dependency('xshmfence', version: '>= 1.1', required: false)
|
xshmfence_dep = dependency('xshmfence', version: '>= 1.1', required: false)
|
||||||
xwaylandproto_dep = dependency('xwaylandproto', version: '>= 1.0', fallback: ['xorgproto', 'ext_xorgproto'], 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')
|
pixman_dep = dependency('pixman-1')
|
||||||
libbsd_dep = dependency('libbsd-overlay', required: false)
|
libbsd_dep = dependency('libbsd-overlay', required: false)
|
||||||
|
@ -631,6 +632,7 @@ common_dep = [
|
||||||
xf86dgaproto_dep,
|
xf86dgaproto_dep,
|
||||||
xf86vidmodeproto_dep,
|
xf86vidmodeproto_dep,
|
||||||
applewmproto_dep,
|
applewmproto_dep,
|
||||||
|
dpmsproto_dep,
|
||||||
|
|
||||||
pixman_dep,
|
pixman_dep,
|
||||||
libbsd_dep,
|
libbsd_dep,
|
||||||
|
|
Loading…
Reference in New Issue