From d8337034b532638d246227d850154ee6b21c7ac9 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 15 Aug 2013 21:46:55 +0200 Subject: [PATCH] Formspec textlist: Black Irrlicht magic to detect fake doubleclicks --- src/guiFormSpecMenu.cpp | 62 +++++++++++++++++++++++++++++++++++------ src/guiFormSpecMenu.h | 14 ++++++++-- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 049341c14..79497dca1 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "util/numeric.h" #include "filesys.h" +#include "gettime.h" #include "gettext.h" @@ -81,6 +82,10 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, m_selected_item(NULL), m_selected_amount(0), m_selected_dragging(false), + m_listbox_click_fname(), + m_listbox_click_index(-1), + m_listbox_click_time(0), + m_listbox_doubleclick(false), m_tooltip_element(NULL), m_allowclose(true), m_use_gettext(false), @@ -143,6 +148,42 @@ int GUIFormSpecMenu::getListboxIndex(std::string listboxname) { return -1; } +bool GUIFormSpecMenu::checkListboxClick(std::wstring wlistboxname, + int eventtype) +{ + // WARNING: BLACK IRRLICHT MAGIC + // Used to fix Irrlicht's subpar reporting of single clicks and double + // clicks in listboxes (gui::EGET_LISTBOX_CHANGED, + // gui::EGET_LISTBOX_SELECTED_AGAIN): + // 1. IGUIListBox::setSelected() is counted as a click. + // Including the initial setSelected() done by parseTextList(). + // 2. Clicking on a the selected item and then dragging for less + // than 500ms is counted as a doubleclick, no matter when the + // item was previously selected (e.g. more than 500ms ago) + + // So when Irrlicht reports a doubleclick, we need to check + // for ourselves if really was a doubleclick. Or just a fake. + + for(unsigned int i=0; i < m_listboxes.size(); i++) { + std::wstring name(m_listboxes[i].first.fname.c_str()); + int selected = m_listboxes[i].second->getSelected(); + if (name == wlistboxname && selected >= 0) { + u32 now = getTimeMs(); + bool doubleclick = + (eventtype == gui::EGET_LISTBOX_SELECTED_AGAIN) + && (name == m_listbox_click_fname) + && (selected == m_listbox_click_index) + && (m_listbox_click_time >= now - 500); + m_listbox_click_fname = name; + m_listbox_click_index = selected; + m_listbox_click_time = now; + m_listbox_doubleclick = doubleclick; + return true; + } + } + return false; +} + std::vector split(const std::string &s, char delim) { std::vector tokens; @@ -1920,7 +1961,7 @@ ItemStack GUIFormSpecMenu::verifySelectedItem() return ItemStack(); } -void GUIFormSpecMenu::acceptInput(int eventtype) +void GUIFormSpecMenu::acceptInput() { if(m_text_dst) { @@ -1957,11 +1998,12 @@ void GUIFormSpecMenu::acceptInput(int eventtype) } else if(s.ftype == f_ListBox) { std::stringstream ss; - if (eventtype == gui::EGET_LISTBOX_CHANGED) { - ss << "CHG:"; + + if (m_listbox_doubleclick) { + ss << "DCL:"; } else { - ss << "DCL:"; + ss << "CHG:"; } ss << (getListboxIndex(wide_to_narrow(s.fname.c_str()))+1); fields[wide_to_narrow(s.fname.c_str())] = ss.str(); @@ -2459,12 +2501,16 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) for(u32 i=0; isetFocus(this); diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 84124afc3..28f11d2e7 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -228,9 +228,9 @@ public: void updateSelectedItem(); ItemStack verifySelectedItem(); - void acceptInput(int evttype=-1); + void acceptInput(); bool OnEvent(const SEvent& event); - + int getListboxIndex(std::string listboxname); protected: @@ -272,6 +272,12 @@ protected: ItemStack m_selected_content_guess; InventoryLocation m_selected_content_guess_inventory; + // WARNING: BLACK IRRLICHT MAGIC, see checkListboxClick() + std::wstring m_listbox_click_fname; + int m_listbox_click_index; + u32 m_listbox_click_time; + bool m_listbox_doubleclick; + v2s32 m_pointer; gui::IGUIStaticText *m_tooltip_element; @@ -301,6 +307,10 @@ private: fs_key_pendig current_keys_pending; + // Determine whether listbox click was double click + // (Using some black Irrlicht magic) + bool checkListboxClick(std::wstring wlistboxname, int eventtype); + void parseElement(parserData* data,std::string element); void parseSize(parserData* data,std::string element);