Now FINAL CUT queues keyboard and mouse input to speed up the processing of widget events

This commit is contained in:
Markus Gans 2020-11-01 20:11:36 +01:00
parent 98f9cd5718
commit 0ee09aad2c
22 changed files with 832 additions and 549 deletions

View File

@ -1,3 +1,7 @@
2020-11-01 Markus Gans <guru.mail@muenster.de>
* Now FINAL CUT queues keyboard and mouse input to speed up
the processing of widget events
2020-10-22 Markus Gans <guru.mail@muenster.de> 2020-10-22 Markus Gans <guru.mail@muenster.de>
* Repair terminal update skipping * Repair terminal update skipping

View File

@ -27,10 +27,6 @@
#include <final/final.h> #include <final/final.h>
// Global FApplication object
static finalcut::FApplication* app{nullptr};
// function prototype // function prototype
bool keyPressed(); bool keyPressed();
void term_boundaries (int&, int&); void term_boundaries (int&, int&);
@ -66,8 +62,8 @@ bool keyPressed()
void term_boundaries (int& x, int& y) void term_boundaries (int& x, int& y)
{ {
// checks and corrects the terminal boundaries // checks and corrects the terminal boundaries
const auto term_width = int(app->getDesktopWidth()); const auto term_width = int(finalcut::FTerm::getColumnNumber());
const auto term_height = int(app->getDesktopHeight()); const auto term_height = int(finalcut::FTerm::getLineNumber());
if ( x < 0 ) if ( x < 0 )
x = 0; x = 0;
@ -226,9 +222,6 @@ int main (int argc, char* argv[])
if ( finalcut::FApplication::isQuit() ) if ( finalcut::FApplication::isQuit() )
return 0; return 0;
// Pointer to the global virtual terminal object
app = &term_app;
// Get screen dimension // Get screen dimension
auto xmax = int(term_app.getDesktopWidth() - 1); auto xmax = int(term_app.getDesktopWidth() - 1);
auto ymax = int(term_app.getDesktopHeight() - 1); auto ymax = int(term_app.getDesktopHeight() - 1);
@ -282,7 +275,5 @@ int main (int argc, char* argv[])
// Waiting for keypress // Waiting for keypress
keyPressed(); keyPressed();
app = nullptr; // End of term_app object scope
return 0; return 0;
} }

View File

