[X2go-Commits] nx-libs.git - master (branch) updated: redist-client/3.5.0.16-3-g34f232c

X2Go dev team git-admin at x2go.org
Tue Dec 4 13:31:39 CET 2012


The branch, master has been updated
       via  34f232c142929a1f833faae96873e009b317ec2b (commit)
      from  5a640efd1002d5fadff72542afb8e00bd14bcb6e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 34f232c142929a1f833faae96873e009b317ec2b
Author: Alexander Wuerstlein <arw at arw.name>
Date:   Tue Dec 4 13:31:01 2012 +0100

    Add patch: 210_nxagent_configurable-keystrokes.full.patch, replaces the hardcoded nxagent keybindings by a configurable table of keybindings.

-----------------------------------------------------------------------

Summary of changes:
 debian/changelog                                   |    4 +
 debian/control                                     |    1 +
 .../210_nxagent_configurable-keystrokes.full.patch |  963 ++++++++++++++++++++
 debian/patches/series                              |    1 +
 4 files changed, 969 insertions(+)
 create mode 100644 debian/patches/210_nxagent_configurable-keystrokes.full.patch

The diff of changes is:
diff --git a/debian/changelog b/debian/changelog
index 0fb9570..1278241 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -3,6 +3,10 @@ nx-libs (2:3.5.0.17-0) UNRELEASED; urgency=low
   [ Jan Engelhardt ]
   * Fix /bin/Makefile. Add $(DESTDIR) to every install path.
 
+  [ Alexander Wuerstlein ]
+  * Add patch: 210_nxagent_configurable-keystrokes.full.patch, replaces the
+    hardcoded nxagent keybindings by a configurable table of keybindings.
+
  -- Mike Gabriel <mike.gabriel at das-netzwerkteam.de>  Wed, 07 Nov 2012 21:14:23 +0100
 
 nx-libs (2:3.5.0.16-0) unstable; urgency=low
diff --git a/debian/control b/debian/control
index 75a7f30..f34b1d2 100644
--- a/debian/control
+++ b/debian/control
@@ -13,6 +13,7 @@ Build-Depends:
  zlib1g-dev,
  quilt (>= 0.46-7~),
  libxmltok1-dev,
+ libxml2-dev,
  autoconf
 Build-Conflicts:
  x11proto-core-dev,
