[PATCH xserver] dpms: Add support for DPMSInfoNotify event

2018-10-02 Thread Alexander Volkov
From: Alexander Volkov 

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 
---
 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 *) , 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 **), 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);
+}
+}

[PATCH xserver] dpms: Add support for DPMSInfoNotify event

2018-10-02 Thread Alexander Volkov
From: Alexander Volkov 

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 
---
 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 *) , 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 **), 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);
+}
+}