kbd.c revision 79a8a9c6
1/* 2 * Copyright (c) 2002 by The XFree86 Project, Inc. 3 * Author: Ivan Pascal. 4 * 5 * Based on the code from 6 * xf86Config.c which is 7 * Copyright 1991-2002 by The XFree86 Project, Inc. 8 * Copyright 1997 by Metro Link, Inc. 9 * xf86Events.c and xf86Io.c which are 10 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. 11 */ 12 13#ifdef HAVE_CONFIG_H 14#include "config.h" 15#endif 16 17#include <stdio.h> 18#include <string.h> 19#include <stdlib.h> 20#include <unistd.h> 21 22#define NEED_EVENTS 23#include <X11/X.h> 24#include <X11/Xproto.h> 25 26#include "xf86.h" 27#include "atKeynames.h" 28#include "xf86Privstr.h" 29 30#ifdef XINPUT 31#include <X11/extensions/XI.h> 32#include <X11/extensions/XIproto.h> 33#include "extnsionst.h" 34#include "extinit.h" 35#else 36#include "inputstr.h" 37#endif 38 39#include "xf86Xinput.h" 40#include "xf86_OSproc.h" 41#include "xf86OSKbd.h" 42#include "compiler.h" 43 44#ifdef XKB 45#include <X11/extensions/XKB.h> 46#include <X11/extensions/XKBstr.h> 47#include <X11/extensions/XKBsrv.h> 48#endif 49 50extern int XkbDfltRepeatDelay; 51extern int XkbDfltRepeatInterval; 52 53#define CAPSFLAG 1 54#define NUMFLAG 2 55#define SCROLLFLAG 4 56#define MODEFLAG 8 57#define COMPOSEFLAG 16 58/* Used to know when the first DEVICE_ON after a DEVICE_INIT is called */ 59#define INITFLAG (1 << 31) 60 61static InputInfoPtr KbdPreInit(InputDriverPtr drv, IDevPtr dev, int flags); 62static int KbdProc(DeviceIntPtr device, int what); 63static int KbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl); 64static void KbdBell(int percent, DeviceIntPtr dev, pointer ctrl, int unused); 65static void PostKbdEvent(InputInfoPtr pInfo, unsigned int key, Bool down); 66 67static void InitKBD(InputInfoPtr pInfo, Bool init); 68static void SetXkbOption(InputInfoPtr pInfo, char *name, char **option); 69static void UpdateLeds(InputInfoPtr pInfo); 70 71_X_EXPORT InputDriverRec KBD = { 72 1, 73 "kbd", 74 NULL, 75 KbdPreInit, 76 NULL, 77 NULL, 78 0 79}; 80 81_X_EXPORT InputDriverRec KEYBOARD = { 82 1, 83 "keyboard", 84 NULL, 85 KbdPreInit, 86 NULL, 87 NULL, 88 0 89}; 90 91typedef enum { 92 OPTION_ALWAYS_CORE, 93 OPTION_SEND_CORE_EVENTS, 94 OPTION_CORE_KEYBOARD, 95 OPTION_DEVICE, 96 OPTION_PROTOCOL, 97 OPTION_AUTOREPEAT, 98 OPTION_XLEDS, 99 OPTION_XKB_DISABLE, 100 OPTION_XKB_KEYMAP, 101 OPTION_XKB_KEYCODES, 102 OPTION_XKB_TYPES, 103 OPTION_XKB_COMPAT, 104 OPTION_XKB_SYMBOLS, 105 OPTION_XKB_GEOMETRY, 106 OPTION_XKB_RULES, 107 OPTION_XKB_MODEL, 108 OPTION_XKB_LAYOUT, 109 OPTION_XKB_VARIANT, 110 OPTION_XKB_OPTIONS, 111 OPTION_PANIX106, 112 OPTION_CUSTOM_KEYCODES 113} KeyboardOpts; 114 115/* These aren't actually used ... */ 116static const OptionInfoRec KeyboardOptions[] = { 117 { OPTION_ALWAYS_CORE, "AlwaysCore", OPTV_BOOLEAN, {0}, FALSE }, 118 { OPTION_SEND_CORE_EVENTS, "SendCoreEvents", OPTV_BOOLEAN, {0}, FALSE }, 119 { OPTION_CORE_KEYBOARD, "CoreKeyboard", OPTV_BOOLEAN, {0}, FALSE }, 120 { OPTION_DEVICE, "Device", OPTV_STRING, {0}, FALSE }, 121 { OPTION_PROTOCOL, "Protocol", OPTV_STRING, {0}, FALSE }, 122 { OPTION_AUTOREPEAT, "AutoRepeat", OPTV_STRING, {0}, FALSE }, 123 { OPTION_XLEDS, "XLeds", OPTV_STRING, {0}, FALSE }, 124 { OPTION_XKB_DISABLE, "XkbDisable", OPTV_BOOLEAN, {0}, FALSE }, 125 { OPTION_XKB_KEYMAP, "XkbKeymap", OPTV_STRING, {0}, FALSE }, 126 { OPTION_XKB_KEYCODES, "XkbKeycodes", OPTV_STRING, {0}, FALSE }, 127 { OPTION_XKB_TYPES, "XkbTypes", OPTV_STRING, {0}, FALSE }, 128 { OPTION_XKB_COMPAT, "XkbCompat", OPTV_STRING, {0}, FALSE }, 129 { OPTION_XKB_SYMBOLS, "XkbSymbols", OPTV_STRING, {0}, FALSE }, 130 { OPTION_XKB_GEOMETRY, "XkbGeometry", OPTV_STRING, {0}, FALSE }, 131 { OPTION_XKB_RULES, "XkbRules", OPTV_STRING, {0}, FALSE }, 132 { OPTION_XKB_MODEL, "XkbModel", OPTV_STRING, {0}, FALSE }, 133 { OPTION_XKB_LAYOUT, "XkbLayout", OPTV_STRING, {0}, FALSE }, 134 { OPTION_XKB_VARIANT, "XkbVariant", OPTV_STRING, {0}, FALSE }, 135 { OPTION_XKB_OPTIONS, "XkbOptions", OPTV_STRING, {0}, FALSE }, 136 { OPTION_PANIX106, "Panix106", OPTV_BOOLEAN, {0}, FALSE }, 137 { OPTION_CUSTOM_KEYCODES, "CustomKeycodes", OPTV_BOOLEAN, {0}, FALSE }, 138 { -1, NULL, OPTV_NONE, {0}, FALSE } 139}; 140 141static const char *kbdDefaults[] = { 142#ifdef XQUEUE 143 "Protocol", "Xqueue", 144#else 145 "Protocol", "standard", 146#endif 147 "AutoRepeat", "500 30", 148 "XkbRules", __XKBDEFRULES__, 149 "XkbModel", "pc105", 150 "XkbLayout", "us", 151 "Panix106", "off", 152 "CustomKeycodes", "off", 153 NULL 154}; 155 156static const char *kbd98Defaults[] = { 157#ifdef XQUEUE 158 "Protocol", "Xqueue", 159#else 160 "Protocol", "standard", 161#endif 162 "AutoRepeat", "500 30", 163 "XkbRules", "xfree98", 164 "XkbModel", "pc98", 165 "XkbLayout", "nec/jp", 166 "Panix106", "off", 167 "CustomKeycodes", "off", 168 NULL 169}; 170 171const char *xkbSymbols[] = { 172 "XkbDfltRepeatDelay", 173 "XkbDfltRepeatInterval", 174 NULL, 175}; 176 177#ifdef XKB 178static char *xkb_rules; 179static char *xkb_model; 180static char *xkb_layout; 181static char *xkb_variant; 182static char *xkb_options; 183 184static XkbComponentNamesRec xkbnames; 185#endif /* XKB */ 186 187/*ARGSUSED*/ 188static const OptionInfoRec * 189KeyboardAvailableOptions(void *unused) 190{ 191 return (KeyboardOptions); 192} 193 194static void 195SetXkbOption(InputInfoPtr pInfo, char *name, char **option) 196{ 197 char *s; 198 199 if ((s = xf86SetStrOption(pInfo->options, name, NULL))) { 200 if (!s[0]) { 201 xfree(s); 202 *option = NULL; 203 } else { 204 *option = s; 205 xf86Msg(X_CONFIG, "%s: %s: \"%s\"\n", pInfo->name, name, s); 206 } 207 } 208} 209 210 211#define ModifierIsSet(k) ((modifiers & (k)) == (k)) 212 213static Bool 214CommonSpecialKey(int key, Bool down, int modifiers) 215{ 216 if ((!ModifierIsSet(ShiftMask)) && 217 (((ModifierIsSet(ControlMask | AltMask)) || 218 (ModifierIsSet(ControlMask | AltLangMask))))) { 219 switch (key) { 220 221 case KEY_BackSpace: 222 xf86ProcessActionEvent(ACTION_TERMINATE, NULL); 223 break; 224 225 /* 226 * The idea here is to pass the scancode down to a list of 227 * registered routines. There should be some standard conventions 228 * for processing certain keys. 229 */ 230 case KEY_KP_Minus: /* Keypad - */ 231 if (down) xf86ProcessActionEvent(ACTION_PREV_MODE, NULL); 232 break; 233 234 case KEY_KP_Plus: /* Keypad + */ 235 if (down) xf86ProcessActionEvent(ACTION_NEXT_MODE, NULL); 236 break; 237 } 238 } 239 return FALSE; 240} 241 242 243static InputInfoPtr 244KbdPreInit(InputDriverPtr drv, IDevPtr dev, int flags) 245{ 246 InputInfoPtr pInfo; 247 KbdDevPtr pKbd; 248 MessageType from = X_DEFAULT; 249 char *s; 250 251 if (!(pInfo = xf86AllocateInput(drv, 0))) 252 return NULL; 253 254 /* Initialise the InputInfoRec. */ 255 pInfo->name = dev->identifier; 256 pInfo->type_name = XI_KEYBOARD; 257 pInfo->flags = XI86_KEYBOARD_CAPABLE; 258 pInfo->device_control = KbdProc; 259 /* 260 * We don't specify our own read_input function. We expect 261 * an OS specific readInput() function to handle this. 262 */ 263 pInfo->read_input = NULL; 264 pInfo->control_proc = NULL; 265 pInfo->close_proc = NULL; 266 pInfo->switch_mode = NULL; 267 pInfo->conversion_proc = NULL; 268 pInfo->reverse_conversion_proc = NULL; 269 pInfo->fd = -1; 270 pInfo->dev = NULL; 271 pInfo->private_flags = 0; 272 pInfo->always_core_feedback = 0; 273 pInfo->conf_idev = dev; 274 275 if (!xf86IsPc98()) 276 xf86CollectInputOptions(pInfo, kbdDefaults, NULL); 277 else 278 xf86CollectInputOptions(pInfo, kbd98Defaults, NULL); 279 xf86ProcessCommonOptions(pInfo, pInfo->options); 280 281 if (!(pKbd = xcalloc(sizeof(KbdDevRec), 1))) 282 return pInfo; 283 284 pInfo->private = pKbd; 285 pKbd->PostEvent = PostKbdEvent; 286 287 xf86LoaderReqSymLists(xkbSymbols, NULL); 288 289 if (!xf86OSKbdPreInit(pInfo)) 290 return pInfo; 291 292 if (!pKbd->OpenKeyboard(pInfo)) { 293 return pInfo; 294 } 295 296 if ((s = xf86SetStrOption(pInfo->options, "AutoRepeat", NULL))) { 297 int delay, rate; 298 if (sscanf(s, "%d %d", &delay, &rate) != 2) { 299 xf86Msg(X_ERROR, "\"%s\" is not a valid AutoRepeat value", s); 300 } else { 301 pKbd->delay = delay; 302 XkbDfltRepeatDelay = delay; 303 pKbd->rate = rate; 304 XkbDfltRepeatInterval = 1000/rate; 305 } 306 xfree(s); 307 } 308 309 if ((s = xf86SetStrOption(pInfo->options, "XLeds", NULL))) { 310 char *l, *end; 311 unsigned int i; 312 l = strtok(s, " \t\n"); 313 while (l) { 314 i = strtoul(l, &end, 0); 315 if (*end == '\0') 316 pKbd->xledsMask |= 1L << (i - 1); 317 else { 318 xf86Msg(X_ERROR, "\"%s\" is not a valid XLeds value", l); 319 } 320 l = strtok(NULL, " \t\n"); 321 } 322 xfree(s); 323 } 324 325#ifdef XKB 326 327/* XkbDisable must be a server flag but for compatibility we check it here */ 328 329 if (xf86FindOption(pInfo->options, "XkbDisable")) 330 xf86Msg(X_WARNING, 331 "%s: XKB can't be disabled here. Use \"ServerFlags\" section.\n", 332 pInfo->name); 333 334 pKbd->noXkb = noXkbExtension; 335 if (pKbd->noXkb) { 336 xf86Msg(X_CONFIG, "XKB: disabled\n"); 337 } else { 338 SetXkbOption(pInfo, "XkbKeymap", &xkbnames.keymap); 339 if (xkbnames.keymap) { 340 xf86Msg(X_CONFIG, "%s: XkbKeymap overrides all other XKB settings\n", 341 pInfo->name); 342 } else { 343 SetXkbOption(pInfo, "XkbRules", &xkb_rules); 344 SetXkbOption(pInfo, "XkbModel", &xkb_model); 345 SetXkbOption(pInfo, "XkbLayout", &xkb_layout); 346 SetXkbOption(pInfo, "XkbVariant", &xkb_variant); 347 SetXkbOption(pInfo, "XkbOptions", &xkb_options); 348 349 SetXkbOption(pInfo, "XkbKeycodes", &xkbnames.keycodes); 350 SetXkbOption(pInfo, "XkbTypes", &xkbnames.types); 351 SetXkbOption(pInfo, "XkbCompat", &xkbnames.compat); 352 SetXkbOption(pInfo, "XkbSymbols", &xkbnames.symbols); 353 SetXkbOption(pInfo, "XkbGeometry", &xkbnames.geometry); 354 } 355 } 356 357 if ((xkb_model && !strcmp(xkb_model, "sun")) || 358 (xkb_rules && !strcmp(xkb_rules, "sun"))) 359 pKbd->sunKbd = TRUE; 360#endif 361 362#if defined(SVR4) && defined(i386) 363 if ((pKbd->Panix106 = 364 xf86SetBoolOption(pInfo->options, "Panix106", FALSE))) { 365 xf86Msg(X_CONFIG, "%s: PANIX106: enabled\n", pInfo->name); 366 } 367#endif 368 369 pKbd->CustomKeycodes = FALSE; 370 from = X_DEFAULT; 371 if (xf86FindOption(pInfo->options, "CustomKeycodes")) { 372 pKbd->CustomKeycodes = xf86SetBoolOption(pInfo->options, "CustomKeycodes", 373 pKbd->CustomKeycodes); 374 from = X_CONFIG; 375 } 376 377 xf86Msg(from, "%s: CustomKeycodes %s\n", 378 pInfo->name, pKbd->CustomKeycodes ? "enabled" : "disabled"); 379 380 pInfo->flags |= XI86_CONFIGURED; 381 382 return pInfo; 383} 384 385static void 386KbdBell(int percent, DeviceIntPtr dev, pointer ctrl, int unused) 387{ 388 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 389 KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 390 pKbd->Bell(pInfo, percent, ((KeybdCtrl*) ctrl)->bell_pitch, 391 ((KeybdCtrl*) ctrl)->bell_duration); 392} 393 394static void 395UpdateLeds(InputInfoPtr pInfo) 396{ 397 KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 398 int leds = 0; 399 400 if (pKbd->keyLeds & CAPSFLAG) leds |= XLED1; 401 if (pKbd->keyLeds & NUMFLAG) leds |= XLED2; 402 if (pKbd->keyLeds & SCROLLFLAG || 403 pKbd->keyLeds & MODEFLAG) leds |= XLED3; 404 if (pKbd->keyLeds & COMPOSEFLAG) leds |= XLED4; 405 406 pKbd->leds = (pKbd->leds & pKbd->xledsMask) | (leds & ~pKbd->xledsMask); 407 pKbd->SetLeds(pInfo, pKbd->leds); 408} 409 410static int 411KbdCtrl( DeviceIntPtr device, KeybdCtrl *ctrl) 412{ 413 int leds; 414 InputInfoPtr pInfo = (InputInfoPtr) device->public.devicePrivate; 415 KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 416 417 if ( ctrl->leds & XLED1) { 418 pKbd->keyLeds |= CAPSFLAG; 419 } else { 420 pKbd->keyLeds &= ~CAPSFLAG; 421 } 422 if ( ctrl->leds & XLED2) { 423 pKbd->keyLeds |= NUMFLAG; 424 } else { 425 pKbd->keyLeds &= ~NUMFLAG; 426 } 427 if ( ctrl->leds & XLED3) { 428 pKbd->keyLeds |= SCROLLFLAG; 429 } else { 430 pKbd->keyLeds &= ~SCROLLFLAG; 431 } 432 if ( ctrl->leds & (XCOMP|XLED4) ) { 433 pKbd->keyLeds |= COMPOSEFLAG; 434 } else { 435 pKbd->keyLeds &= ~COMPOSEFLAG; 436 } 437 leds = ctrl->leds & ~(XCAPS | XNUM | XSCR); /* ??? */ 438#ifdef XKB 439 if (pKbd->noXkb) { 440#endif 441 pKbd->leds = (leds & pKbd->xledsMask) | (pKbd->leds & ~pKbd->xledsMask); 442#ifdef XKB 443 } else { 444 pKbd->leds = leds; 445 } 446#endif 447 pKbd->SetLeds(pInfo, pKbd->leds); 448 pKbd->autoRepeat = ctrl->autoRepeat; 449 450 return (Success); 451} 452 453static void 454InitKBD(InputInfoPtr pInfo, Bool init) 455{ 456 char rad; 457 xEvent kevent; 458 KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 459#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 1 460 DeviceIntPtr pKeyboard = pInfo->dev; 461 KeyClassRec *keyc = pKeyboard->key; 462 KeySym *map = keyc->curKeySyms.map; 463 unsigned int i; 464#endif 465 466 kevent.u.keyButtonPointer.time = GetTimeInMillis(); 467 kevent.u.keyButtonPointer.rootX = 0; 468 kevent.u.keyButtonPointer.rootY = 0; 469 470/* The server does this for us with i-h. */ 471#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 1 472 /* 473 * Hmm... here is the biggest hack of every time ! 474 * It may be possible that a switch-vt procedure has finished BEFORE 475 * you released all keys neccessary to do this. That peculiar behavior 476 * can fool the X-server pretty much, cause it assumes that some keys 477 * were not released. TWM may stuck alsmost completly.... 478 * OK, what we are doing here is after returning from the vt-switch 479 * exeplicitely unrelease all keyboard keys before the input-devices 480 * are reenabled. 481 */ 482 for (i = keyc->curKeySyms.minKeyCode, map = keyc->curKeySyms.map; 483 i < keyc->curKeySyms.maxKeyCode; 484 i++, map += keyc->curKeySyms.mapWidth) 485 if (KeyPressed(i)) 486 { 487 switch (*map) { 488 /* Don't release the lock keys */ 489 case XK_Caps_Lock: 490 case XK_Shift_Lock: 491 case XK_Num_Lock: 492 case XK_Scroll_Lock: 493 case XK_Kana_Lock: 494 break; 495 default: 496 kevent.u.u.detail = i; 497 kevent.u.u.type = KeyRelease; 498 (* pKeyboard->public.processInputProc)(&kevent, pKeyboard, 1); 499 } 500 } 501#endif 502 503 pKbd->scanPrefix = 0; 504 505 if (init) { 506 pKbd->keyLeds = pKbd->GetLeds(pInfo); 507 UpdateLeds(pInfo); 508 pKbd->keyLeds |= INITFLAG; 509 if( pKbd->delay <= 375) rad = 0x00; 510 else if (pKbd->delay <= 625) rad = 0x20; 511 else if (pKbd->delay <= 875) rad = 0x40; 512 else rad = 0x60; 513 if (pKbd->rate <= 2) rad |= 0x1F; 514 else if (pKbd->rate >= 30) rad |= 0x00; 515 else rad |= ((58 / pKbd->rate) - 2); 516 pKbd->SetKbdRepeat(pInfo, rad); 517 } else { 518 int leds = pKbd->keyLeds; 519 520 pKbd->keyLeds = pKbd->GetLeds(pInfo); 521 UpdateLeds(pInfo); 522 if ((pKbd->keyLeds & CAPSFLAG) != 523 ((leds & INITFLAG) ? 0 : (leds & CAPSFLAG))) { 524 pKbd->PostEvent(pInfo, KEY_CapsLock, TRUE); 525 pKbd->PostEvent(pInfo, KEY_CapsLock, FALSE); 526 } 527 if ((pKbd->keyLeds & NUMFLAG) != 528 (leds & INITFLAG ? 0 : leds & NUMFLAG)) { 529 pKbd->PostEvent(pInfo, KEY_NumLock, TRUE); 530 pKbd->PostEvent(pInfo, KEY_NumLock, FALSE); 531 } 532 } 533} 534 535static int 536KbdProc(DeviceIntPtr device, int what) 537{ 538 539 InputInfoPtr pInfo = device->public.devicePrivate; 540 KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 541 KeySymsRec keySyms; 542 CARD8 modMap[MAP_LENGTH]; 543 int ret; 544 545 switch (what) { 546 case DEVICE_INIT: 547 ret = pKbd->KbdInit(pInfo, what); 548 if (ret != Success) 549 return ret; 550 551 pKbd->KbdGetMapping(pInfo, &keySyms, modMap); 552 553 device->public.on = FALSE; 554#ifdef XKB 555 if (pKbd->noXkb) { 556#endif 557 InitKeyboardDeviceStruct((DevicePtr) device, 558 &keySyms, 559 modMap, 560 KbdBell, 561 (KbdCtrlProcPtr)KbdCtrl); 562#ifdef XKB 563 } else { 564 if (xkbnames.keymap) 565 xkb_rules = NULL; 566 XkbSetRulesDflts(xkb_rules, xkb_model, xkb_layout, 567 xkb_variant, xkb_options); 568 XkbInitKeyboardDeviceStruct(device, 569 &xkbnames, 570 &keySyms, 571 modMap, 572 KbdBell, 573 (KbdCtrlProcPtr)KbdCtrl); 574 } 575#endif 576 InitKBD(pInfo, TRUE); 577 break; 578 case DEVICE_ON: 579 if (device->public.on) 580 break; 581 /* 582 * Set the keyboard into "direct" mode and turn on 583 * event translation. 584 */ 585 if ((ret = pKbd->KbdOn(pInfo, what)) != Success) 586 return ret; 587 /* 588 * Discard any pending input after a VT switch to prevent the server 589 * passing on parts of the VT switch sequence. 590 */ 591 if (pInfo->fd >= 0) { 592 xf86FlushInput(pInfo->fd); 593 AddEnabledDevice(pInfo->fd); 594 } 595 596 device->public.on = TRUE; 597 InitKBD(pInfo, FALSE); 598 break; 599 600 case DEVICE_CLOSE: 601 case DEVICE_OFF: 602 603 /* 604 * Restore original keyboard directness and translation. 605 */ 606 if (pInfo->fd != -1) 607 RemoveEnabledDevice(pInfo->fd); 608 pKbd->KbdOff(pInfo, what); 609 device->public.on = FALSE; 610 break; 611 } 612 return (Success); 613} 614 615static void 616PostKbdEvent(InputInfoPtr pInfo, unsigned int scanCode, Bool down) 617{ 618 619 KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 620 DeviceIntPtr device = pInfo->dev; 621 KeyClassRec *keyc = device->key; 622 KbdFeedbackClassRec *kbdfeed = device->kbdfeed; 623 int specialkey = 0; 624 625 Bool UsePrefix = FALSE; 626 KeySym *keysym; 627 int keycode; 628 unsigned long changeLock = 0; 629 static int lockkeys = 0; 630 631#ifdef DEBUG 632 ErrorF("kbd driver rec scancode: 0x02%x %s\n", scanCode, down?"down":"up"); 633#endif 634 635 /* Disable any keyboard processing while in suspend */ 636 if (xf86inSuspend) 637 return; 638 639 if (pKbd->sunKbd) { 640 /* 641 * XXX XXX XXX: 642 * 643 * I really don't know what's wrong here, but passing the real 644 * scanCode offsets by one from XKB's point of view. 645 * 646 * (ecd@skynet.be, 980405) 647 */ 648 scanCode--; 649 goto sunKeyboards; 650 } 651 652 /* 653 * First do some special scancode remapping ... 654 */ 655 if (pKbd->RemapScanCode != NULL) { 656 if (pKbd->RemapScanCode(pInfo, (int*) &scanCode)) 657 return; 658 } else { 659 if (pKbd->scancodeMap != NULL) { 660 TransMapPtr map = pKbd->scancodeMap; 661 if (scanCode >= map->begin && scanCode < map->end) 662 scanCode = map->map[scanCode - map->begin]; 663 } 664 } 665 666 /* 667 * and now get some special keysequences 668 */ 669 670 specialkey = scanCode; 671 672 if (pKbd->GetSpecialKey != NULL) { 673 specialkey = pKbd->GetSpecialKey(pInfo, scanCode); 674 } else { 675 if (pKbd->specialMap != NULL) { 676 TransMapPtr map = pKbd->specialMap; 677 if (scanCode >= map->begin && scanCode < map->end) 678 specialkey = map->map[scanCode - map->begin]; 679 } 680 } 681 682#ifndef TERMINATE_FALLBACK 683#define TERMINATE_FALLBACK 0 684#endif 685#ifdef XKB 686 if (noXkbExtension 687#if TERMINATE_FALLBACK 688 || specialkey == KEY_BackSpace 689#endif 690 ) 691#endif 692 { 693 if (CommonSpecialKey(specialkey, down, keyc->state)) 694 return; 695 if (pKbd->SpecialKey != NULL) 696 if (pKbd->SpecialKey(pInfo, specialkey, down, keyc->state)) 697 return; 698 } 699 700#ifndef __sparc64__ 701 /* 702 * PC keyboards generate separate key codes for 703 * Alt+Print and Control+Pause but in the X keyboard model 704 * they need to get the same key code as the base key on the same 705 * physical keyboard key. 706 */ 707 if (!xf86IsPc98()) { 708 if (ModifierDown(AltMask) && (scanCode == KEY_SysReqest)) 709 scanCode = KEY_Print; 710 else if (scanCode == KEY_Break) 711 scanCode = KEY_Pause; 712 } 713#endif 714 715sunKeyboards: 716 /* 717 * Now map the scancodes to real X-keycodes ... 718 */ 719 keycode = scanCode + MIN_KEYCODE; 720 keysym = (keyc->curKeySyms.map + 721 keyc->curKeySyms.mapWidth * 722 (keycode - keyc->curKeySyms.minKeyCode)); 723 724#ifdef XKB 725 if (pKbd->noXkb) { 726#endif 727 /* 728 * Filter autorepeated caps/num/scroll lock keycodes. 729 */ 730 if( down ) { 731 switch( keysym[0] ) { 732 case XK_Caps_Lock : 733 if (lockkeys & CAPSFLAG) 734 return; 735 else 736 lockkeys |= CAPSFLAG; 737 break; 738 739 case XK_Num_Lock : 740 if (lockkeys & NUMFLAG) 741 return; 742 else 743 lockkeys |= NUMFLAG; 744 break; 745 746 case XK_Scroll_Lock : 747 if (lockkeys & SCROLLFLAG) 748 return; 749 else 750 lockkeys |= SCROLLFLAG; 751 break; 752 } 753 if (keysym[1] == XF86XK_ModeLock) 754 { 755 if (lockkeys & MODEFLAG) 756 return; 757 else 758 lockkeys |= MODEFLAG; 759 } 760 } 761 else { 762 switch( keysym[0] ) { 763 case XK_Caps_Lock : 764 lockkeys &= ~CAPSFLAG; 765 break; 766 767 case XK_Num_Lock : 768 lockkeys &= ~NUMFLAG; 769 break; 770 771 case XK_Scroll_Lock : 772 lockkeys &= ~SCROLLFLAG; 773 break; 774 } 775 if (keysym[1] == XF86XK_ModeLock) 776 lockkeys &= ~MODEFLAG; 777 } 778 779 /* 780 * LockKey special handling: 781 * ignore releases, toggle on & off on presses. 782 * Don't deal with the Caps_Lock keysym directly, but check the lock modifier 783 */ 784 785 if (keyc->modifierMap[keycode] & LockMask) 786 changeLock = CAPSFLAG; 787 if (keysym[0] == XK_Num_Lock) 788 changeLock = NUMFLAG; 789 if (keysym[0] == XK_Scroll_Lock) 790 changeLock = SCROLLFLAG; 791 if (keysym[1] == XF86XK_ModeLock) 792 changeLock = MODEFLAG; 793 794 if (changeLock) { 795 if (!down) 796 return; 797 798 pKbd->keyLeds &= ~changeLock; 799 800 if (KeyPressed(keycode)) { 801 down = !down; 802 } else { 803 pKbd->keyLeds |= changeLock; 804 } 805 UpdateLeds(pInfo); 806 } 807 808 if (!pKbd->CustomKeycodes) { 809 /* 810 * normal, non-keypad keys 811 */ 812 if (scanCode < KEY_KP_7 || scanCode > KEY_KP_Decimal) { 813#if !defined(CSRG_BASED) && \ 814 !defined(__GNU__) && \ 815 defined(KB_84) 816 /* 817 * magic ALT_L key on AT84 keyboards for multilingual support 818 */ 819 if (pKbd->kbdType == KB_84 && 820 ModifierDown(AltMask) && 821 keysym[2] != NoSymbol) 822 { 823 UsePrefix = TRUE; 824 } 825#endif /* !CSRG_BASED && ... */ 826 } 827 } 828#ifdef XKB 829 } 830#endif 831 832 /* 833 * check for an autorepeat-event 834 */ 835 if (down && KeyPressed(keycode)) { 836 int num = keycode >> 3; 837 int bit = 1 << (keycode & 7); 838 839 if ((pKbd->autoRepeat != AutoRepeatModeOn) || 840 keyc->modifierMap[keycode] || 841 !(kbdfeed->ctrl.autoRepeats[num] & bit)) 842 return; 843 } 844 845 if (UsePrefix) { 846 xf86PostKeyboardEvent(device, 847 keyc->modifierKeyMap[keyc->maxKeysPerModifier*7], TRUE); 848 xf86PostKeyboardEvent(device, keycode, down); 849 xf86PostKeyboardEvent(device, 850 keyc->modifierKeyMap[keyc->maxKeysPerModifier*7], FALSE); 851 } else { 852 xf86PostKeyboardEvent(device, keycode, down); 853 } 854} 855 856ModuleInfoRec KbdInfo = { 857 1, 858 "KBD", 859 NULL, 860 0, 861 KeyboardAvailableOptions, 862}; 863 864static void 865xf86KbdUnplug(pointer p) 866{ 867} 868 869static pointer 870xf86KbdPlug(pointer module, 871 pointer options, 872 int *errmaj, 873 int *errmin) 874{ 875 static Bool Initialised = FALSE; 876 877 if (!Initialised) 878 Initialised = TRUE; 879 880 xf86AddInputDriver(&KBD, module, 0); 881 882 return module; 883} 884 885static XF86ModuleVersionInfo xf86KbdVersionRec = 886{ 887 "kbd", 888 MODULEVENDORSTRING, 889 MODINFOSTRING1, 890 MODINFOSTRING2, 891 XORG_VERSION_CURRENT, 892 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, 893 ABI_CLASS_XINPUT, 894 ABI_XINPUT_VERSION, 895 MOD_CLASS_XINPUT, 896 {0, 0, 0, 0} /* signature, to be patched into the file by */ 897 /* a tool */ 898}; 899 900_X_EXPORT XF86ModuleData kbdModuleData = { 901 &xf86KbdVersionRec, 902 xf86KbdPlug, 903 xf86KbdUnplug 904}; 905