Discussion:
[PATCH xorgproto] Add DPMSInfoNotify event
Alexander Volkov
2018-10-02 13:05:48 UTC
Permalink
From: Alexander Volkov <***@rusbitech.ru>

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.

Bump DPMS version to 1.2.

Signed-off-by: Alexander Volkov <***@rusbitech.ru>
---
include/X11/extensions/dpmsconst.h | 5 ++++-
include/X11/extensions/dpmsproto.h | 27 ++++++++++++++++++++++++++-
2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/include/X11/extensions/dpmsconst.h b/include/X11/extensions/dpmsconst.h
index 75f0586..f46d2d9 100644
--- a/include/X11/extensions/dpmsconst.h
+++ b/include/X11/extensions/dpmsconst.h
@@ -30,7 +30,7 @@ Equipment Corporation.
#define _DPMSCONST_H 1

#define DPMSMajorVersion 1
-#define DPMSMinorVersion 1
+#define DPMSMinorVersion 2

#define DPMSExtensionName "DPMS"

@@ -39,5 +39,8 @@ Equipment Corporation.
#define DPMSModeSuspend 2
#define DPMSModeOff 3

+#define DPMSInfoNotifyMask (1L << 0)
+#define DPMSInfoNotify 0
+
#endif /* !_DPMSCONST_H */

diff --git a/include/X11/extensions/dpmsproto.h b/include/X11/extensions/dpmsproto.h
index 63fd3fc..9c26054 100644
--- a/include/X11/extensions/dpmsproto.h
+++ b/include/X11/extensions/dpmsproto.h
@@ -39,8 +39,9 @@ Equipment Corporation.
#define X_DPMSDisable 5
#define X_DPMSForceLevel 6
#define X_DPMSInfo 7
+#define X_DPMSSelectInput 8

-#define DPMSNumberEvents 0
+#define DPMSNumberEvents 1

#define DPMSNumberErrors 0

@@ -172,4 +173,28 @@ typedef struct {
} xDPMSInfoReply;
#define sz_xDPMSInfoReply 32

+typedef struct {
+ CARD8 reqType; /* always DPMSCode */
+ CARD8 dpmsReqType; /* always X_DPMSSelectInput */
+ CARD16 length B16;
+ CARD32 eventMask B32;
+} xDPMSSelectInputReq;
+#define sz_xDPMSSelectInputReq 8
+
+typedef struct {
+ CARD8 type; /* always eventBase + DPMSInfoNotify */
+ CARD8 pad0;
+ CARD16 sequenceNumber B16;
+ Time timestamp B32;
+ CARD16 power_level B16;
+ BOOL state;
+ CARD8 pad1;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xDPMSInfoNotifyEvent;
+#define sz_xDPMSInfoNotifyEvent 32
+
#endif /* _DPMSPROTO_H_ */
--
2.17.0

_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.
Alexander Volkov
2018-10-02 13:05:49 UTC
Permalink
From: Alexander Volkov <***@rusbitech.ru>

It was introduced in 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 <***@rusbitech.ru>
---
Xext/dpms.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 207 insertions(+), 5 deletions(-)

diff --git a/Xext/dpms.c b/Xext/dpms.c
index e43a37974..3ac8b5795 100644
--- a/Xext/dpms.c
+++ b/Xext/dpms.c
@@ -50,6 +50,173 @@ CARD32 DPMSSuspendTime = -1;
CARD32 DPMSOffTime = -1;
Bool DPMSEnabled;

+static int DPMSEventBase = 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(xDPMSInfoNotifyEvent * from,
+ xDPMSInfoNotifyEvent * to)
+{
+ to->type = from->type;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->timestamp, to->timestamp);
+ cpswaps(from->power_level, to->power_level);
+ to->state = from->state;
+}
+
+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 != 0) {
+ 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. This must be indirect as
+ * the list may be arbitrarily rearranged which cannot be
+ * done through the resource database.
+ */
+ 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 = DPMSEventBase + DPMSInfoNotify;
+ se.timestamp = currentTime.milliseconds;
+ se.power_level = DPMSPowerLevel;
+ se.state = DPMSEnabled;
+ WriteEventsToClient(pEvent->client, 1, (xEvent *)&se);
+ }
+}
+
Bool
DPMSSupported(void)
{
@@ -86,6 +253,7 @@ int
DPMSSet(ClientPtr client, int level)
{
int rc, i;
+ int old_level = DPMSPowerLevel;

DPMSPowerLevel = level;

@@ -109,6 +277,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;
}

@@ -212,8 +383,10 @@ ProcDPMSEnable(ClientPtr client)
REQUEST_SIZE_MATCH(xDPMSEnableReq);

DPMSEnabled = TRUE;
- if (!was_enabled)
+ if (!was_enabled) {
SetScreenSaverTimer();
+ SendDPMSInfoNotify();
+ }

return Success;
}
@@ -221,6 +394,8 @@ ProcDPMSEnable(ClientPtr client)
static int
ProcDPMSDisable(ClientPtr client)
{
+ Bool was_enabled = DPMSEnabled;
+
/* REQUEST(xDPMSDisableReq); */

REQUEST_SIZE_MATCH(xDPMSDisableReq);
@@ -228,6 +403,8 @@ ProcDPMSDisable(ClientPtr client)
DPMSSet(client, DPMSModeOn);

DPMSEnabled = FALSE;
+ if (was_enabled)
+ SendDPMSInfoNotify();

return Success;
}
@@ -298,6 +475,8 @@ ProcDPMSDispatch(ClientPtr client)
return ProcDPMSForceLevel(client);
case X_DPMSInfo:
return ProcDPMSInfo(client);
+ case X_DPMSSelectInput:
+ return ProcDPMSSelectInput(client);
default:
return BadRequest;
}
@@ -397,6 +576,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 +609,8 @@ SProcDPMSDispatch(ClientPtr client)
return SProcDPMSForceLevel(client);
case X_DPMSInfo:
return SProcDPMSInfo(client);
+ case X_DPMSSelectInput:
+ return SProcDPMSSelectInput(client);
default:
return BadRequest;
}
@@ -432,6 +625,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 +639,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, DPMSNumberEvents, 0,
+ ProcDPMSDispatch, SProcDPMSDispatch,
+ DPMSCloseDownExtension, StandardMinorOpcode))) {
+ DPMSEventBase = extEntry->eventBase;
+ EventSwapVector[DPMSEventBase] = (EventSwapPtr) SDPMSInfoNotifyEvent;
+ }
}
--
2.17.0

