aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer/KeyboardX11.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vncviewer/KeyboardX11.cxx')
-rw-r--r--vncviewer/KeyboardX11.cxx125
1 files changed, 125 insertions, 0 deletions
diff --git a/vncviewer/KeyboardX11.cxx b/vncviewer/KeyboardX11.cxx
index 973278fc..587d9fc5 100644
--- a/vncviewer/KeyboardX11.cxx
+++ b/vncviewer/KeyboardX11.cxx
@@ -22,6 +22,7 @@
#include <assert.h>
+#include <algorithm>
#include <stdexcept>
#include <X11/XKBlib.h>
@@ -87,6 +88,63 @@ KeyboardX11::~KeyboardX11()
{
}
+struct GrabInfo {
+ Window window;
+ bool found;
+};
+
+static Bool is_same_window(Display*, XEvent* event, XPointer arg)
+{
+ GrabInfo* info = (GrabInfo*)arg;
+
+ assert(info);
+
+ // Focus is returned to our window
+ if ((event->type == FocusIn) &&
+ (event->xfocus.window == info->window)) {
+ info->found = true;
+ }
+
+ // Focus got stolen yet again
+ if ((event->type == FocusOut) &&
+ (event->xfocus.window == info->window)) {
+ info->found = false;
+ }
+
+ return False;
+}
+
+bool KeyboardX11::isKeyboardReset(const void* event)
+{
+ const XEvent* xevent = (const XEvent*)event;
+
+ assert(event);
+
+ if (xevent->type == FocusOut) {
+ if (xevent->xfocus.mode == NotifyGrab) {
+ GrabInfo info;
+ XEvent dummy;
+
+ // Something grabbed the keyboard, but we don't know if it was to
+ // ourselves or someone else
+
+ // Make sure we have all the queued events from the X server
+ XSync(fl_display, False);
+
+ // Check if we'll get the focus back right away
+ info.window = xevent->xfocus.window;
+ info.found = false;
+ XCheckIfEvent(fl_display, &dummy, is_same_window, (XPointer)&info);
+ if (info.found)
+ return false;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool KeyboardX11::handleEvent(const void* event)
{
const XEvent *xevent = (const XEvent*)event;
@@ -98,6 +156,10 @@ bool KeyboardX11::handleEvent(const void* event)
char str;
KeySym keysym;
+ // FLTK likes to use this instead of CurrentTime, so we need to keep
+ // it updated now that we steal this event
+ fl_event_time = xevent->xkey.time;
+
keycode = code_map_keycode_to_qnum[xevent->xkey.keycode];
XLookupString((XKeyEvent*)&xevent->xkey, &str, 1, &keysym, nullptr);
@@ -109,6 +171,7 @@ bool KeyboardX11::handleEvent(const void* event)
handler->handleKeyPress(xevent->xkey.keycode, keycode, keysym);
return true;
} else if (xevent->type == KeyRelease) {
+ fl_event_time = xevent->xkey.time;
handler->handleKeyRelease(xevent->xkey.keycode);
return true;
}
@@ -116,6 +179,31 @@ bool KeyboardX11::handleEvent(const void* event)
return false;
}
+std::list<uint32_t> KeyboardX11::translateToKeySyms(int systemKeyCode)
+{
+ Status status;
+ XkbStateRec state;
+ std::list<uint32_t> keySyms;
+ unsigned char group;
+
+ status = XkbGetState(fl_display, XkbUseCoreKbd, &state);
+ if (status != Success)
+ return keySyms;
+
+ // Start with the currently used group
+ translateToKeySyms(systemKeyCode, state.group, &keySyms);
+
+ // Then all other groups
+ for (group = 0; group < XkbNumKbdGroups; group++) {
+ if (group == state.group)
+ continue;
+
+ translateToKeySyms(systemKeyCode, group, &keySyms);
+ }
+
+ return keySyms;
+}
+
unsigned KeyboardX11::getLEDState()
{
unsigned state;
@@ -219,3 +307,40 @@ out:
return mask;
}
+
+void KeyboardX11::translateToKeySyms(int systemKeyCode,
+ unsigned char group,
+ std::list<uint32_t>* keySyms)
+{
+ unsigned int mods;
+
+ // Start with no modifiers
+ translateToKeySyms(systemKeyCode, group, 0, keySyms);
+
+ // Next just a single modifier at a time
+ for (mods = 1; mods < (Mod5Mask+1); mods <<= 1)
+ translateToKeySyms(systemKeyCode, group, mods, keySyms);
+
+ // Finally everything
+ for (mods = 0; mods < (Mod5Mask<<1); mods++)
+ translateToKeySyms(systemKeyCode, group, mods, keySyms);
+}
+
+void KeyboardX11::translateToKeySyms(int systemKeyCode,
+ unsigned char group,
+ unsigned char mods,
+ std::list<uint32_t>* keySyms)
+{
+ KeySym ks;
+ std::list<uint32_t>::const_iterator iter;
+
+ ks = XkbKeycodeToKeysym(fl_display, systemKeyCode, group, mods);
+ if (ks == NoSymbol)
+ return;
+
+ iter = std::find(keySyms->begin(), keySyms->end(), ks);
+ if (iter != keySyms->end())
+ return;
+
+ keySyms->push_back(ks);
+}