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 #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"
52 #include "panoramiXsrv.h"
55 #include "inpututils.h"
56 #include "xiquerypointer.h"
58 /***********************************************************************
60 * This procedure allows a client to query the pointer of a device.
65 SProcXIQueryPointer(ClientPtr client
)
67 REQUEST(xXIQueryPointerReq
);
68 REQUEST_SIZE_MATCH(xXIQueryPointerReq
);
70 swaps(&stuff
->length
);
71 swaps(&stuff
->deviceid
);
73 return (ProcXIQueryPointer(client
));
77 ProcXIQueryPointer(ClientPtr client
)
80 xXIQueryPointerReply rep
;
81 DeviceIntPtr pDev
, kbd
;
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)
102 rc
= dixLookupDevice(&pDev
, stuff
->deviceid
, client
, DixReadAccess
);
104 client
->errorValue
= stuff
->deviceid
;
108 if (pDev
->valuator
== NULL
|| IsKeyboardDevice(pDev
) || (!IsMaster(pDev
) && !IsFloating(pDev
))) { /* no attached devices */
109 client
->errorValue
= stuff
->deviceid
;
113 rc
= dixLookupWindow(&pWin
, stuff
->win
, client
, DixGetAttrAccess
);
115 client
->errorValue
= stuff
->win
;
119 if (pDev
->valuator
->motionHintWindow
)
120 MaybeStopHint(pDev
, client
);
123 kbd
= GetMaster(pDev
, MASTER_KEYBOARD
);
125 kbd
= (pDev
->key
) ? pDev
: NULL
;
127 pSprite
= pDev
->spriteInfo
->sprite
;
129 rep
= (xXIQueryPointerReply
) {
131 .RepType
= X_XIQueryPointer
,
132 .sequenceNumber
= client
->sequence
,
134 .root
= (GetCurrentRootWindow(pDev
))->drawable
.id
,
135 .root_x
= double_to_fp1616(pSprite
->hot
.x
),
136 .root_y
= double_to_fp1616(pSprite
->hot
.y
),
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
;
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);
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]);
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
;
182 rep
.same_screen
= xFalse
;
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
);
198 WriteReplyToClient(client
, sizeof(xXIQueryPointerReply
), &rep
);
200 WriteToClient(client
, buttons_size
, buttons
);
207 /***********************************************************************
209 * This procedure writes the reply for the XIQueryPointer function,
210 * if the client and server have a different byte ordering.
215 SRepXIQueryPointer(ClientPtr client
, int size
, xXIQueryPointerReply
* rep
)
217 swaps(&rep
->sequenceNumber
);
225 swaps(&rep
->buttons_len
);
227 WriteToClient(client
, size
, rep
);