[X2Go-Commits] nx-libs.git - build-main (branch) updated: redist-client/3.5.0.16-3-g34f232c

X2Go dev team git-admin at x2go.org
Fri Aug 30 16:23:56 CEST 2013


The branch, build-main 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 -----------------------------------------------------------------
-----------------------------------------------------------------------

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