Home | History | Annotate | Line # | Download | only in src
      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 
     36 static 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                      Time time)
     43 {
     44     xXIPassiveGrabDeviceReq *req;
     45     xXIPassiveGrabDeviceReply reply;
     46     xXIGrabModifierInfo *failed_mods;
     47     int len = 0, i;
     48     int ret = -1;
     49     char *buff;
     50 
     51     XExtDisplayInfo *extinfo = XInput_find_display(dpy);
     52 
     53     LockDisplay(dpy);
     54     if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
     55 	return -1;
     56 
     57     if (mask->mask_len > INT_MAX - 3 ||
     58         (mask->mask_len + 3)/4 >= 0xffff)
     59         goto out;
     60 
     61     buff = calloc(4, (mask->mask_len + 3)/4);
     62     if (!buff)
     63         goto out;
     64 
     65     GetReq(XIPassiveGrabDevice, req);
     66     req->reqType = extinfo->codes->major_opcode;
     67     req->ReqType = X_XIPassiveGrabDevice;
     68     req->deviceid = deviceid;
     69     req->grab_mode = grab_mode;
     70     req->paired_device_mode = paired_device_mode;
     71     req->owner_events = owner_events;
     72     req->grab_window = grab_window;
     73     req->cursor = cursor;
     74     req->detail = detail;
     75     req->num_modifiers = num_modifiers;
     76     req->mask_len = (mask->mask_len + 3)/4;
     77     req->grab_type = grabtype;
     78     req->time = time;
     79 
     80     len = req->mask_len + num_modifiers;
     81     SetReqLen(req, len, len);
     82 
     83     memcpy(buff, mask->mask, mask->mask_len);
     84     Data(dpy, buff, req->mask_len * 4);
     85     for (i = 0; i < num_modifiers; i++)
     86         Data(dpy, (char*)&modifiers_inout[i].modifiers, 4);
     87 
     88     free(buff);
     89 
     90     if (!_XReply(dpy, (xReply *)&reply, 0, xFalse))
     91         goto out;
     92 
     93     failed_mods = calloc(reply.num_modifiers, sizeof(xXIGrabModifierInfo));
     94     if (!failed_mods)
     95         goto out;
     96     _XRead(dpy, (char*)failed_mods, reply.num_modifiers * sizeof(xXIGrabModifierInfo));
     97 
     98     for (i = 0; i < reply.num_modifiers && i < num_modifiers; i++)
     99     {
    100         modifiers_inout[i].status = failed_mods[i].status;
    101         modifiers_inout[i].modifiers = failed_mods[i].modifiers;
    102     }
    103     free(failed_mods);
    104 
    105     ret = reply.num_modifiers;
    106 
    107  out:
    108     UnlockDisplay(dpy);
    109     SyncHandle();
    110     return ret;
    111 }
    112 
    113 int
    114 XIGrabButton(Display* dpy, int deviceid, int button,
    115              Window grab_window, Cursor cursor,
    116              int grab_mode, int paired_device_mode,
    117              Bool owner_events, XIEventMask *mask,
    118              int num_modifiers, XIGrabModifiers *modifiers_inout)
    119 {
    120     return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeButton, button,
    121                                 grab_window, cursor, grab_mode,
    122                                 paired_device_mode, owner_events, mask,
    123                                 num_modifiers, modifiers_inout, CurrentTime);
    124 }
    125 
    126 int
    127 XIGrabKeycode(Display* dpy, int deviceid, int keycode,
    128              Window grab_window, int grab_mode, int paired_device_mode,
    129              Bool owner_events, XIEventMask *mask,
    130              int num_modifiers, XIGrabModifiers *modifiers_inout)
    131 {
    132     return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeKeycode, keycode,
    133                                 grab_window, None, grab_mode, paired_device_mode,
    134                                 owner_events, mask, num_modifiers,
    135                                 modifiers_inout, CurrentTime);
    136 }
    137 
    138 int
    139 XIGrabEnter(Display *dpy, int deviceid, Window grab_window, Cursor cursor,
    140             int grab_mode, int paired_device_mode, Bool owner_events,
    141             XIEventMask *mask, int num_modifiers,
    142             XIGrabModifiers *modifiers_inout)
    143 {
    144     return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeEnter, 0,
    145                                 grab_window, cursor, grab_mode, paired_device_mode,
    146                                 owner_events, mask, num_modifiers,
    147                                 modifiers_inout, CurrentTime);
    148 }
    149 
    150 int
    151 XIGrabFocusIn(Display *dpy, int deviceid, Window grab_window, int grab_mode,
    152             int paired_device_mode, Bool owner_events, XIEventMask *mask,
    153             int num_modifiers, XIGrabModifiers *modifiers_inout)
    154 {
    155     return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeFocusIn, 0,
    156                                 grab_window, None, grab_mode, paired_device_mode,
    157                                 owner_events, mask, num_modifiers,
    158                                 modifiers_inout, CurrentTime);
    159 }
    160 
    161 int
    162 XIGrabTouchBegin(Display *dpy, int deviceid, Window grab_window,
    163                  Bool owner_events, XIEventMask *mask,
    164                  int num_modifiers, XIGrabModifiers *modifiers_inout)
    165 {
    166     XExtDisplayInfo *extinfo = XInput_find_display(dpy);
    167 
    168     LockDisplay(dpy);
    169     if (_XiCheckExtInit(dpy, XInput_2_2, extinfo) == -1)
    170 	return -1;
    171     UnlockDisplay(dpy);
    172 
    173     /* FIXME: allow selection of GrabMode for paired devices? */
    174     return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeTouchBegin, 0,
    175                                 grab_window, None, XIGrabModeTouch,
    176                                 GrabModeAsync, owner_events, mask,
    177                                 num_modifiers, modifiers_inout, CurrentTime);
    178 }
    179 
    180 int XIGrabPinchGestureBegin(Display* dpy, int deviceid, Window grab_window, int grab_mode,
    181                             int paired_device_mode, int owner_events,
    182                             XIEventMask *mask, int num_modifiers, XIGrabModifiers *modifiers_inout)
    183 {
    184     XExtDisplayInfo *extinfo = XInput_find_display(dpy);
    185 
    186     LockDisplay(dpy);
    187     if (_XiCheckExtInit(dpy, XInput_2_4, extinfo) == -1)
    188         return -1;
    189     UnlockDisplay(dpy);
    190 
    191     return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeGesturePinchBegin, 0,
    192                                 grab_window, None, grab_mode, paired_device_mode,
    193                                 owner_events, mask, num_modifiers, modifiers_inout, CurrentTime);
    194 }
    195 
    196 int XIGrabSwipeGestureBegin(Display* dpy, int deviceid, Window grab_window, int grab_mode,
    197                             int paired_device_mode, int owner_events,
    198                             XIEventMask *mask, int num_modifiers, XIGrabModifiers *modifiers_inout)
    199 {
    200     XExtDisplayInfo *extinfo = XInput_find_display(dpy);
    201 
    202     LockDisplay(dpy);
    203     if (_XiCheckExtInit(dpy, XInput_2_4, extinfo) == -1)
    204         return -1;
    205     UnlockDisplay(dpy);
    206 
    207     return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeGestureSwipeBegin, 0,
    208                                 grab_window, None, grab_mode, paired_device_mode,
    209                                 owner_events, mask, num_modifiers, modifiers_inout, CurrentTime);
    210 }
    211 
    212 static int
    213 _XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail,
    214                        Window grab_window, int num_modifiers, XIGrabModifiers *modifiers)
    215 {
    216     xXIPassiveUngrabDeviceReq *req;
    217     int i;
    218 
    219     XExtDisplayInfo *extinfo = XInput_find_display(dpy);
    220 
    221     LockDisplay(dpy);
    222     if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
    223 	return -1;
    224 
    225     GetReq(XIPassiveUngrabDevice, req);
    226     req->reqType = extinfo->codes->major_opcode;
    227     req->ReqType = X_XIPassiveUngrabDevice;
    228     req->deviceid = deviceid;
    229     req->grab_window = grab_window;
    230     req->detail = detail;
    231     req->num_modifiers = num_modifiers;
    232     req->grab_type = grabtype;
    233 
    234     SetReqLen(req, num_modifiers, num_modifiers);
    235     for (i = 0; i < num_modifiers; i++)
    236         Data32(dpy, &modifiers[i].modifiers, 4);
    237 
    238     UnlockDisplay(dpy);
    239     SyncHandle();
    240     return Success;
    241 }
    242 
    243 int
    244 XIUngrabButton(Display* display, int deviceid, int button,Window grab_window,
    245                int num_modifiers, XIGrabModifiers *modifiers)
    246 {
    247     return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeButton, button,
    248                                   grab_window, num_modifiers, modifiers);
    249 }
    250 
    251 int
    252 XIUngrabKeycode(Display* display, int deviceid, int keycode, Window grab_window,
    253                int num_modifiers, XIGrabModifiers *modifiers)
    254 {
    255     return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeKeycode, keycode,
    256                                   grab_window, num_modifiers, modifiers);
    257 }
    258 
    259 
    260 int
    261 XIUngrabEnter(Display* display, int deviceid, Window grab_window,
    262                int num_modifiers, XIGrabModifiers *modifiers)
    263 {
    264     return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeEnter, 0,
    265                                   grab_window, num_modifiers, modifiers);
    266 }
    267 
    268 int
    269 XIUngrabFocusIn(Display* display, int deviceid, Window grab_window,
    270                int num_modifiers, XIGrabModifiers *modifiers)
    271 {
    272     return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeFocusIn, 0,
    273                                   grab_window, num_modifiers, modifiers);
    274 }
    275 
    276 int
    277 XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window,
    278                    int num_modifiers, XIGrabModifiers *modifiers)
    279 {
    280     XExtDisplayInfo *extinfo = XInput_find_display(display);
    281 
    282     LockDisplay(display);
    283     if (_XiCheckExtInit(display, XInput_2_2, extinfo) == -1)
    284 	return -1;
    285     UnlockDisplay(display);
    286 
    287     return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0,
    288                                   grab_window, num_modifiers, modifiers);
    289 }
    290 
    291 int XIUngrabPinchGestureBegin(Display* display, int deviceid, Window grab_window,
    292                               int num_modifiers, XIGrabModifiers *modifiers)
    293 {
    294     XExtDisplayInfo *extinfo = XInput_find_display(display);
    295 
    296     LockDisplay(display);
    297     if (_XiCheckExtInit(display, XInput_2_4, extinfo) == -1)
    298         return -1;
    299     UnlockDisplay(display);
    300 
    301     return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeGesturePinchBegin, 0,
    302                                   grab_window, num_modifiers, modifiers);
    303 }
    304 
    305 int XIUngrabSwipeGestureBegin(Display* display, int deviceid, Window grab_window,
    306                               int num_modifiers, XIGrabModifiers *modifiers)
    307 {
    308     XExtDisplayInfo *extinfo = XInput_find_display(display);
    309 
    310     LockDisplay(display);
    311     if (_XiCheckExtInit(display, XInput_2_4, extinfo) == -1)
    312         return -1;
    313     UnlockDisplay(display);
    314 
    315     return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeGestureSwipeBegin, 0,
    316                                   grab_window, num_modifiers, modifiers);
    317 }
    318