@ -46,11 +46,19 @@
namespace finalcut namespace finalcut
{ {
// Global application object namespace internal
static FApplication* app_object{nullptr}; {
// Flag to exit the local event loop struct var
static bool app_exit_loop{false}; {
static FApplication* app_object; // Global application object
static bool exit_loop; // Flag to exit the local event loop
};
FApplication* var::app_object {nullptr};
bool var::exit_loop {false};
} // namespace internal
// Static attributes // Static attributes
FWidget* FWidget::main_widget {nullptr}; // main application widget FWidget* FWidget::main_widget {nullptr}; // main application widget
@ -66,7 +74,7 @@ int FApplication::loop_level {0}; // event loop level
int FApplication::quit_code {EXIT_SUCCESS}; int FApplication::quit_code {EXIT_SUCCESS};
bool FApplication::quit_now {false}; bool FApplication::quit_now {false};
uInt64 FApplication::next_event_wait {5000}; // preset to 5 ms (200 Hz) uInt64 FApplication::next_event_wait {5000}; // preset to 5 ms (200 Hz)
struct timeval FApplication::time_last_event{}; struct timeval FApplication::time_last_event {};
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -83,7 +91,7 @@ FApplication::FApplication (const int& _argc, char* _argv[])
if ( quit_now ) if ( quit_now )
return; return;
if ( app_object ) if ( internal::var::app_object )
{ {
auto ftermdata = FTerm::getFTermData(); auto ftermdata = FTerm::getFTermData();
ftermdata->setExitMessage("FApplication: There should be " ftermdata->setExitMessage("FApplication: There should be "
@ -93,7 +101,7 @@ FApplication::FApplication (const int& _argc, char* _argv[])
} }
// First define the application object // First define the application object
app_object = this; internal::var::app_object = this;
if ( ! (_argc && _argv) ) if ( ! (_argc && _argv) )
{ {
@ -109,7 +117,7 @@ FApplication::FApplication (const int& _argc, char* _argv[])
//---------------------------------------------------------------------- //----------------------------------------------------------------------
FApplication::~FApplication() // destructor FApplication::~FApplication() // destructor
{ {
app_object = nullptr; internal::var::app_object = nullptr;
if ( eventInQueue() ) if ( eventInQueue() )
event_queue.clear(); event_queue.clear();
@ -122,7 +130,7 @@ FApplication::~FApplication() // destructor
//---------------------------------------------------------------------- //----------------------------------------------------------------------
FApplication* FApplication::getApplicationObject() FApplication* FApplication::getApplicationObject()
{ {
return app_object; return internal::var::app_object;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -162,7 +170,7 @@ void FApplication::setLog (const FLogPtr& log)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
bool FApplication::isQuit() bool FApplication::isQuit()
{ {
return ( app_object ) ? quit_now : true; return ( internal::var::app_object ) ? quit_now : true;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -185,13 +193,13 @@ int FApplication::enterLoop() // event loop
loop_level++; loop_level++;
quit_now = false; quit_now = false;
const bool old_app_exit_loop = app_exit_loop; const bool old_app_exit_loop = internal::var::exit_loop;
app_exit_loop = false; internal::var::exit_loop = false;
while ( ! (quit_now || app_exit_loop) ) while ( ! (quit_now || internal::var::exit_loop) )
processNextEvent(); processNextEvent();
app_exit_loop = old_app_exit_loop; internal::var::exit_loop = old_app_exit_loop;
loop_level--; loop_level--;
return 0; return 0;
} }
@ -199,7 +207,7 @@ int FApplication::enterLoop() // event loop
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::exitLoop() const void FApplication::exitLoop() const
{ {
app_exit_loop = true; internal::var::exit_loop = true;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -218,7 +226,7 @@ void FApplication::quit() const
//---------------------------------------------------------------------- //----------------------------------------------------------------------
bool FApplication::sendEvent (FObject* receiver, FEvent* event ) bool FApplication::sendEvent (FObject* receiver, FEvent* event )
{ {
if ( quit_now || app_exit_loop || ! (bool(receiver) && bool(event)) ) if ( quit_now || internal::var::exit_loop || ! (bool(receiver) && bool(event)) )
return false; return false;
if ( ! isEventProcessable (receiver, event) ) if ( ! isEventProcessable (receiver, event) )
@ -256,7 +264,7 @@ void FApplication::sendQueuedEvents()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
bool FApplication::eventInQueue() const bool FApplication::eventInQueue() const
{ {
if ( app_object ) if ( internal::var::app_object )
return ( ! event_queue.empty() ); return ( ! event_queue.empty() );
else else
return false; return false;
@ -358,7 +366,7 @@ void FApplication::setKeyboardWidget (FWidget* widget)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::closeConfirmationDialog (FWidget* w, FCloseEvent* ev) void FApplication::closeConfirmationDialog (FWidget* w, FCloseEvent* ev)
{ {
app_object->unsetMoveSizeMode(); internal::var::app_object->unsetMoveSizeMode();
const int ret = FMessageBox::info ( w, "Quit" const int ret = FMessageBox::info ( w, "Quit"
, "Do you really want\n" , "Do you really want\n"
"to quit the program ?" "to quit the program ?"
@ -402,31 +410,39 @@ void FApplication::init()
// Initialize keyboard // Initialize keyboard
keyboard = FTerm::getFKeyboard(); keyboard = FTerm::getFKeyboard();
// Set the keyboard keypress timeout
if ( keyboard ) if ( keyboard )
{ {
auto cmd1 = std::bind(&FApplication::keyPressed, this); auto cmd1 = std::bind(&FApplication::keyPressed, this);
auto cmd2 = std::bind(&FApplication::keyReleased, this); auto cmd2 = std::bind(&FApplication::keyReleased, this);
auto cmd3 = std::bind(&FApplication::escapeKeyPressed, this); auto cmd3 = std::bind(&FApplication::escapeKeyPressed, this);
auto cmd4 = std::bind(&FApplication::mouseTracking, this);
FKeyboardCommand key_cmd1 (cmd1); FKeyboardCommand key_cmd1 (cmd1);
FKeyboardCommand key_cmd2 (cmd2); FKeyboardCommand key_cmd2 (cmd2);
FKeyboardCommand key_cmd3 (cmd3); FKeyboardCommand key_cmd3 (cmd3);
FKeyboardCommand key_cmd4 (cmd4);
keyboard->setPressCommand (key_cmd1); keyboard->setPressCommand (key_cmd1);
keyboard->setReleaseCommand (key_cmd2); keyboard->setReleaseCommand (key_cmd2);
keyboard->setEscPressedCommand (key_cmd3); keyboard->setEscPressedCommand (key_cmd3);
keyboard->setMouseTrackingCommand (key_cmd4);
// Set the keyboard keypress timeout
keyboard->setKeypressTimeout (key_timeout); keyboard->setKeypressTimeout (key_timeout);
} }
// Initialize mouse control // Initialize mouse control
mouse = FTerm::getFMouseControl(); mouse = FTerm::getFMouseControl();
// Set stdin number for a gpm-mouse
if ( mouse ) if ( mouse )
{
using namespace std::placeholders;
auto cmd = std::bind(&FApplication::mouseEvent, this, _1);
FMouseCommand mouse_cmd (cmd);
mouse->setEventCommand (mouse_cmd);
// Set stdin number for a gpm-mouse
mouse->setStdinNo (FTermios::getStdIn()); mouse->setStdinNo (FTermios::getStdIn());
// Set the default double click interval
// Set the default double click interval
if ( mouse )
mouse->setDblclickInterval (dblclick_interval); mouse->setDblclickInterval (dblclick_interval);
}
// Initialize logging // Initialize logging
if ( ! getStartOptions().logfile_stream.is_open() ) if ( ! getStartOptions().logfile_stream.is_open() )
@ -676,54 +692,71 @@ void FApplication::escapeKeyPressed() const
sendEscapeKeyPressEvent(); sendEscapeKeyPressEvent();
} }
//----------------------------------------------------------------------
void FApplication::mouseTracking()
{
performMouseAction();
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline void FApplication::performKeyboardAction() inline void FApplication::performKeyboardAction()
{ {
if ( keyboard->getKey() == fc::Fckey_l ) // Ctrl-L (redraw the screen)
{
redraw();
}
else
{
const bool acceptKeyDown = sendKeyDownEvent (keyboard_widget);
const bool acceptKeyPress = sendKeyPressEvent (keyboard_widget);
if ( ! (acceptKeyDown || acceptKeyPress) )
sendKeyboardAccelerator();
}
}
//----------------------------------------------------------------------
inline void FApplication::performMouseAction()
{
if ( ! mouse )
return;
auto& buffer = keyboard->getKeyBuffer();
switch ( keyboard->getKey() ) switch ( keyboard->getKey() )
{ {
case fc::Fckey_l: // Ctrl-L (redraw the screen)
redraw();
break;
case fc::Fkey_mouse: case fc::Fkey_mouse:
if ( mouse ) mouse->setRawData (FMouse::x11, buffer);
{
FKeyboard::keybuffer& buffer = keyboard->getKeyBuffer();
mouse->setRawData (FMouse::x11, buffer);
keyboard->hasUnprocessedInput() = mouse->hasUnprocessedInput();
processMouseEvent();
}
break; break;
case fc::Fkey_extended_mouse: case fc::Fkey_extended_mouse:
if ( mouse ) mouse->setRawData (FMouse::sgr, buffer);
{
FKeyboard::keybuffer& buffer = keyboard->getKeyBuffer();
mouse->setRawData (FMouse::sgr, buffer);
keyboard->hasUnprocessedInput() = mouse->hasUnprocessedInput();
processMouseEvent();
}
break; break;
case fc::Fkey_urxvt_mouse: case fc::Fkey_urxvt_mouse:
if ( mouse ) mouse->setRawData (FMouse::urxvt, buffer);
{
FKeyboard::keybuffer& buffer = keyboard->getKeyBuffer();
mouse->setRawData (FMouse::urxvt, buffer);
keyboard->hasUnprocessedInput() = mouse->hasUnprocessedInput();
processMouseEvent();
}
break;
default:
const bool acceptKeyDown = sendKeyDownEvent (keyboard_widget);
const bool acceptKeyPress = sendKeyPressEvent (keyboard_widget);
if ( ! (acceptKeyDown || acceptKeyPress) )
sendKeyboardAccelerator();
break; break;
} }
keyboard->hasUnprocessedInput() = mouse->hasUnprocessedInput();
queuingMouseInput();
}
//----------------------------------------------------------------------
void FApplication::mouseEvent (const FMouseData& md)
{
determineClickedWidget (md);
if ( FWidget::getClickedWidget() )
{
unsetMoveSizeMode();
closeDropDown (md);
unselectMenubarItems (md);
sendMouseEvent (md);
}
if ( mouse )
mouse->drawGpmPointer();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -790,20 +823,62 @@ inline void FApplication::sendKeyboardAccelerator()
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::processKeyboardEvent() const inline bool FApplication::hasDataInQueue() const
{ {
if ( quit_now || app_exit_loop ) if ( keyboard && keyboard->hasDataInQueue() )
return true;
else if ( mouse && mouse->hasDataInQueue() )
return true;
return false;
}
//----------------------------------------------------------------------
void FApplication::queuingKeyboardInput() const
{
if ( quit_now || internal::var::exit_loop || ! keyboard )
return; return;
findKeyboardWidget(); findKeyboardWidget();
flush();
keyboard->escapeKeyHandling(); // special case: Esc key keyboard->escapeKeyHandling(); // special case: Esc key
keyboard->clearKeyBufferOnTimeout(); keyboard->clearKeyBufferOnTimeout();
std::fflush(stdout);
if ( isKeyPressed() ) if ( isKeyPressed() )
keyboard->fetchKeyCode(); keyboard->fetchKeyCode();
} }
//----------------------------------------------------------------------
void FApplication::queuingMouseInput() const
{
if ( quit_now || internal::var::exit_loop
|| ! mouse || ! mouse->hasData() )
return;
struct timeval* time_keypressed = keyboard->getKeyPressedTime();
mouse->processEvent (time_keypressed);
keyboard->hasUnprocessedInput() = mouse->hasUnprocessedInput();
mouse->clearEvent();
}
//----------------------------------------------------------------------
void FApplication::processKeyboardEvent() const
{
if ( quit_now || internal::var::exit_loop || ! keyboard )
return;
keyboard->processQueuedInput();
}
//----------------------------------------------------------------------
void FApplication::processMouseEvent() const
{
if ( quit_now || internal::var::exit_loop || ! mouse )
return;
mouse->processQueuedInput();
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
bool FApplication::processDialogSwitchAccelerator() const bool FApplication::processDialogSwitchAccelerator() const
{ {
@ -859,7 +934,7 @@ bool FApplication::processAccelerator (const FWidget& widget) const
return a_ev.isAccepted(); return a_ev.isAccepted();
} }
if ( quit_now || app_exit_loop ) if ( quit_now || internal::var::exit_loop )
break; break;
} }
@ -867,38 +942,22 @@ bool FApplication::processAccelerator (const FWidget& widget) const
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
bool FApplication::getMouseEvent() const void FApplication::determineClickedWidget (const FMouseData& md)
{ {
bool mouse_event_occurred{false}; clicked_widget = FWidget::getClickedWidget();
if ( mouse && mouse->hasData() ) if ( clicked_widget )
{ return; // The clicked widget was already found
struct timeval* time_keypressed = keyboard->getKeyPressedTime();
mouse->processEvent (time_keypressed);
keyboard->hasUnprocessedInput() = mouse->hasUnprocessedInput();
mouse_event_occurred = mouse->hasEvent();
}
return mouse_event_occurred; if ( ! md.isLeftButtonPressed()
} && ! md.isLeftButtonDoubleClick()
&& ! md.isRightButtonPressed()
&& ! md.isMiddleButtonPressed()
&& ! md.isWheelUp()
&& ! md.isWheelDown() )
return;
//---------------------------------------------------------------------- const auto& mouse_position = md.getPos();
FWidget*& FApplication::determineClickedWidget()
{
FWidget*& clicked = FWidget::getClickedWidget();
if ( clicked || ! mouse )
return clicked;
if ( ! mouse->isLeftButtonPressed()
&& ! mouse->isLeftButtonDoubleClick()
&& ! mouse->isRightButtonPressed()
&& ! mouse->isMiddleButtonPressed()
&& ! mouse->isWheelUp()
&& ! mouse->isWheelDown() )
return clicked;
auto mouse_position = mouse->getPos();
// Determine the window object on the current click position // Determine the window object on the current click position
auto window = FWindow::getWindowWidgetAt (mouse_position); auto window = FWindow::getWindowWidgetAt (mouse_position);
@ -906,12 +965,10 @@ FWidget*& FApplication::determineClickedWidget()
if ( window ) if ( window )
{ {
// Determine the widget at the current click position // Determine the widget at the current click position
auto child = window->childWidgetAt (mouse_position); auto child = window->childWidgetAt(mouse_position);
clicked = ( child != nullptr ) ? child : window; clicked_widget = ( child != nullptr ) ? child : window;
setClickedWidget (clicked); setClickedWidget (clicked_widget);
} }
return clicked;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -919,43 +976,43 @@ void FApplication::unsetMoveSizeMode() const
{ {
// Unset the move/size mode // Unset the move/size mode
auto move_size = getMoveSizeWidget(); auto& move_size = getMoveSizeWidget();
if ( move_size ) if ( move_size )
{ {
auto w = move_size; FWidget* w{nullptr};
setMoveSizeWidget(nullptr); std::swap(w, move_size); // Clear move_size_widget
w->redraw(); w->redraw();
} }
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::closeDropDown() const void FApplication::closeDropDown (const FMouseData& md) const
{ {
// Close the open menu // Close the open menu
if ( ! mouse || mouse->isMoved() ) if ( md.isMoved() )
return; return;
auto mouse_position = mouse->getPos(); const auto& mouse_position = md.getPos();
finalcut::closeDropDown (this, mouse_position); finalcut::closeDropDown (this, mouse_position);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::unselectMenubarItems() const void FApplication::unselectMenubarItems (const FMouseData& md) const
{ {
// Unselect the menu bar items // Unselect the menu bar items
const auto& openmenu = FWidget::getOpenMenu(); const auto& openmenu = FWidget::getOpenMenu();
auto menu_bar = FWidget::getMenuBar(); auto menu_bar = FWidget::getMenuBar();
if ( openmenu || (mouse && mouse->isMoved()) ) if ( openmenu || md.isMoved() )
return; return;
if ( ! (menu_bar && menu_bar->hasSelectedItem() && mouse) ) if ( ! (menu_bar && menu_bar->hasSelectedItem()) )
return; return;
const auto& mouse_position = mouse->getPos(); const auto& mouse_position = md.getPos();
if ( ! menu_bar->getTermGeometry().contains(mouse_position) ) if ( ! menu_bar->getTermGeometry().contains(mouse_position) )
{ {
@ -975,116 +1032,102 @@ void FApplication::unselectMenubarItems() const
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::sendMouseEvent() const void FApplication::sendMouseEvent (const FMouseData& md) const
{ {
auto clicked = FWidget::getClickedWidget(); const auto& mouse_position = md.getPos();
if ( ! (clicked && mouse) )
return;
const auto& mouse_position = mouse->getPos();
int key_state{0}; int key_state{0};
if ( mouse->isShiftKeyPressed() ) if ( md.isShiftKeyPressed() )
key_state |= fc::ShiftButton; key_state |= fc::ShiftButton;
if ( mouse->isControlKeyPressed() ) if ( md.isControlKeyPressed() )
key_state |= fc::ControlButton; key_state |= fc::ControlButton;
if ( mouse->isMetaKeyPressed() ) if ( md.isMetaKeyPressed() )
key_state |= fc::MetaButton; key_state |= fc::MetaButton;
const auto& widgetMousePos = clicked->termToWidgetPos(mouse_position); const auto& widgetMousePos = clicked_widget->termToWidgetPos(mouse_position);
if ( mouse->isMoved() ) if ( md.isMoved() )
{ {
sendMouseMoveEvent (widgetMousePos, mouse_position, key_state); sendMouseMoveEvent (md, widgetMousePos, mouse_position, key_state);
} }
else else
{ {
sendMouseLeftClickEvent (widgetMousePos, mouse_position, key_state); sendMouseLeftClickEvent (md, widgetMousePos, mouse_position, key_state);
sendMouseRightClickEvent (widgetMousePos, mouse_position, key_state); sendMouseRightClickEvent (md, widgetMousePos, mouse_position, key_state);
sendMouseMiddleClickEvent (widgetMousePos, mouse_position, key_state); sendMouseMiddleClickEvent (md, widgetMousePos, mouse_position, key_state);
} }
sendWheelEvent (widgetMousePos, mouse_position); sendWheelEvent (md, widgetMousePos, mouse_position);
mouse->clearEvent();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::sendMouseMoveEvent ( const FPoint& widgetMousePos void FApplication::sendMouseMoveEvent ( const FMouseData& md
, const FPoint& widgetMousePos
, const FPoint& mouse_position , const FPoint& mouse_position
, int key_state ) const , int key_state ) const
{ {
if ( ! mouse ) if ( md.isLeftButtonPressed() )
return;
auto clicked = FWidget::getClickedWidget();
if ( mouse->isLeftButtonPressed() )
{ {
FMouseEvent m_down_ev ( fc::MouseMove_Event FMouseEvent m_down_ev ( fc::MouseMove_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::LeftButton | key_state ); , fc::LeftButton | key_state );
sendEvent (clicked, &m_down_ev); sendEvent (clicked_widget, &m_down_ev);
} }
if ( mouse->isRightButtonPressed() ) if ( md.isRightButtonPressed() )
{ {
FMouseEvent m_down_ev ( fc::MouseMove_Event FMouseEvent m_down_ev ( fc::MouseMove_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::RightButton | key_state ); , fc::RightButton | key_state );
sendEvent (clicked, &m_down_ev); sendEvent (clicked_widget, &m_down_ev);
} }
if ( mouse->isMiddleButtonPressed() ) if ( md.isMiddleButtonPressed() )
{ {
FMouseEvent m_down_ev ( fc::MouseMove_Event FMouseEvent m_down_ev ( fc::MouseMove_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::MiddleButton | key_state ); , fc::MiddleButton | key_state );
sendEvent (clicked, &m_down_ev); sendEvent (clicked_widget, &m_down_ev);
} }
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::sendMouseLeftClickEvent ( const FPoint& widgetMousePos void FApplication::sendMouseLeftClickEvent ( const FMouseData& md
, const FPoint& widgetMousePos
, const FPoint& mouse_position , const FPoint& mouse_position
, int key_state ) const , int key_state ) const
{ {
if ( ! mouse ) if ( md.isLeftButtonDoubleClick() )
return;
auto clicked = FWidget::getClickedWidget();
if ( mouse->isLeftButtonDoubleClick() )
{ {
FMouseEvent m_dblclick_ev ( fc::MouseDoubleClick_Event FMouseEvent m_dblclick_ev ( fc::MouseDoubleClick_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::LeftButton | key_state ); , fc::LeftButton | key_state );
sendEvent (clicked, &m_dblclick_ev); sendEvent (clicked_widget, &m_dblclick_ev);
} }
else if ( mouse->isLeftButtonPressed() ) else if ( md.isLeftButtonPressed() )
{ {
FMouseEvent m_down_ev ( fc::MouseDown_Event FMouseEvent m_down_ev ( fc::MouseDown_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::LeftButton | key_state ); , fc::LeftButton | key_state );
sendEvent (clicked, &m_down_ev); sendEvent (clicked_widget, &m_down_ev);
} }
else if ( mouse->isLeftButtonReleased() ) else if ( md.isLeftButtonReleased() )
{ {
FMouseEvent m_up_ev ( fc::MouseUp_Event FMouseEvent m_up_ev ( fc::MouseUp_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::LeftButton | key_state ); , fc::LeftButton | key_state );
auto released_widget = clicked; auto released_widget = clicked_widget;
if ( ! mouse->isRightButtonPressed() if ( ! md.isRightButtonPressed()
&& ! mouse->isMiddleButtonPressed() ) && ! md.isMiddleButtonPressed() )
setClickedWidget(nullptr); setClickedWidget(nullptr);
sendEvent (released_widget, &m_up_ev); sendEvent (released_widget, &m_up_ev);
@ -1092,33 +1135,29 @@ void FApplication::sendMouseLeftClickEvent ( const FPoint& widgetMousePos
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::sendMouseRightClickEvent ( const FPoint& widgetMousePos void FApplication::sendMouseRightClickEvent ( const FMouseData& md
, const FPoint& widgetMousePos
, const FPoint& mouse_position , const FPoint& mouse_position
, int key_state ) const , int key_state ) const
{ {
if ( ! mouse ) if ( md.isRightButtonPressed() )
return;
auto clicked = FWidget::getClickedWidget();
if ( mouse->isRightButtonPressed() )
{ {
FMouseEvent m_down_ev ( fc::MouseDown_Event FMouseEvent m_down_ev ( fc::MouseDown_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::RightButton | key_state ); , fc::RightButton | key_state );
sendEvent (clicked, &m_down_ev); sendEvent (clicked_widget, &m_down_ev);
} }
else if ( mouse->isRightButtonReleased() ) else if ( md.isRightButtonReleased() )
{ {
FMouseEvent m_up_ev ( fc::MouseUp_Event FMouseEvent m_up_ev ( fc::MouseUp_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::RightButton | key_state ); , fc::RightButton | key_state );
auto released_widget = clicked; auto released_widget = clicked_widget;
if ( ! mouse->isLeftButtonPressed() if ( ! md.isLeftButtonPressed()
&& ! mouse->isMiddleButtonPressed() ) && ! md.isMiddleButtonPressed() )
setClickedWidget(nullptr); setClickedWidget(nullptr);
sendEvent (released_widget, &m_up_ev); sendEvent (released_widget, &m_up_ev);
@ -1126,37 +1165,33 @@ void FApplication::sendMouseRightClickEvent ( const FPoint& widgetMousePos
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::sendMouseMiddleClickEvent ( const FPoint& widgetMousePos void FApplication::sendMouseMiddleClickEvent ( const FMouseData& md
, const FPoint& widgetMousePos
, const FPoint& mouse_position , const FPoint& mouse_position
, int key_state ) const , int key_state ) const
{ {
if ( ! mouse ) if ( md.isMiddleButtonPressed() )
return;
auto clicked = FWidget::getClickedWidget();
if ( mouse->isMiddleButtonPressed() )
{ {
FMouseEvent m_down_ev ( fc::MouseDown_Event FMouseEvent m_down_ev ( fc::MouseDown_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::MiddleButton | key_state ); , fc::MiddleButton | key_state );
sendEvent (clicked, &m_down_ev); sendEvent (clicked_widget, &m_down_ev);
// gnome-terminal sends no released on middle click // gnome-terminal sends no released on middle click
if ( FTerm::isGnomeTerminal() ) if ( FTerm::isGnomeTerminal() )
setClickedWidget(nullptr); setClickedWidget(nullptr);
} }
else if ( mouse->isMiddleButtonReleased() ) else if ( md.isMiddleButtonReleased() )
{ {
FMouseEvent m_up_ev ( fc::MouseUp_Event FMouseEvent m_up_ev ( fc::MouseUp_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::MiddleButton | key_state ); , fc::MiddleButton | key_state );
auto released_widget = clicked; auto released_widget = clicked_widget;
if ( ! mouse->isLeftButtonPressed() if ( ! md.isLeftButtonPressed()
&& ! mouse->isRightButtonPressed() ) && ! md.isRightButtonPressed() )
{ {
setClickedWidget(nullptr); setClickedWidget(nullptr);
} }
@ -1166,32 +1201,28 @@ void FApplication::sendMouseMiddleClickEvent ( const FPoint& widgetMousePos
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::sendWheelEvent ( const FPoint& widgetMousePos void FApplication::sendWheelEvent ( const FMouseData& md
, const FPoint& widgetMousePos
, const FPoint& mouse_position ) const , const FPoint& mouse_position ) const
{ {
if ( ! mouse ) if ( md.isWheelUp() )
return;
auto clicked = FWidget::getClickedWidget();
if ( mouse->isWheelUp() )
{ {
FWheelEvent wheel_ev ( fc::MouseWheel_Event FWheelEvent wheel_ev ( fc::MouseWheel_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::WheelUp ); , fc::WheelUp );
auto scroll_over_widget = clicked; auto scroll_over_widget = clicked_widget;
setClickedWidget(nullptr); setClickedWidget(nullptr);
sendEvent(scroll_over_widget, &wheel_ev); sendEvent(scroll_over_widget, &wheel_ev);
} }
if ( mouse->isWheelDown() ) if ( md.isWheelDown() )
{ {
FWheelEvent wheel_ev ( fc::MouseWheel_Event FWheelEvent wheel_ev ( fc::MouseWheel_Event
, widgetMousePos , widgetMousePos
, mouse_position , mouse_position
, fc::WheelDown ); , fc::WheelDown );
auto scroll_over_widget = clicked; auto scroll_over_widget = clicked_widget;
setClickedWidget(nullptr); setClickedWidget(nullptr);
sendEvent (scroll_over_widget, &wheel_ev); sendEvent (scroll_over_widget, &wheel_ev);
} }
@ -1211,22 +1242,6 @@ FWidget* FApplication::processParameters (const int& argc, char* argv[])
return nullptr; return nullptr;
} }
//----------------------------------------------------------------------
void FApplication::processMouseEvent()
{
if ( ! getMouseEvent() )
return;
determineClickedWidget();
unsetMoveSizeMode();
closeDropDown();
unselectMenubarItems();
sendMouseEvent();
if ( mouse )
mouse->drawGpmPointer();
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::processResizeEvent() const void FApplication::processResizeEvent() const
{ {
@ -1240,7 +1255,7 @@ void FApplication::processResizeEvent() const
} }
FResizeEvent r_ev(fc::Resize_Event); FResizeEvent r_ev(fc::Resize_Event);
sendEvent(app_object, &r_ev); sendEvent(internal::var::app_object, &r_ev);
if ( r_ev.isAccepted() ) if ( r_ev.isAccepted() )
FTerm::changeTermSizeFinished(); FTerm::changeTermSizeFinished();
@ -1284,15 +1299,17 @@ bool FApplication::processNextEvent()
uInt num_events{0}; uInt num_events{0};
bool is_timeout = isNextEventTimeout(); bool is_timeout = isNextEventTimeout();
if ( is_timeout ) if ( is_timeout || hasDataInQueue() )
{ {
FObject::getCurrentTime (&time_last_event); FObject::getCurrentTime (&time_last_event);
processTerminalUpdate(); // before user input queuingKeyboardInput();
queuingMouseInput();
processKeyboardEvent(); processKeyboardEvent();
processMouseEvent(); processMouseEvent();
processResizeEvent(); processResizeEvent();
processTerminalUpdate(); // after user input
processCloseWidget(); processCloseWidget();
processTerminalUpdate(); // after terminal changes
flush();
processLogger(); processLogger();
} }

View File

@ -621,7 +621,7 @@ void FDialog::onMouseMove (FMouseEvent* ev)
// Mouse event handover to the menu // Mouse event handover to the menu
if ( ms.mouse_over_menu ) if ( ms.mouse_over_menu )
passEventToSubMenu (ms, ev); passEventToSubMenu (ms, std::move(*ev));
leaveZoomButton(ms); // Check zoom button pressed leaveZoomButton(ms); // Check zoom button pressed
resizeMouseUpMove(ms); // Resize the dialog resizeMouseUpMove(ms); // Resize the dialog
@ -1359,7 +1359,7 @@ inline bool FDialog::isMouseOverMenu (const FPoint& termpos) const
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline void FDialog::passEventToSubMenu ( const MouseStates& ms inline void FDialog::passEventToSubMenu ( const MouseStates& ms
, const FMouseEvent* ev ) , const FMouseEvent&& ev )
{ {
// Mouse event handover to the dialog menu // Mouse event handover to the dialog menu
if ( ! ms.mouse_over_menu if ( ! ms.mouse_over_menu
@ -1368,7 +1368,7 @@ inline void FDialog::passEventToSubMenu ( const MouseStates& ms
const auto& g = ms.termPos; const auto& g = ms.termPos;
const auto& p = dialog_menu->termToWidgetPos(g); const auto& p = dialog_menu->termToWidgetPos(g);
const int b = ev->getButton(); const int b = ev.getButton();
try try
{ {

View File

@ -30,10 +30,12 @@
#include <array> #include <array>
#include <string> #include <string>
#include "final/fapplication.h"
#include "final/fkeyboard.h" #include "final/fkeyboard.h"
#include "final/fkey_map.h" #include "final/fkey_map.h"
#include "final/fobject.h" #include "final/fobject.h"
#include "final/fterm.h" #include "final/fterm.h"
#include "final/ftermdetection.h"
#include "final/ftermios.h" #include "final/ftermios.h"
#if defined(__linux__) #if defined(__linux__)
@ -46,9 +48,7 @@ namespace finalcut
// static class attributes // static class attributes
uInt64 FKeyboard::read_blocking_time{100000}; // preset to 100 ms (10 Hz) uInt64 FKeyboard::read_blocking_time{100000}; // preset to 100 ms (10 Hz)
uInt64 FKeyboard::key_timeout{100000}; // preset to 100 ms (10 Hz) uInt64 FKeyboard::key_timeout{100000}; // preset to 100 ms (10 Hz)
uInt64 FKeyboard::interval_timeout{33333}; // preset to 33.333 ms (30 Hz)
struct timeval FKeyboard::time_keypressed{}; struct timeval FKeyboard::time_keypressed{};
struct timeval FKeyboard::time_last_request{};
#if defined(__linux__) #if defined(__linux__)
FTermLinux* FKeyboard::linux{nullptr}; FTermLinux* FKeyboard::linux{nullptr};
@ -66,14 +66,14 @@ FKeyboard::FKeyboard()
// Initialize keyboard values // Initialize keyboard values
time_keypressed.tv_sec = 0; time_keypressed.tv_sec = 0;
time_keypressed.tv_usec = 0; time_keypressed.tv_usec = 0;
time_last_request.tv_sec = 0;
time_last_request.tv_usec = 0;
// Get the stdin file status flags // Get the stdin file status flags
stdin_status_flags = fcntl(FTermios::getStdIn(), F_GETFL); stdin_status_flags = fcntl(FTermios::getStdIn(), F_GETFL);
if ( stdin_status_flags == -1 ) if ( stdin_status_flags == -1 )
std::abort(); std::abort();
term_detection = FTerm::getFTermDetection();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -148,9 +148,9 @@ bool& FKeyboard::hasUnprocessedInput()
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
bool FKeyboard::isKeyPressed ( uInt64 blocking_time) bool FKeyboard::isKeyPressed (uInt64 blocking_time)
{ {
if ( has_pending_input || ! isIntervalTimeout() ) if ( has_pending_input )
return false; return false;
fd_set ifds{}; fd_set ifds{};
@ -159,14 +159,26 @@ bool FKeyboard::isKeyPressed ( uInt64 blocking_time)
FD_ZERO(&ifds); FD_ZERO(&ifds);
FD_SET(stdin_no, &ifds); FD_SET(stdin_no, &ifds);
tv.tv_sec = 0; tv.tv_sec = tv.tv_usec = 0; // Non-blocking input
tv.tv_usec = suseconds_t(blocking_time); // preset to 100 ms
FObject::getCurrentTime (&time_last_request);
const int result = select (stdin_no + 1, &ifds, nullptr, nullptr, &tv);
has_pending_input = bool( result > 0 );
if ( has_pending_input && FD_ISSET(stdin_no, &ifds) ) if ( blocking_time > 0
&& term_detection->hasNonBlockingInputSupport()
&& select(stdin_no + 1, &ifds, nullptr, nullptr, &tv) > 0
&& FD_ISSET(stdin_no, &ifds) )
{
has_pending_input = true;
FD_CLR (stdin_no, &ifds); FD_CLR (stdin_no, &ifds);
tv.tv_sec = 0;
}
tv.tv_usec = suseconds_t(blocking_time); // preset to 100 ms
if ( ! has_pending_input
&& select(stdin_no + 1, &ifds, nullptr, nullptr, &tv) > 0
&& FD_ISSET(stdin_no, &ifds) )
{
has_pending_input = true;
}
return has_pending_input; return has_pending_input;
} }
@ -177,6 +189,7 @@ void FKeyboard::clearKeyBuffer()
// Empty the buffer // Empty the buffer
fifo_offset = 0; fifo_offset = 0;
fkey = 0;
key = 0; key = 0;
std::fill_n (fifo_buf, FIFO_BUF_SIZE, '\0'); std::fill_n (fifo_buf, FIFO_BUF_SIZE, '\0');
fifo_in_use = false; fifo_in_use = false;
@ -214,6 +227,30 @@ void FKeyboard::escapeKeyHandling()
substringKeyHandling(); substringKeyHandling();
} }
//----------------------------------------------------------------------
void FKeyboard::processQueuedInput()
{
while ( ! fkey_queue.empty() )
{
key = fkey_queue.front();
fkey_queue.pop();
if ( key > 0 )
{
keyPressed();
if ( FApplication::isQuit() )
return;
keyReleased();
if ( FApplication::isQuit() )
return;
key = 0;
}
}
}
// private methods of FKeyboard // private methods of FKeyboard
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -370,12 +407,6 @@ inline bool FKeyboard::isKeypressTimeout()
return FObject::isTimeout (&time_keypressed, key_timeout); return FObject::isTimeout (&time_keypressed, key_timeout);
} }
//----------------------------------------------------------------------
inline bool FKeyboard::isIntervalTimeout()
{
return FObject::isTimeout (&time_last_request, interval_timeout);
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
FKey FKeyboard::UTF8decode (const char utf8[]) const FKey FKeyboard::UTF8decode (const char utf8[]) const
{ {
@ -440,7 +471,8 @@ void FKeyboard::parseKeyBuffer()
ssize_t bytesread{}; ssize_t bytesread{};
FObject::getCurrentTime (&time_keypressed); FObject::getCurrentTime (&time_keypressed);
while ( (bytesread = readKey()) > 0 ) while ( fkey_queue.size() < MAX_QUEUE_SIZE
&& (bytesread = readKey()) > 0 )
{ {
has_pending_input = false; has_pending_input = false;
@ -454,27 +486,29 @@ void FKeyboard::parseKeyBuffer()
// Read the rest from the fifo buffer // Read the rest from the fifo buffer
while ( ! isKeypressTimeout() while ( ! isKeypressTimeout()
&& fifo_offset > 0 && fifo_offset > 0
&& key != fc::Fkey_incomplete ) && fkey != fc::Fkey_incomplete )
{ {
key = parseKeyString(); fkey = parseKeyString();
key = keyCorrection(key); fkey = keyCorrection(fkey);
if ( key != fc::Fkey_incomplete ) if ( fkey == fc::Fkey_mouse
keyPressed(); || fkey == fc::Fkey_extended_mouse
|| fkey == fc::Fkey_urxvt_mouse )
fifo_offset = int(std::strlen(fifo_buf)); {
key = fkey;
if ( key == fc::Fkey_mouse mouseTracking();
|| key == fc::Fkey_extended_mouse fifo_offset = int(std::strlen(fifo_buf));
|| key == fc::Fkey_urxvt_mouse )
break; break;
}
if ( fkey != fc::Fkey_incomplete )
{
fkey_queue.push(fkey);
fifo_offset = int(std::strlen(fifo_buf));
}
} }
// Send key up event fkey = 0;
if ( key > 0 )
keyReleased();
key = 0;
} }
read_character = 0; read_character = 0;
@ -545,14 +579,13 @@ void FKeyboard::substringKeyHandling()
unprocessed_buffer_data = false; unprocessed_buffer_data = false;
if ( fifo_buf[1] == 'O' ) if ( fifo_buf[1] == 'O' )
key = fc::Fmkey_O; fkey = fc::Fmkey_O;
else if ( fifo_buf[1] == '[' ) else if ( fifo_buf[1] == '[' )
key = fc::Fmkey_left_square_bracket; fkey = fc::Fmkey_left_square_bracket;
else else
key = fc::Fmkey_right_square_bracket; fkey = fc::Fmkey_right_square_bracket;
keyPressed(); fkey_queue.push(fkey);
keyReleased();
} }
} }
@ -574,4 +607,10 @@ void FKeyboard::escapeKeyPressed() const
escape_key_cmd.execute(); escape_key_cmd.execute();
} }
//----------------------------------------------------------------------
void FKeyboard::mouseTracking() const
{
mouse_tracking_cmd.execute();
}
} // namespace finalcut } // namespace finalcut

View File

@ -279,19 +279,19 @@ void FMenu::onMouseMove (FMouseEvent* ev)
if ( ms.mouse_over_submenu ) if ( ms.mouse_over_submenu )
{ {
passEventToSubMenu(*ev); // Event handover to sub-menu passEventToSubMenu(std::move(*ev)); // Event handover to sub-menu
return; return;
} }
if ( ! ms.mouse_over_menu && ms.mouse_over_supermenu ) if ( ! ms.mouse_over_menu && ms.mouse_over_supermenu )
{ {
passEventToSuperMenu(*ev); // Event handover to super-menu passEventToSuperMenu(std::move(*ev)); // Event handover to super-menu
return; return;
} }
if ( ms.mouse_over_menubar ) if ( ms.mouse_over_menubar )
{ {
passEventToMenuBar(*ev); // Event handover to the menu bar passEventToMenuBar(std::move(*ev)); // Event handover to the menu bar
return; return;
} }
@ -909,7 +909,7 @@ void FMenu::mouseMoveOverBorder (MouseStates& ms) const
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMenu::passEventToSubMenu (const FMouseEvent& ev) void FMenu::passEventToSubMenu (const FMouseEvent&& ev)
{ {
// Mouse event handover to sub-menu // Mouse event handover to sub-menu
@ -932,7 +932,7 @@ void FMenu::passEventToSubMenu (const FMouseEvent& ev)
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMenu::passEventToSuperMenu (const FMouseEvent& ev) void FMenu::passEventToSuperMenu (const FMouseEvent&& ev)
{ {
// Mouse event handover to super-menu // Mouse event handover to super-menu
@ -956,7 +956,7 @@ void FMenu::passEventToSuperMenu (const FMouseEvent& ev)
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMenu::passEventToMenuBar (const FMouseEvent& ev) const void FMenu::passEventToMenuBar (const FMouseEvent&& ev) const
{ {
// Mouse event handover to the menu bar // Mouse event handover to the menu bar

View File

@ -209,7 +209,7 @@ void FMenuBar::onMouseMove (FMouseEvent* ev)
// Handle menu entries // Handle menu entries
if ( mouse_down ) if ( mouse_down )
mouseMoveOverList(ev); mouseMoveOverList(std::move(*ev));
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -867,7 +867,7 @@ void FMenuBar::mouseUpOverList (const FMouseEvent* ev)
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMenuBar::mouseMoveOverList (const FMouseEvent* ev) void FMenuBar::mouseMoveOverList (const FMouseEvent&& ev)
{ {
auto list = getItemList(); auto list = getItemList();
@ -876,10 +876,10 @@ void FMenuBar::mouseMoveOverList (const FMouseEvent* ev)
focus_changed = false; focus_changed = false;
bool mouse_over_menubar{false}; bool mouse_over_menubar{false};
int mouse_x = ev->getX(); int mouse_x = ev.getX();
int mouse_y = ev->getY(); int mouse_y = ev.getY();
if ( getTermGeometry().contains(ev->getTermPos()) ) if ( getTermGeometry().contains(ev.getTermPos()) )
mouse_over_menubar = true; mouse_over_menubar = true;
for (auto&& item : list) for (auto&& item : list)
@ -904,7 +904,7 @@ void FMenuBar::mouseMoveOverList (const FMouseEvent* ev)
else else
{ {
// Event handover to the menu // Event handover to the menu
passEventToMenu(*ev); passEventToMenu(std::move(ev));
} }
} }
} }
@ -926,7 +926,7 @@ void FMenuBar::mouseMoveOverList (const FMouseEvent* ev)
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMenuBar::passEventToMenu (const FMouseEvent& ev) const void FMenuBar::passEventToMenu (const FMouseEvent&& ev) const
{ {
if ( ! hasSelectedItem() || ! getSelectedItem()->hasMenu() ) if ( ! hasSelectedItem() || ! getSelectedItem()->hasMenu() )
return; return;

View File

@ -28,6 +28,7 @@
#include <iostream> #include <iostream>
#include <new> #include <new>
#include "final/fapplication.h"
#include "final/fconfig.h" #include "final/fconfig.h"
#include "final/fkeyboard.h" #include "final/fkeyboard.h"
#include "final/fmouse.h" #include "final/fmouse.h"
@ -39,6 +40,136 @@
namespace finalcut namespace finalcut
{ {
//----------------------------------------------------------------------
// class FMouseData
//----------------------------------------------------------------------
// constructors and destructor
//----------------------------------------------------------------------
FMouseData::FMouseData()
{ }
//----------------------------------------------------------------------
FMouseData::~FMouseData()
{ }
// public methods of FMouseData
//----------------------------------------------------------------------
FString FMouseData::getClassName() const
{
return "FMouseData";
}
//----------------------------------------------------------------------
const FPoint& FMouseData::getPos() const
{
return mouse;
}
//----------------------------------------------------------------------
bool FMouseData::isLeftButtonPressed() const
{
return bool(getButtonState().left_button == Pressed);
}
//----------------------------------------------------------------------
bool FMouseData::isLeftButtonReleased() const
{
return bool(getButtonState().left_button == Released);
}
//----------------------------------------------------------------------
bool FMouseData::isLeftButtonDoubleClick() const
{
return bool(getButtonState().left_button == DoubleClick);
}
//----------------------------------------------------------------------
bool FMouseData::isRightButtonPressed() const
{
return bool(getButtonState().right_button == Pressed);
}
//----------------------------------------------------------------------
bool FMouseData::isRightButtonReleased() const
{
return bool(getButtonState().right_button == Released);
}
//----------------------------------------------------------------------
bool FMouseData::isMiddleButtonPressed() const
{
return bool(getButtonState().middle_button == Pressed);
}
//----------------------------------------------------------------------
bool FMouseData::isMiddleButtonReleased() const
{
return bool(getButtonState().middle_button == Released);
}
//----------------------------------------------------------------------
bool FMouseData::isShiftKeyPressed() const
{
return bool(getButtonState().shift_button);
}
//----------------------------------------------------------------------
bool FMouseData::isControlKeyPressed() const
{
return bool(getButtonState().control_button);
}
//----------------------------------------------------------------------
bool FMouseData::isMetaKeyPressed() const
{
return bool(getButtonState().meta_button);
}
//----------------------------------------------------------------------
bool FMouseData::isWheelUp() const
{
return bool(getButtonState().wheel_up);
}
//----------------------------------------------------------------------
bool FMouseData::isWheelDown() const
{
return bool(getButtonState().wheel_down);
}
//----------------------------------------------------------------------
bool FMouseData::isMoved() const
{
return bool(getButtonState().mouse_moved);
}
//----------------------------------------------------------------------
void FMouseData::clearButtonState()
{
// Fill bit field with 0
std::memset(&b_state, 0x00, sizeof(b_state));
}
// protected methods of FMouseData
//----------------------------------------------------------------------
inline FMouseData::FMouseButton& FMouseData::getButtonState()
{
return b_state;
}
//----------------------------------------------------------------------
inline const FMouseData::FMouseButton& FMouseData::getButtonState() const
{
return b_state;
}
//----------------------------------------------------------------------
void FMouseData::setPos (const FPoint& m)
{
mouse = m;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// class FMouse // class FMouse
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -51,6 +182,10 @@ FMouse::FMouse()
clearButtonState(); clearButtonState();
} }
//----------------------------------------------------------------------
FMouse::~FMouse() // destructor
{ }
// public methods of FMouse // public methods of FMouse
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -59,12 +194,6 @@ FString FMouse::getClassName() const
return "FMouse"; return "FMouse";
} }
//----------------------------------------------------------------------
inline const FPoint& FMouse::getPos() const
{
return mouse;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline void FMouse::clearEvent() inline void FMouse::clearEvent()
{ {
@ -95,104 +224,14 @@ inline bool FMouse::hasEvent() const
return mouse_event_occurred; return mouse_event_occurred;
} }
//----------------------------------------------------------------------
inline bool FMouse::isLeftButtonPressed()
{
return bool(getButtonState().left_button == Pressed);
}
//----------------------------------------------------------------------
inline bool FMouse::isLeftButtonReleased()
{
return bool(getButtonState().left_button == Released);
}
//----------------------------------------------------------------------
inline bool FMouse::isLeftButtonDoubleClick()
{
return bool(getButtonState().left_button == DoubleClick);
}
//----------------------------------------------------------------------
inline bool FMouse::isRightButtonPressed()
{
return bool(getButtonState().right_button == Pressed);
}
//----------------------------------------------------------------------
inline bool FMouse::isRightButtonReleased()
{
return bool(getButtonState().right_button == Released);
}
//----------------------------------------------------------------------
inline bool FMouse::isMiddleButtonPressed()
{
return bool(getButtonState().middle_button == Pressed);
}
//----------------------------------------------------------------------
inline bool FMouse::isMiddleButtonReleased()
{
return bool(getButtonState().middle_button == Released);
}
//----------------------------------------------------------------------
inline bool FMouse::isShiftKeyPressed()
{
return bool(getButtonState().shift_button);
}
//----------------------------------------------------------------------
inline bool FMouse::isControlKeyPressed()
{
return bool(getButtonState().control_button);
}
//----------------------------------------------------------------------
inline bool FMouse::isMetaKeyPressed()
{
return bool(getButtonState().meta_button);
}
//----------------------------------------------------------------------
inline bool FMouse::isWheelUp()
{
return bool(getButtonState().wheel_up);
}
//----------------------------------------------------------------------
inline bool FMouse::isWheelDown()
{
return bool(getButtonState().wheel_down);
}
//----------------------------------------------------------------------
inline bool FMouse::isMoved()
{
return bool(getButtonState().mouse_moved);
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FMouse::hasUnprocessedInput() const inline bool FMouse::hasUnprocessedInput() const
{ {
return unprocessed_buffer_data; return unprocessed_buffer_data;
} }
//----------------------------------------------------------------------
void FMouse::clearButtonState()
{
// Fill bit field with 0
std::memset(&b_state, 0x00, sizeof(b_state));
}
// protected methods of FMouse // protected methods of FMouse
//----------------------------------------------------------------------
inline FMouse::FMouseButton& FMouse::getButtonState()
{
return b_state;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline const FPoint& FMouse::getNewPos() const inline const FPoint& FMouse::getNewPos() const
{ {
@ -223,12 +262,6 @@ timeval* FMouse::getMousePressedTime()
return &time_mousepressed; return &time_mousepressed;
} }
//----------------------------------------------------------------------
void FMouse::setPos (const FPoint& m)
{
mouse = m;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMouse::setNewPos (int x, int y) void FMouse::setNewPos (int x, int y)
{ {
@ -1514,6 +1547,25 @@ void FMouseControl::setRawData ( FMouse::mouse_type mt
mouse->setRawData (fifo_buf); mouse->setRawData (fifo_buf);
} }
//----------------------------------------------------------------------
void FMouseControl::processQueuedInput()
{
while ( ! fmousedata_queue.empty() )
{
if ( FApplication::isQuit() )
return;
FMouseDataPtr md(std::move(fmousedata_queue.front()));
fmousedata_queue.pop();
if ( md.get() )
event_cmd.execute(*md);
if ( FApplication::isQuit() )
return;
}
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMouseControl::processEvent (struct timeval* time) void FMouseControl::processEvent (struct timeval* time)
{ {
@ -1522,7 +1574,10 @@ void FMouseControl::processEvent (struct timeval* time)
clearEvent(); clearEvent();
if ( mouse_object ) if ( mouse_object )
{
mouse_object->processEvent(time); mouse_object->processEvent(time);
fmousedata_queue.emplace(new FMouseData(std::move(*mouse_object)));
}
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

View File

@ -1512,7 +1512,7 @@ inline const wchar_t* FString::_extractToken ( wchar_t* rest[]
if ( ! token[0] ) if ( ! token[0] )
return nullptr; return nullptr;
*rest = std::wcspbrk(std::move(token), delim); *rest = std::wcspbrk(token, delim);
if ( *rest ) if ( *rest )
*(*rest)++ = '\0'; *(*rest)++ = '\0';

View File

@ -63,14 +63,21 @@
namespace finalcut namespace finalcut
{ {
// Global FTerm object namespace internal
static FTerm* init_term_object{nullptr}; {
// Global init state struct var
static bool term_initialized{false}; {
static FTerm* init_term_object; // Global FTerm object
static bool term_initialized; // Global init state
static uInt object_counter; // Counts the number of object instances
};
// Counts the number of object instances FTerm* var::init_term_object{nullptr};
static uInt object_counter{0}; bool var::term_initialized{false};
uInt var::object_counter{0};
} // namespace internal
// Static class attributes // Static class attributes
FTermData* FTerm::data {nullptr}; FTermData* FTerm::data {nullptr};
@ -107,21 +114,21 @@ FMouseControl* FTerm::mouse {nullptr};
//---------------------------------------------------------------------- //----------------------------------------------------------------------
FTerm::FTerm() FTerm::FTerm()
{ {
if ( object_counter == 0 ) if ( internal::var::object_counter == 0 )
allocationValues(); // Allocation of global objects allocationValues(); // Allocation of global objects
object_counter++; internal::var::object_counter++;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
FTerm::~FTerm() // destructor FTerm::~FTerm() // destructor
{ {
if ( init_term_object == this ) if ( internal::var::init_term_object == this )
finish(); // Resetting console settings finish(); // Resetting console settings
object_counter--; internal::var::object_counter--;
if ( object_counter == 0 ) if ( internal::var::object_counter == 0 )
{ {
printExitMessage(); printExitMessage();
deallocationValues(); // Deallocation of global objects deallocationValues(); // Deallocation of global objects
@ -588,7 +595,7 @@ bool FTerm::isNewFont()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
bool FTerm::isInitialized() bool FTerm::isInitialized()
{ {
return term_initialized; return internal::var::term_initialized;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -2271,7 +2278,7 @@ inline void FTerm::deallocationValues()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FTerm::init() void FTerm::init()
{ {
init_term_object = this; internal::var::init_term_object = this;
// Initialize global values for all objects // Initialize global values for all objects
init_global_values(); init_global_values();
@ -2359,7 +2366,7 @@ void FTerm::init()
FTermios::setRawMode(); FTermios::setRawMode();
// The terminal is now initialized // The terminal is now initialized
term_initialized = true; internal::var::term_initialized = true;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -2584,8 +2591,8 @@ void FTerm::terminalSizeChange()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FTerm::processTermination (int signum) void FTerm::processTermination (int signum)
{ {
if ( init_term_object ) if ( internal::var::init_term_object )
init_term_object->finish(); internal::var::init_term_object->finish();
std::fflush (stderr); std::fflush (stderr);
std::fflush (stdout); std::fflush (stdout);
@ -2599,8 +2606,8 @@ void FTerm::processTermination (int signum)
printExitMessage(); printExitMessage();
} }
if ( init_term_object ) if ( internal::var::init_term_object )
init_term_object->deallocationValues(); internal::var::init_term_object->deallocationValues();
std::terminate(); std::terminate();
} }

View File

@ -60,6 +60,7 @@ FKeyboard* FTermDetection::keyboard{nullptr};
char FTermDetection::termtype[256]{}; char FTermDetection::termtype[256]{};
char FTermDetection::ttytypename[256]{}; char FTermDetection::ttytypename[256]{};
bool FTermDetection::decscusr_support{}; bool FTermDetection::decscusr_support{};
bool FTermDetection::non_blocking_input_support{};
bool FTermDetection::terminal_detection{}; bool FTermDetection::terminal_detection{};
bool FTermDetection::color256{}; bool FTermDetection::color256{};
const FString* FTermDetection::answer_back{nullptr}; const FString* FTermDetection::answer_back{nullptr};
@ -83,6 +84,7 @@ FTermDetection::FTermDetection()
{ {
// Preset to true // Preset to true
terminal_detection = true; terminal_detection = true;
non_blocking_input_support = true;
// Preset to false // Preset to false
decscusr_support = false; decscusr_support = false;
@ -405,6 +407,13 @@ void FTermDetection::detectTerminal()
std::strncpy (termtype, new_termtype, sizeof(termtype)); std::strncpy (termtype, new_termtype, sizeof(termtype));
termtype[sizeof(termtype) - 1] = '\0'; termtype[sizeof(termtype) - 1] = '\0';
} }
#if defined(__CYGWIN__)
const auto& termfilename = fterm_data->getTermFileName();
if ( std::strncmp(termfilename, "/dev/cons", 9) == 0 )
non_blocking_input_support = false; // Fixes problem with mouse input
#endif
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

View File

@ -50,9 +50,6 @@
namespace finalcut namespace finalcut
{ {
// global FVTerm object
static FVTerm* init_object{nullptr};
// static class attributes // static class attributes
bool FVTerm::draw_completed{false}; bool FVTerm::draw_completed{false};
bool FVTerm::no_terminal_updates{false}; bool FVTerm::no_terminal_updates{false};
@ -67,6 +64,7 @@ uInt FVTerm::cursor_address_length{};
struct timeval FVTerm::last_term_size_check{}; struct timeval FVTerm::last_term_size_check{};
std::queue<int>* FVTerm::output_buffer{nullptr}; std::queue<int>* FVTerm::output_buffer{nullptr};
FPoint* FVTerm::term_pos{nullptr}; FPoint* FVTerm::term_pos{nullptr};
const FVTerm* FVTerm::init_object{nullptr};
FSystem* FVTerm::fsystem{nullptr}; FSystem* FVTerm::fsystem{nullptr};
FTerm* FVTerm::fterm{nullptr}; FTerm* FVTerm::fterm{nullptr};
FVTerm::FTermArea* FVTerm::vterm{nullptr}; FVTerm::FTermArea* FVTerm::vterm{nullptr};
@ -277,7 +275,6 @@ void FVTerm::updateTerminal() const
return; return;
} }
skipped_terminal_update = 0;
std::size_t changedlines = 0; std::size_t changedlines = 0;
static constexpr int check_interval = 5; static constexpr int check_interval = 5;
@ -296,7 +293,7 @@ void FVTerm::updateTerminal() const
} }
} }
skipped_terminal_update = 0;
vterm->has_changes = false; vterm->has_changes = false;
// sets the new input cursor position // sets the new input cursor position
@ -359,6 +356,7 @@ int FVTerm::print (FTermArea* area, const FString& s)
return -1; return -1;
std::vector<FChar> term_string{}; std::vector<FChar> term_string{};
term_string.reserve(s.getLength());
const wchar_t* p = s.wc_str(); const wchar_t* p = s.wc_str();
if ( p ) if ( p )
@ -373,7 +371,7 @@ int FVTerm::print (FTermArea* area, const FString& s)
nc.attr.byte[1] = next_attribute.attr.byte[1]; nc.attr.byte[1] = next_attribute.attr.byte[1];
nc.attr.byte[2] = 0; nc.attr.byte[2] = 0;
nc.attr.byte[3] = 0; nc.attr.byte[3] = 0;
term_string.push_back(nc); term_string.push_back(std::move(nc));
p++; p++;
} // end of while } // end of while
@ -2755,7 +2753,7 @@ bool FVTerm::updateTerminalLine (uInt y) const
{ {
// Updates pending changes from line y to the terminal // Updates pending changes from line y to the terminal
bool ret{}; bool ret{false};
const auto& vt = vterm; const auto& vt = vterm;
uInt& xmin = vt->changes[y].xmin; uInt& xmin = vt->changes[y].xmin;
uInt& xmax = vt->changes[y].xmax; uInt& xmax = vt->changes[y].xmax;
@ -2766,9 +2764,6 @@ bool FVTerm::updateTerminalLine (uInt y) const
bool draw_leading_ws = false; bool draw_leading_ws = false;
bool draw_trailing_ws = false; bool draw_trailing_ws = false;
const auto& ce = TCAP(fc::t_clr_eol); const auto& ce = TCAP(fc::t_clr_eol);
auto& first_char = vt->data[y * uInt(vt->width)];
auto& last_char = vt->data[(y + 1) * uInt(vt->width) - 1];
auto& min_char = vt->data[y * uInt(vt->width) + xmin];
// Clear rest of line // Clear rest of line
bool is_eol_clean = canClearToEOL (xmin, y); bool is_eol_clean = canClearToEOL (xmin, y);
@ -2786,6 +2781,7 @@ bool FVTerm::updateTerminalLine (uInt y) const
if ( is_eol_clean ) if ( is_eol_clean )
{ {
auto& min_char = vt->data[y * uInt(vt->width) + xmin];
appendAttributes (min_char); appendAttributes (min_char);
appendOutputBuffer (ce); appendOutputBuffer (ce);
markAsPrinted (xmin, uInt(vt->width - 1), y); markAsPrinted (xmin, uInt(vt->width - 1), y);
@ -2795,6 +2791,7 @@ bool FVTerm::updateTerminalLine (uInt y) const
if ( draw_leading_ws ) if ( draw_leading_ws )
{ {
const auto& cb = TCAP(fc::t_clr_bol); const auto& cb = TCAP(fc::t_clr_bol);
auto& first_char = vt->data[y * uInt(vt->width)];
appendAttributes (first_char); appendAttributes (first_char);
appendOutputBuffer (cb); appendOutputBuffer (cb);
markAsPrinted (0, xmin, y); markAsPrinted (0, xmin, y);
@ -2804,6 +2801,7 @@ bool FVTerm::updateTerminalLine (uInt y) const
if ( draw_trailing_ws ) if ( draw_trailing_ws )
{ {
auto& last_char = vt->data[(y + 1) * uInt(vt->width) - 1];
appendAttributes (last_char); appendAttributes (last_char);
appendOutputBuffer (ce); appendOutputBuffer (ce);
markAsPrinted (xmax + 1, uInt(vt->width - 1), y); markAsPrinted (xmax + 1, uInt(vt->width - 1), y);
@ -2814,8 +2812,6 @@ bool FVTerm::updateTerminalLine (uInt y) const
xmin = uInt(vt->width); xmin = uInt(vt->width);
xmax = 0; xmax = 0;
} }
else
ret = false;
cursorWrap(); cursorWrap();
return ret; return ret;

View File

@ -37,8 +37,17 @@
namespace finalcut namespace finalcut
{ {
// global FWidget object namespace internal
static FWidget* root_widget{nullptr}; {
struct var
{
static FWidget* root_widget; // global FWidget object
};
FWidget* var::root_widget{nullptr};
} // namespace internal
// static class attributes // static class attributes
FStatusBar* FWidget::statusbar{nullptr}; FStatusBar* FWidget::statusbar{nullptr};
@ -74,7 +83,7 @@ FWidget::FWidget (FWidget* parent)
if ( ! parent ) if ( ! parent )
{ {
if ( root_widget ) if ( internal::var::root_widget )
{ {
auto ftermdata = FTerm::getFTermData(); auto ftermdata = FTerm::getFTermData();
ftermdata->setExitMessage("FWidget: No parent defined! " ftermdata->setExitMessage("FWidget: No parent defined! "
@ -134,7 +143,7 @@ FWidget::~FWidget() // destructor
accelerator_list.clear(); accelerator_list.clear();
// finish the program // finish the program
if ( root_widget == this ) if ( internal::var::root_widget == this )
finish(); finish();
} }
@ -496,7 +505,7 @@ void FWidget::setTopPadding (int top, bool adjust)
{ {
if ( isRootWidget() ) if ( isRootWidget() )
{ {
auto r = root_widget; auto r = internal::var::root_widget;
r->wclient_offset.setY1 (r->padding.top); r->wclient_offset.setY1 (r->padding.top);
adjustSizeGlobal(); adjustSizeGlobal();
} }
@ -517,7 +526,7 @@ void FWidget::setLeftPadding (int left, bool adjust)
{ {
if ( isRootWidget() ) if ( isRootWidget() )
{ {
auto r = root_widget; auto r = internal::var::root_widget;
r->wclient_offset.setX1 (r->padding.left); r->wclient_offset.setX1 (r->padding.left);
adjustSizeGlobal(); adjustSizeGlobal();
} }
@ -538,7 +547,7 @@ void FWidget::setBottomPadding (int bottom, bool adjust)
{ {
if ( isRootWidget() ) if ( isRootWidget() )
{ {
auto r = root_widget; auto r = internal::var::root_widget;
r->wclient_offset.setY2 (int(r->getHeight()) - 1 - r->padding.bottom); r->wclient_offset.setY2 (int(r->getHeight()) - 1 - r->padding.bottom);
adjustSizeGlobal(); adjustSizeGlobal();
} }
@ -559,7 +568,7 @@ void FWidget::setRightPadding (int right, bool adjust)
{ {
if ( isRootWidget() ) if ( isRootWidget() )
{ {
auto r = root_widget; auto r = internal::var::root_widget;
r->wclient_offset.setX2 (int(r->getWidth()) - 1 - r->padding.right); r->wclient_offset.setX2 (int(r->getWidth()) - 1 - r->padding.right);
adjustSizeGlobal(); adjustSizeGlobal();
} }
@ -575,8 +584,8 @@ void FWidget::setTermSize (const FSize& size) const
if ( FTerm::isXTerminal() ) if ( FTerm::isXTerminal() )
{ {
root_widget->wsize.setRect(FPoint{1, 1}, size); internal::var::root_widget->wsize.setRect(FPoint{1, 1}, size);
root_widget->adjust_wsize = root_widget->wsize; internal::var::root_widget->adjust_wsize = internal::var::root_widget->wsize;
FTerm::setTermSize(size); // width = columns / height = lines FTerm::setTermSize(size); // width = columns / height = lines
detectTermSize(); detectTermSize();
} }
@ -944,8 +953,8 @@ void FWidget::show()
return; return;
// Initialize desktop on first call // Initialize desktop on first call
if ( ! init_desktop && root_widget ) if ( ! init_desktop && internal::var::root_widget )
root_widget->initDesktop(); internal::var::root_widget->initDesktop();
if ( ! show_root_widget ) if ( ! show_root_widget )
{ {
@ -1237,8 +1246,8 @@ void FWidget::initTerminal()
// Set default foreground and background color of the desktop/terminal // Set default foreground and background color of the desktop/terminal
auto color_theme = getColorTheme(); auto color_theme = getColorTheme();
root_widget->foreground_color = color_theme->term_fg; internal::var::root_widget->foreground_color = color_theme->term_fg;
root_widget->background_color = color_theme->term_bg; internal::var::root_widget->background_color = color_theme->term_bg;
resetColors(); resetColors();
// The terminal is now initialized // The terminal is now initialized
@ -1278,7 +1287,7 @@ void FWidget::adjustSize()
if ( ignore_padding && ! isDialogWidget() ) if ( ignore_padding && ! isDialogWidget() )
setTermOffset(); setTermOffset();
else else
woffset = root_widget->wclient_offset; woffset = internal::var::root_widget->wclient_offset;
} }
else if ( ignore_padding && p ) else if ( ignore_padding && p )
{ {
@ -1674,8 +1683,8 @@ void FWidget::onAccel (FAccelEvent*)
void FWidget::onResize (FResizeEvent* ev) void FWidget::onResize (FResizeEvent* ev)
{ {
// The terminal was resized // The terminal was resized
root_widget->resize(); internal::var::root_widget->resize();
root_widget->redraw(); internal::var::root_widget->redraw();
ev->accept(); ev->accept();
} }
@ -1733,11 +1742,11 @@ void FWidget::initRootWidget()
} }
// Initialize default widget colors // Initialize default widget colors
// (before terminal detection and root_widget is set) // (before terminal detection and internal::var::root_widget is set)
initColorTheme(); initColorTheme();
// Root widget basic initialization // Root widget basic initialization
root_widget = this; internal::var::root_widget = this;
show_root_widget = nullptr; show_root_widget = nullptr;
redraw_root_widget = nullptr; redraw_root_widget = nullptr;
modal_dialog_counter = 0; modal_dialog_counter = 0;
@ -2094,7 +2103,7 @@ void FWidget::setStatusbarText (bool enable) const
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void detectTermSize() void detectTermSize()
{ {
const auto& r = root_widget; const auto& r = internal::var::root_widget;
FTerm::detectTermSize(); FTerm::detectTermSize();
r->adjust_wsize.setRect (1, 1, r->getDesktopWidth(), r->getDesktopHeight()); r->adjust_wsize.setRect (1, 1, r->getDesktopWidth(), r->getDesktopHeight());
r->woffset.setRect (0, 0, r->getDesktopWidth(), r->getDesktopHeight()); r->woffset.setRect (0, 0, r->getDesktopWidth(), r->getDesktopHeight());

View File

@ -80,6 +80,7 @@ class FEvent;
class FFocusEvent; class FFocusEvent;
class FKeyEvent; class FKeyEvent;
class FLog; class FLog;
class FMouseData;
class FMouseEvent; class FMouseEvent;
class FStartOptions; class FStartOptions;
class FTimerEvent; class FTimerEvent;
@ -181,36 +182,47 @@ class FApplication : public FWidget
void keyPressed(); void keyPressed();
void keyReleased() const; void keyReleased() const;
void escapeKeyPressed() const; void escapeKeyPressed() const;
void mouseTracking();
void performKeyboardAction(); void performKeyboardAction();
void performMouseAction();
void mouseEvent (const FMouseData&);
void sendEscapeKeyPressEvent() const; void sendEscapeKeyPressEvent() const;
bool sendKeyDownEvent (FWidget*) const; bool sendKeyDownEvent (FWidget*) const;
bool sendKeyPressEvent (FWidget*) const; bool sendKeyPressEvent (FWidget*) const;
bool sendKeyUpEvent (FWidget*) const; bool sendKeyUpEvent (FWidget*) const;
void sendKeyboardAccelerator(); void sendKeyboardAccelerator();
bool hasDataInQueue() const;
void queuingKeyboardInput() const;
void queuingMouseInput() const;
void processKeyboardEvent() const; void processKeyboardEvent() const;
void processMouseEvent() const;
bool processDialogSwitchAccelerator() const; bool processDialogSwitchAccelerator() const;
bool processAccelerator (const FWidget&) const; bool processAccelerator (const FWidget&) const;
bool getMouseEvent() const; void determineClickedWidget (const FMouseData&);
FWidget*& determineClickedWidget();
void unsetMoveSizeMode() const; void unsetMoveSizeMode() const;
void closeDropDown() const; void closeDropDown (const FMouseData&) const;
void unselectMenubarItems() const; void unselectMenubarItems (const FMouseData&) const;
void sendMouseEvent() const; void sendMouseEvent (const FMouseData&) const;
void sendMouseMoveEvent ( const FPoint& void sendMouseMoveEvent ( const FMouseData&
, const FPoint&
, const FPoint& , const FPoint&
, int ) const; , int ) const;
void sendMouseLeftClickEvent ( const FPoint& void sendMouseLeftClickEvent ( const FMouseData&
, const FPoint&
, const FPoint& , const FPoint&
, int ) const; , int ) const;
void sendMouseRightClickEvent ( const FPoint& void sendMouseRightClickEvent ( const FMouseData&
, const FPoint&
, const FPoint& , const FPoint&
, int ) const; , int ) const;
void sendMouseMiddleClickEvent ( const FPoint& void sendMouseMiddleClickEvent ( const FMouseData&
, const FPoint&
, const FPoint& , const FPoint&
, int ) const; , int ) const;
void sendWheelEvent (const FPoint&, const FPoint&) const; void sendWheelEvent ( const FMouseData&
, const FPoint&
, const FPoint& ) const;
static FWidget* processParameters (const int&, char*[]); static FWidget* processParameters (const int&, char*[]);
void processMouseEvent();
void processResizeEvent() const; void processResizeEvent() const;
void processCloseWidget(); void processCloseWidget();
void processLogger() const; void processLogger() const;
@ -225,6 +237,7 @@ class FApplication : public FWidget
uInt64 key_timeout{100000}; // 100 ms uInt64 key_timeout{100000}; // 100 ms
uInt64 dblclick_interval{500000}; // 500 ms uInt64 dblclick_interval{500000}; // 500 ms
std::streambuf* default_clog_rdbuf{std::clog.rdbuf()}; std::streambuf* default_clog_rdbuf{std::clog.rdbuf()};
FWidget* clicked_widget{};
FEventQueue event_queue{}; FEventQueue event_queue{};
static uInt64 next_event_wait; static uInt64 next_event_wait;
static timeval time_last_event; static timeval time_last_event;

View File

@ -195,7 +195,7 @@ class FDialog : public FWindow
void pressZoomButton (const MouseStates&); void pressZoomButton (const MouseStates&);
bool isMouseOverMenu (const FPoint&) const; bool isMouseOverMenu (const FPoint&) const;
void passEventToSubMenu ( const MouseStates& void passEventToSubMenu ( const MouseStates&
, const FMouseEvent* ); , const FMouseEvent&& );
void moveSizeKey (FKeyEvent*); void moveSizeKey (FKeyEvent*);
void raiseActivateDialog(); void raiseActivateDialog();
void lowerActivateDialog(); void lowerActivateDialog();

View File

@ -40,6 +40,7 @@
#include <array> #include <array>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <queue>
#include "final/fkey_map.h" #include "final/fkey_map.h"
#include "final/fstring.h" #include "final/fstring.h"
@ -51,6 +52,7 @@ namespace finalcut
// class forward declaration // class forward declaration
class FApplication; class FApplication;
class FString; class FString;
class FTermDetection;
class FTermLinux; class FTermLinux;
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -127,9 +129,11 @@ class FKeyboard final
void setPressCommand (const FKeyboardCommand&); void setPressCommand (const FKeyboardCommand&);
void setReleaseCommand (const FKeyboardCommand&); void setReleaseCommand (const FKeyboardCommand&);
void setEscPressedCommand (const FKeyboardCommand&); void setEscPressedCommand (const FKeyboardCommand&);
void setMouseTrackingCommand (const FKeyboardCommand&);
// Inquiry // Inquiry
bool hasPendingInput() const; bool hasPendingInput() const;
bool hasDataInQueue() const;
// Methods // Methods
static void init(); static void init();
@ -139,6 +143,7 @@ class FKeyboard final
void clearKeyBufferOnTimeout(); void clearKeyBufferOnTimeout();
void fetchKeyCode(); void fetchKeyCode();
void escapeKeyHandling(); void escapeKeyHandling();
void processQueuedInput();
private: private:
// Using-declaration // Using-declaration
@ -146,6 +151,7 @@ class FKeyboard final
// Constants // Constants
static constexpr FKey NOT_SET = static_cast<FKey>(-1); static constexpr FKey NOT_SET = static_cast<FKey>(-1);
static constexpr std::size_t MAX_QUEUE_SIZE = 32;
// Accessors // Accessors
FKey getMouseProtocolKey() const; FKey getMouseProtocolKey() const;
@ -167,23 +173,26 @@ class FKeyboard final
void keyPressed() const; void keyPressed() const;
void keyReleased() const; void keyReleased() const;
void escapeKeyPressed() const; void escapeKeyPressed() const;
void mouseTracking() const;
// Data members // Data members
FKeyboardCommand keypressed_cmd{}; FKeyboardCommand keypressed_cmd{};
FKeyboardCommand keyreleased_cmd{}; FKeyboardCommand keyreleased_cmd{};
FKeyboardCommand escape_key_cmd{}; FKeyboardCommand escape_key_cmd{};
FKeyboardCommand mouse_tracking_cmd{};
#if defined(__linux__) #if defined(__linux__)
#undef linux #undef linux
static FTermLinux* linux; static FTermLinux* linux;
#endif #endif
FTermDetection* term_detection{nullptr};
static timeval time_keypressed; static timeval time_keypressed;
static timeval time_last_request;
static uInt64 read_blocking_time; static uInt64 read_blocking_time;
static uInt64 key_timeout; static uInt64 key_timeout;
static uInt64 interval_timeout;
FKeyMapPtr key_map{}; FKeyMapPtr key_map{};
std::queue<FKey> fkey_queue{};
FKey fkey{0};
FKey key{0}; FKey key{0};
uChar read_character{}; uChar read_character{};
char fifo_buf[FIFO_BUF_SIZE]{'\0'}; char fifo_buf[FIFO_BUF_SIZE]{'\0'};
@ -247,6 +256,10 @@ inline bool FKeyboard::unsetNonBlockingInput()
inline bool FKeyboard::hasPendingInput() const inline bool FKeyboard::hasPendingInput() const
{ return has_pending_input; } { return has_pending_input; }
//----------------------------------------------------------------------
inline bool FKeyboard::hasDataInQueue() const
{ return ! fkey_queue.empty(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline void FKeyboard::enableUTF8() inline void FKeyboard::enableUTF8()
{ utf8_input = true; } { utf8_input = true; }
@ -275,6 +288,10 @@ inline void FKeyboard::setReleaseCommand (const FKeyboardCommand& cmd)
inline void FKeyboard::setEscPressedCommand (const FKeyboardCommand& cmd) inline void FKeyboard::setEscPressedCommand (const FKeyboardCommand& cmd)
{ escape_key_cmd = cmd; } { escape_key_cmd = cmd; }
//----------------------------------------------------------------------
inline void FKeyboard::setMouseTrackingCommand (const FKeyboardCommand& cmd)
{ mouse_tracking_cmd = cmd; }
} // namespace finalcut } // namespace finalcut
#endif // FKEYBOARD_H #endif // FKEYBOARD_H

View File

@ -192,9 +192,9 @@ class FMenu : public FWindow, public FMenuList
void mouseMoveDeselection (FMenuItem*, MouseStates&); void mouseMoveDeselection (FMenuItem*, MouseStates&);
void mouseUpOverBorder(); void mouseUpOverBorder();
void mouseMoveOverBorder (MouseStates&) const; void mouseMoveOverBorder (MouseStates&) const;
void passEventToSubMenu (const FMouseEvent&); void passEventToSubMenu (const FMouseEvent&&);
void passEventToSuperMenu (const FMouseEvent&); void passEventToSuperMenu (const FMouseEvent&&);
void passEventToMenuBar (const FMouseEvent&) const; void passEventToMenuBar (const FMouseEvent&&) const;
bool containsMenuStructure (const FPoint&); bool containsMenuStructure (const FPoint&);
bool containsMenuStructure (int, int); bool containsMenuStructure (int, int);
FMenu* superMenuAt (const FPoint&); FMenu* superMenuAt (const FPoint&);

View File

@ -139,8 +139,8 @@ class FMenuBar : public FWindow, public FMenuList
void selectMenuItem (FMenuItem*); void selectMenuItem (FMenuItem*);
void mouseDownOverList (const FMouseEvent*); void mouseDownOverList (const FMouseEvent*);
void mouseUpOverList (const FMouseEvent*); void mouseUpOverList (const FMouseEvent*);
void mouseMoveOverList (const FMouseEvent*); void mouseMoveOverList (const FMouseEvent&&);
void passEventToMenu (const FMouseEvent&) const; void passEventToMenu (const FMouseEvent&&) const;
void leaveMenuBar(); void leaveMenuBar();
// Data members // Data members

View File

@ -23,6 +23,11 @@
/* Inheritance diagram /* Inheritance diagram
* *
* *
*
* FMouseData
*
*
*
* *
* FMouse * FMouse
* *
@ -61,7 +66,9 @@
#endif #endif
#include <cstddef> #include <cstddef>
#include <functional>
#include <map> #include <map>
#include <queue>
#include "final/fkeyboard.h" #include "final/fkeyboard.h"
#include "final/fpoint.h" #include "final/fpoint.h"
@ -78,63 +85,47 @@ namespace finalcut
{ {
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// class FMouse // class FMouseData
//---------------------------------------------------------------------- //----------------------------------------------------------------------
class FMouseData
class FMouse
{ {
public: public:
// Enumeration
enum mouse_type
{
none = 0,
gpm = 1,
x11 = 2,
sgr = 3,
urxvt = 4
};
// Constructor
FMouse();
// Destructor
virtual ~FMouse()
{ }
// Accessors // Accessors
virtual FString getClassName() const; virtual FString getClassName() const;
const FPoint& getPos() const; const FPoint& getPos() const;
void clearEvent();
// Mutators // Constructor
void setMaxWidth (uInt16); FMouseData();
void setMaxHeight (uInt16);
void setDblclickInterval (const uInt64); // Default copy constructor
FMouseData (const FMouseData&) = default;
// Default move constructor
FMouseData (FMouseData&&) = default;
// Default copy assignment operator (=)
FMouseData& operator = (const FMouseData&) = default;
// Default move assignment operator (=)
FMouseData& operator = (FMouseData&&) = default;
// Destructor
virtual ~FMouseData();
// Inquiries // Inquiries
virtual bool hasData() = 0; bool isLeftButtonPressed() const;
bool hasEvent() const; bool isLeftButtonReleased() const;
bool isLeftButtonPressed(); bool isLeftButtonDoubleClick() const;
bool isLeftButtonReleased(); bool isRightButtonPressed() const;
bool isLeftButtonDoubleClick(); bool isRightButtonReleased() const;
bool isRightButtonPressed(); bool isMiddleButtonPressed() const;
bool isRightButtonReleased(); bool isMiddleButtonReleased() const;
bool isMiddleButtonPressed(); bool isShiftKeyPressed() const;
bool isMiddleButtonReleased(); bool isControlKeyPressed() const;
bool isShiftKeyPressed(); bool isMetaKeyPressed() const;
bool isControlKeyPressed(); bool isWheelUp() const;
bool isMetaKeyPressed(); bool isWheelDown() const;
bool isWheelUp(); bool isMoved() const;
bool isWheelDown();
bool isMoved();
bool hasUnprocessedInput() const;
// Methods // Methods
template <typename ClassT>
static FMouse* createMouseObject ();
void clearButtonState(); void clearButtonState();
virtual void setRawData (FKeyboard::keybuffer&) = 0;
virtual void processEvent (struct timeval*) = 0;
protected: protected:
// Typedef and Enumerations // Typedef and Enumerations
@ -162,34 +153,88 @@ class FMouse
// Accessors // Accessors
FMouseButton& getButtonState(); FMouseButton& getButtonState();
const FPoint& getNewPos() const; const FMouseButton& getButtonState() const;
uInt16 getMaxWidth() const;
uInt16 getMaxHeight() const;
uInt64 getDblclickInterval() const;
timeval* getMousePressedTime();
// Mutator // Mutator
void setPos (const FPoint&); void setPos (const FPoint&);
void setNewPos (int, int);
void setPending (bool);
void setEvent();
void setMousePressedTime (const timeval*);
void resetMousePressedTime();
// Inquiry
bool isDblclickTimeout (const timeval*) const;
private: private:
// Data members // Data members
FMouseButton b_state{}; FMouseButton b_state{};
bool mouse_event_occurred{false}; FPoint mouse{0, 0}; // mouse click position
bool unprocessed_buffer_data{false}; };
uInt16 max_width{80};
uInt16 max_height{25};
uInt64 dblclick_interval{500000}; // 500 ms //----------------------------------------------------------------------
struct timeval time_mousepressed{}; // class FMouse
FPoint mouse{0, 0}; // mouse click position //----------------------------------------------------------------------
FPoint new_mouse_position{};
class FMouse : public FMouseData
{
public:
// Enumeration
enum mouse_type
{
none = 0,
gpm = 1,
x11 = 2,
sgr = 3,
urxvt = 4
};
// Constructor
FMouse();
// Destructor
~FMouse() override;
// Accessors
FString getClassName() const override;
void clearEvent();
// Mutators
void setMaxWidth (uInt16);
void setMaxHeight (uInt16);
void setDblclickInterval (const uInt64);
// Inquiries
virtual bool hasData() = 0;
bool hasEvent() const;
bool hasUnprocessedInput() const;
// Methods
template <typename ClassT>
static FMouse* createMouseObject ();
virtual void setRawData (FKeyboard::keybuffer&) = 0;
virtual void processEvent (struct timeval*) = 0;
protected:
// Accessors
const FPoint& getNewPos() const;
uInt16 getMaxWidth() const;
uInt16 getMaxHeight() const;
uInt64 getDblclickInterval() const;
timeval* getMousePressedTime();
// Mutator
void setNewPos (int, int);
void setPending (bool);
void setEvent();
void setMousePressedTime (const timeval*);
void resetMousePressedTime();
// Inquiry
bool isDblclickTimeout (const timeval*) const;
private:
// Data members
bool mouse_event_occurred{false};
bool unprocessed_buffer_data{false};
uInt16 max_width{80};
uInt16 max_height{25};
uInt64 dblclick_interval{500000}; // 500 ms
struct timeval time_mousepressed{};
FPoint new_mouse_position{};
}; };
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -446,6 +491,32 @@ class FMouseUrxvt final : public FMouse
}; };
//----------------------------------------------------------------------
// class FMouseCommand
//----------------------------------------------------------------------
class FMouseCommand final
{
public:
// Constructors
FMouseCommand () = default;
explicit FMouseCommand (const std::function<void(const FMouseData&)>& fn)
: handler(fn)
{ }
// Method
template <typename T>
void execute(T&& arg) const
{
handler(std::forward<T>(arg));
}
private:
// Data members
std::function<void(const FMouseData&)> handler{};
};
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// class FMouseControl // class FMouseControl
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -466,62 +537,68 @@ class FMouseControl
FMouseControl& operator = (const FMouseControl&) = delete; FMouseControl& operator = (const FMouseControl&) = delete;
// Accessors // Accessors
virtual FString getClassName() const; virtual FString getClassName() const;
const FPoint& getPos(); const FPoint& getPos();
void clearEvent(); void clearEvent();
// Mutators // Mutators
void setStdinNo (int); void setStdinNo (int);
void setMaxWidth (uInt16); void setMaxWidth (uInt16);
void setMaxHeight (uInt16); void setMaxHeight (uInt16);
void setDblclickInterval (const uInt64); void setDblclickInterval (const uInt64);
void useGpmMouse (bool = true); void setEventCommand (const FMouseCommand&);
void useXtermMouse (bool = true); void useGpmMouse (bool = true);
void useXtermMouse (bool = true);
// Inquiries // Inquiries
bool hasData(); bool hasData();
bool hasEvent(); bool hasEvent();
bool isLeftButtonPressed(); bool isLeftButtonPressed();
bool isLeftButtonReleased(); bool isLeftButtonReleased();
bool isLeftButtonDoubleClick(); bool isLeftButtonDoubleClick();
bool isRightButtonPressed(); bool isRightButtonPressed();
bool isRightButtonReleased(); bool isRightButtonReleased();
bool isMiddleButtonPressed(); bool isMiddleButtonPressed();
bool isMiddleButtonReleased(); bool isMiddleButtonReleased();
bool isShiftKeyPressed(); bool isShiftKeyPressed();
bool isControlKeyPressed(); bool isControlKeyPressed();
bool isMetaKeyPressed(); bool isMetaKeyPressed();
bool isWheelUp(); bool isWheelUp();
bool isWheelDown(); bool isWheelDown();
bool isMoved(); bool isMoved();
bool hasUnprocessedInput(); bool hasUnprocessedInput();
bool isGpmMouseEnabled(); bool hasDataInQueue() const;
bool isGpmMouseEnabled();
// Methods // Methods
void enable(); void enable();
void disable(); void disable();
virtual void setRawData ( FMouse::mouse_type virtual void setRawData ( FMouse::mouse_type
, FKeyboard::keybuffer& ); , FKeyboard::keybuffer& );
virtual void processEvent (struct timeval* time); virtual void processEvent (struct timeval* time);
bool getGpmKeyPressed (bool); void processQueuedInput();
void drawGpmPointer(); bool getGpmKeyPressed (bool);
void drawGpmPointer();
private: private:
// Typedef // Typedef
typedef std::map<FMouse::mouse_type, FMouse*> FMouseProtocol; typedef std::map<FMouse::mouse_type, FMouse*> FMouseProtocol;
typedef std::unique_ptr<FMouseData> FMouseDataPtr;
// Accessor // Accessor
FMouse* getMouseWithData(); FMouse* getMouseWithData();
FMouse* getMouseWithEvent(); FMouse* getMouseWithEvent();
void xtermMouse (bool) const; void xtermMouse (bool) const;
void enableXTermMouse() const; void enableXTermMouse() const;
void disableXTermMouse() const; void disableXTermMouse() const;
// Data member // Data member
FMouseProtocol mouse_protocol{}; FMouseProtocol mouse_protocol{};
FPoint zero_point{0, 0}; FMouseCommand event_cmd{};
bool use_gpm_mouse{false}; std::queue<FMouseDataPtr> fmousedata_queue{};
bool use_xterm_mouse{false}; FPoint zero_point{0, 0};
bool use_gpm_mouse{false};
bool use_xterm_mouse{false};
}; };
// FMouseControl inline functions // FMouseControl inline functions
@ -529,6 +606,14 @@ class FMouseControl
inline FString FMouseControl::getClassName() const inline FString FMouseControl::getClassName() const
{ return "FMouseControl"; } { return "FMouseControl"; }
//----------------------------------------------------------------------
inline void FMouseControl::setEventCommand (const FMouseCommand& cmd)
{ event_cmd = cmd; }
//----------------------------------------------------------------------
inline bool FMouseControl::hasDataInQueue() const
{ return ! fmousedata_queue.empty(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline void FMouseControl::enableXTermMouse() const inline void FMouseControl::enableXTermMouse() const
{ xtermMouse(true); } { xtermMouse(true); }

View File

@ -128,6 +128,7 @@ class FTermDetection final
static bool isMltermTerminal(); static bool isMltermTerminal();
static bool canDisplay256Colors(); static bool canDisplay256Colors();
static bool hasTerminalDetection(); static bool hasTerminalDetection();
static bool hasNonBlockingInputSupport();
static bool hasSetCursorStyleSupport(); static bool hasSetCursorStyleSupport();
// Mutators // Mutators
@ -203,6 +204,7 @@ class FTermDetection final
static char termtype[256]; static char termtype[256];
static char ttytypename[256]; static char ttytypename[256];
static bool decscusr_support; static bool decscusr_support;
static bool non_blocking_input_support;
static bool terminal_detection; static bool terminal_detection;
static bool color256; static bool color256;
static int gnome_terminal_id; static int gnome_terminal_id;
@ -277,6 +279,10 @@ inline const char* FTermDetection::getTermType_SecDA()
inline bool FTermDetection::canDisplay256Colors() inline bool FTermDetection::canDisplay256Colors()
{ return color256; } { return color256; }
//----------------------------------------------------------------------
inline bool FTermDetection::hasNonBlockingInputSupport()
{ return non_blocking_input_support; }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FTermDetection::hasSetCursorStyleSupport() inline bool FTermDetection::hasSetCursorStyleSupport()
{ return decscusr_support; } { return decscusr_support; }

View File

@ -427,6 +427,7 @@ class FVTerm
FTermArea* print_area{nullptr}; // print area for this object FTermArea* print_area{nullptr}; // print area for this object
FTermArea* child_print_area{nullptr}; // print area for children FTermArea* child_print_area{nullptr}; // print area for children
FTermArea* vwin{nullptr}; // virtual window FTermArea* vwin{nullptr}; // virtual window
static const FVTerm* init_object; // Global FVTerm object
static FSystem* fsystem; static FSystem* fsystem;
static FTerm* fterm; static FTerm* fterm;
static FTermArea* vterm; // virtual terminal static FTermArea* vterm; // virtual terminal

View File

@ -49,6 +49,24 @@ void check_c_string ( const char* s1
::CppUnit::Asserter::fail ("Strings are not equal", sourceLine); ::CppUnit::Asserter::fail ("Strings are not equal", sourceLine);
} }
namespace finalcut
{
namespace internal
{
struct var
{
// Global application object is need for FApplication::isQuit()
static FApplication* app_object;
};
FApplication* var::app_object {nullptr};
} // namespace internal
} // namespace finalcut
namespace test namespace test
{ {
@ -311,6 +329,7 @@ class FKeyboardTest : public CPPUNIT_NS::TestFixture
void keyPressed(); void keyPressed();
void keyReleased(); void keyReleased();
void escapeKeyPressed(); void escapeKeyPressed();
void mouseTracking();
// Data members // Data members
FKey key_pressed{0}; FKey key_pressed{0};
@ -2152,6 +2171,7 @@ void FKeyboardTest::metaKeyTest()
const struct timespec ms[]{{0, 100000000L}}; const struct timespec ms[]{{0, 100000000L}};
nanosleep (ms, NULL); nanosleep (ms, NULL);
keyboard->escapeKeyHandling(); keyboard->escapeKeyHandling();
keyboard->processQueuedInput();
std::cout << " - Key: " << keyboard->getKeyName(key_pressed) << std::endl; std::cout << " - Key: " << keyboard->getKeyName(key_pressed) << std::endl;
CPPUNIT_ASSERT ( key_pressed == finalcut::fc::Fmkey_O ); CPPUNIT_ASSERT ( key_pressed == finalcut::fc::Fmkey_O );
clear(); clear();
@ -2239,6 +2259,7 @@ void FKeyboardTest::metaKeyTest()
// Wait 100 ms - Substring keys needs a timeout // Wait 100 ms - Substring keys needs a timeout
nanosleep (ms, NULL); nanosleep (ms, NULL);
keyboard->escapeKeyHandling(); keyboard->escapeKeyHandling();
keyboard->processQueuedInput();
std::cout << " - Key: " << keyboard->getKeyName(key_pressed) << std::endl; std::cout << " - Key: " << keyboard->getKeyName(key_pressed) << std::endl;
CPPUNIT_ASSERT ( key_pressed == finalcut::fc::Fmkey_left_square_bracket ); CPPUNIT_ASSERT ( key_pressed == finalcut::fc::Fmkey_left_square_bracket );
clear(); clear();
@ -2256,6 +2277,7 @@ void FKeyboardTest::metaKeyTest()
// Wait 100 ms - Substring keys needs a timeout // Wait 100 ms - Substring keys needs a timeout
nanosleep (ms, NULL); nanosleep (ms, NULL);
keyboard->escapeKeyHandling(); keyboard->escapeKeyHandling();
keyboard->processQueuedInput();
std::cout << " - Key: " << keyboard->getKeyName(key_pressed) << std::endl; std::cout << " - Key: " << keyboard->getKeyName(key_pressed) << std::endl;
CPPUNIT_ASSERT ( key_pressed == finalcut::fc::Fmkey_right_square_bracket ); CPPUNIT_ASSERT ( key_pressed == finalcut::fc::Fmkey_right_square_bracket );
clear(); clear();
@ -2954,16 +2976,21 @@ void FKeyboardTest::unknownKeyTest()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FKeyboardTest::init() void FKeyboardTest::init()
{ {
finalcut::internal::var::app_object \
= reinterpret_cast<finalcut::FApplication*>(this); // Need for isQuit()
keyboard = new finalcut::FKeyboard(); keyboard = new finalcut::FKeyboard();
auto cmd1 = std::bind(&FKeyboardTest::keyPressed, this); auto cmd1 = std::bind(&FKeyboardTest::keyPressed, this);
auto cmd2 = std::bind(&FKeyboardTest::keyReleased, this); auto cmd2 = std::bind(&FKeyboardTest::keyReleased, this);
auto cmd3 = std::bind(&FKeyboardTest::escapeKeyPressed, this); auto cmd3 = std::bind(&FKeyboardTest::escapeKeyPressed, this);
auto cmd4 = std::bind(&FKeyboardTest::mouseTracking, this);
finalcut::FKeyboardCommand key_cmd1 (cmd1); finalcut::FKeyboardCommand key_cmd1 (cmd1);
finalcut::FKeyboardCommand key_cmd2 (cmd2); finalcut::FKeyboardCommand key_cmd2 (cmd2);
finalcut::FKeyboardCommand key_cmd3 (cmd3); finalcut::FKeyboardCommand key_cmd3 (cmd3);
finalcut::FKeyboardCommand key_cmd4 (cmd4);
keyboard->setPressCommand (key_cmd1); keyboard->setPressCommand (key_cmd1);
keyboard->setReleaseCommand (key_cmd2); keyboard->setReleaseCommand (key_cmd2);
keyboard->setEscPressedCommand (key_cmd3); keyboard->setEscPressedCommand (key_cmd3);
keyboard->setMouseTrackingCommand (key_cmd4);
keyboard->setKeypressTimeout (100000); // 100 ms keyboard->setKeypressTimeout (100000); // 100 ms
processInput(); processInput();
CPPUNIT_ASSERT ( key_pressed == 0 ); CPPUNIT_ASSERT ( key_pressed == 0 );
@ -3008,6 +3035,7 @@ void FKeyboardTest::processInput()
if ( keyboard->isKeyPressed() ) if ( keyboard->isKeyPressed() )
keyboard->fetchKeyCode(); keyboard->fetchKeyCode();
keyboard->processQueuedInput();
// Keyboard interval timeout 75 ms (= 75,000,000 ns) // Keyboard interval timeout 75 ms (= 75,000,000 ns)
const struct timespec ms[]{{0, 75000000L}}; const struct timespec ms[]{{0, 75000000L}};
nanosleep (ms, NULL); nanosleep (ms, NULL);
@ -3043,6 +3071,12 @@ void FKeyboardTest::escapeKeyPressed()
number_of_keys++; number_of_keys++;
} }
//----------------------------------------------------------------------
void FKeyboardTest::mouseTracking()
{
key_pressed = keyboard->getKey();
}
// Put the test suite in the registry // Put the test suite in the registry
CPPUNIT_TEST_SUITE_REGISTRATION (FKeyboardTest); CPPUNIT_TEST_SUITE_REGISTRATION (FKeyboardTest);