diff --git a/ChangeLog b/ChangeLog index 9919c104..e372cf18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2017-01-14 Markus Gans + * Mouse functions are now in a separate class + 2017-01-05 Markus Gans * Refactoring FVTerm::restoreVTerm * Fixed buffer size in FOptiMove diff --git a/README.md b/README.md index 9ef5218e..4b86cf23 100644 --- a/README.md +++ b/README.md @@ -140,15 +140,15 @@ Class digramm : │ ┌────────────┐ : ├────┤ FHideEvent │ : │ └────────────┘ - : │ ┌─────────────┐ - : ├────┤ FCloseEvent │ - : │ └─────────────┘ 1┌───────────┐ : │ ┌─────────────┐ - ┌-----------┤ FOptiMove │ : └────┤ FTimerEvent │ + ┌-----------┤ FOptiMove │ : ├────┤ FCloseEvent │ + : └───────────┘ : │ └─────────────┘ + : 1┌───────────┐ : │ ┌─────────────┐ + ┌-----------┤ FOptiAttr │ : └────┤ FTimerEvent │ : └───────────┘ : └─────────────┘ - : 1┌───────────┐ : - ┌-----------┤ FOptiAttr │ : ┌──────────────┐ - : └───────────┘ : ┌────┤ FApplication │ + : 1┌───────────────┐ : + ┌-----------┤ FMouseControl │ : ┌──────────────┐ + : └───────────────┘ : ┌────┤ FApplication │ : *┌─────────┐ : │ └──────────────┘ : ┌--------┤ FString │ : │ ┌─────────┐ : : └─────────┘ : ├────┤ FButton │ diff --git a/doc/class-diagram.txt b/doc/class-diagram.txt index 546b2814..111d1556 100644 --- a/doc/class-diagram.txt +++ b/doc/class-diagram.txt @@ -26,15 +26,15 @@ : │ ┌────────────┐ : ├────┤ FHideEvent │ : │ └────────────┘ - : │ ┌─────────────┐ - : ├────┤ FCloseEvent │ - : │ └─────────────┘ 1┌───────────┐ : │ ┌─────────────┐ - ┌-----------┤ FOptiMove │ : └────┤ FTimerEvent │ + ┌-----------┤ FOptiMove │ : ├────┤ FCloseEvent │ + : └───────────┘ : │ └─────────────┘ + : 1┌───────────┐ : │ ┌─────────────┐ + ┌-----------┤ FOptiAttr │ : └────┤ FTimerEvent │ : └───────────┘ : └─────────────┘ - : 1┌───────────┐ : - ┌-----------┤ FOptiAttr │ : ┌──────────────┐ - : └───────────┘ : ┌────┤ FApplication │ + : 1┌───────────────┐ : + ┌-----------┤ FMouseControl │ : ┌──────────────┐ + : └───────────────┘ : ┌────┤ FApplication │ : *┌─────────┐ : │ └──────────────┘ : ┌--------┤ FString │ : │ ┌─────────┐ : : └─────────┘ : ├────┤ FButton │ diff --git a/examples/opti-move.cpp b/examples/opti-move.cpp index dbf0e288..2f7cb7f1 100644 --- a/examples/opti-move.cpp +++ b/examples/opti-move.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 * @@ -211,4 +211,5 @@ int main (int argc, char* argv[]) // Waiting for keypress keyPressed(); + app = 0; // End of TermApp object scope } diff --git a/include/final/fapplication.h b/include/final/fapplication.h index a58df829..aef95249 100644 --- a/include/final/fapplication.h +++ b/include/final/fapplication.h @@ -126,22 +126,6 @@ class FApplication : public FWidget typedef std::pair eventPair; typedef std::deque eventQueue; - enum btn_state - { - Pressed = 1, - Released = 2, - DoubleClick = 3 - }; - -#ifdef F_HAVE_LIBGPM - enum gpmEventType - { - no_event = 0, - keyboard_event = 1, - mouse_event = 2 - }; -#endif - // Constants static const int NEED_MORE_DATA = -1; // parseKeyString return value @@ -154,20 +138,11 @@ class FApplication : public FWidget // Methods void init(); static void cmd_options (const int&, char*[]); - -#ifdef F_HAVE_LIBGPM - int gpmEvent (bool = true); - bool processGpmEvent(); -#endif - bool KeyPressed(); ssize_t readKey(); FWidget* findKeyboardWidget(); bool getKeyPressedState(); void keyboardBufferTimeout (FWidget*); - void readRawX11MouseData(); - void readRawExtendedMouseData(); - void readRawUrxvtMouseData(); void sendEscapeKeyPressEvent (FWidget*); bool sendKeyDownEvent (FWidget*); bool sendKeyPressEvent (FWidget*); @@ -188,10 +163,6 @@ class FApplication : public FWidget bool processDialogSwitchAccelerator(); bool processAccelerator (const FWidget*&); - void getX11ButtonState (int); - bool parseX11Mouse(); - bool parseSGRMouse(); - bool parseUrxvtMouse(); bool getMouseEvent(); FWidget*& determineClickedWidget(); void unsetMoveSizeMode(); @@ -221,30 +192,7 @@ class FApplication : public FWidget int app_argc; char** app_argv; int key; - -#ifdef F_HAVE_LIBGPM - Gpm_Event gpm_ev; - bool gpmMouseEvent; -#endif - - struct button_state // bit field - { - uChar left_button : 2; // 0..3 - uChar right_button : 2; // 0..3 - uChar middle_button : 2; // 0..3 - uChar shift_button : 1; // 0..1 - uChar control_button : 1; // 0..1 - uChar meta_button : 1; // 0..1 - uChar wheel_up : 1; // 0..1 - uChar wheel_down : 1; // 0..1 - uChar mouse_moved : 1; // 0..1 - uChar : 4; // padding bits - } b_state; - char k_buf[1024]; - char x11_mouse[4]; - char sgr_mouse[13]; - char urxvt_mouse[13]; char fifo_buf[512]; int fifo_offset; bool fifo_in_use; @@ -252,15 +200,11 @@ class FApplication : public FWidget long key_timeout; long dblclick_interval; struct timeval time_keypressed; - struct timeval time_mousepressed; - FPoint new_mouse_position; static eventQueue* event_queue; static int quit_code; static bool quit_now; static int loop_level; static bool process_timer_event; - static FPoint* zero_point; - static uChar x11_button_state; static FWidget* move_size_widget; static FWidget* main_widget; static FWidget* active_window; diff --git a/include/final/flistbox.h b/include/final/flistbox.h index 7c6df3db..5fc44899 100644 --- a/include/final/flistbox.h +++ b/include/final/flistbox.h @@ -3,7 +3,7 @@ * * * This file is part of the Final Cut widget toolkit * * * -* Copyright 2014-2017 Markus Gans * +* Copyright 2014-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 * diff --git a/include/final/fmouse.h b/include/final/fmouse.h new file mode 100644 index 00000000..099c6f79 --- /dev/null +++ b/include/final/fmouse.h @@ -0,0 +1,543 @@ +/*********************************************************************** +* fmouse.h - Read mouse events * +* * +* This file is part of the Final Cut widget toolkit * +* * +* Copyright 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 * +* as published by the Free Software Foundation; either version 3 of * +* the License, or (at your option) any later version. * +* * +* The Final Cut is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public * +* License along with this program. If not, see * +* . * +***********************************************************************/ + +/* Inheritance diagram + * ═══════════════════ + * + * ▕▔▔▔▔▔▔▔▔▔▔▏ + * ▕ FMouse ▏ + * ▕▁▁▁▁▁▁▁▁▁▁▏ + * ▲ + * │ + * ┌─────────────┬──────┴───────┬─────────────┐ + * │ │ │ │ + * ▕▔▔▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▏ + * ▕ FMouseGPM ▏ ▕ FMouseX11 ▏ ▕ FMouseSGR ▏ ▕ FMouseUrxvt ▏ + * ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▏ + * + * + * + * ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏1 1▕▔▔▔▔▔▔▔▔▔▔▔▏ + * ▕ FMouseControl ▏- -┬- - -▕ FMouseGPM ▏ + * ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▁▁▁▁▏ + * : + * : 1▕▔▔▔▔▔▔▔▔▔▔▔▏ + * :- - -▕ FMouseX11 ▏ + * : ▕▁▁▁▁▁▁▁▁▁▁▁▏ + * : + * : 1▕▔▔▔▔▔▔▔▔▔▔▔▏ + * └- - -▕ FMouseSGR ▏ + * : ▕▁▁▁▁▁▁▁▁▁▁▁▏ + * : + * : 1▕▔▔▔▔▔▔▔▔▔▔▔▔▔▏ + * └- - -▕ FMouseUrxvt ▏ + * ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▏ + */ + +#ifndef FMOUSE_H +#define FMOUSE_H + +#if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT) + #error "Only can be included directly." +#endif + +#include +#include + +#include "final/fconfig.h" +#include "final/fpoint.h" +#include "final/ftypes.h" + +#if defined(__linux__) + #include // need for gpm keyboard modifiers +#endif + +#ifdef F_HAVE_LIBGPM + #include + #undef buttons // from term.h +#endif + + +//---------------------------------------------------------------------- +// class FMouse +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FMouse +{ + public: + // Enumeration + enum mouse_type + { + none = 0, + gpm = 1, + x11 = 2, + sgr = 3, + urxvt = 4 + }; + + // Constructor + FMouse(); + + // Destructor + virtual ~FMouse() + { } + + // Accessors + virtual const char* getClassName() const; + FPoint& getPos(); + void clearEvent(); + + // Mutators + void setMaxWidth (short); + void setMaxHeight (short); + + // Inquiries + virtual bool hasData() = 0; + bool hasEvent(); + bool isLeftButtonPressed(); + bool isLeftButtonReleased(); + bool isLeftButtonDoubleClick(); + bool isRightButtonPressed(); + bool isRightButtonReleased(); + bool isMiddleButtonPressed(); + bool isMiddleButtonReleased(); + bool isShiftKeyPressed(); + bool isControlKeyPressed(); + bool isMetaKeyPressed(); + bool isWheelUp(); + bool isWheelDown(); + bool isMoved(); + bool isInputDataPending(); + + // Methods + static FMouse* createMouseObject (mouse_type); + virtual void setRawData (char[], int) = 0; + virtual void processEvent (struct timeval*) = 0; + + protected: + // Typedef and Enumerations + typedef struct + { + uChar left_button : 2; // 0..3 + uChar right_button : 2; // 0..3 + uChar middle_button : 2; // 0..3 + uChar shift_button : 1; // 0..1 + uChar control_button : 1; // 0..1 + uChar meta_button : 1; // 0..1 + uChar wheel_up : 1; // 0..1 + uChar wheel_down : 1; // 0..1 + uChar mouse_moved : 1; // 0..1 + uChar : 4; // padding bits + } button; // bit field + + enum states + { + Undefined = 0, + Pressed = 1, + Released = 2, + DoubleClick = 3 + }; + + // Mutator + void setPos (const FPoint&); + + // Method + bool isDblclickTimeout (timeval*); + + // Data Members + button b_state; + bool mouse_event_occurred; + bool input_data_pending; + long dblclick_interval; + short max_width; + short max_height; + struct timeval time_mousepressed; + FPoint zero_point; + FPoint mouse; // mouse click position + FPoint new_mouse_position; +}; +#pragma pack(pop) + + +#ifdef F_HAVE_LIBGPM +//---------------------------------------------------------------------- +// class FMouseGPM +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FMouseGPM : public FMouse +{ + public: + // Constructor + FMouseGPM(); + + // Destructor + virtual ~FMouseGPM(); + + // Accessors + const char* getClassName() const; + + // Mutators + void setStdinNo(int); + + // Inquiry + virtual bool hasData(); + bool isGpmMouseEnabled(); + + // Methods + virtual void setRawData (char[], int); + virtual void processEvent (struct timeval*); + bool gpmMouse (bool); + bool enableGpmMouse(); + bool disableGpmMouse(); + bool getGpmKeyPressed(bool); + void drawGpmPointer(); + + private: + // Enumeration + enum gpmEventType + { + no_event = 0, + keyboard_event = 1, + mouse_event = 2 + }; + + // Method + int gpmEvent (bool = true); + + // Data Member + Gpm_Event gpm_ev; + bool has_gpm_mouse_data; + bool gpm_mouse_enabled; + int stdin_no; +}; +#pragma pack(pop) +#endif + +//---------------------------------------------------------------------- +inline const char* FMouseGPM::getClassName() const +{ return "FMouseGPM"; } + +//---------------------------------------------------------------------- +inline bool FMouseGPM::enableGpmMouse() +{ return gpmMouse(true); } + +//---------------------------------------------------------------------- +inline bool FMouseGPM::disableGpmMouse() +{ return gpmMouse(false); } + +//---------------------------------------------------------------------- +inline bool FMouseGPM::isGpmMouseEnabled() +{ return gpm_mouse_enabled; } + + +//---------------------------------------------------------------------- +// class FMouseX11 +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FMouseX11 : public FMouse +{ + public: + // Constructor + FMouseX11(); + + // Destructor + virtual ~FMouseX11(); + + // Accessors + const char* getClassName() const; + + // Inquiry + virtual bool hasData(); + + // Methods + virtual void setRawData (char[], int); + virtual void processEvent (struct timeval*); + + private: + // Enumeration + enum btn_states + { + key_shift = 0x04, + key_meta = 0x08, + key_ctrl = 0x10, + key_button_mask = 0x1c, + button1_pressed = 0x20, + button2_pressed = 0x21, + button3_pressed = 0x22, + all_buttons_released = 0x23, + button1_pressed_move = 0x40, + button2_pressed_move = 0x41, + button3_pressed_move = 0x42, + button_mask = 0x63, + button_up = 0x60, + button_down = 0x61, + button_up_move = 0x60, + button_down_move = 0x61 + }; + + // Constant + static const std::size_t MOUSE_BUF_SIZE = 4; + + // Method + void setKeyState (int); + void setMoveState (const FPoint&, int); + void setButtonState (int, struct timeval*); + + // Data Member + char x11_mouse[MOUSE_BUF_SIZE]; + uChar x11_button_state; +}; +#pragma pack(pop) + +//---------------------------------------------------------------------- +inline const char* FMouseX11::getClassName() const +{ return "FMouseX11"; } + + +//---------------------------------------------------------------------- +// class FMouseSGR +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FMouseSGR : public FMouse +{ + public: + // Constructor + FMouseSGR(); + + // Destructor + virtual ~FMouseSGR(); + + // Accessors + const char* getClassName() const; + + // Inquiry + virtual bool hasData(); + + // Methods + virtual void setRawData (char[], int); + virtual void processEvent (struct timeval*); + + private: + // Enumeration + enum x11_ext_btn_states + { + key_shift = 0x04, + key_meta = 0x08, + key_ctrl = 0x10, + key_button_mask = 0x1c, + button1 = 0x00, + button2 = 0x01, + button3 = 0x02, + button1_move = 0x20, + button2_move = 0x21, + button3_move = 0x22, + button_mask = 0x63, + button_up = 0x40, + button_down = 0x41, + pressed = 'M', + released = 'm' + }; + + // Constant + static const std::size_t MOUSE_BUF_SIZE = 13; + + // Methods + void setKeyState (int); + void setMoveState (const FPoint&, int); + void setPressedButtonState (int, struct timeval*); + void setReleasedButtonState (int); + + // Data Members + char sgr_mouse[MOUSE_BUF_SIZE]; + uChar sgr_button_state; +}; +#pragma pack(pop) + +//---------------------------------------------------------------------- +inline const char* FMouseSGR::getClassName() const +{ return "FMouseSGR"; } + + +//---------------------------------------------------------------------- +// class FMouseUrxvt +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FMouseUrxvt : public FMouse +{ + public: + // Constructor + FMouseUrxvt(); + + // Destructor + virtual ~FMouseUrxvt(); + + // Accessors + const char* getClassName() const; + + // Inquiry + virtual bool hasData(); + + // Methods + virtual void setRawData (char[], int); + virtual void processEvent (struct timeval*); + + private: + // Enumeration + enum urxvt_btn_states + { + key_shift = 0x04, + key_meta = 0x08, + key_ctrl = 0x10, + key_button_mask = 0x1c, + button1_pressed = 0x20, + button2_pressed = 0x21, + button3_pressed = 0x22, + all_buttons_released = 0x23, + button1_pressed_move = 0x40, + button2_pressed_move = 0x41, + button3_pressed_move = 0x42, + button_mask = 0x63, + button_up = 0x60, + button_down = 0x61, + button_up_move = 0x60, + button_down_move = 0x61 + }; + + // Constant + static const std::size_t MOUSE_BUF_SIZE = 13; + + // Methods + void setKeyState (int); + void setMoveState (const FPoint&, int); + void setButtonState (int, struct timeval*); + + // Data Members + char urxvt_mouse[MOUSE_BUF_SIZE]; + uChar urxvt_button_state; +}; +#pragma pack(pop) + +//---------------------------------------------------------------------- +inline const char* FMouseUrxvt::getClassName() const +{ return "FMouseUrxvt"; } + + +//---------------------------------------------------------------------- +// class FMouseControl +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) +class FMouseControl +{ + public: + // Constructor + FMouseControl(); + + // Destructor + virtual ~FMouseControl(); + + // Accessors + const char* getClassName() const; + FPoint& getPos(); + void clearEvent(); + + // Mutators + void setStdinNo (int); + void setMaxWidth (short); + void setMaxHeight (short); + void useGpmMouse (bool = true); + void useXtermMouse (bool = true); + + // Inquiries + bool hasData(); + bool hasEvent(); + bool isLeftButtonPressed(); + bool isLeftButtonReleased(); + bool isLeftButtonDoubleClick(); + bool isRightButtonPressed(); + bool isRightButtonReleased(); + bool isMiddleButtonPressed(); + bool isMiddleButtonReleased(); + bool isShiftKeyPressed(); + bool isControlKeyPressed(); + bool isMetaKeyPressed(); + bool isWheelUp(); + bool isWheelDown(); + bool isMoved(); + bool isInputDataPending(); + bool isGpmMouseEnabled(); + + // Methods + void enable(); + void disable(); + void xtermMouse (bool); + void enableXTermMouse(); + void disableXTermMouse(); + virtual void setRawData (FMouse::mouse_type, char[], int); + virtual void processEvent (struct timeval* time); + bool getGpmKeyPressed (bool); + void drawGpmPointer(); + + private: + std::map mouse_protocol; + std::map::iterator iter; + + // Accessor + FMouse* getMouseWithData(); + FMouse* getMouseWithEvent(); + void putstring (const char[], int = 1); + + // Data Member + FPoint zero_point; + bool use_gpm_mouse; + bool use_xterm_mouse; +}; +#pragma pack(pop) + +inline const char* FMouseControl::getClassName() const +{ return "FMouseControl"; } + +//---------------------------------------------------------------------- +inline void FMouseControl::enableXTermMouse() +{ xtermMouse(true); } + +//---------------------------------------------------------------------- +inline void FMouseControl::disableXTermMouse() +{ xtermMouse(false); } + +#endif // FMOUSE_H diff --git a/include/final/fobject.h b/include/final/fobject.h index b4d0440d..3b05bee0 100644 --- a/include/final/fobject.h +++ b/include/final/fobject.h @@ -3,7 +3,7 @@ * * * This file is part of the Final Cut widget toolkit * * * -* Copyright 2015-2017 Markus Gans * +* Copyright 2015-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 * @@ -96,6 +96,7 @@ class FObject // Timer methods static void getCurrentTime (timeval*); + static bool isTimeout (timeval*, register long); int addTimer (int); bool delTimer (int); bool delOwnTimer(); diff --git a/include/final/fterm.h b/include/final/fterm.h index 2d05d729..aea2fa25 100644 --- a/include/final/fterm.h +++ b/include/final/fterm.h @@ -56,13 +56,8 @@ #include "final/fconfig.h" -#ifdef F_HAVE_LIBGPM - #include -#endif - #if defined(__linux__) #include // Linux framebuffer console - #include // need for gpm keyboard modifiers #if defined(__x86_64__) || defined(__i386) || defined(__arm__) #include // is deprecated @@ -88,6 +83,7 @@ #include #include + #if defined(__sun) && defined(__SVR4) #include typedef struct termio SGTTY; @@ -104,6 +100,10 @@ #include // termcap #endif +#ifdef F_HAVE_LIBGPM + #undef buttons // from term.h +#endif + #if F_HAVE_GETTTYNAM && F_HAVE_TTYENT_H #include #endif @@ -119,6 +119,7 @@ #include #include "final/fc.h" +#include "final/fmouse.h" #include "final/fobject.h" #include "final/foptiattr.h" #include "final/foptimove.h" @@ -128,11 +129,6 @@ #include "final/ftermcap.h" -#ifdef F_HAVE_LIBGPM - #undef buttons // from term.h -#endif - - //---------------------------------------------------------------------- // class FTerm //---------------------------------------------------------------------- @@ -169,6 +165,7 @@ class FTerm static int getLineNumber(); static int getColumnNumber(); static const FString getKeyName (int); + static FMouseControl* getMouseControl(); #if defined(__linux__) static modifier_key& getLinuxModifierKey(); @@ -194,7 +191,6 @@ class FTerm // Inquiries static bool isKeypressTimeout (timeval*); - static bool isDblclickTimeout (timeval*); static bool isNormal (char_data*&); static bool isRaw(); static bool hasPCcharset(); @@ -348,19 +344,6 @@ class FTerm static bool hasChangedTermSize(); static void changeTermSizeFinished(); static void xtermMetaSendsESC (bool); - static void xtermMouse (bool); - static void enableXTermMouse(); - static void disableXTermMouse(); - -#ifdef F_HAVE_LIBGPM - static bool gpmMouse (bool); - static bool enableGpmMouse(); - static bool disableGpmMouse(); - static bool isGpmMouseEnabled(); -#endif // F_HAVE_LIBGPM - static FPoint& getMousePos(); - static void setMousePos (const FPoint&); - static void setMousePos (short, short); static void exitWithMessage (std::string) #if defined(__clang__) || defined(__GNUC__) __attribute__((noreturn)) @@ -425,9 +408,6 @@ class FTerm // Disable assignment operator (=) FTerm& operator = (const FTerm&); - // Inquiries - static bool isTimeout (timeval*, register long); - #if defined(__linux__) static int isLinuxConsole(); #endif @@ -556,13 +536,11 @@ class FTerm static std::map * encoding_set; static FTermcap::tcap_map* tcap; - static bool mouse_support; static bool decscusr_support; static bool terminal_detection; static bool raw_mode; static bool input_data_pending; static bool non_blocking_stdin; - static bool gpm_mouse_enabled; static bool pc_charset_console; static bool utf8_input; static bool utf8_state; @@ -596,7 +574,6 @@ class FTerm static char* locale_name; static char* locale_xterm; static FRect* term; // current terminal geometry - static FPoint* mouse; // mouse click position static int gnome_terminal_id; static int stdin_status_flags; @@ -622,6 +599,7 @@ class FTerm static FOptiMove* opti_move; static FOptiAttr* opti_attr; + static FMouseControl* mouse; static const FString* xterm_font; static const FString* xterm_title; static const FString* answer_back; @@ -702,11 +680,7 @@ inline const FString& FTerm::getSecDAString() //---------------------------------------------------------------------- inline bool FTerm::isKeypressTimeout (timeval* time) -{ return isTimeout (time, key_timeout); } - -//---------------------------------------------------------------------- -inline bool FTerm::isDblclickTimeout (timeval* time) -{ return isTimeout (time, dblclick_interval); } +{ return FObject::isTimeout (time, key_timeout); } //---------------------------------------------------------------------- inline bool FTerm::isRaw() @@ -868,39 +842,5 @@ inline bool FTerm::hasChangedTermSize() inline void FTerm::changeTermSizeFinished() { resize_term = false; } -//---------------------------------------------------------------------- -inline void FTerm::enableXTermMouse() -{ xtermMouse(true); } - -//---------------------------------------------------------------------- -inline void FTerm::disableXTermMouse() -{ xtermMouse(false); } - -#ifdef F_HAVE_LIBGPM -//---------------------------------------------------------------------- -inline bool FTerm::enableGpmMouse() -{ return gpmMouse(true); } - -//---------------------------------------------------------------------- -inline bool FTerm::disableGpmMouse() -{ return gpmMouse(false); } - -//---------------------------------------------------------------------- -inline bool FTerm::isGpmMouseEnabled() -{ return gpm_mouse_enabled; } -#endif // F_HAVE_LIBGPM - -//---------------------------------------------------------------------- -inline FPoint& FTerm::getMousePos() -{ return *mouse; } - -//---------------------------------------------------------------------- -inline void FTerm::setMousePos (const FPoint& m) -{ *mouse = m; } - -//---------------------------------------------------------------------- -inline void FTerm::setMousePos (short x, short y) -{ mouse->setPoint (x, y); } - #endif // FTERM_H diff --git a/src/Makefile.am b/src/Makefile.am index fdb08749..86f7466c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,6 +23,7 @@ libfinal_la_SOURCES = \ flistbox.cpp \ flistview.cpp \ fmenu.cpp \ + fmouse.cpp \ fdialoglistmenu.cpp \ fmenubar.cpp \ fmenuitem.cpp \ @@ -71,6 +72,7 @@ finalcutinclude_HEADERS = \ ../include/final/flistbox.h \ ../include/final/flistview.h \ ../include/final/fmenu.h \ + ../include/final/fmouse.h \ ../include/final/fdialoglistmenu.h \ ../include/final/fmenubar.h \ ../include/final/fmenuitem.h \ diff --git a/src/Makefile.clang b/src/Makefile.clang index cebfa9b5..6e96626e 100644 --- a/src/Makefile.clang +++ b/src/Makefile.clang @@ -23,6 +23,7 @@ INCLUDE_HEADERS = \ flistbox.h \ flistview.h \ fmenu.h \ + fmouse.h \ fdialoglistmenu.h \ fmenubar.h \ fradiomenuitem.h \ @@ -76,6 +77,7 @@ OBJS = \ flistbox.o \ flistview.o \ fmenu.o \ + fmouse.o \ fdialoglistmenu.o \ fmenubar.o \ fmenuitem.o \ diff --git a/src/Makefile.gcc b/src/Makefile.gcc index 401cb33f..b1a73f0e 100644 --- a/src/Makefile.gcc +++ b/src/Makefile.gcc @@ -23,6 +23,7 @@ INCLUDE_HEADERS = \ flistbox.h \ flistview.h \ fmenu.h \ + fmouse.h \ fdialoglistmenu.h \ fmenubar.h \ fradiomenuitem.h \ @@ -76,6 +77,7 @@ OBJS = \ flistbox.o \ flistview.o \ fmenu.o \ + fmouse.o \ fdialoglistmenu.o \ fmenubar.o \ fmenuitem.o \ diff --git a/src/Makefile.in b/src/Makefile.in index 2464bad3..935bf635 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -131,13 +131,13 @@ libfinal_la_LIBADD = am_libfinal_la_OBJECTS = fstring.lo fpoint.lo frect.lo fscrollbar.lo \ fprogressbar.lo flineedit.lo fbutton.lo fbuttongroup.lo \ ftogglebutton.lo fradiobutton.lo fcheckbox.lo fswitch.lo \ - flabel.lo flistbox.lo flistview.lo fmenu.lo fdialoglistmenu.lo \ - fmenubar.lo fmenuitem.lo fradiomenuitem.lo fcheckmenuitem.lo \ - fmenulist.lo fdialog.lo fscrollview.lo fwindow.lo \ - fmessagebox.lo ftooltip.lo ffiledialog.lo ftextview.lo \ - fstatusbar.lo fterm.lo fvterm.lo fevent.lo foptiattr.lo \ - foptimove.lo ftermbuffer.lo fapplication.lo fwidget.lo \ - fobject.lo + flabel.lo flistbox.lo flistview.lo fmenu.lo fmouse.lo \ + fdialoglistmenu.lo fmenubar.lo fmenuitem.lo fradiomenuitem.lo \ + fcheckmenuitem.lo fmenulist.lo fdialog.lo fscrollview.lo \ + fwindow.lo fmessagebox.lo ftooltip.lo ffiledialog.lo \ + ftextview.lo fstatusbar.lo fterm.lo fvterm.lo fevent.lo \ + foptiattr.lo foptimove.lo ftermbuffer.lo fapplication.lo \ + fwidget.lo fobject.lo libfinal_la_OBJECTS = $(am_libfinal_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -350,6 +350,7 @@ libfinal_la_SOURCES = \ flistbox.cpp \ flistview.cpp \ fmenu.cpp \ + fmouse.cpp \ fdialoglistmenu.cpp \ fmenubar.cpp \ fmenuitem.cpp \ @@ -396,6 +397,7 @@ finalcutinclude_HEADERS = \ ../include/final/flistbox.h \ ../include/final/flistview.h \ ../include/final/fmenu.h \ + ../include/final/fmouse.h \ ../include/final/fdialoglistmenu.h \ ../include/final/fmenubar.h \ ../include/final/fmenuitem.h \ @@ -522,6 +524,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmenuitem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmenulist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmessagebox.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmouse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fobject.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/foptiattr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/foptimove.Plo@am__quote@ diff --git a/src/fapplication.cpp b/src/fapplication.cpp index 9e615cae..86af3c1d 100644 --- a/src/fapplication.cpp +++ b/src/fapplication.cpp @@ -42,8 +42,6 @@ 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 -FPoint* FApplication::zero_point = 0; // zero point (x=0, y=0) -uChar FApplication::x11_button_state = 0x03; int FApplication::quit_code = 0; bool FApplication::quit_now = false; @@ -62,19 +60,12 @@ FApplication::FApplication ( const int& _argc , app_argc(_argc) , app_argv(_argv) , key(0) -#ifdef F_HAVE_LIBGPM - , gpm_ev() - , gpmMouseEvent(false) -#endif - , b_state() , fifo_offset(0) , fifo_in_use(false) , fifo_buf_size(sizeof(fifo_buf)) , key_timeout(100000) // 100 ms , dblclick_interval(500000) // 500 ms , time_keypressed() - , time_mousepressed() - , new_mouse_position() { assert ( ! rootObj && "FApplication: There should be only one application object" ); @@ -99,9 +90,6 @@ FApplication::FApplication ( const int& _argc //---------------------------------------------------------------------- FApplication::~FApplication() // destructor { - if ( zero_point ) - delete zero_point; - if ( event_queue ) delete event_queue; @@ -376,17 +364,14 @@ void FApplication::init() // init keyboard values time_keypressed.tv_sec = 0; time_keypressed.tv_usec = 0; - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - x11_button_state = 0x23; -#ifdef F_HAVE_LIBGPM - gpm_ev.x = -1; -#endif + FMouseControl* mouse = getMouseControl(); + + if ( mouse ) + mouse->setStdinNo(stdin_no); try { - zero_point = new FPoint (0,0); event_queue = new eventQueue; } catch (const std::bad_alloc& ex) @@ -398,11 +383,6 @@ void FApplication::init() // init arrays with '\0' std::fill_n (k_buf, sizeof(k_buf), '\0'); std::fill_n (fifo_buf, fifo_buf_size, '\0'); - std::fill_n (x11_mouse, sizeof(x11_mouse), '\0'); - std::fill_n (sgr_mouse, sizeof(sgr_mouse), '\0'); - std::fill_n (urxvt_mouse, sizeof(urxvt_mouse), '\0'); - // init bit field with 0 - std::memset(&b_state, 0x00, sizeof(b_state)); } //---------------------------------------------------------------------- @@ -474,40 +454,6 @@ void FApplication::cmd_options (const int& argc, char* argv[]) } } -//---------------------------------------------------------------------- -#ifdef F_HAVE_LIBGPM -int FApplication::gpmEvent (bool clear) -{ - register int result; - register int max = ( gpm_fd > stdin_no ) ? gpm_fd : stdin_no; - fd_set ifds; - struct timeval tv; - - FD_ZERO(&ifds); - FD_SET(stdin_no, &ifds); - FD_SET(gpm_fd, &ifds); - tv.tv_sec = 0; - tv.tv_usec = 100000; // 100 ms - result = select (max + 1, &ifds, 0, 0, &tv); - - if ( result > 0 && FD_ISSET(stdin_no, &ifds) ) - { - if ( clear ) - FD_CLR (stdin_no, &ifds); - - return keyboard_event; - } - - if ( clear && result > 0 && FD_ISSET(gpm_fd, &ifds) ) - FD_CLR (gpm_fd, &ifds); - - if ( result > 0 ) - return mouse_event; - else - return no_event; -} -#endif // F_HAVE_LIBGPM - //---------------------------------------------------------------------- inline bool FApplication::KeyPressed() { @@ -576,114 +522,14 @@ inline void FApplication::keyboardBufferTimeout (FWidget*) //---------------------------------------------------------------------- inline bool FApplication::getKeyPressedState() { -#ifdef F_HAVE_LIBGPM + FMouseControl* mouse = getMouseControl(); - if ( isGpmMouseEnabled() ) - { - gpmMouseEvent = false; - int type = gpmEvent(); - - switch ( type ) - { - case mouse_event: - gpmMouseEvent = true; - break; - - case keyboard_event: - return true; - - default: - return false; - } - } - -#endif // F_HAVE_LIBGPM + if ( mouse && mouse->isGpmMouseEnabled() ) + return mouse->getGpmKeyPressed(unprocessedInput()); return KeyPressed(); } -//---------------------------------------------------------------------- -inline void FApplication::readRawX11MouseData() -{ - static const int len = 6; - int n; - x11_mouse[0] = fifo_buf[3]; - x11_mouse[1] = fifo_buf[4]; - x11_mouse[2] = fifo_buf[5]; - x11_mouse[3] = '\0'; - - // Remove founded entry - for (n = len; n < fifo_buf_size; n++) - fifo_buf[n - len] = fifo_buf[n]; - - n = fifo_buf_size - len - 1; - - // Fill rest with '\0' - for (; n < fifo_buf_size; n++) - fifo_buf[n - len] = '\0'; - - unprocessedInput() = bool(fifo_buf[0] != '\0'); - processMouseEvent(); -} - -//---------------------------------------------------------------------- -inline void FApplication::readRawExtendedMouseData() -{ - int len = int(std::strlen(fifo_buf)); - int n = 3; - - while ( n < len && n < fifo_buf_size ) - { - sgr_mouse[n - 3] = fifo_buf[n]; - n++; - - if ( fifo_buf[n] == 'M' || fifo_buf[n] == 'm' ) - len = n + 1; - } - - sgr_mouse[n - 3] = '\0'; - - for (n = len; n < fifo_buf_size; n++) // Remove founded entry - fifo_buf[n - len] = fifo_buf[n]; - - n = fifo_buf_size - len - 1; - - for (; n < fifo_buf_size; n++) // Fill rest with '\0' - fifo_buf[n - len] = '\0'; - - unprocessedInput() = bool(fifo_buf[0] != '\0'); - processMouseEvent(); -} - -//---------------------------------------------------------------------- -inline void FApplication::readRawUrxvtMouseData() -{ - int len = int(std::strlen(fifo_buf)); - int n = 2; - - while ( n < len && n < fifo_buf_size ) - { - urxvt_mouse[n - 2] = fifo_buf[n]; - n++; - - if ( fifo_buf[n] == 'M' || fifo_buf[n] == 'm' ) - len = n + 1; - } - - urxvt_mouse[n - 2] = '\0'; - - for (n = len; n < fifo_buf_size; n++) // Remove founded entry - fifo_buf[n - len] = fifo_buf[n]; - - n = fifo_buf_size - len - 1; - - for (; n < fifo_buf_size; n++) // Fill rest with '\0' - fifo_buf[n - len] = '\0'; - - unprocessedInput() = bool(fifo_buf[0] != '\0'); - processMouseEvent(); -} - //---------------------------------------------------------------------- inline void FApplication::sendEscapeKeyPressEvent (FWidget* widget) { @@ -762,6 +608,7 @@ void FApplication::processKeyboardEvent() { bool isKeyPressed; FWidget* widget = findKeyboardWidget(); + FMouseControl* mouse = getMouseControl(); keyboardBufferTimeout(widget); flush_out(); isKeyPressed = getKeyPressedState(); @@ -770,7 +617,6 @@ void FApplication::processKeyboardEvent() { register ssize_t bytesread; widget->getCurrentTime (&time_keypressed); - x11_mouse[0] = sgr_mouse[0] = urxvt_mouse[0] = '\0'; if ( quit_now || app_exit_loop ) return; @@ -809,15 +655,30 @@ void FApplication::processKeyboardEvent() break; case fc::Fkey_mouse: - readRawX11MouseData(); + if ( mouse ) + { + mouse->setRawData (FMouse::x11, fifo_buf, sizeof(fifo_buf)); + unprocessedInput() = mouse->isInputDataPending(); + processMouseEvent(); + } break; case fc::Fkey_extended_mouse: - readRawExtendedMouseData(); + if ( mouse ) + { + mouse->setRawData (FMouse::sgr, fifo_buf, sizeof(fifo_buf)); + unprocessedInput() = mouse->isInputDataPending(); + processMouseEvent(); + } break; case fc::Fkey_urxvt_mouse: - readRawUrxvtMouseData(); + if ( mouse ) + { + mouse->setRawData (FMouse::urxvt, fifo_buf, sizeof(fifo_buf)); + unprocessedInput() = mouse->isInputDataPending(); + processMouseEvent(); + } break; default: @@ -1239,587 +1100,20 @@ bool FApplication::processAccelerator (const FWidget*& widget) return accpt; } -//---------------------------------------------------------------------- -void FApplication::getX11ButtonState (int button) -{ - // get the x11 and urxvt mouse button state - const FPoint& mouse_position = getMousePos(); - - enum btn_states - { - key_shift = 0x04, - key_meta = 0x08, - key_ctrl = 0x10, - key_button_mask = 0x1c, - button1_pressed = 0x20, - button2_pressed = 0x21, - button3_pressed = 0x22, - all_buttons_released = 0x23, - button1_pressed_move = 0x40, - button2_pressed_move = 0x41, - button3_pressed_move = 0x42, - button_mask = 0x63, - button_up = 0x60, - button_down = 0x61, - button_up_move = 0x60, - button_down_move = 0x61 - }; - - switch ( button ) - { - case button1_pressed: - case button1_pressed_move: - if ( mouse_position == new_mouse_position - && x11_button_state == all_buttons_released - && ! isDblclickTimeout(&time_mousepressed) ) - { - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - b_state.left_button = DoubleClick; - } - else - { - time_mousepressed = time_keypressed; // save click time - b_state.left_button = Pressed; - } - break; - - case button2_pressed: - case button2_pressed_move: - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - b_state.middle_button = Pressed; - break; - - case button3_pressed: - case button3_pressed_move: - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - b_state.right_button = Pressed; - break; - - case all_buttons_released: - switch ( x11_button_state & button_mask ) - { - case button1_pressed: - case button1_pressed_move: - b_state.left_button = Released; - break; - - case button2_pressed: - case button2_pressed_move: - b_state.middle_button = Released; - break; - - case button3_pressed: - case button3_pressed_move: - b_state.right_button = Released; - break; - - default: - break; - } - break; - - case button_up: - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - b_state.wheel_up = Pressed; - break; - - case button_down: - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - b_state.wheel_down = Pressed; - break; - - default: - break; - } -} - -//---------------------------------------------------------------------- -bool FApplication::parseX11Mouse() -{ - const FPoint& mouse_position = getMousePos(); - uChar x, y; - - enum x11_btn_states - { - key_shift = 0x04, - key_meta = 0x08, - key_ctrl = 0x10, - key_button_mask = 0x1c, - button1_pressed = 0x20, - button2_pressed = 0x21, - button3_pressed = 0x22, - all_buttons_released = 0x23, - button1_pressed_move = 0x40, - button2_pressed_move = 0x41, - button3_pressed_move = 0x42, - button_mask = 0x63, - button_up = 0x60, - button_down = 0x61 - }; - - x = uChar(x11_mouse[1] - 0x20); - y = uChar(x11_mouse[2] - 0x20); - new_mouse_position.setPoint (x, y); - // fill bit field with 0 - std::memset(&b_state, 0x00, sizeof(b_state)); - - if ( (x11_mouse[0] & key_shift) == key_shift ) - b_state.shift_button = Pressed; - - if ( (x11_mouse[0] & key_meta) == key_meta ) - b_state.meta_button = Pressed; - - if ( (x11_mouse[0] & key_ctrl) == key_ctrl ) - b_state.control_button = Pressed; - - if ( (x11_mouse[0] & button_mask) >= button1_pressed_move - && (x11_mouse[0] & button_mask) <= button3_pressed_move - && mouse_position != *zero_point ) - { - b_state.mouse_moved = true; - } - - getX11ButtonState (x11_mouse[0] & button_mask); - - if ( uChar(x11_mouse[1]) == mouse_position.getX() + 0x20 - && uChar(x11_mouse[2]) == mouse_position.getY() + 0x20 - && b_state.wheel_up != Pressed - && b_state.wheel_down != Pressed - && uChar(x11_mouse[0]) == x11_button_state ) - { - return false; - } - - setMousePos (x, y); - x11_button_state = uChar(x11_mouse[0]); - x11_mouse[0] = '\0'; - return true; -} - -//---------------------------------------------------------------------- -bool FApplication::parseSGRMouse() -{ - const FPoint& mouse_position = getMousePos(); - register char* p; - int button; - short x, y; - - enum x11_ext_btn_states - { - key_shift = 0x04, - key_meta = 0x08, - key_ctrl = 0x10, - key_button_mask = 0x1c, - button1 = 0x00, - button2 = 0x01, - button3 = 0x02, - button1_move = 0x20, - button2_move = 0x21, - button3_move = 0x22, - button_mask = 0x63, - button_up = 0x40, - button_down = 0x41, - pressed = 'M', - released = 'm' - }; - - x = 0; - y = 0; - button = 0; - - // parse the SGR mouse string - p = sgr_mouse; - - while ( *p && *p != ';' ) - { - if ( *p < '0' || *p > '9') - return false; - - button = 10 * button + (*p - '0'); - p++; - } - - while ( *p++ && *p != ';' ) - { - if ( *p < '0' || *p > '9') - return false; - x = short(10 * x + (*p - '0')); - } - - while ( *p++ && *p != 'M' && *p != 'm' ) - { - if ( *p < '0' || *p > '9') - return false; - - y = short(10 * y + (*p - '0')); - } - - new_mouse_position.setPoint (x, y); - // fill bit field with 0 - std::memset(&b_state, 0x00, sizeof(b_state)); - - if ( (button & key_shift) == key_shift ) - b_state.shift_button = Pressed; - - if ( (button & key_meta) == key_meta ) - b_state.meta_button = Pressed; - - if ( (button & key_ctrl) == key_ctrl ) - b_state.control_button = Pressed; - - if ( (button & button_mask) >= button1_move - && (button & button_mask) <= button3_move - && mouse_position != *zero_point ) - { - b_state.mouse_moved = true; - } - - if ( *p == pressed ) - { - switch ( button & button_mask ) - { - case button1: - case button1_move: - if ( mouse_position == new_mouse_position - && (((x11_button_state & 0x80) >> 2) + 'M') == released - && ! isDblclickTimeout(&time_mousepressed) ) - { - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - b_state.left_button = DoubleClick; - } - else - { - time_mousepressed = time_keypressed; // save click time - b_state.left_button = Pressed; - } - break; - - case button2: - case button2_move: - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - b_state.middle_button = Pressed; - break; - - case button3: - case button3_move: - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - b_state.right_button = Pressed; - break; - - case button_up: - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - b_state.wheel_up = Pressed; - break; - - case button_down: - time_mousepressed.tv_sec = 0; - time_mousepressed.tv_usec = 0; - b_state.wheel_down = Pressed; - break; - - default: - break; - } - } - else // *p == released - { - switch ( button & button_mask ) - { - case button1: - case button1_move: - b_state.left_button = Released; - break; - - case button2: - case button2_move: - b_state.middle_button = Released; - break; - - case button3: - case button3_move: - b_state.right_button = Released; - break; - - default: - break; - } - } - - if ( mouse_position == new_mouse_position - && b_state.wheel_up != Pressed - && b_state.wheel_down != Pressed - && x11_button_state == uChar(((*p & 0x20) << 2) + button) ) - { - return false; - } - - setMousePos (x, y); - x11_button_state = uChar(((*p & 0x20) << 2) + button); - sgr_mouse[0] = '\0'; - return true; -} - -//---------------------------------------------------------------------- -bool FApplication::parseUrxvtMouse() -{ - const FPoint& mouse_position = getMousePos(); - register char* p; - register bool x_neg; - register bool y_neg; - int button; - short x, y; - - enum urxvt_btn_states - { - key_shift = 0x04, - key_meta = 0x08, - key_ctrl = 0x10, - key_button_mask = 0x1c, - button1_pressed = 0x20, - button2_pressed = 0x21, - button3_pressed = 0x22, - all_buttons_released = 0x23, - button1_pressed_move = 0x40, - button2_pressed_move = 0x41, - button3_pressed_move = 0x42, - button_mask = 0x63, - button_up = 0x60, - button_down = 0x61, - button_up_move = 0x60, - button_down_move = 0x61 - }; - x = 0; - y = 0; - button = 0; - - // parse the SGR mouse string - p = urxvt_mouse; - x_neg = false; - y_neg = false; - - while ( *p && *p != ';' ) - { - if ( *p < '0' || *p > '9') - return false; - - button = 10 * button + (*p - '0'); - p++; - } - - if ( *++p == '-' ) - { - p++; - x_neg = true; - } - - while ( *p && *p != ';' ) - { - if ( *p < '0' || *p > '9') - return false; - - x = short(10 * x + (*p - '0')); - p++; - } - - if ( *++p == '-' ) - { - p++; - y_neg = true; - } - - while ( *p && *p != 'M' ) - { - if ( *p < '0' || *p > '9') - return false; - - y = short(10 * y + (*p - '0')); - p++; - } - - if ( x_neg || x == 0 ) - x = 1; - - if ( y_neg || y == 0 ) - y = 1; - - if ( x > getDesktopWidth() ) - x = short(getDesktopWidth()); - - if ( y > getDesktopHeight() ) - y = short(getDesktopHeight()); - - new_mouse_position.setPoint (x, y); - // fill bit field with 0 - std::memset(&b_state, 0x00, sizeof(b_state)); - - if ( (button & key_shift) == key_shift ) - b_state.shift_button = Pressed; - - if ( (button & key_meta) == key_meta ) - b_state.meta_button = Pressed; - - if ( (button & key_ctrl) == key_ctrl ) - b_state.control_button = Pressed; - - if ( (button & button_mask) >= button1_pressed_move - && (button & button_mask) <= button3_pressed_move - && mouse_position != *zero_point ) - { - b_state.mouse_moved = true; - } - - getX11ButtonState (button & button_mask); - - if ( mouse_position == new_mouse_position - && b_state.wheel_up != Pressed - && b_state.wheel_down != Pressed - && x11_button_state == uChar(button) ) - { - return false; - } - - setMousePos (x, y); - x11_button_state = uChar(button); - urxvt_mouse[0] = '\0'; - return true; -} - -//---------------------------------------------------------------------- -#ifdef F_HAVE_LIBGPM -bool FApplication::processGpmEvent() -{ - // fill bit field with 0 - std::memset(&b_state, 0x00, sizeof(b_state)); - - if ( Gpm_GetEvent(&gpm_ev) == 1 ) - { - Gpm_FitEvent (&gpm_ev); - - if ( gpm_ev.type & GPM_DRAG && gpm_ev.wdx == 0 && gpm_ev.wdy == 0 ) - b_state.mouse_moved = true; - - if ( gpm_ev.wdy > 0 ) - b_state.wheel_up = Pressed; - else if ( gpm_ev.wdy < 0 ) - b_state.wheel_down = Pressed; - - switch ( gpm_ev.type & 0x0f ) - { - case GPM_DOWN: - case GPM_DRAG: - if ( gpm_ev.buttons & GPM_B_LEFT ) - { - if ( gpm_ev.type & GPM_DOUBLE ) - b_state.left_button = DoubleClick; - else - b_state.left_button = Pressed; - } - - if ( gpm_ev.buttons & GPM_B_MIDDLE ) - b_state.middle_button = Pressed; - - if ( gpm_ev.buttons & GPM_B_RIGHT ) - b_state.right_button = Pressed; - - if ( gpm_ev.buttons & GPM_B_UP ) - b_state.wheel_up = Pressed; - - if ( gpm_ev.buttons & GPM_B_DOWN ) - b_state.wheel_down = Pressed; - - // keyboard modifiers - if ( gpm_ev.modifiers & (1 << KG_SHIFT) ) - b_state.shift_button = Pressed; - - if ( gpm_ev.modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)) ) - b_state.meta_button = Pressed; - - if ( gpm_ev.modifiers & (1 << KG_CTRL) ) - b_state.control_button = Pressed; - - break; - - case GPM_UP: - if ( gpm_ev.buttons & GPM_B_LEFT ) - b_state.left_button = Released; - - if ( gpm_ev.buttons & GPM_B_MIDDLE ) - b_state.middle_button = Released; - - if ( gpm_ev.buttons & GPM_B_RIGHT ) - b_state.right_button = Released; - - default: - break; - } - - setMousePos (gpm_ev.x, gpm_ev.y); - - if ( gpmEvent(false) == mouse_event ) - unprocessedInput() = true; - else - unprocessedInput() = false; - - GPM_DRAWPOINTER(&gpm_ev); - gpmMouseEvent = false; - - return true; - } - - gpmMouseEvent = false; - return false; -} -#endif // F_HAVE_LIBGPM - //---------------------------------------------------------------------- bool FApplication::getMouseEvent() { - bool Event = false; + bool mouse_event_occurred = false; + FMouseControl* mouse = getMouseControl(); -#ifdef F_HAVE_LIBGPM - if ( ! gpmMouseEvent - && x11_mouse[0] == '\0' - && sgr_mouse[0] == '\0' - && urxvt_mouse[0] == '\0' ) + if ( mouse && mouse->hasData() ) { - return false; + mouse->processEvent (&time_keypressed); + unprocessedInput() = mouse->isInputDataPending(); + mouse_event_occurred = mouse->hasEvent(); } -#else - if ( x11_mouse[0] == '\0' - && sgr_mouse[0] == '\0' - && urxvt_mouse[0] == '\0' ) - { - return false; - } -#endif -#ifdef F_HAVE_LIBGPM - if ( gpmMouseEvent ) - Event = processGpmEvent(); -#endif - - if ( x11_mouse[0] ) - Event = parseX11Mouse(); - - if ( sgr_mouse[0] ) - Event = parseSGRMouse(); - - if ( urxvt_mouse[0] ) - Event = parseUrxvtMouse(); - - if ( ! Event ) - return false; - - return true; + return mouse_event_occurred; } //---------------------------------------------------------------------- @@ -1828,15 +1122,20 @@ FWidget*& FApplication::determineClickedWidget() if ( clicked_widget ) return clicked_widget; - if ( b_state.left_button != Pressed - && b_state.left_button != DoubleClick - && b_state.right_button != Pressed - && b_state.middle_button != Pressed - && b_state.wheel_up != Pressed - && b_state.wheel_down != Pressed ) + FMouseControl* mouse = getMouseControl(); + + if ( ! mouse ) return clicked_widget; - const FPoint& mouse_position = getMousePos(); + if ( ! mouse->isLeftButtonPressed() + && ! mouse->isLeftButtonDoubleClick() + && ! mouse->isRightButtonPressed() + && ! mouse->isMiddleButtonPressed() + && ! mouse->isWheelUp() + && ! mouse->isWheelDown() ) + return clicked_widget; + + const FPoint& mouse_position = mouse->getPos(); // Determine the window object on the current click position FWidget* window = FWindow::getWindowWidgetAt (mouse_position); @@ -1868,14 +1167,20 @@ void FApplication::closeOpenMenu() { // Close the open menu - if ( ! open_menu || b_state.mouse_moved ) + FMouseControl* mouse = getMouseControl(); + + if ( ! open_menu || ( mouse && mouse->isMoved()) ) return; FMenu* menu = static_cast(open_menu); - const FPoint& mouse_position = getMousePos(); - if ( menu->containsMenuStructure(mouse_position) ) - return; + if ( mouse ) + { + const FPoint& mouse_position = mouse->getPos(); + + if ( menu->containsMenuStructure(mouse_position) ) + return; + } bool is_window_menu; FWidget* super = menu->getSuperMenu(); @@ -1906,7 +1211,9 @@ void FApplication::unselectMenubarItems() { // Unselect the menu bar items - if ( open_menu || b_state.mouse_moved ) + FMouseControl* mouse = getMouseControl(); + + if ( open_menu || (mouse && mouse->isMoved()) ) return; FMenuBar* menubar = getMenuBar(); @@ -1917,7 +1224,10 @@ void FApplication::unselectMenubarItems() if ( ! menubar->hasSelectedItem() ) return; - const FPoint& mouse_position = getMousePos(); + if ( ! mouse ) + return; + + const FPoint& mouse_position = mouse->getPos(); if ( ! getMenuBar()->getTermGeometry().contains(mouse_position) ) { @@ -1945,22 +1255,27 @@ void FApplication::sendMouseEvent() if ( ! clicked_widget ) return; + FMouseControl* mouse = getMouseControl(); + + if ( ! mouse ) + return; + FPoint widgetMousePos; - const FPoint& mouse_position = getMousePos(); + const FPoint& mouse_position = mouse->getPos(); int key_state = 0; - if ( b_state.shift_button == Pressed ) + if ( mouse->isShiftKeyPressed() ) key_state |= fc::ShiftButton; - if ( b_state.meta_button == Pressed ) - key_state |= fc::MetaButton; - - if ( b_state.control_button == Pressed ) + if ( mouse->isControlKeyPressed() ) key_state |= fc::ControlButton; + if ( mouse->isMetaKeyPressed() ) + key_state |= fc::MetaButton; + widgetMousePos = clicked_widget->termToWidgetPos(mouse_position); - if ( b_state.mouse_moved ) + if ( mouse->isMoved() ) { sendMouseMoveEvent (widgetMousePos, mouse_position, key_state); } @@ -1972,6 +1287,7 @@ void FApplication::sendMouseEvent() } sendWheelEvent (widgetMousePos, mouse_position); + mouse->clearEvent(); } //---------------------------------------------------------------------- @@ -1979,7 +1295,12 @@ void FApplication::sendMouseMoveEvent ( const FPoint& widgetMousePos , const FPoint& mouse_position , int key_state ) { - if ( b_state.left_button == Pressed ) + FMouseControl* mouse = getMouseControl(); + + if ( ! mouse ) + return; + + if ( mouse->isLeftButtonPressed() ) { FMouseEvent m_down_ev ( fc::MouseMove_Event , widgetMousePos @@ -1988,7 +1309,7 @@ void FApplication::sendMouseMoveEvent ( const FPoint& widgetMousePos sendEvent (clicked_widget, &m_down_ev); } - if ( b_state.right_button == Pressed ) + if ( mouse->isRightButtonPressed() ) { FMouseEvent m_down_ev ( fc::MouseMove_Event , widgetMousePos @@ -1997,7 +1318,7 @@ void FApplication::sendMouseMoveEvent ( const FPoint& widgetMousePos sendEvent (clicked_widget, &m_down_ev); } - if ( b_state.middle_button == Pressed ) + if ( mouse->isMiddleButtonPressed() ) { FMouseEvent m_down_ev ( fc::MouseMove_Event , widgetMousePos @@ -2012,7 +1333,12 @@ void FApplication::sendMouseLeftClickEvent ( const FPoint& widgetMousePos , const FPoint& mouse_position , int key_state ) { - if ( b_state.left_button == DoubleClick ) + FMouseControl* mouse = getMouseControl(); + + if ( ! mouse ) + return; + + if ( mouse->isLeftButtonDoubleClick() ) { FMouseEvent m_dblclick_ev ( fc::MouseDoubleClick_Event , widgetMousePos @@ -2020,7 +1346,7 @@ void FApplication::sendMouseLeftClickEvent ( const FPoint& widgetMousePos , fc::LeftButton | key_state ); sendEvent (clicked_widget, &m_dblclick_ev); } - else if ( b_state.left_button == Pressed ) + else if ( mouse->isLeftButtonPressed() ) { FMouseEvent m_down_ev ( fc::MouseDown_Event , widgetMousePos @@ -2028,7 +1354,7 @@ void FApplication::sendMouseLeftClickEvent ( const FPoint& widgetMousePos , fc::LeftButton | key_state ); sendEvent (clicked_widget, &m_down_ev); } - else if ( b_state.left_button == Released ) + else if ( mouse->isLeftButtonReleased() ) { FMouseEvent m_up_ev ( fc::MouseUp_Event , widgetMousePos @@ -2036,8 +1362,8 @@ void FApplication::sendMouseLeftClickEvent ( const FPoint& widgetMousePos , fc::LeftButton | key_state ); FWidget* released_widget = clicked_widget; - if ( b_state.right_button != Pressed - && b_state.middle_button != Pressed ) + if ( ! mouse->isRightButtonPressed() + && ! mouse->isMiddleButtonPressed() ) clicked_widget = 0; sendEvent (released_widget, &m_up_ev); @@ -2049,7 +1375,12 @@ void FApplication::sendMouseRightClickEvent ( const FPoint& widgetMousePos , const FPoint& mouse_position , int key_state ) { - if ( b_state.right_button == Pressed ) + FMouseControl* mouse = getMouseControl(); + + if ( ! mouse ) + return; + + if ( mouse->isRightButtonPressed() ) { FMouseEvent m_down_ev ( fc::MouseDown_Event , widgetMousePos @@ -2057,7 +1388,7 @@ void FApplication::sendMouseRightClickEvent ( const FPoint& widgetMousePos , fc::RightButton | key_state ); sendEvent (clicked_widget, &m_down_ev); } - else if ( b_state.right_button == Released ) + else if ( mouse->isRightButtonReleased() ) { FMouseEvent m_up_ev ( fc::MouseUp_Event , widgetMousePos @@ -2065,8 +1396,8 @@ void FApplication::sendMouseRightClickEvent ( const FPoint& widgetMousePos , fc::RightButton | key_state ); FWidget* released_widget = clicked_widget; - if ( b_state.left_button != Pressed - && b_state.middle_button != Pressed ) + if ( ! mouse->isLeftButtonPressed() + && ! mouse->isMiddleButtonPressed() ) clicked_widget = 0; sendEvent (released_widget, &m_up_ev); @@ -2078,7 +1409,12 @@ void FApplication::sendMouseMiddleClickEvent ( const FPoint& widgetMousePos , const FPoint& mouse_position , int key_state ) { - if ( b_state.middle_button == Pressed ) + FMouseControl* mouse = getMouseControl(); + + if ( ! mouse ) + return; + + if ( mouse->isMiddleButtonPressed() ) { FMouseEvent m_down_ev ( fc::MouseDown_Event , widgetMousePos @@ -2090,7 +1426,7 @@ void FApplication::sendMouseMiddleClickEvent ( const FPoint& widgetMousePos if ( isGnomeTerminal() ) clicked_widget = 0; } - else if ( b_state.middle_button == Released ) + else if ( mouse->isMiddleButtonReleased() ) { FMouseEvent m_up_ev ( fc::MouseUp_Event , widgetMousePos @@ -2098,37 +1434,8 @@ void FApplication::sendMouseMiddleClickEvent ( const FPoint& widgetMousePos , fc::MiddleButton | key_state ); FWidget* released_widget = clicked_widget; - if ( b_state.right_button != Pressed - && b_state.left_button != Pressed ) - { - clicked_widget = 0; - } - - sendEvent (released_widget, &m_up_ev); - } - - if ( b_state.middle_button == Pressed ) - { - FMouseEvent m_down_ev ( fc::MouseDown_Event - , widgetMousePos - , mouse_position - , fc::MiddleButton | key_state ); - sendEvent (clicked_widget, &m_down_ev); - - // gnome-terminal sends no released on middle click - if ( isGnomeTerminal() ) - clicked_widget = 0; - } - else if ( b_state.middle_button == Released ) - { - FMouseEvent m_up_ev ( fc::MouseUp_Event - , widgetMousePos - , mouse_position - , fc::MiddleButton | key_state ); - FWidget* released_widget = clicked_widget; - - if ( b_state.right_button != Pressed - && b_state.left_button != Pressed ) + if ( ! mouse->isLeftButtonPressed() + && ! mouse->isRightButtonPressed() ) { clicked_widget = 0; } @@ -2141,7 +1448,12 @@ void FApplication::sendMouseMiddleClickEvent ( const FPoint& widgetMousePos void FApplication::sendWheelEvent ( const FPoint& widgetMousePos , const FPoint& mouse_position ) { - if ( b_state.wheel_up == Pressed ) + FMouseControl* mouse = getMouseControl(); + + if ( ! mouse ) + return; + + if ( mouse->isWheelUp() ) { FWheelEvent wheel_ev ( fc::MouseWheel_Event , widgetMousePos @@ -2152,7 +1464,7 @@ void FApplication::sendWheelEvent ( const FPoint& widgetMousePos sendEvent(scroll_over_widget, &wheel_ev); } - if ( b_state.wheel_down == Pressed ) + if ( mouse->isWheelDown() ) { FWheelEvent wheel_ev ( fc::MouseWheel_Event , widgetMousePos @@ -2167,6 +1479,8 @@ void FApplication::sendWheelEvent ( const FPoint& widgetMousePos //---------------------------------------------------------------------- void FApplication::processMouseEvent() { + FMouseControl* mouse = getMouseControl(); + if ( ! getMouseEvent() ) return; @@ -2176,10 +1490,8 @@ void FApplication::processMouseEvent() unselectMenubarItems(); sendMouseEvent(); -#ifdef F_HAVE_LIBGPM - if ( isGpmMouseEnabled() && gpm_ev.x != -1 ) - GPM_DRAWPOINTER(&gpm_ev); -#endif + if ( mouse ) + mouse->drawGpmPointer(); } //---------------------------------------------------------------------- diff --git a/src/fbutton.cpp b/src/fbutton.cpp index fdd3b5e9..e2e6f78d 100644 --- a/src/fbutton.cpp +++ b/src/fbutton.cpp @@ -401,6 +401,7 @@ void FButton::onMouseMove (FMouseEvent* ev) void FButton::onTimer (FTimerEvent* ev) { delTimer(ev->timerId()); + clearShadow(); setUp(); } @@ -587,9 +588,7 @@ inline int FButton::clickAnimationIndent (FWidget* parent_widget) //---------------------------------------------------------------------- inline void FButton::clearRightMargin (FWidget* parent_widget) { - if ( button_down - || isNewFont() - || ( ! is.flat && hasShadow() && ! isMonochron()) ) + if ( button_down || isNewFont() ) return; // Restore the right background after button down diff --git a/src/fmouse.cpp b/src/fmouse.cpp new file mode 100644 index 00000000..75fcd3a1 --- /dev/null +++ b/src/fmouse.cpp @@ -0,0 +1,1587 @@ +/*********************************************************************** +* fmouse.cpp - Read mouse events * +* * +* This file is part of the Final Cut widget toolkit * +* * +* Copyright 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 * +* as published by the Free Software Foundation; either version 3 of * +* the License, or (at your option) any later version. * +* * +* The Final Cut is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public * +* License along with this program. If not, see * +* . * +***********************************************************************/ + +#include +#include +#include +#include +#include + +#include "final/fmouse.h" +#include "final/fterm.h" + + +//---------------------------------------------------------------------- +// class FMouse +//---------------------------------------------------------------------- + +// constructors and destructor +//---------------------------------------------------------------------- +FMouse::FMouse() + : b_state() + , mouse_event_occurred(false) + , input_data_pending(false) + , dblclick_interval(500000) // 500 ms + , max_width(80) + , max_height(25) + , time_mousepressed() + , zero_point(0,0) // zero point (x=0, y=0) + , mouse(0,0) // mouse click position + , new_mouse_position() +{ + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + + // init bit field with 0 + std::memset(&b_state, 0x00, sizeof(b_state)); +} + + +// public methods of FMouse +//---------------------------------------------------------------------- +const char* FMouse::getClassName() const +{ + return "FMouse"; +} + +//---------------------------------------------------------------------- +inline FPoint& FMouse::getPos() +{ + return mouse; +} + +//---------------------------------------------------------------------- +inline void FMouse::clearEvent() +{ + mouse_event_occurred = false; +} + +//---------------------------------------------------------------------- +inline void FMouse::setMaxWidth (short x_max) +{ + max_width = x_max; +} + +//---------------------------------------------------------------------- +inline void FMouse::setMaxHeight (short y_max) +{ + max_height = y_max; +} + +//---------------------------------------------------------------------- +inline bool FMouse::hasEvent() +{ + return mouse_event_occurred; +} + +//---------------------------------------------------------------------- +inline bool FMouse::isLeftButtonPressed() +{ + return bool(b_state.left_button == Pressed); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isLeftButtonReleased() +{ + return bool(b_state.left_button == Released); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isLeftButtonDoubleClick() +{ + return bool(b_state.left_button == DoubleClick); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isRightButtonPressed() +{ + return bool(b_state.right_button == Pressed); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isRightButtonReleased() +{ + return bool(b_state.right_button == Released); +} +//---------------------------------------------------------------------- +inline bool FMouse::isMiddleButtonPressed() +{ + return bool(b_state.middle_button == Pressed); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isMiddleButtonReleased() +{ + return bool(b_state.middle_button == Released); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isShiftKeyPressed() +{ + return bool(b_state.shift_button); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isControlKeyPressed() +{ + return bool(b_state.control_button); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isMetaKeyPressed() +{ + return bool(b_state.meta_button); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isWheelUp() +{ + return bool(b_state.wheel_up); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isWheelDown() +{ + return bool(b_state.wheel_down); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isMoved() +{ + return bool(b_state.mouse_moved); +} + +//---------------------------------------------------------------------- +inline bool FMouse::isInputDataPending() +{ + return input_data_pending; +} + +//---------------------------------------------------------------------- +inline FMouse* FMouse::createMouseObject (mouse_type mt) +{ + switch ( mt ) + { + case none: + return 0; + + case gpm: + return new FMouseGPM; + + case x11: + return new FMouseX11; + + case sgr: + return new FMouseSGR; + + case urxvt: + return new FMouseUrxvt; + } + + return new FMouseX11; +} + + +// protected methods of FMouse +//---------------------------------------------------------------------- +void FMouse::setPos (const FPoint& m) +{ + mouse = m; +} + +//---------------------------------------------------------------------- +bool FMouse::isDblclickTimeout (timeval* time) +{ + return FObject::isTimeout (time, dblclick_interval); +} + + +#ifdef F_HAVE_LIBGPM +//---------------------------------------------------------------------- +// class FMouseGPM +//---------------------------------------------------------------------- + +// constructors and destructor +//---------------------------------------------------------------------- +FMouseGPM::FMouseGPM() + : FMouse() + , gpm_ev() + , has_gpm_mouse_data(false) + , gpm_mouse_enabled(false) + , stdin_no(0) +{ + gpm_ev.x = -1; +} + +//---------------------------------------------------------------------- +FMouseGPM::~FMouseGPM() // destructor +{ } + + +// public methods of FMouseX11 +//---------------------------------------------------------------------- +void FMouseGPM::setStdinNo (int file_descriptor) +{ + stdin_no = file_descriptor; +} + +//---------------------------------------------------------------------- +bool FMouseGPM::hasData() +{ + return has_gpm_mouse_data; +} + +//---------------------------------------------------------------------- +void FMouseGPM::setRawData (char[], int) +{ } + +//---------------------------------------------------------------------- +void FMouseGPM::processEvent (struct timeval*) +{ + // Fill bit field with 0 + std::memset(&b_state, 0x00, sizeof(b_state)); + + if ( Gpm_GetEvent(&gpm_ev) == 1 ) + { + Gpm_FitEvent (&gpm_ev); + + if ( gpm_ev.type & GPM_DRAG && gpm_ev.wdx == 0 && gpm_ev.wdy == 0 ) + b_state.mouse_moved = true; + + if ( gpm_ev.wdy > 0 ) + b_state.wheel_up = true; + else if ( gpm_ev.wdy < 0 ) + b_state.wheel_down = true; + + switch ( gpm_ev.type & 0x0f ) + { + case GPM_DOWN: + case GPM_DRAG: + if ( gpm_ev.buttons & GPM_B_LEFT ) + { + if ( gpm_ev.type & GPM_DOUBLE ) + b_state.left_button = DoubleClick; + else + b_state.left_button = Pressed; + } + + if ( gpm_ev.buttons & GPM_B_MIDDLE ) + b_state.middle_button = Pressed; + + if ( gpm_ev.buttons & GPM_B_RIGHT ) + b_state.right_button = Pressed; + + if ( gpm_ev.buttons & GPM_B_UP ) + b_state.wheel_up = true; + + if ( gpm_ev.buttons & GPM_B_DOWN ) + b_state.wheel_down = true; + + // Keyboard modifiers + if ( gpm_ev.modifiers & (1 << KG_SHIFT) ) + b_state.shift_button = true; + + if ( gpm_ev.modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)) ) + b_state.meta_button = true; + + if ( gpm_ev.modifiers & (1 << KG_CTRL) ) + b_state.control_button = true; + + break; + + case GPM_UP: + if ( gpm_ev.buttons & GPM_B_LEFT ) + b_state.left_button = Released; + + if ( gpm_ev.buttons & GPM_B_MIDDLE ) + b_state.middle_button = Released; + + if ( gpm_ev.buttons & GPM_B_RIGHT ) + b_state.right_button = Released; + + default: + break; + } + + setPos (FPoint(gpm_ev.x, gpm_ev.y)); + + if ( gpmEvent(false) == mouse_event ) + input_data_pending = true; + else + input_data_pending = false; + + GPM_DRAWPOINTER(&gpm_ev); + has_gpm_mouse_data = false; + mouse_event_occurred = true; + return; + } + + has_gpm_mouse_data = false; + mouse_event_occurred = false; +} + +//---------------------------------------------------------------------- +bool FMouseGPM::gpmMouse (bool on) +{ + // activate/deactivate the gpm mouse support + + if ( on ) + { + Gpm_Connect conn; + conn.eventMask = uInt16(~GPM_MOVE); + conn.defaultMask = GPM_MOVE; + conn.maxMod = uInt16(~0); + conn.minMod = 0; + Gpm_Open(&conn, 0); + + switch ( gpm_fd ) + { + case -1: + return false; + + case -2: + Gpm_Close(); + return false; + + default: + break; + } + } + else + { + Gpm_Close(); + } + + gpm_mouse_enabled = on; + return on; +} + +//---------------------------------------------------------------------- +bool FMouseGPM::getGpmKeyPressed (bool pending) +{ + input_data_pending = pending; + has_gpm_mouse_data = false; + int type = gpmEvent(); + + switch ( type ) + { + case mouse_event: + has_gpm_mouse_data = true; + break; + + case keyboard_event: + return true; + + default: + return false; + } + + return false; +} + +//---------------------------------------------------------------------- +void FMouseGPM::drawGpmPointer() +{ + if ( isGpmMouseEnabled() && gpm_ev.x != -1 ) + GPM_DRAWPOINTER(&gpm_ev); +} + +//---------------------------------------------------------------------- +int FMouseGPM::gpmEvent (bool clear) +{ + register int result; + register int max = ( gpm_fd > stdin_no ) ? gpm_fd : stdin_no; + fd_set ifds; + struct timeval tv; + + FD_ZERO(&ifds); + FD_SET(stdin_no, &ifds); + FD_SET(gpm_fd, &ifds); + tv.tv_sec = 0; + tv.tv_usec = 100000; // 100 ms + result = select (max + 1, &ifds, 0, 0, &tv); + + if ( result > 0 && FD_ISSET(stdin_no, &ifds) ) + { + if ( clear ) + FD_CLR (stdin_no, &ifds); + + return keyboard_event; + } + + if ( clear && result > 0 && FD_ISSET(gpm_fd, &ifds) ) + FD_CLR (gpm_fd, &ifds); + + if ( result > 0 ) + return mouse_event; + else + return no_event; +} +#endif + + +//---------------------------------------------------------------------- +// class FMouseX11 +//---------------------------------------------------------------------- + +// constructors and destructor +//---------------------------------------------------------------------- +FMouseX11::FMouseX11() + : FMouse() + , x11_mouse() + , x11_button_state(all_buttons_released) +{ + x11_mouse[0] = '\0'; +} + +//---------------------------------------------------------------------- +FMouseX11::~FMouseX11() // destructor +{ } + + +// public methods of FMouseX11 +//---------------------------------------------------------------------- +bool FMouseX11::hasData() +{ + return bool(x11_mouse[0]); +} + +//---------------------------------------------------------------------- +void FMouseX11::setRawData (char fifo_buf[], int fifo_buf_size) +{ + // Import the X11 xterm mouse protocol (SGR-Mode) raw mouse data + + static const int len = 6; + int n; + x11_mouse[0] = fifo_buf[3]; + x11_mouse[1] = fifo_buf[4]; + x11_mouse[2] = fifo_buf[5]; + x11_mouse[3] = '\0'; + + // Remove founded entry + for (n = len; n < fifo_buf_size; n++) + fifo_buf[n - len] = fifo_buf[n]; + + n = fifo_buf_size - len - 1; + + // Fill rest with '\0' + for (; n < fifo_buf_size; n++) + fifo_buf[n - len] = '\0'; + + input_data_pending = bool(fifo_buf[0] != '\0'); +} + +//---------------------------------------------------------------------- +void FMouseX11::processEvent (struct timeval* time) +{ + // Parse and interpret the X11 xterm mouse string + + const FPoint& mouse_position = getPos(); + uChar x, y; + int button; + + x = uChar(x11_mouse[1] - 0x20); + y = uChar(x11_mouse[2] - 0x20); + button = x11_mouse[0]; + new_mouse_position.setPoint (x, y); + // Fill bit field with 0 + std::memset(&b_state, 0x00, sizeof(b_state)); + setKeyState (button); + setMoveState (mouse_position, button); + setButtonState (button & button_mask, time); + + if ( new_mouse_position == mouse_position + && ! isWheelUp() + && ! isWheelDown() + && uChar(button) == x11_button_state ) + { + mouse_event_occurred = false; + return; + } + + mouse_event_occurred = true; + setPos (FPoint(x, y)); + // Get the button state from string + x11_button_state = uChar(button); + // Delete already interpreted data + x11_mouse[0] = '\0'; +} + + +// private methods of FMouseX11 +//---------------------------------------------------------------------- +void FMouseX11::setKeyState (int button) +{ + if ( (button & key_shift) == key_shift ) + b_state.shift_button = Pressed; + + if ( (button & key_meta) == key_meta ) + b_state.meta_button = Pressed; + + if ( (button & key_ctrl) == key_ctrl ) + b_state.control_button = Pressed; +} + +//---------------------------------------------------------------------- +void FMouseX11::setMoveState (const FPoint& mouse_position, int button) +{ + if ( (button & button_mask) >= button1_pressed_move + && (button & button_mask) <= button3_pressed_move + && mouse_position != zero_point ) + { + b_state.mouse_moved = true; + } +} + +//---------------------------------------------------------------------- +void FMouseX11::setButtonState (int button, struct timeval* time) +{ + // Get the x11 mouse button state + + const FPoint& mouse_position = getPos(); + + switch ( button ) + { + case button1_pressed: + case button1_pressed_move: + if ( mouse_position == new_mouse_position + && x11_button_state == all_buttons_released + && ! isDblclickTimeout(&time_mousepressed) ) + { + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.left_button = DoubleClick; + } + else + { + time_mousepressed = *time; // save click time + b_state.left_button = Pressed; + } + break; + + case button2_pressed: + case button2_pressed_move: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.middle_button = Pressed; + break; + + case button3_pressed: + case button3_pressed_move: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.right_button = Pressed; + break; + + case all_buttons_released: + switch ( x11_button_state & button_mask ) + { + case button1_pressed: + case button1_pressed_move: + b_state.left_button = Released; + break; + + case button2_pressed: + case button2_pressed_move: + b_state.middle_button = Released; + break; + + case button3_pressed: + case button3_pressed_move: + b_state.right_button = Released; + break; + + default: + break; + } + break; + + case button_up: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.wheel_up = Pressed; + break; + + case button_down: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.wheel_down = Pressed; + break; + + default: + break; + } +} + + +//---------------------------------------------------------------------- +// class FMouseSGR +//---------------------------------------------------------------------- + +// constructors and destructor +//---------------------------------------------------------------------- +FMouseSGR::FMouseSGR() + : FMouse() + , sgr_mouse() + , sgr_button_state(0x23) +{ + sgr_mouse[0] = '\0'; +} + +//---------------------------------------------------------------------- +FMouseSGR::~FMouseSGR() // destructor +{ } + + +// public methods of FMouseSGR +//---------------------------------------------------------------------- +bool FMouseSGR::hasData() +{ + return bool(sgr_mouse[0]); +} + +//---------------------------------------------------------------------- +void FMouseSGR::setRawData (char fifo_buf[], int fifo_buf_size) +{ + // Import the X11 xterm mouse protocol (SGR-Mode) raw mouse data + + int len = int(std::strlen(fifo_buf)); + int n = 3; + + while ( n < len && n < fifo_buf_size ) + { + sgr_mouse[n - 3] = fifo_buf[n]; + n++; + + if ( fifo_buf[n] == 'M' || fifo_buf[n] == 'm' ) + len = n + 1; + } + + sgr_mouse[n - 3] = '\0'; + + for (n = len; n < fifo_buf_size; n++) // Remove founded entry + fifo_buf[n - len] = fifo_buf[n]; + + n = fifo_buf_size - len - 1; + + for (; n < fifo_buf_size; n++) // Fill rest with '\0' + fifo_buf[n - len] = '\0'; + + input_data_pending = bool(fifo_buf[0] != '\0'); +} + +//---------------------------------------------------------------------- +void FMouseSGR::processEvent (struct timeval* time) +{ + const FPoint& mouse_position = getPos(); + register char* p; + int button; + short x, y; + + x = 0; + y = 0; + button = 0; + + // parse the SGR mouse string + p = sgr_mouse; + + while ( *p && *p != ';' ) + { + if ( *p < '0' || *p > '9') + { + mouse_event_occurred = false; + return; + } + + button = 10 * button + (*p - '0'); + p++; + } + + while ( *p++ && *p != ';' ) + { + if ( *p < '0' || *p > '9') + { + mouse_event_occurred = false; + return; + } + + x = short(10 * x + (*p - '0')); + } + + while ( *p++ && *p != 'M' && *p != 'm' ) + { + if ( *p < '0' || *p > '9') + { + mouse_event_occurred = false; + return; + } + + y = short(10 * y + (*p - '0')); + } + + new_mouse_position.setPoint (x, y); + // Fill bit field with 0 + std::memset(&b_state, 0x00, sizeof(b_state)); + setKeyState (button); + setMoveState (mouse_position, button); + + if ( *p == pressed ) + setPressedButtonState (button & button_mask, time); + else // *p == released + setReleasedButtonState (button & button_mask); + + if ( mouse_position == new_mouse_position + && ! isWheelUp() + && ! isWheelDown() + && sgr_button_state == uChar(((*p & 0x20) << 2) + button) ) + { + mouse_event_occurred = false; + return; + } + + mouse_event_occurred = true; + setPos (FPoint(x, y)); + // Get the button state from string + sgr_button_state = uChar(((*p & 0x20) << 2) + button); + // Delete already interpreted data + sgr_mouse[0] = '\0'; +} + +// private methods of FMouseSGR +//---------------------------------------------------------------------- +void FMouseSGR::setKeyState (int button) +{ + if ( (button & key_shift) == key_shift ) + b_state.shift_button = true; + + if ( (button & key_meta) == key_meta ) + b_state.meta_button = true; + + if ( (button & key_ctrl) == key_ctrl ) + b_state.control_button = true; +} + +//---------------------------------------------------------------------- +void FMouseSGR::setMoveState (const FPoint& mouse_position, int button) +{ + if ( (button & button_mask) >= button1_move + && (button & button_mask) <= button3_move + && mouse_position != zero_point ) + { + b_state.mouse_moved = true; + } +} + +//---------------------------------------------------------------------- +void FMouseSGR::setPressedButtonState (int button, struct timeval* time) +{ + // Gets the extended x11 mouse mode (SGR) status for pressed buttons + + const FPoint& mouse_position = getPos(); + + switch ( button ) + { + case button1: + case button1_move: + if ( mouse_position == new_mouse_position + && (((sgr_button_state & 0x80) >> 2) + 'M') == released + && ! isDblclickTimeout(&time_mousepressed) ) + { + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.left_button = DoubleClick; + } + else + { + time_mousepressed = *time; // save click time + b_state.left_button = Pressed; + } + break; + + case button2: + case button2_move: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.middle_button = Pressed; + break; + + case button3: + case button3_move: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.right_button = Pressed; + break; + + case button_up: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.wheel_up = true; + break; + + case button_down: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.wheel_down = true; + break; + + default: + break; + } +} + +//---------------------------------------------------------------------- +void FMouseSGR::setReleasedButtonState (int button) +{ + // Gets the extended x11 mouse mode (SGR) status for released buttons + + switch ( button ) + { + case button1: + case button1_move: + b_state.left_button = Released; + break; + + case button2: + case button2_move: + b_state.middle_button = Released; + break; + + case button3: + case button3_move: + b_state.right_button = Released; + break; + + default: + break; + } +} + + +//---------------------------------------------------------------------- +// class FMouseUrxvt +//---------------------------------------------------------------------- + +// constructors and destructor +//---------------------------------------------------------------------- +FMouseUrxvt::FMouseUrxvt() + : FMouse() + , urxvt_mouse() + , urxvt_button_state(0x23) +{ + urxvt_mouse[0] = '\0'; +} + +//---------------------------------------------------------------------- +FMouseUrxvt::~FMouseUrxvt() // destructor +{ } + + +// public methods of FMouseUrxvt +//---------------------------------------------------------------------- +bool FMouseUrxvt::hasData() +{ + return bool(urxvt_mouse[0]); +} + +//---------------------------------------------------------------------- +void FMouseUrxvt::setRawData (char fifo_buf[], int fifo_buf_size) +{ + // Import the X11 xterm mouse protocol (Urxvt-Mode) raw mouse data + + int len = int(std::strlen(fifo_buf)); + int n = 2; + + while ( n < len && n < fifo_buf_size ) + { + urxvt_mouse[n - 2] = fifo_buf[n]; + n++; + + if ( fifo_buf[n] == 'M' || fifo_buf[n] == 'm' ) + len = n + 1; + } + + urxvt_mouse[n - 2] = '\0'; + + for (n = len; n < fifo_buf_size; n++) // Remove founded entry + fifo_buf[n - len] = fifo_buf[n]; + + n = fifo_buf_size - len - 1; + + for (; n < fifo_buf_size; n++) // Fill rest with '\0' + fifo_buf[n - len] = '\0'; + + input_data_pending = bool(fifo_buf[0] != '\0'); +} + +//---------------------------------------------------------------------- +void FMouseUrxvt::processEvent (struct timeval* time) +{ + // Parse and interpret the X11 xterm mouse string (Urxvt-Mode) + + const FPoint& mouse_position = getPos(); + register char* p; + register bool x_neg; + register bool y_neg; + int button; + short x, y; + + x = 0; + y = 0; + button = 0; + + // Parse the Urxvt mouse string + p = urxvt_mouse; + x_neg = false; + y_neg = false; + + while ( *p && *p != ';' ) + { + if ( *p < '0' || *p > '9') + { + mouse_event_occurred = false; + return; + } + + button = 10 * button + (*p - '0'); + p++; + } + + if ( *++p == '-' ) + { + p++; + x_neg = true; + } + + while ( *p && *p != ';' ) + { + if ( *p < '0' || *p > '9') + { + mouse_event_occurred = false; + return; + } + + x = short(10 * x + (*p - '0')); + p++; + } + + if ( *++p == '-' ) + { + p++; + y_neg = true; + } + + while ( *p && *p != 'M' ) + { + if ( *p < '0' || *p > '9') + { + mouse_event_occurred = false; + return; + } + + y = short(10 * y + (*p - '0')); + p++; + } + + if ( x_neg || x == 0 ) + x = 1; + + if ( y_neg || y == 0 ) + y = 1; + + if ( x > max_width ) + x = max_height; + + if ( y > max_height ) + y = max_height; + + new_mouse_position.setPoint (x, y); + // Fill bit field with 0 + std::memset(&b_state, 0x00, sizeof(b_state)); + setKeyState (button); + setMoveState (mouse_position, button); + setButtonState (button & button_mask, time); + + if ( mouse_position == new_mouse_position + && ! isWheelUp() + && ! isWheelDown() + && urxvt_button_state == uChar(button) ) + { + mouse_event_occurred = false; + return; + } + + mouse_event_occurred = true; + setPos (FPoint(x, y)); + urxvt_button_state = uChar(button); + urxvt_mouse[0] = '\0'; +} + + +// private methods of FMouseUrxvt +//---------------------------------------------------------------------- +void FMouseUrxvt::setKeyState (int button) +{ + if ( (button & key_shift) == key_shift ) + b_state.shift_button = Pressed; + + if ( (button & key_meta) == key_meta ) + b_state.meta_button = Pressed; + + if ( (button & key_ctrl) == key_ctrl ) + b_state.control_button = Pressed; +} + +//---------------------------------------------------------------------- +void FMouseUrxvt::setMoveState (const FPoint& mouse_position, int button) +{ + if ( (button & button_mask) >= button1_pressed_move + && (button & button_mask) <= button3_pressed_move + && mouse_position != zero_point ) + { + b_state.mouse_moved = true; + } +} + +//---------------------------------------------------------------------- +void FMouseUrxvt::setButtonState (int button, struct timeval* time) +{ + // Get the urxvt mouse button state + + const FPoint& mouse_position = getPos(); + + switch ( button ) + { + case button1_pressed: + case button1_pressed_move: + if ( mouse_position == new_mouse_position + && urxvt_button_state == all_buttons_released + && ! isDblclickTimeout(&time_mousepressed) ) + { + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.left_button = DoubleClick; + } + else + { + time_mousepressed = *time; // save click time + b_state.left_button = Pressed; + } + break; + + case button2_pressed: + case button2_pressed_move: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.middle_button = Pressed; + break; + + case button3_pressed: + case button3_pressed_move: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.right_button = Pressed; + break; + + case all_buttons_released: + switch ( urxvt_button_state & button_mask ) + { + case button1_pressed: + case button1_pressed_move: + b_state.left_button = Released; + break; + + case button2_pressed: + case button2_pressed_move: + b_state.middle_button = Released; + break; + + case button3_pressed: + case button3_pressed_move: + b_state.right_button = Released; + break; + + default: + break; + } + break; + + case button_up: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.wheel_up = Pressed; + break; + + case button_down: + time_mousepressed.tv_sec = 0; + time_mousepressed.tv_usec = 0; + b_state.wheel_down = Pressed; + break; + + default: + break; + } +} + +//---------------------------------------------------------------------- +// class FMouseControl +//---------------------------------------------------------------------- + +// constructors and destructor +//---------------------------------------------------------------------- +FMouseControl::FMouseControl() + : zero_point(0,0) + , use_gpm_mouse(false) + , use_xterm_mouse(false) +{ +#ifdef F_HAVE_LIBGPM + mouse_protocol[FMouse::gpm] = FMouse::createMouseObject(FMouse::gpm); +#endif + + mouse_protocol[FMouse::x11] = FMouse::createMouseObject(FMouse::x11); + mouse_protocol[FMouse::sgr] = FMouse::createMouseObject(FMouse::sgr); + mouse_protocol[FMouse::urxvt] = FMouse::createMouseObject(FMouse::urxvt); +} + +//---------------------------------------------------------------------- +FMouseControl::~FMouseControl() // destructor +{ + iter = mouse_protocol.begin(); + + while ( iter != mouse_protocol.end() ) + { + if ( iter->second ) + delete iter->second; + + ++iter; + } +} + + +// public methods of FMouseControl +//---------------------------------------------------------------------- +FPoint& FMouseControl::getPos() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->getPos(); + + return zero_point; +} + +//---------------------------------------------------------------------- +void FMouseControl::clearEvent() +{ + FMouse* mouse_object; + + while ( (mouse_object = getMouseWithEvent()) != 0 ) + mouse_object->clearEvent(); +} + +//---------------------------------------------------------------------- +void FMouseControl::setStdinNo (int file_descriptor) +{ +#ifdef F_HAVE_LIBGPM + + FMouse* mouse = mouse_protocol[FMouse::gpm]; + FMouseGPM* gpm_mouse = static_cast(mouse); + + if ( gpm_mouse ) + gpm_mouse->setStdinNo(file_descriptor); + +#endif +} + +//---------------------------------------------------------------------- +void FMouseControl::setMaxWidth (short x_max) +{ + mouse_protocol[FMouse::urxvt]->setMaxWidth(x_max); +} + +//---------------------------------------------------------------------- +void FMouseControl::setMaxHeight (short y_max) +{ + mouse_protocol[FMouse::urxvt]->setMaxHeight(y_max); +} + +//---------------------------------------------------------------------- +void FMouseControl::useGpmMouse (bool on) +{ + use_gpm_mouse = on; +} + +//---------------------------------------------------------------------- +void FMouseControl::useXtermMouse (bool on) +{ + use_xterm_mouse = on; +} + +//---------------------------------------------------------------------- +bool FMouseControl::hasData() +{ + FMouse* mouse_object = getMouseWithData(); + + if ( mouse_object ) // with data + return true; + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::hasEvent() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) // with event + return true; + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isLeftButtonPressed() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isLeftButtonPressed(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isLeftButtonReleased() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isLeftButtonReleased(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isLeftButtonDoubleClick() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isLeftButtonDoubleClick(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isRightButtonPressed() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isRightButtonPressed(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isRightButtonReleased() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isRightButtonReleased(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isMiddleButtonPressed() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isMiddleButtonPressed(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isMiddleButtonReleased() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isMiddleButtonReleased(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isShiftKeyPressed() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isShiftKeyPressed(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isControlKeyPressed() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isControlKeyPressed(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isMetaKeyPressed() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isMetaKeyPressed(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isWheelUp() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isWheelUp(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isWheelDown() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isWheelDown(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isMoved() +{ + FMouse* mouse_object = getMouseWithEvent(); + + if ( mouse_object ) + return mouse_object->isMoved(); + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isInputDataPending() +{ + iter = mouse_protocol.begin(); + + while ( iter != mouse_protocol.end() ) + { + if ( iter->second ) + return iter->second->isInputDataPending(); + + ++iter; + } + + return false; +} + +//---------------------------------------------------------------------- +bool FMouseControl::isGpmMouseEnabled() +{ + if ( mouse_protocol.empty() ) + return false; + +#ifdef F_HAVE_LIBGPM + + FMouse* mouse = mouse_protocol[FMouse::gpm]; + FMouseGPM* gpm_mouse = static_cast(mouse); + + if ( gpm_mouse ) + return gpm_mouse->isGpmMouseEnabled(); + +#endif + + return false; +} + +//---------------------------------------------------------------------- +void FMouseControl::enable() +{ + if ( use_gpm_mouse ) + { + FMouse* mouse = mouse_protocol[FMouse::gpm]; + FMouseGPM* gpm_mouse = static_cast(mouse); + + if ( gpm_mouse ) + use_gpm_mouse = gpm_mouse->enableGpmMouse(); + } + + if ( use_xterm_mouse ) + enableXTermMouse(); +} + +//---------------------------------------------------------------------- +void FMouseControl::disable() +{ + if ( use_gpm_mouse ) + { + FMouse* mouse = mouse_protocol[FMouse::gpm]; + FMouseGPM* gpm_mouse = static_cast(mouse); + + if ( gpm_mouse ) + gpm_mouse->disableGpmMouse(); + } + + if ( use_xterm_mouse ) + disableXTermMouse(); +} + +//---------------------------------------------------------------------- +void FMouseControl::xtermMouse (bool on) +{ + // activate/deactivate the xterm mouse support + if ( ! use_xterm_mouse ) + return; + + if ( on ) + putstring (CSI "?1001s" // save old highlight mouse tracking + CSI "?1000h" // enable x11 mouse tracking + CSI "?1002h" // enable cell motion mouse tracking + CSI "?1015h" // enable urxvt mouse mode + CSI "?1006h"); // enable SGR mouse mode + else + putstring (CSI "?1006l" // disable SGR mouse mode + CSI "?1015l" // disable urxvt mouse mode + CSI "?1002l" // disable cell motion mouse tracking + CSI "?1000l" // disable x11 mouse tracking + CSI "?1001r"); // restore old highlight mouse tracking + + std::fflush(stdout); +} + +//---------------------------------------------------------------------- +void FMouseControl::setRawData ( FMouse::mouse_type mt + , char fifo_buf[] + , int fifo_buf_size ) +{ + FMouse* mouse = mouse_protocol[mt]; + + if ( mouse ) + mouse->setRawData (fifo_buf, fifo_buf_size); +} + +//---------------------------------------------------------------------- +void FMouseControl::processEvent (struct timeval* time) +{ + FMouse* mouse_object = getMouseWithData(); + + if ( mouse_object ) + mouse_object->processEvent(time); +} + +//---------------------------------------------------------------------- +bool FMouseControl::getGpmKeyPressed (bool pending) +{ + if ( mouse_protocol.empty() ) + return false; + +#ifdef F_HAVE_LIBGPM + + FMouse* mouse = mouse_protocol[FMouse::gpm]; + FMouseGPM* gpm_mouse = static_cast(mouse); + + if ( gpm_mouse ) + return gpm_mouse->getGpmKeyPressed(pending); + +#endif + + return false; +} + +//---------------------------------------------------------------------- +void FMouseControl::drawGpmPointer() +{ + if ( mouse_protocol.empty() ) + return; + +#ifdef F_HAVE_LIBGPM + + FMouse* mouse = mouse_protocol[FMouse::gpm]; + FMouseGPM* gpm_mouse = static_cast(mouse); + + if ( gpm_mouse ) + gpm_mouse->drawGpmPointer(); + +#endif +} + + +// private methods of FMouseControl +//---------------------------------------------------------------------- +FMouse* FMouseControl::getMouseWithData() +{ + iter = mouse_protocol.begin(); + + while ( iter != mouse_protocol.end() ) + { + if ( iter->second && iter->second->hasData() ) + return iter->second; + + ++iter; + } + + return 0; +} + +//---------------------------------------------------------------------- +FMouse* FMouseControl::getMouseWithEvent() +{ + iter = mouse_protocol.begin(); + + while ( iter != mouse_protocol.end() ) + { + if ( iter->second && iter->second->hasEvent() ) + return iter->second; + + ++iter; + } + + return 0; +} + +//---------------------------------------------------------------------- +void FMouseControl::putstring (const char s[], int affcnt) +{ + FTerm::putstring (s, affcnt); +} diff --git a/src/fobject.cpp b/src/fobject.cpp index f4ed50bc..84e5f7cb 100644 --- a/src/fobject.cpp +++ b/src/fobject.cpp @@ -182,6 +182,27 @@ void FObject::getCurrentTime (timeval* time) } } +//---------------------------------------------------------------------- +bool FObject::isTimeout (timeval* time, register long timeout) +{ + register long diff_usec; + struct timeval now; + struct timeval diff; + + FObject::getCurrentTime(&now); + diff.tv_sec = now.tv_sec - time->tv_sec; + diff.tv_usec = now.tv_usec - time->tv_usec; + + if ( diff.tv_usec < 0 ) + { + diff.tv_sec--; + diff.tv_usec += 1000000; + } + + diff_usec = (diff.tv_sec * 1000000) + diff.tv_usec; + return ( diff_usec > timeout ); +} + //---------------------------------------------------------------------- int FObject::addTimer (int interval) { diff --git a/src/foptiattr.cpp b/src/foptiattr.cpp index 980d96da..692997d4 100644 --- a/src/foptiattr.cpp +++ b/src/foptiattr.cpp @@ -558,7 +558,7 @@ char* FOptiAttr::changeAttribute (char_data*& term, char_data*& next) changeAttributeSeparately (term, next); } - if ( term && fake_reverse ) + if ( fake_reverse ) term->attr.bit.reverse = true; return attr_buf; diff --git a/src/fterm.cpp b/src/fterm.cpp index 55738a2d..ed6df4de 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -60,13 +60,11 @@ uInt FTerm::baudrate; long FTerm::key_timeout; long FTerm::dblclick_interval; bool FTerm::resize_term; -bool FTerm::mouse_support; bool FTerm::decscusr_support; bool FTerm::terminal_detection; bool FTerm::raw_mode; bool FTerm::input_data_pending; bool FTerm::non_blocking_stdin; -bool FTerm::gpm_mouse_enabled; bool FTerm::color256; bool FTerm::monochron; bool FTerm::xterm_terminal; @@ -115,7 +113,6 @@ int FTerm::framebuffer_bpp = -1; char* FTerm::locale_name = 0; char* FTerm::locale_xterm = 0; -FPoint* FTerm::mouse = 0; FRect* FTerm::term = 0; char FTerm::exit_message[8192] = ""; @@ -126,6 +123,7 @@ const FString* FTerm::answer_back = 0; const FString* FTerm::sec_da = 0; FOptiMove* FTerm::opti_move = 0; FOptiAttr* FTerm::opti_attr = 0; +FMouseControl* FTerm::mouse = 0; std::map* FTerm::vt100_alt_char = 0; std::map* \ FTerm::encoding_set = 0; @@ -227,6 +225,15 @@ const FString FTerm::getKeyName (int keynum) return FString(""); } +//---------------------------------------------------------------------- +FMouseControl* FTerm::getMouseControl() +{ + if ( mouse ) + return mouse; + else + return 0; +} + #if defined(__linux__) //---------------------------------------------------------------------- FTerm::modifier_key& FTerm::getLinuxModifierKey() @@ -1753,77 +1760,6 @@ void FTerm::xtermMetaSendsESC (bool on) std::fflush(stdout); } -//---------------------------------------------------------------------- -void FTerm::xtermMouse (bool on) -{ - // activate/deactivate the xterm mouse support - if ( ! mouse_support ) - return; - - if ( on ) - putstring (CSI "?1001s" // save old highlight mouse tracking - CSI "?1000h" // enable x11 mouse tracking - CSI "?1002h" // enable cell motion mouse tracking - CSI "?1015h" // enable urxvt mouse mode - CSI "?1006h"); // enable SGR mouse mode - else - putstring (CSI "?1006l" // disable SGR mouse mode - CSI "?1015l" // disable urxvt mouse mode - CSI "?1002l" // disable cell motion mouse tracking - CSI "?1000l" // disable x11 mouse tracking - CSI "?1001r"); // restore old highlight mouse tracking - - std::fflush(stdout); -} - - -#ifdef F_HAVE_LIBGPM -//---------------------------------------------------------------------- -bool FTerm::gpmMouse (bool on) -{ - // activate/deactivate the gpm mouse support - if ( ! linux_terminal ) - return false; - - if ( openConsole() == 0 ) - { - if ( ! isLinuxConsole() ) - return false; - - closeConsole(); - } - - if ( on ) - { - Gpm_Connect conn; - conn.eventMask = uInt16(~GPM_MOVE); - conn.defaultMask = GPM_MOVE; - conn.maxMod = uInt16(~0); - conn.minMod = 0; - Gpm_Open(&conn, 0); - - switch ( gpm_fd ) - { - case -1: - return false; - - case -2: - Gpm_Close(); - return false; - - default: - break; - } - } - else - { - Gpm_Close(); - } - - return on; -} -#endif // F_HAVE_LIBGPM - //---------------------------------------------------------------------- void FTerm::exitWithMessage (std::string message) { @@ -1848,27 +1784,6 @@ void FTerm::exitWithMessage (std::string message) // private methods of FTerm -//---------------------------------------------------------------------- -bool FTerm::isTimeout (timeval* time, register long timeout) -{ - register long diff_usec; - struct timeval now; - struct timeval diff; - - FObject::getCurrentTime(&now); - diff.tv_sec = now.tv_sec - time->tv_sec; - diff.tv_usec = now.tv_usec - time->tv_usec; - - if ( diff.tv_usec < 0 ) - { - diff.tv_sec--; - diff.tv_usec += 1000000; - } - - diff_usec = (diff.tv_sec * 1000000) + diff.tv_usec; - return ( diff_usec > timeout ); -} - //---------------------------------------------------------------------- #if defined(__linux__) int FTerm::isLinuxConsole() @@ -2623,7 +2538,6 @@ void FTerm::init_global_values() no_shadow_character = \ no_half_block_character = \ ascii_console = \ - mouse_support = \ decscusr_support = \ force_vt100 = \ tera_terminal = \ @@ -4388,31 +4302,33 @@ void FTerm::restoreColorPalette() //---------------------------------------------------------------------- void FTerm::enableMouse() { -#ifdef F_HAVE_LIBGPM - // Enable the linux general purpose mouse (gpm) server - gpm_mouse_enabled = enableGpmMouse(); -#endif + bool gpm_mouse = false; + bool xterm_mouse = false; - // Enable xterm mouse support - if ( TCAP(fc::t_key_mouse) && ! linux_terminal ) + if ( linux_terminal && openConsole() == 0 ) { - mouse_support = true; - enableXTermMouse(); + if ( isLinuxConsole() ) + gpm_mouse = true; + + closeConsole(); } + + if ( TCAP(fc::t_key_mouse) && ! linux_terminal ) + xterm_mouse = true; + + mouse->setMaxWidth (short(getColumnNumber())); + mouse->setMaxHeight (short(getLineNumber())); + // Enable the linux general purpose mouse (gpm) server + mouse->useGpmMouse (gpm_mouse); + // Enable xterm mouse support + mouse->useXtermMouse (xterm_mouse); + mouse->enable(); } //---------------------------------------------------------------------- void FTerm::disableMouse() { - // Disable xterm mouse support - if ( mouse_support ) - disableXTermMouse(); - -#ifdef F_HAVE_LIBGPM - // Disable the linux general purpose mouse (gpm) server - if ( gpm_mouse_enabled ) - disableGpmMouse(); -#endif + mouse->disable(); } //---------------------------------------------------------------------- @@ -4440,8 +4356,8 @@ inline void FTerm::allocationValues() { opti_move = new FOptiMove(); opti_attr = new FOptiAttr(); + mouse = new FMouseControl(); term = new FRect(0, 0, 0, 0); - mouse = new FPoint(0, 0); vt100_alt_char = new std::map; encoding_set = new std::map; } @@ -4473,12 +4389,12 @@ inline void FTerm::deallocationValues() if ( xterm_font ) delete xterm_font; - if ( mouse ) - delete mouse; - if ( term ) delete term; + if ( mouse ) + delete mouse; + if ( opti_attr ) delete opti_attr; @@ -4835,15 +4751,15 @@ inline int FTerm::getMetaKey ( char buffer[] // Looking for meta key strings in the buffer assert ( buf_size > 0 ); - register int len, n; - for (int i = 0; fc::Fmetakey[i].string[0] != 0; i++) { char* kmeta = fc::Fmetakey[i].string; // The string is never null - len = int(std::strlen(kmeta)); + register int len = int(std::strlen(kmeta)); if ( std::strncmp(kmeta, buffer, uInt(len)) == 0 ) // found { + register int n; + if ( len == 2 && ( buffer[1] == 'O' || buffer[1] == '[' || buffer[1] == ']' ) ) diff --git a/stamp-h1 b/stamp-h1 deleted file mode 100644 index 4547fe1b..00000000 --- a/stamp-h1 +++ /dev/null @@ -1 +0,0 @@ -timestamp for config.h