From b4a390a92d7aabb4685ae8eeed561f5022403fed Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sun, 5 Mar 2017 23:51:24 +0100 Subject: [PATCH 01/14] add autograb mode and inputlock mode Fixes ArcticaProject/nx-libs#384 You can now toggle between autograb mode by pressing CTRL-ALT-G (default, can be adjusted in keystrokes.cfg). You can toogle inputlock mode (pointer stays in the nxagent window) by pressing CTRL-ALT-C. --- doc/nxagent/README.keystrokes | 6 + etc/keystrokes.cfg | 2 + nx-X11/programs/Xserver/hw/nxagent/Events.c | 155 +++++++++++++++++- nx-X11/programs/Xserver/hw/nxagent/Events.h | 4 +- .../programs/Xserver/hw/nxagent/Keystroke.c | 14 +- .../programs/Xserver/hw/nxagent/Keystroke.h | 3 + 6 files changed, 179 insertions(+), 5 deletions(-) diff --git a/doc/nxagent/README.keystrokes b/doc/nxagent/README.keystrokes index 750a460ebd..32974cbca6 100644 --- a/doc/nxagent/README.keystrokes +++ b/doc/nxagent/README.keystrokes @@ -126,6 +126,12 @@ reread_keystrokes Forces nxagent to re-read the keystroke configuration. Useful to add/change keystrokes to a running session. +autograb + Toggles autograb mode + +lockinput + Locks/unlocsk pointer within nxagent window + force_synchronization Forces immediate drawing of elements to be synchronized which can fix some visual bugs. diff --git a/etc/keystrokes.cfg b/etc/keystrokes.cfg index 8563698392..c8c40e35f6 100644 --- a/etc/keystrokes.cfg +++ b/etc/keystrokes.cfg @@ -24,4 +24,6 @@ + + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index d8bf4df60e..6b57ed1fce 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -78,6 +78,8 @@ #undef Atom #undef Time +#include + #ifdef NXAGENT_FIXKEYS #include "inputstr.h" #include "input.h" @@ -678,6 +680,103 @@ static void nxagentSwitchDeferMode(void) } } +void setWinNameSuffix(const char *suffix) +{ + static unsigned char * prev = NULL; + char * pre = " ("; + char * post = ")"; + char * newname; + + if (suffix) { + if (!(newname = calloc(strlen(nxagentWindowName) + strlen(pre) + strlen(suffix) + strlen(post) + 1, sizeof(char)))) + { + fprintf(stderr, "%s: malloc failed", __func__); + return; + } + strcpy(newname, nxagentWindowName); + strcpy(newname + strlen(nxagentWindowName), pre); + strcpy(newname + strlen(nxagentWindowName) + strlen(pre), suffix); + strcpy(newname + strlen(nxagentWindowName) + strlen(pre) + strlen(suffix), post); + free(prev); + prev = NULL; + XFetchName(nxagentDisplay, nxagentDefaultWindows[0], &prev); + XStoreName(nxagentDisplay, nxagentDefaultWindows[0], newname); + free(newname); + } + else + { + if (prev) + { + XStoreName(nxagentDisplay, nxagentDefaultWindows[0], prev); + free(prev); + prev = NULL; + } + else + { + XStoreName(nxagentDisplay, nxagentDefaultWindows[0], nxagentWindowName); + } + } +} + +static Bool autograb = False; +static Bool inputlock = False; + +static void nxagentAutoGrab(void) +{ + if (!inputlock) + { + #ifdef DEBUG + if (autograb) + fprintf(stderr, "disabling autograb\n"); + else + fprintf(stderr, "enabling autograb\n"); + #endif + + if (!autograb) + { + nxagentGrabPointerAndKeyboard(NULL); + setWinNameSuffix("autograb on"); + } + else + { + nxagentUngrabPointerAndKeyboard(NULL); + setWinNameSuffix(NULL); + } + autograb = !autograb; + } +} + +/* TODO: drop inputlock when switching to Fullscreen */ +static void nxagentLockInput(void) +{ + #ifdef DEBUG + if (inputlock) + fprintf(stderr, "releasing inputlock\n"); + else + fprintf(stderr, "activating inputlock\n"); + #endif + + if (!inputlock) + { + setWinNameSuffix("input locked"); + XGrabPointer(nxagentDisplay,nxagentDefaultWindows[0], True, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask, + GrabModeAsync, GrabModeAsync, nxagentDefaultWindows[0], None, CurrentTime); + } + else + { + nxagentUngrabPointerAndKeyboard(NULL); + XTextProperty name = { + .value = (unsigned char *)nxagentWindowName, + .encoding = XA_STRING, + .format = 8, + .nitems = strlen((char *) name.value) + }; + setWinNameSuffix(NULL); + } + inputlock = !inputlock; +} + static Bool nxagentExposurePredicate(Display *display, XEvent *event, XPointer window) { /* @@ -1064,6 +1163,18 @@ void nxagentDispatchEvents(PredicateFuncPtr predicate) break; } + case doAutoGrab: + { + nxagentAutoGrab(); + + break; + } + case doLockInput: + { + nxagentLockInput(); + + break; + } default: { FatalError("nxagentDispatchEvent: handleKeyPress returned unknown value\n"); @@ -1508,6 +1619,17 @@ FIXME: Don't enqueue the KeyRelease event if the key was } } + /* FIXME: only when in windowed mode! */ + if (autograb) + { + if (X.xfocus.window == nxagentDefaultWindows[0] && X.xfocus.mode == NotifyNormal) + { + #ifdef DEBUG + fprintf(stderr, "%s: (FocusIn): grabbing\n", __func__); + #endif + nxagentGrabPointerAndKeyboard(NULL); + } + } break; } case FocusOut: @@ -1586,6 +1708,19 @@ FIXME: Don't enqueue the KeyRelease event if the key was #endif /* NXAGENT_FIXKEYS */ + if (autograb) + { + XlibWindow w; + int revert_to; + XGetInputFocus(nxagentDisplay, &w, &revert_to); + if (w != nxagentDefaultWindows[0] && X.xfocus.mode == NotifyWhileGrabbed) + { + #ifdef DEBUG + fprintf(stderr, "%s: (FocusOut): ungrabbing\n", __func__); + #endif + nxagentUngrabPointerAndKeyboard(NULL); + } + } break; } case KeymapNotify: @@ -3844,13 +3979,26 @@ void nxagentGrabPointerAndKeyboard(XEvent *X) fprintf(stderr, "nxagentGrabPointerAndKeyboard: Going to grab the keyboard in context [B1].\n"); #endif - result = XGrabKeyboard(nxagentDisplay, nxagentFullscreenWindow, - True, GrabModeAsync, GrabModeAsync, now); + if (nxagentFullscreenWindow) + result = XGrabKeyboard(nxagentDisplay, nxagentFullscreenWindow, + True, GrabModeAsync, GrabModeAsync, now); + else + result = XGrabKeyboard(nxagentDisplay, RootWindow(nxagentDisplay, DefaultScreen(nxagentDisplay)), + True, GrabModeAsync, GrabModeAsync, now); if (result != GrabSuccess) { + #ifdef DEBUG + fprintf(stderr, "%s: keyboard grab failed.\n", __func__); + #endif return; } + #ifdef DEBUG + else + { + fprintf(stderr, "%s: keyboard grab successful.\n", __func__); + } + #endif /* * The smart scheduler could be stopped while @@ -3868,7 +4016,8 @@ void nxagentGrabPointerAndKeyboard(XEvent *X) resource = nxagentWaitForResource(NXGetCollectGrabPointerResource, nxagentCollectGrabPointerPredicate); - NXCollectGrabPointer(nxagentDisplay, resource, + if (nxagentFullscreenWindow) + NXCollectGrabPointer(nxagentDisplay, resource, nxagentFullscreenWindow, True, NXAGENT_POINTER_EVENT_MASK, GrabModeAsync, GrabModeAsync, None, None, now); diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.h b/nx-X11/programs/Xserver/hw/nxagent/Events.h index 5df0e1f05c..f24a6584fb 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.h @@ -50,7 +50,9 @@ enum HandleEventResult doViewportRight, doViewportDown, doSwitchResizeMode, - doSwitchDeferMode + doSwitchDeferMode, + doAutoGrab, + doLockInput }; extern CARD32 nxagentLastEventTime; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c index 662da6b04d..28a73c15a0 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c @@ -99,6 +99,10 @@ char * nxagentSpecialKeystrokeNames[] = { "viewport_scroll_down", "reread_keystrokes", + + "autograb", + "lockinput", + NULL, }; @@ -138,6 +142,8 @@ struct nxagentSpecialKeystrokeMap default_map[] = { {KEYSTROKE_VIEWPORT_SCROLL_DOWN, ControlMask, True, XK_Down}, {KEYSTROKE_VIEWPORT_SCROLL_DOWN, ControlMask, True, XK_KP_Down}, {KEYSTROKE_REREAD_KEYSTROKES, ControlMask, True, XK_k}, + {KEYSTROKE_AUTOGRAB, ControlMask, True, XK_g}, + {KEYSTROKE_LOCKINPUT, ControlMask, True, XK_c}, {KEYSTROKE_END_MARKER, 0, False, NoSymbol}, }; struct nxagentSpecialKeystrokeMap *map = default_map; @@ -467,7 +473,7 @@ static enum nxagentSpecialKeystroke find_keystroke(XKeyEvent *X) #endif for (struct nxagentSpecialKeystrokeMap *cur = map; cur->stroke != KEYSTROKE_END_MARKER; cur++) { #ifdef DEBUG - fprintf(stderr, "%s: checking keysym '%c' (%d)\n", __func__, cur->keysym, cur->keysym); + fprintf(stderr,"%s: keysym %d stroke %d, type %d\n", __func__, cur->keysym, cur->stroke, X->type); #endif if (cur->keysym == keysym && modifier_matches(cur->modifierMask, cur->modifierAltMeta, X->state)) { #ifdef DEBUG @@ -624,6 +630,12 @@ Bool nxagentCheckSpecialKeystroke(XKeyEvent *X, enum HandleEventResult *result) if (X->type == KeyRelease) nxagentInitKeystrokes(True); break; + case KEYSTROKE_AUTOGRAB: + *result = doAutoGrab; + break; + case KEYSTROKE_LOCKINPUT: + *result = doLockInput; + 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: diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h index 13a83d0fea..4ec76f4f0c 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h @@ -73,6 +73,9 @@ enum nxagentSpecialKeystroke { KEYSTROKE_REREAD_KEYSTROKES, + KEYSTROKE_AUTOGRAB, + KEYSTROKE_LOCKINPUT, + KEYSTROKE_NOTHING, /* insert more here and in the string translation */ From 355ce8906a99cb54f6874cdd92c2dbee6fe448eb Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 16 Mar 2017 12:24:14 +0100 Subject: [PATCH 02/14] Refactor AutoGrab --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 48 +++++++++++++-------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 6b57ed1fce..a0da62bb8c 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -721,28 +721,40 @@ void setWinNameSuffix(const char *suffix) static Bool autograb = False; static Bool inputlock = False; -static void nxagentAutoGrab(void) +static void nxagentEnableAutoGrab(void) { +#ifdef DEBUG + fprintf(stderr, "enabling autograb\n"); +#endif + + nxagentGrabPointerAndKeyboard(NULL); + setWinNameSuffix("autograb on"); + autograb = True; +} + +static void nxagentDisableAutoGrab(void) +{ +#ifdef DEBUG + fprintf(stderr, "disabling autograb\n"); +#endif + + nxagentUngrabPointerAndKeyboard(NULL); + setWinNameSuffix(NULL); + autograb = False; +} + +static void nxagentToggleAutoGrab(void) +{ + /* autograb only works in windowed mode */ + if (nxagentOption(Rootless) || nxagentOption(Fullscreen)) + return; + if (!inputlock) { - #ifdef DEBUG - if (autograb) - fprintf(stderr, "disabling autograb\n"); - else - fprintf(stderr, "enabling autograb\n"); - #endif - if (!autograb) - { - nxagentGrabPointerAndKeyboard(NULL); - setWinNameSuffix("autograb on"); - } + nxagentEnableAutoGrab(); else - { - nxagentUngrabPointerAndKeyboard(NULL); - setWinNameSuffix(NULL); - } - autograb = !autograb; + nxagentDisableAutoGrab(); } } @@ -1165,7 +1177,7 @@ void nxagentDispatchEvents(PredicateFuncPtr predicate) } case doAutoGrab: { - nxagentAutoGrab(); + nxagentToggleAutoGrab(); break; } From c3376e2f992a40b833d7e6911ffe4c9ca594d2c3 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 16 Mar 2017 12:26:39 +0100 Subject: [PATCH 03/14] Refactor InputLock --- etc/keystrokes.cfg | 2 +- nx-X11/programs/Xserver/hw/nxagent/Events.c | 60 ++++++++++--------- nx-X11/programs/Xserver/hw/nxagent/Events.h | 2 +- .../programs/Xserver/hw/nxagent/Keystroke.c | 8 +-- .../programs/Xserver/hw/nxagent/Keystroke.h | 2 +- 5 files changed, 40 insertions(+), 34 deletions(-) diff --git a/etc/keystrokes.cfg b/etc/keystrokes.cfg index c8c40e35f6..2cb242641d 100644 --- a/etc/keystrokes.cfg +++ b/etc/keystrokes.cfg @@ -25,5 +25,5 @@ - + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index a0da62bb8c..1ffcd62b90 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -758,35 +758,41 @@ static void nxagentToggleAutoGrab(void) } } -/* TODO: drop inputlock when switching to Fullscreen */ -static void nxagentLockInput(void) +static void nxagentEnableInputlock(void) { - #ifdef DEBUG - if (inputlock) - fprintf(stderr, "releasing inputlock\n"); - else - fprintf(stderr, "activating inputlock\n"); - #endif +#ifdef DEBUG + fprintf(stderr, "activating inputlock\n"); +#endif + setWinNameSuffix("input locked"); + XGrabPointer(nxagentDisplay,nxagentDefaultWindows[0], True, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask, + GrabModeAsync, GrabModeAsync, nxagentDefaultWindows[0], None, CurrentTime); + inputlock = True; +} + +static void nxagentDisableInputlock(void) +{ +#ifdef DEBUG + fprintf(stderr, "deactivating inputlock\n"); +#endif + nxagentUngrabPointerAndKeyboard(NULL); + XTextProperty name = { + .value = (unsigned char *)nxagentWindowName, + .encoding = XA_STRING, + .format = 8, + .nitems = strlen((char *) name.value) + }; + setWinNameSuffix(NULL); + inputlock = False; +} +/* TODO: drop inputlock when switching to Fullscreen */ +static void nxagentToggleInputLock(void) +{ if (!inputlock) - { - setWinNameSuffix("input locked"); - XGrabPointer(nxagentDisplay,nxagentDefaultWindows[0], True, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask, - GrabModeAsync, GrabModeAsync, nxagentDefaultWindows[0], None, CurrentTime); - } + nxagentEnableInputlock(); else - { - nxagentUngrabPointerAndKeyboard(NULL); - XTextProperty name = { - .value = (unsigned char *)nxagentWindowName, - .encoding = XA_STRING, - .format = 8, - .nitems = strlen((char *) name.value) - }; - setWinNameSuffix(NULL); - } - inputlock = !inputlock; + nxagentDisableInputlock(); } static Bool nxagentExposurePredicate(Display *display, XEvent *event, XPointer window) @@ -1181,9 +1187,9 @@ void nxagentDispatchEvents(PredicateFuncPtr predicate) break; } - case doLockInput: + case doInputLock: { - nxagentLockInput(); + nxagentToggleInputLock(); break; } diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.h b/nx-X11/programs/Xserver/hw/nxagent/Events.h index f24a6584fb..3c5623ca16 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.h @@ -52,7 +52,7 @@ enum HandleEventResult doSwitchResizeMode, doSwitchDeferMode, doAutoGrab, - doLockInput + doInputLock }; extern CARD32 nxagentLastEventTime; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c index 28a73c15a0..19f829c8e0 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c @@ -101,7 +101,7 @@ char * nxagentSpecialKeystrokeNames[] = { "reread_keystrokes", "autograb", - "lockinput", + "inputlock", NULL, }; @@ -143,7 +143,7 @@ struct nxagentSpecialKeystrokeMap default_map[] = { {KEYSTROKE_VIEWPORT_SCROLL_DOWN, ControlMask, True, XK_KP_Down}, {KEYSTROKE_REREAD_KEYSTROKES, ControlMask, True, XK_k}, {KEYSTROKE_AUTOGRAB, ControlMask, True, XK_g}, - {KEYSTROKE_LOCKINPUT, ControlMask, True, XK_c}, + {KEYSTROKE_INPUTLOCK, ControlMask, True, XK_c}, {KEYSTROKE_END_MARKER, 0, False, NoSymbol}, }; struct nxagentSpecialKeystrokeMap *map = default_map; @@ -633,8 +633,8 @@ Bool nxagentCheckSpecialKeystroke(XKeyEvent *X, enum HandleEventResult *result) case KEYSTROKE_AUTOGRAB: *result = doAutoGrab; break; - case KEYSTROKE_LOCKINPUT: - *result = doLockInput; + case KEYSTROKE_INPUTLOCK: + *result = doInputLock; break; case KEYSTROKE_NOTHING: /* do nothing. difference to KEYSTROKE_IGNORE is the return value */ case KEYSTROKE_END_MARKER: /* just to make gcc STFU */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h index 4ec76f4f0c..73d29bbda2 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h @@ -74,7 +74,7 @@ enum nxagentSpecialKeystroke { KEYSTROKE_REREAD_KEYSTROKES, KEYSTROKE_AUTOGRAB, - KEYSTROKE_LOCKINPUT, + KEYSTROKE_INPUTLOCK, KEYSTROKE_NOTHING, From 3a0fbd0662b31f3635617cb65c8fd37855431bb4 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 16 Mar 2017 12:30:44 +0100 Subject: [PATCH 04/14] Events.c: window name is signed --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 1ffcd62b90..34faa53b14 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -682,7 +682,7 @@ static void nxagentSwitchDeferMode(void) void setWinNameSuffix(const char *suffix) { - static unsigned char * prev = NULL; + static char * prev = NULL; char * pre = " ("; char * post = ")"; char * newname; From b5338e79a714f6e4b81f2f374903e0c4c3af3c6c Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 16 Mar 2017 13:00:48 +0100 Subject: [PATCH 05/14] make autograb and inputlock nxagent options --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 21 +++++++++----------- nx-X11/programs/Xserver/hw/nxagent/Options.c | 4 ++++ nx-X11/programs/Xserver/hw/nxagent/Options.h | 12 +++++++++++ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 34faa53b14..3c07723ff2 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -718,9 +718,6 @@ void setWinNameSuffix(const char *suffix) } } -static Bool autograb = False; -static Bool inputlock = False; - static void nxagentEnableAutoGrab(void) { #ifdef DEBUG @@ -729,7 +726,7 @@ static void nxagentEnableAutoGrab(void) nxagentGrabPointerAndKeyboard(NULL); setWinNameSuffix("autograb on"); - autograb = True; + nxagentChangeOption(AutoGrab, True); } static void nxagentDisableAutoGrab(void) @@ -740,7 +737,7 @@ static void nxagentDisableAutoGrab(void) nxagentUngrabPointerAndKeyboard(NULL); setWinNameSuffix(NULL); - autograb = False; + nxagentChangeOption(AutoGrab, False); } static void nxagentToggleAutoGrab(void) @@ -749,9 +746,9 @@ static void nxagentToggleAutoGrab(void) if (nxagentOption(Rootless) || nxagentOption(Fullscreen)) return; - if (!inputlock) + if (!nxagentOption(InputLock)) { - if (!autograb) + if (!nxagentOption(AutoGrab)) nxagentEnableAutoGrab(); else nxagentDisableAutoGrab(); @@ -767,7 +764,7 @@ static void nxagentEnableInputlock(void) XGrabPointer(nxagentDisplay,nxagentDefaultWindows[0], True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask, GrabModeAsync, GrabModeAsync, nxagentDefaultWindows[0], None, CurrentTime); - inputlock = True; + nxagentChangeOption(InputLock, True); } static void nxagentDisableInputlock(void) @@ -783,13 +780,13 @@ static void nxagentDisableInputlock(void) .nitems = strlen((char *) name.value) }; setWinNameSuffix(NULL); - inputlock = False; + nxagentChangeOption(InputLock, False); } /* TODO: drop inputlock when switching to Fullscreen */ static void nxagentToggleInputLock(void) { - if (!inputlock) + if (!nxagentOption(InputLock)) nxagentEnableInputlock(); else nxagentDisableInputlock(); @@ -1638,7 +1635,7 @@ FIXME: Don't enqueue the KeyRelease event if the key was } /* FIXME: only when in windowed mode! */ - if (autograb) + if (nxagentOption(AutoGrab)) { if (X.xfocus.window == nxagentDefaultWindows[0] && X.xfocus.mode == NotifyNormal) { @@ -1726,7 +1723,7 @@ FIXME: Don't enqueue the KeyRelease event if the key was #endif /* NXAGENT_FIXKEYS */ - if (autograb) + if (nxagentOption(AutoGrab)) { XlibWindow w; int revert_to; diff --git a/nx-X11/programs/Xserver/hw/nxagent/Options.c b/nx-X11/programs/Xserver/hw/nxagent/Options.c index c06967c76e..ad229e042f 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Options.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Options.c @@ -172,6 +172,10 @@ void nxagentInitOptions(void) nxagentOptions.ReconnectTolerance = DEFAULT_TOLERANCE; nxagentOptions.KeycodeConversion = DEFAULT_KEYCODE_CONVERSION; + + nxagentOptions.AutoGrab = False; + + nxagentOptions.InputLock = False; } /* diff --git a/nx-X11/programs/Xserver/hw/nxagent/Options.h b/nx-X11/programs/Xserver/hw/nxagent/Options.h index b5394ee016..764a28b82d 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Options.h +++ b/nx-X11/programs/Xserver/hw/nxagent/Options.h @@ -450,6 +450,18 @@ typedef struct _AgentOptions * Convert evdev keycodes to pc105. */ KeycodeConversionMode KeycodeConversion; + + /* + * True if agent should grab the input in windowed mode whenever the + * agent window gets the focus + */ + int AutoGrab; /* Should be Bool but I do not want to include Xlib.h here */ + + /* + * True if the pointer is locked within the agent window (in windowed mode) + */ + int InputLock; /* Should be Bool but I do not want to include Xlib.h here */ + } AgentOptionsRec; typedef AgentOptionsRec *AgentOptionsPtr; From 5ccd51a141850b93c91dca08055479b44796cc50 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 16 Mar 2017 13:12:01 +0100 Subject: [PATCH 06/14] add command line options -autograb and -inputlock --- nx-X11/programs/Xserver/hw/nxagent/Args.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Args.c b/nx-X11/programs/Xserver/hw/nxagent/Args.c index 161403cd0a..2fc8a213b9 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Args.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Args.c @@ -1041,6 +1041,21 @@ int ddxProcessArgument(int argc, char *argv[], int i) return 0; } + if (!strcmp(argv[i], "-autograb")) + { + nxagentChangeOption(AutoGrab, True); + + return 1; + } + + if (!strcmp(argv[i], "-inputlock")) + { + nxagentChangeOption(InputLock, True); + + return 1; + } + + /* * Disable Xinerama (i.e. fake it in Screen.c) if somehow Xinerama support * has been disabled on the cmdline. @@ -2197,6 +2212,8 @@ void ddxUseMsg(void) ErrorF("-noignore don't ignore pointer and keyboard configuration changes mandated by clients\n"); ErrorF("-nokbreset don't reset keyboard device if the session is resumed\n"); ErrorF("-noxkblock always allow applications to change layout through XKEYBOARD\n"); + ErrorF("-autograb enable autograb\n"); + ErrorF("-inputlock enable inputlock\n"); ErrorF("-tile WxH size of image tiles (minimum allowed: 32x32)\n"); ErrorF("-keystrokefile file file with keyboard shortcut definitions\n"); ErrorF("-verbose print more warning and error messages\n"); From 5312a8a75027b2ce7ecde39bca0f360f0ef85b4e Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 20 Apr 2017 14:19:27 +0200 Subject: [PATCH 07/14] make autograb and inputlock available via options file, too --- nx-X11/programs/Xserver/hw/nxagent/Args.c | 26 +++++++++++++++++++ .../programs/Xserver/hw/nxagent/man/nxagent.1 | 6 +++++ 2 files changed, 32 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Args.c b/nx-X11/programs/Xserver/hw/nxagent/Args.c index 2fc8a213b9..7ecd363402 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Args.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Args.c @@ -1556,6 +1556,32 @@ static void nxagentParseSingleOption(char *name, char *value) return; } + else if (!strcmp(name, "autograb")) + { + if (!strcmp(value, "0")) + { + nxagentChangeOption(AutoGrab, False); + } + else + { + nxagentChangeOption(AutoGrab, True); + } + + return; + } + else if (!strcmp(name, "inputlock")) + { + if (!strcmp(value, "0")) + { + nxagentChangeOption(InputLock, False); + } + else + { + nxagentChangeOption(InputLock, True); + } + + return; + } else { #ifdef DEBUG diff --git a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 index 6804032a22..6645901ae5 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 +++ b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 @@ -750,6 +750,12 @@ format must be included in both. This is potentially unsafe. .I bypass means that all of these checks are essentially deactivated. This is a very bad idea. +.TP 8 +.B autograb= +enable or disable autograb (default: disabled) +.TP 8 +.B inputlock= +enable or disable inputlock (default: disabled) .RE If you want to use \fBnxagent\fR as a replacement for Xnest or Xephyr you From 495d9542db8f78fd289a4ff974f62eb8b591dd15 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 20 Apr 2017 17:52:42 +0200 Subject: [PATCH 08/14] Events.c: improve window name suffix handling --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 104 +++++++++++++------- 1 file changed, 70 insertions(+), 34 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 3c07723ff2..306aca4626 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -680,42 +680,76 @@ static void nxagentSwitchDeferMode(void) } } -void setWinNameSuffix(const char *suffix) +enum {WINDOWSUFFIX_AUTOGRAB = 0, WINDOWSUFFIX_INPUTLOCK, WINDOWSUFFIX_MAX}; + +static char * nxagentWindowSuffixes[WINDOWSUFFIX_MAX] = {NULL}; + +void setWinNameSuffix(int index, const char *suffix) { - static char * prev = NULL; - char * pre = " ("; - char * post = ")"; + if (index < 0 || index >= WINDOWSUFFIX_MAX) + return; + + if (nxagentWindowSuffixes[index]) + { + free(nxagentWindowSuffixes[index]); + nxagentWindowSuffixes[index] = NULL; + } + + if (suffix) + nxagentWindowSuffixes[index] = strdup(suffix); +} + +void updateWinName() +{ + static const char * pre = " ("; + static const char * post = ")"; + static const char * comma = ", "; char * newname; - if (suffix) { - if (!(newname = calloc(strlen(nxagentWindowName) + strlen(pre) + strlen(suffix) + strlen(post) + 1, sizeof(char)))) + int len = strlen(nxagentWindowName) + 1; + int count = 0; + for (int i = 0; i < WINDOWSUFFIX_MAX; i++) + { + if (nxagentWindowSuffixes[i]) { - fprintf(stderr, "%s: malloc failed", __func__); - return; + if (count) + len += strlen(comma); + len += strlen(nxagentWindowSuffixes[i]); + count++; } - strcpy(newname, nxagentWindowName); - strcpy(newname + strlen(nxagentWindowName), pre); - strcpy(newname + strlen(nxagentWindowName) + strlen(pre), suffix); - strcpy(newname + strlen(nxagentWindowName) + strlen(pre) + strlen(suffix), post); - free(prev); - prev = NULL; - XFetchName(nxagentDisplay, nxagentDefaultWindows[0], &prev); - XStoreName(nxagentDisplay, nxagentDefaultWindows[0], newname); - free(newname); } - else + + if (count) + len += strlen(pre) + strlen(post); + + if (!(newname = calloc(len, sizeof(char)))) { - if (prev) - { - XStoreName(nxagentDisplay, nxagentDefaultWindows[0], prev); - free(prev); - prev = NULL; - } - else + fprintf(stderr, "%s: malloc failed", __func__); + return; + } + + strncpy(newname, nxagentWindowName, len); + + if (count) + strncat(newname, pre, len); + + int first = True; + for (int i = 0; i < WINDOWSUFFIX_MAX; i++) + { + if (nxagentWindowSuffixes[i]) { - XStoreName(nxagentDisplay, nxagentDefaultWindows[0], nxagentWindowName); + if (!first) + strncat(newname, comma, len); + strncat(newname, nxagentWindowSuffixes[i], len); + first = False; } } + + if (count) + strncat(newname, post, len); + + XStoreName(nxagentDisplay, nxagentDefaultWindows[0], newname); + free(newname); } static void nxagentEnableAutoGrab(void) @@ -725,8 +759,8 @@ static void nxagentEnableAutoGrab(void) #endif nxagentGrabPointerAndKeyboard(NULL); - setWinNameSuffix("autograb on"); - nxagentChangeOption(AutoGrab, True); + setWinNameSuffix(WINDOWSUFFIX_AUTOGRAB, "input grabbed"); + updateWinName(); } static void nxagentDisableAutoGrab(void) @@ -736,8 +770,8 @@ static void nxagentDisableAutoGrab(void) #endif nxagentUngrabPointerAndKeyboard(NULL); - setWinNameSuffix(NULL); - nxagentChangeOption(AutoGrab, False); + setWinNameSuffix(WINDOWSUFFIX_AUTOGRAB, NULL); + updateWinName(); } static void nxagentToggleAutoGrab(void) @@ -760,7 +794,8 @@ static void nxagentEnableInputlock(void) #ifdef DEBUG fprintf(stderr, "activating inputlock\n"); #endif - setWinNameSuffix("input locked"); + setWinNameSuffix(WINDOWSUFFIX_INPUTLOCK, "pointer locked"); + updateWinName(); XGrabPointer(nxagentDisplay,nxagentDefaultWindows[0], True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask, GrabModeAsync, GrabModeAsync, nxagentDefaultWindows[0], None, CurrentTime); @@ -773,14 +808,15 @@ static void nxagentDisableInputlock(void) fprintf(stderr, "deactivating inputlock\n"); #endif nxagentUngrabPointerAndKeyboard(NULL); - XTextProperty name = { + /* XTextProperty name = { .value = (unsigned char *)nxagentWindowName, .encoding = XA_STRING, .format = 8, .nitems = strlen((char *) name.value) }; - setWinNameSuffix(NULL); - nxagentChangeOption(InputLock, False); + */ + setWinNameSuffix(WINDOWSUFFIX_INPUTLOCK, NULL); + updateWinName(); } /* TODO: drop inputlock when switching to Fullscreen */ From bbe4093403afbec9e94e167c8bd2846b884ffe89 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 18 May 2017 15:08:29 +0200 Subject: [PATCH 09/14] Events.c: improve debugging output for FocusIn/Out --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 60 +++++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 306aca4626..1d8cda76f0 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -295,6 +295,36 @@ void ProcessInputEvents(void) mieqProcessInputEvents(); } +#ifdef DEBUG +char * nxagentGetNotifyMode(int mode) +{ + switch (mode) + { + case NotifyNormal: + { + return "NotifyNormal"; + break; + } + case NotifyGrab: + { + return "NotifyGrab"; + break; + } + case NotifyUngrab: + { + return "NotifyUngrab"; + break; + } + case NotifyWhileGrabbed: + { + return "NotifyWhileGrabbed"; + break; + } + } + return "Unknown"; +} +#endif + #ifdef DEBUG_TREE /* @@ -1643,8 +1673,18 @@ FIXME: Don't enqueue the KeyRelease event if the key was { WindowPtr pWin; - #ifdef TEST - fprintf(stderr, "nxagentDispatchEvents: Going to handle new FocusIn event.\n"); + #ifdef DEBUG + fprintf(stderr, "%s: Going to handle new FocusIn event [0x%x] mode: [%s]\n", __func__, X.xfocus.window, nxagentGetNotifyMode(X.xfocus.mode)); + { + XlibWindow w; + int revert_to; + XGetInputFocus(nxagentDisplay, &w, &revert_to); + fprintf(stderr, "%s: (FocusIn): Event win [0x%x] Focus owner [0x%x] nxagentDefaultWindows[0] [0x%x]\n", __func__, X.xfocus.window, w, nxagentDefaultWindows[0]); + } + #else + #ifdef TEST + fprintf(stderr, "%s: Going to handle new FocusIn event\n", __func__); + #endif #endif /* @@ -1680,13 +1720,25 @@ FIXME: Don't enqueue the KeyRelease event if the key was #endif nxagentGrabPointerAndKeyboard(NULL); } + /* else + { + #ifdef DEBUG + fprintf(stderr, "%s: (FocusIn): ungrabbing\n", __func__); + #endif + nxagentUngrabPointerAndKeyboard(NULL); + } + */ } break; } case FocusOut: { - #ifdef TEST - fprintf(stderr, "nxagentDispatchEvents: Going to handle new FocusOut event.\n"); + #ifdef DEBUG + fprintf(stderr, "%s: Going to handle new FocusOut event [0x%x] mode: [%s]\n", __func__, X.xfocus.window, nxagentGetNotifyMode(X.xfocus.mode)); + #else + #ifdef TEST + fprintf(stderr, "%s: Going to handle new FocusOut event.\n", __func__); + #endif #endif if (X.xfocus.detail != NotifyInferior) From 924cde37b24fdd946d2ecf64df82534b33c058b5 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 18 May 2017 15:09:29 +0200 Subject: [PATCH 10/14] Events.c: do not ungrab keyboard on LeaveNotify when in autograb mode --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 1d8cda76f0..cb239aa345 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -1959,11 +1959,14 @@ FIXME: Don't enqueue the KeyRelease event if the key was nxagentLastEnteredWindow = NULL; } - if (X.xcrossing.window == nxagentDefaultWindows[0] && - X.xcrossing.detail != NotifyInferior && - X.xcrossing.mode == NotifyNormal) + if (!nxagentOption(AutoGrab)) { - nxagentUngrabPointerAndKeyboard(&X); + if (X.xcrossing.window == nxagentDefaultWindows[0] && + X.xcrossing.detail != NotifyInferior && + X.xcrossing.mode == NotifyNormal) + { + nxagentUngrabPointerAndKeyboard(&X); + } } if (X.xcrossing.detail != NotifyInferior) From b128c17a2c5591158eddfabf372faf5f43e0afa4 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 18 May 2017 15:19:13 +0200 Subject: [PATCH 11/14] Events.c: change global variable for autograb and inputlock on (de)activation_ --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index cb239aa345..c3b814ca20 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -791,6 +791,7 @@ static void nxagentEnableAutoGrab(void) nxagentGrabPointerAndKeyboard(NULL); setWinNameSuffix(WINDOWSUFFIX_AUTOGRAB, "input grabbed"); updateWinName(); + nxagentChangeOption(AutoGrab, True); } static void nxagentDisableAutoGrab(void) @@ -802,6 +803,7 @@ static void nxagentDisableAutoGrab(void) nxagentUngrabPointerAndKeyboard(NULL); setWinNameSuffix(WINDOWSUFFIX_AUTOGRAB, NULL); updateWinName(); + nxagentChangeOption(AutoGrab, False); } static void nxagentToggleAutoGrab(void) @@ -847,6 +849,7 @@ static void nxagentDisableInputlock(void) */ setWinNameSuffix(WINDOWSUFFIX_INPUTLOCK, NULL); updateWinName(); + nxagentChangeOption(InputLock, False); } /* TODO: drop inputlock when switching to Fullscreen */ From 06be726ef00aa047410543df46ef6a4b92a0cb59 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 18 May 2017 15:20:22 +0200 Subject: [PATCH 12/14] Events.c: fix state display in window title --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index c3b814ca20..34814f8400 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -789,7 +789,7 @@ static void nxagentEnableAutoGrab(void) #endif nxagentGrabPointerAndKeyboard(NULL); - setWinNameSuffix(WINDOWSUFFIX_AUTOGRAB, "input grabbed"); + setWinNameSuffix(WINDOWSUFFIX_AUTOGRAB, "autograb on"); updateWinName(); nxagentChangeOption(AutoGrab, True); } @@ -826,7 +826,7 @@ static void nxagentEnableInputlock(void) #ifdef DEBUG fprintf(stderr, "activating inputlock\n"); #endif - setWinNameSuffix(WINDOWSUFFIX_INPUTLOCK, "pointer locked"); + setWinNameSuffix(WINDOWSUFFIX_INPUTLOCK, "inputlock on"); updateWinName(); XGrabPointer(nxagentDisplay,nxagentDefaultWindows[0], True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask, From 11fdfdac41c239375ae30522d996655ba16e281d Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Thu, 25 May 2017 23:20:50 +0200 Subject: [PATCH 13/14] Events.c: Autograb only for windowed modes This also make re-autograbbing after switch back from AllScreens work. --- nx-X11/programs/Xserver/hw/nxagent/Events.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c index 34814f8400..608b0e12e2 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Events.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -1713,8 +1713,7 @@ FIXME: Don't enqueue the KeyRelease event if the key was } } - /* FIXME: only when in windowed mode! */ - if (nxagentOption(AutoGrab)) + if (nxagentOption(AutoGrab) && !(nxagentOption(AllScreens) || nxagentOption(Fullscreen) || nxagentOption(Rootless))) { if (X.xfocus.window == nxagentDefaultWindows[0] && X.xfocus.mode == NotifyNormal) { From b739b2db3cd505e6921444392f61340292b76903 Mon Sep 17 00:00:00 2001 From: Ulrich Sibiller Date: Sun, 28 May 2017 10:46:01 +0200 Subject: [PATCH 14/14] nxagent.1: fix indentation --- nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 index 6645901ae5..2ee5c1bfa0 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 +++ b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 @@ -750,6 +750,7 @@ format must be included in both. This is potentially unsafe. .I bypass means that all of these checks are essentially deactivated. This is a very bad idea. +.RE .TP 8 .B autograb= enable or disable autograb (default: disabled)