16747b715Smrg/*
26747b715Smrg * Copyright 2008 Red Hat, Inc.
36747b715Smrg *
46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
56747b715Smrg * copy of this software and associated documentation files (the "Software"),
66747b715Smrg * to deal in the Software without restriction, including without limitation
76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
96747b715Smrg * Software is furnished to do so, subject to the following conditions:
106747b715Smrg *
116747b715Smrg * The above copyright notice and this permission notice (including the next
126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
136747b715Smrg * Software.
146747b715Smrg *
156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
216747b715Smrg * DEALINGS IN THE SOFTWARE.
226747b715Smrg *
236747b715Smrg * Author: Peter Hutterer
246747b715Smrg */
256747b715Smrg
266747b715Smrg#ifdef HAVE_DIX_CONFIG_H
276747b715Smrg#include <dix-config.h>
286747b715Smrg#endif
296747b715Smrg
306747b715Smrg#include "dixstruct.h"
316747b715Smrg#include "windowstr.h"
326747b715Smrg#include "exglobals.h"
336747b715Smrg#include "exevents.h"
346747b715Smrg#include <X11/extensions/XI2proto.h>
35f7df2e56Smrg#include "inpututils.h"
366747b715Smrg
376747b715Smrg#include "xiselectev.h"
386747b715Smrg
39f7df2e56Smrg/**
40f7df2e56Smrg * Ruleset:
41f7df2e56Smrg * - if A has XIAllDevices, B may select on device X
42f7df2e56Smrg * - If A has XIAllDevices, B may select on XIAllMasterDevices
43f7df2e56Smrg * - If A has XIAllMasterDevices, B may select on device X
44f7df2e56Smrg * - If A has XIAllMasterDevices, B may select on XIAllDevices
45f7df2e56Smrg * - if A has device X, B may select on XIAllDevices/XIAllMasterDevices
46f7df2e56Smrg */
475a112b11Smrgstatic int
485a112b11Smrgcheck_for_touch_selection_conflicts(ClientPtr B, WindowPtr win, int deviceid,
495a112b11Smrg                                    int evtype)
50f7df2e56Smrg{
51f7df2e56Smrg    OtherInputMasks *inputMasks = wOtherInputMasks(win);
52f7df2e56Smrg    InputClients *A = NULL;
53f7df2e56Smrg
54f7df2e56Smrg    if (inputMasks)
55f7df2e56Smrg        A = inputMasks->inputClients;
56f7df2e56Smrg    for (; A; A = A->next) {
57f7df2e56Smrg        DeviceIntPtr tmp;
58f7df2e56Smrg
59f7df2e56Smrg        if (CLIENT_ID(A->resource) == B->index)
60f7df2e56Smrg            continue;
61f7df2e56Smrg
62f7df2e56Smrg        if (deviceid == XIAllDevices)
63f7df2e56Smrg            tmp = inputInfo.all_devices;
64f7df2e56Smrg        else if (deviceid == XIAllMasterDevices)
65f7df2e56Smrg            tmp = inputInfo.all_master_devices;
66f7df2e56Smrg        else
67f7df2e56Smrg            dixLookupDevice(&tmp, deviceid, serverClient, DixReadAccess);
68f7df2e56Smrg        if (!tmp)
69f7df2e56Smrg            return BadImplementation;       /* this shouldn't happen */
70f7df2e56Smrg
71f7df2e56Smrg        /* A has XIAllDevices */
725a112b11Smrg        if (xi2mask_isset_for_device(A->xi2mask, inputInfo.all_devices, evtype)) {
73f7df2e56Smrg            if (deviceid == XIAllDevices)
74f7df2e56Smrg                return BadAccess;
75f7df2e56Smrg        }
76f7df2e56Smrg
77f7df2e56Smrg        /* A has XIAllMasterDevices */
785a112b11Smrg        if (xi2mask_isset_for_device(A->xi2mask, inputInfo.all_master_devices, evtype)) {
79f7df2e56Smrg            if (deviceid == XIAllMasterDevices)
80f7df2e56Smrg                return BadAccess;
81f7df2e56Smrg        }
82f7df2e56Smrg
83f7df2e56Smrg        /* A has this device */
845a112b11Smrg        if (xi2mask_isset_for_device(A->xi2mask, tmp, evtype))
85f7df2e56Smrg            return BadAccess;
86f7df2e56Smrg    }
87f7df2e56Smrg
88f7df2e56Smrg    return Success;
89f7df2e56Smrg}
90f7df2e56Smrg
91f7df2e56Smrg
926747b715Smrg/**
936747b715Smrg * Check the given mask (in len bytes) for invalid mask bits.
946747b715Smrg * Invalid mask bits are any bits above XI2LastEvent.
956747b715Smrg *
966747b715Smrg * @return BadValue if at least one invalid bit is set or Success otherwise.
976747b715Smrg */
98f7df2e56Smrgint
99f7df2e56SmrgXICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len)
1006747b715Smrg{
101f7df2e56Smrg    if (len >= XIMaskLen(XI2LASTEVENT)) {
1026747b715Smrg        int i;
103f7df2e56Smrg
104f7df2e56Smrg        for (i = XI2LASTEVENT + 1; i < len * 8; i++) {
105f7df2e56Smrg            if (BitIsOn(mask, i)) {
1069ace9065Smrg                client->errorValue = i;
1076747b715Smrg                return BadValue;
1089ace9065Smrg            }
1099ace9065Smrg        }
1106747b715Smrg    }
1116747b715Smrg
1126747b715Smrg    return Success;
1136747b715Smrg}
1146747b715Smrg
1157e31ba66Smrgint _X_COLD
1166747b715SmrgSProcXISelectEvents(ClientPtr client)
1176747b715Smrg{
1186747b715Smrg    int i;
1190b0d8713Smrg    int len;
120f7df2e56Smrg    xXIEventMask *evmask;
1216747b715Smrg
1226747b715Smrg    REQUEST(xXISelectEventsReq);
123f7df2e56Smrg    swaps(&stuff->length);
1246747b715Smrg    REQUEST_AT_LEAST_SIZE(xXISelectEventsReq);
125f7df2e56Smrg    swapl(&stuff->win);
126f7df2e56Smrg    swaps(&stuff->num_masks);
1276747b715Smrg
1280b0d8713Smrg    len = stuff->length - bytes_to_int32(sizeof(xXISelectEventsReq));
129f7df2e56Smrg    evmask = (xXIEventMask *) &stuff[1];
130f7df2e56Smrg    for (i = 0; i < stuff->num_masks; i++) {
1310b0d8713Smrg        if (len < bytes_to_int32(sizeof(xXIEventMask)))
1320b0d8713Smrg            return BadLength;
1330b0d8713Smrg        len -= bytes_to_int32(sizeof(xXIEventMask));
134f7df2e56Smrg        swaps(&evmask->deviceid);
135f7df2e56Smrg        swaps(&evmask->mask_len);
1360b0d8713Smrg        if (len < evmask->mask_len)
1370b0d8713Smrg            return BadLength;
1380b0d8713Smrg        len -= evmask->mask_len;
139f7df2e56Smrg        evmask =
140f7df2e56Smrg            (xXIEventMask *) (((char *) &evmask[1]) + evmask->mask_len * 4);
1416747b715Smrg    }
1426747b715Smrg
1436747b715Smrg    return (ProcXISelectEvents(client));
1446747b715Smrg}
1456747b715Smrg
1466747b715Smrgint
1476747b715SmrgProcXISelectEvents(ClientPtr client)
1486747b715Smrg{
1496747b715Smrg    int rc, num_masks;
1506747b715Smrg    WindowPtr win;
1516747b715Smrg    DeviceIntPtr dev;
1526747b715Smrg    DeviceIntRec dummy;
1536747b715Smrg    xXIEventMask *evmask;
1546747b715Smrg    int *types = NULL;
1556747b715Smrg    int len;
1566747b715Smrg
1576747b715Smrg    REQUEST(xXISelectEventsReq);
1586747b715Smrg    REQUEST_AT_LEAST_SIZE(xXISelectEventsReq);
1596747b715Smrg
1606747b715Smrg    if (stuff->num_masks == 0)
1616747b715Smrg        return BadValue;
1626747b715Smrg
1636747b715Smrg    rc = dixLookupWindow(&win, stuff->win, client, DixReceiveAccess);
1646747b715Smrg    if (rc != Success)
1656747b715Smrg        return rc;
1666747b715Smrg
1676747b715Smrg    len = sz_xXISelectEventsReq;
1686747b715Smrg
1696747b715Smrg    /* check request validity */
170f7df2e56Smrg    evmask = (xXIEventMask *) &stuff[1];
1716747b715Smrg    num_masks = stuff->num_masks;
172f7df2e56Smrg    while (num_masks--) {
1736747b715Smrg        len += sizeof(xXIEventMask) + evmask->mask_len * 4;
1746747b715Smrg
1756747b715Smrg        if (bytes_to_int32(len) > stuff->length)
1766747b715Smrg            return BadLength;
1776747b715Smrg
1786747b715Smrg        if (evmask->deviceid != XIAllDevices &&
1796747b715Smrg            evmask->deviceid != XIAllMasterDevices)
1806747b715Smrg            rc = dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess);
1816747b715Smrg        else {
1826747b715Smrg            /* XXX: XACE here? */
1836747b715Smrg        }
1846747b715Smrg        if (rc != Success)
1856747b715Smrg            return rc;
1866747b715Smrg
1876747b715Smrg        /* hierarchy event mask is not allowed on devices */
188f7df2e56Smrg        if (evmask->deviceid != XIAllDevices && evmask->mask_len >= 1) {
189f7df2e56Smrg            unsigned char *bits = (unsigned char *) &evmask[1];
190f7df2e56Smrg
191f7df2e56Smrg            if (BitIsOn(bits, XI_HierarchyChanged)) {
1929ace9065Smrg                client->errorValue = XI_HierarchyChanged;
1936747b715Smrg                return BadValue;
1949ace9065Smrg            }
1956747b715Smrg        }
1966747b715Smrg
1976747b715Smrg        /* Raw events may only be selected on root windows */
198f7df2e56Smrg        if (win->parent && evmask->mask_len >= 1) {
199f7df2e56Smrg            unsigned char *bits = (unsigned char *) &evmask[1];
200f7df2e56Smrg
2016747b715Smrg            if (BitIsOn(bits, XI_RawKeyPress) ||
2026747b715Smrg                BitIsOn(bits, XI_RawKeyRelease) ||
2036747b715Smrg                BitIsOn(bits, XI_RawButtonPress) ||
2046747b715Smrg                BitIsOn(bits, XI_RawButtonRelease) ||
205f7df2e56Smrg                BitIsOn(bits, XI_RawMotion) ||
206f7df2e56Smrg                BitIsOn(bits, XI_RawTouchBegin) ||
207f7df2e56Smrg                BitIsOn(bits, XI_RawTouchUpdate) ||
208f7df2e56Smrg                BitIsOn(bits, XI_RawTouchEnd)) {
2099ace9065Smrg                client->errorValue = XI_RawKeyPress;
2106747b715Smrg                return BadValue;
2119ace9065Smrg            }
2126747b715Smrg        }
2136747b715Smrg
214f7df2e56Smrg        if (evmask->mask_len >= 1) {
215f7df2e56Smrg            unsigned char *bits = (unsigned char *) &evmask[1];
216f7df2e56Smrg
217f7df2e56Smrg            /* All three touch events must be selected at once */
218f7df2e56Smrg            if ((BitIsOn(bits, XI_TouchBegin) ||
219f7df2e56Smrg                 BitIsOn(bits, XI_TouchUpdate) ||
220f7df2e56Smrg                 BitIsOn(bits, XI_TouchOwnership) ||
221f7df2e56Smrg                 BitIsOn(bits, XI_TouchEnd)) &&
222f7df2e56Smrg                (!BitIsOn(bits, XI_TouchBegin) ||
223f7df2e56Smrg                 !BitIsOn(bits, XI_TouchUpdate) ||
224f7df2e56Smrg                 !BitIsOn(bits, XI_TouchEnd))) {
225f7df2e56Smrg                client->errorValue = XI_TouchBegin;
226f7df2e56Smrg                return BadValue;
227f7df2e56Smrg            }
228f7df2e56Smrg
2295a112b11Smrg            /* All three pinch gesture events must be selected at once */
2305a112b11Smrg            if ((BitIsOn(bits, XI_GesturePinchBegin) ||
2315a112b11Smrg                 BitIsOn(bits, XI_GesturePinchUpdate) ||
2325a112b11Smrg                 BitIsOn(bits, XI_GesturePinchEnd)) &&
2335a112b11Smrg                (!BitIsOn(bits, XI_GesturePinchBegin) ||
2345a112b11Smrg                 !BitIsOn(bits, XI_GesturePinchUpdate) ||
2355a112b11Smrg                 !BitIsOn(bits, XI_GesturePinchEnd))) {
2365a112b11Smrg                client->errorValue = XI_GesturePinchBegin;
2375a112b11Smrg                return BadValue;
2385a112b11Smrg            }
2395a112b11Smrg
2405a112b11Smrg            /* All three swipe gesture events must be selected at once. Note
2415a112b11Smrg               that the XI_GestureSwipeEnd is at index 32 which is on the next
2425a112b11Smrg               4-byte mask element */
2435a112b11Smrg            if (evmask->mask_len == 1 &&
2445a112b11Smrg                (BitIsOn(bits, XI_GestureSwipeBegin) ||
2455a112b11Smrg                 BitIsOn(bits, XI_GestureSwipeUpdate)))
2465a112b11Smrg            {
2475a112b11Smrg                client->errorValue = XI_GestureSwipeBegin;
2485a112b11Smrg                return BadValue;
2495a112b11Smrg            }
2505a112b11Smrg
2515a112b11Smrg            if (evmask->mask_len >= 2 &&
2525a112b11Smrg                (BitIsOn(bits, XI_GestureSwipeBegin) ||
2535a112b11Smrg                 BitIsOn(bits, XI_GestureSwipeUpdate) ||
2545a112b11Smrg                 BitIsOn(bits, XI_GestureSwipeEnd)) &&
2555a112b11Smrg                (!BitIsOn(bits, XI_GestureSwipeBegin) ||
2565a112b11Smrg                 !BitIsOn(bits, XI_GestureSwipeUpdate) ||
2575a112b11Smrg                 !BitIsOn(bits, XI_GestureSwipeEnd))) {
2585a112b11Smrg                client->errorValue = XI_GestureSwipeBegin;
2595a112b11Smrg                return BadValue;
2605a112b11Smrg            }
2615a112b11Smrg
2625a112b11Smrg            /* Only one client per window may select for touch or gesture events
2635a112b11Smrg             * on the same devices, including master devices.
264f7df2e56Smrg             * XXX: This breaks if a device goes from floating to attached. */
265f7df2e56Smrg            if (BitIsOn(bits, XI_TouchBegin)) {
266f7df2e56Smrg                rc = check_for_touch_selection_conflicts(client,
267f7df2e56Smrg                                                         win,
2685a112b11Smrg                                                         evmask->deviceid,
2695a112b11Smrg                                                         XI_TouchBegin);
2705a112b11Smrg                if (rc != Success)
2715a112b11Smrg                    return rc;
2725a112b11Smrg            }
2735a112b11Smrg            if (BitIsOn(bits, XI_GesturePinchBegin)) {
2745a112b11Smrg                rc = check_for_touch_selection_conflicts(client,
2755a112b11Smrg                                                         win,
2765a112b11Smrg                                                         evmask->deviceid,
2775a112b11Smrg                                                         XI_GesturePinchBegin);
2785a112b11Smrg                if (rc != Success)
2795a112b11Smrg                    return rc;
2805a112b11Smrg            }
2815a112b11Smrg            if (BitIsOn(bits, XI_GestureSwipeBegin)) {
2825a112b11Smrg                rc = check_for_touch_selection_conflicts(client,
2835a112b11Smrg                                                         win,
2845a112b11Smrg                                                         evmask->deviceid,
2855a112b11Smrg                                                         XI_GestureSwipeBegin);
286f7df2e56Smrg                if (rc != Success)
287f7df2e56Smrg                    return rc;
288f7df2e56Smrg            }
289f7df2e56Smrg        }
290f7df2e56Smrg
291f7df2e56Smrg        if (XICheckInvalidMaskBits(client, (unsigned char *) &evmask[1],
2926747b715Smrg                                   evmask->mask_len * 4) != Success)
2936747b715Smrg            return BadValue;
2946747b715Smrg
295f7df2e56Smrg        evmask =
296f7df2e56Smrg            (xXIEventMask *) (((unsigned char *) evmask) +
297f7df2e56Smrg                              evmask->mask_len * 4);
2986747b715Smrg        evmask++;
2996747b715Smrg    }
3006747b715Smrg
3016747b715Smrg    if (bytes_to_int32(len) != stuff->length)
3026747b715Smrg        return BadLength;
3036747b715Smrg
3046747b715Smrg    /* Set masks on window */
305f7df2e56Smrg    evmask = (xXIEventMask *) &stuff[1];
3066747b715Smrg    num_masks = stuff->num_masks;
307f7df2e56Smrg    while (num_masks--) {
3086747b715Smrg        if (evmask->deviceid == XIAllDevices ||
309f7df2e56Smrg            evmask->deviceid == XIAllMasterDevices) {
3106747b715Smrg            dummy.id = evmask->deviceid;
3116747b715Smrg            dev = &dummy;
312f7df2e56Smrg        }
313f7df2e56Smrg        else
3146747b715Smrg            dixLookupDevice(&dev, evmask->deviceid, client, DixUseAccess);
3156747b715Smrg        if (XISetEventMask(dev, win, client, evmask->mask_len * 4,
316f7df2e56Smrg                           (unsigned char *) &evmask[1]) != Success)
3176747b715Smrg            return BadAlloc;
318f7df2e56Smrg        evmask =
319f7df2e56Smrg            (xXIEventMask *) (((unsigned char *) evmask) +
320f7df2e56Smrg                              evmask->mask_len * 4);
3216747b715Smrg        evmask++;
3226747b715Smrg    }
3236747b715Smrg
3246747b715Smrg    RecalculateDeliverableEvents(win);
3256747b715Smrg
3266747b715Smrg    free(types);
3276747b715Smrg    return Success;
3286747b715Smrg}
3296747b715Smrg
3307e31ba66Smrgint _X_COLD
3316747b715SmrgSProcXIGetSelectedEvents(ClientPtr client)
3326747b715Smrg{
3336747b715Smrg    REQUEST(xXIGetSelectedEventsReq);
334f7df2e56Smrg    swaps(&stuff->length);
3356747b715Smrg    REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq);
336f7df2e56Smrg    swapl(&stuff->win);
3376747b715Smrg
3386747b715Smrg    return (ProcXIGetSelectedEvents(client));
3396747b715Smrg}
3406747b715Smrg
3416747b715Smrgint
3426747b715SmrgProcXIGetSelectedEvents(ClientPtr client)
3436747b715Smrg{
3446747b715Smrg    int rc, i;
3456747b715Smrg    WindowPtr win;
3466747b715Smrg    char *buffer = NULL;
3476747b715Smrg    xXIGetSelectedEventsReply reply;
3486747b715Smrg    OtherInputMasks *masks;
3496747b715Smrg    InputClientsPtr others = NULL;
3506747b715Smrg    xXIEventMask *evmask = NULL;
3516747b715Smrg    DeviceIntPtr dev;
352875c6e4fSmrg    uint32_t length;
3536747b715Smrg
3546747b715Smrg    REQUEST(xXIGetSelectedEventsReq);
3556747b715Smrg    REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq);
3566747b715Smrg
3576747b715Smrg    rc = dixLookupWindow(&win, stuff->win, client, DixGetAttrAccess);
3586747b715Smrg    if (rc != Success)
3596747b715Smrg        return rc;
3606747b715Smrg
361f7df2e56Smrg    reply = (xXIGetSelectedEventsReply) {
362f7df2e56Smrg        .repType = X_Reply,
363f7df2e56Smrg        .RepType = X_XIGetSelectedEvents,
364f7df2e56Smrg        .sequenceNumber = client->sequence,
365f7df2e56Smrg        .length = 0,
366f7df2e56Smrg        .num_masks = 0
367f7df2e56Smrg    };
3686747b715Smrg
3696747b715Smrg    masks = wOtherInputMasks(win);
370f7df2e56Smrg    if (masks) {
371f7df2e56Smrg        for (others = wOtherInputMasks(win)->inputClients; others;
372f7df2e56Smrg             others = others->next) {
373f7df2e56Smrg            if (SameClient(others, client)) {
3746747b715Smrg                break;
3756747b715Smrg            }
3766747b715Smrg        }
3776747b715Smrg    }
3786747b715Smrg
379f7df2e56Smrg    if (!others) {
3806747b715Smrg        WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply);
3816747b715Smrg        return Success;
3826747b715Smrg    }
3836747b715Smrg
384f7df2e56Smrg    buffer =
385f7df2e56Smrg        calloc(MAXDEVICES, sizeof(xXIEventMask) + pad_to_int32(XI2MASKSIZE));
3866747b715Smrg    if (!buffer)
3876747b715Smrg        return BadAlloc;
3886747b715Smrg
389f7df2e56Smrg    evmask = (xXIEventMask *) buffer;
390f7df2e56Smrg    for (i = 0; i < MAXDEVICES; i++) {
3916747b715Smrg        int j;
392f7df2e56Smrg        const unsigned char *devmask = xi2mask_get_one_mask(others->xi2mask, i);
3936747b715Smrg
394f7df2e56Smrg        if (i > 2) {
3956747b715Smrg            rc = dixLookupDevice(&dev, i, client, DixGetAttrAccess);
3966747b715Smrg            if (rc != Success)
3976747b715Smrg                continue;
3986747b715Smrg        }
3996747b715Smrg
400f7df2e56Smrg        for (j = xi2mask_mask_size(others->xi2mask) - 1; j >= 0; j--) {
401f7df2e56Smrg            if (devmask[j] != 0) {
402f7df2e56Smrg                int mask_len = (j + 4) / 4;     /* j is an index, hence + 4, not + 3 */
4036747b715Smrg
4046747b715Smrg                evmask->deviceid = i;
4056747b715Smrg                evmask->mask_len = mask_len;
4066747b715Smrg                reply.num_masks++;
407f7df2e56Smrg                reply.length += sizeof(xXIEventMask) / 4 + evmask->mask_len;
4086747b715Smrg
409f7df2e56Smrg                if (client->swapped) {
410f7df2e56Smrg                    swaps(&evmask->deviceid);
411f7df2e56Smrg                    swaps(&evmask->mask_len);
4126747b715Smrg                }
4136747b715Smrg
4146747b715Smrg                memcpy(&evmask[1], devmask, j + 1);
415f7df2e56Smrg                evmask = (xXIEventMask *) ((char *) evmask +
416f7df2e56Smrg                                           sizeof(xXIEventMask) + mask_len * 4);
4176747b715Smrg                break;
4186747b715Smrg            }
4196747b715Smrg        }
4206747b715Smrg    }
4216747b715Smrg
422875c6e4fSmrg    /* save the value before SRepXIGetSelectedEvents swaps it */
423875c6e4fSmrg    length = reply.length;
4246747b715Smrg    WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply);
4256747b715Smrg
4266747b715Smrg    if (reply.num_masks)
427875c6e4fSmrg        WriteToClient(client, length * 4, buffer);
4286747b715Smrg
4296747b715Smrg    free(buffer);
4306747b715Smrg    return Success;
4316747b715Smrg}
4326747b715Smrg
433f7df2e56Smrgvoid
434f7df2e56SmrgSRepXIGetSelectedEvents(ClientPtr client,
435f7df2e56Smrg                        int len, xXIGetSelectedEventsReply * rep)
4366747b715Smrg{
437f7df2e56Smrg    swaps(&rep->sequenceNumber);
438f7df2e56Smrg    swapl(&rep->length);
439f7df2e56Smrg    swaps(&rep->num_masks);
440f7df2e56Smrg    WriteToClient(client, len, rep);
4416747b715Smrg}
442