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>
* Hidden windows are now non-clickable

View File

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

View File

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

View File

@ -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<FMenuItem*>::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<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() )
{
//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 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"; }

View File

@ -532,12 +532,18 @@ void FMenuBar::cb_item_activated (FWidget* widget, void*)
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();
}
}
}

View File

@ -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<FWidget*>(getSuperMenu());
if ( w && isMenuBar(w) )
w->redraw();
ev->accept();
if ( super_menu && isMenuBar(super_menu) )
{
FMenuBar* mb = dynamic_cast<FMenuBar*>(super_menu);
if ( mb )
{
setSelected();
mb->selectedMenuItem = this;
mb->redraw();
ev->accept();
}
}
}
}

View File

@ -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,

View File

@ -110,11 +110,12 @@ FTerm::term_area* FTerm::vstatusbar = 0;
FTerm::term_area* FTerm::last_area = 0;
std::queue<int>* FTerm::output_buffer = 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;
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<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
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();

View File

@ -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<FWidget*>(FApplication::open_menu);
return open_menu;
}
//----------------------------------------------------------------------
void FWidget::setOpenMenu(FWidget* obj)
{
FApplication::open_menu = obj;
}
//----------------------------------------------------------------------
int FWidget::numOfFocusableChildren()
{

View File

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