xf86-input-evdev-2.5.0 のSandS用パッチ

追記(2011年2月21日)

定家さんこの記事のコードの改良版をgitに公開(下のURL)してくださいました。 http://gitorious.org/at-home-modifier しっかりとしたREADMEなどが付随しているので、現状ではそちらのコードを使用したほうが良いでしょう。 (追記終わり)

Linux で SandS の実現を目指す : xf86-input-evdev の修正(メモ) – 落書き、時々落学 を最新用にした. つまり,evdevがアップデートされたので,それに対応. といっても,ほぼ何もしていない. xcalloc が deprecated されたらしいので,とりあえず calloc に変えておいたぐらい.

PKGBUILD

pkgname=xf86-input-evdev
pkgver=2.5.0
pkgrel=1
pkgdesc=“X.org evdev input driver”
arch=(i686 x86_64)
url=“http://xorg.freedesktop.org/"
license=(‘custom’)
depends=(‘glibc’)
makedepends=(‘xorg-server-devel’)
conflicts=(‘xorg-server<1.9.0’)
options=(‘!libtool’ !makeflags)
groups=(‘xorg-input-drivers’)
source=(${url}/releases/individual/driver/${pkgname}-${pkgver}.tar.bz2
${pkgname}-${pkgver}-mad-key.patch)
build() {
cd “${srcdir}/${pkgname}-${pkgver}”
patch -p0 -i ${srcdir}/${pkgname}-${pkgver}-mad-key.patch
./configure –prefix=/usr
make
make DESTDIR=“${pkgdir}” install
install -m755 -d “${pkgdir}/usr/share/licenses/${pkgname}”
install -m644 COPYING “${pkgdir}/usr/share/licenses/${pkgname}/”
}
sha1sums=(‘fe83410d76830ec15c4a73ace385d66644c58944’
‘e5ed1217fb22594dffe6976883dae71427784ba6’)

patch

http://dl.dropbox.com/u/662567/xf86-input-evdev-2.5.0-mad-key.patch に置いてある.念の為,ここにもコードを載せておく.

