xipassivegrab.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /*
  2. * Copyright © 2009 Red Hat, Inc.
  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
  24. */
  25. /***********************************************************************
  26. *
  27. * Request to grab or ungrab input device.
  28. *
  29. */
  30. #ifdef HAVE_DIX_CONFIG_H
  31. #include <dix-config.h>
  32. #endif
  33. #include "inputstr.h" /* DeviceIntPtr */
  34. #include "windowstr.h" /* window structure */
  35. #include <X11/extensions/XI2.h>
  36. #include <X11/extensions/XI2proto.h>
  37. #include "swaprep.h"
  38. #include "exglobals.h" /* BadDevice */
  39. #include "exevents.h"
  40. #include "xipassivegrab.h"
  41. #include "dixgrabs.h"
  42. #include "misc.h"
  43. #include "inpututils.h"
  44. int
  45. SProcXIPassiveGrabDevice(ClientPtr client)
  46. {
  47. int i;
  48. uint32_t *mods;
  49. REQUEST(xXIPassiveGrabDeviceReq);
  50. REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
  51. swaps(&stuff->length);
  52. swaps(&stuff->deviceid);
  53. swapl(&stuff->grab_window);
  54. swapl(&stuff->cursor);
  55. swapl(&stuff->time);
  56. swapl(&stuff->detail);
  57. swaps(&stuff->mask_len);
  58. swaps(&stuff->num_modifiers);
  59. REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq,
  60. ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4);
  61. mods = (uint32_t *) &stuff[1] + stuff->mask_len;
  62. for (i = 0; i < stuff->num_modifiers; i++, mods++) {
  63. swapl(mods);
  64. }
  65. return ProcXIPassiveGrabDevice(client);
  66. }
  67. int
  68. ProcXIPassiveGrabDevice(ClientPtr client)
  69. {
  70. DeviceIntPtr dev, mod_dev;
  71. xXIPassiveGrabDeviceReply rep = {
  72. .repType = X_Reply,
  73. .RepType = X_XIPassiveGrabDevice,
  74. .sequenceNumber = client->sequence,
  75. .length = 0,
  76. .num_modifiers = 0
  77. };
  78. int i, ret = Success;
  79. uint32_t *modifiers;
  80. xXIGrabModifierInfo *modifiers_failed;
  81. GrabMask mask = { 0 };
  82. GrabParameters param;
  83. void *tmp;
  84. int mask_len;
  85. REQUEST(xXIPassiveGrabDeviceReq);
  86. REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq,
  87. ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4);
  88. if (stuff->deviceid == XIAllDevices)
  89. dev = inputInfo.all_devices;
  90. else if (stuff->deviceid == XIAllMasterDevices)
  91. dev = inputInfo.all_master_devices;
  92. else {
  93. ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
  94. if (ret != Success) {
  95. client->errorValue = stuff->deviceid;
  96. return ret;
  97. }
  98. }
  99. if (stuff->grab_type != XIGrabtypeButton &&
  100. stuff->grab_type != XIGrabtypeKeycode &&
  101. stuff->grab_type != XIGrabtypeEnter &&
  102. stuff->grab_type != XIGrabtypeFocusIn &&
  103. stuff->grab_type != XIGrabtypeTouchBegin) {
  104. client->errorValue = stuff->grab_type;
  105. return BadValue;
  106. }
  107. if ((stuff->grab_type == XIGrabtypeEnter ||
  108. stuff->grab_type == XIGrabtypeFocusIn ||
  109. stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) {
  110. client->errorValue = stuff->detail;
  111. return BadValue;
  112. }
  113. if (stuff->grab_type == XIGrabtypeTouchBegin &&
  114. (stuff->grab_mode != XIGrabModeTouch ||
  115. stuff->paired_device_mode != GrabModeAsync)) {
  116. client->errorValue = stuff->grab_mode;
  117. return BadValue;
  118. }
  119. if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1],
  120. stuff->mask_len * 4) != Success)
  121. return BadValue;
  122. mask.xi2mask = xi2mask_new();
  123. if (!mask.xi2mask)
  124. return BadAlloc;
  125. mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4);
  126. xi2mask_set_one_mask(mask.xi2mask, stuff->deviceid,
  127. (unsigned char *) &stuff[1], mask_len * 4);
  128. memset(&param, 0, sizeof(param));
  129. param.grabtype = XI2;
  130. param.ownerEvents = stuff->owner_events;
  131. param.grabWindow = stuff->grab_window;
  132. param.cursor = stuff->cursor;
  133. if (IsKeyboardDevice(dev)) {
  134. param.this_device_mode = stuff->grab_mode;
  135. param.other_devices_mode = stuff->paired_device_mode;
  136. }
  137. else {
  138. param.this_device_mode = stuff->paired_device_mode;
  139. param.other_devices_mode = stuff->grab_mode;
  140. }
  141. if (stuff->cursor != None) {
  142. ret = dixLookupResourceByType(&tmp, stuff->cursor,
  143. RT_CURSOR, client, DixUseAccess);
  144. if (ret != Success) {
  145. client->errorValue = stuff->cursor;
  146. goto out;
  147. }
  148. }
  149. ret =
  150. dixLookupWindow((WindowPtr *) &tmp, stuff->grab_window, client,
  151. DixSetAttrAccess);
  152. if (ret != Success)
  153. goto out;
  154. ret = CheckGrabValues(client, &param);
  155. if (ret != Success)
  156. goto out;
  157. modifiers = (uint32_t *) &stuff[1] + stuff->mask_len;
  158. modifiers_failed =
  159. calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
  160. if (!modifiers_failed) {
  161. ret = BadAlloc;
  162. goto out;
  163. }
  164. mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
  165. for (i = 0; i < stuff->num_modifiers; i++, modifiers++) {
  166. uint8_t status = Success;
  167. param.modifiers = *modifiers;
  168. ret = CheckGrabValues(client, &param);
  169. if (ret != Success)
  170. goto out;
  171. switch (stuff->grab_type) {
  172. case XIGrabtypeButton:
  173. status = GrabButton(client, dev, mod_dev, stuff->detail,
  174. &param, XI2, &mask);
  175. break;
  176. case XIGrabtypeKeycode:
  177. status = GrabKey(client, dev, mod_dev, stuff->detail,
  178. &param, XI2, &mask);
  179. break;
  180. case XIGrabtypeEnter:
  181. case XIGrabtypeFocusIn:
  182. status = GrabWindow(client, dev, stuff->grab_type, &param, &mask);
  183. break;
  184. case XIGrabtypeTouchBegin:
  185. status = GrabTouch(client, dev, mod_dev, &param, &mask);
  186. break;
  187. }
  188. if (status != GrabSuccess) {
  189. xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
  190. info->status = status;
  191. info->modifiers = *modifiers;
  192. if (client->swapped)
  193. swapl(&info->modifiers);
  194. rep.num_modifiers++;
  195. rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo));
  196. }
  197. }
  198. WriteReplyToClient(client, sizeof(rep), &rep);
  199. if (rep.num_modifiers)
  200. WriteToClient(client, rep.length * 4, modifiers_failed);
  201. free(modifiers_failed);
  202. out:
  203. xi2mask_free(&mask.xi2mask);
  204. return ret;
  205. }
  206. void
  207. SRepXIPassiveGrabDevice(ClientPtr client, int size,
  208. xXIPassiveGrabDeviceReply * rep)
  209. {
  210. swaps(&rep->sequenceNumber);
  211. swapl(&rep->length);
  212. swaps(&rep->num_modifiers);
  213. WriteToClient(client, size, rep);
  214. }
  215. int
  216. SProcXIPassiveUngrabDevice(ClientPtr client)
  217. {
  218. int i;
  219. uint32_t *modifiers;
  220. REQUEST(xXIPassiveUngrabDeviceReq);
  221. REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
  222. swaps(&stuff->length);
  223. swapl(&stuff->grab_window);
  224. swaps(&stuff->deviceid);
  225. swapl(&stuff->detail);
  226. swaps(&stuff->num_modifiers);
  227. REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq,
  228. ((uint32_t) stuff->num_modifiers) << 2);
  229. modifiers = (uint32_t *) &stuff[1];
  230. for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
  231. swapl(modifiers);
  232. return ProcXIPassiveUngrabDevice(client);
  233. }
  234. int
  235. ProcXIPassiveUngrabDevice(ClientPtr client)
  236. {
  237. DeviceIntPtr dev, mod_dev;
  238. WindowPtr win;
  239. GrabPtr tempGrab;
  240. uint32_t *modifiers;
  241. int i, rc;
  242. REQUEST(xXIPassiveUngrabDeviceReq);
  243. REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq,
  244. ((uint32_t) stuff->num_modifiers) << 2);
  245. if (stuff->deviceid == XIAllDevices)
  246. dev = inputInfo.all_devices;
  247. else if (stuff->deviceid == XIAllMasterDevices)
  248. dev = inputInfo.all_master_devices;
  249. else {
  250. rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
  251. if (rc != Success)
  252. return rc;
  253. }
  254. if (stuff->grab_type != XIGrabtypeButton &&
  255. stuff->grab_type != XIGrabtypeKeycode &&
  256. stuff->grab_type != XIGrabtypeEnter &&
  257. stuff->grab_type != XIGrabtypeFocusIn &&
  258. stuff->grab_type != XIGrabtypeTouchBegin) {
  259. client->errorValue = stuff->grab_type;
  260. return BadValue;
  261. }
  262. if ((stuff->grab_type == XIGrabtypeEnter ||
  263. stuff->grab_type == XIGrabtypeFocusIn ||
  264. stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) {
  265. client->errorValue = stuff->detail;
  266. return BadValue;
  267. }
  268. rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
  269. if (rc != Success)
  270. return rc;
  271. mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
  272. tempGrab = AllocGrab(NULL);
  273. if (!tempGrab)
  274. return BadAlloc;
  275. tempGrab->resource = client->clientAsMask;
  276. tempGrab->device = dev;
  277. tempGrab->window = win;
  278. switch (stuff->grab_type) {
  279. case XIGrabtypeButton:
  280. tempGrab->type = XI_ButtonPress;
  281. break;
  282. case XIGrabtypeKeycode:
  283. tempGrab->type = XI_KeyPress;
  284. break;
  285. case XIGrabtypeEnter:
  286. tempGrab->type = XI_Enter;
  287. break;
  288. case XIGrabtypeFocusIn:
  289. tempGrab->type = XI_FocusIn;
  290. break;
  291. case XIGrabtypeTouchBegin:
  292. tempGrab->type = XI_TouchBegin;
  293. break;
  294. }
  295. tempGrab->grabtype = XI2;
  296. tempGrab->modifierDevice = mod_dev;
  297. tempGrab->modifiersDetail.pMask = NULL;
  298. tempGrab->detail.exact = stuff->detail;
  299. tempGrab->detail.pMask = NULL;
  300. modifiers = (uint32_t *) &stuff[1];
  301. for (i = 0; i < stuff->num_modifiers; i++, modifiers++) {
  302. tempGrab->modifiersDetail.exact = *modifiers;
  303. DeletePassiveGrabFromList(tempGrab);
  304. }
  305. FreeGrab(tempGrab);
  306. return Success;
  307. }