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