Make cursor visibility more standards compliant

This commit is contained in:
Markus Gans 2015-10-23 00:24:20 +02:00
parent a478bf6a2a
commit 7e961d40c3
11 changed files with 142 additions and 47 deletions

View File

@ -1,3 +1,6 @@
2015-10-22 Markus Gans <guru.mail@muenster.de>
* Make cursor visibility more standards compliant.
2015-10-18 Markus Gans <guru.mail@muenster.de> 2015-10-18 Markus Gans <guru.mail@muenster.de>
* Hidden windows are now non-clickable * Hidden windows are now non-clickable

View File

@ -2,6 +2,7 @@
// Provides: class FApplication // Provides: class FApplication
#include "fapp.h" #include "fapp.h"
#include "fmenu.h"
#include "fwindow.h" #include "fwindow.h"
// global application object // 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::active_window = 0; // the active window
FWidget* FApplication::focus_widget = 0; // has keyboard input focus FWidget* FApplication::focus_widget = 0; // has keyboard input focus
FWidget* FApplication::clicked_widget = 0; // is focused by click 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) FPoint* FApplication::zero_point = 0; // zero point (x=0, y=0)
int FApplication::quit_code = 0; int FApplication::quit_code = 0;
bool FApplication::quit_now = false; bool FApplication::quit_now = false;
@ -956,6 +958,19 @@ void FApplication::processMouseEvent()
} }
} }
if ( open_menu && ! b_state.mouse_moved )
{
FMenu* menu = static_cast<FMenu*>(open_menu);
if ( ! menu->containsMenuStructure(*mouse) )
{
menu->unselectItemInList();
menu->hide();
menu->hideSubMenus();
menu->hideSuperMenus();
}
}
if ( clicked_widget ) if ( clicked_widget )
{ {
FPoint localMousePos; FPoint localMousePos;
@ -1022,6 +1037,8 @@ void FApplication::processMouseEvent()
, *mouse , *mouse
, LeftButton | key_state ); , LeftButton | key_state );
FWidget* released_widget = clicked_widget; FWidget* released_widget = clicked_widget;
if ( b_state.right_button != Pressed
&& b_state.middle_button != Pressed )
clicked_widget = 0; clicked_widget = 0;
sendEvent (released_widget, &m_up_ev); sendEvent (released_widget, &m_up_ev);
} }
@ -1041,6 +1058,8 @@ void FApplication::processMouseEvent()
, *mouse , *mouse
, RightButton | key_state ); , RightButton | key_state );
FWidget* released_widget = clicked_widget; FWidget* released_widget = clicked_widget;
if ( b_state.left_button != Pressed
&& b_state.middle_button != Pressed )
clicked_widget = 0; clicked_widget = 0;
sendEvent (released_widget, &m_up_ev); sendEvent (released_widget, &m_up_ev);
} }
@ -1063,6 +1082,8 @@ void FApplication::processMouseEvent()
, *mouse , *mouse
, MiddleButton | key_state ); , MiddleButton | key_state );
FWidget* released_widget = clicked_widget; FWidget* released_widget = clicked_widget;
if ( b_state.right_button != Pressed
&& b_state.left_button != Pressed )
clicked_widget = 0; clicked_widget = 0;
sendEvent (released_widget, &m_up_ev); sendEvent (released_widget, &m_up_ev);
} }

View File

@ -113,6 +113,7 @@ class FApplication : public FWidget
static FWidget* active_window; static FWidget* active_window;
static FWidget* focus_widget; static FWidget* focus_widget;
static FWidget* clicked_widget; static FWidget* clicked_widget;
static FWidget* open_menu;
private: private:
FApplication (const FApplication&); // Disabled copy constructor FApplication (const FApplication&); // Disabled copy constructor

View File