_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.or
Alexander Volkov
2018-10-02 13:05:50 UTC
Permalink
From: Alexander Volkov <***@rusbitech.ru>

See the description in xorgproto repository.

Signed-off-by: Alexander Volkov <***@rusbitech.ru>
---
src/dpms.xml | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/dpms.xml b/src/dpms.xml
index 5581284..51decb7 100644
--- a/src/dpms.xml
+++ b/src/dpms.xml
@@ -26,7 +26,8 @@ sale, use or other dealings in this Software without prior written
authorization from the authors.
-->
<xcb header="dpms" extension-xname="DPMS" extension-name="DPMS"
- major-version="0" minor-version="0">
+ major-version="1" minor-version="2">
+ <import>xproto</import>
<request name="GetVersion" opcode="0">
<field type="CARD16" name="client_major_version" />
<field type="CARD16" name="client_minor_version" />
@@ -84,4 +85,20 @@ authorization from the authors.
<pad bytes="21" />
</reply>
</request>
+
+ <enum name="EventMask" >
+ <item name="InfoNotify"> <bit>0</bit> </item>
+ </enum>
+
+ <request name="SelectInput" opcode="8">
+ <field type="CARD32" name="event_mask" mask="EventMask"/>
+ </request>
+
+ <event name="InfoNotify" number="0">
+ <pad bytes="1" />
+ <field type="TIMESTAMP" name="timestamp"/>
+ <field type="CARD16" name="power_level" enum="DPMSMode" />
+ <field type="BOOL" name="state" />
+ <pad bytes="21"/>
+ </event>
</xcb>
--
2.17.0

_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
In
Alexander Volkov
2018-10-02 13:10:36 UTC
Permalink
From: Alexander Volkov <***@rusbitech.ru>

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.

Bump DPMS version to 1.2.

Signed-off-by: Alexander Volkov <***@rusbitech.ru>
---
include/X11/extensions/dpmsconst.h | 5 ++++-
include/X11/extensions/dpmsproto.h | 27 ++++++++++++++++++++++++++-
2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/include/X11/extensions/dpmsconst.h b/include/X11/extensions/dpmsconst.h
index 75f0586..f46d2d9 100644
--- a/include/X11/extensions/dpmsconst.h
+++ b/include/X11/extensions/dpmsconst.h
@@ -30,7 +30,7 @@ Equipment Corporation.
#define _DPMSCONST_H 1

#define DPMSMajorVersion 1
-#define DPMSMinorVersion 1
+#define DPMSMinorVersion 2

#define DPMSExtensionName "DPMS"

@@ -39,5 +39,8 @@ Equipment Corporation.
#define DPMSModeSuspend 2
#define DPMSModeOff 3

