aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/hw/nxagent/Keyboard.c')
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Keyboard.c1359
1 files changed, 1359 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c
new file mode 100644
index 000000000..dbdfc5b19
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c
@@ -0,0 +1,1359 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of NoMachine. Redistribution and use of the present */
+/* software is allowed according to terms specified in the file LICENSE */
+/* which comes in the source distribution. */
+/* */
+/* Check http://www.nomachine.com/licensing.html for applicability. */
+/* */
+/* NX and NoMachine are trademarks of NoMachine S.r.l. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "keysym.h"
+#include "screenint.h"
+#include "inputstr.h"
+#include "misc.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Keyboard.h"
+#include "Events.h"
+#include "Options.h"
+
+#include "NXlib.h"
+
+#ifdef XKB
+
+#include <X11/extensions/XKB.h>
+#include <X11/extensions/XKBsrv.h>
+#include <X11/extensions/XKBconfig.h>
+
+#endif /* XKB */
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef WATCH
+
+#ifdef WATCH
+#include "unistd.h"
+#endif
+
+/*
+ * Unfortunately we cannot just include XKBlib.h.
+ * It conflicts with the server side definitions
+ * of the same symbols. This is more a X problem
+ * than our.
+ */
+
+#ifdef XKB
+
+extern Bool XkbQueryExtension(
+#if NeedFunctionPrototypes
+ Display * /* dpy */,
+ int * /* opcodeReturn */,
+ int * /* eventBaseReturn */,
+ int * /* errorBaseReturn */,
+ int * /* majorRtrn */,
+ int * /* minorRtrn */
+#endif
+);
+
+extern XkbDescPtr XkbGetKeyboard(
+#if NeedFunctionPrototypes
+ Display * /* dpy */,
+ unsigned int /* which */,
+ unsigned int /* deviceSpec */
+#endif
+);
+
+extern Status XkbGetControls(
+#if NeedFunctionPrototypes
+ Display * /* dpy */,
+ unsigned long /* which */,
+ XkbDescPtr /* desc */
+#endif
+);
+
+#ifndef XKB_BASE_DIRECTORY
+#define XKB_BASE_DIRECTORY "/usr/share/X11/xkb"
+#endif
+#ifndef XKB_ALTERNATE_BASE_DIRECTORY
+#define XKB_ALTERNATE_BASE_DIRECTORY "/usr/X11R6/lib/X11/xkb"
+#endif
+#ifndef XKB_CONFIG_FILE
+#define XKB_CONFIG_FILE "X0-config.keyboard"
+#endif
+#ifndef XKB_DFLT_RULES_FILE
+#define XKB_DFLT_RULES_FILE "xfree86"
+#endif
+#ifndef XKB_ALTS_RULES_FILE
+#define XKB_ALTS_RULES_FILE "xorg"
+#endif
+#ifndef XKB_DFLT_KB_LAYOUT
+#define XKB_DFLT_KB_LAYOUT "us"
+#endif
+#ifndef XKB_DFLT_KB_MODEL
+#define XKB_DFLT_KB_MODEL "pc102"
+#endif
+#ifndef XKB_DFLT_KB_VARIANT
+#define XKB_DFLT_KB_VARIANT NULL
+#endif
+#ifndef XKB_DFLT_KB_OPTIONS
+#define XKB_DFLT_KB_OPTIONS NULL
+#endif
+
+#define NXAGENT_KEYMAP_DIR_FILE "keymap.dir"
+
+extern int XkbDfltRepeatDelay;
+extern int XkbDfltRepeatInterval;
+
+#endif /* XKB */
+
+/*
+ * Save the values queried from X server.
+ */
+
+XkbAgentInfoRec nxagentXkbInfo = { -1, -1, -1, -1, -1 };
+
+/*
+ * Keyboard status, updated through XKB
+ * events.
+ */
+
+XkbAgentStateRec nxagentXkbState = { 0, 0, 0, 0, 0 };
+
+/*
+ * Info for disabling/enabling Xkb extension.
+ */
+
+XkbWrapperRec nxagentXkbWrapper;
+
+extern char *nxagentKeyboard;
+
+static char *nxagentXkbGetRules(void);
+
+unsigned int nxagentAltMetaMask;
+
+void nxagentCheckAltMetaKeys(CARD8, int);
+
+static int nxagentSaveKeyboardDeviceData(DeviceIntPtr dev, DeviceIntPtr devBackup);
+
+static int nxagentRestoreKeyboardDeviceData(DeviceIntPtr devBackup, DeviceIntPtr dev);
+
+static int nxagentFreeKeyboardDeviceData(DeviceIntPtr dev);
+
+static void nxagentCheckXkbBaseDirectory(void)
+{
+
+ /*
+ * Set XkbBaseDirectory global
+ * variable appropriately.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckXkbBaseDirectory: "
+ "Before calling _NXGetXkbBasePath.\n");
+
+ fprintf(stderr, "nxagentCheckXkbBaseDirectory: "
+ "XkbBaseDirectory varible [%s].\n",
+ XkbBaseDirectory);
+ #endif
+
+ XkbBaseDirectory = _NXGetXkbBasePath(XkbBaseDirectory);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckXkbBaseDirectory: "
+ "After calling _NXGetXkbBasePath.\n");
+
+ fprintf(stderr, "nxagentCheckXkbBaseDirectory: "
+ "XkbBaseDirectory varible [%s].\n",
+ XkbBaseDirectory);
+ #endif
+
+ return;
+}
+
+static char *nxagentXkbGetRules()
+{
+ int ret;
+ int size, sizeDflt, sizeAlt;
+ char *path;
+ struct stat buf;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentXkbGetRules: XkbBaseDirectory [%s].\n",
+ XkbBaseDirectory);
+ #endif
+
+ sizeDflt = strlen(XKB_DFLT_RULES_FILE);
+ sizeAlt = strlen(XKB_ALTS_RULES_FILE);
+ size = strlen(XkbBaseDirectory) + strlen("/rules/");
+ size += (sizeDflt > sizeAlt) ? sizeDflt: sizeAlt;
+
+ if ((path = malloc((size + 1) * sizeof(char))) == NULL)
+ {
+ FatalError("nxagentXkbGetRules: malloc failed.");
+ }
+
+ strcpy(path, XkbBaseDirectory);
+ strcat(path, "/rules/");
+ strcat(path, XKB_DFLT_RULES_FILE);
+ ret = stat(path, &buf);
+
+ if (ret == 0)
+ {
+ free(path);
+ return XKB_DFLT_RULES_FILE;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentXkbGetRules: WARNING! Failed to stat file [%s]: %s.\n", path, strerror(ret));
+ #endif
+
+ strcpy(path, XkbBaseDirectory);
+ strcat(path, "/rules/");
+ strcat(path, XKB_ALTS_RULES_FILE);
+ ret = stat(path, &buf);
+
+ if (ret == 0)
+ {
+ free(path);
+ return XKB_ALTS_RULES_FILE;
+ }
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentXkbGetRules: WARNING! Failed to stat file [%s]: %s.\n", path, strerror(ret));
+ #endif
+
+ free(path);
+ return XKB_DFLT_RULES_FILE;
+}
+
+void nxagentBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls)
+{
+ XBell(nxagentDisplay, volume);
+}
+
+void nxagentChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
+{
+ #ifdef XKB
+
+ XkbSrvInfoPtr xkbi;
+ XkbControlsPtr xkbc;
+
+ if (!noXkbExtension)
+ {
+ xkbi = pDev -> key -> xkbInfo;
+ xkbc = xkbi -> desc -> ctrls;
+
+ /*
+ * We want to prevent agent generating auto-repeated
+ * keystrokes. Let's intercept any attempt by appli-
+ * cations to change the default timeouts on the
+ * nxagent device.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeKeyboardControl: Repeat delay was [%d] interval was [%d].\n",
+ xkbc -> repeat_delay, xkbc -> repeat_interval);
+ #endif
+
+ xkbc -> repeat_delay = ~ 0;
+ xkbc -> repeat_interval = ~ 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeKeyboardControl: Repeat delay is now [%d] interval is now [%d].\n",
+ xkbc -> repeat_delay, xkbc -> repeat_interval);
+ #endif
+ }
+
+ #endif
+
+ /*
+ * If enabled, propagate the changes to the
+ * devices attached to the real X server.
+ */
+
+ if (nxagentOption(DeviceControl) == True)
+ {
+ unsigned long value_mask;
+ XKeyboardControl values;
+ int i;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeKeyboardControl: WARNING! Propagating changes to keyboard settings.\n");
+ #endif
+
+ value_mask = KBKeyClickPercent |
+ KBBellPercent |
+ KBBellPitch |
+ KBBellDuration;
+
+ values.key_click_percent = ctrl->click;
+ values.bell_percent = ctrl->bell;
+ values.bell_pitch = ctrl->bell_pitch;
+ values.bell_duration = ctrl->bell_duration;
+
+ /*
+ * Don't propagate the auto repeat mode. It is forced to be
+ * off in the agent server.
+ *
+ * value_mask |= KBAutoRepeatMode;
+ * values.auto_repeat_mode = ctrl->autoRepeat ?
+ * AutoRepeatModeOn : AutoRepeatModeOff;
+ */
+
+ XChangeKeyboardControl(nxagentDisplay, value_mask, &values);
+
+ /*
+ * At this point, we need to walk through the vector and
+ * compare it to the current server vector. If there are
+ * differences, report them.
+ */
+
+ value_mask = KBLed | KBLedMode;
+
+ for (i = 1; i <= 32; i++)
+ {
+ values.led = i;
+ values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff;
+
+ XChangeKeyboardControl(nxagentDisplay, value_mask, &values);
+ }
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeKeyboardControl: WARNING! Not propagating changes to keyboard settings.\n");
+ #endif
+}
+
+int nxagentKeyboardProc(DeviceIntPtr pDev, int onoff)
+{
+ XModifierKeymap *modifier_keymap;
+ KeySym *keymap;
+ int mapWidth;
+ int min_keycode, max_keycode;
+ KeySymsRec keySyms;
+ CARD8 modmap[256];
+ int i, j;
+ XKeyboardState values;
+ char *model = NULL, *layout = NULL;
+ int free_model = 0, free_layout = 0;
+ XkbDescPtr xkb = NULL;
+
+ int ret;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_INIT].\n");
+ #endif
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return Success;
+ }
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentKeyboardProc: Watchpoint 9.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+N/A
+*/
+
+ sleep(30);
+
+ #endif
+
+ /*
+ * Prevent agent from generating auto-repeat keystroke.
+ * Note that this is working only if XKB is enabled.
+ * A better solution should account cases where XKB is
+ * not available. Check also the behaviour of the
+ * DeviceControl nxagent option.
+ */
+
+ XkbDfltRepeatDelay = ~ 0;
+ XkbDfltRepeatInterval = ~ 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Set repeat delay to [%u] interval to [%u].\n",
+ XkbDfltRepeatDelay, XkbDfltRepeatInterval);
+ #endif
+
+ modifier_keymap = XGetModifierMapping(nxagentDisplay);
+
+ if (modifier_keymap == NULL)
+ {
+ return -1;
+ }
+
+ XDisplayKeycodes(nxagentDisplay, &min_keycode, &max_keycode);
+#ifdef _XSERVER64
+ {
+ KeySym64 *keymap64;
+ int i, len;
+ keymap64 = XGetKeyboardMapping(nxagentDisplay,
+ min_keycode,
+ max_keycode - min_keycode + 1,
+ &mapWidth);
+
+ if (keymap == NULL)
+ {
+ XFreeModifiermap(modifier_keymap);
+
+ return -1;
+ }
+
+ len = (max_keycode - min_keycode + 1) * mapWidth;
+ keymap = (KeySym *)xalloc(len * sizeof(KeySym));
+ for(i = 0; i < len; ++i)
+ keymap[i] = keymap64[i];
+ XFree(keymap64);
+ }
+
+#else /* #ifdef _XSERVER64 */
+
+ keymap = XGetKeyboardMapping(nxagentDisplay,
+ min_keycode,
+ max_keycode - min_keycode + 1,
+ &mapWidth);
+
+ if (keymap == NULL)
+ {
+ XFreeModifiermap(modifier_keymap);
+
+ return -1;
+ }
+
+#endif /* #ifdef _XSERVER64 */
+
+ nxagentAltMetaMask = 0;
+
+ for (i = 0; i < 256; i++)
+ modmap[i] = 0;
+ for (j = 0; j < 8; j++)
+ for(i = 0; i < modifier_keymap->max_keypermod; i++) {
+ CARD8 keycode;
+ if ((keycode =
+ modifier_keymap->
+ modifiermap[j * modifier_keymap->max_keypermod + i]))
+ modmap[keycode] |= 1<<j;
+
+ if (keycode > 0)
+ {
+ nxagentCheckAltMetaKeys(keycode, j);
+ }
+ }
+ XFreeModifiermap(modifier_keymap);
+
+ keySyms.minKeyCode = min_keycode;
+ keySyms.maxKeyCode = max_keycode;
+ keySyms.mapWidth = mapWidth;
+ keySyms.map = keymap;
+
+#ifdef XKB
+
+ /*
+ * First of all the validity
+ * of XkbBaseDirectory global
+ * variable is checked.
+ */
+
+ nxagentCheckXkbBaseDirectory();
+
+ if (noXkbExtension) {
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: No XKB extension.\n");
+ #endif
+
+XkbError:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: XKB error.\n");
+ #endif
+
+ XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
+ xkb = NULL;
+ if (free_model)
+ {
+ free_model = 0;
+ free(model);
+ }
+ if (free_layout)
+ {
+ free_layout = 0;
+ free(layout);
+ }
+#endif
+ XGetKeyboardControl(nxagentDisplay, &values);
+
+ memmove((char *) defaultKeyboardControl.autoRepeats,
+ (char *) values.auto_repeats, sizeof(values.auto_repeats));
+
+ ret = InitKeyboardDeviceStruct((DevicePtr) pDev, &keySyms, modmap,
+ nxagentBell, nxagentChangeKeyboardControl);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: InitKeyboardDeviceStruct returns [%d].\n", ret);
+ #endif
+
+#ifdef XKB
+ } else {
+ FILE *file;
+ XkbConfigRtrnRec config;
+
+ int nxagentXkbConfigFilePathSize;
+
+ char *nxagentXkbConfigFilePath;
+
+ XkbComponentNamesRec names;
+ char *rules, *variants, *options;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Using XKB extension.\n");
+ #endif
+
+ memset(&names, 0, sizeof(XkbComponentNamesRec));
+
+ rules = nxagentXkbGetRules();
+
+ if ((nxagentKeyboard != NULL) && (strcmp(nxagentKeyboard, "query") !=0))
+ {
+ for (i = 0; nxagentKeyboard[i] != '/' && nxagentKeyboard[i] != 0; i++);
+
+ if(nxagentKeyboard[i] == 0 || nxagentKeyboard[i + 1] == 0 || i == 0)
+ {
+ ErrorF("Warning: Wrong keyboard type: %s.\n",nxagentKeyboard);
+
+ goto XkbError;
+ }
+
+ free_model = 1;
+ model = malloc(i + 1);
+
+ strncpy(model, nxagentKeyboard, i);
+
+ model[i] = '\0';
+
+ free_layout = 1;
+ layout = malloc(strlen(&nxagentKeyboard[i + 1]) + 1);
+
+ strcpy(layout, &nxagentKeyboard[i + 1]);
+
+ /*
+ * There is no description for pc105 on Solaris.
+ * Need to revert to the closest approximation.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Using keyboard model [%s] with layout [%s].\n",
+ model, layout);
+ #endif
+
+ #ifdef __sun
+
+ if (strcmp(model, "pc105") == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: WARNING! Keyboard model 'pc105' unsupported on Solaris.\n");
+
+ fprintf(stderr, "nxagentKeyboardProc: WARNING! Forcing keyboard model to 'pc104'.\n");
+ #endif
+
+ strcpy(model, "pc104");
+ }
+
+ #endif
+ }
+ else
+ {
+ layout = XKB_DFLT_KB_LAYOUT;
+ model = XKB_DFLT_KB_MODEL;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Using default keyboard: model [%s] layout [%s].\n",
+ model, layout);
+ #endif
+ }
+
+ variants = XKB_DFLT_KB_VARIANT;
+ options = XKB_DFLT_KB_OPTIONS;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: XkbInitialMap [%s]\n", XkbInitialMap ? XkbInitialMap: "NULL");
+ #endif
+
+ if (XkbInitialMap) {
+ if ((names.keymap = strchr(XkbInitialMap, '/')) != NULL)
+ ++names.keymap;
+ else
+ names.keymap = XkbInitialMap;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Init XKB extension.\n");
+ #endif
+
+ if (XkbQueryExtension(nxagentDisplay,
+ &nxagentXkbInfo.Opcode,
+ &nxagentXkbInfo.EventBase,
+ &nxagentXkbInfo.ErrorBase,
+ &nxagentXkbInfo.MajorVersion,
+ &nxagentXkbInfo.MinorVersion) == 0)
+ {
+ ErrorF("Unable to initialize XKEYBOARD extension.\n");
+
+ goto XkbError;
+ }
+
+ xkb = XkbGetKeyboard(nxagentDisplay, XkbGBN_AllComponentsMask, XkbUseCoreKbd);
+
+ if (xkb == NULL || xkb->geom == NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: No current keyboard.\n");
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: No keyboard, going to set rules and init device.\n");
+ #endif
+
+ XkbSetRulesDflts(rules, model, layout, variants, options);
+ XkbInitKeyboardDeviceStruct((pointer)pDev, &names, &keySyms, modmap,
+ nxagentBell, nxagentChangeKeyboardControl);
+
+ if (!nxagentKeyboard ||
+ (nxagentKeyboard && (strcmp(nxagentKeyboard, "query") == 0)))
+ {
+ goto XkbError;
+ }
+
+ goto XkbEnd;
+ }
+
+ XkbGetControls(nxagentDisplay, XkbAllControlsMask, xkb);
+
+ nxagentXkbConfigFilePathSize = strlen(XkbBaseDirectory) +
+ strlen(XKB_CONFIG_FILE) + 1;
+
+ nxagentXkbConfigFilePath = malloc((nxagentXkbConfigFilePathSize + 1) * sizeof(char));
+
+ if ( nxagentXkbConfigFilePath == NULL)
+ {
+ FatalError("nxagentKeyboardProc: malloc failed.");
+ }
+
+ strcpy(nxagentXkbConfigFilePath, XkbBaseDirectory);
+ strcat(nxagentXkbConfigFilePath, "/");
+ strcat(nxagentXkbConfigFilePath, XKB_CONFIG_FILE);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: nxagentXkbConfigFilePath [%s].\n",
+ nxagentXkbConfigFilePath);
+ #endif
+
+ if ((file = fopen(nxagentXkbConfigFilePath, "r")) != NULL) {
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Going to parse config file.\n");
+ #endif
+
+ if (XkbCFParse(file, XkbCFDflts, xkb, &config) == 0) {
+ ErrorF("Error parsing config file.\n");
+
+ free(nxagentXkbConfigFilePath);
+
+ fclose(file);
+ goto XkbError;
+ }
+ if (config.rules_file)
+ rules = config.rules_file;
+ if (config.model)
+ {
+ if (free_model)
+ {
+ free_model = 0;
+ free(model);
+ }
+ model = config.model;
+ }
+ if (config.layout)
+ {
+ if (free_layout)
+ {
+ free_layout = 0;
+ free(layout);
+ }
+ layout = config.layout;
+ }
+ if (config.variant)
+ variants = config.variant;
+ if (config.options)
+ options = config.options;
+
+ free(nxagentXkbConfigFilePath);
+
+ fclose(file);
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: No config file.\n");
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: No config file, going to set rules and init device.\n");
+ #endif
+
+ XkbSetRulesDflts(rules, model, layout, variants, options);
+ XkbInitKeyboardDeviceStruct((pointer)pDev, &names, &keySyms, modmap,
+ nxagentBell, nxagentChangeKeyboardControl);
+
+ if (!nxagentKeyboard ||
+ (nxagentKeyboard && (strcmp(nxagentKeyboard, "query") == 0)))
+ {
+ goto XkbError;
+ }
+
+ goto XkbEnd;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Going to set rules and init device.\n");
+ #endif
+
+ XkbSetRulesDflts(rules, model, layout, variants, options);
+ XkbInitKeyboardDeviceStruct((pointer)pDev, &names, &keySyms, modmap,
+ nxagentBell, nxagentChangeKeyboardControl);
+ XkbDDXChangeControls((pointer)pDev, xkb->ctrls, xkb->ctrls);
+
+XkbEnd:
+ if (free_model)
+ {
+ free_model = 0;
+ free(model);
+ }
+
+ if (free_layout)
+ {
+ free_layout = 0;
+ free(layout);
+ }
+
+ XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
+
+ xkb = NULL;
+ }
+#endif
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentKeyboardProc: Watchpoint 10.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+#1 U 3 2 80320 bits (10 KB) -> 28621 bits (3 KB) -> 26773/1 -> 9540/1 = 2.806:1
+#98 1 256 bits (0 KB) -> 27 bits (0 KB) -> 256/1 -> 27/1 = 9.481:1
+#101 1 32000 bits (4 KB) -> 2940 bits (0 KB) -> 32000/1 -> 2940/1 = 10.884:1
+#119 1 384 bits (0 KB) -> 126 bits (0 KB) -> 384/1 -> 126/1 = 3.048:1
+*/
+
+ sleep(30);
+
+ #endif
+
+#ifdef _XSERVER64
+ xfree(keymap);
+#else
+ XFree(keymap);
+#endif
+ break;
+ case DEVICE_ON:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_ON].\n");
+ #endif
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return Success;
+ }
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentKeyboardProc: Watchpoint 11.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+#117 1 320 bits (0 KB) -> 52 bits (0 KB) -> 320/1 -> 52/1 = 6.154:1
+*/
+
+ sleep(30);
+
+ #endif
+
+ nxagentEnableKeyboardEvents();
+
+ break;
+
+ case DEVICE_OFF:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_OFF].\n");
+ #endif
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return Success;
+ }
+
+ nxagentDisableKeyboardEvents();
+
+ break;
+
+ case DEVICE_CLOSE:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_CLOSE].\n");
+ #endif
+
+ break;
+ }
+
+ return Success;
+}
+
+Bool LegalModifier(key, pDev)
+ unsigned int key;
+ DevicePtr pDev;
+{
+ return TRUE;
+}
+
+void nxagentNotifyKeyboardChanges(int oldMinKeycode, int oldMaxKeycode)
+{
+ #ifdef XKB
+
+ if (!noXkbExtension)
+ {
+ DeviceIntPtr dev;
+ XkbDescPtr xkb;
+ xkbNewKeyboardNotify nkn;
+
+ dev = inputInfo.keyboard;
+ xkb = dev -> key -> xkbInfo -> desc;
+
+ nkn.deviceID = nkn.oldDeviceID = dev -> id;
+ nkn.minKeyCode = 8;
+ nkn.maxKeyCode = 255;
+ nkn.oldMinKeyCode = oldMinKeycode;
+ nkn.oldMaxKeyCode = oldMaxKeycode;
+ nkn.requestMajor = XkbReqCode;
+ nkn.requestMinor = X_kbGetKbdByName;
+ nkn.changed = XkbNKN_KeycodesMask;
+
+ XkbSendNewKeyboardNotify(dev, &nkn);
+ }
+ else
+ {
+
+ #endif
+
+ int i;
+ xEvent event;
+
+ event.u.u.type = MappingNotify;
+ event.u.mappingNotify.request = MappingKeyboard;
+ event.u.mappingNotify.firstKeyCode = inputInfo.keyboard -> key -> curKeySyms.minKeyCode;
+ event.u.mappingNotify.count = inputInfo.keyboard -> key -> curKeySyms.maxKeyCode -
+ inputInfo.keyboard -> key -> curKeySyms.minKeyCode;
+
+ /*
+ * 0 is the server client
+ */
+
+ for (i = 1; i < currentMaxClients; i++)
+ {
+ if (clients[i] && clients[i] -> clientState == ClientStateRunning)
+ {
+ event.u.u.sequenceNumber = clients[i] -> sequence;
+ WriteEventsToClient(clients[i], 1, &event);
+ }
+ }
+
+ #ifdef XKB
+
+ }
+
+ #endif
+
+}
+
+int nxagentResetKeyboard(void)
+{
+ DeviceIntPtr dev = inputInfo.keyboard;
+ DeviceIntPtr devBackup;
+
+ int result;
+ int oldMinKeycode = 8;
+ int oldMaxKeycode = 255;
+
+ int savedBellPercent;
+ int savedBellPitch;
+ int savedBellDuration;
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return 0;
+ }
+
+ /*
+ * Save bell settings.
+ */
+
+ savedBellPercent = inputInfo.keyboard -> kbdfeed -> ctrl.bell;
+ savedBellPitch = inputInfo.keyboard -> kbdfeed -> ctrl.bell_pitch;
+ savedBellDuration = inputInfo.keyboard -> kbdfeed -> ctrl.bell_duration;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetKeyboard: bellPercent [%d] bellPitch [%d] bellDuration [%d].\n",
+ savedBellPercent, savedBellPitch, savedBellDuration);
+ #endif
+
+ devBackup = xalloc(sizeof(DeviceIntRec));
+
+ if (devBackup == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentSaveKeyboardDeviceData: PANIC! Can't allocate backup structure.\n");
+ #endif
+ }
+ else
+ {
+ memset(devBackup, 0, sizeof(DeviceIntRec));
+ }
+
+ nxagentSaveKeyboardDeviceData(dev, devBackup);
+
+ if (dev->key)
+ {
+ #ifdef XKB
+ if (noXkbExtension == 0 && dev->key->xkbInfo)
+ {
+ oldMinKeycode = dev->key->xkbInfo -> desc -> min_key_code;
+ oldMaxKeycode = dev->key->xkbInfo -> desc -> max_key_code;
+ }
+ #endif
+
+ dev->key=NULL;
+ }
+
+ dev->focus=NULL;
+
+ dev->kbdfeed=NULL;
+
+ #ifdef XKB
+ nxagentTuneXkbWrapper();
+ #endif
+
+ result = (*inputInfo.keyboard -> deviceProc)(inputInfo.keyboard, DEVICE_INIT);
+
+ if (result == Success && inputInfo.keyboard -> key != NULL)
+ {
+
+ /*
+ * Restore bell settings.
+ */
+
+ inputInfo.keyboard -> kbdfeed -> ctrl.bell = savedBellPercent;
+ inputInfo.keyboard -> kbdfeed -> ctrl.bell_pitch = savedBellPitch;
+ inputInfo.keyboard -> kbdfeed -> ctrl.bell_duration = savedBellDuration;
+
+ nxagentNotifyKeyboardChanges(oldMinKeycode, oldMaxKeycode);
+
+ nxagentFreeKeyboardDeviceData(devBackup);
+
+ free(devBackup);
+
+ return 1;
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentResetKeyboard: Can't initialize the keyboard device.\n");
+ #endif
+
+ nxagentRestoreKeyboardDeviceData(devBackup, dev);
+
+ return 0;
+ }
+}
+
+void nxagentCheckAltMetaKeys(CARD8 keycode, int j)
+{
+ if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Meta_L))
+ {
+ nxagentAltMetaMask |= 1 << j;
+ }
+
+ if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Meta_R))
+ {
+ nxagentAltMetaMask |= 1 << j;
+ }
+
+ if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Alt_L))
+ {
+ nxagentAltMetaMask |= 1 << j;
+ }
+
+ if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Alt_R))
+ {
+ nxagentAltMetaMask |= 1 << j;
+ }
+}
+
+static int nxagentSaveKeyboardDeviceData(DeviceIntPtr dev, DeviceIntPtr devBackup)
+{
+ if (devBackup == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentSaveKeyboardDeviceData: PANIC! Pointer to backup structure is null.\n");
+ #endif
+
+ return -1;
+ }
+
+ devBackup -> key = dev -> key;
+
+ devBackup -> focus = dev -> focus;
+
+ devBackup -> kbdfeed = dev -> kbdfeed;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSaveKeyboardDeviceData: Saved device data.\n");
+ #endif
+
+ return 1;
+}
+
+static int nxagentRestoreKeyboardDeviceData(DeviceIntPtr devBackup, DeviceIntPtr dev)
+{
+ if (devBackup == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentRestoreKeyboardDeviceData: PANIC! Pointer to backup structure is null.\n");
+ #endif
+
+ return -1;
+ }
+
+ dev -> key = devBackup -> key;
+
+ dev -> focus = devBackup -> focus;
+
+ dev -> kbdfeed = devBackup -> kbdfeed;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentRestoreKeyboardDeviceData: Restored device data.\n");
+ #endif
+
+ return 1;
+}
+
+
+static int nxagentFreeKeyboardDeviceData(DeviceIntPtr dev)
+{
+ KbdFeedbackPtr k, knext;
+
+ if (dev == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentFreeKeyboardDeviceData: PANIC! Pointer to device structure is null.\n");
+ #endif
+
+ return -1;
+ }
+
+ if (dev->key)
+ {
+ #ifdef XKB
+ if (noXkbExtension == 0 && dev->key->xkbInfo)
+ {
+ XkbFreeInfo(dev->key->xkbInfo);
+ dev->key->xkbInfo = NULL;
+ }
+ #endif
+
+ xfree(dev->key->curKeySyms.map);
+ xfree(dev->key->modifierKeyMap);
+ xfree(dev->key);
+
+ dev->key=NULL;
+ }
+
+ if (dev->focus)
+ {
+ xfree(dev->focus->trace);
+ xfree(dev->focus);
+ dev->focus=NULL;
+ }
+
+ for (k = dev->kbdfeed; k; k = knext)
+ {
+ knext = k->next;
+ #ifdef XKB
+ if (k->xkb_sli)
+ XkbFreeSrvLedInfo(k->xkb_sli);
+ #endif
+ xfree(k);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentFreeKeyboardDeviceData: Freed device data.\n");
+ #endif
+
+ return 1;
+}
+
+#if XKB
+
+int ProcXkbInhibited(register ClientPtr client)
+{
+ unsigned char majorop;
+ unsigned char minorop;
+
+ #ifdef TEST
+ fprintf(stderr, "ProcXkbInhibited: Called.\n");
+ #endif
+
+ majorop = ((xReq *)client->requestBuffer)->reqType;
+
+ #ifdef PANIC
+ if (majorop != (unsigned char)nxagentXkbWrapper.base)
+ {
+ fprintf(stderr, "ProcXkbInhibited: MAJOROP is [%d] but should be [%d].\n",
+ majorop, nxagentXkbWrapper.base);
+ }
+ #endif
+
+ minorop = *((unsigned char *) client->requestBuffer + 1);
+
+ #ifdef TEST
+ fprintf(stderr, "ProcXkbInhibited: MAJOROP is [%d] MINOROP is [%d].\n",
+ majorop, minorop);
+ #endif
+
+ switch (minorop)
+ {
+ case X_kbLatchLockState:
+ case X_kbSetControls:
+ case X_kbSetCompatMap:
+ case X_kbSetIndicatorMap:
+ case X_kbSetNamedIndicator:
+ case X_kbSetNames:
+ case X_kbSetGeometry:
+ case X_kbSetDebuggingFlags:
+ case X_kbSetMap:
+ {
+ return client->noClientException;
+ }
+ case X_kbGetKbdByName:
+ {
+ return BadAccess;
+ }
+ default:
+ {
+ return (client->swapped ? nxagentXkbWrapper.SProcXkbDispatchBackup(client) :
+ nxagentXkbWrapper.ProcXkbDispatchBackup(client));
+ }
+ }
+}
+
+void nxagentInitXkbWrapper(void)
+{
+ ExtensionEntry * extension;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitXkbWrapper: Called.\n");
+ #endif
+
+ if (nxagentOption(InhibitXkb) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitXkbWrapper: Nothing to do.\n");
+ #endif
+
+ return;
+ }
+
+ memset(&nxagentXkbWrapper, 0, sizeof(XkbWrapperRec));
+
+ extension = CheckExtension("XKEYBOARD");
+
+ if (extension != NULL)
+ {
+ nxagentXkbWrapper.base = extension -> base;
+ nxagentXkbWrapper.eventBase = extension -> eventBase;
+ nxagentXkbWrapper.errorBase = extension -> errorBase;
+ nxagentXkbWrapper.ProcXkbDispatchBackup = NULL;
+ nxagentXkbWrapper.SProcXkbDispatchBackup = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitXkbWrapper: base [%d] eventBase [%d] errorBase [%d].\n",
+ extension -> base, extension -> eventBase, extension -> errorBase);
+ #endif
+ }
+ else
+ {
+ nxagentXkbWrapper.base = -1;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitXkbWrapper: XKEYBOARD extension not found.\n");
+ #endif
+ }
+}
+
+void nxagentDisableXkbExtension(void)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisableXkbExtension: Called.\n");
+ #endif
+
+ if (nxagentXkbWrapper.base > 0)
+ {
+ if (nxagentXkbWrapper.ProcXkbDispatchBackup == NULL)
+ {
+ nxagentXkbWrapper.ProcXkbDispatchBackup = ProcVector[nxagentXkbWrapper.base];
+
+ ProcVector[nxagentXkbWrapper.base] = ProcXkbInhibited;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentDisableXkbExtension: Nothing to be done for ProcXkbDispatch.\n");
+ }
+ #endif
+
+ if (nxagentXkbWrapper.SProcXkbDispatchBackup == NULL)
+ {
+ nxagentXkbWrapper.SProcXkbDispatchBackup = SwappedProcVector[nxagentXkbWrapper.base];
+
+ SwappedProcVector[nxagentXkbWrapper.base] = ProcXkbInhibited;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentDisableXkbExtension: Nothing to be done for SProcXkbDispatch.\n");
+ }
+ #endif
+ }
+}
+
+void nxagentEnableXkbExtension(void)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentEnableXkbExtension: Called.\n");
+ #endif
+
+ if (nxagentXkbWrapper.base > 0)
+ {
+ if (nxagentXkbWrapper.ProcXkbDispatchBackup != NULL)
+ {
+ ProcVector[nxagentXkbWrapper.base] = nxagentXkbWrapper.ProcXkbDispatchBackup;
+
+ nxagentXkbWrapper.ProcXkbDispatchBackup = NULL;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentEnableXkbExtension: Nothing to be done for ProcXkbDispatch.\n");
+ }
+ #endif
+
+ if (nxagentXkbWrapper.SProcXkbDispatchBackup != NULL)
+ {
+ SwappedProcVector[nxagentXkbWrapper.base] = nxagentXkbWrapper.SProcXkbDispatchBackup;
+
+ nxagentXkbWrapper.SProcXkbDispatchBackup = NULL;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentEnableXkbExtension: Nothing to be done for SProcXkbDispatch.\n");
+ }
+ #endif
+ }
+}
+
+void nxagentTuneXkbWrapper(void)
+{
+ if (nxagentOption(InhibitXkb) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTuneXkbWrapper: Nothing to do.\n");
+ #endif
+
+ return;
+ }
+
+ if (nxagentKeyboard != NULL &&
+ strcmp(nxagentKeyboard, "query") == 0)
+ {
+ nxagentDisableXkbExtension();
+ }
+ else
+ {
+ nxagentEnableXkbExtension();
+ }
+}
+
+#endif