diff -Naur src.orig/evdev.c src/evdev.c
— src.orig/evdev.c    2010-10-02 11:34:25.213939676 +0900
+++ src/evdev.c 2010-10-02 11:42:23.187641557 +0900
@@ -115,6 +115,32 @@
* cannot be used by evdev, leaving us with a space of 2 at the end. */
static EvdevPtr evdev_devices[MAXDEVICES] = {NULL};
+static void AddMadKey(EvdevPtr pEvdev, int trigger, int transfer, MadKeyType type)
+{
+    MadKeyList *keyList = pEvdev->madKeyList;
+    MadKeyList *key;
+    if (keyList != NULL) {
+        while (keyList->next != NULL)
+            keyList = keyList->next;
+    }
+
+ + key = calloc(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) + pEvdev->madKeyList = key; + else + keyList->next = key; +} + static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode) { InputInfoPtr pInfo; @@ -262,13 +288,25 @@ static int wheel_left_button = 6; static int wheel_right_button = 7; +static void +EvdevEnqueKeyEvent(EvdevPtr pEvdev, int code, int value) +{ + EventQueuePtr pQueue = &pEvdev->queue[pEvdev->num_queue]; + pQueue->type = EV_QUEUE_KEY; + pQueue->key = code + MIN_KEYCODE; + pQueue->val = value; + pEvdev->num_queue++; +} + void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event ev, int value) { - int code = ev->code + MIN_KEYCODE; - EventQueuePtr pQueue; EvdevPtr pEvdev = pInfo->private; + int scanCode = ev->code; + unsigned int tmpScanCode = scanCode; + unsigned int lastScanCode = pEvdev->lastScanCode; + / Filter all repeated events from device. We’ll do softrepeat in the server, but only since 1.6 / if (value == 2 @@ -289,11 +327,88 @@ return; } - pQueue = &pEvdev->queue[pEvdev->num_queue]; - pQueue->type = EV_QUEUE_KEY; - pQueue->key = code; - pQueue->val = value; - pEvdev->num_queue++; + + / + * Sticky Key + */ + if (value) { + if (pEvdev->stickyPhase == 1) { + pEvdev->stickyPhase = 2; + EvdevEnqueKeyEvent(pEvdev, pEvdev->stickyScanCode, TRUE); + goto madKeyFinish; + } else if (pEvdev->stickyPhase == 2) { + pEvdev->stickyPhase = 0; + EvdevEnqueKeyEvent(pEvdev, pEvdev->stickyScanCode, FALSE); + goto madKeyFinish; + } + } else { + MadKeyList *keyList; + for (keyList = pEvdev->madKeyList; keyList != NULL; keyList = keyList->next) { + MadKey key = keyList->madKey; + if (key->type == MAD_KEY_STICKY + && key->trigger == scanCode + && lastScanCode == scanCode) { + if (pEvdev->stickyPhase == -1) { / ignore / + pEvdev->stickyPhase = 0; + break; + } else { + pEvdev->stickyPhase = 1; + pEvdev->stickyScanCode = keyList->madKey->transfer; + return; + } + } + } + } +
+ /
+ * Pseudo Modifier + */ + { + MadKeyList *keyList; + for (keyList = pEvdev->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; + pEvdev->stickyPhase = -1; + } else if (value) + scanCode = key->transfer; + else { + if (lastScanCode == scanCode) { + EvdevEnqueKeyEvent(pEvdev, key->transfer, FALSE); + EvdevEnqueKeyEvent(pEvdev, key->trigger, TRUE); + } else + scanCode = key->transfer; + } + goto madKeyFinish; + } + } + } +
+ /
+ * One Shot Modifier + */ + if (!value) { + MadKeyList *keyList; + for (keyList = pEvdev->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; + EvdevEnqueKeyEvent(pEvdev, lastScanCode, FALSE); + EvdevEnqueKeyEvent(pEvdev, scanCode, TRUE); + goto madKeyFinish; + } + } + } +
+ madKeyFinish: + if (value) + pEvdev->lastScanCode = tmpScanCode; +
+ EvdevEnqueKeyEvent(pEvdev, scanCode, value); } void @@ -1100,6 +1215,8 @@ pInfo = device->public.devicePrivate; pEvdev = pInfo->private; + pEvdev->lastScanCode = 0; + pEvdev->stickyPhase = 0; /
sorry, no rules change allowed for you */ xf86ReplaceStrOption(pInfo->options, “xkb_rules”, “evdev”); @@ -2126,6 +2243,62 @@ EvdevDragLockPreInit(pInfo); } + if (pEvdev->flags & EVDEV_KEYBOARD_EVENTS) + { + pEvdev->madKeyList = NULL; + if (xf86FindOption(pInfo->options, “StickyShift”)) { + AddMadKey(pEvdev, KEY_LEFTSHIFT, KEY_LEFTSHIFT, MAD_KEY_STICKY); + AddMadKey(pEvdev, KEY_RIGHTSHIFT, KEY_RIGHTSHIFT, MAD_KEY_STICKY); + xf86Msg(X_CONFIG, “%s: StickyShift enabled\n”, pInfo->name); + } + if (xf86FindOption(pInfo->options, “StickyCtrl”)) { + AddMadKey(pEvdev, KEY_LEFTCTRL, KEY_LEFTCTRL, MAD_KEY_STICKY); + AddMadKey(pEvdev, KEY_RIGHTCTRL, KEY_RIGHTCTRL, MAD_KEY_STICKY); + xf86Msg(X_CONFIG, “%s: StickyCtrl enabled\n”, pInfo->name); + } + if (xf86FindOption(pInfo->options, “StickyAlt”)) { + AddMadKey(pEvdev, KEY_LEFTALT, KEY_LEFTALT, MAD_KEY_STICKY); + AddMadKey(pEvdev, KEY_RIGHTALT, KEY_RIGHTALT, 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(pEvdev, 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(pEvdev, KEY_LEFTSHIFT, transfer, MAD_KEY_ONE_SHOT_MOD); + AddMadKey(pEvdev, KEY_RIGHTSHIFT, 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(pEvdev, KEY_LEFTCTRL, transfer, MAD_KEY_ONE_SHOT_MOD); + AddMadKey(pEvdev, KEY_RIGHTCTRL, transfer, MAD_KEY_ONE_SHOT_MOD); +#ifdef XKB + if (xkb_options != NULL && strstr(xkb_options, “ctrl:swapcaps”) != NULL) + AddMadKey(pEvdev, 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(pEvdev, KEY_LEFTALT, transfer, MAD_KEY_ONE_SHOT_MOD); + AddMadKey(pEvdev, KEY_RIGHTALT, transfer, MAD_KEY_ONE_SHOT_MOD); + xf86Msg(X_CONFIG, “%s: OneShotAlt enabled\n”, pInfo->name); + } + + } + return pInfo; error: diff -Naur src.orig/evdev.h src/evdev.h — src.orig/evdev.h 2010-10-02 11:34:25.213939676 +0900 +++ src/evdev.h 2010-10-02 11:34:32.114356654 +0900 @@ -104,6 +104,25 @@ int traveled_distance; } WheelAxis, WheelAxisPtr; +/ key status data for mad-key system */ +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; + / Event queue used to defer keyboard/button events until EV_SYN time. / typedef struct { enum { @@ -133,6 +152,17 @@ int delta[REL_CNT]; unsigned int abs, rel; + int lastScanCode; + int stickyScanCode; + / + * -1: ignore + * 0: disabled + * 1: presss enabled + * 2: release enabled + */ + int stickyPhase; + MadKeyList madKeyList; + / XKB stuff has to be per-device rather than per-driver */ #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5 XkbComponentNamesRec xkbnames;