Browse Source

Remove simple keyboard model

Remove the FLTK simple keyboard system and reorganise things in
preparation for a more direct approach.
tags/v1.3.90
Pierre Ossman 9 years ago
parent
commit
25188c448c

+ 0
- 3
CMakeLists.txt View File

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


+ 0
- 1
config.h.in View File

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

+ 0
- 286
contrib/fltk/01-str2599-fltk-1.3.x-keyboard-x11.patch View File

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

contrib/fltk/04-str2636-fltk-1.3.x-clipboard.patch → contrib/fltk/01-str2636-fltk-1.3.x-clipboard.patch View File


+ 0
- 256
contrib/fltk/02-str2599-fltk-1.3.x-keyboard-win32.patch View File

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

contrib/fltk/05-str2636-fltk-1.3.x-clipboard-x11.patch → contrib/fltk/02-str2636-fltk-1.3.x-clipboard-x11.patch View File


+ 0
- 375
contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch View File

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

contrib/fltk/06-str2636-fltk-1.3.x-clipboard-win32-fix.patch → contrib/fltk/03-str2636-fltk-1.3.x-clipboard-win32-fix.patch View File


contrib/fltk/07-str2636-fltk-1.3.x-clipboard-win32.patch → contrib/fltk/04-str2636-fltk-1.3.x-clipboard-win32.patch View File


contrib/fltk/08-str2636-fltk-1.3.x-clipboard-osx.patch → contrib/fltk/05-str2636-fltk-1.3.x-clipboard-osx.patch View File


contrib/fltk/09-str2659-pixmap.patch → contrib/fltk/06-str2659-pixmap.patch View File


contrib/fltk/10-str2660-fltk-1.3.x-cursor.patch → contrib/fltk/07-str2660-fltk-1.3.x-cursor.patch View File


contrib/fltk/11-str2802-fltk-1.3.0-modal.patch → contrib/fltk/08-str2802-fltk-1.3.0-modal.patch View File


contrib/fltk/12-str2816-fltk-1.3.0-icons.patch → contrib/fltk/09-str2816-fltk-1.3.0-icons.patch View File


contrib/fltk/13-str2860-fltk-1.3.x-screen_num.patch → contrib/fltk/10-str2860-fltk-1.3.x-screen_num.patch View File


contrib/fltk/14-str2860-fltk-1.3.x-multihead.patch → contrib/fltk/11-str2860-fltk-1.3.x-multihead.patch View File


+ 175
- 150
vncviewer/Viewport.cxx View File

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



+ 6
- 2
vncviewer/Viewport.h View File

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


+ 39
- 29
vncviewer/menukey.cxx View File

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

+ 4
- 1
vncviewer/menukey.h View File

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


Loading…
Cancel
Save