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>
* Better support of general arrow keys
* Improved event handling code
2020-04-13 Markus Gans <guru.mail@muenster.de>
* Several small code improvements

View File

@ -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);

View File

@ -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<const FWidget*>(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<FObject*>(receiver);
return r->event(const_cast<FEvent*>(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<const FEvent>(*event));
event_queue->push_back(send_event);
eventPair send_event (receiver, std::make_shared<FEvent>(*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<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

View File

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

View File

@ -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);

View File

@ -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<const FObject*, std::shared_ptr<const FEvent> > eventPair;
typedef std::deque<eventPair> eventQueue;
typedef std::pair<FObject*, std::shared_ptr<FEvent> > eventPair;
typedef std::deque<eventPair> 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;
};

View File

@ -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 <linux/fb.h> header file. */
#ifndef F_HAVE_LINUX_FB_H

View File

@ -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};

View File

@ -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();

View File

@ -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);