135c4bbdfSmrg/**
235c4bbdfSmrg * Copyright © 2011 Red Hat, Inc.
335c4bbdfSmrg *
435c4bbdfSmrg *  Permission is hereby granted, free of charge, to any person obtaining a
535c4bbdfSmrg *  copy of this software and associated documentation files (the "Software"),
635c4bbdfSmrg *  to deal in the Software without restriction, including without limitation
735c4bbdfSmrg *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
835c4bbdfSmrg *  and/or sell copies of the Software, and to permit persons to whom the
935c4bbdfSmrg *  Software is furnished to do so, subject to the following conditions:
1035c4bbdfSmrg *
1135c4bbdfSmrg *  The above copyright notice and this permission notice (including the next
1235c4bbdfSmrg *  paragraph) shall be included in all copies or substantial portions of the
1335c4bbdfSmrg *  Software.
1435c4bbdfSmrg *
1535c4bbdfSmrg *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1635c4bbdfSmrg *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1735c4bbdfSmrg *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1835c4bbdfSmrg *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1935c4bbdfSmrg *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2035c4bbdfSmrg *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2135c4bbdfSmrg *  DEALINGS IN THE SOFTWARE.
2235c4bbdfSmrg */
2335c4bbdfSmrg
24ed6184dfSmrg/* Test relies on assert() */
25ed6184dfSmrg#undef NDEBUG
26ed6184dfSmrg
2735c4bbdfSmrg#ifdef HAVE_DIX_CONFIG_H
2835c4bbdfSmrg#include <dix-config.h>
2935c4bbdfSmrg#endif
3035c4bbdfSmrg
3135c4bbdfSmrg/*
3235c4bbdfSmrg * Protocol testing for XIPassiveGrab request.
3335c4bbdfSmrg */
3435c4bbdfSmrg#include <stdint.h>
3535c4bbdfSmrg#include <X11/X.h>
3635c4bbdfSmrg#include <X11/Xproto.h>
3735c4bbdfSmrg#include <X11/extensions/XI2proto.h>
3835c4bbdfSmrg#include "inputstr.h"
3935c4bbdfSmrg#include "windowstr.h"
4035c4bbdfSmrg#include "scrnintstr.h"
4135c4bbdfSmrg#include "xipassivegrab.h"
4235c4bbdfSmrg#include "exevents.h"
4335c4bbdfSmrg#include "exglobals.h"
4435c4bbdfSmrg
4535c4bbdfSmrg#include "protocol-common.h"
4635c4bbdfSmrg
475a7dfde8Smrgextern ClientRec client_window;
4835c4bbdfSmrgstatic ClientRec client_request;
4935c4bbdfSmrg
5035c4bbdfSmrg#define N_MODS 7
5135c4bbdfSmrgstatic uint32_t modifiers[N_MODS] = { 1, 2, 3, 4, 5, 6, 7 };
5235c4bbdfSmrg
531b5d61b8Smrgstatic struct test_data {
5435c4bbdfSmrg    int num_modifiers;
5535c4bbdfSmrg} testdata;
5635c4bbdfSmrg
5735c4bbdfSmrgint __wrap_GrabButton(ClientPtr client, DeviceIntPtr dev,
5835c4bbdfSmrg                      DeviceIntPtr modifier_device, int button,
5935c4bbdfSmrg                      GrabParameters *param, enum InputLevel grabtype,
6035c4bbdfSmrg                      GrabMask *mask);
611b5d61b8Smrgint __real_GrabButton(ClientPtr client, DeviceIntPtr dev,
621b5d61b8Smrg                      DeviceIntPtr modifier_device, int button,
631b5d61b8Smrg                      GrabParameters *param, enum InputLevel grabtype,
641b5d61b8Smrg                      GrabMask *mask);
6535c4bbdfSmrgstatic void reply_XIPassiveGrabDevice_data(ClientPtr client, int len,
6635c4bbdfSmrg                                           char *data, void *closure);
6735c4bbdfSmrg
6835c4bbdfSmrgint
6935c4bbdfSmrg__wrap_GrabButton(ClientPtr client, DeviceIntPtr dev,
7035c4bbdfSmrg                  DeviceIntPtr modifier_device, int button,
7135c4bbdfSmrg                  GrabParameters *param, enum InputLevel grabtype,
7235c4bbdfSmrg                  GrabMask *mask)
7335c4bbdfSmrg{
741b5d61b8Smrg    if (!enable_GrabButton_wrap)
751b5d61b8Smrg        __real_GrabButton(client, dev, modifier_device, button, param, grabtype, mask);
761b5d61b8Smrg
7735c4bbdfSmrg    /* Fail every odd modifier */
7835c4bbdfSmrg    if (param->modifiers % 2)
7935c4bbdfSmrg        return BadAccess;
8035c4bbdfSmrg
8135c4bbdfSmrg    return Success;
8235c4bbdfSmrg}
8335c4bbdfSmrg
8435c4bbdfSmrgstatic void
8535c4bbdfSmrgreply_XIPassiveGrabDevice(ClientPtr client, int len, char *data, void *closure)
8635c4bbdfSmrg{
8735c4bbdfSmrg    xXIPassiveGrabDeviceReply *rep = (xXIPassiveGrabDeviceReply *) data;
8835c4bbdfSmrg
8935c4bbdfSmrg    if (client->swapped) {
9035c4bbdfSmrg        swaps(&rep->sequenceNumber);
9135c4bbdfSmrg        swapl(&rep->length);
9235c4bbdfSmrg        swaps(&rep->num_modifiers);
9335c4bbdfSmrg
9435c4bbdfSmrg        testdata.num_modifiers = rep->num_modifiers;
9535c4bbdfSmrg    }
9635c4bbdfSmrg
9735c4bbdfSmrg    reply_check_defaults(rep, len, XIPassiveGrabDevice);
9835c4bbdfSmrg
9935c4bbdfSmrg    /* ProcXIPassiveGrabDevice sends the data in two batches, let the second
10035c4bbdfSmrg     * handler handle the modifier data */
10135c4bbdfSmrg    if (rep->num_modifiers > 0)
10235c4bbdfSmrg        reply_handler = reply_XIPassiveGrabDevice_data;
10335c4bbdfSmrg}
10435c4bbdfSmrg
10535c4bbdfSmrgstatic void
10635c4bbdfSmrgreply_XIPassiveGrabDevice_data(ClientPtr client, int len, char *data,
10735c4bbdfSmrg                               void *closure)
10835c4bbdfSmrg{
10935c4bbdfSmrg    int i;
11035c4bbdfSmrg
11135c4bbdfSmrg    xXIGrabModifierInfo *mods = (xXIGrabModifierInfo *) data;
11235c4bbdfSmrg
11335c4bbdfSmrg    for (i = 0; i < testdata.num_modifiers; i++, mods++) {
11435c4bbdfSmrg        if (client->swapped)
11535c4bbdfSmrg            swapl(&mods->modifiers);
11635c4bbdfSmrg
11735c4bbdfSmrg        /* 1 - 7 is the range we use for the global modifiers array
11835c4bbdfSmrg         * above */
11935c4bbdfSmrg        assert(mods->modifiers > 0);
12035c4bbdfSmrg        assert(mods->modifiers <= 7);
12135c4bbdfSmrg        assert(mods->modifiers % 2 == 1);       /* because we fail odd ones */
12235c4bbdfSmrg        assert(mods->status != Success);
12335c4bbdfSmrg        assert(mods->pad0 == 0);
12435c4bbdfSmrg        assert(mods->pad1 == 0);
12535c4bbdfSmrg    }
12635c4bbdfSmrg
12735c4bbdfSmrg    reply_handler = reply_XIPassiveGrabDevice;
12835c4bbdfSmrg}
12935c4bbdfSmrg
13035c4bbdfSmrgstatic void
13135c4bbdfSmrgrequest_XIPassiveGrabDevice(ClientPtr client, xXIPassiveGrabDeviceReq * req,
13235c4bbdfSmrg                            int error, int errval)
13335c4bbdfSmrg{
13435c4bbdfSmrg    int rc;
13535c4bbdfSmrg    int local_modifiers;
13635c4bbdfSmrg    int mask_len;
13735c4bbdfSmrg
13835c4bbdfSmrg    client_request.req_len = req->length;
13935c4bbdfSmrg    rc = ProcXIPassiveGrabDevice(&client_request);
14035c4bbdfSmrg    assert(rc == error);
14135c4bbdfSmrg
14235c4bbdfSmrg    if (rc != Success)
14335c4bbdfSmrg        assert(client_request.errorValue == errval);
14435c4bbdfSmrg
14535c4bbdfSmrg    client_request.swapped = TRUE;
14635c4bbdfSmrg    swaps(&req->length);
14735c4bbdfSmrg    swapl(&req->time);
14835c4bbdfSmrg    swapl(&req->grab_window);
14935c4bbdfSmrg    swapl(&req->cursor);
15035c4bbdfSmrg    swapl(&req->detail);
15135c4bbdfSmrg    swaps(&req->deviceid);
15235c4bbdfSmrg    local_modifiers = req->num_modifiers;
15335c4bbdfSmrg    swaps(&req->num_modifiers);
15435c4bbdfSmrg    mask_len = req->mask_len;
15535c4bbdfSmrg    swaps(&req->mask_len);
15635c4bbdfSmrg
15735c4bbdfSmrg    while (local_modifiers--) {
15835c4bbdfSmrg        CARD32 *mod = (CARD32 *) (req + 1) + mask_len + local_modifiers;
15935c4bbdfSmrg
16035c4bbdfSmrg        swapl(mod);
16135c4bbdfSmrg    }
16235c4bbdfSmrg
16335c4bbdfSmrg    rc = SProcXIPassiveGrabDevice(&client_request);
16435c4bbdfSmrg    assert(rc == error);
16535c4bbdfSmrg
16635c4bbdfSmrg    if (rc != Success)
16735c4bbdfSmrg        assert(client_request.errorValue == errval);
16835c4bbdfSmrg}
16935c4bbdfSmrg
17035c4bbdfSmrgstatic unsigned char *data[4096];       /* the request buffer */
17135c4bbdfSmrgstatic void
17235c4bbdfSmrgtest_XIPassiveGrabDevice(void)
17335c4bbdfSmrg{
17435c4bbdfSmrg    int i;
17535c4bbdfSmrg    xXIPassiveGrabDeviceReq *request = (xXIPassiveGrabDeviceReq *) data;
17635c4bbdfSmrg    unsigned char *mask;
17735c4bbdfSmrg
17835c4bbdfSmrg    request_init(request, XIPassiveGrabDevice);
17935c4bbdfSmrg
18035c4bbdfSmrg    request->grab_window = CLIENT_WINDOW_ID;
18135c4bbdfSmrg
18235c4bbdfSmrg    reply_handler = reply_XIPassiveGrabDevice;
18335c4bbdfSmrg    client_request = init_client(request->length, request);
18435c4bbdfSmrg
18535c4bbdfSmrg    printf("Testing invalid device\n");
18635c4bbdfSmrg    request->deviceid = 12;
18735c4bbdfSmrg    request_XIPassiveGrabDevice(&client_request, request, BadDevice,
18835c4bbdfSmrg                                request->deviceid);
18935c4bbdfSmrg
19035c4bbdfSmrg    printf("Testing invalid length\n");
19135c4bbdfSmrg    request->length -= 2;
19235c4bbdfSmrg    request_XIPassiveGrabDevice(&client_request, request, BadLength,
19335c4bbdfSmrg                                client_request.errorValue);
19435c4bbdfSmrg    /* re-init request since swapped length test leaves some values swapped */
19535c4bbdfSmrg    request_init(request, XIPassiveGrabDevice);
19635c4bbdfSmrg    request->grab_window = CLIENT_WINDOW_ID;
19735c4bbdfSmrg    request->deviceid = XIAllMasterDevices;
19835c4bbdfSmrg
19935c4bbdfSmrg    printf("Testing invalid grab types\n");
200ed6184dfSmrg    for (i = XIGrabtypeGestureSwipeBegin + 1; i < 0xFF; i++) {
20135c4bbdfSmrg        request->grab_type = i;
20235c4bbdfSmrg        request_XIPassiveGrabDevice(&client_request, request, BadValue,
20335c4bbdfSmrg                                    request->grab_type);
20435c4bbdfSmrg    }
20535c4bbdfSmrg
20635c4bbdfSmrg    printf("Testing invalid grab type + detail combinations\n");
20735c4bbdfSmrg    request->grab_type = XIGrabtypeEnter;
20835c4bbdfSmrg    request->detail = 1;
20935c4bbdfSmrg    request_XIPassiveGrabDevice(&client_request, request, BadValue,
21035c4bbdfSmrg                                request->detail);
21135c4bbdfSmrg
21235c4bbdfSmrg    request->grab_type = XIGrabtypeFocusIn;
21335c4bbdfSmrg    request_XIPassiveGrabDevice(&client_request, request, BadValue,
21435c4bbdfSmrg                                request->detail);
21535c4bbdfSmrg
21635c4bbdfSmrg    request->detail = 0;
21735c4bbdfSmrg
21835c4bbdfSmrg    printf("Testing invalid masks\n");
21935c4bbdfSmrg    mask = (unsigned char *) &request[1];
22035c4bbdfSmrg
22135c4bbdfSmrg    request->mask_len = bytes_to_int32(XI2LASTEVENT + 1);
22235c4bbdfSmrg    request->length += request->mask_len;
22335c4bbdfSmrg    SetBit(mask, XI2LASTEVENT + 1);
22435c4bbdfSmrg    request_XIPassiveGrabDevice(&client_request, request, BadValue,
22535c4bbdfSmrg                                XI2LASTEVENT + 1);
22635c4bbdfSmrg
22735c4bbdfSmrg    ClearBit(mask, XI2LASTEVENT + 1);
22835c4bbdfSmrg
22935c4bbdfSmrg    /* tested all special cases now, test a few valid cases */
23035c4bbdfSmrg
23135c4bbdfSmrg    /* no modifiers */
23235c4bbdfSmrg    request->deviceid = XIAllDevices;
23335c4bbdfSmrg    request->grab_type = XIGrabtypeButton;
23435c4bbdfSmrg    request->detail = XIAnyButton;
23535c4bbdfSmrg    request_XIPassiveGrabDevice(&client_request, request, Success, 0);
23635c4bbdfSmrg
23735c4bbdfSmrg    /* Set a few random masks to make sure we handle modifiers correctly */
23835c4bbdfSmrg    SetBit(mask, XI_ButtonPress);
23935c4bbdfSmrg    SetBit(mask, XI_KeyPress);
24035c4bbdfSmrg    SetBit(mask, XI_Enter);
24135c4bbdfSmrg
24235c4bbdfSmrg    /* some modifiers */
24335c4bbdfSmrg    request->num_modifiers = N_MODS;
24435c4bbdfSmrg    request->length += N_MODS;
24535c4bbdfSmrg    memcpy((uint32_t *) (request + 1) + request->mask_len, modifiers,
24635c4bbdfSmrg           sizeof(modifiers));
24735c4bbdfSmrg    request_XIPassiveGrabDevice(&client_request, request, Success, 0);
24835c4bbdfSmrg}
24935c4bbdfSmrg
25035c4bbdfSmrgint
2511b5d61b8Smrgprotocol_xipassivegrabdevice_test(void)
25235c4bbdfSmrg{
25335c4bbdfSmrg    init_simple();
25435c4bbdfSmrg
25535c4bbdfSmrg    test_XIPassiveGrabDevice();
25635c4bbdfSmrg
25735c4bbdfSmrg    return 0;
25835c4bbdfSmrg}
259