@ -197,6 +197,7 @@ void FMenu::hideSuperMenus()
{ {
selectedMenuItem->unsetSelected(); selectedMenuItem->unsetSelected();
selectedMenuItem = 0; selectedMenuItem = 0;
mb->mouse_down = false;
mb->redraw(); 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) int FMenu::getHotkeyPos (wchar_t*& src, wchar_t*& dest, uInt length)
{ {
@ -414,31 +431,13 @@ void FMenu::processActivate()
emitCallback("activate"); emitCallback("activate");
} }
// public methods of FMenu // public methods of FMenu
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMenu::onMouseDown (FMouseEvent* ev) void FMenu::onMouseDown (FMouseEvent* ev)
{ {
if ( ev->getButton() != LeftButton ) if ( ev->getButton() != LeftButton )
{
mouse_down = false;
if ( ! itemlist.empty() )
{
std::vector<FMenuItem*>::const_iterator iter, end;
iter = itemlist.begin();
end = itemlist.end();
while ( iter != end )
{
(*iter)->unsetSelected();
if ( selectedListItem == *iter )
selectedListItem = 0;
++iter;
}
}
redraw();
return; return;
}
if ( mouse_down ) if ( mouse_down )
return; return;
@ -532,6 +531,10 @@ void FMenu::onMouseUp (FMouseEvent* ev)
} }
++iter; ++iter;
} }
// Click on a non-FMenuItem (border or separator line)
unselectItemInList();
hide();
hideSuperMenus();
} }
} }
} }
@ -645,6 +648,12 @@ void FMenu::hide()
restoreVTerm (getGeometryGlobalShadow()); restoreVTerm (getGeometryGlobalShadow());
updateTerminal(); updateTerminal();
flush_out(); flush_out();
FMenu* open_menu = static_cast<FMenu*>(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() ) if ( menuitem->hasMenu() )
{ {
//beep(); FMenu* menu = menuitem->getMenu();
if ( ! menu->isVisible() )
{
FMenu* open_menu = static_cast<FMenu*>(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);
}
} }
} }

View File

@ -63,6 +63,8 @@ class FMenu : public FWindow, public FMenuList
void setSuperMenu (FWidget*); void setSuperMenu (FWidget*);
void hideSubMenus(); void hideSubMenus();
void hideSuperMenus(); void hideSuperMenus();
bool containsMenuStructure (const FPoint&) const;
bool containsMenuStructure (int, int) const;
int getHotkeyPos (wchar_t*&, wchar_t*&, uInt); int getHotkeyPos (wchar_t*&, wchar_t*&, uInt);
void draw(); void draw();
void drawBorder(); void drawBorder();
@ -108,6 +110,7 @@ class FMenu : public FWindow, public FMenuList
void cb_menuitem_deactivated (FWidget*, void*); void cb_menuitem_deactivated (FWidget*, void*);
private: private:
friend class FApplication;
friend class FMenuItem; friend class FMenuItem;
}; };
#pragma pack(pop) #pragma pack(pop)
@ -122,6 +125,10 @@ inline FWidget* FMenu::getSuperMenu() const
inline void FMenu::setSuperMenu (FWidget* smenu) inline void FMenu::setSuperMenu (FWidget* smenu)
{ super_menu = smenu; } { super_menu = smenu; }
//----------------------------------------------------------------------
inline bool FMenu::containsMenuStructure (const FPoint& p) const
{ return containsMenuStructure (p.getX(), p.getY()); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline const char* FMenu::getClassName() const inline const char* FMenu::getClassName() const
{ return "FMenu"; } { return "FMenu"; }

View File

@ -532,12 +532,18 @@ void FMenuBar::cb_item_activated (FWidget* widget, void*)
FMenu* menu = menuitem->getMenu(); FMenu* menu = menuitem->getMenu();
if ( ! menu->isVisible() ) if ( ! menu->isVisible() )
{ {
FMenu* open_menu = static_cast<FMenu*>(getOpenMenu());
if ( open_menu && open_menu != menu )
open_menu->hide();
setOpenMenu(menu);
menu->setVisible(); menu->setVisible();
menu->show(); menu->show();
raiseWindow(menu); raiseWindow(menu);
menu->redraw(); menu->redraw();
updateTerminal(); updateTerminal();
flush_out(); flush_out();
} }
} }
} }

View File

