aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2016-12-10 17:13:40 +0100
committerPierre Ossman <ossman@cendio.se>2017-08-24 12:33:08 +0200
commit1668cfaef2fe7effb38f311d232d4f57a8703d11 (patch)
treeb0d3e8f6f82246618720f66fdba695fde2e0bd5c /vncviewer
parent2fa63f8576e5d1c632efeeb2c185f11e943899d8 (diff)
downloadtigervnc-1668cfaef2fe7effb38f311d232d4f57a8703d11.tar.gz
tigervnc-1668cfaef2fe7effb38f311d232d4f57a8703d11.zip
Sync LED state when gaining focus
The state might have changed when we didn't have focus. Get everything back in sync once we're back in control.
Diffstat (limited to 'vncviewer')
-rw-r--r--vncviewer/DesktopWindow.cxx32
-rw-r--r--vncviewer/Viewport.cxx81
-rw-r--r--vncviewer/Viewport.h2
-rw-r--r--vncviewer/cocoa.h3
-rw-r--r--vncviewer/cocoa.mm27
5 files changed, 133 insertions, 12 deletions
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index 3973cd66..897f9557 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -666,23 +666,31 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
DesktopWindow *dw = dynamic_cast<DesktopWindow*>(win);
- if (dw && fullscreenSystemKeys) {
+ if (dw) {
switch (event) {
case FL_FOCUS:
- // FIXME: We reassert the keyboard grabbing on focus as FLTK there are
- // some issues we need to work around:
- // a) Fl::grab(0) on X11 will release the keyboard grab for us.
- // b) Gaining focus on the system level causes FLTK to switch
- // window level on OS X.
- if (dw->fullscreen_active())
- dw->grabKeyboard();
+ if (fullscreenSystemKeys) {
+ // FIXME: We reassert the keyboard grabbing on focus as FLTK there are
+ // some issues we need to work around:
+ // a) Fl::grab(0) on X11 will release the keyboard grab for us.
+ // b) Gaining focus on the system level causes FLTK to switch
+ // window level on OS X.
+ if (dw->fullscreen_active())
+ dw->grabKeyboard();
+ }
+
+ // We may have gotten our lock keys out of sync with the server
+ // whilst we didn't have focus. Try to sort this out.
+ dw->viewport->pushLEDState();
break;
case FL_UNFOCUS:
- // FIXME: We need to relinquish control when the entire window loses
- // focus as it is very tied to this specific window on some
- // platforms and we want to be able to open subwindows.
- dw->ungrabKeyboard();
+ if (fullscreenSystemKeys) {
+ // FIXME: We need to relinquish control when the entire window loses
+ // focus as it is very tied to this specific window on some
+ // platforms and we want to be able to open subwindows.
+ dw->ungrabKeyboard();
+ }
break;
}
}
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index c0bbd0dd..bfadd4c0 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -329,6 +329,87 @@ void Viewport::setLEDState(unsigned int state)
#endif
}
+void Viewport::pushLEDState()
+{
+ unsigned int state;
+
+ // Server support?
+ if (cc->cp.ledState() == ledUnknown)
+ return;
+
+ state = 0;
+
+#if defined(WIN32)
+ if (GetKeyState(VK_CAPITAL) & 0x1)
+ state |= ledCapsLock;
+ if (GetKeyState(VK_NUMLOCK) & 0x1)
+ state |= ledNumLock;
+ if (GetKeyState(VK_SCROLL) & 0x1)
+ state |= ledScrollLock;
+#elif defined(__APPLE__)
+ int ret;
+ bool on;
+
+ ret = cocoa_get_caps_lock_state(&on);
+ if (ret != 0) {
+ vlog.error(_("Failed to get keyboard LED state: %d"), ret);
+ return;
+ }
+ if (on)
+ state |= ledCapsLock;
+
+ ret = cocoa_get_num_lock_state(&on);
+ if (ret != 0) {
+ vlog.error(_("Failed to get keyboard LED state: %d"), ret);
+ return;
+ }
+ if (on)
+ state |= ledNumLock;
+
+ // No support for Scroll Lock //
+ state |= (cc->cp.ledState() & ledScrollLock);
+
+#else
+ unsigned int mask;
+
+ Status status;
+ XkbStateRec xkbState;
+
+ status = XkbGetState(fl_display, XkbUseCoreKbd, &xkbState);
+ if (status != Success) {
+ vlog.error(_("Failed to get keyboard LED state: %d"), status);
+ return;
+ }
+
+ if (xkbState.locked_mods & LockMask)
+ state |= ledCapsLock;
+
+ mask = getModifierMask(XK_Num_Lock);
+ if (xkbState.locked_mods & mask)
+ state |= ledNumLock;
+
+ mask = getModifierMask(XK_Scroll_Lock);
+ if (xkbState.locked_mods & mask)
+ state |= ledScrollLock;
+#endif
+
+ if ((state & ledCapsLock) != (cc->cp.ledState() & ledCapsLock)) {
+ vlog.debug("Inserting fake CapsLock to get in sync with server");
+ handleKeyPress(fakeKeyBase + 100, XK_Caps_Lock);
+ handleKeyRelease(fakeKeyBase + 100);
+ }
+ if ((state & ledNumLock) != (cc->cp.ledState() & ledNumLock)) {
+ vlog.debug("Inserting fake NumLock to get in sync with server");
+ handleKeyPress(fakeKeyBase + 101, XK_Num_Lock);
+ handleKeyRelease(fakeKeyBase + 101);
+ }
+ if ((state & ledScrollLock) != (cc->cp.ledState() & ledScrollLock)) {
+ vlog.debug("Inserting fake ScrollLock to get in sync with server");
+ handleKeyPress(fakeKeyBase + 102, XK_Scroll_Lock);
+ handleKeyRelease(fakeKeyBase + 102);
+ }
+}
+
void Viewport::draw(Surface* dst)
{
diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h
index 652feb45..31158c2d 100644
--- a/vncviewer/Viewport.h
+++ b/vncviewer/Viewport.h
@@ -49,6 +49,8 @@ public:
// Change client LED state
void setLEDState(unsigned int state);
+ // Change server LED state
+ void pushLEDState();
void draw(Surface* dst);
diff --git a/vncviewer/cocoa.h b/vncviewer/cocoa.h
index b5d5f763..a7138026 100644
--- a/vncviewer/cocoa.h
+++ b/vncviewer/cocoa.h
@@ -36,4 +36,7 @@ int cocoa_event_keysym(const void *event);
int cocoa_set_caps_lock_state(bool on);
int cocoa_set_num_lock_state(bool on);
+int cocoa_get_caps_lock_state(bool *on);
+int cocoa_get_num_lock_state(bool *on);
+
#endif
diff --git a/vncviewer/cocoa.mm b/vncviewer/cocoa.mm
index 6483291c..e26851d6 100644
--- a/vncviewer/cocoa.mm
+++ b/vncviewer/cocoa.mm
@@ -447,6 +447,23 @@ static int cocoa_set_modifier_lock_state(int modifier, bool on)
return KERN_SUCCESS;
}
+static int cocoa_get_modifier_lock_state(int modifier, bool *on)
+{
+ kern_return_t ret;
+ io_connect_t ioc;
+
+ ret = cocoa_open_hid(&ioc);
+ if (ret != KERN_SUCCESS)
+ return ret;
+
+ ret = IOHIDGetModifierLockState(ioc, modifier, on);
+ IOServiceClose(ioc);
+ if (ret != KERN_SUCCESS)
+ return ret;
+
+ return KERN_SUCCESS;
+}
+
int cocoa_set_caps_lock_state(bool on)
{
return cocoa_set_modifier_lock_state(kIOHIDCapsLockState, on);
@@ -456,3 +473,13 @@ int cocoa_set_num_lock_state(bool on)
{
return cocoa_set_modifier_lock_state(kIOHIDNumLockState, on);
}
+
+int cocoa_get_caps_lock_state(bool *on)
+{
+ return cocoa_get_modifier_lock_state(kIOHIDCapsLockState, on);
+}
+
+int cocoa_get_num_lock_state(bool *on)
+{
+ return cocoa_get_modifier_lock_state(kIOHIDNumLockState, on);
+}