From afceb7ebaed13dd680a1acfb8354b736a1fd2cc3 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sat, 18 Jan 2020 18:20:00 +0100 Subject: Dialog.c: show configured keystrokes in dialogs Instead of hardcoding the keystrokes in Dialog.h determine the currently configured keystrokes for the action and insert them into the dialog strings. Fixes ArcticaProject/nx-libs#438 --- nx-X11/programs/Xserver/hw/nxagent/Dialog.c | 26 ++++- nx-X11/programs/Xserver/hw/nxagent/Dialog.h | 19 ++-- nx-X11/programs/Xserver/hw/nxagent/Keystroke.c | 129 ++++++++++++++++++++----- nx-X11/programs/Xserver/hw/nxagent/Keystroke.h | 3 + 4 files changed, 144 insertions(+), 33 deletions(-) (limited to 'nx-X11/programs/Xserver/hw/nxagent') diff --git a/nx-X11/programs/Xserver/hw/nxagent/Dialog.c b/nx-X11/programs/Xserver/hw/nxagent/Dialog.c index 2d4eb6229..808e1501f 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Dialog.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Dialog.c @@ -41,6 +41,7 @@ #include "Display.h" #include "Dialog.h" #include "Utils.h" +#include "Keystroke.h" #include #include "compext/Compext.h" @@ -187,6 +188,7 @@ void nxagentLaunchDialog(DialogType dialogType) int *pid; char *type; char *message; + char *strings[2] = {NULL}; /* don't forget to add free() calls if you change the number */ int local; const char *window = NULL; @@ -247,6 +249,7 @@ void nxagentLaunchDialog(DialogType dialogType) type = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_TYPE; local = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_LOCAL; pid = &nxagentEnableRandRModeDialogPid; + strings[0] = nxagentFindFirstKeystroke("resize"); break; } case DIALOG_DISABLE_DESKTOP_RESIZE_MODE: @@ -255,6 +258,8 @@ void nxagentLaunchDialog(DialogType dialogType) type = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_TYPE; local = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_LOCAL; pid = &nxagentDisableRandRModeDialogPid; + strings[0] = nxagentFindFirstKeystroke("resize"); + strings[1] = nxagentFindMatchingKeystrokes("viewport_"); break; } case DIALOG_ENABLE_DEFER_MODE: @@ -263,6 +268,7 @@ void nxagentLaunchDialog(DialogType dialogType) type = DIALOG_ENABLE_DEFER_MODE_TYPE; local = DIALOG_ENABLE_DEFER_MODE_LOCAL; pid = &nxagentEnableDeferModePid; + strings[0] = nxagentFindFirstKeystroke("defer"); break; } case DIALOG_DISABLE_DEFER_MODE: @@ -271,6 +277,7 @@ void nxagentLaunchDialog(DialogType dialogType) type = DIALOG_DISABLE_DEFER_MODE_TYPE; local = DIALOG_DISABLE_DEFER_MODE_LOCAL; pid = &nxagentDisableDeferModePid; + strings[0] = nxagentFindFirstKeystroke("defer"); break; } case DIALOG_ENABLE_AUTOGRAB_MODE: @@ -279,6 +286,7 @@ void nxagentLaunchDialog(DialogType dialogType) type = DIALOG_ENABLE_AUTOGRAB_MODE_TYPE; local = DIALOG_ENABLE_AUTOGRAB_MODE_LOCAL; pid = &nxagentEnableAutograbModePid; + strings[0] = nxagentFindFirstKeystroke("autograb"); break; } case DIALOG_DISABLE_AUTOGRAB_MODE: @@ -287,6 +295,7 @@ void nxagentLaunchDialog(DialogType dialogType) type = DIALOG_DISABLE_AUTOGRAB_MODE_TYPE; local = DIALOG_DISABLE_AUTOGRAB_MODE_LOCAL; pid = &nxagentDisableAutograbModePid; + strings[0] = nxagentFindFirstKeystroke("autograb"); break; } default: @@ -321,6 +330,17 @@ void nxagentLaunchDialog(DialogType dialogType) return; } + char *msg = NULL; + if (-1 == asprintf(&msg, message, strings[0], strings[1])) + { + #ifdef DEBUG + fprintf(stderr, "%s: could not allocate message string.\n", __func__); + #endif + SAFE_free(strings[0]); + SAFE_free(strings[1]); + return; + } + /* * We don't want to receive SIGCHLD before we store the child pid. */ @@ -331,9 +351,13 @@ void nxagentLaunchDialog(DialogType dialogType) sigprocmask(SIG_BLOCK, &set, &oldSet); - *pid = NXTransDialog(nxagentDialogName, message, window, + *pid = NXTransDialog(nxagentDialogName, msg, window, type, local, dialogDisplay); + SAFE_free(strings[0]); + SAFE_free(strings[1]); + SAFE_free(msg); + #ifdef TEST fprintf(stderr, "nxagentLaunchDialog: Launched dialog %s with pid [%d] on display %s.\n", DECODE_DIALOG_TYPE(dialogType), *pid, dialogDisplay); diff --git a/nx-X11/programs/Xserver/hw/nxagent/Dialog.h b/nx-X11/programs/Xserver/hw/nxagent/Dialog.h index 42bba290d..2f503bc62 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Dialog.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Dialog.h @@ -174,7 +174,7 @@ nxagentFailedReconnectionMessage "\ The session is now running in desktop resize mode.\n\ You can resize the desktop by simply dragging the\n\ -desktop window's border. You can press Ctrl+Alt+R\n\ +desktop window's border. You can press %s\n\ again to disable this option.\ " @@ -187,9 +187,12 @@ again to disable this option.\ "\ The session is now running in viewport mode. You can\n\ navigate across different areas of the desktop window\n\ -by dragging the desktop with the mouse or by using the\n\ -arrows keys while pressing Ctrl+Alt. Press Ctrl+Alt+R\n\ -again to return to the desktop resize mode.\ +by dragging the desktop with the mouse while pressing\n\ +Ctrl+Alt or use the keystrokes listed below. Press\n\ +%s again to return to the desktop resize mode.\n\ +\n\ +Use these keystrokes to navigate:\n\ +%s\ " #define DIALOG_DISABLE_DESKTOP_RESIZE_MODE_TYPE "ok" @@ -201,7 +204,7 @@ again to return to the desktop resize mode.\ \ "\ Deferred screen updates are now enabled. You can press\n\ -Ctrl+Alt+E again to disable this option.\ +%s again to disable this option.\ " #define DIALOG_ENABLE_DEFER_MODE_TYPE "ok" @@ -213,7 +216,7 @@ Ctrl+Alt+E again to disable this option.\ \ "\ Deferred screen updates are now disabled. You can press\n\ -Ctrl+Alt+E to enable it again.\ +%s to enable it again.\ " #define DIALOG_DISABLE_DEFER_MODE_TYPE "ok" @@ -225,7 +228,7 @@ Ctrl+Alt+E to enable it again.\ \ "\ Keyboard auto-grabbing mode is now enabled. You can press\n\ -Ctrl+Alt+G again to disable auto-grabbing.\ +%s again to disable auto-grabbing.\ " #define DIALOG_ENABLE_AUTOGRAB_MODE_TYPE "ok" @@ -237,7 +240,7 @@ Ctrl+Alt+G again to disable auto-grabbing.\ \ "\ Keyboard auto-grabbing mode is now disabled. You can press\n\ -Ctrl+Alt+G again to re-enable auto-grabbing.\ +%s again to re-enable auto-grabbing.\ " #define DIALOG_DISABLE_AUTOGRAB_MODE_TYPE "ok" diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c index ea139b10f..2f89195f5 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c @@ -428,35 +428,117 @@ void nxagentInitKeystrokes(Bool force) nxagentDumpKeystrokes(); } -void nxagentDumpKeystrokes(void) +static char *nxagentGetSingleKeystrokeString(struct nxagentSpecialKeystrokeMap *cur) +{ + if (!cur) + return strdup(""); /* caller is expected to free the returned string */ + + char *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11; + s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = s9 = s10 = s11 = ""; + + unsigned int mask = cur->modifierMask; + + if (mask & ControlMask) {s1 = "Ctrl+"; mask &= ~ControlMask;} + if (mask & ShiftMask) {s2 = "Shift+"; mask &= ~ShiftMask;} + + /* these are only here for better readable modifier names. Normally + they are covered by the Mod and Lock lines below */ + if (cur->modifierAltMeta) {s3 = "Alt+"; mask &= ~(cur->modifierAltMeta);} + if (mask & nxagentCapsMask) {s4 = "CapsLock+"; mask &= ~nxagentCapsMask;} + if (mask & nxagentNumlockMask) {s5 = "NumLock+"; mask &= ~nxagentNumlockMask;} + + if (mask & Mod1Mask) {s6 = "Mod1+"; mask &= ~Mod1Mask;} + if (mask & Mod2Mask) {s7 = "Mod2+"; mask &= ~Mod2Mask;} + if (mask & Mod3Mask) {s8 = "Mod3+"; mask &= ~Mod3Mask;} + if (mask & Mod4Mask) {s9 = "Mod4+"; mask &= ~Mod4Mask;} + if (mask & Mod5Mask) {s10 = "Mod5+"; mask &= ~Mod5Mask;} + if (mask & LockMask) {s11 = "Lock+"; mask &= ~LockMask;} + + char *ret = NULL; + asprintf(&ret, "%s%s%s%s%s%s%s%s%s%s%s%s", s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, XKeysymToString(cur->keysym)); + return ret; +} + +/* + * return the _first_ keystroke for the passed keystroke name + * + * e.g. nxagentFindFirstKeystroke("resize") -> "Ctrl+Alt+r" + * + * result must be free()d after use. + */ +char *nxagentFindFirstKeystroke(char *name) +{ + for (struct nxagentSpecialKeystrokeMap *cur = map; cur->stroke != KEYSTROKE_END_MARKER; cur++) + { + if (nxagentSpecialKeystrokeNames[cur->stroke] && + strcmp(nxagentSpecialKeystrokeNames[cur->stroke], name) == 0) + { + return nxagentGetSingleKeystrokeString(cur); + } + } + return NULL; +} + +/* + * return a string with linefeeds of all keystrokes who's name starts + * with the the passed string, + * + * e.g. nxagentFindKeystrokeString("viewport_scroll_") + * -> + * " viewport_scroll_left : Ctrl+Alt+Left + * viewport_scroll_left : Ctrl+Alt+KP_Left + * viewport_scroll_up : Ctrl+Alt+Up + * viewport_scroll_up : Ctrl+Alt+KP_Up + * viewport_scroll_right : Ctrl+Alt+Right + * viewport_scroll_right : Ctrl+Alt+KP_Right + * viewport_scroll_down : Ctrl+Alt+Down + * viewport_scroll_down : Ctrl+Alt+KP_Down + * " + * result must be free()d after use. + */ +char *nxagentFindMatchingKeystrokes(char *name) { int maxlen = 0; for (int i = 0; nxagentSpecialKeystrokeNames[i]; i++) maxlen = max(maxlen, strlen(nxagentSpecialKeystrokeNames[i])); - fprintf(stderr, "Currently known keystrokes:\n"); - - for (struct nxagentSpecialKeystrokeMap *cur = map; cur->stroke != KEYSTROKE_END_MARKER; cur++) { - unsigned int mask = cur->modifierMask; - fprintf(stderr, " %-*s ", maxlen, nxagentSpecialKeystrokeNames[cur->stroke]); - if (mask & ControlMask) {fprintf(stderr, "Ctrl+"); mask &= ~ControlMask;} - if (mask & ShiftMask) {fprintf(stderr, "Shift+"); mask &= ~ShiftMask;} - - /* these are only here for better readable modifier - names. Normally they are covered by the Mod and Lock lines - below */ - if (cur->modifierAltMeta) {fprintf(stderr, "Alt+"); mask &= ~(cur->modifierAltMeta);} - if (mask & nxagentCapsMask) {fprintf(stderr, "CapsLock+"); mask &= ~nxagentCapsMask;} - if (mask & nxagentNumlockMask) {fprintf(stderr, "NumLock+"); mask &= ~nxagentNumlockMask;} - - if (mask & Mod1Mask) {fprintf(stderr, "Mod1+"); mask &= ~Mod1Mask;} - if (mask & Mod2Mask) {fprintf(stderr, "Mod2+"); mask &= ~Mod2Mask;} - if (mask & Mod3Mask) {fprintf(stderr, "Mod3+"); mask &= ~Mod3Mask;} - if (mask & Mod4Mask) {fprintf(stderr, "Mod4+"); mask &= ~Mod4Mask;} - if (mask & Mod5Mask) {fprintf(stderr, "Mod5+"); mask &= ~Mod5Mask;} - if (mask & LockMask) {fprintf(stderr, "Lock+"); mask &= ~LockMask;} - fprintf(stderr, "%s\n", XKeysymToString(cur->keysym)); + char * res = strdup(""); /* let the caller free the string */ + for (struct nxagentSpecialKeystrokeMap *cur = map; cur->stroke != KEYSTROKE_END_MARKER; cur++) + { + if (nxagentSpecialKeystrokeNames[cur->stroke] && + strncmp(nxagentSpecialKeystrokeNames[cur->stroke], name, strlen(name)) == 0) + { + char *tmp; + char *tmp1 = nxagentGetSingleKeystrokeString(cur); + if (-1 == asprintf(&tmp, "%s %-*s : %s\n", res, maxlen, + nxagentSpecialKeystrokeNames[cur->stroke], + tmp1)) + { + SAFE_free(tmp1); + #ifdef TEST + fprintf(stderr, "%s: returning incomplete result:\n%s", __func__, res); + #endif + return res; + } + else + { + SAFE_free(tmp1); + free(res); + res = tmp; + } + } } + #ifdef TEST + fprintf(stderr, "%s: returning result:\n%s", __func__, res); + #endif + return res; +} + +void nxagentDumpKeystrokes(void) +{ + char *s = nxagentFindMatchingKeystrokes(""); + fprintf(stderr, "Currently known keystrokes:\n%s", s); + SAFE_free(s); } static enum nxagentSpecialKeystroke find_keystroke(XKeyEvent *X) @@ -465,7 +547,6 @@ static enum nxagentSpecialKeystroke find_keystroke(XKeyEvent *X) KeySym keysym = XKeycodeToKeysym(nxagentDisplay, X->keycode, 0); - #ifdef DEBUG fprintf(stderr, "%s: got keysym '%c' (%d)\n", __func__, keysym, keysym); #endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h index 9d7c4c4d5..463bda9b3 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h @@ -32,6 +32,9 @@ extern Bool nxagentCheckSpecialKeystroke(XKeyEvent*, enum HandleEventResult*); extern void nxagentDumpKeystrokes(void); extern void nxagentInitKeystrokes(Bool force); +char *nxagentFindFirstKeystroke(char *name); +char *nxagentFindMatchingKeystrokes(char *name); + /* 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 */ -- cgit v1.2.3