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
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 #ifdef HAVE_DIX_CONFIG_H
33 #include <dix-config.h>
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"
44 #include "exglobals.h"
45 #include "eventconvert.h"
46 #include "scrnintstr.h"
50 #include "panoramiXsrv.h"
53 #include "inpututils.h"
54 #include "xiquerypointer.h"
56 /***********************************************************************
58 * This procedure allows a client to query the pointer of a device.
63 SProcXIQueryPointer(ClientPtr client
)
65 REQUEST(xXIQueryPointerReq
);
66 swaps(&stuff
->length
);
67 swaps(&stuff
->deviceid
);
69 return (ProcXIQueryPointer(client
));
73 ProcXIQueryPointer(ClientPtr client
)
76 xXIQueryPointerReply rep
;
77 DeviceIntPtr pDev
, kbd
;
82 int buttons_size
= 0; /* size of buttons array */
83 XIClientPtr xi_client
;
84 Bool have_xi22
= FALSE
;
86 REQUEST(xXIQueryPointerReq
);
87 REQUEST_SIZE_MATCH(xXIQueryPointerReq
);
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)
98 rc
= dixLookupDevice(&pDev
, stuff
->deviceid
, client
, DixReadAccess
);
100 client
->errorValue
= stuff
->deviceid
;
104 if (pDev
->valuator
== NULL
|| IsKeyboardDevice(pDev
) || (!IsMaster(pDev
) && !IsFloating(pDev
))) { /* no attached devices */
105 client
->errorValue
= stuff
->deviceid
;
109 rc
= dixLookupWindow(&pWin
, stuff
->win
, client
, DixGetAttrAccess
);
111 SendErrorToClient(client
, IReqCode
, X_XIQueryPointer
, stuff
->win
, rc
);
115 if (pDev
->valuator
->motionHintWindow
)
116 MaybeStopHint(pDev
, client
);
119 kbd
= GetMaster(pDev
, MASTER_KEYBOARD
);
121 kbd
= (pDev
->key
) ? pDev
: NULL
;
123 pSprite
= pDev
->spriteInfo
->sprite
;
125 rep
= (xXIQueryPointerReply
) {
127 .RepType
= X_XIQueryPointer
,
128 .sequenceNumber
= client
->sequence
,
130 .root
= (GetCurrentRootWindow(pDev
))->drawable
.id
,
131 .root_x
= double_to_fp1616(pSprite
->hot
.x
),
132 .root_y
= double_to_fp1616(pSprite
->hot
.y
),
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
;
142 rep
.group
.base_group
= state
->base_group
;
143 rep
.group
.latched_group
= state
->latched_group
;
144 rep
.group
.locked_group
= state
->locked_group
;
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
);
158 for (i
= 1; i
< pDev
->button
->numButtons
; i
++)
159 if (BitIsOn(pDev
->button
->down
, i
))
160 SetBit(buttons
, pDev
->button
->map
[i
]);
162 if (!have_xi22
&& pDev
->touch
&& pDev
->touch
->buttonsDown
> 0)
163 SetBit(buttons
, pDev
->button
->map
[1]);
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
;
179 rep
.same_screen
= xFalse
;
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
);
195 WriteReplyToClient(client
, sizeof(xXIQueryPointerReply
), &rep
);
197 WriteToClient(client
, buttons_size
, buttons
);
204 /***********************************************************************
206 * This procedure writes the reply for the XIQueryPointer function,
207 * if the client and server have a different byte ordering.
212 SRepXIQueryPointer(ClientPtr client
, int size
, xXIQueryPointerReply
* rep
)
214 swaps(&rep
->sequenceNumber
);
222 swaps(&rep
->buttons_len
);
224 WriteToClient(client
, size
, rep
);