diff --git a/debian/patches/210_nxagent_configurable-keystrokes.full.patch b/debian/patches/210_nxagent_configurable-keystrokes.full.patch
new file mode 100644
index 0000000..0045e8a
--- /dev/null
+++ b/debian/patches/210_nxagent_configurable-keystrokes.full.patch
@@ -0,0 +1,963 @@
+Author: Alexander Wuerstlein <arw at arw.name>
+Description: Make nxagent-specific keyboard bindings configurable
+ Replaces the hardcoded nxagent keybindings by a configurable
+ table of keybindings. The default configuration is the same as the
+ original one, to maintain compatibility. A user/administrator can either
+ specify a command line parameter, environment variable or place a file
+ in ~/.nx/config/keystroke.cfg or /etc/nx/keystroke.cfg to reconfigure
+ these keybindings.
+ .
+ The configuration file format is XML, a dependency on libxml2 is added
+ to allow parsing the configuration.
+diff --git a/nx-X11/programs/Xserver/Imakefile b/nx-X11/programs/Xserver/Imakefile
+index 3f53eca..80e3a71 100644
+--- a/nx-X11/programs/Xserver/Imakefile
++++ b/nx-X11/programs/Xserver/Imakefile
+@@ -1013,15 +1013,18 @@ $(NXAGENTOBJS) $(NXAGENTLIBS) $(NXAGENTSYSLIBS):: $(NXAGENTDIRS)
+ #if defined(SunArchitecture)
+ NXAGENTNXLIBS = -L ../../../nxcomp -L ../../../nxcompext -L ../../../nxcompshad \
+                 -lXcomp -lXcompext -lXcompshad -lrt -L/usr/sfw/lib -lNX_Xrender -lNX_Xfixes \
+-                -L../../../nx-X11/exports/lib -lNX_Xtst -lNX_Xdamage -lNX_Xrandr -lNX_Xcomposite -lNX_Xdmcp
++                -L../../../nx-X11/exports/lib -lNX_Xtst -lNX_Xdamage -lNX_Xrandr -lNX_Xcomposite -lNX_Xdmcp \
++`pkg-config --libs libxml-2.0`
+ #elif defined(cygwinArchitecture)
+ NXAGENTNXLIBS = -L ../../../nxcomp -L ../../../nxcompext \
+                 -lXcomp -lXcompext -lNX_Xrender -lNX_X11 -lNX_Xext -lNX_Xcomposite -lNX_Xfixes \
+-                -L ../../../nxcompshad -lXcompshad -L../../../nx-X11/exports/lib -lNX_Xtst -lNX_Xdmcp
++                -L ../../../nxcompshad -lXcompshad -L../../../nx-X11/exports/lib -lNX_Xtst -lNX_Xdmcp \
++`pkg-config --libs libxml-2.0`
+ #else
+ NXAGENTNXLIBS = -L ../../../nxcomp -L ../../../nxcompext -L ../../../nxcompshad \
+                 -lXcomp -lXcompext -lXcompshad -lNX_Xrender -lNX_X11 -lNX_Xext -lNX_Xfixes \
+-                -L../../../nx-X11/exports/lib -lNX_Xtst -lNX_Xdamage -lNX_Xrandr -lNX_Xcomposite -lNX_Xinerama -lNX_Xdmcp
++                -L../../../nx-X11/exports/lib -lNX_Xtst -lNX_Xdamage -lNX_Xrandr -lNX_Xcomposite -lNX_Xinerama -lNX_Xdmcp \
++`pkg-config --libs libxml-2.0`
+ #endif
+ 
+ #endif
+diff --git a/nx-X11/programs/Xserver/hw/nxagent/Imakefile b/nx-X11/programs/Xserver/hw/nxagent/Imakefile
+index a8e1621..ccd53d1 100644
+--- a/nx-X11/programs/Xserver/hw/nxagent/Imakefile
++++ b/nx-X11/programs/Xserver/hw/nxagent/Imakefile
+@@ -142,7 +142,8 @@ INCLUDES = -I. -I../../../../../nxcomp -I../../../../../nxcompext -I../../../../
+            -I../../miext/damage -I../../miext/cw \
+    -I../../GL/glx -I../../GL/include -I../../../../lib/GL/include -I../../Xext \
+            -I$(EXTINCSRC) -I$(XINCLUDESRC) \
+-   $(VFBINCLUDES) $(NXFONTINCLUDES) $(LIBXRANDRINCLUDES)
++   $(VFBINCLUDES) $(NXFONTINCLUDES) $(LIBXRANDRINCLUDES) \
++   `pkg-config --cflags-only-I libxml-2.0`
+ #ifdef SunArchitecture
+ INCLUDES = -I. -I../../../../../nxcomp -I../../../../../nxcompext -I../../../../../nxcompshad \
+            -I../../../../extras/Mesa/include \
+@@ -152,7 +153,8 @@ INCLUDES = -I. -I../../../../../nxcomp -I../../../../../nxcompext -I../../../../
+       -I../../GL/glx -I../../GL/include -I../../../../lib/GL/include -I../../Xext \
+            -I../../miext/damage -I../../miext/cw \
+            -I$(EXTINCSRC) -I$(XINCLUDESRC) \
+-          $(VFBINCLUDES) $(NXFONTINCLUDES) $(LIBXRANDRINCLUDES)
++          $(VFBINCLUDES) $(NXFONTINCLUDES) $(LIBXRANDRINCLUDES) \
++          `pkg-config --cflags-only-I libxml-2.0`
+ #else
+ #ifdef cygwinArchitecture
+ INCLUDES = -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+@@ -162,7 +164,8 @@ INCLUDES = -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+            -I../../../../../nxcomp -I../../../../../nxcompext -I../../../../../nxcompshad \
+            -I../../../../extras/Mesa/include \
+            -I$(EXTINCSRC) -I$(XINCLUDESRC) \
+-          $(VFBINCLUDES) $(NXFONTINCLUDES) $(LIBXRANDRINCLUDES)
++          $(VFBINCLUDES) $(NXFONTINCLUDES) $(LIBXRANDRINCLUDES) \
++          `pkg-config --cflags-only-I libxml-2.0`
+ #endif
+ #endif
+ 
+diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c
+index 6c6e477..b5f4acf 100644
+--- a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c
++++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c
+@@ -28,8 +28,15 @@
+ #include "Keystroke.h"
+ #include "Drawable.h"
+ 
++#include <unistd.h>
++
++#include <libxml/parser.h>
++#include <libxml/tree.h>
++
+ extern Bool nxagentWMIsRunning;
+ extern Bool nxagentIpaq;
++extern char *nxagentKeystrokeFile;
++Bool nxagentKeystrokeFileParsed = False;
+ 
+ #ifdef NX_DEBUG_INPUT
+ int nxagentDebugInputDevices = 0;
+@@ -47,10 +54,369 @@ extern void nxagentDeactivateInputDevicesGrabs();
+ #undef  DEBUG
+ #undef  DUMP
+ 
++
++/* this table is used to parse actions given on the command line or in the
++ * config file, therefore indices have to match the enum in Keystroke.h */
++char * nxagentSpecialKeystrokeNames[] = {
++       "end_marker",
++       "close_session",
++       "switch_all_screens",
++       "minimize",
++       "left",
++       "up",
++       "right",
++       "down",
++       "resize",
++       "defer",
++       "ignore",
++       "force_synchronization",
++
++       "debug_tree",
++       "regions_on_screen",
++       "test_input",
++       "deactivate_input_devices_grab",
++
++       "fullscreen",
++       "viewport_move_left",
++       "viewport_move_up",
++       "viewport_move_right",
++       "viewport_move_down",
++       NULL,
++};
++
++struct nxagentSpecialKeystrokeMap default_map[] = {
++  /* stroke, modifierMask, modifierAltMeta, keysym */
++  {KEYSTROKE_DEBUG_TREE, ControlMask, 1, XK_q},
++  {KEYSTROKE_DEBUG_TREE, ControlMask, 1, XK_Q},
++  {KEYSTROKE_CLOSE_SESSION, ControlMask, 1, XK_t},
++  {KEYSTROKE_CLOSE_SESSION, ControlMask, 1, XK_T},
++  {KEYSTROKE_SWITCH_ALL_SCREENS, ControlMask, 1, XK_f},
++  {KEYSTROKE_SWITCH_ALL_SCREENS, ControlMask, 1, XK_F},
++  {KEYSTROKE_MINIMIZE, ControlMask, 1, XK_m},
++  {KEYSTROKE_MINIMIZE, ControlMask, 1, XK_M},
++  {KEYSTROKE_LEFT, ControlMask, 1, XK_Left},
++  {KEYSTROKE_LEFT, ControlMask, 1, XK_KP_Left},
++  {KEYSTROKE_UP, ControlMask, 1, XK_Up},
++  {KEYSTROKE_UP, ControlMask, 1, XK_KP_Up},
++  {KEYSTROKE_RIGHT, ControlMask, 1, XK_Right},
++  {KEYSTROKE_RIGHT, ControlMask, 1, XK_KP_Right},
++  {KEYSTROKE_DOWN, ControlMask, 1, XK_Down},
++  {KEYSTROKE_DOWN, ControlMask, 1, XK_KP_Down},
++  {KEYSTROKE_RESIZE, ControlMask, 1, XK_r},
++  {KEYSTROKE_RESIZE, ControlMask, 1, XK_R},
++  {KEYSTROKE_DEFER, ControlMask, 1, XK_e},
++  {KEYSTROKE_DEFER, ControlMask, 1, XK_E},
++  {KEYSTROKE_IGNORE, ControlMask, 1, XK_BackSpace},
++  {KEYSTROKE_IGNORE, 0, 0, XK_Terminate_Server},
++  {KEYSTROKE_FORCE_SYNCHRONIZATION, ControlMask, 1, XK_j},
++  {KEYSTROKE_FORCE_SYNCHRONIZATION, ControlMask, 1, XK_J},
++  {KEYSTROKE_REGIONS_ON_SCREEN, ControlMask, 1, XK_a},
++  {KEYSTROKE_REGIONS_ON_SCREEN, ControlMask, 1, XK_A},
++  {KEYSTROKE_TEST_INPUT, ControlMask, 1, XK_x},
++  {KEYSTROKE_TEST_INPUT, ControlMask, 1, XK_X},
++  {KEYSTROKE_DEACTIVATE_INPUT_DEVICES_GRAB, ControlMask, 1, XK_y},
++  {KEYSTROKE_DEACTIVATE_INPUT_DEVICES_GRAB, ControlMask, 1, XK_Y},
++  {KEYSTROKE_FULLSCREEN, ControlMask | ShiftMask, 1, XK_f},
++  {KEYSTROKE_FULLSCREEN, ControlMask | ShiftMask, 1, XK_F},
++  {KEYSTROKE_VIEWPORT_MOVE_LEFT, ControlMask | ShiftMask, 1, XK_Left},
++  {KEYSTROKE_VIEWPORT_MOVE_LEFT, ControlMask | ShiftMask, 1, XK_KP_Left},
++  {KEYSTROKE_VIEWPORT_MOVE_UP, ControlMask | ShiftMask, 1, XK_Up},
++  {KEYSTROKE_VIEWPORT_MOVE_UP, ControlMask | ShiftMask, 1, XK_KP_Up},
++  {KEYSTROKE_VIEWPORT_MOVE_RIGHT, ControlMask | ShiftMask, 1, XK_Right},
++  {KEYSTROKE_VIEWPORT_MOVE_RIGHT, ControlMask | ShiftMask, 1, XK_KP_Right},
++  {KEYSTROKE_VIEWPORT_MOVE_DOWN, ControlMask | ShiftMask, 1, XK_Down},
++  {KEYSTROKE_VIEWPORT_MOVE_DOWN, ControlMask | ShiftMask, 1, XK_KP_Down},
++  {KEYSTROKE_END_MARKER, 0, 0, 0},
++};
++struct nxagentSpecialKeystrokeMap *map = default_map;
++
++static int modifier_matches(unsigned int mask, int compare_alt_meta, unsigned int state)
++{
++  /* nxagentAltMetaMask needs special handling
++   * it seems to me its an and-ed mask of all possible meta and alt keys
++   * somehow...
++   *
++   * otherwise this function would be just a simple bitop
++   */
++  int ret = 1;
++
++  if (compare_alt_meta) {
++    if (! (state & nxagentAltMetaMask)) {
++      ret = 0;
++    }
++
++    mask &= ~nxagentAltMetaMask;
++  }
++
++  /* all modifiers except meta/alt have to match exactly, extra bits are evil */
++  if ((mask & state) != mask) {
++    ret = 0;
++  }
++
++  return ret;
++}
++
++static int read_binding_from_xmlnode(xmlNode *node, struct nxagentSpecialKeystrokeMap *ret)
++{
++  int successful = 0;
++  struct nxagentSpecialKeystrokeMap new = {0, 0, 0, 0};
++  xmlAttr *attr;
++
++  for (attr = node->properties; attr; attr = attr->next)
++  {
++    /* ignore attributes without data (which should never happen anyways) */
++    if (attr->children->content == NULL)
++    {
++      char *aname = (attr->name)?(attr->name):"unknown";
++      fprintf(stderr, "attribute %s with NULL value", aname);
++      continue;
++    }
++    if (strcmp((char *)attr->name, "action") == 0)
++    {
++      int i;
++      for (i = 0; nxagentSpecialKeystrokeNames[i] != NULL; i++)
++      {
++        if (strcmp(nxagentSpecialKeystrokeNames[i],(char *)attr->children->content) == 0)
++        {
++          /* this relies on the values of enum nxagentSpecialKeystroke and the
++           * indices of nxagentSpecialKeystrokeNames being in sync */
++          new.stroke = i;
++          break;
++        }
++      }
++      continue;
++    }
++    else if (strcmp((char *)attr->name, "key") == 0)
++    {
++      new.keysym = XStringToKeysym((char *)attr->children->content);
++      /* NoSymbol is usually 0, but could there be weird implementations? */
++      if (new.keysym == NoSymbol)
++      {
++        new.keysym = 0;
++      }
++      continue;
++    }
++
++    /* ignore attributes with value="0" or "false", everything else is interpreted as true */
++    if (strcmp((char *)attr->children->content, "0") == 0 || strcmp((char *)attr->children->content, "false") == 0)
++      continue;
++
++    if (strcmp((char *)attr->name, "Mod1") == 0)
++    {
++      new.modifierMask |= Mod1Mask;
++    }
++    else if (strcmp((char *)attr->name, "Mod2") == 0)
++    {
++      new.modifierMask |= Mod2Mask;
++    }
++    else if (strcmp((char *)attr->name, "Mod3") == 0)
++    {
++      new.modifierMask |= Mod3Mask;
++    }
++    else if (strcmp((char *)attr->name, "Mod4") == 0)
++    {
++      new.modifierMask |= Mod4Mask;
++    }
++    else if (strcmp((char *)attr->name, "Control") == 0)
++    {
++      new.modifierMask |= ControlMask;
++    }
++    else if (strcmp((char *)attr->name, "Shift") == 0)
++    {
++      new.modifierMask |= ShiftMask;
++    }
++    else if (strcmp((char *)attr->name, "Lock") == 0)
++    {
++      new.modifierMask |= LockMask;
++    }
++    else if (strcmp((char *)attr->name, "AltMeta") == 0)
++    {
++      new.modifierAltMeta = 1;
++    }
++  }
++
++  if (new.stroke != 0 && new.keysym != 0)
++  {
++    /* keysym and stroke are required, everything else is optional */
++    successful = 1;
++    memcpy(ret, &new, sizeof(struct nxagentSpecialKeystrokeMap));
++  }
++  return successful;
++}
++
++/*
++ * searches a keystroke xml file
++ *
++ * search order:
++ *  - '-keystrokefile' commandline parameter
++ *  - $NXAGENT_KEYSTROKEFILE environment variable
++ *  - $HOME/.nx/config/keystroke.cfg
++ *  - /etc/nx/keystroke.cfg
++ *  - hardcoded traditional NX default settings
++ */
++static void parse_keystroke_file(void)
++{
++  char *filename = NULL;
++
++  char *homefile = "/.nx/config/keystroke.cfg";
++  char *etcfile = "/etc/nx/keystroke.cfg";
++
++  if (nxagentKeystrokeFile != NULL && access(nxagentKeystrokeFile, R_OK) == 0)
++  {
++    filename = strdup(nxagentKeystrokeFile);
++    if (filename == NULL)
++    {
++      fprintf(stderr, "malloc failed");
++      exit(EXIT_FAILURE);
++    }
++  }
++  else if ((filename = getenv("NXAGENT_KEYSTROKEFILE")) != NULL && access(filename, R_OK) == 0)
++  {
++    filename = strdup(filename);
++    if (filename == NULL)
++    {
++      fprintf(stderr, "malloc failed");
++      exit(EXIT_FAILURE);
++    }
++  }
++  else
++  {
++    char *homedir = getenv("HOME");
++    filename = NULL;
++    if (homedir != NULL)
++    {
++      homedir = strdup(homedir);
++      if (homedir == NULL)
++      {
++        fprintf(stderr, "malloc failed");
++exit(EXIT_FAILURE);
++      }
++      filename = calloc(1, strlen(homefile) + strlen(homedir) + 1);
++      if (filename == NULL)
++      {
++        fprintf(stderr, "malloc failed");
++        exit(EXIT_FAILURE);
++      }
++      strcpy(filename, homedir);
++      strcpy(filename + strlen(homedir), homefile);
++      if (homedir)
++      {
++        free(homedir);
++      }
++    }
++
++    if (access(filename, R_OK) == 0)
++    {
++      /* empty */
++    }
++    else if (access(etcfile, R_OK == 0))
++    {
++      if (filename)
++        free(filename);
++      filename = strdup(etcfile);
++      if (filename == NULL)
++      {
++        fprintf(stderr, "malloc failed");
++        exit(EXIT_FAILURE);
++      }
++    }
++    else
++    {
++      if (filename)
++free(filename);
++      filename = NULL;
++    }
++  }
++
++  /* now we know which file to read, if any */
++  if (filename)
++  {
++    xmlDoc *doc = NULL;
++    xmlNode *root = NULL;
++    LIBXML_TEST_VERSION
++    doc = xmlReadFile(filename, NULL, 0);
++    if (doc != NULL)
++    {
++      xmlNode *cur = NULL;
++      root = xmlDocGetRootElement(doc);
++
++      for (cur = root; cur; cur = cur->next)
++      {
++        if (cur->type == XML_ELEMENT_NODE && strcmp((char *)cur->name, "keystrokes") == 0)
++{
++          xmlNode *bindings = NULL;
++          int num = 0;
++          int idx = 0;
++
++          for (bindings = cur->children; bindings; bindings = bindings->next)
++          {
++            if (bindings->type == XML_ELEMENT_NODE && strcmp((char *)bindings->name, "keystroke") == 0)
++            {
++              num++;
++            }
++          }
++          map = calloc((num + 1), sizeof(struct nxagentSpecialKeystrokeMap));
++          if (map == NULL)
++          {
++            fprintf(stderr, "malloc failed");
++            exit(EXIT_FAILURE);
++          }
++
++          for (bindings = cur->children; bindings; bindings = bindings->next)
++          {
++            if (bindings->type == XML_ELEMENT_NODE && strcmp((char *)bindings->name, "keystroke") == 0)
++            {
++              int res = 0;
++              res = read_binding_from_xmlnode(bindings, &(map[idx]));
++              if (res)
++                idx++;
++            }
++          }
++
++          map[idx].stroke = KEYSTROKE_END_MARKER;
++        }
++      }
++
++      xmlFreeDoc(doc);
++      xmlCleanupParser();
++    }
++    else
++    {
++      #ifdef DEBUG
++      fprintf("XML parsing for %s failed\n", filename);
++      #endif
++    }
++    free(filename);
++  }
++}
++
++static enum nxagentSpecialKeystroke find_keystroke(XKeyEvent *X)
++{
++  KeySym keysym = XKeycodeToKeysym(nxagentDisplay, X->keycode, 0);
++  struct nxagentSpecialKeystrokeMap *cur = map;
++
++  if (! nxagentKeystrokeFileParsed)
++  {
++    parse_keystroke_file();
++    nxagentKeystrokeFileParsed = True;
++  }
++
++  enum nxagentSpecialKeystroke ret = KEYSTROKE_NOTHING;
++
++  while ((cur++)->stroke != KEYSTROKE_END_MARKER) {
++    if (cur->keysym == keysym && modifier_matches(cur->modifierMask, cur->modifierAltMeta, X->state)) {
++      return cur->stroke;
++    }
++  }
++
++  return ret;
++}
++
+ int nxagentCheckSpecialKeystroke(XKeyEvent *X, enum HandleEventResult *result)
+ {
+   KeySym sym;
+   int index = 0;
++  enum nxagentSpecialKeystroke stroke = find_keystroke(X);
+ 
+   *result = doNothing;
+ 
+@@ -87,257 +453,128 @@ int nxagentCheckSpecialKeystroke(XKeyEvent *X, enum HandleEventResult *result)
+     return 1;
+   }
+ 
+-  if ((X -> state & nxagentAltMetaMask) &&
+-          ((X -> state & (ControlMask | ShiftMask)) == ControlMask))
+-  {
+-    switch (sym)
+-    {
++  switch (stroke) {
++    case KEYSTROKE_DEBUG_TREE:
+       #ifdef DEBUG_TREE
+-
+-      case XK_q:
+-      case XK_Q:
+-      {
+-        *result = doDebugTree;
+-
+-        break;
+-      }
+-
+-      #endif /* DEBUG_TREE */
+-
+-      case XK_t:
+-      case XK_T:
+-      {
+-        *result = doCloseSession;
+-
+-        break;
+-      }
+-      case XK_f:
+-      case XK_F:
+-      {
+-        if (nxagentOption(Rootless) == False)
+-        {
+-          *result = doSwitchAllScreens;
+-        }
+-
+-        break;
+-      }
+-      case XK_m:
+-      case XK_M:
+-      {
+-        if (nxagentOption(Rootless) == False)
+-        {
+-          *result = doMinimize;
+-        }
+-
+-        break;
+-      }
+-      case XK_Left:
+-      case XK_KP_Left:
+-      {
+-        if (nxagentOption(Rootless) == False &&
+-                nxagentOption(DesktopResize) == False)
+-        {
+-          *result = doViewportLeft;
+-        }
+-
+-        break;
++      *result = doDebugTree;
++      #endif
++      break;
++    case KEYSTROKE_CLOSE_SESSION:
++      *result = doCloseSession;
++      break;
++    case KEYSTROKE_SWITCH_ALL_SCREENS:
++      if (nxagentOption(Rootless) == False) {
++        *result = doSwitchAllScreens;
+       }
+-      case XK_Up:
+-      case XK_KP_Up:
+-      {
+-        if (nxagentOption(Rootless) == False &&
+-                nxagentOption(DesktopResize) == False)
+-        {
+-          *result = doViewportUp;
+-        }
+-
+-        break;
++      break;
++    case KEYSTROKE_MINIMIZE:
++      if (nxagentOption(Rootless) == False) {
++        *result = doMinimize;
+       }
+-      case XK_Right:
+-      case XK_KP_Right:
+-      {
+-        if (nxagentOption(Rootless) == False &&
+-                nxagentOption(DesktopResize) == False)
+-        {
+-          *result = doViewportRight;
+-        }
+-
+-        break;
++      break;
++    case KEYSTROKE_LEFT:
++      if (nxagentOption(Rootless) == False &&
++          nxagentOption(DesktopResize) == False) {
++        *result = doViewportLeft;
+       }
+-      case XK_Down:
+-      case XK_KP_Down:
+-      {
+-        if (nxagentOption(Rootless) == 0 &&
+-                nxagentOption(DesktopResize) == 0)
+-        {
+-          *result = doViewportDown;
+-        }
+-
+-        break;
++      break;
++    case KEYSTROKE_UP:
++      if (nxagentOption(Rootless) == False &&
++          nxagentOption(DesktopResize) == False) {
++        *result = doViewportUp;
+       }
+-      case XK_R:
+-      case XK_r:
+-      {
+-        if (nxagentOption(Rootless) == 0)
+-        {
+-          *result = doSwitchResizeMode;
+-        }
+-
+-        break;
++      break;
++    case KEYSTROKE_RIGHT:
++      if (nxagentOption(Rootless) == False &&
++          nxagentOption(DesktopResize) == False) {
++        *result = doViewportRight;
+       }
+-      case XK_E:
+-      case XK_e:
+-      {
+-        *result = doSwitchDeferMode;
+-
+-        break;
++      break;
++    case KEYSTROKE_DOWN:
++      if (nxagentOption(Rootless) == False &&
++          nxagentOption(DesktopResize) == False) {
++        *result = doViewportDown;
+       }
+-      case XK_BackSpace:
+-      case XK_Terminate_Server:
+-      {
+-        /*
+-         * Discard Ctrl-Alt-BackSpace key.
+-         */
+-
+-        return 1;
+-
+-        break;
++      break;
++    case KEYSTROKE_RESIZE:
++      if (nxagentOption(Rootless) == False) {
++        *result = doSwitchResizeMode;
+       }
+-
+-      case XK_J:
+-      case XK_j:
+-      {
+-        nxagentForceSynchronization = 1;
+-
+-        return 1;
+-      }
+-
++      break;
++    case KEYSTROKE_DEFER:
++      *result = doSwitchDeferMode;
++      break;
++    case KEYSTROKE_IGNORE:
++      /* this is used e.g. to ignore C-A-Backspace aka XK_Terminate_Server */
++      return 1;
++      break;
++    case KEYSTROKE_FORCE_SYNCHRONIZATION:
++      nxagentForceSynchronization = 1;
++      break;
++    case KEYSTROKE_REGIONS_ON_SCREEN:
+       #ifdef DUMP
+-
+-      case XK_A:
+-      case XK_a:
+-      {
+-        /*
+-         * Used to test the lazy encoding.
+-         */
+-
+-        nxagentRegionsOnScreen();
+-
+-        return 1;
+-      }
+-
++      nxagentRegionsOnScreen();
+       #endif
+-
++      break;
++    case KEYSTROKE_TEST_INPUT:
++      /*
++       * Used to test the input devices state.
++       */
+       #ifdef NX_DEBUG_INPUT
+-
+-      case XK_X:
+-      case XK_x:
+-      {
+-        /*
+-         * Used to test the input devices state.
+-         */
+-
+-        if (X -> type == KeyPress)
+-        {
+-          if (nxagentDebugInputDevices == 0)
+-          {
+-            fprintf(stderr, "Info: Turning input devices debug ON.\n");
+-    
+-            nxagentDebugInputDevices = 1;
+-          }
+-          else
+-          {
+-            fprintf(stderr, "Info: Turning input devices debug OFF.\n");
+-    
+-            nxagentDebugInputDevices = 0;
+-    
+-            nxagentLastInputDevicesDumpTime = 0;
+-          }
++      if (X -> type == KeyPress) {
++        if (nxagentDebugInputDevices == 0) {
++          fprintf(stderr, "Info: Turning input devices debug ON.\n");
++          nxagentDebugInputDevices = 1;
++        } else {
++          fprintf(stderr, "Info: Turning input devices debug OFF.\n");
++          nxagentDebugInputDevices = 0;
++          nxagentLastInputDevicesDumpTime = 0;
+         }
+-
+-        return 1;
+       }
+-
+-      case XK_Y:
+-      case XK_y:
+-      {
+-        /*
+-         * Used to deactivate input devices grab.
+-         */
+-
+-        if (X -> type == KeyPress)
+-        {
+-          nxagentDeactivateInputDevicesGrabs();
+-        }
+-
+-        return 1;
++      return 1;
++      #endif
++      break;
++    case KEYSTROKE_DEACTIVATE_INPUT_DEVICES_GRAB:
++      #ifdef NX_DEBUG_INPUT
++      if (X->type == KeyPress) {
++        nxagentDeactivateInputDevicesGrab();
+       }
+-
++      return 1;
+       #endif
+-    }
+-  }
+-  else if ((X -> state & nxagentAltMetaMask) &&
+-               ((X -> state & (ControlMask | ShiftMask)) == (ControlMask |
+-                   ShiftMask)))
+-  {
+-    switch (sym)
+-    {
+-      case XK_f:
+-      case XK_F:
+-      {
+-        if (nxagentOption(Rootless) == 0)
+-        {
+-          *result = doSwitchFullscreen;
+-        }
+-
+-        break;
++      break;
++    case KEYSTROKE_FULLSCREEN:
++      if (nxagentOption(Rootless) == 0) {
++        *result = doSwitchFullscreen;
+       }
+-      case XK_Left:
+-      case XK_KP_Left:
+-      {
+-        if (nxagentOption(Rootless) == 0 &&
+-                nxagentOption(DesktopResize) == 0)
+-        {
+-          *result = doViewportMoveLeft;
+-        }
+-
+-        break;
++      break;
++    case KEYSTROKE_VIEWPORT_MOVE_LEFT:
++      if (nxagentOption(Rootless) == 0 &&
++          nxagentOption(DesktopResize) == 0) {
++        *result = doViewportMoveLeft;
+       }
+-      case XK_Up:
+-      case XK_KP_Up:
+-      {
+-        if (nxagentOption(Rootless) == 0 &&
+-                nxagentOption(DesktopResize) == 0)
+-        {
+-          *result = doViewportMoveUp;
+-        }
+-
+-        break;
++      break;
++    case KEYSTROKE_VIEWPORT_MOVE_UP:
++      if (nxagentOption(Rootless) == 0 &&
++          nxagentOption(DesktopResize) == 0) {
++        *result = doViewportMoveUp;
+       }
+-      case XK_Right:
+-      case XK_KP_Right:
+-      {
+-        if (nxagentOption(Rootless) == 0 &&
+-                nxagentOption(DesktopResize) == 0)
+-        {
+-          *result = doViewportMoveRight;
+-        }
+-
+-        break;
++      break;
++    case KEYSTROKE_VIEWPORT_MOVE_RIGHT:
++      if (nxagentOption(Rootless) == 0 &&
++          nxagentOption(DesktopResize) == 0) {
++        *result = doViewportMoveRight;
+       }
+-      case XK_Down:
+-      case XK_KP_Down:
+-      {
+-        if (nxagentOption(Rootless) == 0 &&
+-                nxagentOption(DesktopResize) == 0)
+-        {
+-          *result = doViewportMoveDown;
+-        }
+-
+-        break;
++      break;
++    case KEYSTROKE_VIEWPORT_MOVE_DOWN:
++      if (nxagentOption(Rootless) == 0 &&
++          nxagentOption(DesktopResize) == 0) {
++        *result = doViewportMoveDown;
+       }
+-    }
++      break;
++    case KEYSTROKE_NOTHING: /* do nothing. difference to KEYSTROKE_IGNORE is the return value */
++    case KEYSTROKE_END_MARKER: /* just to make gcc STFU */
++    case KEYSTROKE_MAX:
++      break;
+   }
+-
+   return (*result == doNothing) ? 0 : 1;
+ }
+diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h
+index ef71a88..ecfb2c4 100644
+--- a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h
++++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h
+@@ -24,4 +24,51 @@ extern int nxagentCheckSpecialKeystroke(XKeyEvent*, enum HandleEventResult*);
+ 
+ unsigned int nxagentAltMetaMask;
+ 
++/* keep this sorted, do not rely on any numerical value in this enum, and be aware
++ * that KEYSTROKE_MAX may be used in a malloc */
++
++/* also be aware that if changing any numerical values, you also need to change values
++ * Keystroke.c nxagentSpecialKeystrokeNames */
++enum nxagentSpecialKeystroke {
++       /* 0 is used as end marker */
++       KEYSTROKE_END_MARKER = 0,
++       KEYSTROKE_CLOSE_SESSION = 1,
++       KEYSTROKE_SWITCH_ALL_SCREENS = 2,
++       KEYSTROKE_MINIMIZE = 3,
++       KEYSTROKE_LEFT = 4,
++       KEYSTROKE_UP = 5,
++       KEYSTROKE_RIGHT = 6,
++       KEYSTROKE_DOWN = 7,
++       KEYSTROKE_RESIZE = 8,
++       KEYSTROKE_DEFER = 9,
++       KEYSTROKE_IGNORE = 10,
++       KEYSTROKE_FORCE_SYNCHRONIZATION = 11,
++
++       /* stuff used for debugging, probably not useful for most people */
++       KEYSTROKE_DEBUG_TREE = 12,
++       KEYSTROKE_REGIONS_ON_SCREEN = 13,
++       KEYSTROKE_TEST_INPUT = 14,
++       KEYSTROKE_DEACTIVATE_INPUT_DEVICES_GRAB = 15,
++
++       KEYSTROKE_FULLSCREEN = 16,
++       KEYSTROKE_VIEWPORT_MOVE_LEFT = 17,
++       KEYSTROKE_VIEWPORT_MOVE_UP = 18,
++       KEYSTROKE_VIEWPORT_MOVE_RIGHT = 19,
++       KEYSTROKE_VIEWPORT_MOVE_DOWN = 20,
++
++       KEYSTROKE_NOTHING = 21,
++
++       /* insert more here, increment KEYSTROKE_MAX accordingly.
++        * then update string translation below */
++
++       KEYSTROKE_MAX=22,
++};
++
++struct nxagentSpecialKeystrokeMap {
++       enum nxagentSpecialKeystroke stroke;
++       unsigned int modifierMask; /* everything except alt/meta */
++       int modifierAltMeta; /* modifier combination should include alt/meta */
++       KeySym keysym;
++};
++
+ #endif /* __Keystroke_H__ */
+--- /dev/null
++++ b/README.keystrokes
+@@ -0,0 +1,83 @@
++Configurable keybindings in nxagent
++
++Keybindings in the redistributed x2go version of nxagent can now be configured
++by the user. This is done via a configuration file. 
++
++File location
++-------------
++
++nxagent searches for the configuration file in the following order:
++- in the location given by the '-keystrokefile' command line parameter
++- in the location given by the NXAGENT_KEYSTROKEFILE environment variable
++- in ~/.nx/config/keystroke.cfg
++- in /etc/nx/keystroke.cfg
++
++If none of those files is accessible, the default configuration is used which
++is the same as the old, traditional nxagent keybindings.
++
++File format
++-----------
++
++The configuration file is XML with the following format:
++
++<!DOCTYPE NXKeystroke>
++<keystrokes>
++<keystroke action="fullscreen" AltMeta="1" Control="1" key="b" />
++<keystroke action="minimize" AltMeta="1" Control="1" key="space" />
++<keystroke action="minimize" key="Escape" Shift="1" />
++<keystroke action="close_session" key="F7" />
++<keystroke action="fullscreen" key="F7" Mod1="1" />
++<keystroke action="fullscreen" key="F6" Mod1="1" />
++<keystroke action="force_synchronization" key="f" />
++<keystroke action="fullscreen" key="space" Mod1="0" Mod2="0" Control="0" Shift="0" AltMeta="0" />
++</keystrokes>
++
++Each 'action' defines an action to be executed when receiving that keystroke. A
++list of possible actions is given below. Some of those actions are only
++available with debug builds of nxagent.
++
++Keys are given as a combination of 'key' and (optionally) a number of
++modifiers. The key attribute is evaluated into a X11 key via the usual
++XStringToKeysym function. A list of possible keys can be found in
++/usr/include/X11/keysymdef.h, the names are specified without the leading
++'XK_'. Evaluation is case-sensitive, so, 'space' and 'Escape' will work while
++'Space' and 'escape' won't.
++
++Modifiers are given as boolean attributes, possible modifiers are Mod1, Mod2,
++Mod3, Mod4, Control, Shift, Lock. Sensible combinations strongly depend on your
++keyboard configuration, but usually you will need Mod1 and Control. Boolean in
++this context means '0', 'false' and an unspecified attribute are false, anything
++else is considered true.
++
++Everything in this file is case-sensitive. Unknown lines are ignored.
++Keybindings are evaluated from top to bottom, so if a keybinding matches, other
++keybindings further down will be ignored. The contents of the file replaces the
++default keybindings, and only one file is read, no merging between different
++configuration files is done. This also means that an empty or invalid configuration
++file deactivates all keybindings.
++
++List of possible 'action' attributes:
++-------------------------------------
++
++close_session
++switch_all_screens
++minimize
++left
++up
++right
++down
++resize
++defer
++ignore
++fullscreen
++viewport_move_left
++viewport_move_up
++viewport_move_right
++viewport_move_down
++
++Only in builds with certain debugging options enabled, ignored otherwise:
++force_synchronization
++debug_tree
++regions_on_screen
++test_input
++deactivate_input_devices_grab
\ No newline at end of file
diff --git a/debian/patches/series b/debian/patches/series
index b78dbbd..99f30f2 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -43,6 +43,7 @@
 203_nxagent_disable-rootless-exit.full.patch
 204_nxagent_repaint-solidpict.full.patch
 209_x2goagent-add-man-page.full.patch
+210_nxagent_configurable-keystrokes.full.patch
 220_nxproxy-bind-loopback-only.full+lite.patch
 300_nxagent_set-wm-class.full.patch
 301_nx-X11_use-shared-libs.full.patch


hooks/post-receive
-- 
nx-libs.git (NX (redistributed))

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "nx-libs.git" (NX (redistributed)).




More information about the x2go-commits mailing list