diff --git a/ChangeLog b/ChangeLog index 51a50cec..6ad66460 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2015-10-22 Markus Gans + * Make cursor visibility more standards compliant. + 2015-10-18 Markus Gans * Hidden windows are now non-clickable diff --git a/src/fapp.cpp b/src/fapp.cpp index 1e19dba9..b7293ec3 100644 --- a/src/fapp.cpp +++ b/src/fapp.cpp @@ -2,6 +2,7 @@ // Provides: class FApplication #include "fapp.h" +#include "fmenu.h" #include "fwindow.h" // global application object @@ -16,6 +17,7 @@ FWidget* FApplication::main_widget = 0; // main application widget FWidget* FApplication::active_window = 0; // the active window FWidget* FApplication::focus_widget = 0; // has keyboard input focus FWidget* FApplication::clicked_widget = 0; // is focused by click +FWidget* FApplication::open_menu = 0; // currently open menu FPoint* FApplication::zero_point = 0; // zero point (x=0, y=0) int FApplication::quit_code = 0; bool FApplication::quit_now = false; @@ -956,6 +958,19 @@ void FApplication::processMouseEvent() } } + if ( open_menu && ! b_state.mouse_moved ) + { + FMenu* menu = static_cast(open_menu); + + if ( ! menu->containsMenuStructure(*mouse) ) + { + menu->unselectItemInList(); + menu->hide(); + menu->hideSubMenus(); + menu->hideSuperMenus(); + } + } + if ( clicked_widget ) { FPoint localMousePos; @@ -1022,7 +1037,9 @@ void FApplication::processMouseEvent() , *mouse , LeftButton | key_state ); FWidget* released_widget = clicked_widget; - clicked_widget = 0; + if ( b_state.right_button != Pressed + && b_state.middle_button != Pressed ) + clicked_widget = 0; sendEvent (released_widget, &m_up_ev); } @@ -1041,7 +1058,9 @@ void FApplication::processMouseEvent() , *mouse , RightButton | key_state ); FWidget* released_widget = clicked_widget; - clicked_widget = 0; + if ( b_state.left_button != Pressed + && b_state.middle_button != Pressed ) + clicked_widget = 0; sendEvent (released_widget, &m_up_ev); } @@ -1063,6 +1082,8 @@ void FApplication::processMouseEvent() , *mouse , 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); } diff --git a/src/fapp.h b/src/fapp.h index 10107899..3310c526 100644 --- a/src/fapp.h +++ b/src/fapp.h @@ -113,6 +113,7 @@ class FApplication : public FWidget static FWidget* active_window; static FWidget* focus_widget; static FWidget* clicked_widget; + static FWidget* open_menu; private: FApplication (const FApplication&); // Disabled copy constructor diff --git a/src/fmenu.cpp b/src/fmenu.cpp index cfe14039..5875af79 100644 --- a/src/fmenu.cpp +++ b/src/fmenu.cpp @@ -197,6 +197,7 @@ void FMenu::hideSuperMenus() { selectedMenuItem->unsetSelected(); selectedMenuItem = 0; + mb->mouse_down = false; mb->redraw(); } } @@ -209,6 +210,22 @@ void FMenu::hideSuperMenus() } } +//---------------------------------------------------------------------- +bool FMenu::containsMenuStructure (int x, int y) const +{ + // Check mouse click position for item, menu and all sub menus + FMenuItem* si = selectedListItem; + + if ( getGeometryGlobal().contains(x,y) ) + return true; + else if ( si && si->hasMenu() ) + return si->getMenu()->getGeometryGlobal().contains(x,y); + else if ( item && item->getGeometryGlobal().contains(x,y) ) + return true; + else + return false; +} + //---------------------------------------------------------------------- int FMenu::getHotkeyPos (wchar_t*& src, wchar_t*& dest, uInt length) { @@ -414,31 +431,13 @@ void FMenu::processActivate() emitCallback("activate"); } + // public methods of FMenu //---------------------------------------------------------------------- void FMenu::onMouseDown (FMouseEvent* ev) { if ( ev->getButton() != LeftButton ) - { - mouse_down = false; - - if ( ! itemlist.empty() ) - { - std::vector::const_iterator iter, end; - iter = itemlist.begin(); - end = itemlist.end(); - - while ( iter != end ) - { - (*iter)->unsetSelected(); - if ( selectedListItem == *iter ) - selectedListItem = 0; - ++iter; - } - } - redraw(); return; - } if ( mouse_down ) return; @@ -532,6 +531,10 @@ void FMenu::onMouseUp (FMouseEvent* ev) } ++iter; } + // Click on a non-FMenuItem (border or separator line) + unselectItemInList(); + hide(); + hideSuperMenus(); } } } @@ -645,6 +648,12 @@ void FMenu::hide() restoreVTerm (getGeometryGlobalShadow()); updateTerminal(); flush_out(); + + FMenu* open_menu = static_cast(getOpenMenu()); + if ( open_menu && open_menu != this ) + open_menu->hide(); + setOpenMenu(0); + mouse_down = false; } } @@ -687,7 +696,23 @@ void FMenu::cb_menuitem_activated (FWidget* widget, void*) if ( menuitem->hasMenu() ) { - //beep(); + FMenu* menu = menuitem->getMenu(); + if ( ! menu->isVisible() ) + { + FMenu* open_menu = static_cast(getOpenMenu()); + if ( open_menu && open_menu != menu ) + open_menu->hide(); + setOpenMenu(menu); + + menu->setVisible(); + menu->show(); + raiseWindow(menu); + menu->redraw(); + updateTerminal(); + flush_out(); + if ( ! isMenu(getSuperMenu()) ) + setOpenMenu(menu); + } } } diff --git a/src/fmenu.h b/src/fmenu.h index 32d924c0..bc7701bb 100644 --- a/src/fmenu.h +++ b/src/fmenu.h @@ -63,6 +63,8 @@ class FMenu : public FWindow, public FMenuList void setSuperMenu (FWidget*); void hideSubMenus(); void hideSuperMenus(); + bool containsMenuStructure (const FPoint&) const; + bool containsMenuStructure (int, int) const; int getHotkeyPos (wchar_t*&, wchar_t*&, uInt); void draw(); void drawBorder(); @@ -108,6 +110,7 @@ class FMenu : public FWindow, public FMenuList void cb_menuitem_deactivated (FWidget*, void*); private: + friend class FApplication; friend class FMenuItem; }; #pragma pack(pop) @@ -122,6 +125,10 @@ inline FWidget* FMenu::getSuperMenu() const inline void FMenu::setSuperMenu (FWidget* smenu) { super_menu = smenu; } +//---------------------------------------------------------------------- +inline bool FMenu::containsMenuStructure (const FPoint& p) const +{ return containsMenuStructure (p.getX(), p.getY()); } + //---------------------------------------------------------------------- inline const char* FMenu::getClassName() const { return "FMenu"; } diff --git a/src/fmenubar.cpp b/src/fmenubar.cpp index 7af642c0..5ed6f94a 100644 --- a/src/fmenubar.cpp +++ b/src/fmenubar.cpp @@ -532,12 +532,18 @@ void FMenuBar::cb_item_activated (FWidget* widget, void*) FMenu* menu = menuitem->getMenu(); if ( ! menu->isVisible() ) { + FMenu* open_menu = static_cast(getOpenMenu()); + if ( open_menu && open_menu != menu ) + open_menu->hide(); + setOpenMenu(menu); + menu->setVisible(); menu->show(); raiseWindow(menu); menu->redraw(); updateTerminal(); flush_out(); + } } } diff --git a/src/fmenuitem.cpp b/src/fmenuitem.cpp index 2affdf3c..b609fccf 100644 --- a/src/fmenuitem.cpp +++ b/src/fmenuitem.cpp @@ -107,7 +107,8 @@ void FMenuItem::init (FWidget* parent) if ( menubar_ptr ) menubar_ptr->menu_dimension(); - //addAccelerator (item->getKey(), item); + // Meta + hotkey + addAccelerator (0x20000e0+tolower(hotkey), this); this->addCallback ( @@ -203,13 +204,19 @@ void FMenuItem::processClicked() //---------------------------------------------------------------------- void FMenuItem::onAccel (FAccelEvent* ev) { - if ( isSelected() ) + if ( isActivated() && ! isSelected() ) { - unsetSelected(); - FWidget* w = reinterpret_cast(getSuperMenu()); - if ( w && isMenuBar(w) ) - w->redraw(); - ev->accept(); + if ( super_menu && isMenuBar(super_menu) ) + { + FMenuBar* mb = dynamic_cast(super_menu); + if ( mb ) + { + setSelected(); + mb->selectedMenuItem = this; + mb->redraw(); + ev->accept(); + } + } } } diff --git a/src/ftcap_map.h b/src/ftcap_map.h index 29c80ce4..8f29fdd8 100644 --- a/src/ftcap_map.h +++ b/src/ftcap_map.h @@ -48,6 +48,7 @@ static tcap_map tcap[] = { 0, "cv" }, // row_address -> vertical position #1 absolute (P) { 0, "vs" }, // cursor_visible -> make cursor very visible { 0, "vi" }, // cursor_invisible -> make cursor invisible + { 0, "ve" }, // cursor_normal -> make cursor appear normal (undo vi/vs) { 0, "up" }, // cursor_up -> up one line { 0, "do" }, // cursor_down -> down one line { 0, "le" }, // cursor_left -> move left one space @@ -120,6 +121,7 @@ enum termcaps t_row_address, t_cursor_visible, t_cursor_invisible, + t_cursor_normal, t_cursor_up, t_cursor_down, t_cursor_left, diff --git a/src/fterm.cpp b/src/fterm.cpp index e94cc2b6..5ad0ea48 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -110,11 +110,12 @@ FTerm::term_area* FTerm::vstatusbar = 0; FTerm::term_area* FTerm::last_area = 0; std::queue* FTerm::output_buffer = 0; std::map* FTerm::vt100_alt_char = 0; -std::map* +std::map* \ FTerm::encoding_set = 0; console_font_op FTerm::screenFont; unimapdesc FTerm::screenUnicodeMap; -fc::console_cursor_style FTerm::consoleCursorStyle; +fc::console_cursor_style \ + FTerm::consoleCursorStyle; //---------------------------------------------------------------------- @@ -1016,6 +1017,16 @@ void FTerm::init_termcaps() for (int i=0; tcap[i].tname[0] != 0; i++) tcap[i].string = tgetstr(tcap[i].tname, &buffer); + // set invisible cursor for cygwin terminal + if ( cygwin_terminal && ! tcap[t_cursor_invisible].string ) + tcap[t_cursor_invisible].string = \ + const_cast("\033[?25l"); + + // set visible cursor for cygwin terminal + if ( cygwin_terminal && ! tcap[t_cursor_visible].string ) + tcap[t_cursor_visible].string = \ + const_cast("\033[?25h"); + // set ansi blink for cygwin terminal if ( cygwin_terminal && ! tcap[t_enter_blink_mode].string ) tcap[t_enter_blink_mode].string = \ @@ -3321,30 +3332,27 @@ bool FTerm::setTermUnderline (bool on) //---------------------------------------------------------------------- bool FTerm::hideCursor(bool on) { - char *vi, *vs; + char *vi, *vs, *ve; if ( on == hiddenCursor ) return hiddenCursor; vi = tcap[t_cursor_invisible].string; vs = tcap[t_cursor_visible].string; + ve = tcap[t_cursor_normal].string; if ( on ) { if ( vi ) appendOutputBuffer (vi); - else - appendOutputBuffer ("\033[?25l"); hiddenCursor = true; // global } else { if ( vs ) appendOutputBuffer (vs); - else if ( vi ) // putty-256color - appendOutputBuffer ("\033[?12;25h"); - else - appendOutputBuffer ("\033[?25h"); + else if ( ve ) + appendOutputBuffer (ve); hiddenCursor = false; } flush_out(); diff --git a/src/fwidget.cpp b/src/fwidget.cpp index d738f6a0..cfd2e1bc 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -289,12 +289,12 @@ void FWidget::setColorTheme() wc.shadow_fg = fc::Black; wc.shadow_bg = fc::LightGray; // only for transparent shadow wc.current_element_focus_fg = fc::LightGray; - wc.current_element_focus_bg = fc::Blue; + wc.current_element_focus_bg = fc::Red; wc.current_element_fg = fc::LightGray; wc.current_element_bg = fc::Blue; wc.current_inc_search_element_fg = fc::Red; - wc.selected_current_element_fg = fc::Cyan; - wc.selected_current_element_bg = fc::Blue; + wc.selected_current_element_fg = fc::Blue; + wc.selected_current_element_bg = fc::Red; wc.label_fg = fc::Black; wc.label_bg = fc::LightGray; wc.label_inactive_fg = fc::Cyan; @@ -310,18 +310,18 @@ void FWidget::setColorTheme() wc.inputfield_inactive_fg = fc::Black; wc.inputfield_inactive_bg = fc::LightGray; wc.toggle_button_active_focus_fg = fc::LightGray; - wc.toggle_button_active_focus_bg = fc::Blue; + wc.toggle_button_active_focus_bg = fc::Red; wc.toggle_button_active_fg = fc::Black; wc.toggle_button_active_bg = fc::LightGray; wc.toggle_button_inactive_fg = fc::Cyan; wc.toggle_button_inactive_bg = fc::LightGray; wc.button_active_focus_fg = fc::LightGray; - wc.button_active_focus_bg = fc::Blue; + wc.button_active_focus_bg = fc::Red; wc.button_active_fg = fc::LightGray; wc.button_active_bg = fc::Blue; - wc.button_inactive_fg = fc::LightGray; - wc.button_inactive_bg = fc::Cyan; - wc.button_hotkey_fg = fc::Red; + wc.button_inactive_fg = fc::Black; + wc.button_inactive_bg = fc::Blue; + wc.button_hotkey_fg = fc::LightGray; wc.titlebar_active_fg = fc::LightGray; wc.titlebar_active_bg = fc::Red; wc.titlebar_inactive_fg = fc::Black; @@ -349,7 +349,7 @@ void FWidget::setColorTheme() wc.scrollbar_bg = fc::LightGray; wc.scrollbar_button_fg = fc::Black; wc.scrollbar_button_bg = fc::LightGray; - wc.progressbar_fg = fc::Black; + wc.progressbar_fg = fc::Blue; wc.progressbar_bg = fc::LightGray; } } @@ -882,6 +882,19 @@ void FWidget::setClickedWidget(FWidget* obj) FApplication::clicked_widget = obj; } +//---------------------------------------------------------------------- +FWidget* FWidget::getOpenMenu() +{ + FWidget* open_menu = static_cast(FApplication::open_menu); + return open_menu; +} + +//---------------------------------------------------------------------- +void FWidget::setOpenMenu(FWidget* obj) +{ + FApplication::open_menu = obj; +} + //---------------------------------------------------------------------- int FWidget::numOfFocusableChildren() { diff --git a/src/fwidget.h b/src/fwidget.h index 20c32893..5973bc3b 100644 --- a/src/fwidget.h +++ b/src/fwidget.h @@ -331,6 +331,8 @@ class FWidget : public FObject, public FTerm virtual void setFocusWidget(FWidget*); static FWidget* getClickedWidget(); static void setClickedWidget(FWidget*); + static FWidget* getOpenMenu(); + static void setOpenMenu(FWidget*); int numOfFocusableChildren(); FWidget* parentWidget() const; bool isRootWidget() const;