summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--config.h.in1
-rw-r--r--contrib/fltk/01-str2599-fltk-1.3.x-keyboard-x11.patch286
-rw-r--r--contrib/fltk/01-str2636-fltk-1.3.x-clipboard.patch (renamed from contrib/fltk/04-str2636-fltk-1.3.x-clipboard.patch)0
-rw-r--r--contrib/fltk/02-str2599-fltk-1.3.x-keyboard-win32.patch256
-rw-r--r--contrib/fltk/02-str2636-fltk-1.3.x-clipboard-x11.patch (renamed from contrib/fltk/05-str2636-fltk-1.3.x-clipboard-x11.patch)0
-rw-r--r--contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch375
-rw-r--r--contrib/fltk/03-str2636-fltk-1.3.x-clipboard-win32-fix.patch (renamed from contrib/fltk/06-str2636-fltk-1.3.x-clipboard-win32-fix.patch)0
-rw-r--r--contrib/fltk/04-str2636-fltk-1.3.x-clipboard-win32.patch (renamed from contrib/fltk/07-str2636-fltk-1.3.x-clipboard-win32.patch)0
-rw-r--r--contrib/fltk/05-str2636-fltk-1.3.x-clipboard-osx.patch (renamed from contrib/fltk/08-str2636-fltk-1.3.x-clipboard-osx.patch)0
-rw-r--r--contrib/fltk/06-str2659-pixmap.patch (renamed from contrib/fltk/09-str2659-pixmap.patch)0
-rw-r--r--contrib/fltk/07-str2660-fltk-1.3.x-cursor.patch (renamed from contrib/fltk/10-str2660-fltk-1.3.x-cursor.patch)0
-rw-r--r--contrib/fltk/08-str2802-fltk-1.3.0-modal.patch (renamed from contrib/fltk/11-str2802-fltk-1.3.0-modal.patch)0
-rw-r--r--contrib/fltk/09-str2816-fltk-1.3.0-icons.patch (renamed from contrib/fltk/12-str2816-fltk-1.3.0-icons.patch)0
-rw-r--r--contrib/fltk/10-str2860-fltk-1.3.x-screen_num.patch (renamed from contrib/fltk/13-str2860-fltk-1.3.x-screen_num.patch)0
-rw-r--r--contrib/fltk/11-str2860-fltk-1.3.x-multihead.patch (renamed from contrib/fltk/14-str2860-fltk-1.3.x-multihead.patch)0
-rw-r--r--vncviewer/Viewport.cxx325
-rw-r--r--vncviewer/Viewport.h8
-rw-r--r--vncviewer/menukey.cxx68
-rw-r--r--vncviewer/menukey.h5
20 files changed, 224 insertions, 1103 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ce0a00af..30520a51 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -279,9 +279,6 @@ if(FLTK_FOUND)
set(CMAKE_REQUIRED_INCLUDES ${FLTK_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${FLTK_LIBRARIES})
- # FLTK STR #2599
- check_cxx_source_compiles("#include <FL/Fl_Widget.H>\nint main(int c, char** v) { void (Fl_Widget::*foo)() = &Fl_Widget::set_simple_keyboard; return 0; }" HAVE_FLTK_DEAD_KEYS)
-
# FLTK STR #2636
check_cxx_source_compiles("#include <FL/Fl.H>\nint main(int c, char** v) { Fl::add_clipboard_notify(NULL, NULL); return 0; }" HAVE_FLTK_CLIPBOARD)
diff --git a/config.h.in b/config.h.in
index 0c9e71a5..a88c31c5 100644
--- a/config.h.in
+++ b/config.h.in
@@ -10,7 +10,6 @@
#cmakedefine HAVE_GNUTLS_DATUM_T
#cmakedefine HAVE_GNUTLS_PK_ALGORITHM_T
#cmakedefine HAVE_GNUTLS_SIGN_ALGORITHM_T
-#cmakedefine HAVE_FLTK_DEAD_KEYS
#cmakedefine HAVE_FLTK_CLIPBOARD
#cmakedefine HAVE_FLTK_MEDIAKEYS
#cmakedefine HAVE_FLTK_FULLSCREEN
diff --git a/contrib/fltk/01-str2599-fltk-1.3.x-keyboard-x11.patch b/contrib/fltk/01-str2599-fltk-1.3.x-keyboard-x11.patch
deleted file mode 100644
index cabc0f1c..00000000
--- a/contrib/fltk/01-str2599-fltk-1.3.x-keyboard-x11.patch
+++ /dev/null
@@ -1,286 +0,0 @@
-diff -ur fltk-1.3.0r9619.org/FL/Fl_Widget.H fltk-1.3.0r9619/FL/Fl_Widget.H
---- fltk-1.3.0r9619.org/FL/Fl_Widget.H 2012-04-23 22:12:06.000000000 +0200
-+++ fltk-1.3.0r9619/FL/Fl_Widget.H 2012-06-18 13:46:07.302320825 +0200
-@@ -171,6 +171,7 @@
- GROUP_RELATIVE = 1<<16, ///< position this widget relative to the parent group, not to the window
- COPIED_TOOLTIP = 1<<17, ///< the widget tooltip is internally copied, its destruction is handled by the widget
- FULLSCREEN = 1<<18, ///< a fullscreen window (Fl_Window)
-+ SIMPLE_KEYBOARD = 1<<19, ///< the widget wants simple, consistent keypresses and not advanced input (like character composition and CJK input)
- // (space for more flags)
- USERFLAG3 = 1<<29, ///< reserved for 3rd party extensions
- USERFLAG2 = 1<<30, ///< reserved for 3rd party extensions
-@@ -776,6 +777,35 @@
- */
- void clear_changed() {flags_ &= ~CHANGED;}
-
-+ /**
-+ Returns if the widget sees a simplified keyboard model or not.
-+
-+ Normally widgets get a full-featured keyboard model that is geared
-+ towards text input. This includes support for compose sequences and
-+ advanced input methods, commonly used for asian writing system. This
-+ system however has downsides in that extra graphic can be presented
-+ to the user and that a physical key press doesn't correspond directly
-+ to a FLTK event.
-+
-+ Widgets that need a direct correspondence between actual key events
-+ and those seen by the widget can swith to the simplified keyboard
-+ model.
-+
-+ \retval 0 if the widget uses the normal keyboard model
-+ \see set_changed(), clear_changed()
-+ */
-+ unsigned int simple_keyboard() const {return flags_&SIMPLE_KEYBOARD;}
-+
-+ /** Marks a widget to use the simple keyboard model.
-+ \see changed(), clear_changed()
-+ */
-+ void set_simple_keyboard() {flags_ |= SIMPLE_KEYBOARD;}
-+
-+ /** Marks a widget to use the normal keyboard model.
-+ \see changed(), set_changed()
-+ */
-+ void set_normal_keyboard() {flags_ &= ~SIMPLE_KEYBOARD;}
-+
- /** Gives the widget the keyboard focus.
- Tries to make this widget be the Fl::focus() widget, by first sending
- it an FL_FOCUS event, and if it returns non-zero, setting
-diff -ur fltk-1.3.0r9619.org/src/Fl.cxx fltk-1.3.0r9619/src/Fl.cxx
---- fltk-1.3.0r9619.org/src/Fl.cxx 2012-03-23 17:47:53.000000000 +0100
-+++ fltk-1.3.0r9619/src/Fl.cxx 2012-06-18 13:46:07.303320877 +0200
-@@ -70,6 +70,8 @@
- extern double fl_mac_flush_and_wait(double time_to_wait, char in_idle);
- #endif // WIN32
-
-+extern void fl_update_focus(void);
-+
- //
- // Globals...
- //
-@@ -876,6 +878,8 @@
- fl_oldfocus = p;
- }
- e_number = old_event;
-+ // let the platform code do what it needs
-+ fl_update_focus();
- }
- }
-
-diff -ur fltk-1.3.0r9619.org/src/Fl_grab.cxx fltk-1.3.0r9619/src/Fl_grab.cxx
---- fltk-1.3.0r9619.org/src/Fl_grab.cxx 2012-03-23 17:47:53.000000000 +0100
-+++ fltk-1.3.0r9619/src/Fl_grab.cxx 2012-06-18 13:46:07.303320877 +0200
-@@ -29,6 +29,7 @@
- // override_redirect, it does similar things on WIN32.
-
- extern void fl_fix_focus(); // in Fl.cxx
-+void fl_update_focus(void);
-
- #ifdef WIN32
- // We have to keep track of whether we have captured the mouse, since
-@@ -80,6 +81,7 @@
- #endif
- }
- grab_ = win;
-+ fl_update_focus();
- } else {
- if (grab_) {
- #ifdef WIN32
-@@ -98,6 +100,7 @@
- XFlush(fl_display);
- #endif
- grab_ = 0;
-+ fl_update_focus();
- fl_fix_focus();
- }
- }
-diff -ur fltk-1.3.0r9619.org/src/Fl_x.cxx fltk-1.3.0r9619/src/Fl_x.cxx
---- fltk-1.3.0r9619.org/src/Fl_x.cxx 2012-06-18 13:46:07.205316173 +0200
-+++ fltk-1.3.0r9619/src/Fl_x.cxx 2012-06-18 13:46:18.216844629 +0200
-@@ -298,6 +298,7 @@
- Colormap fl_colormap;
- XIM fl_xim_im = 0;
- XIC fl_xim_ic = 0;
-+Window fl_xim_win = 0;
- char fl_is_over_the_spot = 0;
- static XRectangle status_area;
-
-@@ -583,6 +584,65 @@
- if(xim_styles) XFree(xim_styles);
- }
-
-+void fl_xim_deactivate(void);
-+
-+void fl_xim_activate(Window xid)
-+{
-+ if (!fl_xim_im)
-+ return;
-+
-+ // If the focused window has changed, then use the brute force method
-+ // of completely recreating the input context.
-+ if (fl_xim_win != xid) {
-+ fl_xim_deactivate();
-+
-+ fl_new_ic();
-+ fl_xim_win = xid;
-+
-+ XSetICValues(fl_xim_ic,
-+ XNFocusWindow, fl_xim_win,
-+ XNClientWindow, fl_xim_win,
-+ NULL);
-+ }
-+
-+ fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
-+}
-+
-+void fl_xim_deactivate(void)
-+{
-+ if (!fl_xim_ic)
-+ return;
-+
-+ XDestroyIC(fl_xim_ic);
-+ fl_xim_ic = NULL;
-+
-+ fl_xim_win = 0;
-+}
-+
-+extern Fl_Window *fl_xfocus;
-+
-+void fl_update_focus(void)
-+{
-+ Fl_Widget *focus;
-+
-+ focus = Fl::grab();
-+ if (!focus)
-+ focus = Fl::focus();
-+ if (!focus)
-+ return;
-+
-+ if (focus->simple_keyboard()) {
-+ fl_xim_deactivate();
-+ } else {
-+ // fl_xfocus should always be set if something has focus, but let's
-+ // play it safe
-+ if (!fl_xfocus || !fl_xid(fl_xfocus))
-+ return;
-+
-+ fl_xim_activate(fl_xid(fl_xfocus));
-+ }
-+}
-+
- void fl_open_display() {
- if (fl_display) return;
-
-@@ -917,10 +977,9 @@
- XEvent xevent = thisevent;
- fl_xevent = &thisevent;
- Window xid = xevent.xany.window;
-- static Window xim_win = 0;
-
- if (fl_xim_ic && xevent.type == DestroyNotify &&
-- xid != xim_win && !fl_find(xid))
-+ xid != fl_xim_win && !fl_find(xid))
- {
- XIM xim_im;
- xim_im = XOpenIM(fl_display, NULL, NULL, NULL);
-@@ -935,48 +994,10 @@
- return 0;
- }
-
-- if (fl_xim_ic && (xevent.type == FocusIn))
-- {
--#define POOR_XIM
--#ifdef POOR_XIM
-- if (xim_win != xid)
-- {
-- xim_win = xid;
-- XDestroyIC(fl_xim_ic);
-- fl_xim_ic = NULL;
-- fl_new_ic();
-- XSetICValues(fl_xim_ic,
-- XNFocusWindow, xevent.xclient.window,
-- XNClientWindow, xid,
-- NULL);
-- }
-- fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
--#else
-- if (Fl::first_window() && Fl::first_window()->modal()) {
-- Window x = fl_xid(Fl::first_window());
-- if (x != xim_win) {
-- xim_win = x;
-- XSetICValues(fl_xim_ic,
-- XNFocusWindow, xim_win,
-- XNClientWindow, xim_win,
-- NULL);
-- fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
-- }
-- } else if (xim_win != xid && xid) {
-- xim_win = xid;
-- XSetICValues(fl_xim_ic,
-- XNFocusWindow, xevent.xclient.window,
-- XNClientWindow, xid,
-- //XNFocusWindow, xim_win,
-- //XNClientWindow, xim_win,
-- NULL);
-- fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
-- }
--#endif
-+ if (fl_xim_ic) {
-+ if (XFilterEvent((XEvent *)&xevent, 0))
-+ return 1;
- }
--
-- if ( XFilterEvent((XEvent *)&xevent, 0) )
-- return(1);
-
- #if USE_XRANDR
- if( XRRUpdateConfiguration_f && xevent.type == randrEventBase + RRScreenChangeNotify) {
-@@ -1326,15 +1347,15 @@
- //static XComposeStatus compose;
- len = XLookupString((XKeyEvent*)&(xevent.xkey),
- buffer, buffer_len, &keysym, 0/*&compose*/);
-- if (keysym && keysym < 0x400) { // a character in latin-1,2,3,4 sets
-- // force it to type a character (not sure if this ever is needed):
-- // if (!len) {buffer[0] = char(keysym); len = 1;}
-- len = fl_utf8encode(XKeysymToUcs(keysym), buffer);
-- if (len < 1) len = 1;
-- // ignore all effects of shift on the keysyms, which makes it a lot
-- // easier to program shortcuts and is Windoze-compatible:
-- keysym = XKeycodeToKeysym(fl_display, keycode, 0);
-- }
-+ // XLookupString() is only defined to return Latin-1 (although it
-+ // often gives you more). To be safe, use our own lookups based on
-+ // keysym.
-+ len = fl_utf8encode(XKeysymToUcs(keysym), buffer);
-+ if (len < 1)
-+ len = 1;
-+ // ignore all effects of shift on the keysyms, which makes it a lot
-+ // easier to program shortcuts and is Windoze-compatable:
-+ keysym = XKeycodeToKeysym(fl_display, keycode, 0);
- }
- // MRS: Can't use Fl::event_state(FL_CTRL) since the state is not
- // set until set_event_xy() is called later...
-diff -ur fltk-1.3.0r9619.org/src/xutf8/imKStoUCS.c fltk-1.3.0r9619/src/xutf8/imKStoUCS.c
---- fltk-1.3.0r9619.org/src/xutf8/imKStoUCS.c 2009-03-13 23:43:43.000000000 +0100
-+++ fltk-1.3.0r9619/src/xutf8/imKStoUCS.c 2012-06-18 13:46:07.304320930 +0200
-@@ -266,6 +266,12 @@
- 0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac /* 0x20a8-0x20af */
- };
-
-+static unsigned short const keysym_to_unicode_fe50_fe60[] = {
-+ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0306, 0x0307, 0x0308, /* 0xfe50-0xfe57 */
-+ 0x030a, 0x030b, 0x030c, 0x0327, 0x0328, 0x1da5, 0x3099, 0x309a, /* 0xfe58-0xfe5f */
-+ 0x0323 /* 0xfe60-0xfe67 */
-+};
-+
- unsigned int
- KeySymToUcs4(KeySym keysym)
- {
-@@ -315,6 +321,8 @@
- return keysym_to_unicode_1e9f_1eff[keysym - 0x1e9f];
- else if (keysym > 0x209f && keysym < 0x20ad)
- return keysym_to_unicode_20a0_20ac[keysym - 0x20a0];
-+ else if (keysym > 0xfe4f && keysym < 0xfe61)
-+ return keysym_to_unicode_fe50_fe60[keysym - 0xfe50];
- else
- return 0;
- }
diff --git a/contrib/fltk/04-str2636-fltk-1.3.x-clipboard.patch b/contrib/fltk/01-str2636-fltk-1.3.x-clipboard.patch
index 3f12bc53..3f12bc53 100644
--- a/contrib/fltk/04-str2636-fltk-1.3.x-clipboard.patch
+++ b/contrib/fltk/01-str2636-fltk-1.3.x-clipboard.patch
diff --git a/contrib/fltk/02-str2599-fltk-1.3.x-keyboard-win32.patch b/contrib/fltk/02-str2599-fltk-1.3.x-keyboard-win32.patch
deleted file mode 100644
index c29d3b97..00000000
--- a/contrib/fltk/02-str2599-fltk-1.3.x-keyboard-win32.patch
+++ /dev/null
@@ -1,256 +0,0 @@
-diff -ur fltk-1.3.0r9293.org/src/Fl_win32.cxx fltk-1.3.0r9293/src/Fl_win32.cxx
---- fltk-1.3.0r9293.org/src/Fl_win32.cxx 2012-06-18 09:07:56.522314557 +0200
-+++ fltk-1.3.0r9293/src/Fl_win32.cxx 2012-06-18 09:08:07.392836285 +0200
-@@ -87,6 +87,8 @@
- static Fl_Display_Device fl_gdi_display(&fl_gdi_driver);
- Fl_Display_Device *Fl_Display_Device::_display = &fl_gdi_display; // the platform display
-
-+bool use_simple_keyboard = false;
-+
- // dynamic wsock dll handling api:
- #if defined(__CYGWIN__) && !defined(SOCKET)
- # define SOCKET int
-@@ -120,6 +122,8 @@
- * size and link dependencies.
- */
- static HMODULE s_imm_module = 0;
-+typedef BOOL (WINAPI* flTypeImmAssociateContextEx)(HWND, HIMC, DWORD);
-+static flTypeImmAssociateContextEx flImmAssociateContextEx = 0;
- typedef HIMC (WINAPI* flTypeImmGetContext)(HWND);
- static flTypeImmGetContext flImmGetContext = 0;
- typedef BOOL (WINAPI* flTypeImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
-@@ -135,6 +139,7 @@
- if (!s_imm_module)
- Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n"
- "Please check your input method manager library accessibility.");
-+ flImmAssociateContextEx = (flTypeImmAssociateContextEx)GetProcAddress(s_imm_module, "ImmAssociateContextEx");
- flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext");
- flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow");
- flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext");
-@@ -413,7 +418,12 @@
- }
- }
-
-- TranslateMessage(&fl_msg);
-+ // Don't bother with key to character translation as we do
-+ // it manually for simpley keyboard widgets. In fact, calling
-+ // TranslateMessage() just makes it more difficult as it sets
-+ // a bunch of internal state.
-+ if (!use_simple_keyboard)
-+ TranslateMessage(&fl_msg);
- DispatchMessageW(&fl_msg);
- have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE);
- }
-@@ -638,6 +648,49 @@
- }
- }
-
-+void fl_update_focus(void)
-+{
-+ Fl_Widget *focus;
-+ Fl_Window *win;
-+
-+ get_imm_module();
-+
-+ focus = Fl::grab();
-+ if (!focus)
-+ focus = Fl::focus();
-+ if (!focus)
-+ return;
-+
-+ // Grabs are special in that events are sent to the first
-+ // available window
-+ if (focus == Fl::grab())
-+ win = Fl::first_window();
-+ else {
-+ win = focus->as_window();
-+ if (!win)
-+ win = focus->window();
-+ }
-+
-+ if (!win) {
-+ Fl::warning("Cannot find window for widget receiving focus");
-+ return;
-+ }
-+
-+ // No Win32 window created yet
-+ if (!Fl_X::i(win) || !fl_xid(win))
-+ return;
-+
-+ if (focus->simple_keyboard()) {
-+ use_simple_keyboard = true;
-+ if (flImmGetContext(fl_xid(win)) != 0)
-+ flImmAssociateContextEx(fl_xid(win), 0, 0);
-+ } else {
-+ use_simple_keyboard = false;
-+ if (flImmGetContext(fl_xid(win)) == 0)
-+ flImmAssociateContextEx(fl_xid(win), 0, IACE_DEFAULT);
-+ }
-+}
-+
- HWND fl_capture;
-
- static int mouse_event(Fl_Window *window, int what, int button,
-@@ -785,6 +838,27 @@
- return extended ? extendedlut[vk] : vklut[vk];
- }
-
-+static xchar msdead2fltk(xchar in)
-+{
-+ switch (in) {
-+ case 0x0060: // GRAVE ACCENT
-+ return 0x0300; // COMBINING GRAVE ACCENT
-+ case 0x00b4: // ACUTE ACCENT
-+ return 0x0301; // COMBINING ACUTE ACCENT
-+ case 0x005e: // CIRCUMFLEX ACCENT
-+ return 0x0302; // COMBINING CIRCUMFLEX ACCENT
-+ case 0x007e: // TILDE
-+ return 0x0303; // COMBINING TILDE
-+ case 0x00a8: // DIAERESIS
-+ return 0x0308; // COMBINING DIAERESIS
-+ // FIXME: Windows dead key behaviour isn't documented and I don't have
-+ // any more keyboards to test with...
-+ }
-+
-+ // hope that Windows gave us something proper to begin with
-+ return in;
-+}
-+
- #if USE_COLORMAP
- extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
- #endif
-@@ -846,6 +920,8 @@
- //fl_msg.pt = ???
- //fl_msg.lPrivate = ???
-
-+ MSG fl_orig_msg = fl_msg;
-+
- Fl_Window *window = fl_find(hWnd);
-
- if (window) switch (uMsg) {
-@@ -1025,23 +1101,82 @@
- if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK;
- Fl::e_state = state;
- static char buffer[1024];
-- if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
-
-+ if (use_simple_keyboard) {
-+ BYTE keystate[256];
-+ WCHAR wbuf[8];
-+ int ret;
-+
-+ // I'm not sure if we ever get WM_CHAR (& friends) without an initial
-+ // WM_KEYDOWN (& friends), but if we do then we should not send such
-+ // side band events to simple keyboard widgets.
-+ if ((fl_orig_msg.message != WM_KEYDOWN) &&
-+ (fl_orig_msg.message != WM_SYSKEYDOWN) &&
-+ (fl_orig_msg.message != WM_KEYUP) &&
-+ (fl_orig_msg.message != WM_SYSKEYUP))
-+ break;
-+
-+ GetKeyboardState(keystate);
-+
-+ // Pressing Ctrl wreaks havoc with the symbol lookup, so turn that off.
-+ // But AltGr shows up as Ctrl+Alt in Windows, so keep Ctrl if Alt is
-+ // active.
-+ if (!(keystate[VK_MENU] & 0x80))
-+ keystate[VK_CONTROL] = keystate[VK_LCONTROL] = keystate[VK_RCONTROL] = 0;
-+
-+ // We cannot inspect or modify Windows' internal state of the keyboard
-+ // so we have to try to infer information from ToUnicode() and wedge
-+ // things into a known state.
-+ for (int i = 0;i < 2;i++) {
-+ ret = ToUnicode(fl_orig_msg.wParam, 0, keystate, wbuf,
-+ sizeof(wbuf)/sizeof(wbuf[0]), 0);
-+
-+ // No symbol for this key (or unexpected length)
-+ if ((ret == 0) || (ret < -1)) {
-+ buffer[0] = 0;
-+ Fl::e_length = 0;
-+ break;
-+ }
-+
-+ // A dead key. Convert this to a Unicode combining character so
-+ // that the application can tell the difference between dead and
-+ // normal keys.
-+ if (ret == -1) {
-+ xchar u = (xchar) msdead2fltk(wbuf[0]);
-+ Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
-+ buffer[Fl::e_length] = 0;
-+ break;
-+ }
-+
-+ // If we have two characters (or more) from ToUnicode(), that's
-+ // an invalid sequence. One character chould mean a proper symbol,
-+ // or it could mean a composed one. In both cases we need to call
-+ // ToUnicode() again to get something sane.
-+ if (i == 0)
-+ continue;
-+
-+ // We should now have something sane. Give whatever we have to the
-+ // application.
-+ Fl::e_length = fl_utf8fromwc(buffer, 1024, wbuf, ret);
-+ buffer[Fl::e_length] = 0;
-+ }
-+ } else if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
- xchar u = (xchar) wParam;
- // Fl::e_length = fl_unicode2utf(&u, 1, buffer);
- Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
- buffer[Fl::e_length] = 0;
-+ } else {
-+ buffer[0] = 0;
-+ Fl::e_length = 0;
-+ }
-
--
-- } else if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) {
-- if (state & FL_NUM_LOCK) {
-- // Convert to regular keypress...
-- buffer[0] = Fl::e_keysym-FL_KP;
-- Fl::e_length = 1;
-- } else {
-- // Convert to special keypress...
-- buffer[0] = 0;
-- Fl::e_length = 0;
-+ // The keypad area is a bit odd in that we need to change the keysym
-+ // to properly indicate what the user meant, unlike other keys where
-+ // we normally change the text and keep keysym stable.
-+ if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) {
-+ // The initial mapping tables give us a keysym that corresponds to
-+ // numlock being on, so we only do something when it is off.
-+ if (!(state & FL_NUM_LOCK)) {
- switch (Fl::e_keysym) {
- case FL_KP + '0' :
- Fl::e_keysym = FL_Insert;
-@@ -1073,30 +1208,10 @@
- case FL_KP + '.' :
- Fl::e_keysym = FL_Delete;
- break;
-- case FL_KP + '/' :
-- case FL_KP + '*' :
-- case FL_KP + '-' :
-- case FL_KP + '+' :
-- buffer[0] = Fl::e_keysym-FL_KP;
-- Fl::e_length = 1;
-- break;
- }
- }
-- } else if ((lParam & (1<<31))==0) {
--#ifdef FLTK_PREVIEW_DEAD_KEYS
-- if ((lParam & (1<<24))==0) { // clear if dead key (always?)
-- xchar u = (xchar) wParam;
-- Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
-- buffer[Fl::e_length] = 0;
-- } else { // set if "extended key" (never printable?)
-- buffer[0] = 0;
-- Fl::e_length = 0;
-- }
--#else
-- buffer[0] = 0;
-- Fl::e_length = 0;
--#endif
- }
-+
- Fl::e_text = buffer;
- if (lParam & (1<<31)) { // key up events.
- if (Fl::handle(FL_KEYUP, window)) return 0;
diff --git a/contrib/fltk/05-str2636-fltk-1.3.x-clipboard-x11.patch b/contrib/fltk/02-str2636-fltk-1.3.x-clipboard-x11.patch
index 9e253a3f..9e253a3f 100644
--- a/contrib/fltk/05-str2636-fltk-1.3.x-clipboard-x11.patch
+++ b/contrib/fltk/02-str2636-fltk-1.3.x-clipboard-x11.patch
diff --git a/contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch b/contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch
deleted file mode 100644
index cf13aad7..00000000
--- a/contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch
+++ /dev/null
@@ -1,375 +0,0 @@
-diff -ur fltk-1.3.0r9619.org/configure.in fltk-1.3.0r9619/configure.in
---- fltk-1.3.0r9619.org/configure.in 2012-04-22 04:45:09.000000000 +0200
-+++ fltk-1.3.0r9619/configure.in 2012-06-18 13:47:33.290447462 +0200
-@@ -865,6 +865,8 @@
- Darwin*)
- # MacOS X uses Cocoa for graphics.
- LIBS="$LIBS -framework Cocoa"
-+ # And some Carbon for keyboard handling
-+ LIBS="$LIBS -framework Carbon"
-
- if test x$have_pthread = xyes; then
- AC_DEFINE(HAVE_PTHREAD)
-diff -ur fltk-1.3.0r9619.org/src/Fl_cocoa.mm fltk-1.3.0r9619/src/Fl_cocoa.mm
---- fltk-1.3.0r9619.org/src/Fl_cocoa.mm 2012-06-16 10:49:52.000000000 +0200
-+++ fltk-1.3.0r9619/src/Fl_cocoa.mm 2012-06-18 13:47:42.944910782 +0200
-@@ -53,6 +53,7 @@
- #include <math.h>
-
- #import <Cocoa/Cocoa.h>
-+#import <Carbon/Carbon.h>
-
- #ifndef NSINTEGER_DEFINED // appears with 10.5 in NSObjCRuntime.h
- #if defined(__LP64__) && __LP64__
-@@ -114,6 +115,8 @@
- extern Fl_Window* fl_xmousewin;
- #endif
-
-+bool use_simple_keyboard = false;
-+
- enum { FLTKTimerEvent = 1, FLTKDataReadyEvent };
-
-
-@@ -130,6 +133,39 @@
- {
- }
-
-+// Undocumented voodoo. Taken from Mozilla.
-+#define ENABLE_ROMAN_KYBDS_ONLY -23
-+
-+void fl_update_focus(void)
-+{
-+ Fl_Widget *focus;
-+
-+ focus = Fl::grab();
-+ if (!focus)
-+ focus = Fl::focus();
-+ if (!focus)
-+ return;
-+
-+ if (focus->simple_keyboard())
-+ use_simple_keyboard = true;
-+ else
-+ use_simple_keyboard = false;
-+
-+ // Force a "Roman" or "ASCII" keyboard, which both the Mozilla and
-+ // Safari people seem to think implies turning off advanced IME stuff
-+ // (see nsTSMManager::SyncKeyScript in Mozilla and enableSecureTextInput
-+ // in Safari/Webcore). Should be good enough for us then...
-+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
-+ CFArrayRef inputSources = TISCreateASCIICapableInputSourceList();
-+ TSMSetDocumentProperty(TSMGetActiveDocument(),
-+ kTSMDocumentEnabledInputSourcesPropertyTag,
-+ sizeof(CFArrayRef), &inputSources);
-+ CFRelease(inputSources);
-+#else
-+ KeyScript(use_simple_keyboard ? ENABLE_ROMAN_KYBDS_ONLY : smKeyEnableKybds);
-+#endif
-+}
-+
- /*
- * Mac keyboard lookup table
- */
-@@ -908,6 +944,25 @@
- }
- @end
-
-+static const char* cocoaDead2FLTK(const char *in)
-+{
-+ if (strcmp(in, "\140") == 0) // GRAVE ACCENT
-+ return "\314\200"; // COMBINING GRAVE ACCENT
-+ if (strcmp(in, "\302\264") == 0) // ACUTE ACCENT
-+ return "\314\201"; // COMBINING ACUTE ACCENT
-+ if (strcmp(in, "\136") == 0) // CIRCUMFLEX ACCENT
-+ return "\314\202"; // COMBINING CIRCUMFLEX ACCENT
-+ if (strcmp(in, "\176") == 0) // TILDE
-+ return "\314\203"; // COMBINING TILDE
-+ if (strcmp(in, "\302\250") == 0) // DIAERESIS
-+ return "\314\210"; // COMBINING DIAERESIS
-+ // FIXME: OS X dead key behaviour isn't documented and I don't have
-+ // any more keyboards to test with...
-+
-+ // hope that OS X gave us something proper to begin with
-+ return in;
-+}
-+
- /*
- Handle cocoa keyboard events
- Events during a character composition sequence:
-@@ -1648,6 +1703,7 @@
- - (void)rightMouseDragged:(NSEvent *)theEvent;
- - (void)otherMouseDragged:(NSEvent *)theEvent;
- - (void)scrollWheel:(NSEvent *)theEvent;
-++ (NSString *)keyTranslate:(UInt16)keyCode withModifierFlags:(UInt32)modifierFlags;
- - (BOOL)handleKeyDown:(NSEvent *)theEvent;
- - (void)keyDown:(NSEvent *)theEvent;
- - (void)keyUp:(NSEvent *)theEvent;
-@@ -1726,6 +1782,130 @@
- - (void)scrollWheel:(NSEvent *)theEvent {
- cocoaMouseWheelHandler(theEvent);
- }
-++ (NSString *)keyTranslate:(UInt16)keyCode withModifierFlags:(UInt32)modifierFlags {
-+ const UCKeyboardLayout *layout;
-+ OSStatus err;
-+
-+ layout = NULL;
-+
-+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
-+ TISInputSourceRef keyboard;
-+ CFDataRef uchr;
-+
-+ keyboard = TISCopyCurrentKeyboardInputSource();
-+ uchr = (CFDataRef)TISGetInputSourceProperty(keyboard,
-+ kTISPropertyUnicodeKeyLayoutData);
-+ if (uchr == NULL)
-+ return nil;
-+
-+ layout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
-+#else
-+ KeyboardLayoutRef old_layout;
-+ int kind;
-+
-+ err = KLGetCurrentKeyboardLayout(&old_layout);
-+ if (err != noErr)
-+ return nil;
-+
-+ err = KLGetKeyboardLayoutProperty(old_layout, kKLKind,
-+ (const void**)&kind);
-+ if (err != noErr)
-+ return nil;
-+
-+ // Old, crufty layout format?
-+ if (kind == kKLKCHRKind) {
-+ void *kchr_layout;
-+
-+ UInt32 chars, state;
-+ char buf[3];
-+
-+ unichar result[16];
-+ ByteCount in_len, out_len;
-+
-+ err = KLGetKeyboardLayoutProperty(old_layout, kKLKCHRData,
-+ (const void**)&kchr_layout);
-+ if (err != noErr)
-+ return nil;
-+
-+ state = 0;
-+
-+ keyCode &= 0x7f;
-+ modifierFlags &= 0xff00;
-+
-+ chars = KeyTranslate(kchr_layout, keyCode | modifierFlags, &state);
-+
-+ buf[0] = (chars >> 16) & 0xff;
-+ buf[1] = chars & 0xff;
-+ buf[2] = '\0';
-+
-+ if (buf[0] == '\0') {
-+ buf[0] = buf[1];
-+ buf[1] = '\0';
-+ }
-+
-+ // The data is now in some layout specific encoding. Need to convert
-+ // this to unicode.
-+
-+ ScriptCode script;
-+ TextEncoding encoding;
-+ TECObjectRef converter;
-+
-+ script = (ScriptCode)GetScriptManagerVariable(smKeyScript);
-+
-+ err = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
-+ kTextRegionDontCare, NULL,
-+ &encoding);
-+ if (err != noErr)
-+ return nil;
-+
-+ err = TECCreateConverter(&converter, encoding, kTextEncodingUnicodeV4_0);
-+ if (err != noErr)
-+ return nil;
-+
-+ in_len = strlen(buf);
-+ out_len = sizeof(result);
-+
-+ err = TECConvertText(converter, (ConstTextPtr)buf, in_len, &in_len,
-+ (TextPtr)result, out_len, &out_len);
-+
-+ TECDisposeConverter(converter);
-+
-+ if (err != noErr)
-+ return nil;
-+
-+ return [NSString stringWithCharacters:result
-+ length:(out_len / sizeof(unichar))];
-+ }
-+
-+ if ((kind != kKLKCHRuchrKind) && (kind != kKLuchrKind))
-+ return nil;
-+
-+ err = KLGetKeyboardLayoutProperty(old_layout, kKLuchrData,
-+ (const void**)&layout);
-+ if (err != noErr)
-+ return nil;
-+#endif
-+
-+ if (layout == NULL)
-+ return nil;
-+
-+ UInt32 dead_state;
-+ UniCharCount max_len, actual_len;
-+ UniChar string[255];
-+
-+ dead_state = 0;
-+ max_len = sizeof(string)/sizeof(*string);
-+
-+ modifierFlags = (modifierFlags >> 8) & 0xff;
-+
-+ err = UCKeyTranslate(layout, keyCode, kUCKeyActionDown, modifierFlags,
-+ LMGetKbdType(), 0, &dead_state, max_len, &actual_len,
-+ string);
-+ if (err != noErr)
-+ return nil;
-+
-+ return [NSString stringWithCharacters:string length:actual_len];
-+}
- - (BOOL)handleKeyDown:(NSEvent *)theEvent {
- //NSLog(@"handleKeyDown");
- fl_lock_function();
-@@ -1752,14 +1932,47 @@
- break;
- }
- }
-- if (!no_text_key && !(Fl::e_state & FL_META) ) {
-- // Don't send cmd-<key> to interpretKeyEvents because it beeps.
-+ if (!no_text_key) {
-+ // The simple keyboard model will ignore insertText, so we need to grab
-+ // the symbol directly from the event. Note that we still use setMarkedText.
-+ if (use_simple_keyboard) {
-+ NSString *simple_chars;
-+ UInt32 modifiers;
-+
-+ // We want a "normal" symbol out of the event, which basically means
-+ // we only respect the shift and alt/altgr modifiers. Cocoa can help
-+ // us if we only wanted shift, but as we also want alt/altgr, we'll
-+ // have to do some lookup ourselves. This matches our behaviour on
-+ // other platforms.
-+
-+ modifiers = 0;
-+ if ([theEvent modifierFlags] & NSAlphaShiftKeyMask)
-+ modifiers |= alphaLock;
-+ if ([theEvent modifierFlags] & NSShiftKeyMask)
-+ modifiers |= shiftKey;
-+ if ([theEvent modifierFlags] & NSAlternateKeyMask)
-+ modifiers |= optionKey;
-+
-+ simple_chars = [FLView keyTranslate:[theEvent keyCode]
-+ withModifierFlags:modifiers];
-+ if (simple_chars == nil) {
-+ // Something went wrong. Fall back to what Cocoa gave us...
-+ simple_chars = [theEvent charactersIgnoringModifiers];
-+ }
-+
-+ [FLView prepareEtext:simple_chars];
-+ }
-+
- // Then we can let the OS have a stab at it and see if it thinks it
- // should result in some text
-- NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil];
-- in_key_event = true;
-- [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
-- in_key_event = false;
-+
-+ // Don't send cmd-<key> to interpretKeyEvents because it beeps.
-+ if (!(Fl::e_state & FL_META)) {
-+ NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil];
-+ in_key_event = true;
-+ [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
-+ in_key_event = false;
-+ }
- }
- //NSLog(@"to text=%@ l=%d", [NSString stringWithUTF8String:Fl::e_text], Fl::e_length);
- int handled = Fl::handle(FL_KEYDOWN, window);
-@@ -1937,21 +2150,30 @@
- //NSLog(@"insertText: received=%@",received);
-
- if (!in_key_event) fl_lock_function();
-+
-+ // Simple keyboard widgets do not want these side channel inputs.
-+ if (use_simple_keyboard)
-+ goto end;
-+
- [FLView prepareEtext:received];
-+
- // We can get called outside of key events (e.g. from the character
-- // palette). Transform such actions to FL_PASTE events.
-+ // palette). We need to fake our own key event at that point.
- if (!in_key_event) {
- Fl_Window *target = [(FLWindow*)[self window] getFl_Window];
-- Fl::handle(FL_PASTE, target);
-+ Fl::e_keysym = Fl::e_original_keysym = 0;
-+ Fl::handle(FL_KEYDOWN, target);
- // for some reason, the window does not redraw until the next mouse move or button push
- // sending a 'redraw()' or 'awake()' does not solve the issue!
- Fl::flush();
- }
-+
-+end:
- if (!in_key_event) fl_unlock_function();
- }
-
- - (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection {
-- NSString *received;
-+ NSString *received, *current, *aggregate;
- if (newSelection.location == 0) {
- [self unmarkText];
- return;
-@@ -1962,11 +2184,47 @@
- received = (NSString*)aString;
- }
- //NSLog(@"setMarkedText: %@ %d %d",received,newSelection.location,newSelection.length);
-+
-+ fl_lock_function();
-+
-+ // Simple keyboard widgets generally do not want these side channel
-+ // inputs, but we have no other way of getting dead keys so we make
-+ // an exception in that case.
-+ if (use_simple_keyboard) {
-+ if (in_key_event && (Fl::e_length == 0)) {
-+ [FLView prepareEtext:received];
-+
-+ Fl::e_text = (char*)cocoaDead2FLTK(Fl::e_text);
-+ Fl::e_length = strlen(Fl::e_text);
-+ }
-+ goto end;
-+ }
-+
- // This code creates the OS X behaviour of seeing dead keys as things
- // are being composed.
-+ //
-+ // Note: The concatenation thing is because of how OS X deals with
-+ // invalid sequences. At that point it will spit out one call
-+ // to insertText with the now aborted sequence, and one new
-+ // call to setMarkedText with the new sequence. Since we want
-+ // both to be visible, we need to concatenate.
- next_compose_length = newSelection.location;
-- [FLView prepareEtext:received];
-- //NSLog(@"Fl::e_text=%@ Fl::e_length=%d next_compose_length=%d", received, Fl::e_length, next_compose_length);
-+ current = [NSString stringWithUTF8String:Fl::e_text];
-+ aggregate = [current stringByAppendingString:received];
-+
-+ [FLView prepareEtext:aggregate];
-+ //NSLog(@"Fl::e_text=%@ Fl::e_length=%d next_compose_length=%d", aggregate, Fl::e_length, next_compose_length);
-+
-+ // We can get called outside of key events (e.g. from the character
-+ // palette). We need to fake our own key event at that point.
-+ if (!in_key_event) {
-+ Fl_Window *target = [(FLWindow*)[self window] getFl_Window];
-+ Fl::e_keysym = Fl::e_original_keysym = 0;
-+ Fl::handle(FL_KEYDOWN, target);
-+ }
-+
-+end:
-+ fl_unlock_function();
- }
-
- - (void)unmarkText {
diff --git a/contrib/fltk/06-str2636-fltk-1.3.x-clipboard-win32-fix.patch b/contrib/fltk/03-str2636-fltk-1.3.x-clipboard-win32-fix.patch
index b41af794..b41af794 100644
--- a/contrib/fltk/06-str2636-fltk-1.3.x-clipboard-win32-fix.patch
+++ b/contrib/fltk/03-str2636-fltk-1.3.x-clipboard-win32-fix.patch
diff --git a/contrib/fltk/07-str2636-fltk-1.3.x-clipboard-win32.patch b/contrib/fltk/04-str2636-fltk-1.3.x-clipboard-win32.patch
index ac94779c..ac94779c 100644
--- a/contrib/fltk/07-str2636-fltk-1.3.x-clipboard-win32.patch
+++ b/contrib/fltk/04-str2636-fltk-1.3.x-clipboard-win32.patch
diff --git a/contrib/fltk/08-str2636-fltk-1.3.x-clipboard-osx.patch b/contrib/fltk/05-str2636-fltk-1.3.x-clipboard-osx.patch
index 22e69396..22e69396 100644
--- a/contrib/fltk/08-str2636-fltk-1.3.x-clipboard-osx.patch
+++ b/contrib/fltk/05-str2636-fltk-1.3.x-clipboard-osx.patch
diff --git a/contrib/fltk/09-str2659-pixmap.patch b/contrib/fltk/06-str2659-pixmap.patch
index 30315138..30315138 100644
--- a/contrib/fltk/09-str2659-pixmap.patch
+++ b/contrib/fltk/06-str2659-pixmap.patch
diff --git a/contrib/fltk/10-str2660-fltk-1.3.x-cursor.patch b/contrib/fltk/07-str2660-fltk-1.3.x-cursor.patch
index 8e990505..8e990505 100644
--- a/contrib/fltk/10-str2660-fltk-1.3.x-cursor.patch
+++ b/contrib/fltk/07-str2660-fltk-1.3.x-cursor.patch
diff --git a/contrib/fltk/11-str2802-fltk-1.3.0-modal.patch b/contrib/fltk/08-str2802-fltk-1.3.0-modal.patch
index 7b1b7913..7b1b7913 100644
--- a/contrib/fltk/11-str2802-fltk-1.3.0-modal.patch
+++ b/contrib/fltk/08-str2802-fltk-1.3.0-modal.patch
diff --git a/contrib/fltk/12-str2816-fltk-1.3.0-icons.patch b/contrib/fltk/09-str2816-fltk-1.3.0-icons.patch
index 20b30b8b..20b30b8b 100644
--- a/contrib/fltk/12-str2816-fltk-1.3.0-icons.patch
+++ b/contrib/fltk/09-str2816-fltk-1.3.0-icons.patch
diff --git a/contrib/fltk/13-str2860-fltk-1.3.x-screen_num.patch b/contrib/fltk/10-str2860-fltk-1.3.x-screen_num.patch
index c157af61..c157af61 100644
--- a/contrib/fltk/13-str2860-fltk-1.3.x-screen_num.patch
+++ b/contrib/fltk/10-str2860-fltk-1.3.x-screen_num.patch
diff --git a/contrib/fltk/14-str2860-fltk-1.3.x-multihead.patch b/contrib/fltk/11-str2860-fltk-1.3.x-multihead.patch
index e4a010aa..e4a010aa 100644
--- a/contrib/fltk/14-str2860-fltk-1.3.x-multihead.patch
+++ b/contrib/fltk/11-str2860-fltk-1.3.x-multihead.patch
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index 7d551682..2209fe58 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -86,16 +86,14 @@ enum { ID_EXIT, ID_FULLSCREEN, ID_RESIZE,
ID_CTRL, ID_ALT, ID_MENUKEY, ID_CTRLALTDEL,
ID_REFRESH, ID_OPTIONS, ID_INFO, ID_ABOUT, ID_DISMISS };
+// Fake key presses use this value and above
+static const int fakeKeyBase = 0x200;
+
Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_)
: Fl_Widget(0, 0, w, h), cc(cc_), frameBuffer(NULL),
lastPointerPos(0, 0), lastButtonMask(0),
cursor(NULL), menuCtrlKey(false), menuAltKey(false)
{
-// FLTK STR #2599 must be fixed for proper dead keys support
-#ifdef HAVE_FLTK_DEAD_KEYS
- set_simple_keyboard();
-#endif
-
// FLTK STR #2636 gives us the ability to monitor clipboard changes
#ifdef HAVE_FLTK_CLIPBOARD
Fl::add_clipboard_notify(handleClipboardChange, this);
@@ -399,26 +397,15 @@ int Viewport::handle(int event)
// Release all keys that were pressed as that generally makes most
// sense (e.g. Alt+Tab where we only see the Alt press)
while (!downKeySym.empty())
- handleKeyEvent(downKeySym.begin()->first, downKeySym.begin()->first,
- "", false);
+ handleKeyRelease(downKeySym.begin()->first);
return 1;
case FL_KEYDOWN:
- if (menuKeyCode && (Fl::event_key() == menuKeyCode)) {
- popupContextMenu();
- return 1;
- }
-
- handleKeyEvent(Fl::event_key(), Fl::event_original_key(),
- Fl::event_text(), true);
+ handleFLTKKeyPress();
return 1;
case FL_KEYUP:
- if (menuKeyCode && (Fl::event_key() == menuKeyCode))
- return 1;
-
- handleKeyEvent(Fl::event_key(), Fl::event_original_key(),
- Fl::event_text(), false);
+ handleKeyRelease(Fl::event_original_key());
return 1;
}
@@ -495,9 +482,156 @@ void Viewport::handlePointerTimeout(void *data)
}
-rdr::U32 Viewport::translateKeyEvent(int keyCode, int origKeyCode, const char *keyText)
+void Viewport::handleKeyPress(int keyCode, rdr::U32 keySym)
+{
+ static bool menuRecursion = false;
+
+ // Prevent recursion if the menu wants to send its own
+ // activation key.
+ if (menuKeySym && (keySym == menuKeySym) && !menuRecursion) {
+ menuRecursion = true;
+ popupContextMenu();
+ menuRecursion = false;
+ return;
+ }
+
+ if (viewOnly)
+ return;
+
+#ifdef __APPLE__
+ // Alt on OS X behaves more like AltGr on other systems, and to get
+ // sane behaviour we should translate things in that manner for the
+ // remote VNC server. However that means we lose the ability to use
+ // Alt as a shortcut modifier. Do what RealVNC does and hijack the
+ // left command key as an Alt replacement.
+ switch (keySym) {
+ case XK_Super_L:
+ keySym = XK_Alt_L;
+ break;
+ case XK_Super_R:
+ keySym = XK_Super_L;
+ break;
+ case XK_Alt_L:
+ case XK_Alt_R:
+ keySym = XK_ISO_Level3_Shift;
+ break;
+ }
+#endif
+
+#ifdef WIN32
+ // Ugly hack alert!
+ //
+ // Windows doesn't have a proper AltGr, but handles it using fake
+ // Ctrl+Alt. Unfortunately X11 doesn't generally like the combination
+ // Ctrl+Alt+AltGr, which we usually end up with when Xvnc tries to
+ // get everything in the correct state. Cheat and temporarily release
+ // Ctrl and Alt when we send some other symbol.
+ bool ctrlPressed, altPressed;
+ DownMap::iterator iter;
+
+ ctrlPressed = false;
+ altPressed = false;
+ for (iter = downKeySym.begin();iter != downKeySym.end();++iter) {
+ if (iter->second == XK_Control_L)
+ ctrlPressed = true;
+ else if (iter->second == XK_Alt_R)
+ altPressed = true;
+ }
+
+ if (ctrlPressed && altPressed) {
+ vlog.debug("Faking release of AltGr (Ctrl_L+Alt_R)");
+ try {
+ cc->writer()->keyEvent(XK_Control_L, false);
+ cc->writer()->keyEvent(XK_Alt_R, false);
+ } catch (rdr::Exception& e) {
+ vlog.error("%s", e.str());
+ exit_vncviewer(e.str());
+ }
+ }
+#endif
+
+ // 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.
+ downKeySym[keyCode] = keySym;
+
+#if defined(WIN32) || defined(__APPLE__)
+ vlog.debug("Key pressed: 0x%04x => 0x%04x", keyCode, keySym);
+#else
+ vlog.debug("Key pressed: 0x%04x => XK_%s (0x%04x)",
+ keyCode, XKeysymToString(keySym), keySym);
+#endif
+
+ try {
+ cc->writer()->keyEvent(keySym, true);
+ } catch (rdr::Exception& e) {
+ vlog.error("%s", e.str());
+ exit_vncviewer(e.str());
+ }
+
+#ifdef WIN32
+ // Ugly hack continued...
+ if (ctrlPressed && altPressed) {
+ vlog.debug("Restoring AltGr state");
+ try {
+ cc->writer()->keyEvent(XK_Control_L, true);
+ cc->writer()->keyEvent(XK_Alt_R, true);
+ } catch (rdr::Exception& e) {
+ vlog.error("%s", e.str());
+ exit_vncviewer(e.str());
+ }
+ }
+#endif
+}
+
+
+void Viewport::handleKeyRelease(int keyCode)
+{
+ DownMap::iterator iter;
+
+ if (viewOnly)
+ return;
+
+ iter = downKeySym.find(keyCode);
+ if (iter == downKeySym.end()) {
+ // These occur somewhat frequently so let's not spam them unless
+ // logging is turned up.
+ vlog.debug("Unexpected release of key code %d", keyCode);
+ return;
+ }
+
+#if defined(WIN32) || defined(__APPLE__)
+ vlog.debug("Key released: 0x%04x => 0x%04x", keyCode, iter->second);
+#else
+ vlog.debug("Key released: 0x%04x => XK_%s (0x%04x)",
+ keyCode, XKeysymToString(iter->second), iter->second);
+#endif
+
+ try {
+ cc->writer()->keyEvent(iter->second, false);
+ } catch (rdr::Exception& e) {
+ vlog.error("%s", e.str());
+ exit_vncviewer(e.str());
+ }
+
+ downKeySym.erase(iter);
+}
+
+
+rdr::U32 Viewport::translateKeyEvent(void)
{
unsigned ucs;
+ int keyCode, origKeyCode;
+ const char *keyText;
+ int keyTextLen;
+
+ keyCode = Fl::event_key();
+ origKeyCode = Fl::event_original_key();
+ keyText = Fl::event_text();
+ keyTextLen = Fl::event_length();
+
+ vlog.debug("FLTK key %d (%d) '%s'[%d]", origKeyCode, keyCode, keyText, keyTextLen);
// First check for function keys
if ((keyCode > FL_F) && (keyCode <= FL_F_Last))
@@ -541,23 +675,6 @@ rdr::U32 Viewport::translateKeyEvent(int keyCode, int origKeyCode, const char *k
}
}
-#ifdef __APPLE__
- // Alt on OS X behaves more like AltGr on other systems, and to get
- // sane behaviour we should translate things in that manner for the
- // remote VNC server. However that means we lose the ability to use
- // Alt as a shortcut modifier. Do what RealVNC does and hijack the
- // left command key as an Alt replacement.
- switch (keyCode) {
- case FL_Meta_L:
- return XK_Alt_L;
- case FL_Meta_R:
- return XK_Super_L;
- case FL_Alt_L:
- case FL_Alt_R:
- return XK_ISO_Level3_Shift;
- }
-#endif
-
#if defined(WIN32) || defined(__APPLE__)
// X11 fairly consistently uses XK_KP_Separator for comma and
// XK_KP_Decimal for period. Windows and OS X are a different matter
@@ -722,113 +839,15 @@ rdr::U32 Viewport::translateKeyEvent(int keyCode, int origKeyCode, const char *k
}
-void Viewport::handleKeyEvent(int keyCode, int origKeyCode, const char *keyText, bool down)
+void Viewport::handleFLTKKeyPress(void)
{
rdr::U32 keySym;
- if (viewOnly)
- 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) {
- DownMap::iterator iter;
-
- iter = downKeySym.find(origKeyCode);
- if (iter == downKeySym.end()) {
- vlog.error(_("Unexpected release of FLTK key code %d (0x%04x)"),
- origKeyCode, origKeyCode);
- return;
- }
-
- vlog.debug("Key released: 0x%04x => 0x%04x", origKeyCode, iter->second);
-
- try {
- cc->writer()->keyEvent(iter->second, false);
- } catch (rdr::Exception& e) {
- vlog.error("%s", e.str());
- exit_vncviewer(e.str());
- }
-
- downKeySym.erase(iter);
-
- return;
- }
-
- keySym = translateKeyEvent(keyCode, origKeyCode, keyText);
+ keySym = translateKeyEvent();
if (keySym == NoSymbol)
return;
-#ifdef WIN32
- // Ugly hack alert!
- //
- // Windows doesn't have a proper AltGr, but handles it using fake
- // Ctrl+Alt. Unfortunately X11 doesn't generally like the combination
- // Ctrl+Alt+AltGr, which we usually end up with when Xvnc tries to
- // get everything in the correct state. Cheat and temporarily release
- // Ctrl and Alt whenever we get a key with a symbol.
- bool need_cheat = true;
-
- if (keyText[0] == '\0')
- need_cheat = false;
- else if ((downKeySym.find(FL_Control_L) == downKeySym.end()) &&
- (downKeySym.find(FL_Control_R) == downKeySym.end()))
- need_cheat = false;
- else if ((downKeySym.find(FL_Alt_L) == downKeySym.end()) &&
- (downKeySym.find(FL_Alt_R) == downKeySym.end()))
- need_cheat = false;
-
- if (need_cheat) {
- vlog.debug("Faking release of AltGr (Ctrl+Alt)");
- try {
- if (downKeySym.find(FL_Control_L) != downKeySym.end())
- cc->writer()->keyEvent(XK_Control_L, false);
- if (downKeySym.find(FL_Control_R) != downKeySym.end())
- cc->writer()->keyEvent(XK_Control_R, false);
- if (downKeySym.find(FL_Alt_L) != downKeySym.end())
- cc->writer()->keyEvent(XK_Alt_L, false);
- if (downKeySym.find(FL_Alt_R) != downKeySym.end())
- cc->writer()->keyEvent(XK_Alt_R, false);
- } catch (rdr::Exception& e) {
- vlog.error("%s", e.str());
- exit_vncviewer(e.str());
- }
- }
-#endif
-
- vlog.debug("Key pressed: 0x%04x (0x%04x) '%s' => 0x%04x",
- origKeyCode, keyCode, keyText, keySym);
-
- downKeySym[origKeyCode] = keySym;
-
- try {
- cc->writer()->keyEvent(keySym, down);
- } catch (rdr::Exception& e) {
- vlog.error("%s", e.str());
- exit_vncviewer(e.str());
- }
-
-#ifdef WIN32
- // Ugly hack continued...
- if (need_cheat) {
- vlog.debug("Restoring AltGr state");
- try {
- if (downKeySym.find(FL_Control_L) != downKeySym.end())
- cc->writer()->keyEvent(XK_Control_L, true);
- if (downKeySym.find(FL_Control_R) != downKeySym.end())
- cc->writer()->keyEvent(XK_Control_R, true);
- if (downKeySym.find(FL_Alt_L) != downKeySym.end())
- cc->writer()->keyEvent(XK_Alt_L, true);
- if (downKeySym.find(FL_Alt_R) != downKeySym.end())
- cc->writer()->keyEvent(XK_Alt_R, true);
- } catch (rdr::Exception& e) {
- vlog.error(e.str());
- exit_vncviewer(e.str());
- }
- }
-#endif
+ handleKeyPress(Fl::event_original_key(), keySym);
}
@@ -853,7 +872,7 @@ void Viewport::initContextMenu()
contextMenu->add(_("Alt"), 0, NULL, (void*)ID_ALT,
FL_MENU_TOGGLE | (menuAltKey?FL_MENU_VALUE:0));
- if (menuKeyCode) {
+ if (menuKeySym) {
char sendMenuKey[64];
snprintf(sendMenuKey, 64, _("Send %s"), (const char *)menuKey);
contextMenu->add(sendMenuKey, 0, NULL, (void*)ID_MENUKEY, 0);
@@ -922,25 +941,31 @@ void Viewport::popupContextMenu()
window()->size(w(), h());
break;
case ID_CTRL:
- handleKeyEvent(FL_Control_L, FL_Control_L, "", m->value());
+ if (m->value())
+ handleKeyPress(fakeKeyBase + 0, XK_Control_L);
+ else
+ handleKeyRelease(fakeKeyBase + 0);
menuCtrlKey = !menuCtrlKey;
break;
case ID_ALT:
- handleKeyEvent(FL_Alt_L, FL_Alt_L, "", m->value());
+ if (m->value())
+ handleKeyPress(fakeKeyBase + 1, XK_Alt_L);
+ else
+ handleKeyRelease(fakeKeyBase + 1);
menuAltKey = !menuAltKey;
break;
case ID_MENUKEY:
- handleKeyEvent(menuKeyCode, menuKeyCode, "", true);
- handleKeyEvent(menuKeyCode, menuKeyCode, "", false);
+ handleKeyPress(fakeKeyBase + 2, menuKeySym);
+ handleKeyRelease(fakeKeyBase + 2);
break;
case ID_CTRLALTDEL:
- handleKeyEvent(FL_Control_L, FL_Control_L, "", true);
- handleKeyEvent(FL_Alt_L, FL_Alt_L, "", true);
- handleKeyEvent(FL_Delete, FL_Delete, "", true);
+ handleKeyPress(fakeKeyBase + 3, XK_Control_L);
+ handleKeyPress(fakeKeyBase + 4, XK_Alt_L);
+ handleKeyPress(fakeKeyBase + 5, XK_Delete);
- handleKeyEvent(FL_Delete, FL_Delete, "", false);
- handleKeyEvent(FL_Alt_L, FL_Alt_L, "", false);
- handleKeyEvent(FL_Control_L, FL_Control_L, "", false);
+ handleKeyRelease(fakeKeyBase + 5);
+ handleKeyRelease(fakeKeyBase + 4);
+ handleKeyRelease(fakeKeyBase + 3);
break;
case ID_REFRESH:
cc->refreshFramebuffer();
@@ -966,7 +991,7 @@ void Viewport::popupContextMenu()
void Viewport::setMenuKey()
{
- menuKeyCode = getMenuKeyCode();
+ getMenuKey(&menuKeyCode, &menuKeySym);
}
diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h
index 0523cd14..d9eea353 100644
--- a/vncviewer/Viewport.h
+++ b/vncviewer/Viewport.h
@@ -70,8 +70,11 @@ private:
void handlePointerEvent(const rfb::Point& pos, int buttonMask);
static void handlePointerTimeout(void *data);
- rdr::U32 translateKeyEvent(int keyCode, int origKeyCode, const char *keyText);
- void handleKeyEvent(int keyCode, int origKeyCode, const char *keyText, bool down);
+ void handleKeyPress(int keyCode, rdr::U32 keySym);
+ void handleKeyRelease(int keyCode);
+
+ rdr::U32 translateKeyEvent(void);
+ void handleFLTKKeyPress(void);
void initContextMenu();
void popupContextMenu();
@@ -91,6 +94,7 @@ private:
typedef std::map<int, rdr::U32> DownMap;
DownMap downKeySym;
+ rdr::U32 menuKeySym;
int menuKeyCode;
Fl_Menu_Button *contextMenu;
diff --git a/vncviewer/menukey.cxx b/vncviewer/menukey.cxx
index 2e3a568a..9c52f5e7 100644
--- a/vncviewer/menukey.cxx
+++ b/vncviewer/menukey.cxx
@@ -20,31 +20,37 @@
#include <string.h>
#include <FL/Fl.H>
+// FLTK can pull in the X11 headers on some systems
+#ifndef XK_VoidSymbol
+#define XK_MISCELLANY
+#include <rfb/keysymdef.h>
+#endif
+
#include "menukey.h"
#include "parameters.h"
static const MenuKeySymbol menuSymbols[] = {
- {"F1", FL_F + 1},
- {"F2", FL_F + 2},
- {"F3", FL_F + 3},
- {"F4", FL_F + 4},
- {"F5", FL_F + 5},
- {"F6", FL_F + 6},
- {"F7", FL_F + 7},
- {"F8", FL_F + 8},
- {"F9", FL_F + 9},
- {"F10", FL_F + 10},
- {"F11", FL_F + 11},
- {"F12", FL_F + 12},
- {"Pause", FL_Pause},
- {"Print", FL_Print},
- {"Scroll_Lock", FL_Scroll_Lock},
- {"Escape", FL_Escape},
- {"Insert", FL_Insert},
- {"Delete", FL_Delete},
- {"Home", FL_Home},
- {"Page_Up", FL_Page_Up},
- {"Page_Down", FL_Page_Down},
+ {"F1", FL_F + 1, XK_F1},
+ {"F2", FL_F + 2, XK_F2},
+ {"F3", FL_F + 3, XK_F3},
+ {"F4", FL_F + 4, XK_F4},
+ {"F5", FL_F + 5, XK_F5},
+ {"F6", FL_F + 6, XK_F6},
+ {"F7", FL_F + 7, XK_F7},
+ {"F8", FL_F + 8, XK_F8},
+ {"F9", FL_F + 9, XK_F9},
+ {"F10", FL_F + 10, XK_F10},
+ {"F11", FL_F + 11, XK_F11},
+ {"F12", FL_F + 12, XK_F12},
+ {"Pause", FL_Pause, XK_Pause},
+ {"Print", FL_Print, XK_Print},
+ {"Scroll_Lock", FL_Scroll_Lock, XK_Scroll_Lock},
+ {"Escape", FL_Escape, XK_Escape},
+ {"Insert", FL_Insert, XK_Insert},
+ {"Delete", FL_Delete, XK_Delete},
+ {"Home", FL_Home, XK_Home},
+ {"Page_Up", FL_Page_Up, XK_Page_Up},
+ {"Page_Down", FL_Page_Down, XK_Page_Down},
};
int getMenuKeySymbolCount()
@@ -57,15 +63,19 @@ const MenuKeySymbol* getMenuKeySymbols()
return menuSymbols;
}
-int getMenuKeyCode()
+void getMenuKey(int *keycode, rdr::U32 *keysym)
{
- const char *menuKeyStr;
- int menuKeyCode = 0;
+ const char *menuKeyStr;
- menuKeyStr = menuKey;
- for(int i = 0; i < getMenuKeySymbolCount(); i++)
- if (!strcmp(menuSymbols[i].name, menuKeyStr))
- menuKeyCode = menuSymbols[i].keycode;
+ menuKeyStr = menuKey;
+ for(int i = 0; i < getMenuKeySymbolCount(); i++) {
+ if (!strcmp(menuSymbols[i].name, menuKeyStr)) {
+ *keycode = menuSymbols[i].keycode;
+ *keysym = menuSymbols[i].keysym;
+ return;
+ }
+ }
- return menuKeyCode;
+ *keycode = 0;
+ *keysym = 0;
}
diff --git a/vncviewer/menukey.h b/vncviewer/menukey.h
index ecb46ed6..fcc51353 100644
--- a/vncviewer/menukey.h
+++ b/vncviewer/menukey.h
@@ -18,12 +18,15 @@
#ifndef __KEYSYM_H__
#define __KEYSYM_H__
+#include <rdr/types.h>
+
typedef struct {
const char* name;
int keycode;
+ rdr::U32 keysym;
} MenuKeySymbol;
-int getMenuKeyCode();
+void getMenuKey(int *keycode, rdr::U32 *keysym);
int getMenuKeySymbolCount();
const MenuKeySymbol* getMenuKeySymbols();