os: if inet_ntop() is available, use it for IPv4 addresses as well
[xserver.git] / Xi / xiquerypointer.c
blobfd362dd5413731fc23d963d09ebc98b72c9642ee
1 /*
2 * Copyright 2007-2008 Peter Hutterer
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:
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.
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.
23 * Author: Peter Hutterer, University of South Australia, NICTA
26 /***********************************************************************
28 * Request to query the pointer location of an extension input device.
32 #include <dix-config.h>
34 #include <X11/X.h> /* for inputstr.h */
35 #include <X11/Xproto.h> /* Request macro */
36 #include <X11/extensions/XI.h>
37 #include <X11/extensions/XI2proto.h>
39 #include "dix/dix_priv.h"
40 #include "dix/eventconvert.h"
41 #include "dix/exevents_priv.h"
42 #include "dix/input_priv.h"
44 #include "inputstr.h" /* DeviceIntPtr */
45 #include "windowstr.h" /* window structure */
46 #include "extnsionst.h"
47 #include "exglobals.h"
48 #include "scrnintstr.h"
49 #include "xkbsrv.h"
51 #ifdef PANORAMIX
52 #include "panoramiXsrv.h"
53 #endif
55 #include "inpututils.h"
56 #include "xiquerypointer.h"
58 /***********************************************************************
60 * This procedure allows a client to query the pointer of a device.
64 int _X_COLD
65 SProcXIQueryPointer(ClientPtr client)
67 REQUEST(xXIQueryPointerReq);
68 REQUEST_SIZE_MATCH(xXIQueryPointerReq);
70 swaps(&stuff->length);
71 swaps(&stuff->deviceid);
72 swapl(&stuff->win);
73 return (ProcXIQueryPointer(client));
76 int
77 ProcXIQueryPointer(ClientPtr client)
79 int rc;
80 xXIQueryPointerReply rep;
81 DeviceIntPtr pDev, kbd;
82 WindowPtr pWin, t;
83 SpritePtr pSprite;
84 XkbStatePtr state;
85 char *buttons = NULL;
86 int buttons_size = 0; /* size of buttons array */
87 XIClientPtr xi_client;
88 Bool have_xi22 = FALSE;
90 REQUEST(xXIQueryPointerReq);
91 REQUEST_SIZE_MATCH(xXIQueryPointerReq);
93 /* Check if client is compliant with XInput 2.2 or later. Earlier clients
94 * do not know about touches, so we must report emulated button presses. 2.2
95 * and later clients are aware of touches, so we don't include emulated
96 * button presses in the reply. */
97 xi_client = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
98 if (version_compare(xi_client->major_version,
99 xi_client->minor_version, 2, 2) >= 0)
100 have_xi22 = TRUE;
102 rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
103 if (rc != Success) {
104 client->errorValue = stuff->deviceid;
105 return rc;
108 if (pDev->valuator == NULL || IsKeyboardDevice(pDev) || (!IsMaster(pDev) && !IsFloating(pDev))) { /* no attached devices */
109 client->errorValue = stuff->deviceid;
110 return BadDevice;
113 rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess);
114 if (rc != Success) {
115 client->errorValue = stuff->win;
116 return rc;
119 if (pDev->valuator->motionHintWindow)
120 MaybeStopHint(pDev, client);
122 if (IsMaster(pDev))
123 kbd = GetMaster(pDev, MASTER_KEYBOARD);
124 else
125 kbd = (pDev->key) ? pDev : NULL;
127 pSprite = pDev->spriteInfo->sprite;
129 rep = (xXIQueryPointerReply) {
130 .repType = X_Reply,
131 .RepType = X_XIQueryPointer,
132 .sequenceNumber = client->sequence,
133 .length = 6,
134 .root = (GetCurrentRootWindow(pDev))->drawable.id,
135 .root_x = double_to_fp1616(pSprite->hot.x),
136 .root_y = double_to_fp1616(pSprite->hot.y),
137 .child = None
140 if (kbd) {
141 state = &kbd->key->xkbInfo->state;
142 rep.mods.base_mods = state->base_mods;
143 rep.mods.latched_mods = state->latched_mods;
144 rep.mods.locked_mods = state->locked_mods;
146 rep.group.base_group = state->base_group;
147 rep.group.latched_group = state->latched_group;
148 rep.group.locked_group = state->locked_group;
151 if (pDev->button) {
152 int i;
154 rep.buttons_len = bytes_to_int32(bits_to_bytes(256)); /* button map up to 255 */
155 rep.length += rep.buttons_len;
156 buttons = calloc(rep.buttons_len, 4);
157 if (!buttons)
158 return BadAlloc;
159 buttons_size = rep.buttons_len * 4;
161 for (i = 1; i < pDev->button->numButtons; i++)
162 if (BitIsOn(pDev->button->down, i))
163 SetBit(buttons, pDev->button->map[i]);
165 if (!have_xi22 && pDev->touch && pDev->touch->buttonsDown > 0)
166 SetBit(buttons, pDev->button->map[1]);
168 else
169 rep.buttons_len = 0;
171 if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
172 rep.same_screen = xTrue;
173 rep.win_x = double_to_fp1616(pSprite->hot.x - pWin->drawable.x);
174 rep.win_y = double_to_fp1616(pSprite->hot.y - pWin->drawable.y);
175 for (t = pSprite->win; t; t = t->parent)
176 if (t->parent == pWin) {
177 rep.child = t->drawable.id;
178 break;
181 else {
182 rep.same_screen = xFalse;
183 rep.win_x = 0;
184 rep.win_y = 0;
187 #ifdef PANORAMIX
188 if (!noPanoramiXExtension) {
189 rep.root_x += double_to_fp1616(screenInfo.screens[0]->x);
190 rep.root_y += double_to_fp1616(screenInfo.screens[0]->y);
191 if (stuff->win == rep.root) {
192 rep.win_x += double_to_fp1616(screenInfo.screens[0]->x);
193 rep.win_y += double_to_fp1616(screenInfo.screens[0]->y);
196 #endif
198 WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep);
199 if (buttons)
200 WriteToClient(client, buttons_size, buttons);
202 free(buttons);
204 return Success;
207 /***********************************************************************
209 * This procedure writes the reply for the XIQueryPointer function,
210 * if the client and server have a different byte ordering.
214 void
215 SRepXIQueryPointer(ClientPtr client, int size, xXIQueryPointerReply * rep)
217 swaps(&rep->sequenceNumber);
218 swapl(&rep->length);
219 swapl(&rep->root);
220 swapl(&rep->child);
221 swapl(&rep->root_x);
222 swapl(&rep->root_y);
223 swapl(&rep->win_x);
224 swapl(&rep->win_y);
225 swaps(&rep->buttons_len);
227 WriteToClient(client, size, rep);