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

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


The branch, master has been updated
       via  5938c38aed27035718cea6e92f98294734836e36 (commit)
      from  0a91caa987a5a4f278140323089c4afd8fe1041f (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 5938c38aed27035718cea6e92f98294734836e36
Author: Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
Date:   Tue Dec 4 13:49:18 2012 +0100

    re-add renamed patch file

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

Summary of changes:
 .../302_nxagent_configurable-keystrokes.full.patch |  989 ++++++++++++++++++++
 1 file changed, 989 insertions(+)
 create mode 100644 debian/patches/302_nxagent_configurable-keystrokes.full.patch

The diff of changes is:
diff --git a/debian/patches/302_nxagent_configurable-keystrokes.full.patch b/debian/patches/302_nxagent_configurable-keystrokes.full.patch
new file mode 100644
index 0000000..fb74739
--- /dev/null
+++ b/debian/patches/302_nxagent_configurable-keystrokes.full.patch
@@ -0,0 +1,989 @@
+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.
+--- a/nx-X11/programs/Xserver/Imakefile
++++ b/nx-X11/programs/Xserver/Imakefile
+@@ -1013,15 +1013,18 @@
+ #if defined(SunArchitecture)
+ NXAGENTNXLIBS = -L ../../../nxcomp -L ../../../nxcompext -L ../../../nxcompshad \
+                 -lXcomp -lXcompext -lXcompshad -lrt -L/usr/sfw/lib -lXrender -lXfixes \
+-                -L../../../nx-X11/exports/lib -lXtst -lXdamage -lXrandr -lXcomposite -lXdmcp
++                -L../../../nx-X11/exports/lib -lXtst -lXdamage -lXrandr -lXcomposite -lXdmcp \
++`pkg-config --libs libxml-2.0`
+ #elif defined(cygwinArchitecture)
+ NXAGENTNXLIBS = -L ../../../nxcomp -L ../../../nxcompext \
+                 -lXcomp -lXcompext -lXrender -lX11 -lXext -lXcomposite -lXfixes \
+-                -L ../../../nxcompshad -lXcompshad -L../../../nx-X11/exports/lib -lXtst -lXdmcp
++                -L ../../../nxcompshad -lXcompshad -L../../../nx-X11/exports/lib -lXtst -lXdmcp \
++`pkg-config --libs libxml-2.0`
+ #else
+ NXAGENTNXLIBS = -L ../../../nxcomp -L ../../../nxcompext -L ../../../nxcompshad \
+                 -lXcomp -lXcompext -lXcompshad -lXrender -lX11 -lXext -lXfixes \
+-                -L../../../nx-X11/exports/lib -lXtst -lXdamage -lXrandr -lXcomposite -lXinerama -lXdmcp
++                -L../../../nx-X11/exports/lib -lXtst -lXdamage -lXrandr -lXcomposite -lXinerama -lXdmcp \
++`pkg-config --libs libxml-2.0`
+ #endif
+ 
+ #endif
+--- a/nx-X11/programs/Xserver/hw/nxagent/Imakefile
++++ b/nx-X11/programs/Xserver/hw/nxagent/Imakefile
+@@ -142,7 +142,8 @@
+            -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 @@
+ 	   -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 @@
+            -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
+ 
+--- 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,297 +54,527 @@
+ #undef  DEBUG
+ #undef  DUMP
+ 
+-int nxagentCheckSpecialKeystroke(XKeyEvent *X, enum HandleEventResult *result)
+-{
+-  KeySym sym;
+-  int index = 0;
+ 
+-  *result = doNothing;
++/* 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;
+ 
+-  /*
+-   * I don't know how much hard work is doing this operation.
+-   * Do we need a cache ?
++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;
+ 
+-  sym = XKeycodeToKeysym(nxagentDisplay, X -> keycode, index);
++  if (compare_alt_meta) {
++    if (! (state & nxagentAltMetaMask)) {
++      ret = 0;
++    }
+ 
+-  if (sym == XK_VoidSymbol || sym == NoSymbol)
+-  {
+-    return 0;
++    mask &= ~nxagentAltMetaMask;
+   }
+ 
+-  #ifdef TEST
+-  fprintf(stderr, "nxagentCheckSpecialKeystroke: got code %x - state %x - sym %lx\n",
+-              X -> keycode, X -> state, sym);
+-  #endif
+-
+-  /*
+-   * Check special keys.
+-   */
+-
+-  /*
+-   * FIXME: We should use the keysym instead that the keycode
+-   *        here.
+-   */
++  /* all modifiers except meta/alt have to match exactly, extra bits are evil */
++  if ((mask & state) != mask) {
++    ret = 0;
++  }
+ 
+-  if (X -> keycode == 130 && nxagentIpaq)
+-  {
+-    *result = doStartKbd;
++  return ret;
++}
+ 
+-    return 1;
+-  }
++static int read_binding_from_xmlnode(xmlNode *node, struct nxagentSpecialKeystrokeMap *ret)
++{
++  int successful = 0;
++  struct nxagentSpecialKeystrokeMap new = {0, 0, 0, 0};
++  xmlAttr *attr;
+ 
+-  if ((X -> state & nxagentAltMetaMask) &&
+-          ((X -> state & (ControlMask | ShiftMask)) == ControlMask))
++  for (attr = node->properties; attr; attr = attr->next)
+   {
+-    switch (sym)
++    /* ignore attributes without data (which should never happen anyways) */
++    if (attr->children->content == NULL)
+     {
+-      #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:
++      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 (nxagentOption(Rootless) == False)
++        if (strcmp(nxagentSpecialKeystrokeNames[i],(char *)attr->children->content) == 0)
+         {
+-          *result = doSwitchAllScreens;
++          /* this relies on the values of enum nxagentSpecialKeystroke and the
++           * indices of nxagentSpecialKeystrokeNames being in sync */
++          new.stroke = i;
++          break;
+         }
+-
+-        break;
+       }
+-      case XK_m:
+-      case XK_M:
++      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)
+       {
+-        if (nxagentOption(Rootless) == False)
+-        {
+-          *result = doMinimize;
+-        }
+-
+-        break;
++        new.keysym = 0;
+       }
+-      case XK_Left:
+-      case XK_KP_Left:
+-      {
+-        if (nxagentOption(Rootless) == False &&
+-                nxagentOption(DesktopResize) == False)
+-        {
+-          *result = doViewportLeft;
+-        }
++      continue;
++    }
+ 
+-        break;
+-      }
+-      case XK_Up:
+-      case XK_KP_Up:
+-      {
+-        if (nxagentOption(Rootless) == False &&
+-                nxagentOption(DesktopResize) == False)
+-        {
+-          *result = doViewportUp;
+-        }
++    /* 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;
+ 
+-        break;
+-      }
+-      case XK_Right:
+-      case XK_KP_Right:
+-      {
+-        if (nxagentOption(Rootless) == False &&
+-                nxagentOption(DesktopResize) == False)
+-        {
+-          *result = doViewportRight;
+-        }
++    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;
++    }
++  }
+ 
+-        break;
+-      }
+-      case XK_Down:
+-      case XK_KP_Down:
+-      {
+-        if (nxagentOption(Rootless) == 0 &&
+-                nxagentOption(DesktopResize) == 0)
+-        {
+-          *result = doViewportDown;
+-        }
++  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;
++}
+ 
+-        break;
+-      }
+-      case XK_R:
+-      case XK_r:
+-      {
+-        if (nxagentOption(Rootless) == 0)
+-        {
+-          *result = doSwitchResizeMode;
+-        }
++/*
++ * 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;
+ 
+-        break;
+-      }
+-      case XK_E:
+-      case XK_e:
+-      {
+-        *result = doSwitchDeferMode;
++  char *homefile = "/.nx/config/keystroke.cfg";
++  char *etcfile = "/etc/nx/keystroke.cfg";
+ 
+-        break;
++  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);
+       }
+-      case XK_BackSpace:
+-      case XK_Terminate_Server:
++      filename = calloc(1, strlen(homefile) + strlen(homedir) + 1);
++      if (filename == NULL)
+       {
+-        /*
+-         * Discard Ctrl-Alt-BackSpace key.
+-         */
+-
+-        return 1;
+-
+-        break;
++        fprintf(stderr, "malloc failed");
++        exit(EXIT_FAILURE);
+       }
+-
+-      case XK_J:
+-      case XK_j:
++      strcpy(filename, homedir);
++      strcpy(filename + strlen(homedir), homefile);
++      if (homedir)
+       {
+-        nxagentForceSynchronization = 1;
+-
+-        return 1;
++        free(homedir);
+       }
++    }
+ 
+-      #ifdef DUMP
+-
+-      case XK_A:
+-      case XK_a:
++    if (access(filename, R_OK) == 0)
++    {
++      /* empty */
++    }
++    else if (access(etcfile, R_OK == 0))
++    {
++      if (filename)
++        free(filename);
++      filename = strdup(etcfile);
++      if (filename == NULL)
+       {
+-        /*
+-         * Used to test the lazy encoding.
+-         */
+-
+-        nxagentRegionsOnScreen();
+-
+-        return 1;
++        fprintf(stderr, "malloc failed");
++        exit(EXIT_FAILURE);
+       }
++    }
++    else
++    {
++      if (filename)
++free(filename);
++      filename = NULL;
++    }
++  }
+ 
+-      #endif
+-
+-      #ifdef NX_DEBUG_INPUT
++  /* 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);
+ 
+-      case XK_X:
+-      case XK_x:
++      for (cur = root; cur; cur = cur->next)
+       {
+-        /*
+-         * Used to test the input devices state.
+-         */
++        if (cur->type == XML_ELEMENT_NODE && strcmp((char *)cur->name, "keystrokes") == 0)
++{
++          xmlNode *bindings = NULL;
++          int num = 0;
++          int idx = 0;
+ 
+-        if (X -> type == KeyPress)
+-        {
+-          if (nxagentDebugInputDevices == 0)
++          for (bindings = cur->children; bindings; bindings = bindings->next)
+           {
+-            fprintf(stderr, "Info: Turning input devices debug ON.\n");
+-    
+-            nxagentDebugInputDevices = 1;
++            if (bindings->type == XML_ELEMENT_NODE && strcmp((char *)bindings->name, "keystroke") == 0)
++            {
++              num++;
++            }
+           }
+-          else
++          map = calloc((num + 1), sizeof(struct nxagentSpecialKeystrokeMap));
++          if (map == NULL)
+           {
+-            fprintf(stderr, "Info: Turning input devices debug OFF.\n");
+-    
+-            nxagentDebugInputDevices = 0;
+-    
+-            nxagentLastInputDevicesDumpTime = 0;
++            fprintf(stderr, "malloc failed");
++            exit(EXIT_FAILURE);
+           }
+-        }
+-
+-        return 1;
+-      }
+ 
+-      case XK_Y:
+-      case XK_y:
+-      {
+-        /*
+-         * Used to deactivate input devices grab.
+-         */
++          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++;
++            }
++          }
+ 
+-        if (X -> type == KeyPress)
+-        {
+-          nxagentDeactivateInputDevicesGrabs();
++          map[idx].stroke = KEYSTROKE_END_MARKER;
+         }
+-
+-        return 1;
+       }
+ 
++      xmlFreeDoc(doc);
++      xmlCleanupParser();
++    }
++    else
++    {
++      #ifdef DEBUG
++      fprintf("XML parsing for %s failed\n", filename);
+       #endif
+     }
++    free(filename);
+   }
+-  else if ((X -> state & nxagentAltMetaMask) &&
+-               ((X -> state & (ControlMask | ShiftMask)) == (ControlMask |
+-                   ShiftMask)))
++}
++
++static enum nxagentSpecialKeystroke find_keystroke(XKeyEvent *X)
++{
++  KeySym keysym = XKeycodeToKeysym(nxagentDisplay, X->keycode, 0);
++  struct nxagentSpecialKeystrokeMap *cur = map;
++
++  if (! nxagentKeystrokeFileParsed)
+   {
+-    switch (sym)
+-    {
+-      case XK_f:
+-      case XK_F:
+-      {
+-        if (nxagentOption(Rootless) == 0)
+-        {
+-          *result = doSwitchFullscreen;
+-        }
++    parse_keystroke_file();
++    nxagentKeystrokeFileParsed = True;
++  }
+ 
+-        break;
+-      }
+-      case XK_Left:
+-      case XK_KP_Left:
+-      {
+-        if (nxagentOption(Rootless) == 0 &&
+-                nxagentOption(DesktopResize) == 0)
+-        {
+-          *result = doViewportMoveLeft;
+-        }
++  enum nxagentSpecialKeystroke ret = KEYSTROKE_NOTHING;
+ 
+-        break;
+-      }
+-      case XK_Up:
+-      case XK_KP_Up:
+-      {
+-        if (nxagentOption(Rootless) == 0 &&
+-                nxagentOption(DesktopResize) == 0)
+-        {
+-          *result = doViewportMoveUp;
+-        }
++  while ((cur++)->stroke != KEYSTROKE_END_MARKER) {
++    if (cur->keysym == keysym && modifier_matches(cur->modifierMask, cur->modifierAltMeta, X->state)) {
++      return cur->stroke;
++    }
++  }
+ 
+-        break;
+-      }
+-      case XK_Right:
+-      case XK_KP_Right:
+-      {
+-        if (nxagentOption(Rootless) == 0 &&
+-                nxagentOption(DesktopResize) == 0)
+-        {
+-          *result = doViewportMoveRight;
+-        }
++  return ret;
++}
+ 
+-        break;
+-      }
+-      case XK_Down:
+-      case XK_KP_Down:
+-      {
+-        if (nxagentOption(Rootless) == 0 &&
+-                nxagentOption(DesktopResize) == 0)
+-        {
+-          *result = doViewportMoveDown;
+-        }
++int nxagentCheckSpecialKeystroke(XKeyEvent *X, enum HandleEventResult *result)
++{
++  KeySym sym;
++  int index = 0;
++  enum nxagentSpecialKeystroke stroke = find_keystroke(X);
+ 
+-        break;
+-      }
+-    }
++  *result = doNothing;
++
++  /*
++   * I don't know how much hard work is doing this operation.
++   * Do we need a cache ?
++   */
++
++  sym = XKeycodeToKeysym(nxagentDisplay, X -> keycode, index);
++
++  if (sym == XK_VoidSymbol || sym == NoSymbol)
++  {
++    return 0;
+   }
+ 
++  #ifdef TEST
++  fprintf(stderr, "nxagentCheckSpecialKeystroke: got code %x - state %x - sym %lx\n",
++              X -> keycode, X -> state, sym);
++  #endif
++
++  /*
++   * Check special keys.
++   */
++
++  /*
++   * FIXME: We should use the keysym instead that the keycode
++   *        here.
++   */
++
++  if (X -> keycode == 130 && nxagentIpaq)
++  {
++    *result = doStartKbd;
++
++    return 1;
++  }
++
++  switch (stroke) {
++    case KEYSTROKE_DEBUG_TREE:
++      #ifdef DEBUG_TREE
++      *result = doDebugTree;
++      #endif
++      break;
++    case KEYSTROKE_CLOSE_SESSION:
++      *result = doCloseSession;
++      break;
++    case KEYSTROKE_SWITCH_ALL_SCREENS:
++      if (nxagentOption(Rootless) == False) {
++        *result = doSwitchAllScreens;
++      }
++      break;
++    case KEYSTROKE_MINIMIZE:
++      if (nxagentOption(Rootless) == False) {
++        *result = doMinimize;
++      }
++      break;
++    case KEYSTROKE_LEFT:
++      if (nxagentOption(Rootless) == False &&
++          nxagentOption(DesktopResize) == False) {
++        *result = doViewportLeft;
++      }
++      break;
++    case KEYSTROKE_UP:
++      if (nxagentOption(Rootless) == False &&
++          nxagentOption(DesktopResize) == False) {
++        *result = doViewportUp;
++      }
++      break;
++    case KEYSTROKE_RIGHT:
++      if (nxagentOption(Rootless) == False &&
++          nxagentOption(DesktopResize) == False) {
++        *result = doViewportRight;
++      }
++      break;
++    case KEYSTROKE_DOWN:
++      if (nxagentOption(Rootless) == False &&
++          nxagentOption(DesktopResize) == False) {
++        *result = doViewportDown;
++      }
++      break;
++    case KEYSTROKE_RESIZE:
++      if (nxagentOption(Rootless) == False) {
++        *result = doSwitchResizeMode;
++      }
++      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
++      nxagentRegionsOnScreen();
++      #endif
++      break;
++    case KEYSTROKE_TEST_INPUT:
++      /*
++       * Used to test the input devices state.
++       */
++      #ifdef NX_DEBUG_INPUT
++      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;
++      #endif
++      break;
++    case KEYSTROKE_DEACTIVATE_INPUT_DEVICES_GRAB:
++      #ifdef NX_DEBUG_INPUT
++      if (X->type == KeyPress) {
++        nxagentDeactivateInputDevicesGrab();
++      }
++      return 1;
++      #endif
++      break;
++    case KEYSTROKE_FULLSCREEN:
++      if (nxagentOption(Rootless) == 0) {
++        *result = doSwitchFullscreen;
++      }
++      break;
++    case KEYSTROKE_VIEWPORT_MOVE_LEFT:
++      if (nxagentOption(Rootless) == 0 &&
++          nxagentOption(DesktopResize) == 0) {
++        *result = doViewportMoveLeft;
++      }
++      break;
++    case KEYSTROKE_VIEWPORT_MOVE_UP:
++      if (nxagentOption(Rootless) == 0 &&
++          nxagentOption(DesktopResize) == 0) {
++        *result = doViewportMoveUp;
++      }
++      break;
++    case KEYSTROKE_VIEWPORT_MOVE_RIGHT:
++      if (nxagentOption(Rootless) == 0 &&
++          nxagentOption(DesktopResize) == 0) {
++        *result = doViewportMoveRight;
++      }
++      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;
+ }
+--- a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h
++++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h
+@@ -24,4 +24,51 @@
+ 
+ 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


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