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