xf86-input-evdev-2.4.0 用の SandS パッチ
コンテンツ
追記(2011年2月21日)
定家さんこの記事のコードの改良版をgitに公開(下のURL)してくださいました。 http://gitorious.org/at-home-modifier しっかりとしたREADMEなどが付随しているので、現状ではそちらのコードを使用したほうが良いでしょう。 (追記おわり)
xorg 1.8 にアップデートしたとき,evdevも 2.3.3から2.4.0にアップデートした. その関係で, Linux で SandS の実現を目指す : xf86-input-evdev の修正(メモ) – 落書き、時々落学で作ったパッチがそのままでは使えなくなった. そこで,2.4.0用に作りなおした. http://dl.dropbox.com/u/662567/xf86-input-evdev-2.4.0-mad-key.patch 以下のPKGBUILDと一緒に使えば簡単にバイナリができる.
pkgname=xf86-input-evdev pkgver=2.4.0 pkgrel=1 pkgdesc="X.org evdev input driver" arch=(i686 x86_64) url="http://xorg.freedesktop.org/" license=('custom') depends=('glibc') makedepends=('pkgconfig' 'xorg-server>=1.8.0' 'inputproto>=2.0' 'randrproto>=1.3.1') conflicts=('xorg-server<1.8.0') options=('!libtool') 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 || return 1 ./configure --prefix=/usr || return 1 make || return 1 make DESTDIR="${pkgdir}" install || return 1 install -m755 -d "${pkgdir}/usr/share/licenses/${pkgname}" install -m644 COPYING "${pkgdir}/usr/share/licenses/${pkgname}/" || return 1 } md5sums=('1dbf4d57d99682ba466c7855ed555f19' '6931ed658f5794e0654548c613381522')
ちなみに,xorg 1.8 での設定は Xorg 1.8 にアップデートしたときの設定の移行 – 落書き、時々落学 にあるように,/etc/X11/xorg.conf.d/に適当なファイルを作ればよい. 念の為,パッチの内容をここにも載せておく.
diff -Naur src.orig/evdev.c src/evdev.c --- src.orig/evdev.c 2010-06-27 00:31:41.965189461 +0000 +++ src/evdev.c 2010-06-27 01:00:02.754603018 +0000 @@ -125,6 +125,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 = 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) + pEvdev->madKeyList = key; + else + keyList->next = key; +} + static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode) { InputInfoPtr pInfo; @@ -272,13 +298,26 @@ 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 @@ -299,11 +338,87 @@ 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 @@ -1112,6 +1227,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"); @@ -2103,6 +2220,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; } diff -Naur src.orig/evdev.h src/evdev.h --- src.orig/evdev.h 2010-06-27 00:31:41.965189461 +0000 +++ src/evdev.h 2010-06-27 01:02:37.194587398 +0000 @@ -103,6 +103,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 { @@ -132,6 +151,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;
作成者 Toru Mano
最終更新時刻 2023-01-01 (c70d5a1)