+#define DPMSInfoNotifyMask (1L << 0)
+#define DPMSInfoNotify 0
+
#endif /* !_DPMSCONST_H */

diff --git a/include/X11/extensions/dpmsproto.h b/include/X11/extensions/dpmsproto.h
index 63fd3fc..9c26054 100644
--- a/include/X11/extensions/dpmsproto.h
+++ b/include/X11/extensions/dpmsproto.h
@@ -39,8 +39,9 @@ Equipment Corporation.
#define X_DPMSDisable 5
#define X_DPMSForceLevel 6
#define X_DPMSInfo 7
+#define X_DPMSSelectInput 8

-#define DPMSNumberEvents 0
+#define DPMSNumberEvents 1

#define DPMSNumberErrors 0

@@ -172,4 +173,28 @@ typedef struct {
} xDPMSInfoReply;
#define sz_xDPMSInfoReply 32

+typedef struct {
+ CARD8 reqType; /* always DPMSCode */
+ CARD8 dpmsReqType; /* always X_DPMSSelectInput */
+ CARD16 length B16;
+ CARD32 eventMask B32;
+} xDPMSSelectInputReq;
+#define sz_xDPMSSelectInputReq 8
+
+typedef struct {
+ CARD8 type; /* always eventBase + DPMSInfoNotify */
+ CARD8 pad0;
+ CARD16 sequenceNumber B16;
+ Time timestamp B32;
+ CARD16 power_level B16;
+ BOOL state;
+ CARD8 pad1;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xDPMSInfoNotifyEvent;
+#define sz_xDPMSInfoNotifyEvent 32
+
#endif /* _DPMSPROTO_H_ */
--
2.17.0

_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.
Alexander Volkov
2018-10-02 13:10:37 UTC
Permalink
From: Alexander Volkov <***@rusbitech.ru>

It was introduced in 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 <***@rusbitech.ru>
---
Xext/dpms.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 207 insertions(+), 5 deletions(-)

diff --git a/Xext/dpms.c b/Xext/dpms.c
index e43a37974..3ac8b5795 100644
--- a/Xext/dpms.c
+++ b/Xext/dpms.c
@@ -50,6 +50,173 @@ CARD32 DPMSSuspendTime = -1;
CARD32 DPMSOffTime = -1;
Bool DPMSEnabled;

+static int DPMSEventBase = 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(xDPMSInfoNotifyEvent * from,
+ xDPMSInfoNotifyEvent * to)
+{
+ to->type = from->type;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->timestamp, to->timestamp);
+ cpswaps(from->power_level, to->power_level);
+ to->state = from->state;
+}
+
+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 != 0) {
+ 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. This must be indirect as
+ * the list may be arbitrarily rearranged which cannot be
+ * done through the resource database.
+ */
+ 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 = DPMSEventBase + DPMSInfoNotify;
+ se.timestamp = currentTime.milliseconds;
+ se.power_level = DPMSPowerLevel;
+ se.state = DPMSEnabled;
+ WriteEventsToClient(pEvent->client, 1, (xEvent *)&se);
+ }
+}
+
Bool
DPMSSupported(void)
{
@@ -86,6 +253,7 @@ int
DPMSSet(ClientPtr client, int level)
{
int rc, i;
+ int old_level = DPMSPowerLevel;

DPMSPowerLevel = level;

@@ -109,6 +277,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;
}

@@ -212,8 +383,10 @@ ProcDPMSEnable(ClientPtr client)
REQUEST_SIZE_MATCH(xDPMSEnableReq);

DPMSEnabled = TRUE;
- if (!was_enabled)
+ if (!was_enabled) {
SetScreenSaverTimer();
+ SendDPMSInfoNotify();
+ }

return Success;
}
@@ -221,6 +394,8 @@ ProcDPMSEnable(ClientPtr client)
static int
ProcDPMSDisable(ClientPtr client)
{
+ Bool was_enabled = DPMSEnabled;
+
/* REQUEST(xDPMSDisableReq); */

REQUEST_SIZE_MATCH(xDPMSDisableReq);
@@ -228,6 +403,8 @@ ProcDPMSDisable(ClientPtr client)
DPMSSet(client, DPMSModeOn);

DPMSEnabled = FALSE;
+ if (was_enabled)
+ SendDPMSInfoNotify();

return Success;
}
@@ -298,6 +475,8 @@ ProcDPMSDispatch(ClientPtr client)
return ProcDPMSForceLevel(client);
case X_DPMSInfo:
return ProcDPMSInfo(client);
+ case X_DPMSSelectInput:
+ return ProcDPMSSelectInput(client);
default:
return BadRequest;
}
@@ -397,6 +576,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 +609,8 @@ SProcDPMSDispatch(ClientPtr client)
return SProcDPMSForceLevel(client);
case X_DPMSInfo:
return SProcDPMSInfo(client);
+ case X_DPMSSelectInput:
+ return SProcDPMSSelectInput(client);
default:
return BadRequest;
}
@@ -432,6 +625,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 +639,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, DPMSNumberEvents, 0,
+ ProcDPMSDispatch, SProcDPMSDispatch,
+ DPMSCloseDownExtension, StandardMinorOpcode))) {
+ DPMSEventBase = extEntry->eventBase;
+ EventSwapVector[DPMSEventBase] = (EventSwapPtr) SDPMSInfoNotifyEvent;
+ }
}
--
2.17.0

