protocol-common.c (10281B)
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 /* Test relies on assert() */ 25 #undef NDEBUG 26 27 #ifdef HAVE_DIX_CONFIG_H 28 #include <dix-config.h> 29 #endif 30 31 #include <errno.h> 32 #include <stdint.h> 33 #include "extinit.h" /* for XInputExtensionInit */ 34 #include "exglobals.h" 35 #include "xkbsrv.h" /* for XkbInitPrivates */ 36 #include "xserver-properties.h" 37 #include "syncsrv.h" 38 #include <X11/extensions/XI2.h> 39 40 #define INSIDE_PROTOCOL_COMMON 41 #include "protocol-common.h" 42 43 struct devices devices; 44 ScreenRec screen; 45 WindowRec root; 46 WindowRec window; 47 static ClientRec server_client; 48 49 void *global_userdata; 50 51 void (*reply_handler) (ClientPtr client, int len, char *data, void *userdata); 52 53 int enable_GrabButton_wrap = 1; 54 int enable_XISetEventMask_wrap = 1; 55 56 static void 57 fake_init_sprite(DeviceIntPtr dev) 58 { 59 SpritePtr sprite; 60 61 sprite = dev->spriteInfo->sprite; 62 63 sprite->spriteTraceSize = 10; 64 sprite->spriteTrace = calloc(sprite->spriteTraceSize, sizeof(WindowPtr)); 65 sprite->spriteTraceGood = 1; 66 sprite->spriteTrace[0] = &root; 67 sprite->hot.x = SPRITE_X; 68 sprite->hot.y = SPRITE_Y; 69 sprite->hotPhys.x = sprite->hot.x; 70 sprite->hotPhys.y = sprite->hot.y; 71 sprite->win = &window; 72 sprite->hotPhys.pScreen = &screen; 73 sprite->physLimits.x1 = 0; 74 sprite->physLimits.y1 = 0; 75 sprite->physLimits.x2 = screen.width; 76 sprite->physLimits.y2 = screen.height; 77 } 78 79 /* This is essentially CorePointerProc with ScrollAxes added */ 80 static int 81 TestPointerProc(DeviceIntPtr pDev, int what) 82 { 83 #define NBUTTONS 10 84 #define NAXES 4 85 BYTE map[NBUTTONS + 1]; 86 int i = 0; 87 Atom btn_labels[NBUTTONS] = { 0 }; 88 Atom axes_labels[NAXES] = { 0 }; 89 90 switch (what) { 91 case DEVICE_INIT: 92 for (i = 1; i <= NBUTTONS; i++) 93 map[i] = i; 94 95 btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 96 btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 97 btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 98 btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); 99 btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); 100 btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); 101 btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); 102 /* don't know about the rest */ 103 104 axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 105 axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 106 axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL); 107 axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL); 108 109 if (!InitPointerDeviceStruct 110 ((DevicePtr) pDev, map, NBUTTONS, btn_labels, 111 (PtrCtrlProcPtr) NoopDDA, GetMotionHistorySize(), NAXES, 112 axes_labels)) { 113 ErrorF("Could not initialize device '%s'. Out of memory.\n", 114 pDev->name); 115 return BadAlloc; 116 } 117 pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; 118 pDev->last.valuators[0] = pDev->valuator->axisVal[0]; 119 pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; 120 pDev->last.valuators[1] = pDev->valuator->axisVal[1]; 121 122 /* protocol-xiquerydevice.c relies on these increment */ 123 SetScrollValuator(pDev, 2, SCROLL_TYPE_VERTICAL, 2.4, SCROLL_FLAG_NONE); 124 SetScrollValuator(pDev, 3, SCROLL_TYPE_HORIZONTAL, 3.5, 125 SCROLL_FLAG_PREFERRED); 126 break; 127 128 case DEVICE_CLOSE: 129 break; 130 131 default: 132 break; 133 } 134 135 return Success; 136 137 #undef NBUTTONS 138 #undef NAXES 139 } 140 141 /** 142 * Create and init 2 master devices (VCP + VCK) and two slave devices, one 143 * default mouse, one default keyboard. 144 */ 145 struct devices 146 init_devices(void) 147 { 148 ClientRec client; 149 struct devices local_devices; 150 int ret; 151 152 /* 153 * Put a unique name in display pointer so that when tests are run in 154 * parallel, their xkbcomp outputs to /tmp/server-<display>.xkm don't 155 * stomp on each other. 156 */ 157 #ifdef HAVE_GETPROGNAME 158 display = getprogname(); 159 #elif HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 160 display = program_invocation_short_name; 161 #endif 162 163 client = init_client(0, NULL); 164 165 AllocDevicePair(&client, "Virtual core", &local_devices.vcp, &local_devices.vck, 166 CorePointerProc, CoreKeyboardProc, TRUE); 167 inputInfo.pointer = local_devices.vcp; 168 169 inputInfo.keyboard = local_devices.vck; 170 ret = ActivateDevice(local_devices.vcp, FALSE); 171 assert(ret == Success); 172 /* This may fail if xkbcomp fails or xkb-config is not found. */ 173 ret = ActivateDevice(local_devices.vck, FALSE); 174 assert(ret == Success); 175 EnableDevice(local_devices.vcp, FALSE); 176 EnableDevice(local_devices.vck, FALSE); 177 178 AllocDevicePair(&client, "", &local_devices.mouse, &local_devices.kbd, 179 TestPointerProc, CoreKeyboardProc, FALSE); 180 ret = ActivateDevice(local_devices.mouse, FALSE); 181 assert(ret == Success); 182 ret = ActivateDevice(local_devices.kbd, FALSE); 183 assert(ret == Success); 184 EnableDevice(local_devices.mouse, FALSE); 185 EnableDevice(local_devices.kbd, FALSE); 186 187 local_devices.num_devices = 4; 188 local_devices.num_master_devices = 2; 189 190 fake_init_sprite(local_devices.mouse); 191 fake_init_sprite(local_devices.vcp); 192 193 return local_devices; 194 } 195 196 /* Create minimal client, with the given buffer and len as request buffer */ 197 ClientRec 198 init_client(int len, void *data) 199 { 200 ClientRec client = { 0 }; 201 202 /* we store the privates now and reassign it after the memset. this way 203 * we can share them across multiple test runs and don't have to worry 204 * about freeing them after each test run. */ 205 206 client.index = CLIENT_INDEX; 207 client.clientAsMask = CLIENT_MASK; 208 client.sequence = CLIENT_SEQUENCE; 209 client.req_len = len; 210 211 client.requestBuffer = data; 212 dixAllocatePrivates(&client.devPrivates, PRIVATE_CLIENT); 213 return client; 214 } 215 216 void 217 init_window(WindowPtr local_window, WindowPtr parent, int id) 218 { 219 memset(local_window, 0, sizeof(*local_window)); 220 221 local_window->drawable.id = id; 222 if (parent) { 223 local_window->drawable.x = 30; 224 local_window->drawable.y = 50; 225 local_window->drawable.width = 100; 226 local_window->drawable.height = 200; 227 } 228 local_window->parent = parent; 229 local_window->optional = calloc(1, sizeof(WindowOptRec)); 230 assert(local_window->optional); 231 } 232 233 extern DevPrivateKeyRec miPointerScreenKeyRec; 234 extern DevPrivateKeyRec miPointerPrivKeyRec; 235 236 /* Needed for the screen setup, otherwise we crash during sprite initialization */ 237 static Bool 238 device_cursor_init(DeviceIntPtr dev, ScreenPtr local_screen) 239 { 240 return TRUE; 241 } 242 243 static void 244 device_cursor_cleanup(DeviceIntPtr dev, ScreenPtr local_screen) 245 { 246 } 247 248 static Bool 249 set_cursor_pos(DeviceIntPtr dev, ScreenPtr local_screen, int x, int y, Bool event) 250 { 251 return TRUE; 252 } 253 254 void 255 init_simple(void) 256 { 257 screenInfo.numScreens = 1; 258 screenInfo.screens[0] = &screen; 259 260 screen.myNum = 0; 261 screen.id = 100; 262 screen.width = 640; 263 screen.height = 480; 264 screen.DeviceCursorInitialize = device_cursor_init; 265 screen.DeviceCursorCleanup = device_cursor_cleanup; 266 screen.SetCursorPosition = set_cursor_pos; 267 screen.root = &root; 268 269 dixResetPrivates(); 270 InitAtoms(); 271 XkbInitPrivates(); 272 dixRegisterPrivateKey(&XIClientPrivateKeyRec, PRIVATE_CLIENT, 273 sizeof(XIClientRec)); 274 dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0); 275 dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0); 276 XInputExtensionInit(); 277 278 init_window(&root, NULL, ROOT_WINDOW_ID); 279 init_window(&window, &root, CLIENT_WINDOW_ID); 280 281 serverClient = &server_client; 282 InitClient(serverClient, 0, (void *) NULL); 283 if (!InitClientResources(serverClient)) /* for root resources */ 284 FatalError("couldn't init server resources"); 285 SyncExtensionInit(); 286 287 devices = init_devices(); 288 } 289 290 void 291 __wrap_WriteToClient(ClientPtr client, int len, void *data) 292 { 293 assert(reply_handler != NULL); 294 295 (*reply_handler) (client, len, data, global_userdata); 296 } 297 298 /* dixLookupWindow requires a lot of setup not necessary for this test. 299 * Simple wrapper that returns either one of the fake root window or the 300 * fake client window. If the requested ID is neither of those wanted, 301 * return whatever the real dixLookupWindow does. 302 */ 303 int 304 __wrap_dixLookupWindow(WindowPtr *win, XID id, ClientPtr client, Mask access) 305 { 306 if (id == root.drawable.id) { 307 *win = &root; 308 return Success; 309 } 310 else if (id == window.drawable.id) { 311 *win = &window; 312 return Success; 313 } 314 315 return __real_dixLookupWindow(win, id, client, access); 316 } 317 318 extern ClientRec client_window; 319 320 int 321 __wrap_dixLookupClient(ClientPtr *pClient, XID rid, ClientPtr client, 322 Mask access) 323 { 324 if (rid == ROOT_WINDOW_ID) 325 return BadWindow; 326 327 if (rid == CLIENT_WINDOW_ID) { 328 *pClient = &client_window; 329 return Success; 330 } 331 332 return __real_dixLookupClient(pClient, rid, client, access); 333 }