XISelEv.c revision 3e256790
1/************************************************************ 2 3Copyright 2009 Red Hat, Inc. 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of the author shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from the author. 24 25*/ 26 27/*********************************************************************** 28 * 29 * XISelectEvent - Select for XI2 events. 30 * 31 */ 32 33 34#include <stdint.h> 35#include <X11/Xlibint.h> 36#include <X11/extensions/XI2proto.h> 37#include <X11/extensions/XInput2.h> 38#include <X11/extensions/extutil.h> 39#include <X11/extensions/ge.h> 40#include <X11/extensions/geproto.h> 41#include "XIint.h" 42 43int 44XISelectEvents(Display* dpy, Window win, XIEventMask* masks, int num_masks) 45{ 46 XIEventMask *current; 47 xXISelectEventsReq *req; 48 xXIEventMask mask; 49 int i; 50 int len = 0; 51 int r = Success; 52 53 XExtDisplayInfo *info = XInput_find_display(dpy); 54 LockDisplay(dpy); 55 if (_XiCheckExtInit(dpy, Dont_Check, info) == -1) { 56 r = NoSuchExtension; 57 goto out; 58 } 59 GetReq(XISelectEvents, req); 60 61 req->reqType = info->codes->major_opcode; 62 req->ReqType = X_XISelectEvents; 63 req->win = win; 64 req->num_masks = num_masks; 65 66 /* get the right length */ 67 for (i = 0; i < num_masks; i++) 68 { 69 len++; 70 current = &masks[i]; 71 len += (current->mask_len + 3)/4; 72 } 73 74 SetReqLen(req, len, len); 75 76 for (i = 0; i < num_masks; i++) 77 { 78 char *buff; 79 current = &masks[i]; 80 mask.deviceid = current->deviceid; 81 mask.mask_len = (current->mask_len + 3)/4; 82 /* masks.mask_len is in bytes, but we need 4-byte units on the wire, 83 * and they need to be padded with 0 */ 84 buff = calloc(1, mask.mask_len * 4); 85 memcpy(buff, current->mask, current->mask_len); 86 Data32(dpy, &mask, sizeof(xXIEventMask)); 87 Data(dpy, buff, mask.mask_len * 4); 88 free(buff); 89 } 90 91out: 92 UnlockDisplay(dpy); 93 SyncHandle(); 94 return r; 95 96} 97 98XIEventMask* 99XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return) 100{ 101 int i, len = 0; 102 unsigned char *mask; 103 XIEventMask *mask_out = NULL; 104 xXIEventMask *mask_in = NULL, *mi; 105 xXIGetSelectedEventsReq *req; 106 xXIGetSelectedEventsReply reply; 107 108 *num_masks_return = -1; 109 XExtDisplayInfo *info = XInput_find_display(dpy); 110 LockDisplay(dpy); 111 if (_XiCheckExtInit(dpy, Dont_Check, info) == -1) 112 goto out; 113 114 GetReq(XIGetSelectedEvents, req); 115 116 req->reqType = info->codes->major_opcode; 117 req->ReqType = X_XIGetSelectedEvents; 118 req->win = win; 119 120 if (!_XReply(dpy, (xReply *) &reply, 0, xFalse)) 121 goto out; 122 123 if (reply.num_masks == 0) 124 { 125 *num_masks_return = 0; 126 goto out; 127 } 128 129 mask_in = Xmalloc(reply.length * 4); 130 if (!mask_in) 131 goto out; 132 133 _XRead(dpy, (char*)mask_in, reply.length * 4); 134 135 /* Memory layout of the XIEventMask for a 3 mask reply: 136 * [struct a][struct b][struct c][masks a][masks b][masks c] 137 */ 138 len = reply.num_masks * sizeof(XIEventMask); 139 140 for (i = 0, mi = mask_in; i < reply.num_masks; i++) 141 { 142 len += mi->mask_len * 4; 143 mi = (xXIEventMask*)((char*)mi + mi->mask_len * 4); 144 mi++; 145 } 146 147 mask_out = Xmalloc(len); 148 if (!mask_out) 149 goto out; 150 151 mi = mask_in; 152 mask = (unsigned char*)&mask_out[reply.num_masks]; 153 for (i = 0; i < reply.num_masks; i++) 154 { 155 mask_out[i].deviceid = mi->deviceid; 156 mask_out[i].mask_len = mi->mask_len * 4; 157 mask_out[i].mask = mask; 158 memcpy(mask_out[i].mask, &mi[1], mask_out[i].mask_len); 159 mask += mask_out[i].mask_len; 160 mi = (xXIEventMask*)((char*)mi + mi->mask_len * 4); 161 mi++; 162 } 163 164 *num_masks_return = reply.num_masks; 165 166out: 167 Xfree(mask_in); 168 169 UnlockDisplay(dpy); 170 SyncHandle(); 171 172 return mask_out; 173} 174