XIPassiveGrab.c revision 32ed59c1
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 */ 24#ifdef HAVE_CONFIG_H 25#include <config.h> 26#endif 27 28#include <stdint.h> 29#include <X11/Xlibint.h> 30#include <X11/extensions/XI2proto.h> 31#include <X11/extensions/XInput2.h> 32#include <X11/extensions/extutil.h> 33#include <limits.h> 34#include "XIint.h" 35 36static int 37_XIPassiveGrabDevice(Display* dpy, int deviceid, int grabtype, int detail, 38 Window grab_window, Cursor cursor, 39 int grab_mode, int paired_device_mode, 40 Bool owner_events, XIEventMask *mask, 41 int num_modifiers, XIGrabModifiers *modifiers_inout) 42{ 43 xXIPassiveGrabDeviceReq *req; 44 xXIPassiveGrabDeviceReply reply; 45 xXIGrabModifierInfo *failed_mods; 46 int len = 0, i; 47 int ret = -1; 48 char *buff; 49 50 XExtDisplayInfo *extinfo = XInput_find_display(dpy); 51 52 LockDisplay(dpy); 53 if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1) 54 return -1; 55 56 if (mask->mask_len > INT_MAX - 3 || 57 (mask->mask_len + 3)/4 >= 0xffff) 58 goto out; 59 60 buff = calloc(4, (mask->mask_len + 3)/4); 61 if (!buff) 62 goto out; 63 64 GetReq(XIPassiveGrabDevice, req); 65 req->reqType = extinfo->codes->major_opcode; 66 req->ReqType = X_XIPassiveGrabDevice; 67 req->deviceid = deviceid; 68 req->grab_mode = grab_mode; 69 req->paired_device_mode = paired_device_mode; 70 req->owner_events = owner_events; 71 req->grab_window = grab_window; 72 req->cursor = cursor; 73 req->detail = detail; 74 req->num_modifiers = num_modifiers; 75 req->mask_len = (mask->mask_len + 3)/4; 76 req->grab_type = grabtype; 77 78 len = req->mask_len + num_modifiers; 79 SetReqLen(req, len, len); 80 81 memcpy(buff, mask->mask, mask->mask_len); 82 Data(dpy, buff, req->mask_len * 4); 83 for (i = 0; i < num_modifiers; i++) 84 Data(dpy, (char*)&modifiers_inout[i].modifiers, 4); 85 86 free(buff); 87 88 if (!_XReply(dpy, (xReply *)&reply, 0, xFalse)) 89 goto out; 90 91 failed_mods = calloc(reply.num_modifiers, sizeof(xXIGrabModifierInfo)); 92 if (!failed_mods) 93 goto out; 94 _XRead(dpy, (char*)failed_mods, reply.num_modifiers * sizeof(xXIGrabModifierInfo)); 95 96 for (i = 0; i < reply.num_modifiers && i < num_modifiers; i++) 97 { 98 modifiers_inout[i].status = failed_mods[i].status; 99 modifiers_inout[i].modifiers = failed_mods[i].modifiers; 100 } 101 free(failed_mods); 102 103 ret = reply.num_modifiers; 104 105 out: 106 UnlockDisplay(dpy); 107 SyncHandle(); 108 return ret; 109} 110 111int 112XIGrabButton(Display* dpy, int deviceid, int button, 113 Window grab_window, Cursor cursor, 114 int grab_mode, int paired_device_mode, 115 Bool owner_events, XIEventMask *mask, 116 int num_modifiers, XIGrabModifiers *modifiers_inout) 117{ 118 return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeButton, button, 119 grab_window, cursor, grab_mode, 120 paired_device_mode, owner_events, mask, 121 num_modifiers, modifiers_inout); 122} 123 124int 125XIGrabKeycode(Display* dpy, int deviceid, int keycode, 126 Window grab_window, int grab_mode, int paired_device_mode, 127 Bool owner_events, XIEventMask *mask, 128 int num_modifiers, XIGrabModifiers *modifiers_inout) 129{ 130 return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeKeycode, keycode, 131 grab_window, None, grab_mode, paired_device_mode, 132 owner_events, mask, num_modifiers, 133 modifiers_inout); 134} 135 136int 137XIGrabEnter(Display *dpy, int deviceid, Window grab_window, Cursor cursor, 138 int grab_mode, int paired_device_mode, Bool owner_events, 139 XIEventMask *mask, int num_modifiers, 140 XIGrabModifiers *modifiers_inout) 141{ 142 return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeEnter, 0, 143 grab_window, cursor, grab_mode, paired_device_mode, 144 owner_events, mask, num_modifiers, 145 modifiers_inout); 146} 147 148int 149XIGrabFocusIn(Display *dpy, int deviceid, Window grab_window, int grab_mode, 150 int paired_device_mode, Bool owner_events, XIEventMask *mask, 151 int num_modifiers, XIGrabModifiers *modifiers_inout) 152{ 153 return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeFocusIn, 0, 154 grab_window, None, grab_mode, paired_device_mode, 155 owner_events, mask, num_modifiers, 156 modifiers_inout); 157} 158 159int 160XIGrabTouchBegin(Display *dpy, int deviceid, Window grab_window, 161 Bool owner_events, XIEventMask *mask, 162 int num_modifiers, XIGrabModifiers *modifiers_inout) 163{ 164 XExtDisplayInfo *extinfo = XInput_find_display(dpy); 165 166 LockDisplay(dpy); 167 if (_XiCheckExtInit(dpy, XInput_2_2, extinfo) == -1) 168 return -1; 169 UnlockDisplay(dpy); 170 171 /* FIXME: allow selection of GrabMode for paired devices? */ 172 return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeTouchBegin, 0, 173 grab_window, None, XIGrabModeTouch, 174 GrabModeAsync, owner_events, mask, 175 num_modifiers, modifiers_inout); 176} 177 178 179static int 180_XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail, 181 Window grab_window, int num_modifiers, XIGrabModifiers *modifiers) 182{ 183 xXIPassiveUngrabDeviceReq *req; 184 int i; 185 186 XExtDisplayInfo *extinfo = XInput_find_display(dpy); 187 188 LockDisplay(dpy); 189 if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1) 190 return -1; 191 192 GetReq(XIPassiveUngrabDevice, req); 193 req->reqType = extinfo->codes->major_opcode; 194 req->ReqType = X_XIPassiveUngrabDevice; 195 req->deviceid = deviceid; 196 req->grab_window = grab_window; 197 req->detail = detail; 198 req->num_modifiers = num_modifiers; 199 req->grab_type = grabtype; 200 201 SetReqLen(req, num_modifiers, num_modifiers); 202 for (i = 0; i < num_modifiers; i++) 203 Data32(dpy, &modifiers[i].modifiers, 4); 204 205 UnlockDisplay(dpy); 206 SyncHandle(); 207 return Success; 208} 209 210int 211XIUngrabButton(Display* display, int deviceid, int button,Window grab_window, 212 int num_modifiers, XIGrabModifiers *modifiers) 213{ 214 return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeButton, button, 215 grab_window, num_modifiers, modifiers); 216} 217 218int 219XIUngrabKeycode(Display* display, int deviceid, int keycode, Window grab_window, 220 int num_modifiers, XIGrabModifiers *modifiers) 221{ 222 return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeKeycode, keycode, 223 grab_window, num_modifiers, modifiers); 224} 225 226 227int 228XIUngrabEnter(Display* display, int deviceid, Window grab_window, 229 int num_modifiers, XIGrabModifiers *modifiers) 230{ 231 return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeEnter, 0, 232 grab_window, num_modifiers, modifiers); 233} 234 235int 236XIUngrabFocusIn(Display* display, int deviceid, Window grab_window, 237 int num_modifiers, XIGrabModifiers *modifiers) 238{ 239 return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeFocusIn, 0, 240 grab_window, num_modifiers, modifiers); 241} 242 243int 244XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window, 245 int num_modifiers, XIGrabModifiers *modifiers) 246{ 247 XExtDisplayInfo *extinfo = XInput_find_display(display); 248 249 LockDisplay(display); 250 if (_XiCheckExtInit(display, XInput_2_2, extinfo) == -1) 251 return -1; 252 253 return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0, 254 grab_window, num_modifiers, modifiers); 255} 256