Add support for exiting formspecs by doubleclicking outside
parent
763a511ca5
commit
003634e049
|
@ -134,7 +134,6 @@ function ui.handle_events(event)
|
|||
local retval = value:handle_events(event)
|
||||
|
||||
if retval then
|
||||
print("event handled by: " .. key)
|
||||
return retval
|
||||
end
|
||||
end
|
||||
|
|
|
@ -46,6 +46,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "gettime.h"
|
||||
#include "gettext.h"
|
||||
#include "scripting_game.h"
|
||||
#include "porting.h"
|
||||
|
||||
#define MY_CHECKPOS(a,b) \
|
||||
if (v_pos.size() != 2) { \
|
||||
|
@ -91,6 +92,12 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
|||
current_keys_pending.key_enter = false;
|
||||
current_keys_pending.key_escape = false;
|
||||
|
||||
m_doubleclickdetect[0].time = 0;
|
||||
m_doubleclickdetect[1].time = 0;
|
||||
|
||||
m_doubleclickdetect[0].pos = v2s32(0, 0);
|
||||
m_doubleclickdetect[1].pos = v2s32(0, 0);
|
||||
|
||||
}
|
||||
|
||||
GUIFormSpecMenu::~GUIFormSpecMenu()
|
||||
|
@ -1265,9 +1272,11 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
|
|||
geom.X = data->screensize.Y;
|
||||
geom.Y = 30;
|
||||
|
||||
core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
|
||||
core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X,
|
||||
pos.Y+geom.Y);
|
||||
|
||||
gui::IGUITabControl *e = Environment->addTabControl(rect,this,show_background,show_border,spec.fid);
|
||||
gui::IGUITabControl *e = Environment->addTabControl(rect, this,
|
||||
show_background, show_border, spec.fid);
|
||||
|
||||
if (spec.fname == data->focused_fieldname) {
|
||||
Environment->setFocus(e);
|
||||
|
@ -1276,7 +1285,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
|
|||
e->setNotClipped(true);
|
||||
|
||||
for (unsigned int i=0; i< buttons.size(); i++) {
|
||||
e->addTab(narrow_to_wide(buttons[i]).c_str(),-1);
|
||||
e->addTab(narrow_to_wide(buttons[i]).c_str(), -1);
|
||||
}
|
||||
|
||||
if ((tab_index >= 0) &&
|
||||
|
@ -1287,14 +1296,17 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
|
|||
m_fields.push_back(spec);
|
||||
return;
|
||||
}
|
||||
errorstream<< "Invalid TabHeader element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||
errorstream << "Invalid TabHeader element(" << parts.size() << "): '"
|
||||
<< element << "'" << std::endl;
|
||||
}
|
||||
|
||||
void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
|
||||
{
|
||||
|
||||
if (m_gamedef == 0) {
|
||||
errorstream<<"WARNING: invalid use of item_image_button with m_gamedef==0"<<std::endl;
|
||||
errorstream <<
|
||||
"WARNING: invalid use of item_image_button with m_gamedef==0"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2276,6 +2288,17 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no)
|
|||
}
|
||||
}
|
||||
|
||||
static bool isChild(gui::IGUIElement * tocheck, gui::IGUIElement * parent)
|
||||
{
|
||||
while(tocheck != NULL) {
|
||||
if (tocheck == parent) {
|
||||
return true;
|
||||
}
|
||||
tocheck = tocheck->getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
|
||||
{
|
||||
// Fix Esc/Return key being eaten by checkboxen and tables
|
||||
|
@ -2306,6 +2329,64 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
|
|||
}
|
||||
}
|
||||
|
||||
if (event.EventType == EET_MOUSE_INPUT_EVENT) {
|
||||
s32 x = event.MouseInput.X;
|
||||
s32 y = event.MouseInput.Y;
|
||||
gui::IGUIElement *hovered =
|
||||
Environment->getRootGUIElement()->getElementFromPoint(
|
||||
core::position2d<s32>(x, y));
|
||||
|
||||
if (!isChild(hovered,this)) {
|
||||
if (DoubleClickDetection(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
bool GUIFormSpecMenu::DoubleClickDetection(const SEvent event)
|
||||
{
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
|
||||
m_doubleclickdetect[0].pos = m_doubleclickdetect[1].pos;
|
||||
m_doubleclickdetect[0].time = m_doubleclickdetect[1].time;
|
||||
|
||||
m_doubleclickdetect[1].pos = m_pointer;
|
||||
m_doubleclickdetect[1].time = getTimeMs();
|
||||
}
|
||||
else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) {
|
||||
u32 delta = porting::getDeltaMs(m_doubleclickdetect[0].time, getTimeMs());
|
||||
if (delta > 400) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double squaredistance =
|
||||
m_doubleclickdetect[0].pos
|
||||
.getDistanceFromSQ(m_doubleclickdetect[1].pos);
|
||||
|
||||
if (squaredistance > (30*30)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SEvent* translated = new SEvent();
|
||||
assert(translated != 0);
|
||||
//translate doubleclick to escape
|
||||
memset(translated, 0, sizeof(SEvent));
|
||||
translated->EventType = irr::EET_KEY_INPUT_EVENT;
|
||||
translated->KeyInput.Key = KEY_ESCAPE;
|
||||
translated->KeyInput.Control = false;
|
||||
translated->KeyInput.Shift = false;
|
||||
translated->KeyInput.PressedDown = true;
|
||||
translated->KeyInput.Char = 0;
|
||||
OnEvent(*translated);
|
||||
|
||||
// no need to send the key up event as we're already deleted
|
||||
// and no one else did notice this event
|
||||
delete translated;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -366,6 +366,20 @@ private:
|
|||
void parseBox(parserData* data,std::string element);
|
||||
void parseBackgroundColor(parserData* data,std::string element);
|
||||
void parseListColors(parserData* data,std::string element);
|
||||
|
||||
/**
|
||||
* check if event is part of a double click
|
||||
* @param event event to evaluate
|
||||
* @return true/false if a doubleclick was detected
|
||||
*/
|
||||
bool DoubleClickDetection(const SEvent event);
|
||||
|
||||
struct clickpos
|
||||
{
|
||||
v2s32 pos;
|
||||
s32 time;
|
||||
};
|
||||
clickpos m_doubleclickdetect[2];
|
||||
};
|
||||
|
||||
class FormspecFormSource: public IFormSource
|
||||
|
|
|
@ -275,6 +275,21 @@ inline u32 getTime(TimePrecision prec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delta calculation function taking two 32bit arguments.
|
||||
* @param old_time_ms old time for delta calculation (order is relevant!)
|
||||
* @param new_time_ms new time for delta calculation (order is relevant!)
|
||||
* @return positive 32bit delta value
|
||||
*/
|
||||
inline u32 getDeltaMs(u32 old_time_ms, u32 new_time_ms)
|
||||
{
|
||||
if (new_time_ms >= old_time_ms) {
|
||||
return (new_time_ms - old_time_ms);
|
||||
} else {
|
||||
return (old_time_ms - new_time_ms);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(linux) || defined(__linux)
|
||||
#include <sys/prctl.h>
|
||||
|
||||
|
|
Loading…
Reference in New Issue