XISelEv.c revision 3e256790
1/************************************************************
2
3Copyright 2009 Red Hat, Inc.
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of the author shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from the author.
24
25*/
26
27/***********************************************************************
28 *
29 * XISelectEvent - Select for XI2 events.
30 *
31 */
32
33
34#include <stdint.h>
35#include <X11/Xlibint.h>
36#include <X11/extensions/XI2proto.h>
37#include <X11/extensions/XInput2.h>
38#include <X11/extensions/extutil.h>
39#include <X11/extensions/ge.h>
40#include <X11/extensions/geproto.h>
41#include "XIint.h"
42
43int
44XISelectEvents(Display* dpy, Window win, XIEventMask* masks, int num_masks)
45{
46    XIEventMask  *current;
47    xXISelectEventsReq  *req;
48    xXIEventMask mask;
49    int i;
50    int len = 0;
51    int r = Success;
52
53    XExtDisplayInfo *info = XInput_find_display(dpy);
54    LockDisplay(dpy);
55    if (_XiCheckExtInit(dpy, Dont_Check, info) == -1) {
56        r = NoSuchExtension;
57        goto out;
58    }
59    GetReq(XISelectEvents, req);
60
61    req->reqType = info->codes->major_opcode;
62    req->ReqType = X_XISelectEvents;
63    req->win = win;
64    req->num_masks = num_masks;
65
66    /* get the right length */
67    for (i = 0; i < num_masks; i++)
68    {
69        len++;
70        current = &masks[i];
71        len += (current->mask_len + 3)/4;
72    }
73
74    SetReqLen(req, len, len);
75
76    for (i = 0; i < num_masks; i++)
77    {
78        char *buff;
79        current = &masks[i];
80        mask.deviceid = current->deviceid;
81        mask.mask_len = (current->mask_len + 3)/4;
82        /* masks.mask_len is in bytes, but we need 4-byte units on the wire,
83         * and they need to be padded with 0 */
84        buff = calloc(1, mask.mask_len * 4);
85        memcpy(buff, current->mask, current->mask_len);
86        Data32(dpy, &mask, sizeof(xXIEventMask));
87        Data(dpy, buff, mask.mask_len * 4);
88        free(buff);
89    }
90
91out:
92    UnlockDisplay(dpy);
93    SyncHandle();
94    return r;
95
96}
97
98XIEventMask*
99XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return)
100{
101    int i, len = 0;
102    unsigned char *mask;
103    XIEventMask *mask_out = NULL;
104    xXIEventMask *mask_in = NULL, *mi;
105    xXIGetSelectedEventsReq *req;
106    xXIGetSelectedEventsReply reply;
107
108    *num_masks_return = -1;
109    XExtDisplayInfo *info = XInput_find_display(dpy);
110    LockDisplay(dpy);
111    if (_XiCheckExtInit(dpy, Dont_Check, info) == -1)
112        goto out;
113
114    GetReq(XIGetSelectedEvents, req);
115
116    req->reqType = info->codes->major_opcode;
117    req->ReqType = X_XIGetSelectedEvents;
118    req->win = win;
119
120    if (!_XReply(dpy, (xReply *) &reply, 0, xFalse))
121        goto out;
122
123    if (reply.num_masks == 0)
124    {
125        *num_masks_return = 0;
126        goto out;
127    }
128
129    mask_in = Xmalloc(reply.length * 4);
130    if (!mask_in)
131        goto out;
132
133    _XRead(dpy, (char*)mask_in, reply.length * 4);
134
135    /* Memory layout of the XIEventMask for a 3 mask reply:
136     * [struct a][struct b][struct c][masks a][masks b][masks c]
137     */
138    len = reply.num_masks * sizeof(XIEventMask);
139
140    for (i = 0, mi = mask_in; i < reply.num_masks; i++)
141    {
142        len += mi->mask_len * 4;
143        mi = (xXIEventMask*)((char*)mi + mi->mask_len * 4);
144        mi++;
145    }
146
147    mask_out = Xmalloc(len);
148    if (!mask_out)
149        goto out;
150
151    mi = mask_in;
152    mask = (unsigned char*)&mask_out[reply.num_masks];
153    for (i = 0; i < reply.num_masks; i++)
154    {
155        mask_out[i].deviceid = mi->deviceid;
156        mask_out[i].mask_len = mi->mask_len * 4;
157        mask_out[i].mask = mask;
158        memcpy(mask_out[i].mask, &mi[1], mask_out[i].mask_len);
159        mask += mask_out[i].mask_len;
160        mi = (xXIEventMask*)((char*)mi + mi->mask_len * 4);
161        mi++;
162    }
163
164    *num_masks_return = reply.num_masks;
165
166out:
167    Xfree(mask_in);
168
169    UnlockDisplay(dpy);
170    SyncHandle();
171
172    return mask_out;
173}
174