From 77638fcaa048a7714e7cb536d3ff528a4e41c3ec Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Sat, 7 Mar 2020 21:32:18 +0100 Subject: [PATCH] Fixes keyboard input buffer problem when opening a modal dialog --- ChangeLog | 3 +++ examples/keyboard.cpp | 7 ++++-- src/fapplication.cpp | 3 +++ src/fkey_map.cpp | 1 + src/fkeyboard.cpp | 10 ++++---- src/ftermcap.cpp | 45 +++++++++++++++--------------------- src/ftermcapquirks.cpp | 8 +++++++ src/fvterm.cpp | 2 +- src/fwidget.cpp | 4 +++- src/include/final/fc.h | 2 +- src/include/final/ftermcap.h | 2 +- test/fkeyboard-test.cpp | 6 ++--- test/foptiattr-test.cpp | 6 ++--- 13 files changed, 56 insertions(+), 43 deletions(-) diff --git a/ChangeLog b/ChangeLog index a06c45e1..108f15a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2020-03-07 Markus Gans + * Fixes keyboard input buffer problem when opening a modal dialog + 2020-03-05 Markus Gans * Unbuffered reading of keystrokes for better latency * Mouse adjustments when resizing an rxvt terminal diff --git a/examples/keyboard.cpp b/examples/keyboard.cpp index 24b0b30f..7749db47 100644 --- a/examples/keyboard.cpp +++ b/examples/keyboard.cpp @@ -54,13 +54,16 @@ Keyboard::Keyboard (finalcut::FWidget* parent) void Keyboard::onKeyPress (finalcut::FKeyEvent* ev) { const FKey key_id = ev->key(); + finalcut::FString key_name = getKeyName(key_id); bool is_last_line{false}; + if ( key_name.isEmpty() ) + key_name = wchar_t(key_id); + if ( getPrintPos().getY() == int(getDesktopHeight()) ) is_last_line = true; - print() << "Key " << getKeyName(key_id).c_str() - << " (id " << key_id << ")\n"; + print() << "Key " << key_name << " (id " << key_id << ")\n"; if ( is_last_line ) scrollAreaForward (getVirtualDesktop()); diff --git a/src/fapplication.cpp b/src/fapplication.cpp index d6665800..6c0cbcb3 100644 --- a/src/fapplication.cpp +++ b/src/fapplication.cpp @@ -208,7 +208,10 @@ bool FApplication::sendEvent ( const FObject* receiver case fc::MouseMove_Event: case fc::FocusIn_Event: case fc::FocusOut_Event: + case fc::ChildFocusIn_Event: + case fc::ChildFocusOut_Event: case fc::Accelerator_Event: + keyboard->clearKeyBuffer(); return false; default: diff --git a/src/fkey_map.cpp b/src/fkey_map.cpp index d0396424..9ca1bdd1 100644 --- a/src/fkey_map.cpp +++ b/src/fkey_map.cpp @@ -827,6 +827,7 @@ FKeyName fkeyname[] = { fc::Fkey_mouse , "xterm mouse" }, { fc::Fkey_extended_mouse , "SGR extended mouse" }, { fc::Fkey_urxvt_mouse , "urxvt mouse extension" }, + { fc::Fkey_incomplete , "incomplete key string" }, { 0 , "\0" } }; diff --git a/src/fkeyboard.cpp b/src/fkeyboard.cpp index 54cee144..e71537b0 100644 --- a/src/fkeyboard.cpp +++ b/src/fkeyboard.cpp @@ -260,7 +260,7 @@ inline FKey FKeyboard::getMetaKey() || fifo_buf[1] == ']' ) ) { if ( ! isKeypressTimeout() ) - return fc::need_more_data; + return fc::Fkey_incomplete; } for (n = len; n < FIFO_BUF_SIZE; n++) // Remove founded entry @@ -301,7 +301,7 @@ inline FKey FKeyboard::getSingleKey() len = 4; if ( buf_len < len && ! isKeypressTimeout() ) - return fc::need_more_data; + return fc::Fkey_incomplete; for (std::size_t i{0}; i < len ; i++) utf8char[i] = char(fifo_buf[i] & 0xff); @@ -431,12 +431,12 @@ void FKeyboard::parseKeyBuffer() // Read the rest from the fifo buffer while ( ! isKeypressTimeout() && fifo_offset > 0 - && key != fc::need_more_data ) + && key != fc::Fkey_incomplete ) { key = parseKeyString(); key = keyCorrection(key); - if ( key != fc::need_more_data ) + if ( key != fc::Fkey_incomplete ) keyPressed(); fifo_offset = int(std::strlen(fifo_buf)); @@ -480,7 +480,7 @@ FKey FKeyboard::parseKeyString() return keycode; if ( ! isKeypressTimeout() ) - return fc::need_more_data; + return fc::Fkey_incomplete; } return getSingleKey(); diff --git a/src/ftermcap.cpp b/src/ftermcap.cpp index 1b39e2a2..cbd3926d 100644 --- a/src/ftermcap.cpp +++ b/src/ftermcap.cpp @@ -275,47 +275,40 @@ void FTermcap::termcapKeys (char*& buffer) } // VT100 key codes for the arrow and function keys - termcapKeysVt100 (buffer); + termcapKeysVt100(); } //---------------------------------------------------------------------- -void FTermcap::termcapKeysVt100 (char*& buffer) +void FTermcap::termcapKeysVt100() { // Some terminals (e.g. PuTTY) send vt100 key codes for // the arrow and function keys. - const char* key_up_string = tgetstr(C_STR("ku"), &buffer); - - if ( (key_up_string && (std::strcmp(key_up_string, ESC "OA") == 0)) - || ( TCAP(fc::t_cursor_up) - && (std::strcmp(TCAP(fc::t_cursor_up), CSI "A") == 0) ) ) + for (std::size_t i{0}; fc::fkey[i].tname[0] != 0; i++) { - for (std::size_t i{0}; fc::fkey[i].tname[0] != 0; i++) - { - if ( std::strncmp(fc::fkey[i].tname, "kux", 3) == 0 ) - fc::fkey[i].string = C_STR(CSI "A"); // Key up + if ( std::strncmp(fc::fkey[i].tname, "kux", 3) == 0 ) + fc::fkey[i].string = C_STR(CSI "A"); // Key up - if ( std::strncmp(fc::fkey[i].tname, "kdx", 3) == 0 ) - fc::fkey[i].string = C_STR(CSI "B"); // Key down + if ( std::strncmp(fc::fkey[i].tname, "kdx", 3) == 0 ) + fc::fkey[i].string = C_STR(CSI "B"); // Key down - if ( std::strncmp(fc::fkey[i].tname, "krx", 3) == 0 ) - fc::fkey[i].string = C_STR(CSI "C"); // Key right + if ( std::strncmp(fc::fkey[i].tname, "krx", 3) == 0 ) + fc::fkey[i].string = C_STR(CSI "C"); // Key right - if ( std::strncmp(fc::fkey[i].tname, "klx", 3) == 0 ) - fc::fkey[i].string = C_STR(CSI "D"); // Key left + if ( std::strncmp(fc::fkey[i].tname, "klx", 3) == 0 ) + fc::fkey[i].string = C_STR(CSI "D"); // Key left - if ( std::strncmp(fc::fkey[i].tname, "k1X", 3) == 0 ) - fc::fkey[i].string = C_STR(ESC "OP"); // PF1 + if ( std::strncmp(fc::fkey[i].tname, "k1X", 3) == 0 ) + fc::fkey[i].string = C_STR(ESC "OP"); // PF1 - if ( std::strncmp(fc::fkey[i].tname, "k2X", 3) == 0 ) - fc::fkey[i].string = C_STR(ESC "OQ"); // PF2 + if ( std::strncmp(fc::fkey[i].tname, "k2X", 3) == 0 ) + fc::fkey[i].string = C_STR(ESC "OQ"); // PF2 - if ( std::strncmp(fc::fkey[i].tname, "k3X", 3) == 0 ) - fc::fkey[i].string = C_STR(ESC "OR"); // PF3 + if ( std::strncmp(fc::fkey[i].tname, "k3X", 3) == 0 ) + fc::fkey[i].string = C_STR(ESC "OR"); // PF3 - if ( std::strncmp(fc::fkey[i].tname, "k4X", 3) == 0 ) - fc::fkey[i].string = C_STR(ESC "OS"); // PF4 - } + if ( std::strncmp(fc::fkey[i].tname, "k4X", 3) == 0 ) + fc::fkey[i].string = C_STR(ESC "OS"); // PF4 } } diff --git a/src/ftermcapquirks.cpp b/src/ftermcapquirks.cpp index 5e29e24c..41d0677f 100644 --- a/src/ftermcapquirks.cpp +++ b/src/ftermcapquirks.cpp @@ -360,6 +360,14 @@ void FTermcapQuirks::putty() TCAP(fc::t_exit_pc_charset_mode) = \ C_STR(CSI "10m"); + if ( ! TCAP(fc::t_keypad_xmit) ) + TCAP(fc::t_keypad_xmit) = \ + C_STR(CSI "?1h" ESC "="); + + if ( ! TCAP(fc::t_keypad_local) ) + TCAP(fc::t_keypad_local) = \ + C_STR(CSI "?1l" ESC ">"); + if ( ! TCAP(fc::t_key_mouse) ) TCAP(fc::t_key_mouse) = \ C_STR(CSI "M"); diff --git a/src/fvterm.cpp b/src/fvterm.cpp index 009b5b39..ebd13121 100644 --- a/src/fvterm.cpp +++ b/src/fvterm.cpp @@ -186,7 +186,7 @@ FColor FVTerm::rgb2ColorIndex (uInt8 r, uInt8 g, uInt8 b) void FVTerm::setNonBlockingRead (bool enable) { uInt64 blocking_time = (enable) ? 0 : 100000; // 0 or 100 ms - FKeyboard::setReadBlockingTime (blocking_time); + FKeyboard::setReadBlockingTime (blocking_time); } //---------------------------------------------------------------------- diff --git a/src/fwidget.cpp b/src/fwidget.cpp index 0af10ef4..fcea2172 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -1820,7 +1820,9 @@ void FWidget::KeyPressEvent (FKeyEvent* kev) } } - if ( kev->isAccepted() || widget->isRootWidget() ) + if ( kev->isAccepted() + || widget->isRootWidget() + || widget->getFlags().modal ) return; widget = widget->getParentWidget(); diff --git a/src/include/final/fc.h b/src/include/final/fc.h index 10fccb2c..648b8a56 100644 --- a/src/include/final/fc.h +++ b/src/include/final/fc.h @@ -459,7 +459,7 @@ enum keys : FKey Fkey_f61 = 0x01000192, Fkey_f62 = 0x01000193, Fkey_f63 = 0x01000194, - need_more_data = 0x80000000 + Fkey_incomplete = UINT32_MAX }; // Keyboard - modifier key combinations diff --git a/src/include/final/ftermcap.h b/src/include/final/ftermcap.h index f1dbe48b..94f60e7e 100644 --- a/src/include/final/ftermcap.h +++ b/src/include/final/ftermcap.h @@ -118,7 +118,7 @@ class FTermcap final static void termcapNumerics(); static void termcapStrings (char*&); static void termcapKeys (char*&); - static void termcapKeysVt100 (char*&); + static void termcapKeysVt100(); // Data member static FTermData* fterm_data; diff --git a/test/fkeyboard-test.cpp b/test/fkeyboard-test.cpp index 03c81540..2f72774e 100644 --- a/test/fkeyboard-test.cpp +++ b/test/fkeyboard-test.cpp @@ -3,7 +3,7 @@ * * * This file is part of the Final Cut widget toolkit * * * -* Copyright 2018-2019 Markus Gans * +* Copyright 2018-2020 Markus Gans * * * * The Final Cut is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License * @@ -333,7 +333,7 @@ void FKeyboardTest::noArgumentTest() // Keypress timeout CPPUNIT_ASSERT ( keyboard->getKeypressTimeout() == 100 * 1000 ); - + keyboard->setKeypressTimeout(0); // 0 ms CPPUNIT_ASSERT ( keyboard->getKeypressTimeout() == 0 ); @@ -342,7 +342,7 @@ void FKeyboardTest::noArgumentTest() // Read blocking time CPPUNIT_ASSERT ( keyboard->getReadBlockingTime() == 100 * 1000 ); - + keyboard->setReadBlockingTime(1000000); // 1000 ms CPPUNIT_ASSERT ( keyboard->getReadBlockingTime() == 1000 * 1000 ); diff --git a/test/foptiattr-test.cpp b/test/foptiattr-test.cpp index 7e3bfcdd..b315771a 100644 --- a/test/foptiattr-test.cpp +++ b/test/foptiattr-test.cpp @@ -276,15 +276,15 @@ void FOptiAttrTest::sgrOptimizerTest() std::strcpy(buffer, CSI "1;1H" CSI "m" CSI "38;5;35m"); sgr_optimizer.optimize(); CPPUNIT_ASSERT_CSTRING ( buffer, C_STR(CSI "1;1H" CSI "0;38;5;35m") ); - - std::strcpy(buffer, CSI "m" CSI "38;5;20m" CSI "11;16H" CSI "48;5;229m"); + + std::strcpy(buffer, CSI "m" CSI "38;5;20m" CSI "11;16H" CSI "48;5;229m"); sgr_optimizer.optimize(); CPPUNIT_ASSERT_CSTRING ( buffer, C_STR(CSI "0;38;5;20m" CSI "11;16H" CSI "48;5;229m") ); std::strcpy(buffer, CSI "m" CSI "38;5;20m" "ABC" CSI "48;5;229m"); sgr_optimizer.optimize(); CPPUNIT_ASSERT_CSTRING ( buffer, C_STR(CSI "0;38;5;20mABC" CSI "48;5;229m") ); - + std::strcpy(buffer, CSI "m" CSI "1m" CSI "2m" CSI "3m" CSI "4m" CSI "5m" CSI "7m" CSI "8m" CSI "9m");