Commit | Line | Data |
---|---|---|
a09e091a JB |
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 "inpututils.h" | |
54 | #include "xiquerypointer.h" | |
55 | ||
56 | /*********************************************************************** | |
57 | * | |
58 | * This procedure allows a client to query the pointer of a device. | |
59 | * | |
60 | */ | |
61 | ||
62 | int | |
63 | SProcXIQueryPointer(ClientPtr client) | |
64 | { | |
65 | REQUEST(xXIQueryPointerReq); | |
66 | swaps(&stuff->length); | |
67 | swaps(&stuff->deviceid); | |
68 | swapl(&stuff->win); | |
69 | return (ProcXIQueryPointer(client)); | |
70 | } | |
71 | ||
72 | int | |
73 | ProcXIQueryPointer(ClientPtr client) | |
74 | { | |
75 | int rc; | |
76 | xXIQueryPointerReply rep; | |
77 | DeviceIntPtr pDev, kbd; | |
78 | WindowPtr pWin, t; | |
79 | SpritePtr pSprite; | |
80 | XkbStatePtr state; | |
81 | char *buttons = NULL; | |
82 | int buttons_size = 0; /* size of buttons array */ | |
83 | XIClientPtr xi_client; | |
84 | Bool have_xi22 = FALSE; | |
85 | ||
86 | REQUEST(xXIQueryPointerReq); | |
87 | REQUEST_SIZE_MATCH(xXIQueryPointerReq); | |
88 | ||
89 | /* Check if client is compliant with XInput 2.2 or later. Earlier clients | |
90 | * do not know about touches, so we must report emulated button presses. 2.2 | |
91 | * and later clients are aware of touches, so we don't include emulated | |
92 | * button presses in the reply. */ | |
93 | xi_client = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); | |
94 | if (version_compare(xi_client->major_version, | |
95 | xi_client->minor_version, 2, 2) >= 0) | |
96 | have_xi22 = TRUE; | |
97 | ||
98 | rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess); | |
99 | if (rc != Success) { | |
100 | client->errorValue = stuff->deviceid; | |
101 | return rc; | |
102 | } | |
103 | ||
104 | if (pDev->valuator == NULL || IsKeyboardDevice(pDev) || (!IsMaster(pDev) && !IsFloating(pDev))) { /* no attached devices */ | |
105 | client->errorValue = stuff->deviceid; | |
106 | return BadDevice; | |
107 | } | |
108 | ||
109 | rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess); | |
110 | if (rc != Success) { | |
111 | SendErrorToClient(client, IReqCode, X_XIQueryPointer, stuff->win, rc); | |
112 | return Success; | |
113 | } | |
114 | ||
115 | if (pDev->valuator->motionHintWindow) | |
116 | MaybeStopHint(pDev, client); | |
117 | ||
118 | if (IsMaster(pDev)) | |
119 | kbd = GetMaster(pDev, MASTER_KEYBOARD); | |
120 | else | |
121 | kbd = (pDev->key) ? pDev : NULL; | |
122 | ||
123 | pSprite = pDev->spriteInfo->sprite; | |
124 | ||
125 | rep = (xXIQueryPointerReply) { | |
126 | .repType = X_Reply, | |
127 | .RepType = X_XIQueryPointer, | |
128 | .sequenceNumber = client->sequence, | |
129 | .length = 6, | |
130 | .root = (GetCurrentRootWindow(pDev))->drawable.id, | |
131 | .root_x = double_to_fp1616(pSprite->hot.x), | |
132 | .root_y = double_to_fp1616(pSprite->hot.y), | |
133 | .child = None | |
134 | }; | |
135 | ||
136 | if (kbd) { | |
137 | state = &kbd->key->xkbInfo->state; | |
138 | rep.mods.base_mods = state->base_mods; | |
139 | rep.mods.latched_mods = state->latched_mods; | |
140 | rep.mods.locked_mods = state->locked_mods; | |
141 | ||
142 | rep.group.base_group = state->base_group; | |
143 | rep.group.latched_group = state->latched_group; | |
144 | rep.group.locked_group = state->locked_group; | |
145 | } | |
146 | ||
147 | if (pDev->button) { | |
148 | int i; | |
149 | ||
150 | rep.buttons_len = | |
151 | bytes_to_int32(bits_to_bytes(pDev->button->numButtons)); | |
152 | rep.length += rep.buttons_len; | |
153 | buttons_size = rep.buttons_len * 4; | |
154 | buttons = calloc(1, buttons_size); | |
155 | if (!buttons) | |
156 | return BadAlloc; | |
157 | ||
158 | for (i = 1; i < pDev->button->numButtons; i++) | |
159 | if (BitIsOn(pDev->button->down, i)) | |
160 | SetBit(buttons, pDev->button->map[i]); | |
161 | ||
162 | if (!have_xi22 && pDev->touch && pDev->touch->buttonsDown > 0) | |
163 | SetBit(buttons, pDev->button->map[1]); | |
164 | } | |
165 | else | |
166 | rep.buttons_len = 0; | |
167 | ||
168 | if (pSprite->hot.pScreen == pWin->drawable.pScreen) { | |
169 | rep.same_screen = xTrue; | |
170 | rep.win_x = double_to_fp1616(pSprite->hot.x - pWin->drawable.x); | |
171 | rep.win_y = double_to_fp1616(pSprite->hot.y - pWin->drawable.y); | |
172 | for (t = pSprite->win; t; t = t->parent) | |
173 | if (t->parent == pWin) { | |
174 | rep.child = t->drawable.id; | |
175 | break; | |
176 | } | |
177 | } | |
178 | else { | |
179 | rep.same_screen = xFalse; | |
180 | rep.win_x = 0; | |
181 | rep.win_y = 0; | |
182 | } | |
183 | ||
184 | #ifdef PANORAMIX | |
185 | if (!noPanoramiXExtension) { | |
186 | rep.root_x += double_to_fp1616(screenInfo.screens[0]->x); | |
187 | rep.root_y += double_to_fp1616(screenInfo.screens[0]->y); | |
188 | if (stuff->win == rep.root) { | |
189 | rep.win_x += double_to_fp1616(screenInfo.screens[0]->x); | |
190 | rep.win_y += double_to_fp1616(screenInfo.screens[0]->y); | |
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 | ||
211 | void | |
212 | SRepXIQueryPointer(ClientPtr client, int size, xXIQueryPointerReply * rep) | |
213 | { | |
214 | swaps(&rep->sequenceNumber); | |
215 | swapl(&rep->length); | |
216 | swapl(&rep->root); | |
217 | swapl(&rep->child); | |
218 | swapl(&rep->root_x); | |
219 | swapl(&rep->root_y); | |
220 | swapl(&rep->win_x); | |
221 | swapl(&rep->win_y); | |
222 | swaps(&rep->buttons_len); | |
223 | ||
224 | WriteToClient(client, size, rep); | |
225 | } |