From 522106e207e7230da5e62fb88f2e47742fdf1b21 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 22 Jul 2017 22:21:05 +0200 Subject: nxagent: bypass X2go's keyboard configuration hack If X2go runs in auto keyboard mode it will pass keyboard=null/null to the agent and set the keyboard afterwards with setxkbmap. This patch lets nxagent handle that situation internally (null/null will be interpreted as clone) and disables X2go's mechanism (by creating a dir that effectively blocks it; see x2gosetkeyboard) This is only activated if the agent is run as "x2goagent". Fixes ArcticaProject/nx-libs#368 --- nx-X11/programs/Xserver/hw/nxagent/Keyboard.c | 111 ++++++++++++++++------- nx-X11/programs/Xserver/hw/nxagent/Reconnect.c | 10 ++ nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 | 3 +- 3 files changed, 92 insertions(+), 32 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c index cfe73ac5b..af27c6e28 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c @@ -57,6 +57,7 @@ is" without express or implied warranty. #include "Events.h" #include "Options.h" #include "Error.h" +#include "Init.h" #include "compext/Compext.h" @@ -82,6 +83,7 @@ static void nxagentXkbGetNames(void); void nxagentKeycodeConversionSetup(void); +static void nxagentWriteKeyboardDir(void); static void nxagentWriteKeyboardFile(char *rules, char *model, char *layout, char *variant, char *options); #endif /* XKB */ @@ -751,6 +753,15 @@ XkbError: fprintf(stderr, "nxagentKeyboardProc: nxagentKeyboard is [%s].\n", nxagentKeyboard ? nxagentKeyboard : "NULL"); #endif + if (nxagentX2go == 1 && nxagentKeyboard && (strcmp(nxagentKeyboard, "null/null") == 0)) + { + #ifdef TEST + fprintf(stderr, "%s: changing nxagentKeyboard from [null/null] to [clone].\n", __func__); + #endif + free(nxagentKeyboard); + nxagentKeyboard = strdup("clone"); + } + /* from nxagent changelog: 2.0.22: @@ -846,19 +857,6 @@ XkbError: __func__, nxagentRemoteRules, nxagentRemoteModel, nxagentRemoteLayout, nxagentRemoteVariant, nxagentRemoteOptions); #endif - /* - * Keyboard has always been tricky with nxagent. For that - * reason X2Go offers "auto" keyboard configuration. You can - * specify it in the client side session configuration. In - * "auto" mode x2goserver expects nxagent to write the - * remote keyboard config to a file on startup and - * x2goserver would then pick that file and pass it to - * setxkbmap. This functionality is obsoleted by the "clone" - * stuff but we still need it because x2goserver does not - * know about that yet. Once x2go starts using clone - * we can drop this here. - */ - nxagentWriteKeyboardFile(nxagentRemoteRules, nxagentRemoteModel, nxagentRemoteLayout, nxagentRemoteVariant, nxagentRemoteOptions); /* Only setup keycode conversion if we are NOT in clone mode */ if (nxagentKeyboard && (strcmp(nxagentKeyboard, "clone") == 0)) @@ -868,10 +866,33 @@ XkbError: free(layout); layout = strdup(nxagentRemoteLayout); free(variant); variant = strdup(nxagentRemoteVariant); free(options); options = strdup(nxagentRemoteOptions); + /* + * when cloning we do not want X2Go to set the keyboard + * via a keyboard file generated by nxagent. The defined + * method for switching that off is the creation of a dir + * instead of a file. Which is achieved by passing NULL to + * nxagentWriteKeyboardFile. + */ + if (nxagentX2go == 1) + nxagentWriteKeyboardDir(); } else { nxagentKeycodeConversionSetup(); + /* + * Keyboard has always been tricky with nxagent. For that + * reason X2Go offers "auto" keyboard configuration. You can + * specify it in the client side session configuration. In + * "auto" mode x2goserver expects nxagent to write the + * remote keyboard config to a file on startup and + * x2goserver would then pick that file and pass it to + * setxkbmap. This functionality is obsoleted by the "clone" + * stuff but we still need it because x2goserver does not + * know about that yet. Once x2go starts using clone + * we can drop this here. + */ + if (nxagentX2go == 1) + nxagentWriteKeyboardFile(nxagentRemoteRules, nxagentRemoteModel, nxagentRemoteLayout, nxagentRemoteVariant, nxagentRemoteOptions); } } #ifdef DEBUG @@ -1645,6 +1666,49 @@ static void writeKeyboardfileData(FILE *out, char *rules, char *model, char *lay fprintf(out, "options=\",%s\"\n", options ? options : ""); } +static char* getKeyboardFilePath(void) +{ + char *keyboard_file_path = NULL; + char *sessionpath = nxagentGetSessionPath(); + if (sessionpath) + { + if ((asprintf(&keyboard_file_path, "%s/keyboard", sessionpath) == -1)) + { + free(sessionpath); + FatalError("malloc for keyboard file path failed."); + } + free(sessionpath); + } + else + { + fprintf(stderr, "Warning: Failed to determine keyboard file path: SessionPath not defined\n"); + } + return keyboard_file_path; +} + +static void nxagentWriteKeyboardDir(void) +{ + char *keyboard_file_path = getKeyboardFilePath(); + + if (keyboard_file_path) + { + /* + * special case: if rules is NULL create a directory insteas of + * a file. This is the defined method to disable x2gosetkeyboard. + */ + if (mkdir(keyboard_file_path, 0555) < 0) + { + int save_err = errno; + fprintf(stderr, "Warning: Failed to create keyboard blocking directory '%s': %s\n", keyboard_file_path, strerror(save_err)); + } + else + { + fprintf(stderr, "Info: keyboard blocking directory created: '%s'\n", keyboard_file_path); + } + free(keyboard_file_path); + } +} + static void nxagentWriteKeyboardFile(char *rules, char *model, char *layout, char *variant, char *options) { if (rules && rules[0] != '\0') @@ -1653,21 +1717,14 @@ static void nxagentWriteKeyboardFile(char *rules, char *model, char *layout, cha writeKeyboardfileData(stderr, rules, model, layout, variant, options); #endif - char *sessionpath = nxagentGetSessionPath(); - if (sessionpath) + char *keyboard_file_path = getKeyboardFilePath(); + + if (keyboard_file_path) { - char *keyboard_file_path = NULL; FILE *keyboard_file; - if ((asprintf(&keyboard_file_path, "%s/keyboard", sessionpath) == -1)) - { - free(sessionpath); - FatalError("malloc for keyboard file path failed."); - } - free(sessionpath); if ((keyboard_file = fopen(keyboard_file_path, "w"))) { writeKeyboardfileData(keyboard_file, rules, model, layout, variant, options); - fclose(keyboard_file); fprintf(stderr, "Info: keyboard file created: '%s'\n", keyboard_file_path); } @@ -1678,14 +1735,6 @@ static void nxagentWriteKeyboardFile(char *rules, char *model, char *layout, cha } free(keyboard_file_path); } - else - { - fprintf(stderr, "Warning: Failed to create keyboard file: SessionPath not defined\n"); - } - } - else - { - fprintf(stderr, "Warning: Failed to create the keyboard file\n"); } } diff --git a/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c index 91445a383..a921df6ca 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c @@ -458,6 +458,16 @@ Bool nxagentReconnectSession(void) nxagentProcessOptions(nxagentOptionsFilenameOrString); + if (nxagentKeyboard && (strcmp(nxagentKeyboard, "null/null") == 0)) + { + #ifdef TEST + fprintf(stderr, "nxagentReconnect: changing nxagentKeyboard from [null/null] to [clone].\n"); + #endif + + free(nxagentKeyboard); + nxagentKeyboard = strdup("clone"); + } + if (nxagentReconnectDisplay(reconnectLossyLevel[DISPLAY_STEP]) == 0) { failedStep = DISPLAY_STEP; diff --git a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 index 938c2eb57..737d3609d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 +++ b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 @@ -623,7 +623,8 @@ protocol functions and clone them. This is the recommended setting. For compatibility reasons it is not the default. .TP 8 .I / -use the given model and layout. You can not modify keyboard rules, +use the given model and layout. A value of \fInull/null\fR is equivalent to +\fIclone\fR. You can not modify keyboard rules, variant or options this way. Instead preset values are used. These are \fIbase\fR for rules and empty strings for variant and options. .TP 8 -- cgit v1.2.3