Browse Source

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.
tags/v1.8.90
Pierre Ossman 7 years ago
parent
commit
1668cfaef2
5 changed files with 133 additions and 12 deletions
  1. 20
    12
      vncviewer/DesktopWindow.cxx
  2. 81
    0
      vncviewer/Viewport.cxx
  3. 2
    0
      vncviewer/Viewport.h
  4. 3
    0
      vncviewer/cocoa.h
  5. 27
    0
      vncviewer/cocoa.mm

+ 20
- 12
vncviewer/DesktopWindow.cxx View File

@@ -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;
}
}

+ 81
- 0
vncviewer/Viewport.cxx View File

@@ -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)
{

+ 2
- 0
vncviewer/Viewport.h View File

@@ -49,6 +49,8 @@ public:

// Change client LED state
void setLEDState(unsigned int state);
// Change server LED state
void pushLEDState();

void draw(Surface* dst);


+ 3
- 0
vncviewer/cocoa.h View File

@@ -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

+ 27
- 0
vncviewer/cocoa.mm View File

@@ -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);
}

Loading…
Cancel
Save