Unverified Commit a8c65ab6 authored by Mike Gabriel's avatar Mike Gabriel

Merge branch 'uli42-pr/improve_keyboard2' into 3.6.x

parents ab3e1485 a70ec920
......@@ -78,12 +78,11 @@ is" without express or implied warranty.
#include <errno.h>
static int nxagentXkbGetNames(char **rules, char **model, char **layout,
char **variant, char **options);
static void nxagentXkbGetNames(void);
static void nxagentKeycodeConversionSetup(char *rules, char *model);
void nxagentKeycodeConversionSetup(void);
void nxagentWriteKeyboardFile(char *rules, char *model, char *layout, char *variant, char *options);
static void nxagentWriteKeyboardFile(char *rules, char *model, char *layout, char *variant, char *options);
#endif /* XKB */
......@@ -140,6 +139,13 @@ extern Status XkbGetControls(
extern int XkbDfltRepeatDelay;
extern int XkbDfltRepeatInterval;
/* xkb configuration of the real X server */
static char *nxagentRemoteRules = NULL;
static char *nxagentRemoteModel = NULL;
static char *nxagentRemoteLayout = NULL;
static char *nxagentRemoteVariant = NULL;
static char *nxagentRemoteOptions = NULL;
#endif /* XKB */
/*
......@@ -571,8 +577,10 @@ int nxagentKeyboardProc(DeviceIntPtr pDev, int onoff)
CARD8 modmap[MAP_LENGTH];
int i, j;
XKeyboardState values;
#ifdef XKB
char *model = NULL, *layout = NULL;
XkbDescPtr xkb = NULL;
#endif
switch (onoff)
{
......@@ -694,20 +702,13 @@ N/A
keySyms.mapWidth = mapWidth;
keySyms.map = keymap;
if (XkbQueryExtension(nxagentDisplay,
&nxagentXkbInfo.Opcode,
&nxagentXkbInfo.EventBase,
&nxagentXkbInfo.ErrorBase,
&nxagentXkbInfo.MajorVersion,
&nxagentXkbInfo.MinorVersion) == 0)
#ifdef XKB
if (!nxagentGetRemoteXkbExtension())
{
ErrorF("Unable to initialize XKEYBOARD extension.\n");
ErrorF("Unable to query XKEYBOARD extension.\n");
goto XkbError;
}
#ifdef XKB
if (noXkbExtension) {
#ifdef TEST
fprintf(stderr, "nxagentKeyboardProc: No XKB extension.\n");
......@@ -761,7 +762,9 @@ XkbError:
layout.
*/
if (nxagentKeyboard && (strcmp(nxagentKeyboard, "query") != 0))
if (nxagentKeyboard &&
(strcmp(nxagentKeyboard, "query") != 0) &&
(strcmp(nxagentKeyboard, "clone") != 0))
{
for (i = 0; nxagentKeyboard[i] != '/' && nxagentKeyboard[i] != 0; i++);
......@@ -772,8 +775,33 @@ XkbError:
goto XkbError;
}
/*
The original nxagent only supports model/layout values
here. It uses these values together with the default rules
and empty variant and options. We use a more or less
compatible hack here: The special keyword rlmvo for model
means that the layout part of the string will contain a
full RMLVO config, separated by #, e.g.
rlmvo/base#pc105#de,us#nodeadkeys#lv3:rwin_switch
*/
if (strncmp(nxagentKeyboard, "rlmvo/", 6) == 0)
{
const char * sep = "#";
char * rmlvo = strdup(&nxagentKeyboard[i+1]);
char * tmp = rmlvo;
/* strtok cannot handle empty fields, so use strsep */
rules = strdup(strsep(&tmp, sep));
model = strdup(strsep(&tmp, sep));
layout = strdup(strsep(&tmp, sep));
variant = strdup(strsep(&tmp, sep));
options = strdup(strsep(&tmp, sep));
free(rmlvo);
}
else
{
model = strndup(nxagentKeyboard, i);
layout = strdup(&nxagentKeyboard[i + 1]);
}
/*
* There is no description for pc105 on Solaris.
......@@ -781,8 +809,8 @@ XkbError:
*/
#ifdef TEST
fprintf(stderr, "nxagentKeyboardProc: Using keyboard model [%s] with layout [%s].\n",
model, layout);
fprintf(stderr, "%s: Using [rules='%s',model='%s',layout='%s',variant='%s',options='%s'].\n",
__func__, rules, model, layout, variant, options);
#endif
#ifdef __sun
......@@ -791,7 +819,6 @@ XkbError:
{
#ifdef TEST
fprintf(stderr, "nxagentKeyboardProc: WARNING! Keyboard model 'pc105' unsupported on Solaris.\n");
fprintf(stderr, "nxagentKeyboardProc: WARNING! Forcing keyboard model to 'pc104'.\n");
#endif
......@@ -812,36 +839,47 @@ XkbError:
fprintf(stderr, "nxagentKeyboardProc: Init XKB extension.\n");
#endif
if (nxagentRemoteRules && nxagentRemoteModel)
{
char *remoterules = NULL;
char *remotemodel = NULL;
char *remotelayout = NULL;
char *remotevariant = NULL;
char *remoteoptions = NULL;
#ifdef DEBUG
fprintf(stderr, "%s: Remote: [rules='%s',model='%s',layout='%s',variant='%s',options='%s'].\n",
__func__, nxagentRemoteRules, nxagentRemoteModel, nxagentRemoteLayout, nxagentRemoteVariant, nxagentRemoteOptions);
#endif
unsigned int remoteruleslen = nxagentXkbGetNames(&remoterules, &remotemodel, &remotelayout,
&remotevariant, &remoteoptions);
/*
* 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);
#ifdef DEBUG
if (remoteruleslen && remoterules && remotemodel)
/* Only setup keycode conversion if we are NOT in clone mode */
if (nxagentKeyboard && (strcmp(nxagentKeyboard, "clone") == 0))
{
fprintf(stderr, "%s: Remote: [rules='%s',model='%s',layout='%s',variant='%s',options='%s'].\n",
__func__, remoterules, remotemodel, remotelayout, remotevariant, remoteoptions);
free(rules); rules = strdup(nxagentRemoteRules);
free(model); model = strdup(nxagentRemoteModel);
free(layout); layout = strdup(nxagentRemoteLayout);
free(variant); variant = strdup(nxagentRemoteVariant);
free(options); options = strdup(nxagentRemoteOptions);
}
else
{
fprintf(stderr, "%s: Failed to retrieve remote rules.\n", __func__);
nxagentKeycodeConversionSetup();
}
#endif
nxagentWriteKeyboardFile(remoterules, remotemodel, remotelayout, remotevariant, remoteoptions);
nxagentKeycodeConversionSetup(remoterules, remotemodel);
if (remoterules)
{
XFree(remoterules);
}
#ifdef DEBUG
else
{
fprintf(stderr, "%s: Failed to retrieve remote rules.\n", __func__);
}
#endif
xkb = XkbGetKeyboard(nxagentDisplay, XkbGBN_AllComponentsMask, XkbUseCoreKbd);
......@@ -1498,8 +1536,16 @@ void nxagentTuneXkbWrapper(void)
}
}
static int nxagentXkbGetNames(char **rules, char **model, char **layout,
char **variant, char **options)
void nxagentXkbClearNames(void)
{
free(nxagentRemoteRules); nxagentRemoteRules = NULL;
free(nxagentRemoteModel); nxagentRemoteModel = NULL;
free(nxagentRemoteLayout); nxagentRemoteLayout = NULL;
free(nxagentRemoteVariant); nxagentRemoteVariant = NULL;
free(nxagentRemoteOptions); nxagentRemoteOptions = NULL;
}
static void nxagentXkbGetNames(void)
{
Atom atom;
#ifdef _XSERVER64
......@@ -1514,28 +1560,25 @@ static int nxagentXkbGetNames(char **rules, char **model, char **layout,
char *name;
Status result;
data = name = NULL;
*rules = NULL;
*model = NULL;
*layout = NULL;
*variant = NULL;
*options = NULL;
if (nxagentRemoteRules)
return;
atom = XInternAtom(nxagentDisplay, "_XKB_RULES_NAMES", 1);
if (atom == 0)
{
return 0;
return;
}
data = name = NULL;
result = XGetWindowProperty(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
atom, 0, 256, 0, XA_STRING, &type, &format,
&n, &after, (unsigned char **)&data);
if (result != Success || !data)
{
return 0;
return;
}
if ((after > 0) || (type != XA_STRING) || (format != 8))
......@@ -1543,7 +1586,7 @@ static int nxagentXkbGetNames(char **rules, char **model, char **layout,
if (data)
{
XFree(data);
return 0;
return;
}
}
......@@ -1551,38 +1594,40 @@ static int nxagentXkbGetNames(char **rules, char **model, char **layout,
if (name < data + n)
{
*rules = name;
nxagentRemoteRules = strdup(name);
name += strlen(name) + 1;
}
if (name < data + n)
{
*model = name;
nxagentRemoteModel = strdup(name);
name += strlen(name) + 1;
}
if (name < data + n)
{
*layout = name;
nxagentRemoteLayout = strdup(name);
name += strlen(name) + 1;
}
if (name < data + n)
{
*variant = name;
nxagentRemoteVariant = strdup(name);
name += strlen(name) + 1;
}
if (name < data + n)
{
*options = name;
nxagentRemoteOptions = strdup(name);
name += strlen(name) + 1;
}
return n;
XFree(data);
return;
}
void writeKeyboardfileData(FILE *out, char *rules, char *model, char *layout, char *variant, char *options)
static void writeKeyboardfileData(FILE *out, char *rules, char *model, char *layout, char *variant, char *options)
{
/*
How to set "empty" values with setxkbmap, result of trial and error:
......@@ -1600,7 +1645,7 @@ void writeKeyboardfileData(FILE *out, char *rules, char *model, char *layout, ch
fprintf(out, "options=\",%s\"\n", options ? options : "");
}
void nxagentWriteKeyboardFile(char *rules, char *model, char *layout, char *variant, char *options)
static void nxagentWriteKeyboardFile(char *rules, char *model, char *layout, char *variant, char *options)
{
if (rules && rules[0] != '\0')
{
......@@ -1644,12 +1689,16 @@ void nxagentWriteKeyboardFile(char *rules, char *model, char *layout, char *vari
}
}
void nxagentKeycodeConversionSetup(char * rules, char * model)
void nxagentKeycodeConversionSetup(void)
{
nxagentKeycodeConversion = False;
if (nxagentXkbInfo.Opcode == -1)
return;
if (nxagentOption(KeycodeConversion) == KeycodeConversionOff)
{
fprintf(stderr, "Info: Keycode conversion is off\n");
nxagentKeycodeConversion = False;
}
else if (nxagentOption(KeycodeConversion) == KeycodeConversionOn)
{
......@@ -1658,9 +1707,9 @@ void nxagentKeycodeConversionSetup(char * rules, char * model)
}
else
{
if (rules && model &&
(strcmp(rules, "evdev") == 0 ||
strcmp(model, "evdev") == 0))
if (nxagentRemoteRules && nxagentRemoteModel &&
(strcmp(nxagentRemoteRules, "evdev") == 0 ||
strcmp(nxagentRemoteModel, "evdev") == 0))
{
#ifdef DEBUG
fprintf(stderr, "%s: Activating KeyCode conversion.\n", __func__);
......@@ -1676,47 +1725,33 @@ void nxagentKeycodeConversionSetup(char * rules, char * model)
#endif
fprintf(stderr, "Info: Keycode conversion auto-determined as off\n");
nxagentKeycodeConversion = False;
}
}
}
void nxagentResetKeycodeConversion(void)
Bool nxagentGetRemoteXkbExtension(void)
{
int result;
XkbAgentInfoRec info;
Bool result;
result = XkbQueryExtension(nxagentDisplay, &info.Opcode, &info.EventBase,
&info.ErrorBase, &info.MajorVersion,
&info.MinorVersion);
nxagentXkbInfo.Opcode = nxagentXkbInfo.EventBase = nxagentXkbInfo.ErrorBase = nxagentXkbInfo.MajorVersion = nxagentXkbInfo.MinorVersion = -1;
nxagentXkbClearNames();
if (result != 0)
if ((result = XkbQueryExtension(nxagentDisplay,
&nxagentXkbInfo.Opcode,
&nxagentXkbInfo.EventBase,
&nxagentXkbInfo.ErrorBase,
&nxagentXkbInfo.MajorVersion,
&nxagentXkbInfo.MinorVersion)))
{
char *remoterules = NULL;
char *remotemodel = NULL;
char *remotelayout = NULL;
char *remotevariant = NULL;
char *remoteoptions = NULL;
unsigned int remoteruleslen;
remoteruleslen = nxagentXkbGetNames(&remoterules, &remotemodel, &remotelayout,
&remotevariant, &remoteoptions);
if (remoteruleslen && remoterules && remotemodel)
nxagentKeycodeConversionSetup(remoterules, remotemodel);
if (remoterules)
XFree(remoterules);
nxagentXkbGetNames();
}
#ifdef WARNING
else
{
#ifdef WARNING
fprintf(stderr, "nxagentResetKeycodeConversion: "
"WARNING! Failed to query XKB extension.\n");
fprintf(stderr, "%s: WARNING! Failed to query XKB extension.\n", __func__);
}
#endif
nxagentKeycodeConversion = False;
}
return result;
}
#endif /* XKB */
......@@ -117,8 +117,9 @@ void nxagentEnableXkbExtension(void);
void nxagentTuneXkbWrapper(void);
void nxagentResetKeycodeConversion(void);
void nxagentKeycodeConversionSetup(void);
Bool nxagentGetRemoteXkbExtension(void);
#endif
CARD8 nxagentConvertKeycode(CARD8 k);
......
......@@ -584,6 +584,9 @@ Bool nxagentReconnectSession(void)
goto nxagentReconnectError;
}
/* Update remote XKB information */
nxagentGetRemoteXkbExtension();
/* if there's no keyboard definition in the options file
restore the previous value. */
#ifdef DEBUG
......@@ -598,7 +601,8 @@ Bool nxagentReconnectSession(void)
if (nxagentOption(ResetKeyboardAtResume) == 1 &&
(nxagentKeyboard == NULL || nxagentOldKeyboard == NULL ||
strcmp(nxagentKeyboard, nxagentOldKeyboard) != 0 ||
strcmp(nxagentKeyboard, "query") == 0))
strcmp(nxagentKeyboard, "query") == 0 ||
strcmp(nxagentKeyboard, "clone") == 0))
{
if (nxagentResetKeyboard() == 0)
{
......@@ -616,7 +620,7 @@ Bool nxagentReconnectSession(void)
}
else
{
nxagentResetKeycodeConversion();
nxagentKeycodeConversionSetup();
}
nxagentXkbState.Initialized = 0;
......
......@@ -525,8 +525,8 @@ don't reset keyboard device if the session is resumed
this is only relevant if you also specify \-keyboard=query. In that
case \fBnxagent\fR will lock the keyboard settings and clients will
get an error when trying to change keyboard settings via
XKEYBOARD. With \-noxkblock the lock is not applied and clients can
change the keyboard settings through XKEYBOARD.
XKEYBOARD. With \-noxkblock the lock is not applied and clients are
allowed change the keyboard settings through XKEYBOARD.
.TP 8
.B \-tile WxH
size of image tiles (minimum allowed: 32x32)
......@@ -603,7 +603,7 @@ start or resume a session in fullscreen mode (default: off)
.TP 8
.B keyboard=<string> or kbtype=<string>
.BR query | <model>/<layout>
.BR query | clone | <model>/<layout> | rmlvo/<rules>#<model>#<layout>#<variant>#<options>
.RS 8
.TP 8
......@@ -617,10 +617,22 @@ this platform. Note that in this case XKEYBOARD will always report
the default layout which will most likely not match the experienced
settings.
.TP 8
.I clone
ask the real X server for the keyboard settings using XKEYBOARD
protocol functions and clone them. This is the recommended setting. For
compatibility reasons it is not the default.
.TP 8
.I <model>/<layout>
use the given model and layout. You can not modify keyboard rules,
variant or options. Instead preset values are used. These are
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
.I rmlvo/<rules>#<model>#<layout>#<variant>#<options>
configure the keyboard according to the rmlvo
(Rules+Model+Layout+Variant+Options) description given after the / and
separated by #. This can be used to fully pass the keyboard
configuration of \fBnxagent\fR right after the start. Example:
rmlvo/base#pc105#de,us#nodeadkeys#lv3:rwin_switch
.RE
.TP 8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment