Mercurial > octave-nkf
changeset 19046:7f73293d8423
Revise FLTK keypressfcn and keyreleasefcn callbacks
* __init_fltk__.cc: Fix key events: Use Matlab compatible identifiers
for "Key" and "Character" fields.
author | Andreas Weber <andy.weber.aw@gmail.com> |
---|---|
date | Sat, 16 Aug 2014 19:08:52 +0200 |
parents | c3af040956df |
children | 60e54be64f37 |
files | libinterp/dldfcn/__init_fltk__.cc |
diffstat | 1 files changed, 161 insertions(+), 56 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/dldfcn/__init_fltk__.cc Fri Aug 15 16:26:37 2014 +0200 +++ b/libinterp/dldfcn/__init_fltk__.cc Sat Aug 16 19:08:52 2014 +0200 @@ -661,7 +661,7 @@ public: plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp, bool internal) : Fl_Window (xx, yy, ww, hh + menu_h + status_h + 2, "octave"), - window_label (), shift (0), fp (xfp), canvas (0), + window_label (), fp (xfp), canvas (0), autoscale (0), togglegrid (0), panzoom (0), rotate (0), help (0), status (0), resize_dummy (0), ax_obj (), pos_x (0), pos_y (0) { @@ -945,9 +945,6 @@ // life std::string window_label; - // Mod keys status - int shift; - // Figure properties. figure::properties& fp; @@ -1176,45 +1173,114 @@ return 0; } - int key2shift (int key) + octave_scalar_map format_key_event (int e_key, const char* e_text, int e_state) { - if (key == FL_Shift_L || key == FL_Shift_R) - return FL_SHIFT; + octave_scalar_map evt; - if (key == FL_Control_L || key == FL_Control_R) - return FL_CTRL; + evt.assign ("Character", octave_value (e_text)); + evt.assign ("Modifier", octave_value (modifier2cell (e_state))); + + std::string key_str; + std::ostringstream tmp_str; - if (key == FL_Alt_L || key == FL_Alt_R) - return FL_ALT; + if (e_key == FL_Escape) + key_str = "escape"; + else if (e_key == FL_Tab) + key_str = "tab"; + else if (e_key == FL_Caps_Lock) + key_str = "capslock"; + else if (e_key == FL_Shift_L || e_key == FL_Shift_R) + key_str = "shift"; + else if (e_key == FL_Control_L || e_key == FL_Control_R) + key_str = "control"; + else if (e_key == FL_Meta_L || e_key == FL_Meta_R) + key_str = "windows"; + else if (e_key == FL_Alt_L || e_key == FL_Alt_R) + key_str = "alt"; + else if (e_key == 32) + key_str = "space"; + else if (e_key == FL_Enter) + key_str = "return"; + else if (e_key == FL_BackSpace) + key_str = "backspace"; + else if (e_key == FL_Print) + key_str = "printscreen"; + else if (e_key == FL_Pause) + key_str = "pause"; + else if (e_key == FL_Home) + key_str = "home"; + else if (e_key == FL_End) + key_str = "end"; + else if (e_key == FL_Insert) + key_str = "insert"; + else if (e_key == FL_Page_Up) + key_str = "pageup"; + else if (e_key == FL_Delete) + key_str = "delete"; + else if (e_key == FL_Page_Down) + key_str = "pagedown"; + else if (e_key == FL_Left) + key_str = "leftarrow"; + else if (e_key == FL_Up) + key_str = "uparrow"; + else if (e_key == FL_Right) + key_str = "rightarrow"; + else if (e_key == FL_Down) + key_str = "downarrow"; + else if (e_key == FL_Num_Lock) + key_str = "numlock"; + else if (e_key == 0xffaf) + key_str = "divide"; + else if (e_key == 0xffaa) + key_str = "multiply"; + else if (e_key == 0xffad) + key_str = "subtract"; + else if (e_key == 0xffab) + key_str = "add"; + else if (e_key == 0xff8d) + key_str = "return"; + else if (e_key == 0xffac) + key_str = "separator"; + else if (e_key >= 0xffb0 && e_key <= 0xffb9) + { + tmp_str << "numpad" << (e_key - 0xffb0); + key_str = tmp_str.str (); + } + else if (e_key >= (FL_F + 1) && e_key <= (FL_F + 12)) + { + tmp_str << "f" << (e_key - FL_F); + key_str = tmp_str.str (); + } + else if (e_key == ',') + key_str = "comma"; + else if (e_key == '.') + key_str = "period"; + else if (e_key == '-') + key_str = "hyphen"; + else if (e_key == '^' || e_key == '+' || e_key == '#' + || e_key == '<' || e_key == 0xfe03 /*AltGr*/) + key_str = "0"; + else if (isalnum (e_key)) + key_str = std::tolower (e_key); + else if (isprint (e_text[0])) + key_str = "0"; - if (key == FL_Meta_L || key == FL_Meta_R) - return FL_META; - - return 0; + evt.assign ("Key", octave_value (key_str)); + return evt; } - int key2ascii (int key) - { - if (key < 256) return key; - if (key == FL_Tab) return '\t'; - if (key == FL_Enter) return 0x0a; - if (key == FL_BackSpace) return 0x08; - if (key == FL_Escape) return 0x1b; - - return 0; - } - - Cell modifier2cell () + Cell modifier2cell (int e_state) { string_vector mod; - if (shift & FL_SHIFT) + if (e_state & FL_SHIFT) mod.append (std::string ("shift")); - if (shift & FL_CTRL) + if (e_state & FL_CTRL) mod.append (std::string ("control")); - if (shift & FL_ALT || shift & FL_META) + if (e_state & FL_ALT) mod.append (std::string ("alt")); - + if (e_state & FL_COMMAND) + mod.append (std::string ("command")); return Cell (mod); } @@ -1245,23 +1311,46 @@ if (!fp.is_beingdeleted ()) { //std::cout << "plot_window::handle event = " << fl_eventnames[event] << std::endl; + + // FLTK resends keyboard events with flipped case if all + // widgets rejects the event. + // See Event Propagation http://www.fltk.org/doc-1.3/events.html + static bool key_resent_detected = false; + switch (event) { + case FL_SHORTCUT: + { + // check if it a resent event with switched case + static int last_event_key = 0; + static char last_event_text = 0; + + int e_key = Fl::event_key (); + char e_text = Fl::event_text ()[0]; + key_resent_detected = (e_key == last_event_key + && std::tolower (last_event_text) == std::tolower (e_text) + && ((islower (last_event_text) && isupper (e_text)) + || (isupper (last_event_text) && islower (e_text)))); + + last_event_key = e_key; + last_event_text = e_text; + } + break; + case FL_KEYDOWN: { - int key = Fl::event_key (); + int e_key = Fl::event_key (); + const char *e_text = Fl::event_text (); + int e_state = Fl::event_state (); + octave_scalar_map evt = + format_key_event (e_key, e_text, e_state); - shift |= key2shift (key); - int key_a = key2ascii (key); - if (key_a && fp.get_keypressfcn ().is_defined ()) - { - octave_scalar_map evt; - evt.assign ("Character", octave_value (key_a)); - evt.assign ("Key", octave_value (std::tolower (key_a))); - evt.assign ("Modifier", octave_value (modifier2cell ())); - fp.execute_keypressfcn (evt); - } - switch (key) + fp.set_currentcharacter (std::string (e_text)); + if (fp.get_keypressfcn ().is_defined () + && (evt.contents ("Key").length () > 0)) + fp.execute_keypressfcn (evt); + + switch (e_key) { case 'a': case 'A': @@ -1288,19 +1377,33 @@ case FL_KEYUP: { - int key = Fl::event_key (); - - shift &= (~key2shift (key)); - int key_a = key2ascii (key); - if (key_a && fp.get_keyreleasefcn ().is_defined ()) + int e_key = Fl::event_key (); + int e_state = Fl::event_state (); + octave_scalar_map evt; + if (key_resent_detected && Fl::event_length () == 1) { - octave_scalar_map evt; - evt.assign ("Character", octave_value (key_a)); - evt.assign ("Key", octave_value (std::tolower (key_a))); - evt.assign ("Modifier", octave_value (modifier2cell ())); - fp.execute_keyreleasefcn (evt); - return 1; + // FLTK flipped the case of Fl::event_text because no + // widget wanted the FL_KEYDOWN event. + char tmp_e_text[2]; + tmp_e_text[0] = Fl::event_text ()[0]; + tmp_e_text[1] = 0; + // Undo the case flip + if (std::islower (tmp_e_text[0])) + tmp_e_text[0] = std::toupper (tmp_e_text[0]); + else + tmp_e_text[0] = std::tolower (tmp_e_text[0]); + evt = format_key_event (e_key, tmp_e_text, e_state); } + else + { + const char *e_text = Fl::event_text (); + evt = format_key_event (e_key, e_text, e_state); + } + + if (fp.get_keyreleasefcn ().is_defined () + && (evt.contents ("Key").length () > 0)) + fp.execute_keyreleasefcn (evt); + return 1; } break; } @@ -1321,7 +1424,7 @@ set_currentpoint (pos_x, pos_y); - if (fp.get_windowbuttonupfcn ().is_defined ()) + if (fp.get_windowbuttondownfcn ().is_defined ()) fp.execute_windowbuttondownfcn (Fl::event_button ()); gh = pixel2axes_or_ca (pos_x, pos_y); @@ -1900,7 +2003,9 @@ fltk_graphics_toolkit (void) : base_graphics_toolkit (FLTK_GRAPHICS_TOOLKIT_NAME), input_event_hook_fcn_id () - { } + { + Fl::visual (FL_RGB); + } ~fltk_graphics_toolkit (void) { }