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.c1814
1 files changed, 1814 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..8db38892e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c
@@ -0,0 +1,1814 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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"
+
+#include "Shadow.h"
+
+#ifdef XKB
+
+#include "globals.h"
+#include "property.h"
+
+#include <X11/extensions/XKB.h>
+
+#define XKBSRV_NEED_FILE_FUNCS
+#include <X11/extensions/XKBsrv.h>
+#include <X11/extensions/XKBconfig.h>
+
+#include "X11/extensions/XKBrules.h"
+
+#include "Xatom.h"
+
+static int nxagentXkbGetNames(char **rules, char **model, char **layout,
+ char **variant, char **options);
+
+static void nxagentKeycodeConversionSetup(void);
+
+#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 CARD8 nxagentConvertedKeycodes[] =
+{
+ /* evdev pc105*/
+ /* 0 */ 0,
+ /* 1 */ 1,
+ /* 2 */ 2,
+ /* 3 */ 3,
+ /* 4 */ 4,
+ /* 5 */ 5,
+ /* 6 */ 6,
+ /* 7 */ 7,
+ /* 8 */ 8,
+ /* 9 */ 9,
+ /* 10 */ 10,
+ /* 11 */ 11,
+ /* 12 */ 12,
+ /* 13 */ 13,
+ /* 14 */ 14,
+ /* 15 */ 15,
+ /* 16 */ 16,
+ /* 17 */ 17,
+ /* 18 */ 18,
+ /* 19 */ 19,
+ /* 20 */ 20,
+ /* 21 */ 21,
+ /* 22 */ 22,
+ /* 23 */ 23,
+ /* 24 */ 24,
+ /* 25 */ 25,
+ /* 26 */ 26,
+ /* 27 */ 27,
+ /* 28 */ 28,
+ /* 29 */ 29,
+ /* 30 */ 30,
+ /* 31 */ 31,
+ /* 32 */ 32,
+ /* 33 */ 33,
+ /* 34 */ 34,
+ /* 35 */ 35,
+ /* 36 */ 36,
+ /* 37 */ 37,
+ /* 38 */ 38,
+ /* 39 */ 39,
+ /* 40 */ 40,
+ /* 41 */ 41,
+ /* 42 */ 42,
+ /* 43 */ 43,
+ /* 44 */ 44,
+ /* 45 */ 45,
+ /* 46 */ 46,
+ /* 47 */ 47,
+ /* 48 */ 48,
+ /* 49 */ 49,
+ /* 50 */ 50,
+ /* 51 */ 51,
+ /* 52 */ 52,
+ /* 53 */ 53,
+ /* 54 */ 54,
+ /* 55 */ 55,
+ /* 56 */ 56,
+ /* 57 */ 57,
+ /* 58 */ 58,
+ /* 59 */ 59,
+ /* 60 */ 60,
+ /* 61 */ 61,
+ /* 62 */ 62,
+ /* 63 */ 63,
+ /* 64 */ 64,
+ /* 65 */ 65,
+ /* 66 */ 66,
+ /* 67 */ 67,
+ /* 68 */ 68,
+ /* 69 */ 69,
+ /* 70 */ 70,
+ /* 71 */ 71,
+ /* 72 */ 72,
+ /* 73 */ 73,
+ /* 74 */ 74,
+ /* 75 */ 75,
+ /* 76 */ 76,
+ /* 77 */ 77,
+ /* 78 */ 78,
+ /* 79 */ 79,
+ /* 80 */ 80,
+ /* 81 */ 81,
+ /* 82 */ 82,
+ /* 83 */ 83,
+ /* 84 */ 84,
+ /* 85 */ 85,
+ /* 86 */ 86,
+ /* 87 */ 87,
+ /* 88 */ 88,
+ /* 89 */ 89,
+ /* 90 */ 90,
+ /* 91 */ 91,
+ /* 92 */ 124,
+ /* 93 */ 93,
+ /* 94 */ 94,
+ /* 95 */ 95,
+ /* 96 */ 96,
+ /* 97 */ 211,
+ /* 98 */ 98,
+ /* 99 */ 99,
+ /* 100 */ 100,
+ /* 101 */ 208,
+ /* 102 */ 102,
+ /* 103 */ 103,
+ /* 104 */ 108,
+ /* 105 */ 109,
+ /* 106 */ 112,
+ /* 107 */ 111,
+ /* 108 */ 113,
+ /* 109 */ 109,
+ /* 110 */ 97,
+ /* 111 */ 98,
+ /* 112 */ 99,
+ /* 113 */ 100,
+ /* 114 */ 102,
+ /* 115 */ 103,
+ /* 116 */ 104,
+ /* 117 */ 105,
+ /* 118 */ 106,
+ /* 119 */ 107,
+ /* 120 */ 120,
+ /* 121 */ 121,
+ /* 122 */ 122,
+ /* 123 */ 123,
+ /* 124 */ 124,
+ /* 125 */ 126,
+ /* 126 */ 126,
+ /* 127 */ 110,
+ /* 128 */ 128,
+ /* 129 */ 129,
+ /* 130 */ 130,
+ /* 131 */ 131,
+ /* 132 */ 133,
+ /* 133 */ 115,
+ /* 134 */ 116,
+ /* 135 */ 117,
+ /* 136 */ 136,
+ /* 137 */ 137,
+ /* 138 */ 138,
+ /* 139 */ 139,
+ /* 140 */ 140,
+ /* 141 */ 141,
+ /* 142 */ 142,
+ /* 143 */ 143,
+ /* 144 */ 144,
+ /* 145 */ 145,
+ /* 146 */ 146,
+ /* 147 */ 147,
+ /* 148 */ 148,
+ /* 149 */ 149,
+ /* 150 */ 150,
+ /* 151 */ 151,
+ /* 152 */ 152,
+ /* 153 */ 153,
+ /* 154 */ 154,
+ /* 155 */ 155,
+ /* 156 */ 156,
+ /* 157 */ 157,
+ /* 158 */ 158,
+ /* 159 */ 159,
+ /* 160 */ 160,
+ /* 161 */ 161,
+ /* 162 */ 162,
+ /* 163 */ 163,
+ /* 164 */ 164,
+ /* 165 */ 165,
+ /* 166 */ 166,
+ /* 167 */ 167,
+ /* 168 */ 168,
+ /* 169 */ 169,
+ /* 170 */ 170,
+ /* 171 */ 171,
+ /* 172 */ 172,
+ /* 173 */ 173,
+ /* 174 */ 174,
+ /* 175 */ 175,
+ /* 176 */ 176,
+ /* 177 */ 177,
+ /* 178 */ 178,
+ /* 179 */ 179,
+ /* 180 */ 180,
+ /* 181 */ 181,
+ /* 182 */ 182,
+ /* 183 */ 183,
+ /* 184 */ 184,
+ /* 185 */ 185,
+ /* 186 */ 186,
+ /* 187 */ 187,
+ /* 188 */ 188,
+ /* 189 */ 189,
+ /* 190 */ 190,
+ /* 191 */ 118,
+ /* 192 */ 119,
+ /* 193 */ 120,
+ /* 194 */ 121,
+ /* 195 */ 122,
+ /* 196 */ 196,
+ /* 197 */ 197,
+ /* 198 */ 198,
+ /* 199 */ 199,
+ /* 200 */ 200,
+ /* 201 */ 201,
+ /* 202 */ 202,
+ /* 203 */ 93,
+ /* 204 */ 125,
+ /* 205 */ 156,
+ /* 206 */ 127,
+ /* 207 */ 128,
+ /* 208 */ 208,
+ /* 209 */ 209,
+ /* 210 */ 210,
+ /* 211 */ 211,
+ /* 212 */ 212,
+ /* 213 */ 213,
+ /* 214 */ 214,
+ /* 215 */ 215,
+ /* 216 */ 216,
+ /* 217 */ 217,
+ /* 218 */ 218,
+ /* 219 */ 219,
+ /* 220 */ 220,
+ /* 221 */ 221,
+ /* 222 */ 222,
+ /* 223 */ 223,
+ /* 224 */ 224,
+ /* 225 */ 225,
+ /* 226 */ 226,
+ /* 227 */ 227,
+ /* 228 */ 228,
+ /* 229 */ 229,
+ /* 230 */ 230,
+ /* 231 */ 231,
+ /* 232 */ 232,
+ /* 233 */ 233,
+ /* 234 */ 234,
+ /* 235 */ 235,
+ /* 236 */ 236,
+ /* 237 */ 237,
+ /* 238 */ 238,
+ /* 239 */ 239,
+ /* 240 */ 240,
+ /* 241 */ 241,
+ /* 242 */ 242,
+ /* 243 */ 243,
+ /* 244 */ 244,
+ /* 245 */ 245,
+ /* 246 */ 246,
+ /* 247 */ 247,
+ /* 248 */ 248,
+ /* 249 */ 249,
+ /* 250 */ 250,
+ /* 251 */ 251,
+ /* 252 */ 252,
+ /* 253 */ 253,
+ /* 254 */ 254,
+ /* 255 */ 255
+};
+
+static int nxagentKeycodeConversion = 0;
+
+CARD8 nxagentConvertKeycode(CARD8 k)
+{
+ if (nxagentKeycodeConversion != 0)
+ {
+ return nxagentConvertedKeycodes[k];
+ }
+ else
+ {
+ return k;
+ }
+}
+
+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 (keymap64 == 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);
+
+ nxagentKeycodeConversionSetup();
+
+ if (xkb == NULL || xkb->geom == NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: No current keyboard.\n");
+ if (xkb == NULL)
+ {
+ fprintf(stderr, "nxagentKeyboardProc: xkb is null.\n");
+ }
+ else
+ {
+ fprintf(stderr, "nxagentKeyboardProc: xkb->geom is null.\n");
+ }
+ 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);
+
+ 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);
+
+ free(nxagentXkbConfigFilePath);
+
+ 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 (nxagentOption(Shadow) == 1 && pDev && pDev->key)
+ {
+ NXShadowInitKeymap(&(pDev->key->curKeySyms));
+ }
+
+ 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();
+ }
+}
+
+static int nxagentXkbGetNames(char **rules, char **model, char **layout,
+ char **variant, char **options)
+{
+ Atom atom;
+ #ifdef _XSERVER64
+ Atom64 type;
+ #else
+ Atom type;
+ #endif
+ int format;
+ unsigned long n;
+ unsigned long after;
+ char *data;
+ char *name;
+ Status result;
+
+ data = name = NULL;
+
+ *rules = NULL;
+ *model = NULL;
+ *layout = NULL;
+ *variant = NULL;
+ *options = NULL;
+
+ atom = XInternAtom(nxagentDisplay, "_XKB_RULES_NAMES", 1);
+
+ if (atom == 0)
+ {
+ return 0;
+ }
+
+ result = XGetWindowProperty(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ atom, 0, 256, 0, XA_STRING, &type, &format,
+ &n, &after, (unsigned char **)&data);
+
+ if (result !=Success || data == NULL)
+ {
+ return 0;
+ }
+
+ if ((after > 0) || (type != XA_STRING) || (format != 8))
+ {
+ if (data != NULL)
+ {
+ XFree(data);
+ return 0;
+ }
+ }
+
+ name = data;
+
+ if (name < data + n)
+ {
+ *rules = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *model = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *layout = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *variant = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *options = name;
+ name += strlen(name) + 1;
+ }
+
+ return n;
+}
+
+void nxagentKeycodeConversionSetup(void)
+{
+ char *drules = 0;
+ char *dmodel = 0;
+ char *dlayout = 0;
+ char *dvariant = 0;
+ char *doptions = 0;
+ unsigned int drulesLen;
+
+ nxagentKeycodeConversion = 0;
+
+ drulesLen = nxagentXkbGetNames(&drules, &dmodel, &dlayout,
+ &dvariant, &doptions);
+
+ #ifdef DEBUG
+ if (drulesLen != 0 && drules != NULL && dmodel != NULL)
+ {
+ fprintf(stderr, "nxagentKeycodeConversionSetup: "
+ "Remote: [%s,%s,%s,%s,%s].\n", drules, dmodel, dlayout,
+ dvariant, doptions);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentKeycodeConversionSetup: "
+ "Failed to retrieve remote rules.\n");
+ }
+ #endif
+
+ if (nxagentOption(ClientOs) == ClientOsLinux &&
+ drules != NULL && dmodel != NULL &&
+ (strcmp(drules, "evdev") == 0 ||
+ strcmp(dmodel, "evdev") == 0))
+ {
+ nxagentKeycodeConversion = 1;
+ }
+
+ if (drules != NULL)
+ {
+ XFree(drules);
+ }
+}
+
+void nxagentResetKeycodeConversion(void)
+{
+ int result;
+ XkbAgentInfoRec info;
+
+ result = XkbQueryExtension(nxagentDisplay, &info.Opcode, &info.EventBase,
+ &info.ErrorBase, &info.MajorVersion,
+ &info.MinorVersion);
+
+ if (result != 0)
+ {
+ nxagentKeycodeConversionSetup();
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentResetKeycodeConversion: "
+ "WARNING! Failed to query XKB extension.\n");
+ #endif
+
+ nxagentKeycodeConversion = 0;
+ }
+}
+
+#endif