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)