xiquerypointer.c revision 6747b715
1/*
2 * Copyright 2007-2008 Peter Hutterer
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Author: Peter Hutterer, University of South Australia, NICTA
24 */
25
26/***********************************************************************
27 *
28 * Request to query the pointer location of an extension input device.
29 *
30 */
31
32#ifdef HAVE_DIX_CONFIG_H
33#include <dix-config.h>
34#endif
35
36#include <X11/X.h>	/* for inputstr.h    */
37#include <X11/Xproto.h>	/* Request macro     */
38#include "inputstr.h"	/* DeviceIntPtr      */
39#include "windowstr.h"	/* window structure  */
40#include <X11/extensions/XI.h>
41#include <X11/extensions/XI2proto.h>
42#include "extnsionst.h"
43#include "exevents.h"
44#include "exglobals.h"
45#include "eventconvert.h"
46#include "scrnintstr.h"
47#include "xkbsrv.h"
48
49#ifdef PANORAMIX
50#include "panoramiXsrv.h"
51#endif
52
53#include "xiquerypointer.h"
54
55/***********************************************************************
56 *
57 * This procedure allows a client to query the pointer of a device.
58 *
59 */
60
61int
62SProcXIQueryPointer(ClientPtr client)
63{
64    char n;
65
66    REQUEST(xXIQueryPointerReq);
67    swaps(&stuff->length, n);
68    swaps(&stuff->deviceid, n);
69    swapl(&stuff->win, n);
70    return (ProcXIQueryPointer(client));
71}
72
73int
74ProcXIQueryPointer(ClientPtr client)
75{
76    int rc;
77    xXIQueryPointerReply rep;
78    DeviceIntPtr pDev, kbd;
79    WindowPtr pWin, t;
80    SpritePtr pSprite;
81    XkbStatePtr state;
82    char *buttons = NULL;
83    int buttons_size = 0; /* size of buttons array */
84
85    REQUEST(xXIQueryPointerReq);
86    REQUEST_SIZE_MATCH(xXIQueryPointerReq);
87
88    rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
89    if (rc != Success)
90    {
91        client->errorValue = stuff->deviceid;
92        return rc;
93    }
94
95    if (pDev->valuator == NULL || IsKeyboardDevice(pDev) ||
96        (!IsMaster(pDev) && pDev->u.master)) /* no attached devices */
97    {
98        client->errorValue = stuff->deviceid;
99        return BadDevice;
100    }
101
102    rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess);
103    if (rc != Success)
104    {
105        SendErrorToClient(client, IReqCode, X_XIQueryPointer,
106                stuff->win, rc);
107        return Success;
108    }
109
110    if (pDev->valuator->motionHintWindow)
111        MaybeStopHint(pDev, client);
112
113    if (IsMaster(pDev))
114        kbd = GetPairedDevice(pDev);
115    else
116        kbd = (pDev->key) ? pDev : NULL;
117
118    pSprite = pDev->spriteInfo->sprite;
119
120    memset(&rep, 0, sizeof(rep));
121    rep.repType = X_Reply;
122    rep.RepType = X_XIQueryPointer;
123    rep.length = 6;
124    rep.sequenceNumber = client->sequence;
125    rep.root = (GetCurrentRootWindow(pDev))->drawable.id;
126    rep.root_x = FP1616(pSprite->hot.x, 0);
127    rep.root_y = FP1616(pSprite->hot.y, 0);
128    rep.child = None;
129
130    if (kbd)
131    {
132        state = &kbd->key->xkbInfo->prev_state;
133        rep.mods.base_mods = state->base_mods;
134        rep.mods.latched_mods = state->latched_mods;
135        rep.mods.locked_mods = state->locked_mods;
136
137        rep.group.base_group = state->base_group;
138        rep.group.latched_group = state->latched_group;
139        rep.group.locked_group = state->locked_group;
140    }
141
142    if (pDev->button)
143    {
144        int i, down;
145        rep.buttons_len = bytes_to_int32(bits_to_bytes(pDev->button->numButtons));
146        rep.length += rep.buttons_len;
147        buttons_size = rep.buttons_len * 4;
148        buttons = calloc(1, buttons_size);
149        if (!buttons)
150            return BadAlloc;
151
152        down = pDev->button->buttonsDown;
153
154        for (i = 0; i < pDev->button->numButtons && down; i++)
155        {
156            if (BitIsOn(pDev->button->down, i))
157            {
158                SetBit(buttons, i);
159                down--;
160            }
161        }
162    } else
163        rep.buttons_len = 0;
164
165    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
166    {
167        rep.same_screen = xTrue;
168        rep.win_x = FP1616(pSprite->hot.x - pWin->drawable.x, 0);
169        rep.win_y = FP1616(pSprite->hot.y - pWin->drawable.y, 0);
170        for (t = pSprite->win; t; t = t->parent)
171            if (t->parent == pWin)
172            {
173                rep.child = t->drawable.id;
174                break;
175            }
176    } else
177    {
178        rep.same_screen = xFalse;
179        rep.win_x = 0;
180        rep.win_y = 0;
181    }
182
183#ifdef PANORAMIX
184    if(!noPanoramiXExtension) {
185        rep.root_x += FP1616(screenInfo.screens[0]->x, 0);
186        rep.root_y += FP1616(screenInfo.screens[0]->y, 0);
187        if (stuff->win == rep.root)
188        {
189            rep.win_x += FP1616(screenInfo.screens[0]->x, 0);
190            rep.win_y += FP1616(screenInfo.screens[0]->y, 0);
191        }
192    }
193#endif
194
195    WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep);
196    if (buttons)
197        WriteToClient(client, buttons_size, buttons);
198
199    free(buttons);
200
201    return Success;
202}
203
204/***********************************************************************
205 *
206 * This procedure writes the reply for the XIQueryPointer function,
207 * if the client and server have a different byte ordering.
208 *
209 */
210
211void
212SRepXIQueryPointer(ClientPtr client, int size,
213                   xXIQueryPointerReply * rep)
214{
215    char n;
216
217    swaps(&rep->sequenceNumber, n);
218    swapl(&rep->length, n);
219    swapl(&rep->root, n);
220    swapl(&rep->child, n);
221    swapl(&rep->root_x, n);
222    swapl(&rep->root_y, n);
223    swapl(&rep->win_x, n);
224    swapl(&rep->win_y, n);
225    swaps(&rep->buttons_len, n);
226
227    WriteToClient(client, size, (char *)rep);
228}
229
230