_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.or
Alexander Volkov
2018-10-02 13:10:38 UTC
Permalink
From: Alexander Volkov <***@rusbitech.ru>

See the description in xorgproto repository.

Signed-off-by: Alexander Volkov <***@rusbitech.ru>
---
src/dpms.xml | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/dpms.xml b/src/dpms.xml
index 5581284..51decb7 100644
--- a/src/dpms.xml
+++ b/src/dpms.xml
@@ -26,7 +26,8 @@ sale, use or other dealings in this Software without prior written
authorization from the authors.
-->
<xcb header="dpms" extension-xname="DPMS" extension-name="DPMS"
- major-version="0" minor-version="0">
+ major-version="1" minor-version="2">
+ <import>xproto</import>
<request name="GetVersion" opcode="0">
<field type="CARD16" name="client_major_version" />
<field type="CARD16" name="client_minor_version" />
@@ -84,4 +85,20 @@ authorization from the authors.
<pad bytes="21" />
</reply>
</request>
+
+ <enum name="EventMask" >
+ <item name="InfoNotify"> <bit>0</bit> </item>
+ </enum>
+
+ <request name="SelectInput" opcode="8">
+ <field type="CARD32" name="event_mask" mask="EventMask"/>
+ </request>
+
+ <event name="InfoNotify" number="0">
+ <pad bytes="1" />
+ <field type="TIMESTAMP" name="timestamp"/>
+ <field type="CARD16" name="power_level" enum="DPMSMode" />
+ <field type="BOOL" name="state" />
+ <pad bytes="21"/>
+ </event>
</xcb>
--
2.17.0

_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
In
Alexander Volkov
2018-10-02 14:20:01 UTC
Permalink
Oh, sorry for sending it twice.

See the test program in the attachment.
It can be compiled by gcc -o dpmsnotify dpmsnotify.c -lxcb -lxcb-dpms
Julien Cristau
2018-10-02 14:33:17 UTC
Permalink
Post by Alexander Volkov
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.
Bump DPMS version to 1.2.
---
include/X11/extensions/dpmsconst.h | 5 ++++-
include/X11/extensions/dpmsproto.h | 27 ++++++++++++++++++++++++++-
2 files changed, 30 insertions(+), 2 deletions(-)
We shouldn't be adding new extension events that don't come through the
Generic Event Extension, as the extension event space is basically full,
IIRC (see
https://lists.x.org/pipermail/xorg-devel/2010-March/006716.html). This
also seems like it might belong in RANDR rather than DPMS, as DPMS
doesn't actually tie things to a monitor?

Cheers,
Julien
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg
Alexander Volkov
2018-10-02 14:51:21 UTC
Permalink
Post by Julien Cristau
We shouldn't be adding new extension events that don't come through the
Generic Event Extension, as the extension event space is basically full,
IIRC (see
https://lists.x.org/pipermail/xorg-devel/2010-March/006716.html).
Ok, thanks.
Post by Julien Cristau
This also seems like it might belong in RANDR rather than DPMS, as DPMS
doesn't actually tie things to a monitor?
DPMS turns off/on all monitors. It's more convenient to process a single
event
than to detect available area from monitor's state.
Besides it seems much harder to implemet DPMS for RANDR.
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: ht
Peter Harris
2018-10-02 15:46:29 UTC
Permalink
Post by Alexander Volkov
-#define DPMSNumberEvents 0
+#define DPMSNumberEvents 1
I don't have a strong opinion, so feel free to ignore me, but in general we don't add core events any more (the limited event space is already full in some configurations).

The "modern" way to add events to extensions is called "generic events". Xcb has <event xge="true">. I'm not sure how Xlib works. See the Present extension for a recent example that uses generic events.

Peter Harris
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo

Loading...