Improved event handling code

This commit is contained in:
Markus Gans 2020-04-15 23:17:42 +02:00
parent 62b4a68277
commit 7d4de8e46f
10 changed files with 103 additions and 111 deletions

View File

@ -1,5 +1,6 @@
2020-04-15 Markus Gans <guru.mail@muenster.de> 2020-04-15 Markus Gans <guru.mail@muenster.de>
* Better support of general arrow keys * Better support of general arrow keys
* Improved event handling code
2020-04-13 Markus Gans <guru.mail@muenster.de> 2020-04-13 Markus Gans <guru.mail@muenster.de>
* Several small code improvements * Several small code improvements

View File

@ -130,7 +130,7 @@ int main (int argc, char* argv[])
// Scroll to the focused child element // Scroll to the focused child element
finalcut::FFocusEvent cfi (finalcut::fc::ChildFocusIn_Event); finalcut::FFocusEvent cfi (finalcut::fc::ChildFocusIn_Event);
finalcut::FApplication::queueEvent(&checkButtonGroup, &cfi); app.queueEvent(&checkButtonGroup, &cfi);
// Create a OK button // Create a OK button
finalcut::FButton ok("&OK", &dgl); finalcut::FButton ok("&OK", &dgl);

View File

@ -59,8 +59,6 @@ int FApplication::loop_level {0}; // event loop level
int FApplication::quit_code {0}; int FApplication::quit_code {0};
bool FApplication::quit_now {false}; bool FApplication::quit_now {false};
FApplication::eventQueue* FApplication::event_queue{nullptr};
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// class FApplication // class FApplication
@ -100,10 +98,6 @@ FApplication::FApplication ( const int& _argc
//---------------------------------------------------------------------- //----------------------------------------------------------------------
FApplication::~FApplication() // destructor FApplication::~FApplication() // destructor
{ {
if ( event_queue )
delete event_queue;
event_queue = nullptr;
app_object = nullptr; app_object = nullptr;
} }
@ -172,75 +166,27 @@ void FApplication::quit()
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
bool FApplication::sendEvent ( const FObject* receiver bool FApplication::sendEvent (FObject* receiver, FEvent* event )
, const FEvent* event )
{ {
if ( quit_now || app_exit_loop || ! receiver ) if ( quit_now || app_exit_loop || ! receiver )
return false; return false;
if ( receiver->isWidget() ) if ( ! isEventProcessable (receiver, event) )
{ return false;
const auto widget = static_cast<const FWidget*>(receiver);
if ( getModalDialogCounter() > 0 ) // Sends the event event directly to receiver
{ return receiver->event(event);
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<FObject*>(receiver);
return r->event(const_cast<FEvent*>(event));
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::queueEvent ( const FObject* receiver void FApplication::queueEvent (FObject* receiver, FEvent* event)
, const FEvent* event )
{ {
if ( ! receiver ) if ( ! receiver )
return; return;
// queue this event // queue this event
eventPair send_event (receiver, std::make_shared<const FEvent>(*event)); eventPair send_event (receiver, std::make_shared<FEvent>(*event));
event_queue->push_back(send_event); event_queue.push_back(send_event);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -248,9 +194,9 @@ void FApplication::sendQueuedEvents()
{ {
while ( eventInQueue() ) while ( eventInQueue() )
{ {
sendEvent( event_queue->front().first, sendEvent( event_queue.front().first,
event_queue->front().second.get() ); event_queue.front().second.get() );
event_queue->pop_front(); event_queue.pop_front();
} }
} }
@ -258,7 +204,7 @@ void FApplication::sendQueuedEvents()
bool FApplication::eventInQueue() bool FApplication::eventInQueue()
{ {
if ( app_object ) if ( app_object )
return ( ! event_queue->empty() ); return ( ! event_queue.empty() );
else else
return false; return false;
} }
@ -273,13 +219,13 @@ bool FApplication::removeQueuedEvent (const FObject* receiver)
return false; return false;
bool retval{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 ) if ( iter->first == receiver )
{ {
iter = event_queue->erase(iter); iter = event_queue.erase(iter);
retval = true; retval = true;
} }
else else
@ -404,16 +350,6 @@ void FApplication::init (uInt64 key_time, uInt64 dblclick_time)
// Set the default double click interval // Set the default double click interval
if ( mouse ) if ( mouse )
mouse->setDblclickInterval (dblclick_time); 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 // Send key down event
FKeyEvent k_down_ev (fc::KeyDown_Event, keyboard->getKey()); 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 // Send key press event
FKeyEvent k_press_ev (fc::KeyPress_Event, keyboard->getKey()); 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 // Send key up event
FKeyEvent k_up_ev (fc::KeyUp_Event, keyboard->getKey()); FKeyEvent k_up_ev (fc::KeyUp_Event, keyboard->getKey());
@ -1180,10 +1116,63 @@ bool FApplication::processNextEvent()
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::performTimerAction ( const FObject* receiver void FApplication::performTimerAction (FObject* receiver, FEvent* event)
, const FEvent* event )
{ {
sendEvent (receiver, 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<const FWidget*>(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 } // namespace finalcut

View File

@ -427,7 +427,7 @@ uInt FObject::processTimerEvent()
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FObject::performTimerAction (const FObject*, const FEvent*) void FObject::performTimerAction (FObject*, FEvent*)
{ } { }
} // namespace finalcut } // namespace finalcut

View File

@ -105,7 +105,8 @@ FWidget::~FWidget() // destructor
{ {
processDestroy(); processDestroy();
delCallbacks(); delCallbacks();
FApplication::removeQueuedEvent(this); auto app_object = FApplication::getApplicationObject();
app_object->removeQueuedEvent(this);
// unset clicked widget // unset clicked widget
if ( this == getClickedWidget() ) 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 ) , fc::FocusTypes ft )
{ {
FFocusEvent out (fc::FocusOut_Event); FFocusEvent out (fc::FocusOut_Event);

View File

@ -116,17 +116,17 @@ class FApplication : public FWidget
void exitLoop(); void exitLoop();
static void exit (int = 0); static void exit (int = 0);
void quit(); void quit();
static bool sendEvent (const FObject*, const FEvent*); static bool sendEvent (FObject*, FEvent*);
static void queueEvent (const FObject*, const FEvent*); void queueEvent (FObject*, FEvent*);
static void sendQueuedEvents (); void sendQueuedEvents ();
static bool eventInQueue(); bool eventInQueue();
static bool removeQueuedEvent (const FObject*); bool removeQueuedEvent (const FObject*);
static FWidget* processParameters (const int&, char*[]); static FWidget* processParameters (const int&, char*[]);
static void showParameterUsage () static void showParameterUsage ()
#if defined(__clang__) || defined(__GNUC__) #if defined(__clang__) || defined(__GNUC__)
__attribute__((noreturn)) __attribute__((noreturn))
#endif #endif
; ;
static void closeConfirmationDialog (FWidget*, FCloseEvent*); static void closeConfirmationDialog (FWidget*, FCloseEvent*);
// Callback method // Callback method
@ -134,8 +134,8 @@ class FApplication : public FWidget
private: private:
// Typedefs // Typedefs
typedef std::pair<const FObject*, std::shared_ptr<const FEvent> > eventPair; typedef std::pair<FObject*, std::shared_ptr<FEvent> > eventPair;
typedef std::deque<eventPair> eventQueue; typedef std::deque<eventPair> FEventQueue;
// Methods // Methods
void init (uInt64, uInt64); void init (uInt64, uInt64);
@ -148,9 +148,9 @@ class FApplication : public FWidget
void escapeKeyPressed(); void escapeKeyPressed();
void performKeyboardAction(); void performKeyboardAction();
void sendEscapeKeyPressEvent(); void sendEscapeKeyPressEvent();
bool sendKeyDownEvent (const FWidget*); bool sendKeyDownEvent (FWidget*);
bool sendKeyPressEvent (const FWidget*); bool sendKeyPressEvent (FWidget*);
bool sendKeyUpEvent (const FWidget*); bool sendKeyUpEvent (FWidget*);
void sendKeyboardAccelerator(); void sendKeyboardAccelerator();
void processKeyboardEvent(); void processKeyboardEvent();
bool processDialogSwitchAccelerator(); bool processDialogSwitchAccelerator();
@ -178,20 +178,20 @@ class FApplication : public FWidget
void processResizeEvent(); void processResizeEvent();
void processCloseWidget(); void processCloseWidget();
bool processNextEvent(); bool processNextEvent();
void performTimerAction ( const FObject* void performTimerAction (FObject*, FEvent*) override;
, const FEvent* ) override; static bool isEventProcessable (FObject*, FEvent*);
// Data members // Data members
int app_argc; int app_argc{};
char** app_argv; char** app_argv{};
uInt64 key_timeout{100000}; // 100 ms uInt64 key_timeout{100000}; // 100 ms
uInt64 dblclick_interval{500000}; // 500 ms uInt64 dblclick_interval{500000}; // 500 ms
static FMouseControl* mouse; FEventQueue event_queue{};
static eventQueue* event_queue;
static int quit_code; static int quit_code;
static bool quit_now; static bool quit_now;
static int loop_level; static int loop_level;
static bool process_timer_event; static bool process_timer_event;
static FMouseControl* mouse;
static FKeyboard* keyboard; static FKeyboard* keyboard;
static FWidget* keyboard_widget; static FWidget* keyboard_widget;
}; };

View File

@ -50,7 +50,9 @@
#endif #endif
/* Define to 1 if GPM mouse is enabled */ /* 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 <linux/fb.h> header file. */ /* Define to 1 if you have the <linux/fb.h> header file. */
#ifndef F_HAVE_LINUX_FB_H #ifndef F_HAVE_LINUX_FB_H

View File

@ -153,8 +153,7 @@ class FObject
private: private:
// Method // Method
virtual void performTimerAction ( const FObject* virtual void performTimerAction (FObject*, FEvent*);
, const FEvent* );
// Data members // Data members
FObject* parent_obj{nullptr}; FObject* parent_obj{nullptr};

View File

@ -405,7 +405,7 @@ class FWidget : public FVTerm, public FObject
void emitWheelCallback (const FWheelEvent*); void emitWheelCallback (const FWheelEvent*);
void setWindowFocus (bool); void setWindowFocus (bool);
FCallbackPtr getCallbackPtr (FCallback); FCallbackPtr getCallbackPtr (FCallback);
bool changeFocus (FWidget*, const FWidget*, fc::FocusTypes); bool changeFocus (FWidget*, FWidget*, fc::FocusTypes);
void processDestroy(); void processDestroy();
virtual void draw(); virtual void draw();
void drawWindows(); void drawWindows();

View File

@ -3,7 +3,7 @@
* * * *
* This file is part of the Final Cut widget toolkit * * 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 * * The Final Cut is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public License * * 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(); return finalcut::FObject::isWidget();
} }
virtual void performTimerAction (const FObject*, const finalcut::FEvent*) virtual void performTimerAction (FObject*, finalcut::FEvent*)
{ {
std::cout << "."; std::cout << ".";
fflush(stdout); fflush(stdout);