XIPassiveGrab.c revision 10baa824
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 char *buff; 48 49 XExtDisplayInfo *extinfo = XInput_find_display(dpy); 50 51 LockDisplay(dpy); 52 if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1) 53 return -1; 54 55 if (mask->mask_len > INT_MAX - 3 || 56 (mask->mask_len + 3)/4 >= 0xffff) 57 return -1; 58 59 buff = calloc(4, (mask->mask_len + 3)/4); 60 if (!buff) 61 return -1; 62 63 GetReq(XIPassiveGrabDevice, req); 64 req->reqType = extinfo->codes->major_opcode; 65 req->ReqType = X_XIPassiveGrabDevice; 66 req->deviceid = deviceid; 67 req->grab_mode = grab_mode; 68 req->paired_device_mode = paired_device_mode; 69 req->owner_events = owner_events; 70 req->grab_window = grab_window; 71 req->cursor = cursor; 72 req->detail = detail; 73 req->num_modifiers = num_modifiers; 74 req->mask_len = (mask->mask_len + 3)/4; 75 req->grab_type = grabtype; 76 77 len = req->mask_len + num_modifiers; 78 SetReqLen(req, len, len); 79 80 memcpy(buff, mask->mask, mask->mask_len); 81 Data(dpy, buff, req->mask_len * 4); 82 for (i = 0; i < num_modifiers; i++) 83 Data(dpy, (char*)&modifiers_inout[i].modifiers, 4); 84 85 free(buff); 86 87 if (!_XReply(dpy, (xReply *)&reply, 0, xFalse)) 88 { 89 UnlockDisplay(dpy); 90 SyncHandle(); 91 return -1; 92 } 93 94 failed_mods = calloc(reply.num_modifiers, sizeof(xXIGrabModifierInfo)); 95 if (!failed_mods) 96 return -1; 97 _XRead(dpy, (char*)failed_mods, reply.num_modifiers * sizeof(xXIGrabModifierInfo)); 98 99 for (i = 0; i < reply.num_modifiers && i < num_modifiers; i++) 100 { 101 modifiers_inout[i].status = failed_mods[i].status; 102 modifiers_inout[i].modifiers = failed_mods[i].modifiers; 103 } 104 free(failed_mods); 105 106 UnlockDisplay(dpy); 107 SyncHandle(); 108 return reply.num_modifiers; 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 170 /* FIXME: allow selection of GrabMode for paired devices? */ 171 return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeTouchBegin, 0, 172 grab_window, None, XIGrabModeTouch, 173 GrabModeAsync, owner_events, mask, 174 num_modifiers, modifiers_inout); 175} 176 177 178static int 179_XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail, 180 Window grab_window, int num_modifiers, XIGrabModifiers *modifiers) 181{ 182 xXIPassiveUngrabDeviceReq *req; 183 int i; 184 185 XExtDisplayInfo *extinfo = XInput_find_display(dpy); 186 187 LockDisplay(dpy); 188 if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1) 189 return -1; 190 191 GetReq(XIPassiveUngrabDevice, req); 192 req->reqType = extinfo->codes->major_opcode; 193 req->ReqType = X_XIPassiveUngrabDevice; 194 req->deviceid = deviceid; 195 req->grab_window = grab_window; 196 req->detail = detail; 197 req->num_modifiers = num_modifiers; 198 req->grab_type = grabtype; 199 200 SetReqLen(req, num_modifiers, num_modifiers); 201 for (i = 0; i < num_modifiers; i++) 202 Data32(dpy, &modifiers[i].modifiers, 4); 203 204 UnlockDisplay(dpy); 205 SyncHandle(); 206 return Success; 207} 208 209int 210XIUngrabButton(Display* display, int deviceid, int button,Window grab_window, 211 int num_modifiers, XIGrabModifiers *modifiers) 212{ 213 return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeButton, button, 214 grab_window, num_modifiers, modifiers); 215} 216 217int 218XIUngrabKeycode(Display* display, int deviceid, int keycode, Window grab_window, 219 int num_modifiers, XIGrabModifiers *modifiers) 220{ 221 return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeKeycode, keycode, 222 grab_window, num_modifiers, modifiers); 223} 224 225 226int 227XIUngrabEnter(Display* display, int deviceid, Window grab_window, 228 int num_modifiers, XIGrabModifiers *modifiers) 229{ 230 return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeEnter, 0, 231 grab_window, num_modifiers, modifiers); 232} 233 234int 235XIUngrabFocusIn(Display* display, int deviceid, Window grab_window, 236 int num_modifiers, XIGrabModifiers *modifiers) 237{ 238 return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeFocusIn, 0, 239 grab_window, num_modifiers, modifiers); 240} 241 242int 243XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window, 244 int num_modifiers, XIGrabModifiers *modifiers) 245{ 246 XExtDisplayInfo *extinfo = XInput_find_display(display); 247 248 LockDisplay(display); 249 if (_XiCheckExtInit(display, XInput_2_2, extinfo) == -1) 250 return -1; 251 252 return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0, 253 grab_window, num_modifiers, modifiers); 254} 255