diff options
-rw-r--r-- | man/Makefile.am | 4 | ||||
-rw-r--r-- | man/evdev.man | 12 | ||||
-rw-r--r-- | src/evdev.c | 84 | ||||
-rw-r--r-- | src/evdev.h | 9 |
4 files changed, 108 insertions, 1 deletions
diff --git a/man/Makefile.am b/man/Makefile.am index 66c207f..3e78cf5 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -36,12 +36,16 @@ SED = sed XORGRELSTRING = @PACKAGE_STRING@ XORGMANNAME = X Version 11 +# should allow configure override like xserver's configure.ac does +XKBPATH=${datadir}/X11/xkb + MAN_SUBSTS = \ -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ -e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ -e 's|__xservername__|Xorg|g' \ -e 's|__xconfigfile__|xorg.conf|g' \ -e 's|__projectroot__|$(prefix)|g' \ + -e 's|__xkb_path__|$(XKBPATH)|g' \ -e 's|__appmansuffix__|$(APP_MAN_SUFFIX)|g' \ -e 's|__drivermansuffix__|$(DRIVER_MAN_SUFFIX)|g' \ -e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \ diff --git a/man/evdev.man b/man/evdev.man index 49ab12c..6da4bba 100644 --- a/man/evdev.man +++ b/man/evdev.man @@ -186,6 +186,18 @@ is mapped to the negative Y axis motion and button number .I N2 is mapped to the positive Y axis motion. Default: "4 5". Property: "Evdev Wheel Emulation Axes". +.TP 7 +.BI "Option \*qevent_key_remap\*q \*q" "integer=integer ..." \*q +Specifies a set of mappings for key events; the number on the +left-hand side of the equal sign must be an evdev keycode (look it up +with +.B "showkey -k" +; it can be between 0 and 65535), the number on the right-hand side of +the equal sign must be an X11 keycode (look it up in the +.B "__xkb_path__/keycodes/evdev" +file; it can be between 8 and 255). Integers can be specified as in C +source files (base-10, base-8 if they start with 0, base-16 if they +start with 0x). .SH SUPPORTED PROPERTIES The following properties are provided by the diff --git a/src/evdev.c b/src/evdev.c index 66b746a..7a9da6d 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -120,6 +120,46 @@ static Atom prop_axis_label = 0; static Atom prop_btn_label = 0; #endif +static uint16_t +remapKey(EvdevPtr ev, uint16_t code) +{ + uint8_t slice=code/256; + uint8_t offs=code%256; + + if (!ev->keyremap) return code; + if (!(ev->keyremap->sl[slice])) return code; + if (!(ev->keyremap->sl[slice]->cd[offs])) return code; + return ev->keyremap->sl[slice]->cd[offs]; +} + +static void +addRemap(EvdevPtr ev,uint16_t code,uint8_t value) +{ + uint8_t slice=code/256; + uint8_t offs=code%256; + + if (!ev->keyremap) { + ev->keyremap=(EvdevKeyRemapPtr)xcalloc(1,sizeof(EvdevKeyRemap)); + } + if (!ev->keyremap->sl[slice]) { + ev->keyremap->sl[slice]=(EvdevKeyRemapSlice*)xcalloc(1,sizeof(EvdevKeyRemapSlice)); + } + ev->keyremap->sl[slice]->cd[offs]=value; +} + +static void +freeRemap(EvdevPtr ev) +{ + uint16_t slice; + if (!ev->keyremap) return; + for (slice=0;slice<256;++slice) { + if (!ev->keyremap->sl[slice]) continue; + xfree(ev->keyremap->sl[slice]); + } + xfree(ev->keyremap); + ev->keyremap=0; +} + /* All devices the evdev driver has allocated and knows about. * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK) * cannot be used by evdev, leaving us with a space of 2 at the end. */ @@ -267,6 +307,41 @@ SetXkbOption(InputInfoPtr pInfo, char *name, char **option) } } +static void +SetRemapOption(InputInfoPtr pInfo,const char* name,EvdevPtr ev) +{ + char *s,*c; + unsigned long int code,value; + int consumed; + + s = xf86SetStrOption(pInfo->options, name, NULL); + if (!s) return; + if (!s[0]) { + xfree(s); + return; + } + + c=s; + while (sscanf(c," %li = %li %n",&code,&value,&consumed) > 1) { + if (code < 0 || code > 65535L) { + xf86Msg(X_ERROR,"%s: input code %ld out of range for option \"event_key_remap\", ignoring.\n",pInfo->name,code); + continue; + } + if (value < MIN_KEYCODE || value > 255) { + xf86Msg(X_ERROR,"%s: output value %ld out of range for option \"event_key_remap\", ignoring.\n",pInfo->name,code); + continue; + } + xf86Msg(X_INFO,"%s: remapping %ld into %ld.\n",pInfo->name,code,value); + addRemap(ev,code,value-MIN_KEYCODE); + c+=consumed; + } + + if (*c!='\0') { + xf86Msg(X_ERROR, "%s: invalid input for option \"event_key_remap\" starting at '%s', ignoring.\n", + pInfo->name, c); + } +} + static int wheel_up_button = 4; static int wheel_down_button = 5; static int wheel_left_button = 6; @@ -275,10 +350,14 @@ static int wheel_right_button = 7; void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) { - int code = ev->code + MIN_KEYCODE; + int code; + static char warned[KEY_CNT]; EventQueuePtr pQueue; EvdevPtr pEvdev = pInfo->private; + ev->code=remapKey((EvdevPtr)(pInfo->private),ev->code); + code = ev->code + MIN_KEYCODE; + /* Filter all repeated events from device. We'll do softrepeat in the server, but only since 1.6 */ if (value == 2 @@ -1129,6 +1208,8 @@ EvdevAddKeyClass(DeviceIntPtr device) if (!pEvdev->rmlvo.options) SetXkbOption(pInfo, "XkbOptions", &pEvdev->rmlvo.options); + SetRemapOption(pInfo,"event_key_remap",pEvdev); + #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 if (!InitKeyboardDeviceStruct(device, &pEvdev->rmlvo, NULL, EvdevKbdCtrl)) return !Success; @@ -1612,6 +1693,7 @@ EvdevProc(DeviceIntPtr device, int what) pInfo->fd = -1; } EvdevRemoveDevice(pInfo); + freeRemap(pEvdev); pEvdev->min_maj = 0; break; } diff --git a/src/evdev.h b/src/evdev.h index 1133985..a404c8f 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -114,6 +114,13 @@ typedef struct { } EventQueueRec, *EventQueuePtr; typedef struct { + uint8_t cd[256]; +} EvdevKeyRemapSlice; +typedef struct { + EvdevKeyRemapSlice* sl[256]; +} EvdevKeyRemap, *EvdevKeyRemapPtr; + +typedef struct { const char *device; int grabDevice; /* grab the event device? */ @@ -173,6 +180,8 @@ typedef struct { unsigned char btnmap[32]; /* config-file specified button mapping */ + EvdevKeyRemapPtr keyremap; + int reopen_attempts; /* max attempts to re-open after read failure */ int reopen_left; /* number of attempts left to re-open the device */ OsTimerPtr reopen_timer; |