xiquerypointer.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. * Request to query the pointer location of an extension input device.
  28. *
  29. */
  30. #ifdef HAVE_DIX_CONFIG_H
  31. #include <dix-config.h>
  32. #endif
  33. #include <X11/X.h> /* for inputstr.h */
  34. #include <X11/Xproto.h> /* Request macro */
  35. #include "inputstr.h" /* DeviceIntPtr */
  36. #include "windowstr.h" /* window structure */
  37. #include <X11/extensions/XI.h>
  38. #include <X11/extensions/XI2proto.h>
  39. #include "extnsionst.h"
  40. #include "exevents.h"
  41. #include "exglobals.h"
  42. #include "eventconvert.h"
  43. #include "scrnintstr.h"
  44. #include "xkbsrv.h"
  45. #ifdef PANORAMIX
  46. #include "panoramiXsrv.h"
  47. #endif
  48. #include "inpututils.h"
  49. #include "xiquerypointer.h"
  50. /***********************************************************************
  51. *
  52. * This procedure allows a client to query the pointer of a device.
  53. *
  54. */
  55. int
  56. SProcXIQueryPointer(ClientPtr client)
  57. {
  58. REQUEST(xXIQueryPointerReq);
  59. REQUEST_SIZE_MATCH(xXIQueryPointerReq);
  60. swaps(&stuff->length);
  61. swaps(&stuff->deviceid);
  62. swapl(&stuff->win);
  63. return (ProcXIQueryPointer(client));
  64. }
  65. int
  66. ProcXIQueryPointer(ClientPtr client)
  67. {
  68. int rc;
  69. xXIQueryPointerReply rep;
  70. DeviceIntPtr pDev, kbd;
  71. WindowPtr pWin, t;
  72. SpritePtr pSprite;
  73. XkbStatePtr state;
  74. char *buttons = NULL;
  75. int buttons_size = 0; /* size of buttons array */
  76. XIClientPtr xi_client;
  77. Bool have_xi22 = FALSE;
  78. REQUEST(xXIQueryPointerReq);
  79. REQUEST_SIZE_MATCH(xXIQueryPointerReq);
  80. /* Check if client is compliant with XInput 2.2 or later. Earlier clients
  81. * do not know about touches, so we must report emulated button presses. 2.2
  82. * and later clients are aware of touches, so we don't include emulated
  83. * button presses in the reply. */
  84. xi_client = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
  85. if (version_compare(xi_client->major_version,
  86. xi_client->minor_version, 2, 2) >= 0)
  87. have_xi22 = TRUE;
  88. rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
  89. if (rc != Success) {
  90. client->errorValue = stuff->deviceid;
  91. return rc;
  92. }
  93. if (pDev->valuator == NULL || IsKeyboardDevice(pDev) || (!IsMaster(pDev) && !IsFloating(pDev))) { /* no attached devices */
  94. client->errorValue = stuff->deviceid;
  95. return BadDevice;
  96. }
  97. rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess);
  98. if (rc != Success) {
  99. SendErrorToClient(client, IReqCode, X_XIQueryPointer, stuff->win, rc);
  100. return Success;
  101. }
  102. if (pDev->valuator->motionHintWindow)
  103. MaybeStopHint(pDev, client);
  104. if (IsMaster(pDev))
  105. kbd = GetMaster(pDev, MASTER_KEYBOARD);
  106. else
  107. kbd = (pDev->key) ? pDev : NULL;
  108. pSprite = pDev->spriteInfo->sprite;
  109. rep = (xXIQueryPointerReply) {
  110. .repType = X_Reply,
  111. .RepType = X_XIQueryPointer,
  112. .sequenceNumber = client->sequence,
  113. .length = 6,
  114. .root = (GetCurrentRootWindow(pDev))->drawable.id,
  115. .root_x = double_to_fp1616(pSprite->hot.x),
  116. .root_y = double_to_fp1616(pSprite->hot.y),
  117. .child = None
  118. };
  119. if (kbd) {
  120. state = &kbd->key->xkbInfo->state;
  121. rep.mods.base_mods = state->base_mods;
  122. rep.mods.latched_mods = state->latched_mods;
  123. rep.mods.locked_mods = state->locked_mods;
  124. rep.group.base_group = state->base_group;
  125. rep.group.latched_group = state->latched_group;
  126. rep.group.locked_group = state->locked_group;
  127. }
  128. if (pDev->button) {
  129. int i;
  130. rep.buttons_len =
  131. bytes_to_int32(bits_to_bytes(pDev->button->numButtons));
  132. rep.length += rep.buttons_len;
  133. buttons_size = rep.buttons_len * 4;
  134. buttons = calloc(1, buttons_size);
  135. if (!buttons)
  136. return BadAlloc;
  137. for (i = 1; i < pDev->button->numButtons; i++)
  138. if (BitIsOn(pDev->button->down, i))
  139. SetBit(buttons, pDev->button->map[i]);
  140. if (!have_xi22 && pDev->touch && pDev->touch->buttonsDown > 0)
  141. SetBit(buttons, pDev->button->map[1]);
  142. }
  143. else
  144. rep.buttons_len = 0;
  145. if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
  146. rep.same_screen = xTrue;
  147. rep.win_x = double_to_fp1616(pSprite->hot.x - pWin->drawable.x);
  148. rep.win_y = double_to_fp1616(pSprite->hot.y - pWin->drawable.y);
  149. for (t = pSprite->win; t; t = t->parent)
  150. if (t->parent == pWin) {
  151. rep.child = t->drawable.id;
  152. break;
  153. }
  154. }
  155. else {
  156. rep.same_screen = xFalse;
  157. rep.win_x = 0;
  158. rep.win_y = 0;
  159. }
  160. #ifdef PANORAMIX
  161. if (!noPanoramiXExtension) {
  162. rep.root_x += double_to_fp1616(screenInfo.screens[0]->x);
  163. rep.root_y += double_to_fp1616(screenInfo.screens[0]->y);
  164. if (stuff->win == rep.root) {
  165. rep.win_x += double_to_fp1616(screenInfo.screens[0]->x);
  166. rep.win_y += double_to_fp1616(screenInfo.screens[0]->y);
  167. }
  168. }
  169. #endif
  170. WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep);
  171. if (buttons)
  172. WriteToClient(client, buttons_size, buttons);
  173. free(buttons);
  174. return Success;
  175. }
  176. /***********************************************************************
  177. *
  178. * This procedure writes the reply for the XIQueryPointer function,
  179. * if the client and server have a different byte ordering.
  180. *
  181. */
  182. void
  183. SRepXIQueryPointer(ClientPtr client, int size, xXIQueryPointerReply * rep)
  184. {
  185. swaps(&rep->sequenceNumber);
  186. swapl(&rep->length);
  187. swapl(&rep->root);
  188. swapl(&rep->child);
  189. swapl(&rep->root_x);
  190. swapl(&rep->root_y);
  191. swapl(&rep->win_x);
  192. swapl(&rep->win_y);
  193. swaps(&rep->buttons_len);
  194. WriteToClient(client, size, rep);
  195. }