diff -Nru xf86-input-keyboard-1.3.0.orig/src/kbd.c xf86-input-keyboard-1.3.0/src/kbd.c --- xf86-input-keyboard-1.3.0.orig/src/kbd.c 2008-03-21 03:55:18.000000000 +0900 +++ xf86-input-keyboard-1.3.0/src/kbd.c 2008-04-20 19:51:19.000000000 +0900 @@ -176,6 +176,30 @@ NULL, }; +static void AddMadKey(KbdDevPtr keyboard, int trigger, int transfer, MadKeyType type) +{ + MadKeyList *keyList = keyboard->madKeyList; + if (keyList != NULL) { + while (keyList->next != NULL) + keyList = keyList->next; + } + + MadKeyList *key = xcalloc(sizeof(MadKeyList), 1); + if (key == NULL) + return; + + key->madKey = &key->madKeyEntity; + key->madKey->trigger = trigger; + key->madKey->transfer = transfer; + key->madKey->type = type; + key->next = NULL; + + if (keyList == NULL) + keyboard->madKeyList = key; + else + keyList->next = key; +} + #ifdef XKB static char *xkb_rules; static char *xkb_model; @@ -346,6 +370,56 @@ xf86Msg(from, "%s: CustomKeycodes %s\n", pInfo->name, pKbd->CustomKeycodes ? "enabled" : "disabled"); + pKbd->madKeyList = NULL; + if (xf86FindOption(pInfo->options, "StickyShift")) { + AddMadKey(pKbd, KEY_ShiftL, KEY_ShiftL, MAD_KEY_STICKY); + AddMadKey(pKbd, KEY_ShiftR, KEY_ShiftR, MAD_KEY_STICKY); + xf86Msg(X_CONFIG, "%s: StickyShift enabled\n", pInfo->name); + } + if (xf86FindOption(pInfo->options, "StickyCtrl")) { + AddMadKey(pKbd, KEY_LCtrl, KEY_LCtrl, MAD_KEY_STICKY); + AddMadKey(pKbd, KEY_RCtrl, KEY_RCtrl, MAD_KEY_STICKY); + xf86Msg(X_CONFIG, "%s: StickyCtrl enabled\n", pInfo->name); + } + if (xf86FindOption(pInfo->options, "StickyAlt")) { + AddMadKey(pKbd, KEY_Alt, KEY_Alt, MAD_KEY_STICKY); + xf86Msg(X_CONFIG, "%s: StickyAlt enabled\n", pInfo->name); + } + if (xf86FindOption(pInfo->options, "PseudoModSpace")) { + int transfer = xf86SetIntOption(pInfo->options, + "PseudoModSpace", + MIN_KEYCODE) - MIN_KEYCODE; + AddMadKey(pKbd, KEY_Space, transfer, MAD_KEY_PSEUDO_MOD); + xf86Msg(X_CONFIG, "%s: PseudoModSpace enabled\n", pInfo->name); + } + if (xf86FindOption(pInfo->options, "OneShotShift")) { + int transfer = xf86SetIntOption(pInfo->options, + "OneShotShift", + MIN_KEYCODE) - MIN_KEYCODE; + AddMadKey(pKbd, KEY_ShiftL, transfer, MAD_KEY_ONE_SHOT_MOD); + AddMadKey(pKbd, KEY_ShiftR, transfer, MAD_KEY_ONE_SHOT_MOD); + xf86Msg(X_CONFIG, "%s: OneShotShift enabled\n", pInfo->name); + } + if (xf86FindOption(pInfo->options, "OneShotCtrl")) { + int transfer = xf86SetIntOption(pInfo->options, + "OneShotCtrl", + MIN_KEYCODE) - MIN_KEYCODE; + AddMadKey(pKbd, KEY_LCtrl, transfer, MAD_KEY_ONE_SHOT_MOD); + AddMadKey(pKbd, KEY_RCtrl, transfer, MAD_KEY_ONE_SHOT_MOD); +#ifdef XKB + if (xkb_options != NULL && strstr(xkb_options, "ctrl:swapcaps") != NULL) + AddMadKey(pKbd, KEY_CapsLock, transfer, MAD_KEY_ONE_SHOT_MOD); +#endif + xf86Msg(X_CONFIG, "%s: OneShotCtrl enabled\n", pInfo->name); + } + if (xf86FindOption(pInfo->options, "OneShotAlt")) { + int transfer = xf86SetIntOption(pInfo->options, + "OneShotAlt", + MIN_KEYCODE) - MIN_KEYCODE; + AddMadKey(pKbd, KEY_Alt, transfer, MAD_KEY_ONE_SHOT_MOD); + xf86Msg(X_CONFIG, "%s: OneShotAlt enabled\n", pInfo->name); + } + pInfo->flags |= XI86_CONFIGURED; return pInfo; @@ -491,6 +565,9 @@ pKbd->SetKbdRepeat(pInfo, rad); } else UpdateLeds(pInfo); + + pKbd->lastScanCode = 0; + pKbd->stickyPhase = 0; } static int @@ -582,6 +659,8 @@ KeyClassRec *keyc = device->key; KbdFeedbackClassRec *kbdfeed = device->kbdfeed; int specialkey = 0; + unsigned int tmpScanCode = 0; + unsigned int lastScanCode = pKbd->lastScanCode; Bool UsePrefix = FALSE; KeySym *keysym; @@ -674,6 +753,88 @@ #endif sunKeyboards: + tmpScanCode = scanCode; + + /* + * Sticky Key + */ + if (down) { + if (pKbd->stickyPhase == 1) { + pKbd->stickyPhase = 2; + xf86PostKeyboardEvent(device, pKbd->stickyScanCode + MIN_KEYCODE, TRUE); + goto madKeyFinish; + } else if (pKbd->stickyPhase == 2) { + pKbd->stickyPhase = 0; + xf86PostKeyboardEvent(device, pKbd->stickyScanCode + MIN_KEYCODE, FALSE); + goto madKeyFinish; + } + } else { + MadKeyList *keyList; + for (keyList = pKbd->madKeyList; keyList != NULL; keyList = keyList->next) { + MadKey *key = keyList->madKey; + if (key->type == MAD_KEY_STICKY + && key->trigger == scanCode + && lastScanCode == scanCode) { + if (pKbd->stickyPhase == -1) { /* ignore */ + pKbd->stickyPhase = 0; + break; + } else { + pKbd->stickyPhase = 1; + pKbd->stickyScanCode = keyList->madKey->transfer; + return; + } + } + } + } + + /* + * Pseudo Modifier + */ + { + MadKeyList *keyList; + for (keyList = pKbd->madKeyList; keyList != NULL; keyList = keyList->next) { + MadKey *key = keyList->madKey; + if (key->type == MAD_KEY_PSEUDO_MOD + && key->trigger == scanCode) { + if (lastScanCode == key->transfer) { + tmpScanCode = lastScanCode; + pKbd->stickyPhase = -1; + } else if (down) + scanCode = key->transfer; + else { + if (lastScanCode == scanCode) { + xf86PostKeyboardEvent(device, key->transfer + MIN_KEYCODE, FALSE); + xf86PostKeyboardEvent(device, key->trigger + MIN_KEYCODE, TRUE); + } else + scanCode = key->transfer; + } + goto madKeyFinish; + } + } + } + + /* + * One Shot Modifier + */ + if (!down) { + MadKeyList *keyList; + for (keyList = pKbd->madKeyList; keyList != NULL; keyList = keyList->next) { + MadKey *key = keyList->madKey; + if (key->type == MAD_KEY_ONE_SHOT_MOD + && key->trigger == scanCode + && lastScanCode == scanCode) { + scanCode = key->transfer; + xf86PostKeyboardEvent(device, lastScanCode + MIN_KEYCODE, FALSE); + xf86PostKeyboardEvent(device, scanCode + MIN_KEYCODE, TRUE); + goto madKeyFinish; + } + } + } + +madKeyFinish: + if (down) + pKbd->lastScanCode = tmpScanCode; + /* * Now map the scancodes to real X-keycodes ... */ diff -Nru xf86-input-keyboard-1.3.0.orig/src/xf86OSKbd.h xf86-input-keyboard-1.3.0/src/xf86OSKbd.h --- xf86-input-keyboard-1.3.0.orig/src/xf86OSKbd.h 2008-03-21 03:55:18.000000000 +0900 +++ xf86-input-keyboard-1.3.0/src/xf86OSKbd.h 2008-04-20 17:28:38.000000000 +0900 @@ -56,6 +56,24 @@ unsigned char *map; } TransMapRec, *TransMapPtr; +typedef enum { + MAD_KEY_STICKY, + MAD_KEY_PSEUDO_MOD, + MAD_KEY_ONE_SHOT_MOD, +} MadKeyType; + +typedef struct { + int trigger; + int transfer; + MadKeyType type; +} MadKey; + +typedef struct MadKeyList { + MadKey madKeyEntity; + MadKey *madKey; + struct MadKeyList *next; +} MadKeyList; + typedef struct { KbdInitProc KbdInit; KbdOnProc KbdOn; @@ -88,6 +106,17 @@ TransMapPtr scancodeMap; TransMapPtr specialMap; + int lastScanCode; + int stickyScanCode; + /* + * -1: ignore + * 0: disabled + * 1: presss enabled + * 2: release enabled + */ + int stickyPhase; + MadKeyList *madKeyList; + /* os specific */ pointer private; int kbdType;