summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:56 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:56 +0000
commit724aeb56e7d6e5940ad6d329f53f5b80a9fc38ae (patch)
tree26bf7eeae3c1ca04f2cfcf6bf56a4d9123600342
Initial revisionXORG-STABLE
-rw-r--r--man/kbd.man99
-rw-r--r--man/keyboard.man103
-rw-r--r--src/kbd.c770
3 files changed, 972 insertions, 0 deletions
diff --git a/man/kbd.man b/man/kbd.man
new file mode 100644
index 0000000..5719d56
--- /dev/null
+++ b/man/kbd.man
@@ -0,0 +1,99 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/keyboard/kbd.man,v 1.1 2002/10/11 01:40:33 dawes Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH KBD __drivermansuffix__ __vendorversion__
+.SH NAME
+kbd \- Keyboard input driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qInputDevice\*q"
+.BI " Identifier \*q" idevname \*q
+.B " Driver \*qkbd\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B kbd
+is an XFree86 input driver for keyboards. The driver supports the standard
+OS-provided keyboard interface, but these are currently only available to
+this driver module for Linux and BSD. This driver is experimental, but
+will soon replace the built-in
+.B keyboard
+driver.
+.PP
+The
+.B kbd
+driver functions as a keyboard input device, and may be used as the
+X server's core keyboard.
+.SH CONFIGURATION DETAILS
+Please refer to XF86Config(__filemansuffix__) for general configuration
+details and for options that can be used with all input drivers. This
+section only covers configuration details specific to this driver.
+.PP
+The following driver
+.B Options
+are supported:
+.TP 7
+.BI "Option \*qDevice\*q \*q" string \*q
+Specify the keyboard device. Default: the OS's default console keyboard
+input source.
+.TP 7
+.BI "Option \*qProtocol\*q \*q" string \*q
+Specify the keyboard protocol. Valid protocol types include:
+.PP
+.RS 12
+Standard, Xqueue.
+.RE
+.PP
+.RS 7
+Not all protocols are supported on all platforms. Default: "Standard".
+.RE
+.TP 7
+.BI "Option \*qAutoRepeat\*q \*q" "delay rate" \*q
+sets the auto repeat behaviour for the keyboard. This is not implemented
+on all platforms.
+.I delay
+is the time in milliseconds before a key starts repeating.
+.I rate
+is the number of times a key repeats per second. Default: "500 30".
+.TP 7
+.BI "Option \*qXLeds\*q \*q" ledlist \*q
+makes the keyboard LEDs specified in
+.I ledlist
+available for client use instead of their traditional function
+(Scroll Lock, Caps Lock and Num Lock). The numbers in the list are
+in the range 1 to 3. Default: empty list.
+.TP 7
+.BI "Option \*qXkbRules\*q \*q" rules \*q
+specifies which XKB rules file to use for interpreting the
+.BR XkbModel ,
+.BR XkbLayout ,
+.BR XkbVariant ,
+and
+.B XkbOptions
+settings. Default: "xfree86" for most platforms, but "xfree98" for the
+Japanese PC-98 platforms.
+.TP 7
+.BI "Option \*qXkbModel\*q \*q" modelname \*q
+specifies the XKB keyboard model name. Default: "pc101" for most platforms,
+but "pc98" for the Japanese PC-98 platforms, and "pc101_sol8x86" for
+Solaris 8 on x86.
+.TP 7
+.BI "Option \*qXkbLayout\*q \*q" layoutname \*q
+specifies the XKB keyboard layout name. This is usually the country or
+language type of the keyboard. Default: "us" for most platforms, but
+"nec/jp" for the Japanese PC-98 platforms.
+.TP 7
+.BI "Option \*qXkbVariant\*q \*q" variants \*q
+specifies the XKB keyboard variant components. These can be used to
+enhance the keyboard layout details. Default: not set.
+.TP 7
+.BI "Option \*qXkbOptions\*q \*q" options \*q
+specifies the XKB keyboard option components. These can be used to
+enhance the keyboard behaviour. Default: not set.
+.PP
+Some other XKB-related options are available, but they are incompatible
+with the ones listed above and are not recommended, so they are not
+documented here.
+.SH "SEE ALSO"
+keyboard(__drivermansuffix__), XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__).
diff --git a/man/keyboard.man b/man/keyboard.man
new file mode 100644
index 0000000..93a5fd3
--- /dev/null
+++ b/man/keyboard.man
@@ -0,0 +1,103 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/keyboard/keyboard.man,v 1.3 2002/10/11 01:40:33 dawes Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH KEYBOARD __drivermansuffix__ __vendorversion__
+.SH NAME
+keyboard \- Keyboard input driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qInputDevice\*q"
+.BI " Identifier \*q" idevname \*q
+.B " Driver \*qkeyboard\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B keyboard
+is an XFree86 input driver for keyboards. The driver supports the standard
+OS-provided keyboard interface. This driver is currently built-in to
+the core X server.
+.PP
+The
+.B keyboard
+driver functions as a keyboard input device, and may be used as the
+X server's core keyboard. This driver is currently built-in to the core
+X server, and multiple instances are not yet supported.
+.SH CONFIGURATION DETAILS
+Please refer to XF86Config(__filemansuffix__) for general configuration
+details and for options that can be used with all input drivers. This
+section only covers configuration details specific to this driver.
+.PP
+The following driver
+.B Options
+are supported:
+.TP 7
+.BI "Option \*qProtocol\*q \*q" string \*q
+Specify the keyboard protocol. Valid protocol types include:
+.PP
+.RS 12
+Standard, Xqueue.
+.RE
+.PP
+.RS 7
+Not all protocols are supported on all platforms. Default: "Standard".
+.RE
+.TP 7
+.BI "Option \*qAutoRepeat\*q \*q" "delay rate" \*q
+sets the auto repeat behaviour for the keyboard. This is not implemented
+on all platforms.
+.I delay
+is the time in milliseconds before a key starts repeating.
+.I rate
+is the number of times a key repeats per second. Default: "500 30".
+.TP 7
+.BI "Option \*qXLeds\*q \*q" ledlist \*q
+makes the keyboard LEDs specified in
+.I ledlist
+available for client use instead of their traditional function
+(Scroll Lock, Caps Lock and Num Lock). The numbers in the list are
+in the range 1 to 3. Default: empty list.
+.TP 7
+.BI "Option \*qXkbDisable\*q \*q" boolean \*q
+disable/enable the XKEYBOARD extension. The \-kb command line
+option overrides this config file option. Default: XKB is enabled.
+.PP
+.RS 7
+NOTE: This option should be specified in the
+.B ServerFlags
+section rather than here. It's use here is deprecated.
+.RE
+.TP 7
+.BI "Option \*qXkbRules\*q \*q" rules \*q
+specifies which XKB rules file to use for interpreting the
+.BR XkbModel ,
+.BR XkbLayout ,
+.BR XkbVariant ,
+and
+.B XkbOptions
+settings. Default: "xfree86" for most platforms, but "xfree98" for the
+Japanese PC-98 platforms.
+.TP 7
+.BI "Option \*qXkbModel\*q \*q" modelname \*q
+specifies the XKB keyboard model name. Default: "pc101" for most platforms,
+but "pc98" for the Japanese PC-98 platforms, and "pc101_sol8x86" for
+Solaris 8 on x86.
+.TP 7
+.BI "Option \*qXkbLayout\*q \*q" layoutname \*q
+specifies the XKB keyboard layout name. This is usually the country or
+language type of the keyboard. Default: "us" for most platforms, but
+"nec/jp" for the Japanese PC-98 platforms.
+.TP 7
+.BI "Option \*qXkbVariant\*q \*q" variants \*q
+specifies the XKB keyboard variant components. These can be used to
+enhance the keyboard layout details. Default: not set.
+.TP 7
+.BI "Option \*qXkbOptions\*q \*q" options \*q
+specifies the XKB keyboard option components. These can be used to
+enhance the keyboard behaviour. Default: not set.
+.PP
+Some other XKB-related options are available, but they are incompatible
+with the ones listed above and are not recommended, so they are not
+documented here.
+.SH "SEE ALSO"
+kbd(__drivermansuffix__), XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__).
diff --git a/src/kbd.c b/src/kbd.c
new file mode 100644
index 0000000..f6d4152
--- /dev/null
+++ b/src/kbd.c
@@ -0,0 +1,770 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/input/keyboard/kbd.c,v 1.7 2003/02/17 16:08:29 dawes Exp $ */
+
+/*
+ * Copyright (c) 2002 by The XFree86 Project, Inc.
+ * Author: Ivan Pascal.
+ *
+ * Based on the code from
+ * xf86Config.c which is
+ * Copyright 1991-2002 by The XFree86 Project, Inc.
+ * Copyright 1997 by Metro Link, Inc.
+ * xf86Events.c and xf86Io.c which are
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+ */
+
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+
+#include "xf86.h"
+#include "atKeynames.h"
+#include "xf86Privstr.h"
+
+#ifdef XINPUT
+#include "XI.h"
+#include "XIproto.h"
+#include "extnsionst.h"
+#include "extinit.h"
+#else
+#include "inputstr.h"
+#endif
+
+#include "xf86Xinput.h"
+#include "xf86_OSproc.h"
+#include "xf86OSKbd.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#ifdef XKB
+#include <X11/extensions/XKB.h>
+#include <X11/extensions/XKBstr.h>
+#include <X11/extensions/XKBsrv.h>
+#endif
+
+#define CAPSFLAG 1
+#define NUMFLAG 2
+#define SCROLLFLAG 4
+#define MODEFLAG 8
+#define COMPOSEFLAG 16
+
+static InputInfoPtr KbdPreInit(InputDriverPtr drv, IDevPtr dev, int flags);
+static int KbdProc(DeviceIntPtr device, int what);
+static int KbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
+static void KbdBell(int percent, DeviceIntPtr dev, pointer ctrl, int unused);
+static void PostKbdEvent(InputInfoPtr pInfo, unsigned int key, Bool down);
+
+static void InitKBD(InputInfoPtr pInfo, Bool init);
+static void SetXkbOption(InputInfoPtr pInfo, char *name, char **option);
+static void UpdateLeds(InputInfoPtr pInfo);
+
+#undef KEYBOARD
+InputDriverRec KEYBOARD = {
+ 1,
+ "kbd",
+ NULL,
+ KbdPreInit,
+ NULL,
+ NULL,
+ 0
+};
+
+typedef enum {
+ OPTION_ALWAYS_CORE,
+ OPTION_SEND_CORE_EVENTS,
+ OPTION_CORE_KEYBOARD,
+ OPTION_DEVICE,
+ OPTION_PROTOCOL,
+ OPTION_AUTOREPEAT,
+ OPTION_XLEDS,
+ OPTION_XKB_DISABLE,
+ OPTION_XKB_KEYMAP,
+ OPTION_XKB_KEYCODES,
+ OPTION_XKB_TYPES,
+ OPTION_XKB_COMPAT,
+ OPTION_XKB_SYMBOLS,
+ OPTION_XKB_GEOMETRY,
+ OPTION_XKB_RULES,
+ OPTION_XKB_MODEL,
+ OPTION_XKB_LAYOUT,
+ OPTION_XKB_VARIANT,
+ OPTION_XKB_OPTIONS,
+ OPTION_PANIX106,
+ OPTION_CUSTOM_KEYCODES
+} KeyboardOpts;
+
+static const OptionInfoRec KeyboardOptions[] = {
+ { OPTION_ALWAYS_CORE, "AlwaysCore", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SEND_CORE_EVENTS, "SendCoreEvents", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_CORE_KEYBOARD, "CoreKeyboard", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DEVICE, "Device", OPTV_STRING, {0}, FALSE },
+ { OPTION_PROTOCOL, "Protocol", OPTV_STRING, {0}, FALSE },
+ { OPTION_AUTOREPEAT, "AutoRepeat", OPTV_STRING, {0}, FALSE },
+ { OPTION_XLEDS, "XLeds", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_DISABLE, "XkbDisable", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_XKB_KEYMAP, "XkbKeymap", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_KEYCODES, "XkbKeycodes", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_TYPES, "XkbTypes", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_COMPAT, "XkbCompat", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_SYMBOLS, "XkbSymbols", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_GEOMETRY, "XkbGeometry", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_RULES, "XkbRules", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_MODEL, "XkbModel", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_LAYOUT, "XkbLayout", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_VARIANT, "XkbVariant", OPTV_STRING, {0}, FALSE },
+ { OPTION_XKB_OPTIONS, "XkbOptions", OPTV_STRING, {0}, FALSE },
+ { OPTION_PANIX106, "Panix106", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_CUSTOM_KEYCODES, "CustomKeycodes", OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+static const char *kbdDefaults[] = {
+ "Protocol", "standard",
+ "AutoRepeat", "500 30",
+ "XkbRules", "xfree86",
+ "XkbModel", "pc101",
+ "XkbLayout", "us",
+ "Panix106", "off",
+ "CustomKeycodes", "off",
+ NULL
+};
+
+static const char *kbd98Defaults[] = {
+ "Protocol", "standard",
+ "AutoRepeat", "500 30",
+ "XkbRules", "xfree98",
+ "XkbModel", "pc98",
+ "XkbLayout", "nec/jp",
+ "Panix106", "off",
+ "CustomKeycodes", "off",
+ NULL
+};
+
+#ifdef XKB
+static char *xkb_rules;
+static char *xkb_model;
+static char *xkb_layout;
+static char *xkb_variant;
+static char *xkb_options;
+
+static XkbComponentNamesRec xkbnames;
+#endif /* XKB */
+
+#ifdef XFree86LOADER
+/*ARGSUSED*/
+static const OptionInfoRec *
+KeyboardAvailableOptions(void *unused)
+{
+ return (KeyboardOptions);
+}
+#endif
+
+static void
+SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
+{
+ char *s;
+
+ if ((s = xf86SetStrOption(pInfo->options, name, NULL))) {
+ if (!s[0]) {
+ xfree(s);
+ *option = NULL;
+ } else {
+ *option = s;
+ xf86Msg(X_CONFIG, "%s: %s: \"%s\"\n", pInfo->name, name, s);
+ }
+ }
+}
+
+static InputInfoPtr
+KbdPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
+{
+ InputInfoPtr pInfo;
+ KbdDevPtr pKbd;
+ MessageType from = X_DEFAULT;
+ char *s;
+
+ if (!(pInfo = xf86AllocateInput(drv, 0)))
+ return NULL;
+
+ /* Initialise the InputInfoRec. */
+ pInfo->name = dev->identifier;
+ pInfo->type_name = XI_KEYBOARD;
+ pInfo->flags = XI86_KEYBOARD_CAPABLE;
+ pInfo->device_control = KbdProc;
+ pInfo->read_input = NULL;
+ pInfo->motion_history_proc = NULL;
+ pInfo->history_size = 0;
+ pInfo->control_proc = NULL;
+ pInfo->close_proc = NULL;
+ pInfo->switch_mode = NULL;
+ pInfo->conversion_proc = NULL;
+ pInfo->reverse_conversion_proc = NULL;
+ pInfo->fd = -1;
+ pInfo->dev = NULL;
+ pInfo->private_flags = 0;
+ pInfo->always_core_feedback = 0;
+ pInfo->conf_idev = dev;
+
+ if (!xf86IsPc98())
+ xf86CollectInputOptions(pInfo, kbdDefaults, NULL);
+ else
+ xf86CollectInputOptions(pInfo, kbd98Defaults, NULL);
+ xf86ProcessCommonOptions(pInfo, pInfo->options);
+
+ if (!(pKbd = xcalloc(sizeof(KbdDevRec), 1)))
+ return pInfo;
+
+ pInfo->private = pKbd;
+ pKbd->PostEvent = PostKbdEvent;
+
+ if (!xf86OSKbdPreInit(pInfo))
+ return pInfo;
+
+ if (!pKbd->OpenKeyboard(pInfo)) {
+ return pInfo;
+ }
+
+ if ((s = xf86SetStrOption(pInfo->options, "AutoRepeat", NULL))) {
+ int delay, rate;
+ if (sscanf(s, "%d %d", &delay, &rate) != 2) {
+ xf86Msg(X_ERROR, "\"%s\" is not a valid AutoRepeat value", s);
+ } else {
+ pKbd->delay = delay;
+ pKbd->rate = rate;
+ }
+ xfree(s);
+ }
+
+ if ((s = xf86SetStrOption(pInfo->options, "XLeds", NULL))) {
+ char *l, *end;
+ unsigned int i;
+ l = strtok(s, " \t\n");
+ while (l) {
+ i = strtoul(l, &end, 0);
+ if (*end == '\0')
+ pKbd->xledsMask |= 1L << (i - 1);
+ else {
+ xf86Msg(X_ERROR, "\"%s\" is not a valid XLeds value", l);
+ }
+ l = strtok(NULL, " \t\n");
+ }
+ xfree(s);
+ }
+
+#ifdef XKB
+
+/* XkbDisable must be a server flag but for compatibility we check it here */
+
+ if (xf86FindOption(pInfo->options, "XkbDisable"))
+ xf86Msg(X_WARNING,
+ "%s: XKB can't be disabled here. Use \"ServerFlags\" section.\n",
+ pInfo->name);
+
+ pKbd->noXkb = noXkbExtension;
+ if (pKbd->noXkb) {
+ xf86Msg(X_CONFIG, "XKB: disabled\n");
+ } else {
+ SetXkbOption(pInfo, "XkbKeymap", &xkbnames.keymap);
+ if (xkbnames.keymap) {
+ xf86Msg(X_CONFIG, "%s: XkbKeymap overrides all other XKB settings\n",
+ pInfo->name);
+ } else {
+ SetXkbOption(pInfo, "XkbRules", &xkb_rules);
+ SetXkbOption(pInfo, "XkbModel", &xkb_model);
+ SetXkbOption(pInfo, "XkbLayout", &xkb_layout);
+ SetXkbOption(pInfo, "XkbVariant", &xkb_variant);
+ SetXkbOption(pInfo, "XkbOptions", &xkb_options);
+
+ SetXkbOption(pInfo, "XkbKeycodes", &xkbnames.keycodes);
+ SetXkbOption(pInfo, "XkbTypes", &xkbnames.types);
+ SetXkbOption(pInfo, "XkbCompat", &xkbnames.compat);
+ SetXkbOption(pInfo, "XkbSymbols", &xkbnames.symbols);
+ SetXkbOption(pInfo, "XkbGeometry", &xkbnames.geometry);
+ }
+ }
+
+ if ((xkb_model && !strcmp(xkb_model, "sun")) ||
+ (xkb_rules && !strcmp(xkb_rules, "sun")))
+ pKbd->sunKbd = TRUE;
+#endif
+
+#if defined(SVR4) && defined(i386)
+ if ((pKbd->Panix106 =
+ xf86SetBoolOption(pInfo->options, "Panix106", FALSE))) {
+ xf86Msg(X_CONFIG, "%s: PANIX106: enabled\n", pInfo->name);
+ }
+#endif
+
+ pKbd->CustomKeycodes = FALSE;
+ from = X_DEFAULT;
+ if (xf86FindOption(pInfo->options, "CustomKeycodes")) {
+ pKbd->CustomKeycodes = xf86SetBoolOption(pInfo->options, "CustomKeycodes",
+ pKbd->CustomKeycodes);
+ from = X_CONFIG;
+ }
+
+ xf86Msg(from, "%s: CustomKeycodes %s\n",
+ pInfo->name, pKbd->CustomKeycodes ? "enabled" : "disabled");
+
+ pInfo->flags |= XI86_CONFIGURED;
+
+ return pInfo;
+}
+
+static void
+KbdBell(int percent, DeviceIntPtr dev, pointer ctrl, int unused)
+{
+ InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate;
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ pKbd->Bell(pInfo, percent, ((KeybdCtrl*) ctrl)->bell_pitch,
+ ((KeybdCtrl*) ctrl)->bell_duration);
+}
+
+static void
+UpdateLeds(InputInfoPtr pInfo)
+{
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ int leds = 0;
+
+ if (pKbd->keyLeds & CAPSFLAG) leds |= XLED1;
+ if (pKbd->keyLeds & NUMFLAG) leds |= XLED2;
+ if (pKbd->keyLeds & SCROLLFLAG ||
+ pKbd->keyLeds & MODEFLAG) leds |= XLED3;
+ if (pKbd->keyLeds & COMPOSEFLAG) leds |= XLED4;
+
+ pKbd->leds = (pKbd->leds & pKbd->xledsMask) | (leds & ~pKbd->xledsMask);
+ pKbd->SetLeds(pInfo, pKbd->leds);
+}
+
+static int
+KbdCtrl( DeviceIntPtr device, KeybdCtrl *ctrl)
+{
+ int leds;
+ InputInfoPtr pInfo = (InputInfoPtr) device->public.devicePrivate;
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+
+ if ( ctrl->leds & XCOMP ) {
+ pKbd->keyLeds |= COMPOSEFLAG;
+ } else {
+ pKbd->keyLeds &= ~COMPOSEFLAG;
+ }
+ leds = ctrl->leds & ~(XCAPS | XNUM | XSCR); /* ??? */
+#ifdef XKB
+ if (pKbd->noXkb) {
+#endif
+ pKbd->leds = (leds & pKbd->xledsMask) | (pKbd->leds & ~pKbd->xledsMask);
+#ifdef XKB
+ } else {
+ pKbd->leds = leds;
+ }
+#endif
+ pKbd->SetLeds(pInfo, pKbd->leds);
+
+ return (Success);
+}
+
+static void
+InitKBD(InputInfoPtr pInfo, Bool init)
+{
+ char rad;
+ unsigned int i;
+ xEvent kevent;
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ DeviceIntPtr pKeyboard = pInfo->dev;
+ KeyClassRec *keyc = pKeyboard->key;
+ KeySym *map = keyc->curKeySyms.map;
+
+ kevent.u.keyButtonPointer.time = GetTimeInMillis();
+ kevent.u.keyButtonPointer.rootX = 0;
+ kevent.u.keyButtonPointer.rootY = 0;
+
+ /*
+ * Hmm... here is the biggest hack of every time !
+ * It may be possible that a switch-vt procedure has finished BEFORE
+ * you released all keys neccessary to do this. That peculiar behavior
+ * can fool the X-server pretty much, cause it assumes that some keys
+ * were not released. TWM may stuck alsmost completly....
+ * OK, what we are doing here is after returning from the vt-switch
+ * exeplicitely unrelease all keyboard keys before the input-devices
+ * are reenabled.
+ */
+ for (i = keyc->curKeySyms.minKeyCode, map = keyc->curKeySyms.map;
+ i < keyc->curKeySyms.maxKeyCode;
+ i++, map += keyc->curKeySyms.mapWidth)
+ if (KeyPressed(i))
+ {
+ switch (*map) {
+ /* Don't release the lock keys */
+ case XK_Caps_Lock:
+ case XK_Shift_Lock:
+ case XK_Num_Lock:
+ case XK_Scroll_Lock:
+ case XK_Kana_Lock:
+ break;
+ default:
+ kevent.u.u.detail = i;
+ kevent.u.u.type = KeyRelease;
+ (* pKeyboard->public.processInputProc)(&kevent, pKeyboard, 1);
+ }
+ }
+ pKbd->scanPrefix = 0;
+
+ if (init) {
+ pKbd->keyLeds = 0;
+
+ UpdateLeds(pInfo);
+
+ if( pKbd->delay <= 375) rad = 0x00;
+ else if (pKbd->delay <= 625) rad = 0x20;
+ else if (pKbd->delay <= 875) rad = 0x40;
+ else rad = 0x60;
+ if (pKbd->rate <= 2) rad |= 0x1F;
+ else if (pKbd->rate >= 30) rad |= 0x00;
+ else rad |= ((58 / pKbd->rate) - 2);
+ pKbd->SetKbdRepeat(pInfo, rad);
+ }
+}
+
+static int
+KbdProc(DeviceIntPtr device, int what)
+{
+
+ InputInfoPtr pInfo = device->public.devicePrivate;
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ KeySymsRec keySyms;
+ CARD8 modMap[MAP_LENGTH];
+ int ret;
+
+ switch (what) {
+ case DEVICE_INIT:
+ ret = pKbd->KbdInit(pInfo, what);
+ if (ret != Success)
+ return ret;
+
+ pKbd->KbdGetMapping(pInfo, &keySyms, modMap);
+
+ device->public.on = FALSE;
+#ifdef XKB
+ if (pKbd->noXkb) {
+#endif
+ InitKeyboardDeviceStruct((DevicePtr) device,
+ &keySyms,
+ modMap,
+ KbdBell,
+ (KbdCtrlProcPtr)KbdCtrl);
+#ifdef XKB
+ } else {
+ if (xkbnames.keymap)
+ xkb_rules = NULL;
+ XkbSetRulesDflts(xkb_rules, xkb_model, xkb_layout,
+ xkb_variant, xkb_options);
+ XkbInitKeyboardDeviceStruct(device,
+ &xkbnames,
+ &keySyms,
+ modMap,
+ KbdBell,
+ (KbdCtrlProcPtr)KbdCtrl);
+ }
+#endif
+ InitKBD(pInfo, TRUE);
+ break;
+ case DEVICE_ON:
+ if (device->public.on)
+ break;
+ /*
+ * Set the keyboard into "direct" mode and turn on
+ * event translation.
+ */
+ if ((ret = pKbd->KbdOn(pInfo, what)) != Success)
+ return ret;
+ /*
+ * Discard any pending input after a VT switch to prevent the server
+ * passing on parts of the VT switch sequence.
+ */
+ if (pInfo->fd >= 0) {
+ sleep(1);
+ xf86FlushInput(pInfo->fd);
+ AddEnabledDevice(pInfo->fd);
+ }
+
+ device->public.on = TRUE;
+ InitKBD(pInfo, FALSE);
+ break;
+
+ case DEVICE_CLOSE:
+ case DEVICE_OFF:
+
+ /*
+ * Restore original keyboard directness and translation.
+ */
+ if (pInfo->fd != -1)
+ RemoveEnabledDevice(pInfo->fd);
+ pKbd->KbdOff(pInfo, what);
+ device->public.on = FALSE;
+ break;
+ }
+ return (Success);
+}
+
+static void
+PostKbdEvent(InputInfoPtr pInfo, unsigned int scanCode, Bool down)
+{
+
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ DeviceIntPtr device = pInfo->dev;
+ KeyClassRec *keyc = device->key;
+ KbdFeedbackClassRec *kbdfeed = device->kbdfeed;
+ int specialkey = 0;
+
+ Bool UsePrefix = FALSE;
+ KeySym *keysym;
+ int keycode;
+ unsigned long changeLock = 0;
+ static int lockkeys = 0;
+
+ /* Disable any keyboard processing while in suspend */
+ if (xf86inSuspend)
+ return;
+
+ /*
+ * First do some special scancode remapping ...
+ */
+ if (pKbd->RemapScanCode != NULL) {
+ if (pKbd->RemapScanCode(pInfo, (int*) &scanCode))
+ return;
+ } else {
+ if (pKbd->scancodeMap != NULL) {
+ TransMapPtr map = pKbd->scancodeMap;
+ if (scanCode >= map->begin && scanCode < map->end)
+ scanCode = map->map[scanCode - map->begin];
+ }
+ }
+
+ /*
+ * and now get some special keysequences
+ */
+
+ specialkey = scanCode;
+
+ if (pKbd->GetSpecialKey != NULL) {
+ specialkey = pKbd->GetSpecialKey(pInfo, scanCode);
+ } else {
+ if (pKbd->specialMap != NULL) {
+ TransMapPtr map = pKbd->specialMap;
+ if (scanCode >= map->begin && scanCode < map->end)
+ specialkey = map->map[scanCode - map->begin];
+ }
+ }
+
+#ifndef TERMINATE_FALLBACK
+#define TERMINATE_FALLBACK 1
+#endif
+#ifdef XKB
+ if (noXkbExtension
+#if TERMINATE_FALLBACK
+ || specialkey == KEY_BackSpace
+#endif
+ )
+#endif
+ {
+ if (xf86CommonSpecialKey(specialkey, down, keyc->state))
+ return;
+ if (pKbd->SpecialKey != NULL)
+ if (pKbd->SpecialKey(pInfo, specialkey, down, keyc->state))
+ return;
+ }
+
+ /*
+ * Now map the scancodes to real X-keycodes ...
+ */
+ keycode = scanCode + MIN_KEYCODE;
+ keysym = (keyc->curKeySyms.map +
+ keyc->curKeySyms.mapWidth *
+ (keycode - keyc->curKeySyms.minKeyCode));
+
+#ifdef XKB
+ if (pKbd->noXkb) {
+#endif
+ /*
+ * Filter autorepeated caps/num/scroll lock keycodes.
+ */
+ if( down ) {
+ switch( keysym[0] ) {
+ case XK_Caps_Lock :
+ if (lockkeys & CAPSFLAG)
+ return;
+ else
+ lockkeys |= CAPSFLAG;
+ break;
+
+ case XK_Num_Lock :
+ if (lockkeys & NUMFLAG)
+ return;
+ else
+ lockkeys |= NUMFLAG;
+ break;
+
+ case XK_Scroll_Lock :
+ if (lockkeys & SCROLLFLAG)
+ return;
+ else
+ lockkeys |= SCROLLFLAG;
+ break;
+ }
+ if (keysym[1] == XF86XK_ModeLock)
+ {
+ if (lockkeys & MODEFLAG)
+ return;
+ else
+ lockkeys |= MODEFLAG;
+ }
+ }
+ else {
+ switch( keysym[0] ) {
+ case XK_Caps_Lock :
+ lockkeys &= ~CAPSFLAG;
+ break;
+
+ case XK_Num_Lock :
+ lockkeys &= ~NUMFLAG;
+ break;
+
+ case XK_Scroll_Lock :
+ lockkeys &= ~SCROLLFLAG;
+ break;
+ }
+ if (keysym[1] == XF86XK_ModeLock)
+ lockkeys &= ~MODEFLAG;
+ }
+
+ /*
+ * LockKey special handling:
+ * ignore releases, toggle on & off on presses.
+ * Don't deal with the Caps_Lock keysym directly, but check the lock modifier
+ */
+
+ if (keyc->modifierMap[keycode] & LockMask)
+ changeLock = CAPSFLAG;
+ if (keysym[0] == XK_Num_Lock)
+ changeLock = NUMFLAG;
+ if (keysym[0] == XK_Scroll_Lock)
+ changeLock = SCROLLFLAG;
+ if (keysym[1] == XF86XK_ModeLock)
+ changeLock = MODEFLAG;
+
+ if (changeLock) {
+ if (!down)
+ return;
+
+ pKbd->keyLeds &= ~changeLock;
+
+ if (KeyPressed(keycode)) {
+ down = !down;
+ } else {
+ pKbd->keyLeds |= changeLock;
+ }
+ UpdateLeds(pInfo);
+ }
+
+ if (!pKbd->CustomKeycodes) {
+ /*
+ * normal, non-keypad keys
+ */
+ if (scanCode < KEY_KP_7 || scanCode > KEY_KP_Decimal) {
+#if !defined(CSRG_BASED) && \
+ !defined(__GNU__) && \
+ defined(KB_84)
+ /*
+ * magic ALT_L key on AT84 keyboards for multilingual support
+ */
+ if (pKbd->kbdType == KB_84 &&
+ ModifierDown(AltMask) &&
+ keysym[2] != NoSymbol)
+ {
+ UsePrefix = TRUE;
+ }
+#endif /* !CSRG_BASED && ... */
+ }
+ }
+#ifdef XKB
+ }
+#endif
+
+ /*
+ * check for an autorepeat-event
+ */
+ if (down) {
+ int num = keycode >> 3;
+ int bit = 1 << (keycode & 7);
+ if ((keyc->down[num] & bit) &&
+ ((kbdfeed->ctrl.autoRepeat != AutoRepeatModeOn) ||
+ keyc->modifierMap[keycode] ||
+ !(kbdfeed->ctrl.autoRepeats[num] & bit)))
+ return;
+ }
+
+ if (UsePrefix) {
+ xf86PostKeyboardEvent(device,
+ keyc->modifierKeyMap[keyc->maxKeysPerModifier*7], TRUE);
+ xf86PostKeyboardEvent(device, keycode, down);
+ xf86PostKeyboardEvent(device,
+ keyc->modifierKeyMap[keyc->maxKeysPerModifier*7], FALSE);
+ } else {
+ xf86PostKeyboardEvent(device, keycode, down);
+ }
+}
+
+#ifdef XFree86LOADER
+ModuleInfoRec KeyboardInfo = {
+ 1,
+ "KBD",
+ NULL,
+ 0,
+ KeyboardAvailableOptions,
+};
+
+static void
+xf86KbdUnplug(pointer p)
+{
+}
+
+static pointer
+xf86KbdPlug(pointer module,
+ pointer options,
+ int *errmaj,
+ int *errmin)
+{
+ static Bool Initialised = FALSE;
+
+ if (!Initialised) {
+ Initialised = TRUE;
+#ifndef REMOVE_LOADER_CHECK_MODULE_INFO
+ if (xf86LoaderCheckSymbol("xf86AddModuleInfo"))
+#endif
+ xf86AddModuleInfo(&KeyboardInfo, module);
+ }
+
+ xf86AddInputDriver(&KEYBOARD, module, 0);
+
+ return module;
+}
+
+static XF86ModuleVersionInfo xf86KeyboardVersionRec =
+{
+ "kbd",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_XINPUT,
+ ABI_XINPUT_VERSION,
+ MOD_CLASS_XINPUT,
+ {0, 0, 0, 0} /* signature, to be patched into the file by */
+ /* a tool */
+};
+
+XF86ModuleData kbdModuleData = {&xf86KeyboardVersionRec,
+ xf86KbdPlug,
+ xf86KbdUnplug};
+
+#endif /* XFree86LOADER */