xiquerypointer.c revision 0b0d8713
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    REQUEST_SIZE_MATCH(xXIQueryPointerReq);
68
69    swaps(&stuff->length, n);
70    swaps(&stuff->deviceid, n);
71    swapl(&stuff->win, n);
72    return (ProcXIQueryPointer(client));
73}
74
75int
76ProcXIQueryPointer(ClientPtr client)
77{
78    int rc;
79    xXIQueryPointerReply rep;
80    DeviceIntPtr pDev, kbd;
81    WindowPtr pWin, t;
82    SpritePtr pSprite;
83    XkbStatePtr state;
84    char *buttons = NULL;
85    int buttons_size = 0; /* size of buttons array */
86
87    REQUEST(xXIQueryPointerReq);
88    REQUEST_SIZE_MATCH(xXIQueryPointerReq);
89
90    rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
91    if (rc != Success)
92    {
93        client->errorValue = stuff->deviceid;
94        return rc;
95    }
96
97    if (pDev->valuator == NULL || IsKeyboardDevice(pDev) ||
98        (!IsMaster(pDev) && pDev->u.master)) /* no attached devices */
99    {
100        client->errorValue = stuff->deviceid;
101        return BadDevice;
102    }
103
104    rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess);
105    if (rc != Success)
106    {
107        SendErrorToClient(client, IReqCode, X_XIQueryPointer,
108                stuff->win, rc);
109        return Success;
110    }
111
112    if (pDev->valuator->motionHintWindow)
113        MaybeStopHint(pDev, client);
114
115    if (IsMaster(pDev))
116        kbd = GetPairedDevice(pDev);
117    else
118        kbd = (pDev->key) ? pDev : NULL;
119
120    pSprite = pDev->spriteInfo->sprite;
121
122    memset(&rep, 0, sizeof(rep));
123    rep.repType = X_Reply;
124    rep.RepType = X_XIQueryPointer;
125    rep.length = 6;
126    rep.sequenceNumber = client->sequence;
127    rep.root = (GetCurrentRootWindow(pDev))->drawable.id;
128    rep.root_x = FP1616(pSprite->hot.x, 0);
129    rep.root_y = FP1616(pSprite->hot.y, 0);
130    rep.child = None;
131
132    if (kbd)
133    {
134        state = &kbd->key->xkbInfo->state;
135        rep.mods.base_mods = state->base_mods;
136        rep.mods.latched_mods = state->latched_mods;
137        rep.mods.locked_mods = state->locked_mods;
138
139        rep.group.base_group = state->base_group;
140        rep.group.latched_group = state->latched_group;
141        rep.group.locked_group = state->locked_group;
142    }
143
144    if (pDev->button)
145    {
146        int i, down;
147        rep.buttons_len = bytes_to_int32(bits_to_bytes(pDev->button->numButtons));
148        rep.length += rep.buttons_len;
149        buttons_size = rep.buttons_len * 4;
150        buttons = calloc(1, buttons_size);
151        if (!buttons)
152            return BadAlloc;
153
154        down = pDev->button->buttonsDown;
155
156        for (i = 0; i < pDev->button->numButtons && down; i++)
157        {
158            if (BitIsOn(pDev->button->down, i))
159            {
160                SetBit(buttons, i);
161                down--;
162            }
163        }
164    } else
165        rep.buttons_len = 0;
166
167    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
168    {
169        rep.same_screen = xTrue;
170        rep.win_x = FP1616(pSprite->hot.x - pWin->drawable.x, 0);
171        rep.win_y = FP1616(pSprite->hot.y - pWin->drawable.y, 0);
172        for (t = pSprite->win; t; t = t->parent)
173            if (t->parent == pWin)
174            {
175                rep.child = t->drawable.id;
176                break;
177            }
178    } else
179    {
180        rep.same_screen = xFalse;
181        rep.win_x = 0;
182        rep.win_y = 0;
183    }
184
185#ifdef PANORAMIX
186    if(!noPanoramiXExtension) {
187        rep.root_x += FP1616(screenInfo.screens[0]->x, 0);
188        rep.root_y += FP1616(screenInfo.screens[0]->y, 0);
189        if (stuff->win == rep.root)
190        {
191            rep.win_x += FP1616(screenInfo.screens[0]->x, 0);
192            rep.win_y += FP1616(screenInfo.screens[0]->y, 0);
193        }
194    }
195#endif
196
197    WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep);
198    if (buttons)
199        WriteToClient(client, buttons_size, buttons);
200
201    free(buttons);
202
203    return Success;
204}
205
206/***********************************************************************
207 *
208 * This procedure writes the reply for the XIQueryPointer function,
209 * if the client and server have a different byte ordering.
210 *
211 */
212
213void
214SRepXIQueryPointer(ClientPtr client, int size,
215                   xXIQueryPointerReply * rep)
216{
217    char n;
218
219    swaps(&rep->sequenceNumber, n);
220    swapl(&rep->length, n);
221    swapl(&rep->root, n);
222    swapl(&rep->child, n);
223    swapl(&rep->root_x, n);
224    swapl(&rep->root_y, n);
225    swapl(&rep->win_x, n);
226    swapl(&rep->win_y, n);
227    swaps(&rep->buttons_len, n);
228
229    WriteToClient(client, size, (char *)rep);
230}
231
232