From 7eb6bfa587b632721d8b8544a3e615d108d26e56 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Sun, 28 Jan 2018 19:54:52 +0100 Subject: [PATCH] Refactoring FApplication::processKeyboardEvent --- ChangeLog | 5 + build.sh | 4 +- examples/windows.cpp | 193 ++++++++++++++----------- include/final/fapplication.h | 5 +- include/final/fmouse.h | 1 + src/fapplication.cpp | 270 ++++++++++++++++------------------- 6 files changed, 245 insertions(+), 233 deletions(-) diff --git a/ChangeLog b/ChangeLog index d2adf2db..84950070 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2017-01-28 Markus Gans + * Refactoring FApplication::processKeyboardEvent + * Shorter methods and a fix for recreating new windows + in the window example + 2017-01-25 Markus Gans * UTF-8 fix for Solaris diff --git a/build.sh b/build.sh index 15ccf650..d97e8b9e 100755 --- a/build.sh +++ b/build.sh @@ -101,9 +101,9 @@ fi if $MAKE then - echo "${GREEN}Successful compiled${NORMAL}" + printf '%bSuccessful compiled%b\n' "${GREEN}" "${NORMAL}" else - echo "${RED}Error on compile!${NORMAL}" 1>&2 + printf '%bError on compile!%b\n' "${RED}" "${NORMAL}" 1>&2 exit 1 fi diff --git a/examples/windows.cpp b/examples/windows.cpp index 3fc1f978..f5de2e6c 100644 --- a/examples/windows.cpp +++ b/examples/windows.cpp @@ -3,7 +3,7 @@ * * * This file is part of the Final Cut widget toolkit * * * -* Copyright 2016-2017 Markus Gans * +* Copyright 2016-2018 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 * @@ -117,9 +117,6 @@ SmallWindow::~SmallWindow() { // Remove own timer delOwnTimer(); - - // Remove all callbacks before Window::cb_destroyWindow() will be called - delCallbacks(); } //---------------------------------------------------------------------- @@ -183,7 +180,9 @@ class Window : public FDialog ~Window(); private: - // Typedef + // Typedefs + typedef void (Window::*WindowCallback)(FWidget*, data_ptr); + typedef void (FApplication::*FAppCallback)(FWidget*, data_ptr); typedef struct { bool is_open; @@ -199,8 +198,12 @@ class Window : public FDialog Window& operator = (const Window&); // Method + void createFileMenuItems (FMenu*); + void createDialogButtons(); void activateWindow (FDialog*); void adjustSize(); + void addClickedCallback (FWidget*, WindowCallback); + void addClickedCallback (FWidget*, FAppCallback); // Event handlers void onClose (FCloseEvent*); @@ -222,20 +225,68 @@ Window::Window (FWidget* parent) : FDialog(parent) , windows() { + FMenu* File; + FDialogListMenu* DglList; FString drop_down_symbol; - // menu bar - FMenuBar* Menubar = new FMenuBar (this); + FMenuBar* Menubar; + FStatusBar* statusbar; - // menu bar item - FMenu* File = new FMenu ("&File", Menubar); + // Menu bar + Menubar = new FMenuBar (this); + + // Menu bar item + File = new FMenu ("&File", Menubar); File->setStatusbarMessage ("File management commands"); - // dialog list menu item + // Dialog list menu item drop_down_symbol = wchar_t(fc::BlackDownPointingTriangle); - - FDialogListMenu* DglList = new FDialogListMenu (drop_down_symbol, Menubar); + DglList = new FDialogListMenu (drop_down_symbol, Menubar); DglList->setStatusbarMessage ("List of all the active dialogs"); + // File menu items + createFileMenuItems (File); + + // Dialog buttons + createDialogButtons(); + + // Statusbar at the bottom + statusbar = new FStatusBar (this); + statusbar->setMessage("Status bar message"); + + // Generate data vector for the windows + for (int n = 1; n <= 6; n++) + { + win_data* win_dat = new win_data; + win_dat->is_open = false; + win_dat->title = new FString(); + win_dat->title->sprintf("Window %d", n); + windows.push_back(win_dat); + } +} + +//---------------------------------------------------------------------- +Window::~Window() +{ + std::vector::iterator iter; + iter = windows.begin(); + + while ( iter != windows.end() ) + { + win_data* win_dat = *iter; + + // Remove all callbacks before Window::cb_destroyWindow() will be called + if ( win_dat->is_open && win_dat->dgl ) + win_dat->dgl->delCallbacks(); + + delete win_dat->title; + delete win_dat; + iter = windows.erase(iter); + } +} + +//---------------------------------------------------------------------- +void Window::createFileMenuItems (FMenu* File) +{ // "File" menu item FMenuItem* New = new FMenuItem ("&New", File); New->setStatusbarMessage ("Create the windows"); @@ -261,11 +312,18 @@ Window::Window (FWidget* parent) Quit->addAccelerator (fc::Fmkey_x); // Meta/Alt + X Quit->setStatusbarMessage ("Exit the program"); - // Statusbar at the bottom - FStatusBar* statusbar = new FStatusBar (this); - statusbar->setMessage("Status bar message"); + // Add menu item callback + addClickedCallback (New, &Window::cb_createWindows); + addClickedCallback (Close, &Window::cb_closeWindows); + addClickedCallback (Next, &Window::cb_next); + addClickedCallback (Previous, &Window::cb_previous); + addClickedCallback (Quit, &FApplication::cb_exitApp); +} - // Buttons +//---------------------------------------------------------------------- +void Window::createDialogButtons() +{ + // Dialog buttons FButton* CreateButton = new FButton (this); CreateButton->setGeometry(2, 2, 9, 1); CreateButton->setText (L"&Create"); @@ -278,78 +336,10 @@ Window::Window (FWidget* parent) QuitButton->setGeometry(28, 2, 9, 1); QuitButton->setText (L"&Quit"); - // Add menu item callback - New->addCallback - ( - "clicked", - F_METHOD_CALLBACK (this, &Window::cb_createWindows) - ); - - Close->addCallback - ( - "clicked", - F_METHOD_CALLBACK (this, &Window::cb_closeWindows) - ); - - Next->addCallback - ( - "clicked", - F_METHOD_CALLBACK (this, &Window::cb_next) - ); - - Previous->addCallback - ( - "clicked", - F_METHOD_CALLBACK (this, &Window::cb_previous) - ); - - Quit->addCallback - ( - "clicked", - F_METHOD_CALLBACK (this, &FApplication::cb_exitApp) - ); - // Add button callback - CreateButton->addCallback - ( - "clicked", - F_METHOD_CALLBACK (this, &Window::cb_createWindows) - ); - - CloseButton->addCallback - ( - "clicked", - F_METHOD_CALLBACK (this, &Window::cb_closeWindows) - ); - - QuitButton->addCallback - ( - "clicked", - F_METHOD_CALLBACK (this, &FApplication::cb_exitApp) - ); - - for (int n = 1; n <= 6; n++) - { - win_data* win_dat = new win_data; - win_dat->is_open = false; - win_dat->title = new FString(); - win_dat->title->sprintf("Window %d", n); - windows.push_back(win_dat); - } -} - -//---------------------------------------------------------------------- -Window::~Window() -{ - std::vector::iterator iter; - iter = windows.begin(); - - while ( iter != windows.end() ) - { - delete (*iter)->title; - delete *iter; - iter = windows.erase(iter); - } + addClickedCallback (CreateButton, &Window::cb_createWindows); + addClickedCallback (CloseButton, &Window::cb_closeWindows); + addClickedCallback (QuitButton, &FApplication::cb_exitApp); } //---------------------------------------------------------------------- @@ -400,6 +390,32 @@ void Window::adjustSize() FDialog::adjustSize(); } +//---------------------------------------------------------------------- +void Window::addClickedCallback (FWidget* widget, WindowCallback call) +{ + FMemberCallback callback + = reinterpret_cast(call); + + widget->addCallback + ( + "clicked", + F_METHOD_CALLBACK (this, callback) + ); +} + +//---------------------------------------------------------------------- +void Window::addClickedCallback (FWidget* widget, FAppCallback call) +{ + FMemberCallback callback + = reinterpret_cast(call); + + widget->addCallback + ( + "clicked", + F_METHOD_CALLBACK (this, callback) + ); +} + //---------------------------------------------------------------------- void Window::onClose (FCloseEvent* ev) { @@ -551,7 +567,10 @@ void Window::cb_destroyWindow (FWidget*, data_ptr data) win_data* win_dat = static_cast(data); if ( win_dat ) + { win_dat->is_open = false; + win_dat->dgl = 0; + } } diff --git a/include/final/fapplication.h b/include/final/fapplication.h index 63086ab6..f813d185 100644 --- a/include/final/fapplication.h +++ b/include/final/fapplication.h @@ -136,13 +136,15 @@ class FApplication : public FWidget FApplication& operator = (const FApplication&); // Methods - void init(); + void init (long, long); static void cmd_options (const int&, char*[]); bool KeyPressed(); ssize_t readKey(); FWidget* findKeyboardWidget(); bool getKeyPressedState(); void keyboardBufferTimeout (FWidget*); + void parseKeyPuffer (FWidget*); + void performKeyboardAction (FWidget*); void sendEscapeKeyPressEvent (FWidget*); bool sendKeyDownEvent (FWidget*); bool sendKeyPressEvent (FWidget*); @@ -200,6 +202,7 @@ class FApplication : public FWidget long key_timeout; long dblclick_interval; struct timeval time_keypressed; + static FMouseControl* mouse; static eventQueue* event_queue; static int quit_code; static bool quit_now; diff --git a/include/final/fmouse.h b/include/final/fmouse.h index 8719b745..b8e49777 100644 --- a/include/final/fmouse.h +++ b/include/final/fmouse.h @@ -252,6 +252,7 @@ inline bool FMouseGPM::isGpmMouseEnabled() { return gpm_mouse_enabled; } #endif + //---------------------------------------------------------------------- // class FMouseX11 //---------------------------------------------------------------------- diff --git a/src/fapplication.cpp b/src/fapplication.cpp index 9f058166..7e28fa58 100644 --- a/src/fapplication.cpp +++ b/src/fapplication.cpp @@ -35,17 +35,19 @@ static FApplication* rootObj = 0; static bool app_exit_loop = false; // static attributes -int FApplication::loop_level = 0; // event loop level -FWidget* FApplication::main_widget = 0; // main application widget -FWidget* FApplication::active_window = 0; // the active window -FWidget* FApplication::focus_widget = 0; // has keyboard input focus -FWidget* FApplication::clicked_widget = 0; // is focused by click -FWidget* FApplication::open_menu = 0; // currently open menu -FWidget* FApplication::move_size_widget = 0; // move/size by keyboard -int FApplication::quit_code = 0; -bool FApplication::quit_now = false; +int FApplication::loop_level = 0; // event loop level +FWidget* FApplication::main_widget = 0; // main application widget +FWidget* FApplication::active_window = 0; // the active window +FWidget* FApplication::focus_widget = 0; // has keyboard input focus +FWidget* FApplication::clicked_widget = 0; // is focused by click +FWidget* FApplication::open_menu = 0; // currently open menu +FWidget* FApplication::move_size_widget = 0; // move/size by keyboard +FMouseControl* FApplication::mouse = 0; // mouse control +int FApplication::quit_code = 0; +bool FApplication::quit_now = false; + +FApplication::eventQueue* FApplication::event_queue = 0; -FApplication::eventQueue* FApplication::event_queue = 0; //---------------------------------------------------------------------- // class FApplication @@ -71,15 +73,6 @@ FApplication::FApplication ( const int& _argc && "FApplication: There should be only one application object" ); rootObj = this; - // Set the keyboard keypress timeout - setKeypressTimeout (key_timeout); - - // Set the default double click interval - FMouseControl* mouse = getMouseControl(); - - if ( mouse ) - mouse->setDblclickInterval (dblclick_interval); - if ( ! (_argc && _argv) ) { static char* empty = C_STR(""); @@ -87,7 +80,7 @@ FApplication::FApplication ( const int& _argc app_argv = static_cast(&empty); } - init(); + init (key_timeout, dblclick_interval); } //---------------------------------------------------------------------- @@ -362,16 +355,25 @@ void FApplication::closeConfirmationDialog (FWidget* w, FCloseEvent* ev) // private methods of FApplication //---------------------------------------------------------------------- -void FApplication::init() +void FApplication::init (long key_timeout, long dblclick_interval) { - // init keyboard values + // Initialize keyboard values time_keypressed.tv_sec = 0; time_keypressed.tv_usec = 0; - FMouseControl* mouse = getMouseControl(); + // Set the keyboard keypress timeout + setKeypressTimeout (key_timeout); + // Initialize mouse control + mouse = getMouseControl(); + + // Set stdin number for a gpm-mouse if ( mouse ) - mouse->setStdinNo(stdin_no); + mouse->setStdinNo (stdin_no); + + // Set the default double click interval + if ( mouse ) + mouse->setDblclickInterval (dblclick_interval); try { @@ -383,7 +385,7 @@ void FApplication::init() std::abort(); } - // init arrays with '\0' + // Initialize arrays with '\0' std::fill_n (k_buf, sizeof(k_buf), '\0'); std::fill_n (fifo_buf, fifo_buf_size, '\0'); } @@ -391,7 +393,7 @@ void FApplication::init() //---------------------------------------------------------------------- void FApplication::cmd_options (const int& argc, char* argv[]) { - // interpret the command line options + // Interpret the command line options while ( true ) { @@ -509,6 +511,15 @@ inline FWidget* FApplication::findKeyboardWidget() return widget; } +//---------------------------------------------------------------------- +inline bool FApplication::getKeyPressedState() +{ + if ( mouse && mouse->isGpmMouseEnabled() ) + return mouse->getGpmKeyPressed(unprocessedInput()); + + return KeyPressed(); +} + //---------------------------------------------------------------------- inline void FApplication::keyboardBufferTimeout (FWidget*) { @@ -523,14 +534,97 @@ inline void FApplication::keyboardBufferTimeout (FWidget*) } //---------------------------------------------------------------------- -inline bool FApplication::getKeyPressedState() +inline void FApplication::parseKeyPuffer (FWidget* widget) { - FMouseControl* mouse = getMouseControl(); + register ssize_t bytesread; + getCurrentTime (&time_keypressed); - if ( mouse && mouse->isGpmMouseEnabled() ) - return mouse->getGpmKeyPressed(unprocessedInput()); + if ( quit_now || app_exit_loop ) + return; - return KeyPressed(); + while ( (bytesread = readKey()) > 0 ) + { + if ( bytesread + fifo_offset <= fifo_buf_size ) + { + for (int i = 0; i < bytesread; i++) + { + fifo_buf[fifo_offset] = k_buf[i]; + fifo_offset++; + } + + fifo_in_use = true; + } + + // Read the rest from the fifo buffer + while ( ! widget->isKeypressTimeout(&time_keypressed) + && fifo_offset > 0 + && key != NEED_MORE_DATA ) + { + key = FTerm::parseKeyString(fifo_buf, fifo_buf_size, &time_keypressed); + + if ( key != NEED_MORE_DATA ) + performKeyboardAction (widget); + + fifo_offset = int(std::strlen(fifo_buf)); + } + + // Send key up event + sendKeyUpEvent (widget); + key = 0; + } + + std::fill_n (k_buf, sizeof(k_buf), '\0'); +} + +//---------------------------------------------------------------------- +inline void FApplication::performKeyboardAction (FWidget* widget) +{ +#if defined(__linux__) + key = linuxModifierKeyCorrection (key); +#endif + + switch ( key ) + { + case fc::Fckey_l: // Ctrl-L (redraw the screen) + redraw(); + break; + + case fc::Fkey_mouse: + if ( mouse ) + { + mouse->setRawData (FMouse::x11, fifo_buf, sizeof(fifo_buf)); + unprocessedInput() = mouse->isInputDataPending(); + processMouseEvent(); + } + break; + + case fc::Fkey_extended_mouse: + if ( mouse ) + { + mouse->setRawData (FMouse::sgr, fifo_buf, sizeof(fifo_buf)); + unprocessedInput() = mouse->isInputDataPending(); + processMouseEvent(); + } + break; + + case fc::Fkey_urxvt_mouse: + if ( mouse ) + { + mouse->setRawData (FMouse::urxvt, fifo_buf, sizeof(fifo_buf)); + unprocessedInput() = mouse->isInputDataPending(); + processMouseEvent(); + } + break; + + default: + bool acceptKeyDown = sendKeyDownEvent (widget); + bool acceptKeyPress = sendKeyPressEvent (widget); + + if ( ! (acceptKeyDown || acceptKeyPress) ) + sendKeyboardAccelerator(); + + break; + } } //---------------------------------------------------------------------- @@ -609,102 +703,13 @@ inline void FApplication::sendKeyboardAccelerator() //---------------------------------------------------------------------- void FApplication::processKeyboardEvent() { - bool isKeyPressed; FWidget* widget = findKeyboardWidget(); - FMouseControl* mouse = getMouseControl(); keyboardBufferTimeout(widget); flush_out(); - isKeyPressed = getKeyPressedState(); + bool isKeyPressed = getKeyPressedState(); if ( isKeyPressed ) - { - register ssize_t bytesread; - widget->getCurrentTime (&time_keypressed); - - if ( quit_now || app_exit_loop ) - return; - - while ( (bytesread = readKey()) > 0 ) - { - if ( bytesread + fifo_offset <= fifo_buf_size ) - { - for (int i = 0; i < bytesread; i++) - { - fifo_buf[fifo_offset] = k_buf[i]; - fifo_offset++; - } - - fifo_in_use = true; - } - - // read the rest from the fifo buffer - while ( ! widget->isKeypressTimeout(&time_keypressed) - && fifo_offset > 0 - && key != NEED_MORE_DATA ) - { - key = FTerm::parseKeyString(fifo_buf, fifo_buf_size, &time_keypressed); - - if ( key != NEED_MORE_DATA ) - { - -#if defined(__linux__) - key = linuxModifierKeyCorrection (key); -#endif - - switch ( key ) - { - case fc::Fckey_l: // Ctrl-L (redraw the screen) - redraw(); - break; - - case fc::Fkey_mouse: - if ( mouse ) - { - mouse->setRawData (FMouse::x11, fifo_buf, sizeof(fifo_buf)); - unprocessedInput() = mouse->isInputDataPending(); - processMouseEvent(); - } - break; - - case fc::Fkey_extended_mouse: - if ( mouse ) - { - mouse->setRawData (FMouse::sgr, fifo_buf, sizeof(fifo_buf)); - unprocessedInput() = mouse->isInputDataPending(); - processMouseEvent(); - } - break; - - case fc::Fkey_urxvt_mouse: - if ( mouse ) - { - mouse->setRawData (FMouse::urxvt, fifo_buf, sizeof(fifo_buf)); - unprocessedInput() = mouse->isInputDataPending(); - processMouseEvent(); - } - break; - - default: - bool acceptKeyDown = sendKeyDownEvent (widget); - bool acceptKeyPress = sendKeyPressEvent (widget); - - if ( ! (acceptKeyDown || acceptKeyPress) ) - sendKeyboardAccelerator(); - - break; - } // end of switch - } - - fifo_offset = int(std::strlen(fifo_buf)); - } - - // Send key up event - sendKeyUpEvent (widget); - key = 0; - } - - std::fill_n (k_buf, sizeof(k_buf), '\0'); - } + parseKeyPuffer (widget); // special case: Esc key sendEscapeKeyPressEvent (widget); @@ -1107,7 +1112,6 @@ bool FApplication::processAccelerator (const FWidget*& widget) bool FApplication::getMouseEvent() { bool mouse_event_occurred = false; - FMouseControl* mouse = getMouseControl(); if ( mouse && mouse->hasData() ) { @@ -1125,8 +1129,6 @@ FWidget*& FApplication::determineClickedWidget() if ( clicked_widget ) return clicked_widget; - FMouseControl* mouse = getMouseControl(); - if ( ! mouse ) return clicked_widget; @@ -1170,8 +1172,6 @@ void FApplication::closeOpenMenu() { // Close the open menu - FMouseControl* mouse = getMouseControl(); - if ( ! open_menu || ( mouse && mouse->isMoved()) ) return; @@ -1214,8 +1214,6 @@ void FApplication::unselectMenubarItems() { // Unselect the menu bar items - FMouseControl* mouse = getMouseControl(); - if ( open_menu || (mouse && mouse->isMoved()) ) return; @@ -1258,8 +1256,6 @@ void FApplication::sendMouseEvent() if ( ! clicked_widget ) return; - FMouseControl* mouse = getMouseControl(); - if ( ! mouse ) return; @@ -1298,8 +1294,6 @@ void FApplication::sendMouseMoveEvent ( const FPoint& widgetMousePos , const FPoint& mouse_position , int key_state ) { - FMouseControl* mouse = getMouseControl(); - if ( ! mouse ) return; @@ -1336,8 +1330,6 @@ void FApplication::sendMouseLeftClickEvent ( const FPoint& widgetMousePos , const FPoint& mouse_position , int key_state ) { - FMouseControl* mouse = getMouseControl(); - if ( ! mouse ) return; @@ -1378,8 +1370,6 @@ void FApplication::sendMouseRightClickEvent ( const FPoint& widgetMousePos , const FPoint& mouse_position , int key_state ) { - FMouseControl* mouse = getMouseControl(); - if ( ! mouse ) return; @@ -1412,8 +1402,6 @@ void FApplication::sendMouseMiddleClickEvent ( const FPoint& widgetMousePos , const FPoint& mouse_position , int key_state ) { - FMouseControl* mouse = getMouseControl(); - if ( ! mouse ) return; @@ -1451,8 +1439,6 @@ void FApplication::sendMouseMiddleClickEvent ( const FPoint& widgetMousePos void FApplication::sendWheelEvent ( const FPoint& widgetMousePos , const FPoint& mouse_position ) { - FMouseControl* mouse = getMouseControl(); - if ( ! mouse ) return; @@ -1482,8 +1468,6 @@ void FApplication::sendWheelEvent ( const FPoint& widgetMousePos //---------------------------------------------------------------------- void FApplication::processMouseEvent() { - FMouseControl* mouse = getMouseControl(); - if ( ! getMouseEvent() ) return;