From 7d4de8e46f3ef505fd99b646a4053408739b003c Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Wed, 15 Apr 2020 23:17:42 +0200 Subject: [PATCH] Improved event handling code --- ChangeLog | 1 + examples/choice.cpp | 2 +- src/fapplication.cpp | 157 ++++++++++++++----------------- src/fobject.cpp | 2 +- src/fwidget.cpp | 5 +- src/include/final/fapplication.h | 34 +++---- src/include/final/fconfig.h | 4 +- src/include/final/fobject.h | 3 +- src/include/final/fwidget.h | 2 +- test/fobject-test.cpp | 4 +- 10 files changed, 103 insertions(+), 111 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7a4b99d3..7ae8c352 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 2020-04-15 Markus Gans * Better support of general arrow keys + * Improved event handling code 2020-04-13 Markus Gans * Several small code improvements diff --git a/examples/choice.cpp b/examples/choice.cpp index 31538948..08a1ac6a 100644 --- a/examples/choice.cpp +++ b/examples/choice.cpp @@ -130,7 +130,7 @@ int main (int argc, char* argv[]) // Scroll to the focused child element finalcut::FFocusEvent cfi (finalcut::fc::ChildFocusIn_Event); - finalcut::FApplication::queueEvent(&checkButtonGroup, &cfi); + app.queueEvent(&checkButtonGroup, &cfi); // Create a OK button finalcut::FButton ok("&OK", &dgl); diff --git a/src/fapplication.cpp b/src/fapplication.cpp index 706d3f3b..84249e9e 100644 --- a/src/fapplication.cpp +++ b/src/fapplication.cpp @@ -59,8 +59,6 @@ int FApplication::loop_level {0}; // event loop level int FApplication::quit_code {0}; bool FApplication::quit_now {false}; -FApplication::eventQueue* FApplication::event_queue{nullptr}; - //---------------------------------------------------------------------- // class FApplication @@ -100,10 +98,6 @@ FApplication::FApplication ( const int& _argc //---------------------------------------------------------------------- FApplication::~FApplication() // destructor { - if ( event_queue ) - delete event_queue; - - event_queue = nullptr; app_object = nullptr; } @@ -172,75 +166,27 @@ void FApplication::quit() } //---------------------------------------------------------------------- -bool FApplication::sendEvent ( const FObject* receiver - , const FEvent* event ) +bool FApplication::sendEvent (FObject* receiver, FEvent* event ) { if ( quit_now || app_exit_loop || ! receiver ) return false; - if ( receiver->isWidget() ) - { - const auto widget = static_cast(receiver); + if ( ! isEventProcessable (receiver, event) ) + return false; - if ( getModalDialogCounter() > 0 ) - { - const FWidget* window; - - if ( widget->isWindowWidget() ) - window = widget; - else - window = FWindow::getWindowWidget(widget); - - // block events for widgets in non modal windows - if ( window - && ! window->getFlags().modal - && ! window->isMenuWidget() ) - { - switch ( uInt(event->type()) ) - { - case fc::KeyPress_Event: - case fc::KeyUp_Event: - case fc::KeyDown_Event: - case fc::MouseDown_Event: - case fc::MouseUp_Event: - case fc::MouseDoubleClick_Event: - case fc::MouseWheel_Event: - case fc::MouseMove_Event: - case fc::FocusIn_Event: - case fc::FocusOut_Event: - case fc::ChildFocusIn_Event: - case fc::ChildFocusOut_Event: - case fc::Accelerator_Event: - return false; - - default: - break; - } - } - } - - // Throw away mouse events for disabled widgets - if ( event->type() >= fc::MouseDown_Event - && event->type() <= fc::MouseMove_Event - && ! widget->isEnabled() ) - return false; - } - - // Sends event event directly to receiver - auto r = const_cast(receiver); - return r->event(const_cast(event)); + // Sends the event event directly to receiver + return receiver->event(event); } //---------------------------------------------------------------------- -void FApplication::queueEvent ( const FObject* receiver - , const FEvent* event ) +void FApplication::queueEvent (FObject* receiver, FEvent* event) { if ( ! receiver ) return; // queue this event - eventPair send_event (receiver, std::make_shared(*event)); - event_queue->push_back(send_event); + eventPair send_event (receiver, std::make_shared(*event)); + event_queue.push_back(send_event); } //---------------------------------------------------------------------- @@ -248,9 +194,9 @@ void FApplication::sendQueuedEvents() { while ( eventInQueue() ) { - sendEvent( event_queue->front().first, - event_queue->front().second.get() ); - event_queue->pop_front(); + sendEvent( event_queue.front().first, + event_queue.front().second.get() ); + event_queue.pop_front(); } } @@ -258,7 +204,7 @@ void FApplication::sendQueuedEvents() bool FApplication::eventInQueue() { if ( app_object ) - return ( ! event_queue->empty() ); + return ( ! event_queue.empty() ); else return false; } @@ -273,13 +219,13 @@ bool FApplication::removeQueuedEvent (const FObject* receiver) return false; bool retval{false}; - auto iter = event_queue->begin(); + auto iter = event_queue.begin(); - while ( iter != event_queue->end() ) + while ( iter != event_queue.end() ) { if ( iter->first == receiver ) { - iter = event_queue->erase(iter); + iter = event_queue.erase(iter); retval = true; } else @@ -404,16 +350,6 @@ void FApplication::init (uInt64 key_time, uInt64 dblclick_time) // Set the default double click interval if ( mouse ) mouse->setDblclickInterval (dblclick_time); - - try - { - event_queue = new eventQueue; - } - catch (const std::bad_alloc& ex) - { - std::cerr << bad_alloc_str << ex.what() << std::endl; - std::abort(); - } } //---------------------------------------------------------------------- @@ -631,7 +567,7 @@ inline void FApplication::sendEscapeKeyPressEvent() } //---------------------------------------------------------------------- -inline bool FApplication::sendKeyDownEvent (const FWidget* widget) +inline bool FApplication::sendKeyDownEvent (FWidget* widget) { // Send key down event FKeyEvent k_down_ev (fc::KeyDown_Event, keyboard->getKey()); @@ -640,7 +576,7 @@ inline bool FApplication::sendKeyDownEvent (const FWidget* widget) } //---------------------------------------------------------------------- -inline bool FApplication::sendKeyPressEvent (const FWidget* widget) +inline bool FApplication::sendKeyPressEvent (FWidget* widget) { // Send key press event FKeyEvent k_press_ev (fc::KeyPress_Event, keyboard->getKey()); @@ -649,7 +585,7 @@ inline bool FApplication::sendKeyPressEvent (const FWidget* widget) } //---------------------------------------------------------------------- -inline bool FApplication::sendKeyUpEvent (const FWidget* widget) +inline bool FApplication::sendKeyUpEvent (FWidget* widget) { // Send key up event FKeyEvent k_up_ev (fc::KeyUp_Event, keyboard->getKey()); @@ -1180,10 +1116,63 @@ bool FApplication::processNextEvent() } //---------------------------------------------------------------------- -void FApplication::performTimerAction ( const FObject* receiver - , const FEvent* event ) +void FApplication::performTimerAction (FObject* receiver, FEvent* event) { sendEvent (receiver, event); } +//---------------------------------------------------------------------- +bool FApplication::isEventProcessable (FObject* receiver, FEvent* event ) +{ + if ( ! receiver->isWidget() ) // No restrictions for non-widgets + return true; + + const auto widget = static_cast(receiver); + + if ( getModalDialogCounter() > 0 ) + { + const FWidget* window; + + if ( widget->isWindowWidget() ) + window = widget; + else + window = FWindow::getWindowWidget(widget); + + // block events for widgets in non modal windows + if ( window + && ! window->getFlags().modal + && ! window->isMenuWidget() ) + { + switch ( uInt(event->type()) ) + { + case fc::KeyPress_Event: + case fc::KeyUp_Event: + case fc::KeyDown_Event: + case fc::MouseDown_Event: + case fc::MouseUp_Event: + case fc::MouseDoubleClick_Event: + case fc::MouseWheel_Event: + case fc::MouseMove_Event: + case fc::FocusIn_Event: + case fc::FocusOut_Event: + case fc::ChildFocusIn_Event: + case fc::ChildFocusOut_Event: + case fc::Accelerator_Event: + return false; + + default: + break; + } + } + } + + // Throw away mouse events for disabled widgets + if ( event->type() >= fc::MouseDown_Event + && event->type() <= fc::MouseMove_Event + && ! widget->isEnabled() ) + return false; + + return true; +} + } // namespace finalcut diff --git a/src/fobject.cpp b/src/fobject.cpp index 11d21338..64eeec48 100644 --- a/src/fobject.cpp +++ b/src/fobject.cpp @@ -427,7 +427,7 @@ uInt FObject::processTimerEvent() } //---------------------------------------------------------------------- -void FObject::performTimerAction (const FObject*, const FEvent*) +void FObject::performTimerAction (FObject*, FEvent*) { } } // namespace finalcut diff --git a/src/fwidget.cpp b/src/fwidget.cpp index c5590bcf..fd1a3c35 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -105,7 +105,8 @@ FWidget::~FWidget() // destructor { processDestroy(); delCallbacks(); - FApplication::removeQueuedEvent(this); + auto app_object = FApplication::getApplicationObject(); + app_object->removeQueuedEvent(this); // unset clicked widget if ( this == getClickedWidget() ) @@ -1888,7 +1889,7 @@ FWidget::FCallbackPtr FWidget::getCallbackPtr (FCallback cb_function) } //---------------------------------------------------------------------- -bool FWidget::changeFocus ( FWidget* follower, const FWidget* parent +bool FWidget::changeFocus ( FWidget* follower, FWidget* parent , fc::FocusTypes ft ) { FFocusEvent out (fc::FocusOut_Event); diff --git a/src/include/final/fapplication.h b/src/include/final/fapplication.h index 19233486..cbcb4439 100644 --- a/src/include/final/fapplication.h +++ b/src/include/final/fapplication.h @@ -116,17 +116,17 @@ class FApplication : public FWidget void exitLoop(); static void exit (int = 0); void quit(); - static bool sendEvent (const FObject*, const FEvent*); - static void queueEvent (const FObject*, const FEvent*); - static void sendQueuedEvents (); - static bool eventInQueue(); - static bool removeQueuedEvent (const FObject*); + static bool sendEvent (FObject*, FEvent*); + void queueEvent (FObject*, FEvent*); + void sendQueuedEvents (); + bool eventInQueue(); + bool removeQueuedEvent (const FObject*); static FWidget* processParameters (const int&, char*[]); static void showParameterUsage () #if defined(__clang__) || defined(__GNUC__) __attribute__((noreturn)) #endif - ; + ; static void closeConfirmationDialog (FWidget*, FCloseEvent*); // Callback method @@ -134,8 +134,8 @@ class FApplication : public FWidget private: // Typedefs - typedef std::pair > eventPair; - typedef std::deque eventQueue; + typedef std::pair > eventPair; + typedef std::deque FEventQueue; // Methods void init (uInt64, uInt64); @@ -148,9 +148,9 @@ class FApplication : public FWidget void escapeKeyPressed(); void performKeyboardAction(); void sendEscapeKeyPressEvent(); - bool sendKeyDownEvent (const FWidget*); - bool sendKeyPressEvent (const FWidget*); - bool sendKeyUpEvent (const FWidget*); + bool sendKeyDownEvent (FWidget*); + bool sendKeyPressEvent (FWidget*); + bool sendKeyUpEvent (FWidget*); void sendKeyboardAccelerator(); void processKeyboardEvent(); bool processDialogSwitchAccelerator(); @@ -178,20 +178,20 @@ class FApplication : public FWidget void processResizeEvent(); void processCloseWidget(); bool processNextEvent(); - void performTimerAction ( const FObject* - , const FEvent* ) override; + void performTimerAction (FObject*, FEvent*) override; + static bool isEventProcessable (FObject*, FEvent*); // Data members - int app_argc; - char** app_argv; + int app_argc{}; + char** app_argv{}; uInt64 key_timeout{100000}; // 100 ms uInt64 dblclick_interval{500000}; // 500 ms - static FMouseControl* mouse; - static eventQueue* event_queue; + FEventQueue event_queue{}; static int quit_code; static bool quit_now; static int loop_level; static bool process_timer_event; + static FMouseControl* mouse; static FKeyboard* keyboard; static FWidget* keyboard_widget; }; diff --git a/src/include/final/fconfig.h b/src/include/final/fconfig.h index 4f481ea5..71879cdb 100644 --- a/src/include/final/fconfig.h +++ b/src/include/final/fconfig.h @@ -50,7 +50,9 @@ #endif /* Define to 1 if GPM mouse is enabled */ -/* #undef HAVE_LIBGPM */ +#ifndef F_HAVE_LIBGPM +#define F_HAVE_LIBGPM 1 +#endif /* Define to 1 if you have the header file. */ #ifndef F_HAVE_LINUX_FB_H diff --git a/src/include/final/fobject.h b/src/include/final/fobject.h index f573b078..ff6ecf91 100644 --- a/src/include/final/fobject.h +++ b/src/include/final/fobject.h @@ -153,8 +153,7 @@ class FObject private: // Method - virtual void performTimerAction ( const FObject* - , const FEvent* ); + virtual void performTimerAction (FObject*, FEvent*); // Data members FObject* parent_obj{nullptr}; diff --git a/src/include/final/fwidget.h b/src/include/final/fwidget.h index f8ac6b8c..2e38244f 100644 --- a/src/include/final/fwidget.h +++ b/src/include/final/fwidget.h @@ -405,7 +405,7 @@ class FWidget : public FVTerm, public FObject void emitWheelCallback (const FWheelEvent*); void setWindowFocus (bool); FCallbackPtr getCallbackPtr (FCallback); - bool changeFocus (FWidget*, const FWidget*, fc::FocusTypes); + bool changeFocus (FWidget*, FWidget*, fc::FocusTypes); void processDestroy(); virtual void draw(); void drawWindows(); diff --git a/test/fobject-test.cpp b/test/fobject-test.cpp index 0ea337e0..832070f3 100644 --- a/test/fobject-test.cpp +++ b/test/fobject-test.cpp @@ -3,7 +3,7 @@ * * * This file is part of the Final Cut widget toolkit * * * -* Copyright 2018-2019 Markus Gans * +* Copyright 2018-2020 Markus Gans * * * * The Final Cut is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License * @@ -69,7 +69,7 @@ class FObject_protected : public finalcut::FObject return finalcut::FObject::isWidget(); } - virtual void performTimerAction (const FObject*, const finalcut::FEvent*) + virtual void performTimerAction (FObject*, finalcut::FEvent*) { std::cout << "."; fflush(stdout);