1706f2543Smrg/* 2706f2543Smrg * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina. 3706f2543Smrg * 4706f2543Smrg * All Rights Reserved. 5706f2543Smrg * 6706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining 7706f2543Smrg * a copy of this software and associated documentation files (the 8706f2543Smrg * "Software"), to deal in the Software without restriction, including 9706f2543Smrg * without limitation on the rights to use, copy, modify, merge, 10706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software, 11706f2543Smrg * and to permit persons to whom the Software is furnished to do so, 12706f2543Smrg * subject to the following conditions: 13706f2543Smrg * 14706f2543Smrg * The above copyright notice and this permission notice (including the 15706f2543Smrg * next paragraph) shall be included in all copies or substantial 16706f2543Smrg * portions of the Software. 17706f2543Smrg * 18706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21706f2543Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22706f2543Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23706f2543Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25706f2543Smrg * SOFTWARE. 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * Authors: 30706f2543Smrg * David H. Dawes <dawes@xfree86.org> 31706f2543Smrg * Kevin E. Martin <kem@redhat.com> 32706f2543Smrg * Rickard E. (Rik) Faith <faith@redhat.com> 33706f2543Smrg */ 34706f2543Smrg 35706f2543Smrg/** \file 36706f2543Smrg * 37706f2543Smrg * This file implements common routines used by the backend and console 38706f2543Smrg * input devices. 39706f2543Smrg */ 40706f2543Smrg 41706f2543Smrg#ifdef HAVE_DMX_CONFIG_H 42706f2543Smrg#include <dmx-config.h> 43706f2543Smrg#endif 44706f2543Smrg 45706f2543Smrg#define DMX_STATE_DEBUG 0 46706f2543Smrg 47706f2543Smrg#include "dmxinputinit.h" 48706f2543Smrg#include "dmxcommon.h" 49706f2543Smrg#include "dmxconsole.h" 50706f2543Smrg#include "dmxprop.h" 51706f2543Smrg#include "dmxsync.h" 52706f2543Smrg#include "dmxmap.h" 53706f2543Smrg 54706f2543Smrg#include "inputstr.h" 55706f2543Smrg#include "input.h" 56706f2543Smrg#include <X11/keysym.h> 57706f2543Smrg#include "mipointer.h" 58706f2543Smrg#include "scrnintstr.h" 59706f2543Smrg 60706f2543Smrg#include <unistd.h> /* For usleep() */ 61706f2543Smrg 62706f2543Smrg#if DMX_STATE_DEBUG 63706f2543Smrg#define DMXDBG0(f) dmxLog(dmxDebug,f) 64706f2543Smrg#else 65706f2543Smrg#define DMXDBG0(f) 66706f2543Smrg#endif 67706f2543Smrg 68706f2543Smrg/** Each device has a private area that is visible only from inside the 69706f2543Smrg * driver code. */ 70706f2543Smrgtypedef struct _myPrivate { 71706f2543Smrg DMX_COMMON_PRIVATE; 72706f2543Smrg} myPrivate; 73706f2543Smrg 74706f2543Smrgstatic void dmxCommonKbdSetAR(Display *display, 75706f2543Smrg unsigned char *old, unsigned char *new) 76706f2543Smrg{ 77706f2543Smrg XKeyboardControl kc; 78706f2543Smrg XKeyboardState ks; 79706f2543Smrg unsigned long mask = KBKey | KBAutoRepeatMode; 80706f2543Smrg int i, j; 81706f2543Smrg int minKeycode, maxKeycode; 82706f2543Smrg 83706f2543Smrg if (!old) { 84706f2543Smrg XGetKeyboardControl(display, &ks); 85706f2543Smrg old = (unsigned char *)ks.auto_repeats; 86706f2543Smrg } 87706f2543Smrg 88706f2543Smrg XDisplayKeycodes(display, &minKeycode, &maxKeycode); 89706f2543Smrg for (i = 1; i < 32; i++) { 90706f2543Smrg if (!old || old[i] != new[i]) { 91706f2543Smrg for (j = 0; j < 8; j++) { 92706f2543Smrg if ((new[i] & (1 << j)) != (old[i] & (1 << j))) { 93706f2543Smrg kc.key = i * 8 + j; 94706f2543Smrg kc.auto_repeat_mode = ((new[i] & (1 << j)) 95706f2543Smrg ? AutoRepeatModeOn 96706f2543Smrg : AutoRepeatModeOff); 97706f2543Smrg if (kc.key >= minKeycode && kc.key <= maxKeycode) 98706f2543Smrg XChangeKeyboardControl(display, mask, &kc); 99706f2543Smrg } 100706f2543Smrg } 101706f2543Smrg } 102706f2543Smrg } 103706f2543Smrg} 104706f2543Smrg 105706f2543Smrgstatic void dmxCommonKbdSetLeds(Display *display, unsigned long new) 106706f2543Smrg{ 107706f2543Smrg int i; 108706f2543Smrg XKeyboardControl kc; 109706f2543Smrg 110706f2543Smrg for (i = 0; i < 32; i++) { 111706f2543Smrg kc.led = i + 1; 112706f2543Smrg kc.led_mode = (new & (1 << i)) ? LedModeOn : LedModeOff; 113706f2543Smrg XChangeKeyboardControl(display, KBLed | KBLedMode, &kc); 114706f2543Smrg } 115706f2543Smrg} 116706f2543Smrg 117706f2543Smrgstatic void dmxCommonKbdSetCtrl(Display *display, 118706f2543Smrg KeybdCtrl *old, KeybdCtrl *new) 119706f2543Smrg{ 120706f2543Smrg XKeyboardControl kc; 121706f2543Smrg unsigned long mask = KBKeyClickPercent | KBAutoRepeatMode; 122706f2543Smrg 123706f2543Smrg if (!old 124706f2543Smrg || old->click != new->click 125706f2543Smrg || old->autoRepeat != new->autoRepeat) { 126706f2543Smrg 127706f2543Smrg kc.key_click_percent = new->click; 128706f2543Smrg kc.auto_repeat_mode = new->autoRepeat; 129706f2543Smrg 130706f2543Smrg XChangeKeyboardControl(display, mask, &kc); 131706f2543Smrg } 132706f2543Smrg 133706f2543Smrg dmxCommonKbdSetLeds(display, new->leds); 134706f2543Smrg dmxCommonKbdSetAR(display, old ? old->autoRepeats : NULL, 135706f2543Smrg new->autoRepeats); 136706f2543Smrg} 137706f2543Smrg 138706f2543Smrgstatic void dmxCommonMouSetCtrl(Display *display, PtrCtrl *old, PtrCtrl *new) 139706f2543Smrg{ 140706f2543Smrg Bool do_accel, do_threshold; 141706f2543Smrg 142706f2543Smrg if (!old 143706f2543Smrg || old->num != new->num 144706f2543Smrg || old->den != new->den 145706f2543Smrg || old->threshold != new->threshold) { 146706f2543Smrg do_accel = (new->num > 0 && new->den > 0); 147706f2543Smrg do_threshold = (new->threshold > 0); 148706f2543Smrg if (do_accel || do_threshold) { 149706f2543Smrg XChangePointerControl(display, do_accel, do_threshold, 150706f2543Smrg new->num, new->den, new->threshold); 151706f2543Smrg } 152706f2543Smrg } 153706f2543Smrg} 154706f2543Smrg 155706f2543Smrg/** Update the keyboard control. */ 156706f2543Smrgvoid dmxCommonKbdCtrl(DevicePtr pDev, KeybdCtrl *ctrl) 157706f2543Smrg{ 158706f2543Smrg GETPRIVFROMPDEV; 159706f2543Smrg 160706f2543Smrg if (!priv->stateSaved && priv->be) dmxCommonSaveState(priv); 161706f2543Smrg if (!priv->display || !priv->stateSaved) return; 162706f2543Smrg dmxCommonKbdSetCtrl(priv->display, 163706f2543Smrg priv->kctrlset ? &priv->kctrl : NULL, 164706f2543Smrg ctrl); 165706f2543Smrg priv->kctrl = *ctrl; 166706f2543Smrg priv->kctrlset = 1; 167706f2543Smrg} 168706f2543Smrg 169706f2543Smrg/** Update the mouse control. */ 170706f2543Smrgvoid dmxCommonMouCtrl(DevicePtr pDev, PtrCtrl *ctrl) 171706f2543Smrg{ 172706f2543Smrg GETPRIVFROMPDEV; 173706f2543Smrg 174706f2543Smrg /* Don't set the acceleration for the 175706f2543Smrg * console, because that should be 176706f2543Smrg * controlled by the X server that the 177706f2543Smrg * console is running on. Otherwise, 178706f2543Smrg * the acceleration for the console 179706f2543Smrg * window would be unexpected for the 180706f2543Smrg * scale of the window. */ 181706f2543Smrg if (priv->be) { 182706f2543Smrg dmxCommonMouSetCtrl(priv->display, 183706f2543Smrg priv->mctrlset ? &priv->mctrl : NULL, 184706f2543Smrg ctrl); 185706f2543Smrg priv->mctrl = *ctrl; 186706f2543Smrg priv->mctrlset = 1; 187706f2543Smrg } 188706f2543Smrg} 189706f2543Smrg 190706f2543Smrg/** Sound they keyboard bell. */ 191706f2543Smrgvoid dmxCommonKbdBell(DevicePtr pDev, int percent, 192706f2543Smrg int volume, int pitch, int duration) 193706f2543Smrg{ 194706f2543Smrg GETPRIVFROMPDEV; 195706f2543Smrg XKeyboardControl kc; 196706f2543Smrg XKeyboardState ks; 197706f2543Smrg unsigned long mask = KBBellPercent | KBBellPitch | KBBellDuration; 198706f2543Smrg 199706f2543Smrg if (!priv->be) XGetKeyboardControl(priv->display, &ks); 200706f2543Smrg kc.bell_percent = volume; 201706f2543Smrg kc.bell_pitch = pitch; 202706f2543Smrg kc.bell_duration = duration; 203706f2543Smrg XChangeKeyboardControl(priv->display, mask, &kc); 204706f2543Smrg XBell(priv->display, percent); 205706f2543Smrg if (!priv->be) { 206706f2543Smrg kc.bell_percent = ks.bell_percent; 207706f2543Smrg kc.bell_pitch = ks.bell_pitch; 208706f2543Smrg kc.bell_duration = ks.bell_duration; 209706f2543Smrg XChangeKeyboardControl(priv->display, mask, &kc); 210706f2543Smrg } 211706f2543Smrg} 212706f2543Smrg 213706f2543Smrg/** Get the keyboard mapping. */ 214706f2543Smrgvoid dmxCommonKbdGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) 215706f2543Smrg{ 216706f2543Smrg GETPRIVFROMPDEV; 217706f2543Smrg int min_keycode; 218706f2543Smrg int max_keycode; 219706f2543Smrg int map_width; 220706f2543Smrg KeySym *keyboard_mapping; 221706f2543Smrg XModifierKeymap *modifier_mapping; 222706f2543Smrg int i, j; 223706f2543Smrg 224706f2543Smrg /* Compute pKeySyms. Cast 225706f2543Smrg * XGetKeyboardMapping because of 226706f2543Smrg * compiler warning on 64-bit machines. 227706f2543Smrg * We assume pointers to 32-bit and 228706f2543Smrg * 64-bit ints are the same. */ 229706f2543Smrg XDisplayKeycodes(priv->display, &min_keycode, &max_keycode); 230706f2543Smrg keyboard_mapping = (KeySym *)XGetKeyboardMapping(priv->display, 231706f2543Smrg min_keycode, 232706f2543Smrg max_keycode 233706f2543Smrg - min_keycode + 1, 234706f2543Smrg &map_width); 235706f2543Smrg pKeySyms->minKeyCode = min_keycode; 236706f2543Smrg pKeySyms->maxKeyCode = max_keycode; 237706f2543Smrg pKeySyms->mapWidth = map_width; 238706f2543Smrg pKeySyms->map = keyboard_mapping; 239706f2543Smrg 240706f2543Smrg 241706f2543Smrg /* Compute pModMap */ 242706f2543Smrg modifier_mapping = XGetModifierMapping(priv->display); 243706f2543Smrg for (i = 0; i < MAP_LENGTH; i++) 244706f2543Smrg pModMap[i] = 0; 245706f2543Smrg for (j = 0; j < 8; j++) { 246706f2543Smrg int max_keypermod = modifier_mapping->max_keypermod; 247706f2543Smrg 248706f2543Smrg for (i = 0; i < max_keypermod; i++) { 249706f2543Smrg CARD8 keycode = modifier_mapping->modifiermap[j*max_keypermod + i]; 250706f2543Smrg if (keycode) 251706f2543Smrg pModMap[keycode] |= 1 << j; 252706f2543Smrg } 253706f2543Smrg } 254706f2543Smrg XFreeModifiermap(modifier_mapping); 255706f2543Smrg} 256706f2543Smrg 257706f2543Smrg/** Fill in the XKEYBOARD parts of the \a info structure for the 258706f2543Smrg * specified \a pDev. */ 259706f2543Smrgvoid dmxCommonKbdGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) 260706f2543Smrg{ 261706f2543Smrg GETPRIVFROMPDEV; 262706f2543Smrg GETDMXINPUTFROMPRIV; 263706f2543Smrg char *pt; 264706f2543Smrg 265706f2543Smrg dmxCommonSaveState(priv); 266706f2543Smrg if (priv->xkb) { 267706f2543Smrg#define NAME(x) \ 268706f2543Smrg priv->xkb->names->x ? XGetAtomName(priv->display,priv->xkb->names->x) : NULL 269706f2543Smrg info->names.keycodes = NAME(keycodes); 270706f2543Smrg info->names.types = NAME(types); 271706f2543Smrg info->names.compat = NAME(compat); 272706f2543Smrg info->names.symbols = NAME(symbols); 273706f2543Smrg info->names.geometry = NAME(geometry); 274706f2543Smrg info->freenames = 1; 275706f2543Smrg#undef NAME 276706f2543Smrg dmxLogInput(dmxInput, 277706f2543Smrg "XKEYBOARD: keycodes = %s\n", info->names.keycodes); 278706f2543Smrg dmxLogInput(dmxInput, 279706f2543Smrg "XKEYBOARD: symbols = %s\n", info->names.symbols); 280706f2543Smrg dmxLogInput(dmxInput, 281706f2543Smrg "XKEYBOARD: geometry = %s\n", info->names.geometry); 282706f2543Smrg if ((pt = strchr(info->names.keycodes, '+'))) *pt = '\0'; 283706f2543Smrg } 284706f2543Smrg dmxCommonRestoreState(priv); 285706f2543Smrg} 286706f2543Smrg 287706f2543Smrg/** Turn \a pDev on (i.e., take input from \a pDev). */ 288706f2543Smrgint dmxCommonKbdOn(DevicePtr pDev) 289706f2543Smrg{ 290706f2543Smrg GETPRIVFROMPDEV; 291706f2543Smrg if (priv->be) dmxCommonSaveState(priv); 292706f2543Smrg priv->eventMask |= DMX_KEYBOARD_EVENT_MASK; 293706f2543Smrg XSelectInput(priv->display, priv->window, priv->eventMask); 294706f2543Smrg if (priv->be) 295706f2543Smrg XSetInputFocus(priv->display, priv->window, RevertToPointerRoot, 296706f2543Smrg CurrentTime); 297706f2543Smrg return -1; 298706f2543Smrg} 299706f2543Smrg 300706f2543Smrg/** Turn \a pDev off. */ 301706f2543Smrgvoid dmxCommonKbdOff(DevicePtr pDev) 302706f2543Smrg{ 303706f2543Smrg GETPRIVFROMPDEV; 304706f2543Smrg priv->eventMask &= ~DMX_KEYBOARD_EVENT_MASK; 305706f2543Smrg XSelectInput(priv->display, priv->window, priv->eventMask); 306706f2543Smrg dmxCommonRestoreState(priv); 307706f2543Smrg} 308706f2543Smrg 309706f2543Smrg/** Turn \a pDev on (i.e., take input from \a pDev). */ 310706f2543Smrgint dmxCommonOthOn(DevicePtr pDev) 311706f2543Smrg{ 312706f2543Smrg GETPRIVFROMPDEV; 313706f2543Smrg GETDMXINPUTFROMPRIV; 314706f2543Smrg XEventClass event_list[DMX_MAX_XINPUT_EVENT_TYPES]; 315706f2543Smrg int event_type[DMX_MAX_XINPUT_EVENT_TYPES]; 316706f2543Smrg int count = 0; 317706f2543Smrg 318706f2543Smrg#define ADD(type) \ 319706f2543Smrg if (count < DMX_MAX_XINPUT_EVENT_TYPES) { \ 320706f2543Smrg type(priv->xi, event_type[count], event_list[count]); \ 321706f2543Smrg if (event_type[count]) { \ 322706f2543Smrg dmxMapInsert(dmxLocal, event_type[count], XI_##type); \ 323706f2543Smrg ++count; \ 324706f2543Smrg } \ 325706f2543Smrg } else { \ 326706f2543Smrg dmxLog(dmxWarning, "More than %d event types for %s\n", \ 327706f2543Smrg DMX_MAX_XINPUT_EVENT_TYPES, dmxInput->name); \ 328706f2543Smrg } 329706f2543Smrg 330706f2543Smrg if (!(priv->xi = XOpenDevice(priv->display, dmxLocal->deviceId))) { 331706f2543Smrg dmxLog(dmxWarning, "Cannot open %s device (id=%d) on %s\n", 332706f2543Smrg dmxLocal->deviceName ? dmxLocal->deviceName : "(unknown)", 333706f2543Smrg dmxLocal->deviceId, dmxInput->name); 334706f2543Smrg return -1; 335706f2543Smrg } 336706f2543Smrg ADD(DeviceKeyPress); 337706f2543Smrg ADD(DeviceKeyRelease); 338706f2543Smrg ADD(DeviceButtonPress); 339706f2543Smrg ADD(DeviceButtonRelease); 340706f2543Smrg ADD(DeviceMotionNotify); 341706f2543Smrg ADD(DeviceFocusIn); 342706f2543Smrg ADD(DeviceFocusOut); 343706f2543Smrg ADD(ProximityIn); 344706f2543Smrg ADD(ProximityOut); 345706f2543Smrg ADD(DeviceStateNotify); 346706f2543Smrg ADD(DeviceMappingNotify); 347706f2543Smrg ADD(ChangeDeviceNotify); 348706f2543Smrg XSelectExtensionEvent(priv->display, priv->window, event_list, count); 349706f2543Smrg 350706f2543Smrg return -1; 351706f2543Smrg} 352706f2543Smrg 353706f2543Smrg/** Turn \a pDev off. */ 354706f2543Smrgvoid dmxCommonOthOff(DevicePtr pDev) 355706f2543Smrg{ 356706f2543Smrg GETPRIVFROMPDEV; 357706f2543Smrg 358706f2543Smrg if (priv->xi) XCloseDevice(priv->display, priv->xi); 359706f2543Smrg priv->xi = NULL; 360706f2543Smrg} 361706f2543Smrg 362706f2543Smrg/** Fill the \a info structure with information needed to initialize \a 363706f2543Smrg * pDev. */ 364706f2543Smrgvoid dmxCommonOthGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) 365706f2543Smrg{ 366706f2543Smrg GETPRIVFROMPDEV; 367706f2543Smrg GETDMXINPUTFROMPRIV; 368706f2543Smrg XExtensionVersion *ext; 369706f2543Smrg XDeviceInfo *devices; 370706f2543Smrg Display *display = priv->display; 371706f2543Smrg int num; 372706f2543Smrg int i, j, k; 373706f2543Smrg XextErrorHandler handler; 374706f2543Smrg 375706f2543Smrg if (!display && !(display = XOpenDisplay(dmxInput->name))) 376706f2543Smrg return; 377706f2543Smrg 378706f2543Smrg /* Print out information about the XInput Extension. */ 379706f2543Smrg handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler); 380706f2543Smrg ext = XGetExtensionVersion(display, INAME); 381706f2543Smrg XSetExtensionErrorHandler(handler); 382706f2543Smrg 383706f2543Smrg if (ext && ext != (XExtensionVersion *)NoSuchExtension) { 384706f2543Smrg XFree(ext); 385706f2543Smrg devices = XListInputDevices(display, &num); 386706f2543Smrg for (i = 0; i < num; i++) { 387706f2543Smrg if (devices[i].id == (XID)dmxLocal->deviceId) { 388706f2543Smrg XAnyClassPtr any; 389706f2543Smrg XKeyInfoPtr ki; 390706f2543Smrg XButtonInfoPtr bi; 391706f2543Smrg XValuatorInfoPtr vi; 392706f2543Smrg for (j = 0, any = devices[i].inputclassinfo; 393706f2543Smrg j < devices[i].num_classes; 394706f2543Smrg any = (XAnyClassPtr)((char *)any + any->length), j++) { 395706f2543Smrg switch (any->class) { 396706f2543Smrg case KeyClass: 397706f2543Smrg ki = (XKeyInfoPtr)any; 398706f2543Smrg info->keyboard = 1; 399706f2543Smrg info->keyClass = 1; 400706f2543Smrg info->keySyms.minKeyCode = ki->min_keycode; 401706f2543Smrg info->keySyms.maxKeyCode = ki->max_keycode; 402706f2543Smrg info->kbdFeedbackClass = 1; 403706f2543Smrg break; 404706f2543Smrg case ButtonClass: 405706f2543Smrg bi = (XButtonInfoPtr)any; 406706f2543Smrg info->buttonClass = 1; 407706f2543Smrg info->numButtons = bi->num_buttons; 408706f2543Smrg info->ptrFeedbackClass = 1; 409706f2543Smrg break; 410706f2543Smrg case ValuatorClass: 411706f2543Smrg /* This assume all axes are either 412706f2543Smrg * Absolute or Relative. */ 413706f2543Smrg vi = (XValuatorInfoPtr)any; 414706f2543Smrg info->valuatorClass = 1; 415706f2543Smrg if (vi->mode == Absolute) 416706f2543Smrg info->numAbsAxes = vi->num_axes; 417706f2543Smrg else 418706f2543Smrg info->numRelAxes = vi->num_axes; 419706f2543Smrg for (k = 0; k < vi->num_axes; k++) { 420706f2543Smrg info->res[k] = vi->axes[k].resolution; 421706f2543Smrg info->minres[k] = vi->axes[k].resolution; 422706f2543Smrg info->maxres[k] = vi->axes[k].resolution; 423706f2543Smrg info->minval[k] = vi->axes[k].min_value; 424706f2543Smrg info->maxval[k] = vi->axes[k].max_value; 425706f2543Smrg } 426706f2543Smrg break; 427706f2543Smrg case FeedbackClass: 428706f2543Smrg /* Only keyboard and pointer feedback 429706f2543Smrg * are handled at this time. */ 430706f2543Smrg break; 431706f2543Smrg case ProximityClass: 432706f2543Smrg info->proximityClass = 1; 433706f2543Smrg break; 434706f2543Smrg case FocusClass: 435706f2543Smrg info->focusClass = 1; 436706f2543Smrg break; 437706f2543Smrg case OtherClass: 438706f2543Smrg break; 439706f2543Smrg } 440706f2543Smrg } 441706f2543Smrg } 442706f2543Smrg } 443706f2543Smrg XFreeDeviceList(devices); 444706f2543Smrg } 445706f2543Smrg if (display != priv->display) XCloseDisplay(display); 446706f2543Smrg} 447706f2543Smrg 448706f2543Smrg/** Obtain the mouse button mapping. */ 449706f2543Smrgvoid dmxCommonMouGetMap(DevicePtr pDev, unsigned char *map, int *nButtons) 450706f2543Smrg{ 451706f2543Smrg GETPRIVFROMPDEV; 452706f2543Smrg int i; 453706f2543Smrg 454706f2543Smrg *nButtons = XGetPointerMapping(priv->display, map, DMX_MAX_BUTTONS); 455706f2543Smrg for (i = 0; i <= *nButtons; i++) map[i] = i; 456706f2543Smrg} 457706f2543Smrg 458706f2543Smrgstatic void *dmxCommonXSelect(DMXScreenInfo *dmxScreen, void *closure) 459706f2543Smrg{ 460706f2543Smrg myPrivate *priv = closure; 461706f2543Smrg XSelectInput(dmxScreen->beDisplay, dmxScreen->scrnWin, priv->eventMask); 462706f2543Smrg return NULL; 463706f2543Smrg} 464706f2543Smrg 465706f2543Smrgstatic void *dmxCommonAddEnabledDevice(DMXScreenInfo *dmxScreen, void *closure) 466706f2543Smrg{ 467706f2543Smrg AddEnabledDevice(XConnectionNumber(dmxScreen->beDisplay)); 468706f2543Smrg return NULL; 469706f2543Smrg} 470706f2543Smrg 471706f2543Smrgstatic void *dmxCommonRemoveEnabledDevice(DMXScreenInfo *dmxScreen, 472706f2543Smrg void *closure) 473706f2543Smrg{ 474706f2543Smrg RemoveEnabledDevice(XConnectionNumber(dmxScreen->beDisplay)); 475706f2543Smrg return NULL; 476706f2543Smrg} 477706f2543Smrg 478706f2543Smrg/** Turn \a pDev on (i.e., take input from \a pDev). */ 479706f2543Smrgint dmxCommonMouOn(DevicePtr pDev) 480706f2543Smrg{ 481706f2543Smrg GETPRIVFROMPDEV; 482706f2543Smrg GETDMXINPUTFROMPRIV; 483706f2543Smrg 484706f2543Smrg priv->eventMask |= DMX_POINTER_EVENT_MASK; 485706f2543Smrg if (dmxShadowFB) { 486706f2543Smrg XWarpPointer(priv->display, priv->window, priv->window, 487706f2543Smrg 0, 0, 0, 0, 488706f2543Smrg priv->initPointerX, 489706f2543Smrg priv->initPointerY); 490706f2543Smrg dmxSync(&dmxScreens[dmxInput->scrnIdx], TRUE); 491706f2543Smrg } 492706f2543Smrg if (!priv->be) { 493706f2543Smrg XSelectInput(priv->display, priv->window, priv->eventMask); 494706f2543Smrg AddEnabledDevice(XConnectionNumber(priv->display)); 495706f2543Smrg } else { 496706f2543Smrg dmxPropertyIterate(priv->be, dmxCommonXSelect, priv); 497706f2543Smrg dmxPropertyIterate(priv->be, dmxCommonAddEnabledDevice, dmxInput); 498706f2543Smrg } 499706f2543Smrg 500706f2543Smrg return -1; 501706f2543Smrg} 502706f2543Smrg 503706f2543Smrg/** Turn \a pDev off. */ 504706f2543Smrgvoid dmxCommonMouOff(DevicePtr pDev) 505706f2543Smrg{ 506706f2543Smrg GETPRIVFROMPDEV; 507706f2543Smrg GETDMXINPUTFROMPRIV; 508706f2543Smrg 509706f2543Smrg priv->eventMask &= ~DMX_POINTER_EVENT_MASK; 510706f2543Smrg if (!priv->be) { 511706f2543Smrg RemoveEnabledDevice(XConnectionNumber(priv->display)); 512706f2543Smrg XSelectInput(priv->display, priv->window, priv->eventMask); 513706f2543Smrg } else { 514706f2543Smrg dmxPropertyIterate(priv->be, dmxCommonRemoveEnabledDevice, dmxInput); 515706f2543Smrg dmxPropertyIterate(priv->be, dmxCommonXSelect, priv); 516706f2543Smrg } 517706f2543Smrg} 518706f2543Smrg 519706f2543Smrg/** Given the global coordinates \a x and \a y, determine the screen 520706f2543Smrg * with the lowest number on which those coordinates lie. If they are 521706f2543Smrg * not on any screen, return -1. The number returned is an index into 522706f2543Smrg * \a dmxScreenInfo and is between -1 and \a dmxNumScreens - 1, 523706f2543Smrg * inclusive. */ 524706f2543Smrgint dmxFindPointerScreen(int x, int y) 525706f2543Smrg{ 526706f2543Smrg int i; 527706f2543Smrg 528706f2543Smrg for (i = 0; i < dmxNumScreens; i++) { 529706f2543Smrg ScreenPtr pScreen = screenInfo.screens[i]; 530706f2543Smrg if (x >= pScreen->x && x < pScreen->x + pScreen->width && 531706f2543Smrg y >= pScreen->y && y < pScreen->y + pScreen->height) 532706f2543Smrg return i; 533706f2543Smrg } 534706f2543Smrg return -1; 535706f2543Smrg} 536706f2543Smrg 537706f2543Smrg/** Returns a pointer to the private area for the device that comes just 538706f2543Smrg * prior to \a pDevice in the current \a dmxInput device list. This is 539706f2543Smrg * used as the private area for the current device in some situations 540706f2543Smrg * (e.g., when a keyboard and mouse form a pair that should share the 541706f2543Smrg * same private area). If the requested private area cannot be located, 542706f2543Smrg * then NULL is returned. */ 543706f2543Smrgpointer dmxCommonCopyPrivate(DeviceIntPtr pDevice) 544706f2543Smrg{ 545706f2543Smrg GETDMXLOCALFROMPDEVICE; 546706f2543Smrg DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx]; 547706f2543Smrg int i; 548706f2543Smrg 549706f2543Smrg for (i = 0; i < dmxInput->numDevs; i++) 550706f2543Smrg if (dmxInput->devs[i] == dmxLocal && i) 551706f2543Smrg return dmxInput->devs[i-1]->private; 552706f2543Smrg return NULL; 553706f2543Smrg} 554706f2543Smrg 555706f2543Smrg/** This routine saves and resets some important state for the backend 556706f2543Smrg * and console device drivers: 557706f2543Smrg * - the modifier map is saved and set to 0 (so DMX controls the LEDs) 558706f2543Smrg * - the key click, bell, led, and repeat masks are saved and set to the 559706f2543Smrg * values that DMX claims to be using 560706f2543Smrg * 561706f2543Smrg * This routine and #dmxCommonRestoreState are used when the pointer 562706f2543Smrg * enters and leaves the console window, or when the backend window is 563706f2543Smrg * active or not active (for a full-screen window, this only happens at 564706f2543Smrg * server startup and server shutdown). 565706f2543Smrg */ 566706f2543Smrgvoid dmxCommonSaveState(pointer private) 567706f2543Smrg{ 568706f2543Smrg GETPRIVFROMPRIVATE; 569706f2543Smrg XKeyboardState ks; 570706f2543Smrg unsigned long i; 571706f2543Smrg XModifierKeymap *modmap; 572706f2543Smrg 573706f2543Smrg if (dmxInput->console) priv = dmxInput->devs[0]->private; 574706f2543Smrg if (!priv->display || priv->stateSaved) return; 575706f2543Smrg DMXDBG0("dmxCommonSaveState\n"); 576706f2543Smrg if (dmxUseXKB && (priv->xkb = XkbAllocKeyboard())) { 577706f2543Smrg if (XkbGetIndicatorMap(priv->display, XkbAllIndicatorsMask, priv->xkb) 578706f2543Smrg || XkbGetNames(priv->display, XkbAllNamesMask, priv->xkb)) { 579706f2543Smrg dmxLogInput(dmxInput, "Could not get XKB information\n"); 580706f2543Smrg XkbFreeKeyboard(priv->xkb, 0, True); 581706f2543Smrg priv->xkb = NULL; 582706f2543Smrg } else { 583706f2543Smrg if (priv->xkb->indicators) { 584706f2543Smrg priv->savedIndicators = *priv->xkb->indicators; 585706f2543Smrg for (i = 0; i < XkbNumIndicators; i++) 586706f2543Smrg if (priv->xkb->indicators->phys_indicators & (1 << i)) { 587706f2543Smrg priv->xkb->indicators->maps[i].flags 588706f2543Smrg = XkbIM_NoAutomatic; 589706f2543Smrg } 590706f2543Smrg XkbSetIndicatorMap(priv->display, ~0, priv->xkb); 591706f2543Smrg } 592706f2543Smrg } 593706f2543Smrg } 594706f2543Smrg 595706f2543Smrg XGetKeyboardControl(priv->display, &ks); 596706f2543Smrg priv->savedKctrl.click = ks.key_click_percent; 597706f2543Smrg priv->savedKctrl.bell = ks.bell_percent; 598706f2543Smrg priv->savedKctrl.bell_pitch = ks.bell_pitch; 599706f2543Smrg priv->savedKctrl.bell_duration = ks.bell_duration; 600706f2543Smrg priv->savedKctrl.leds = ks.led_mask; 601706f2543Smrg priv->savedKctrl.autoRepeat = ks.global_auto_repeat; 602706f2543Smrg for (i = 0; i < 32; i++) 603706f2543Smrg priv->savedKctrl.autoRepeats[i] = ks.auto_repeats[i]; 604706f2543Smrg 605706f2543Smrg dmxCommonKbdSetCtrl(priv->display, &priv->savedKctrl, 606706f2543Smrg &priv->dmxLocal->kctrl); 607706f2543Smrg 608706f2543Smrg priv->savedModMap = XGetModifierMapping(priv->display); 609706f2543Smrg 610706f2543Smrg modmap = XNewModifiermap(0); 611706f2543Smrg XSetModifierMapping(priv->display, modmap); 612706f2543Smrg if (dmxInput->scrnIdx != -1) 613706f2543Smrg dmxSync(&dmxScreens[dmxInput->scrnIdx], TRUE); 614706f2543Smrg XFreeModifiermap(modmap); 615706f2543Smrg 616706f2543Smrg priv->stateSaved = 1; 617706f2543Smrg} 618706f2543Smrg 619706f2543Smrg/** This routine restores all the information saved by #dmxCommonSaveState. */ 620706f2543Smrgvoid dmxCommonRestoreState(pointer private) 621706f2543Smrg{ 622706f2543Smrg GETPRIVFROMPRIVATE; 623706f2543Smrg int retcode = -1; 624706f2543Smrg CARD32 start; 625706f2543Smrg 626706f2543Smrg if (dmxInput->console) 627706f2543Smrg priv = dmxInput->devs[0]->private; 628706f2543Smrg if (!priv->stateSaved) 629706f2543Smrg return; 630706f2543Smrg priv->stateSaved = 0; 631706f2543Smrg 632706f2543Smrg DMXDBG0("dmxCommonRestoreState\n"); 633706f2543Smrg if (priv->xkb) { 634706f2543Smrg *priv->xkb->indicators = priv->savedIndicators; 635706f2543Smrg XkbSetIndicatorMap(priv->display, ~0, priv->xkb); 636706f2543Smrg XkbFreeKeyboard(priv->xkb, 0, True); 637706f2543Smrg priv->xkb = 0; 638706f2543Smrg } 639706f2543Smrg 640706f2543Smrg for (start = GetTimeInMillis(); GetTimeInMillis() - start < 5000;) { 641706f2543Smrg CARD32 tmp; 642706f2543Smrg 643706f2543Smrg retcode = XSetModifierMapping(priv->display, priv->savedModMap); 644706f2543Smrg if (retcode == MappingSuccess) 645706f2543Smrg break; 646706f2543Smrg if (retcode == MappingBusy) 647706f2543Smrg dmxLogInput(dmxInput, "Keyboard busy, waiting\n"); 648706f2543Smrg else 649706f2543Smrg dmxLogInput(dmxInput, "Keyboard error, waiting\n"); 650706f2543Smrg 651706f2543Smrg /* Don't generate X11 protocol for a bit */ 652706f2543Smrg for (tmp = GetTimeInMillis(); GetTimeInMillis() - tmp < 250;) { 653706f2543Smrg usleep(250); /* This ends up sleeping only until 654706f2543Smrg * the next key press generates an 655706f2543Smrg * interruption. We make the delay 656706f2543Smrg * relatively short in case the user 657706f2543Smrg * pressed they keys quickly. */ 658706f2543Smrg } 659706f2543Smrg 660706f2543Smrg } 661706f2543Smrg if (retcode != MappingSuccess) 662706f2543Smrg dmxLog(dmxWarning, "Unable to restore keyboard modifier state!\n"); 663706f2543Smrg 664706f2543Smrg XFreeModifiermap(priv->savedModMap); 665706f2543Smrg priv->savedModMap = NULL; 666706f2543Smrg 667706f2543Smrg dmxCommonKbdSetCtrl(priv->display, NULL, &priv->savedKctrl); 668706f2543Smrg priv->kctrlset = 0; /* Invalidate copy */ 669706f2543Smrg} 670