Pierre Ossman | 2f11bd9 | 2014-08-22 14:43:33 +0200 | [diff] [blame^] | 1 | diff -ur fltk-1.3.0r9619.org/FL/Fl_Widget.H fltk-1.3.0r9619/FL/Fl_Widget.H |
| 2 | --- fltk-1.3.0r9619.org/FL/Fl_Widget.H 2012-04-23 22:12:06.000000000 +0200 |
| 3 | +++ fltk-1.3.0r9619/FL/Fl_Widget.H 2012-06-18 13:46:07.302320825 +0200 |
| 4 | @@ -171,6 +171,7 @@ |
| 5 | GROUP_RELATIVE = 1<<16, ///< position this widget relative to the parent group, not to the window |
| 6 | COPIED_TOOLTIP = 1<<17, ///< the widget tooltip is internally copied, its destruction is handled by the widget |
| 7 | FULLSCREEN = 1<<18, ///< a fullscreen window (Fl_Window) |
| 8 | + SIMPLE_KEYBOARD = 1<<19, ///< the widget wants simple, consistent keypresses and not advanced input (like character composition and CJK input) |
| 9 | // (space for more flags) |
| 10 | USERFLAG3 = 1<<29, ///< reserved for 3rd party extensions |
| 11 | USERFLAG2 = 1<<30, ///< reserved for 3rd party extensions |
| 12 | @@ -776,6 +777,35 @@ |
| 13 | */ |
| 14 | void clear_changed() {flags_ &= ~CHANGED;} |
| 15 | |
| 16 | + /** |
| 17 | + Returns if the widget sees a simplified keyboard model or not. |
| 18 | + |
| 19 | + Normally widgets get a full-featured keyboard model that is geared |
| 20 | + towards text input. This includes support for compose sequences and |
| 21 | + advanced input methods, commonly used for asian writing system. This |
| 22 | + system however has downsides in that extra graphic can be presented |
| 23 | + to the user and that a physical key press doesn't correspond directly |
| 24 | + to a FLTK event. |
| 25 | + |
| 26 | + Widgets that need a direct correspondence between actual key events |
| 27 | + and those seen by the widget can swith to the simplified keyboard |
| 28 | + model. |
| 29 | + |
| 30 | + \retval 0 if the widget uses the normal keyboard model |
| 31 | + \see set_changed(), clear_changed() |
| 32 | + */ |
| 33 | + unsigned int simple_keyboard() const {return flags_&SIMPLE_KEYBOARD;} |
| 34 | + |
| 35 | + /** Marks a widget to use the simple keyboard model. |
| 36 | + \see changed(), clear_changed() |
| 37 | + */ |
| 38 | + void set_simple_keyboard() {flags_ |= SIMPLE_KEYBOARD;} |
| 39 | + |
| 40 | + /** Marks a widget to use the normal keyboard model. |
| 41 | + \see changed(), set_changed() |
| 42 | + */ |
| 43 | + void set_normal_keyboard() {flags_ &= ~SIMPLE_KEYBOARD;} |
| 44 | + |
| 45 | /** Gives the widget the keyboard focus. |
| 46 | Tries to make this widget be the Fl::focus() widget, by first sending |
| 47 | it an FL_FOCUS event, and if it returns non-zero, setting |
| 48 | diff -ur fltk-1.3.0r9619.org/src/Fl.cxx fltk-1.3.0r9619/src/Fl.cxx |
| 49 | --- fltk-1.3.0r9619.org/src/Fl.cxx 2012-03-23 17:47:53.000000000 +0100 |
| 50 | +++ fltk-1.3.0r9619/src/Fl.cxx 2012-06-18 13:46:07.303320877 +0200 |
| 51 | @@ -70,6 +70,8 @@ |
| 52 | extern double fl_mac_flush_and_wait(double time_to_wait, char in_idle); |
| 53 | #endif // WIN32 |
| 54 | |
| 55 | +extern void fl_update_focus(void); |
| 56 | + |
| 57 | // |
| 58 | // Globals... |
| 59 | // |
| 60 | @@ -876,6 +878,8 @@ |
| 61 | fl_oldfocus = p; |
| 62 | } |
| 63 | e_number = old_event; |
| 64 | + // let the platform code do what it needs |
| 65 | + fl_update_focus(); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | diff -ur fltk-1.3.0r9619.org/src/Fl_grab.cxx fltk-1.3.0r9619/src/Fl_grab.cxx |
| 70 | --- fltk-1.3.0r9619.org/src/Fl_grab.cxx 2012-03-23 17:47:53.000000000 +0100 |
| 71 | +++ fltk-1.3.0r9619/src/Fl_grab.cxx 2012-06-18 13:46:07.303320877 +0200 |
| 72 | @@ -29,6 +29,7 @@ |
| 73 | // override_redirect, it does similar things on WIN32. |
| 74 | |
| 75 | extern void fl_fix_focus(); // in Fl.cxx |
| 76 | +void fl_update_focus(void); |
| 77 | |
| 78 | #ifdef WIN32 |
| 79 | // We have to keep track of whether we have captured the mouse, since |
| 80 | @@ -80,6 +81,7 @@ |
| 81 | #endif |
| 82 | } |
| 83 | grab_ = win; |
| 84 | + fl_update_focus(); |
| 85 | } else { |
| 86 | if (grab_) { |
| 87 | #ifdef WIN32 |
| 88 | @@ -98,6 +100,7 @@ |
| 89 | XFlush(fl_display); |
| 90 | #endif |
| 91 | grab_ = 0; |
| 92 | + fl_update_focus(); |
| 93 | fl_fix_focus(); |
| 94 | } |
| 95 | } |
| 96 | diff -ur fltk-1.3.0r9619.org/src/Fl_x.cxx fltk-1.3.0r9619/src/Fl_x.cxx |
| 97 | --- fltk-1.3.0r9619.org/src/Fl_x.cxx 2012-06-18 13:46:07.205316173 +0200 |
| 98 | +++ fltk-1.3.0r9619/src/Fl_x.cxx 2012-06-18 13:46:18.216844629 +0200 |
| 99 | @@ -298,6 +298,7 @@ |
| 100 | Colormap fl_colormap; |
| 101 | XIM fl_xim_im = 0; |
| 102 | XIC fl_xim_ic = 0; |
| 103 | +Window fl_xim_win = 0; |
| 104 | char fl_is_over_the_spot = 0; |
| 105 | static XRectangle status_area; |
| 106 | |
| 107 | @@ -583,6 +584,65 @@ |
| 108 | if(xim_styles) XFree(xim_styles); |
| 109 | } |
| 110 | |
| 111 | +void fl_xim_deactivate(void); |
| 112 | + |
| 113 | +void fl_xim_activate(Window xid) |
| 114 | +{ |
| 115 | + if (!fl_xim_im) |
| 116 | + return; |
| 117 | + |
| 118 | + // If the focused window has changed, then use the brute force method |
| 119 | + // of completely recreating the input context. |
| 120 | + if (fl_xim_win != xid) { |
| 121 | + fl_xim_deactivate(); |
| 122 | + |
| 123 | + fl_new_ic(); |
| 124 | + fl_xim_win = xid; |
| 125 | + |
| 126 | + XSetICValues(fl_xim_ic, |
| 127 | + XNFocusWindow, fl_xim_win, |
| 128 | + XNClientWindow, fl_xim_win, |
| 129 | + NULL); |
| 130 | + } |
| 131 | + |
| 132 | + fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height); |
| 133 | +} |
| 134 | + |
| 135 | +void fl_xim_deactivate(void) |
| 136 | +{ |
| 137 | + if (!fl_xim_ic) |
| 138 | + return; |
| 139 | + |
| 140 | + XDestroyIC(fl_xim_ic); |
| 141 | + fl_xim_ic = NULL; |
| 142 | + |
| 143 | + fl_xim_win = 0; |
| 144 | +} |
| 145 | + |
| 146 | +extern Fl_Window *fl_xfocus; |
| 147 | + |
| 148 | +void fl_update_focus(void) |
| 149 | +{ |
| 150 | + Fl_Widget *focus; |
| 151 | + |
| 152 | + focus = Fl::grab(); |
| 153 | + if (!focus) |
| 154 | + focus = Fl::focus(); |
| 155 | + if (!focus) |
| 156 | + return; |
| 157 | + |
| 158 | + if (focus->simple_keyboard()) { |
| 159 | + fl_xim_deactivate(); |
| 160 | + } else { |
| 161 | + // fl_xfocus should always be set if something has focus, but let's |
| 162 | + // play it safe |
| 163 | + if (!fl_xfocus || !fl_xid(fl_xfocus)) |
| 164 | + return; |
| 165 | + |
| 166 | + fl_xim_activate(fl_xid(fl_xfocus)); |
| 167 | + } |
| 168 | +} |
| 169 | + |
| 170 | void fl_open_display() { |
| 171 | if (fl_display) return; |
| 172 | |
| 173 | @@ -917,10 +977,9 @@ |
| 174 | XEvent xevent = thisevent; |
| 175 | fl_xevent = &thisevent; |
| 176 | Window xid = xevent.xany.window; |
| 177 | - static Window xim_win = 0; |
| 178 | |
| 179 | if (fl_xim_ic && xevent.type == DestroyNotify && |
| 180 | - xid != xim_win && !fl_find(xid)) |
| 181 | + xid != fl_xim_win && !fl_find(xid)) |
| 182 | { |
| 183 | XIM xim_im; |
| 184 | xim_im = XOpenIM(fl_display, NULL, NULL, NULL); |
| 185 | @@ -935,48 +994,10 @@ |
| 186 | return 0; |
| 187 | } |
| 188 | |
| 189 | - if (fl_xim_ic && (xevent.type == FocusIn)) |
| 190 | - { |
| 191 | -#define POOR_XIM |
| 192 | -#ifdef POOR_XIM |
| 193 | - if (xim_win != xid) |
| 194 | - { |
| 195 | - xim_win = xid; |
| 196 | - XDestroyIC(fl_xim_ic); |
| 197 | - fl_xim_ic = NULL; |
| 198 | - fl_new_ic(); |
| 199 | - XSetICValues(fl_xim_ic, |
| 200 | - XNFocusWindow, xevent.xclient.window, |
| 201 | - XNClientWindow, xid, |
| 202 | - NULL); |
| 203 | - } |
| 204 | - fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height); |
| 205 | -#else |
| 206 | - if (Fl::first_window() && Fl::first_window()->modal()) { |
| 207 | - Window x = fl_xid(Fl::first_window()); |
| 208 | - if (x != xim_win) { |
| 209 | - xim_win = x; |
| 210 | - XSetICValues(fl_xim_ic, |
| 211 | - XNFocusWindow, xim_win, |
| 212 | - XNClientWindow, xim_win, |
| 213 | - NULL); |
| 214 | - fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height); |
| 215 | - } |
| 216 | - } else if (xim_win != xid && xid) { |
| 217 | - xim_win = xid; |
| 218 | - XSetICValues(fl_xim_ic, |
| 219 | - XNFocusWindow, xevent.xclient.window, |
| 220 | - XNClientWindow, xid, |
| 221 | - //XNFocusWindow, xim_win, |
| 222 | - //XNClientWindow, xim_win, |
| 223 | - NULL); |
| 224 | - fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height); |
| 225 | - } |
| 226 | -#endif |
| 227 | + if (fl_xim_ic) { |
| 228 | + if (XFilterEvent((XEvent *)&xevent, 0)) |
| 229 | + return 1; |
| 230 | } |
| 231 | - |
| 232 | - if ( XFilterEvent((XEvent *)&xevent, 0) ) |
| 233 | - return(1); |
| 234 | |
| 235 | #if USE_XRANDR |
| 236 | if( XRRUpdateConfiguration_f && xevent.type == randrEventBase + RRScreenChangeNotify) { |
| 237 | @@ -1326,15 +1347,15 @@ |
| 238 | //static XComposeStatus compose; |
| 239 | len = XLookupString((XKeyEvent*)&(xevent.xkey), |
| 240 | buffer, buffer_len, &keysym, 0/*&compose*/); |
| 241 | - if (keysym && keysym < 0x400) { // a character in latin-1,2,3,4 sets |
| 242 | - // force it to type a character (not sure if this ever is needed): |
| 243 | - // if (!len) {buffer[0] = char(keysym); len = 1;} |
| 244 | - len = fl_utf8encode(XKeysymToUcs(keysym), buffer); |
| 245 | - if (len < 1) len = 1; |
| 246 | - // ignore all effects of shift on the keysyms, which makes it a lot |
| 247 | - // easier to program shortcuts and is Windoze-compatible: |
| 248 | - keysym = XKeycodeToKeysym(fl_display, keycode, 0); |
| 249 | - } |
| 250 | + // XLookupString() is only defined to return Latin-1 (although it |
| 251 | + // often gives you more). To be safe, use our own lookups based on |
| 252 | + // keysym. |
| 253 | + len = fl_utf8encode(XKeysymToUcs(keysym), buffer); |
| 254 | + if (len < 1) |
| 255 | + len = 1; |
| 256 | + // ignore all effects of shift on the keysyms, which makes it a lot |
| 257 | + // easier to program shortcuts and is Windoze-compatable: |
| 258 | + keysym = XKeycodeToKeysym(fl_display, keycode, 0); |
| 259 | } |
| 260 | // MRS: Can't use Fl::event_state(FL_CTRL) since the state is not |
| 261 | // set until set_event_xy() is called later... |
| 262 | diff -ur fltk-1.3.0r9619.org/src/xutf8/imKStoUCS.c fltk-1.3.0r9619/src/xutf8/imKStoUCS.c |
| 263 | --- fltk-1.3.0r9619.org/src/xutf8/imKStoUCS.c 2009-03-13 23:43:43.000000000 +0100 |
| 264 | +++ fltk-1.3.0r9619/src/xutf8/imKStoUCS.c 2012-06-18 13:46:07.304320930 +0200 |
| 265 | @@ -266,6 +266,12 @@ |
| 266 | 0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac /* 0x20a8-0x20af */ |
| 267 | }; |
| 268 | |
| 269 | +static unsigned short const keysym_to_unicode_fe50_fe60[] = { |
| 270 | + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0306, 0x0307, 0x0308, /* 0xfe50-0xfe57 */ |
| 271 | + 0x030a, 0x030b, 0x030c, 0x0327, 0x0328, 0x1da5, 0x3099, 0x309a, /* 0xfe58-0xfe5f */ |
| 272 | + 0x0323 /* 0xfe60-0xfe67 */ |
| 273 | +}; |
| 274 | + |
| 275 | unsigned int |
| 276 | KeySymToUcs4(KeySym keysym) |
| 277 | { |
| 278 | @@ -315,6 +321,8 @@ |
| 279 | return keysym_to_unicode_1e9f_1eff[keysym - 0x1e9f]; |
| 280 | else if (keysym > 0x209f && keysym < 0x20ad) |
| 281 | return keysym_to_unicode_20a0_20ac[keysym - 0x20a0]; |
| 282 | + else if (keysym > 0xfe4f && keysym < 0xfe61) |
| 283 | + return keysym_to_unicode_fe50_fe60[keysym - 0xfe50]; |
| 284 | else |
| 285 | return 0; |
| 286 | } |