xserver: Branch 'master'
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Dec 18 16:07:54 UTC 2023
Xext/dpms.c | 222 ++++++++++++++++++++++++++++++++++++++++++--
include/protocol-versions.h | 4
meson.build | 2
3 files changed, 221 insertions(+), 7 deletions(-)
New commits:
commit 62fec48a6b156ba06f3187f25c28503b1daca73b
Author: Alexander Volkov <avolkov at astralinux.ru>
Date: Mon Oct 1 19:52:30 2018 +0300
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 at astralinux.ru>
diff --git a/Xext/dpms.c b/Xext/dpms.c
index e43a37974..a0df33f3d 100644
--- a/Xext/dpms.c
+++ b/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);
+ }
}
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index d7bfc6dca..bb2b81b8f 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -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
diff --git a/meson.build b/meson.build
index 6a695d182..d183762d1 100644
--- a/meson.build
+++ b/meson.build
@@ -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,
More information about the xorg-commit
mailing list