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
@@ -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; | |||
} | |||
} |
@@ -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) | |||
{ |
@@ -49,6 +49,8 @@ public: | |||
// Change client LED state | |||
void setLEDState(unsigned int state); | |||
// Change server LED state | |||
void pushLEDState(); | |||
void draw(Surface* dst); | |||
@@ -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 |
@@ -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); | |||
} |