Initial stab at keyboard support. Lots of corner case to work out though...
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4349 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index e225119..23d66f1 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -26,10 +26,17 @@
#include <rfb/CMsgWriter.h>
#include <rfb/LogWriter.h>
+// FLTK can pull in the X11 headers on some systems
+#ifndef XK_VoidSymbol
+#define XK_MISCELLANY
+#include <rfb/keysymdef.h>
+#endif
+
#include "DesktopWindow.h"
#include "CConn.h"
#include "i18n.h"
#include "parameters.h"
+#include "keysym2ucs.h"
using namespace rfb;
@@ -197,6 +204,18 @@
handlePointerEvent(Point(Fl::event_x(), Fl::event_y()), buttonMask);
return 1;
+
+ case FL_FOCUS:
+ // Yes, we would like some focus please!
+ return 1;
+
+ case FL_KEYDOWN:
+ handleKeyEvent(Fl::event_key(), Fl::event_text(), true);
+ return 1;
+
+ case FL_KEYUP:
+ handleKeyEvent(Fl::event_key(), Fl::event_text(), false);
+ return 1;
}
return Fl_Window::handle(event);
@@ -255,3 +274,144 @@
self->cc->writer()->pointerEvent(self->lastPointerPos, self->lastButtonMask);
}
+
+void DesktopWindow::handleKeyEvent(int keyCode, const char *keyText, bool down)
+{
+ rdr::U32 keySym;
+
+ if (viewOnly)
+ return;
+
+ if (keyCode > 0xFFFF) {
+ vlog.error(_("Too large FLTK key code %d (0x%08x)"), keyCode, keyCode);
+ return;
+ }
+
+ // Because of the way keyboards work, we cannot expect to have the same
+ // symbol on release as when pressed. This breaks the VNC protocol however,
+ // so we need to keep track of what keysym a key _code_ generated on press
+ // and send the same on release.
+ if (!down) {
+ cc->writer()->keyEvent(downKeySym[keyCode], false);
+ return;
+ }
+
+ // Special key
+ if (keyText[0] == '\0') {
+ if ((keyCode >= FL_F) && (keyCode <= FL_F_Last))
+ keySym = XK_F1 + (keyCode - FL_F);
+#if 0
+ case FL_KP 0xff80 ///< One of the keypad numbers; use FL_KP + n for number n.
+ case FL_KP_Enter 0xff8d ///< The enter key on the keypad, same as Fl_KP+'\\r'.
+ case FL_KP_Last 0xffbd ///< The last keypad key; use to range-check keypad.
+#endif
+ else {
+ switch (keyCode) {
+ case FL_BackSpace:
+ keySym = XK_BackSpace;
+ break;
+ case FL_Tab:
+ keySym = XK_Tab;
+ break;
+ case FL_Enter:
+ keySym = XK_Return;
+ break;
+ case FL_Pause:
+ keySym = XK_Pause;
+ break;
+ case FL_Scroll_Lock:
+ keySym = XK_Scroll_Lock;
+ break;
+ case FL_Escape:
+ keySym = XK_Escape;
+ break;
+ case FL_Home:
+ keySym = XK_Home;
+ break;
+ case FL_Left:
+ keySym = XK_Left;
+ break;
+ case FL_Up:
+ keySym = XK_Up;
+ break;
+ case FL_Right:
+ keySym = XK_Right;
+ break;
+ case FL_Down:
+ keySym = XK_Down;
+ break;
+ case FL_Page_Up:
+ keySym = XK_Page_Up;
+ break;
+ case FL_Page_Down:
+ keySym = XK_Page_Down;
+ break;
+ case FL_End:
+ keySym = XK_End;
+ break;
+ case FL_Print:
+ keySym = XK_Print;
+ break;
+ case FL_Insert:
+ keySym = XK_Insert;
+ break;
+ case FL_Menu:
+ keySym = XK_Menu;
+ break;
+ case FL_Help:
+ keySym = XK_Help;
+ break;
+ case FL_Num_Lock:
+ keySym = XK_Num_Lock;
+ break;
+ case FL_Shift_L:
+ keySym = XK_Shift_L;
+ break;
+ case FL_Shift_R:
+ keySym = XK_Shift_R;
+ break;
+ case FL_Control_L:
+ keySym = XK_Control_L;
+ break;
+ case FL_Control_R:
+ keySym = XK_Control_R;
+ break;
+ case FL_Caps_Lock:
+ keySym = XK_Caps_Lock;
+ break;
+ case FL_Meta_L:
+ keySym = XK_Super_L;
+ break;
+ case FL_Meta_R:
+ keySym = XK_Super_R;
+ break;
+ case FL_Alt_L:
+ keySym = XK_Alt_L;
+ break;
+ case FL_Alt_R:
+ keySym = XK_Alt_R;
+ break;
+ case FL_Delete:
+ keySym = XK_Delete;
+ break;
+ default:
+ vlog.error(_("Unknown FLTK key code %d (0x%04x)"), keyCode, keyCode);
+ return;
+ }
+ }
+ } else {
+ unsigned ucs;
+
+ if (fl_utf_nb_char((const unsigned char*)keyText, strlen(keyText)) != 1) {
+ vlog.error(_("Multiple characters given for key code %d (0x%04x): '%s'"),
+ keyCode, keyCode, keyText);
+ return;
+ }
+
+ ucs = fl_utf8decode(keyText, NULL, NULL);
+ keySym = ucs2keysym(ucs);
+ }
+
+ downKeySym[keyCode] = keySym;
+ cc->writer()->keyEvent(keySym, down);
+}