XISelEv.c revision c27c18e8
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 52 XExtDisplayInfo *info = XInput_find_display(dpy); 53 LockDisplay(dpy); 54 if (_XiCheckExtInit(dpy, Dont_Check, info) == -1) 55 return (NoSuchExtension); 56 GetReq(XISelectEvents, req); 57 58 req->reqType = info->codes->major_opcode; 59 req->ReqType = X_XISelectEvents; 60 req->win = win; 61 req->num_masks = num_masks; 62 63 /* get the right length */ 64 for (i = 0; i < num_masks; i++) 65 { 66 len++; 67 current = &masks[i]; 68 len += (current->mask_len + 3)/4; 69 } 70 71 SetReqLen(req, len, len); 72 73 for (i = 0; i < num_masks; i++) 74 { 75 char *buff; 76 current = &masks[i]; 77 mask.deviceid = current->deviceid; 78 mask.mask_len = (current->mask_len + 3)/4; 79 /* masks.mask_len is in bytes, but we need 4-byte units on the wire, 80 * and they need to be padded with 0 */ 81 buff = calloc(1, mask.mask_len * 4); 82 memcpy(buff, current->mask, current->mask_len); 83 Data32(dpy, &mask, sizeof(xXIEventMask)); 84 Data(dpy, buff, mask.mask_len * 4); 85 free(buff); 86 } 87 88 UnlockDisplay(dpy); 89 SyncHandle(); 90 return Success; 91 92} 93 94XIEventMask* 95XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return) 96{ 97 int i, len = 0; 98 unsigned char *mask; 99 XIEventMask *mask_out = NULL; 100 xXIEventMask *mask_in = NULL, *mi; 101 xXIGetSelectedEventsReq *req; 102 xXIGetSelectedEventsReply reply; 103 104 XExtDisplayInfo *info = XInput_find_display(dpy); 105 LockDisplay(dpy); 106 if (_XiCheckExtInit(dpy, Dont_Check, info) == -1) 107 { 108 *num_masks_return = -1; 109 return NULL; 110 } 111 112 GetReq(XIGetSelectedEvents, req); 113 114 req->reqType = info->codes->major_opcode; 115 req->ReqType = X_XIGetSelectedEvents; 116 req->win = win; 117 118 if (!_XReply(dpy, (xReply *) &reply, 0, xFalse)) 119 goto error; 120 121 if (reply.num_masks == 0) 122 { 123 *num_masks_return = 0; 124 return NULL; 125 } 126 127 mask_in = Xmalloc(reply.length * 4); 128 if (!mask_in) 129 goto error; 130 131 _XRead(dpy, (char*)mask_in, reply.length * 4); 132 133 /* Memory layout of the XIEventMask for a 3 mask reply: 134 * [struct a][struct b][struct c][masks a][masks b][masks c] 135 */ 136 len = reply.num_masks * sizeof(XIEventMask); 137 138 for (i = 0, mi = mask_in; i < reply.num_masks; i++) 139 { 140 len += mi->mask_len * 4; 141 mi = (xXIEventMask*)((char*)mi + mi->mask_len * 4); 142 mi++; 143 } 144 145 mask_out = Xmalloc(len); 146 if (!mask_out) 147 goto error; 148 149 mi = mask_in; 150 mask = (unsigned char*)&mask_out[reply.num_masks]; 151 for (i = 0; i < reply.num_masks; i++) 152 { 153 mask_out[i].deviceid = mi->deviceid; 154 mask_out[i].mask_len = mi->mask_len * 4; 155 mask_out[i].mask = mask; 156 memcpy(mask_out[i].mask, &mi[1], mask_out[i].mask_len); 157 mask += mask_out[i].mask_len; 158 mi = (xXIEventMask*)((char*)mi + mi->mask_len * 4); 159 mi++; 160 } 161 162 *num_masks_return = reply.num_masks; 163 164 return mask_out; 165 166error: 167 if (mask_in) 168 Xfree(mask_in); 169 *num_masks_return = -1; 170 UnlockDisplay(dpy); 171 SyncHandle(); 172 return NULL; 173 174} 175