@ -107,7 +107,8 @@ void FMenuItem::init (FWidget* parent)
if ( menubar_ptr ) if ( menubar_ptr )
menubar_ptr->menu_dimension(); menubar_ptr->menu_dimension();
//addAccelerator (item->getKey(), item); // Meta + hotkey
addAccelerator (0x20000e0+tolower(hotkey), this);
this->addCallback this->addCallback
( (
@ -203,15 +204,21 @@ void FMenuItem::processClicked()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMenuItem::onAccel (FAccelEvent* ev) void FMenuItem::onAccel (FAccelEvent* ev)
{ {
if ( isSelected() ) if ( isActivated() && ! isSelected() )
{ {
unsetSelected(); if ( super_menu && isMenuBar(super_menu) )
FWidget* w = reinterpret_cast<FWidget*>(getSuperMenu()); {
if ( w && isMenuBar(w) ) FMenuBar* mb = dynamic_cast<FMenuBar*>(super_menu);
w->redraw(); if ( mb )
{
setSelected();
mb->selectedMenuItem = this;
mb->redraw();
ev->accept(); ev->accept();
} }
} }
}
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMenuItem::onMouseDown (FMouseEvent* ev) void FMenuItem::onMouseDown (FMouseEvent* ev)

View File

@ -48,6 +48,7 @@ static tcap_map tcap[] =
{ 0, "cv" }, // row_address -> vertical position #1 absolute (P) { 0, "cv" }, // row_address -> vertical position #1 absolute (P)
{ 0, "vs" }, // cursor_visible -> make cursor very visible { 0, "vs" }, // cursor_visible -> make cursor very visible
{ 0, "vi" }, // cursor_invisible -> make cursor invisible { 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, "up" }, // cursor_up -> up one line
{ 0, "do" }, // cursor_down -> down one line { 0, "do" }, // cursor_down -> down one line
{ 0, "le" }, // cursor_left -> move left one space { 0, "le" }, // cursor_left -> move left one space
@ -120,6 +121,7 @@ enum termcaps
t_row_address, t_row_address,
t_cursor_visible, t_cursor_visible,
t_cursor_invisible, t_cursor_invisible,
t_cursor_normal,
t_cursor_up, t_cursor_up,
t_cursor_down, t_cursor_down,
t_cursor_left, t_cursor_left,

View File

@ -110,11 +110,12 @@ FTerm::term_area* FTerm::vstatusbar = 0;
FTerm::term_area* FTerm::last_area = 0; FTerm::term_area* FTerm::last_area = 0;
std::queue<int>* FTerm::output_buffer = 0; std::queue<int>* FTerm::output_buffer = 0;
std::map<uChar,uChar>* FTerm::vt100_alt_char = 0; std::map<uChar,uChar>* FTerm::vt100_alt_char = 0;
std::map<std::string,fc::encoding>* std::map<std::string,fc::encoding>* \
FTerm::encoding_set = 0; FTerm::encoding_set = 0;
console_font_op FTerm::screenFont; console_font_op FTerm::screenFont;
unimapdesc FTerm::screenUnicodeMap; 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++) for (int i=0; tcap[i].tname[0] != 0; i++)
tcap[i].string = tgetstr(tcap[i].tname, &buffer); 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<char*>("\033[?25l");
// set visible cursor for cygwin terminal
if ( cygwin_terminal && ! tcap[t_cursor_visible].string )
tcap[t_cursor_visible].string = \
const_cast<char*>("\033[?25h");
// set ansi blink for cygwin terminal // set ansi blink for cygwin terminal
if ( cygwin_terminal && ! tcap[t_enter_blink_mode].string ) if ( cygwin_terminal && ! tcap[t_enter_blink_mode].string )
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) bool FTerm::hideCursor(bool on)
{ {
char *vi, *vs; char *vi, *vs, *ve;
if ( on == hiddenCursor ) if ( on == hiddenCursor )
return hiddenCursor; return hiddenCursor;
vi = tcap[t_cursor_invisible].string; vi = tcap[t_cursor_invisible].string;
vs = tcap[t_cursor_visible].string; vs = tcap[t_cursor_visible].string;
ve = tcap[t_cursor_normal].string;
if ( on ) if ( on )
{ {
if ( vi ) if ( vi )
appendOutputBuffer (vi); appendOutputBuffer (vi);
else
appendOutputBuffer ("\033[?25l");
hiddenCursor = true; // global hiddenCursor = true; // global
} }
else else
{ {
if ( vs ) if ( vs )
appendOutputBuffer (vs); appendOutputBuffer (vs);
else if ( vi ) // putty-256color else if ( ve )
appendOutputBuffer ("\033[?12;25h"); appendOutputBuffer (ve);
else
appendOutputBuffer ("\033[?25h");
hiddenCursor = false; hiddenCursor = false;
} }
flush_out(); flush_out();

View File

@ -289,12 +289,12 @@ void FWidget::setColorTheme()
wc.shadow_fg = fc::Black; wc.shadow_fg = fc::Black;
wc.shadow_bg = fc::LightGray; // only for transparent shadow wc.shadow_bg = fc::LightGray; // only for transparent shadow
wc.current_element_focus_fg = fc::LightGray; 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_fg = fc::LightGray;
wc.current_element_bg = fc::Blue; wc.current_element_bg = fc::Blue;
wc.current_inc_search_element_fg = fc::Red; wc.current_inc_search_element_fg = fc::Red;
wc.selected_current_element_fg = fc::Cyan; wc.selected_current_element_fg = fc::Blue;
wc.selected_current_element_bg = fc::Blue; wc.selected_current_element_bg = fc::Red;
wc.label_fg = fc::Black; wc.label_fg = fc::Black;
wc.label_bg = fc::LightGray; wc.label_bg = fc::LightGray;
wc.label_inactive_fg = fc::Cyan; wc.label_inactive_fg = fc::Cyan;
@ -310,18 +310,18 @@ void FWidget::setColorTheme()
wc.inputfield_inactive_fg = fc::Black; wc.inputfield_inactive_fg = fc::Black;
wc.inputfield_inactive_bg = fc::LightGray; wc.inputfield_inactive_bg = fc::LightGray;
wc.toggle_button_active_focus_fg = 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_fg = fc::Black;
wc.toggle_button_active_bg = fc::LightGray; wc.toggle_button_active_bg = fc::LightGray;
wc.toggle_button_inactive_fg = fc::Cyan; wc.toggle_button_inactive_fg = fc::Cyan;
wc.toggle_button_inactive_bg = fc::LightGray; wc.toggle_button_inactive_bg = fc::LightGray;
wc.button_active_focus_fg = 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_fg = fc::LightGray;
wc.button_active_bg = fc::Blue; wc.button_active_bg = fc::Blue;
wc.button_inactive_fg = fc::LightGray; wc.button_inactive_fg = fc::Black;
wc.button_inactive_bg = fc::Cyan; wc.button_inactive_bg = fc::Blue;
wc.button_hotkey_fg = fc::Red; wc.button_hotkey_fg = fc::LightGray;
wc.titlebar_active_fg = fc::LightGray; wc.titlebar_active_fg = fc::LightGray;
wc.titlebar_active_bg = fc::Red; wc.titlebar_active_bg = fc::Red;
wc.titlebar_inactive_fg = fc::Black; wc.titlebar_inactive_fg = fc::Black;
@ -349,7 +349,7 @@ void FWidget::setColorTheme()
wc.scrollbar_bg = fc::LightGray; wc.scrollbar_bg = fc::LightGray;
wc.scrollbar_button_fg = fc::Black; wc.scrollbar_button_fg = fc::Black;
wc.scrollbar_button_bg = fc::LightGray; wc.scrollbar_button_bg = fc::LightGray;
wc.progressbar_fg = fc::Black; wc.progressbar_fg = fc::Blue;
wc.progressbar_bg = fc::LightGray; wc.progressbar_bg = fc::LightGray;
} }
} }
@ -882,6 +882,19 @@ void FWidget::setClickedWidget(FWidget* obj)
FApplication::clicked_widget = obj; FApplication::clicked_widget = obj;
} }
//----------------------------------------------------------------------
FWidget* FWidget::getOpenMenu()
{
FWidget* open_menu = static_cast<FWidget*>(FApplication::open_menu);
return open_menu;
}
//----------------------------------------------------------------------
void FWidget::setOpenMenu(FWidget* obj)
{
FApplication::open_menu = obj;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
int FWidget::numOfFocusableChildren() int FWidget::numOfFocusableChildren()
{ {

View File

@ -331,6 +331,8 @@ class FWidget : public FObject, public FTerm
virtual void setFocusWidget(FWidget*); virtual void setFocusWidget(FWidget*);
static FWidget* getClickedWidget(); static FWidget* getClickedWidget();
static void setClickedWidget(FWidget*); static void setClickedWidget(FWidget*);
static FWidget* getOpenMenu();
static void setOpenMenu(FWidget*);
int numOfFocusableChildren(); int numOfFocusableChildren();
FWidget* parentWidget() const; FWidget* parentWidget() const;
bool isRootWidget() const; bool isRootWidget() const;