Skip to content

Commit 323c860

Browse files
stujones11sfan5
authored andcommittedOct 29, 2018
Move touchscreen input handling to base GUIModalMenu class
1 parent 0d54399 commit 323c860

14 files changed

+425
-272
lines changed
 

‎build/android/jni/Android.mk

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ LOCAL_SRC_FILES := \
165165
jni/src/guiscalingfilter.cpp \
166166
jni/src/gui/guiVolumeChange.cpp \
167167
jni/src/gui/intlGUIEditBox.cpp \
168+
jni/src/gui/modalMenu.cpp \
168169
jni/src/gui/profilergraph.cpp \
169170
jni/src/gui/touchscreengui.cpp \
170171
jni/src/httpfetch.cpp \

‎src/game.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -1288,7 +1288,12 @@ bool Game::createClient(const std::string &playername,
12881288
return false;
12891289

12901290
bool could_connect, connect_aborted;
1291-
1291+
#ifdef HAVE_TOUCHSCREENGUI
1292+
if (g_touchscreengui) {
1293+
g_touchscreengui->init(texture_src);
1294+
g_touchscreengui->hide();
1295+
}
1296+
#endif
12921297
if (!connectToServer(playername, password, address, port,
12931298
&could_connect, &connect_aborted))
12941299
return false;
@@ -1414,7 +1419,7 @@ bool Game::initGui()
14141419
#ifdef HAVE_TOUCHSCREENGUI
14151420

14161421
if (g_touchscreengui)
1417-
g_touchscreengui->init(texture_src);
1422+
g_touchscreengui->show();
14181423

14191424
#endif
14201425

‎src/gui/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ set(gui_SRCS
1010
${CMAKE_CURRENT_SOURCE_DIR}/guiTable.cpp
1111
${CMAKE_CURRENT_SOURCE_DIR}/guiVolumeChange.cpp
1212
${CMAKE_CURRENT_SOURCE_DIR}/intlGUIEditBox.cpp
13+
${CMAKE_CURRENT_SOURCE_DIR}/modalMenu.cpp
1314
${CMAKE_CURRENT_SOURCE_DIR}/profilergraph.cpp
1415
PARENT_SCOPE
1516
)

‎src/gui/guiConfirmRegistration.cpp

+27-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ GUIConfirmRegistration::GUIConfirmRegistration(gui::IGUIEnvironment *env,
4343
m_client(client), m_playername(playername), m_password(password),
4444
m_address(address), m_aborted(aborted)
4545
{
46+
#ifdef __ANDROID__
47+
m_touchscreen_visible = false;
48+
#endif
4649
}
4750

4851
GUIConfirmRegistration::~GUIConfirmRegistration()
@@ -157,6 +160,9 @@ void GUIConfirmRegistration::drawMenu()
157160
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
158161

159162
gui::IGUIElement::draw();
163+
#ifdef __ANDROID__
164+
getAndroidUIInput();
165+
#endif
160166
}
161167

162168
void GUIConfirmRegistration::closeMenu(bool goNext)
@@ -193,10 +199,14 @@ bool GUIConfirmRegistration::processInput()
193199
bool GUIConfirmRegistration::OnEvent(const SEvent &event)
194200
{
195201
if (event.EventType == EET_KEY_INPUT_EVENT) {
196-
if (event.KeyInput.Key == KEY_ESCAPE && event.KeyInput.PressedDown) {
202+
// clang-format off
203+
if ((event.KeyInput.Key == KEY_ESCAPE ||
204+
event.KeyInput.Key == KEY_CANCEL) &&
205+
event.KeyInput.PressedDown) {
197206
closeMenu(false);
198207
return true;
199208
}
209+
// clang-format on
200210
if (event.KeyInput.Key == KEY_RETURN && event.KeyInput.PressedDown) {
201211
acceptInput();
202212
if (processInput())
@@ -239,3 +249,19 @@ bool GUIConfirmRegistration::OnEvent(const SEvent &event)
239249

240250
return false;
241251
}
252+
253+
#ifdef __ANDROID__
254+
bool GUIConfirmRegistration::getAndroidUIInput()
255+
{
256+
if (!hasAndroidUIInput() || m_jni_field_name != "password")
257+
return false;
258+
259+
std::string text = porting::getInputDialogValue();
260+
gui::IGUIElement *e = getElementFromId(ID_confirmPassword);
261+
if (e)
262+
e->setText(utf8_to_wide(text).c_str());
263+
264+
m_jni_field_name.clear();
265+
return false;
266+
}
267+
#endif

‎src/gui/guiConfirmRegistration.h

+6
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,14 @@ class GUIConfirmRegistration : public GUIModalMenu
5050
bool processInput();
5151

5252
bool OnEvent(const SEvent &event);
53+
#ifdef __ANDROID__
54+
bool getAndroidUIInput();
55+
#endif
5356

5457
private:
58+
std::wstring getLabelByID(s32 id) { return L""; }
59+
std::string getNameByID(s32 id) { return "password"; }
60+
5561
Client *m_client = nullptr;
5662
const std::string &m_playername;
5763
const std::string &m_password;

‎src/gui/guiFormSpecMenu.cpp

+5-173
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,6 @@ GUIFormSpecMenu::GUIFormSpecMenu(JoystickController *joystick,
9797
m_text_dst(tdst),
9898
m_joystick(joystick),
9999
m_remap_dbl_click(remap_dbl_click)
100-
#ifdef __ANDROID__
101-
, m_JavaDialogFieldName("")
102-
#endif
103100
{
104101
current_keys_pending.key_down = false;
105102
current_keys_pending.key_up = false;
@@ -2265,23 +2262,11 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
22652262
#ifdef __ANDROID__
22662263
bool GUIFormSpecMenu::getAndroidUIInput()
22672264
{
2268-
/* no dialog shown */
2269-
if (m_JavaDialogFieldName == "") {
2265+
if (!hasAndroidUIInput())
22702266
return false;
2271-
}
22722267

2273-
/* still waiting */
2274-
if (porting::getInputDialogState() == -1) {
2275-
return true;
2276-
}
2277-
2278-
std::string fieldname = m_JavaDialogFieldName;
2279-
m_JavaDialogFieldName = "";
2280-
2281-
/* no value abort dialog processing */
2282-
if (porting::getInputDialogState() != 0) {
2283-
return false;
2284-
}
2268+
std::string fieldname = m_jni_field_name;
2269+
m_jni_field_name.clear();
22852270

22862271
for(std::vector<FieldSpec>::iterator iter = m_fields.begin();
22872272
iter != m_fields.end(); ++iter) {
@@ -2301,8 +2286,7 @@ bool GUIFormSpecMenu::getAndroidUIInput()
23012286

23022287
std::string text = porting::getInputDialogValue();
23032288

2304-
((gui::IGUIEditBox*) tochange)->
2305-
setText(utf8_to_wide(text).c_str());
2289+
((gui::IGUIEditBox *)tochange)->setText(utf8_to_wide(text).c_str());
23062290
}
23072291
return false;
23082292
}
@@ -3043,158 +3027,6 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
30433027
}
30443028
}
30453029

3046-
#ifdef __ANDROID__
3047-
// display software keyboard when clicking edit boxes
3048-
if (event.EventType == EET_MOUSE_INPUT_EVENT
3049-
&& event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
3050-
gui::IGUIElement *hovered =
3051-
Environment->getRootGUIElement()->getElementFromPoint(
3052-
core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
3053-
if ((hovered) && (hovered->getType() == irr::gui::EGUIET_EDIT_BOX)) {
3054-
bool retval = hovered->OnEvent(event);
3055-
if (retval)
3056-
Environment->setFocus(hovered);
3057-
3058-
std::string field_name = getNameByID(hovered->getID());
3059-
/* read-only field */
3060-
if (field_name.empty())
3061-
return retval;
3062-
3063-
m_JavaDialogFieldName = field_name;
3064-
std::string message = gettext("Enter ");
3065-
std::string label = wide_to_utf8(getLabelByID(hovered->getID()));
3066-
if (label.empty())
3067-
label = "text";
3068-
message += gettext(label) + ":";
3069-
3070-
/* single line text input */
3071-
int type = 2;
3072-
3073-
/* multi line text input */
3074-
if (((gui::IGUIEditBox*) hovered)->isMultiLineEnabled())
3075-
type = 1;
3076-
3077-
/* passwords are always single line */
3078-
if (((gui::IGUIEditBox*) hovered)->isPasswordBox())
3079-
type = 3;
3080-
3081-
porting::showInputDialog(gettext("ok"), "",
3082-
wide_to_utf8(((gui::IGUIEditBox*) hovered)->getText()),
3083-
type);
3084-
return retval;
3085-
}
3086-
}
3087-
3088-
if (event.EventType == EET_TOUCH_INPUT_EVENT)
3089-
{
3090-
SEvent translated;
3091-
memset(&translated, 0, sizeof(SEvent));
3092-
translated.EventType = EET_MOUSE_INPUT_EVENT;
3093-
gui::IGUIElement* root = Environment->getRootGUIElement();
3094-
3095-
if (!root) {
3096-
errorstream
3097-
<< "GUIFormSpecMenu::preprocessEvent unable to get root element"
3098-
<< std::endl;
3099-
return false;
3100-
}
3101-
gui::IGUIElement* hovered = root->getElementFromPoint(
3102-
core::position2d<s32>(
3103-
event.TouchInput.X,
3104-
event.TouchInput.Y));
3105-
3106-
translated.MouseInput.X = event.TouchInput.X;
3107-
translated.MouseInput.Y = event.TouchInput.Y;
3108-
translated.MouseInput.Control = false;
3109-
3110-
bool dont_send_event = false;
3111-
3112-
if (event.TouchInput.touchedCount == 1) {
3113-
switch (event.TouchInput.Event) {
3114-
case ETIE_PRESSED_DOWN:
3115-
m_pointer = v2s32(event.TouchInput.X,event.TouchInput.Y);
3116-
translated.MouseInput.Event = EMIE_LMOUSE_PRESSED_DOWN;
3117-
translated.MouseInput.ButtonStates = EMBSM_LEFT;
3118-
m_down_pos = m_pointer;
3119-
break;
3120-
case ETIE_MOVED:
3121-
m_pointer = v2s32(event.TouchInput.X,event.TouchInput.Y);
3122-
translated.MouseInput.Event = EMIE_MOUSE_MOVED;
3123-
translated.MouseInput.ButtonStates = EMBSM_LEFT;
3124-
break;
3125-
case ETIE_LEFT_UP:
3126-
translated.MouseInput.Event = EMIE_LMOUSE_LEFT_UP;
3127-
translated.MouseInput.ButtonStates = 0;
3128-
hovered = root->getElementFromPoint(m_down_pos);
3129-
/* we don't have a valid pointer element use last
3130-
* known pointer pos */
3131-
translated.MouseInput.X = m_pointer.X;
3132-
translated.MouseInput.Y = m_pointer.Y;
3133-
3134-
/* reset down pos */
3135-
m_down_pos = v2s32(0,0);
3136-
break;
3137-
default:
3138-
dont_send_event = true;
3139-
//this is not supposed to happen
3140-
errorstream
3141-
<< "GUIFormSpecMenu::preprocessEvent unexpected usecase Event="
3142-
<< event.TouchInput.Event << std::endl;
3143-
}
3144-
} else if ( (event.TouchInput.touchedCount == 2) &&
3145-
(event.TouchInput.Event == ETIE_PRESSED_DOWN) ) {
3146-
hovered = root->getElementFromPoint(m_down_pos);
3147-
3148-
translated.MouseInput.Event = EMIE_RMOUSE_PRESSED_DOWN;
3149-
translated.MouseInput.ButtonStates = EMBSM_LEFT | EMBSM_RIGHT;
3150-
translated.MouseInput.X = m_pointer.X;
3151-
translated.MouseInput.Y = m_pointer.Y;
3152-
3153-
if (hovered) {
3154-
hovered->OnEvent(translated);
3155-
}
3156-
3157-
translated.MouseInput.Event = EMIE_RMOUSE_LEFT_UP;
3158-
translated.MouseInput.ButtonStates = EMBSM_LEFT;
3159-
3160-
3161-
if (hovered) {
3162-
hovered->OnEvent(translated);
3163-
}
3164-
dont_send_event = true;
3165-
}
3166-
/* ignore unhandled 2 touch events ... accidental moving for example */
3167-
else if (event.TouchInput.touchedCount == 2) {
3168-
dont_send_event = true;
3169-
}
3170-
else if (event.TouchInput.touchedCount > 2) {
3171-
errorstream
3172-
<< "GUIFormSpecMenu::preprocessEvent to many multitouch events "
3173-
<< event.TouchInput.touchedCount << " ignoring them" << std::endl;
3174-
}
3175-
3176-
if (dont_send_event) {
3177-
return true;
3178-
}
3179-
3180-
/* check if translated event needs to be preprocessed again */
3181-
if (preprocessEvent(translated)) {
3182-
return true;
3183-
}
3184-
if (hovered) {
3185-
grab();
3186-
bool retval = hovered->OnEvent(translated);
3187-
3188-
if (event.TouchInput.Event == ETIE_LEFT_UP) {
3189-
/* reset pointer */
3190-
m_pointer = v2s32(0,0);
3191-
}
3192-
drop();
3193-
return retval;
3194-
}
3195-
}
3196-
#endif
3197-
31983030
if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) {
31993031
/* TODO add a check like:
32003032
if (event.JoystickEvent != joystick_we_listen_for)
@@ -3214,7 +3046,7 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
32143046
return handled;
32153047
}
32163048

3217-
return false;
3049+
return GUIModalMenu::preprocessEvent(event);
32183050
}
32193051

32203052
/******************************************************************************/

‎src/gui/guiFormSpecMenu.h

+2-9
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,8 @@ class GUIFormSpecMenu : public GUIModalMenu
372372
{
373373
return padding + offset + AbsoluteRect.UpperLeftCorner;
374374
}
375+
std::wstring getLabelByID(s32 id);
376+
std::string getNameByID(s32 id);
375377
v2s32 getElementBasePos(bool absolute,
376378
const std::vector<std::string> *v_pos);
377379

@@ -411,8 +413,6 @@ class GUIFormSpecMenu : public GUIModalMenu
411413
bool m_selected_dragging = false;
412414
ItemStack m_selected_swap;
413415

414-
v2s32 m_pointer;
415-
v2s32 m_old_pointer; // Mouse position after previous mouse event
416416
gui::IGUIStaticText *m_tooltip_element = nullptr;
417417

418418
u64 m_tooltip_show_delay;
@@ -535,13 +535,6 @@ class GUIFormSpecMenu : public GUIModalMenu
535535
int m_btn_height;
536536
gui::IGUIFont *m_font = nullptr;
537537

538-
std::wstring getLabelByID(s32 id);
539-
std::string getNameByID(s32 id);
540-
#ifdef __ANDROID__
541-
v2s32 m_down_pos;
542-
std::string m_JavaDialogFieldName;
543-
#endif
544-
545538
/* If true, remap a double-click (or double-tap) action to ESC. This is so
546539
* that, for example, Android users can double-tap to close a formspec.
547540
*

‎src/gui/guiKeyChangeMenu.h

+4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ class GUIKeyChangeMenu : public GUIModalMenu
5858

5959
bool pausesGame() { return true; }
6060

61+
protected:
62+
std::wstring getLabelByID(s32 id) { return L""; }
63+
std::string getNameByID(s32 id) { return ""; }
64+
6165
private:
6266
void init_keys();
6367

‎src/gui/guiPasswordChange.cpp

+46-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2323
#include <IGUIButton.h>
2424
#include <IGUIStaticText.h>
2525
#include <IGUIFont.h>
26-
26+
#include "keycode.h"
27+
#include "porting.h"
2728
#include "gettext.h"
2829

2930
const int ID_oldPassword = 256;
@@ -180,6 +181,9 @@ void GUIPasswordChange::drawMenu()
180181
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
181182

182183
gui::IGUIElement::draw();
184+
#ifdef __ANDROID__
185+
getAndroidUIInput();
186+
#endif
183187
}
184188

185189
void GUIPasswordChange::acceptInput()
@@ -211,10 +215,14 @@ bool GUIPasswordChange::processInput()
211215
bool GUIPasswordChange::OnEvent(const SEvent &event)
212216
{
213217
if (event.EventType == EET_KEY_INPUT_EVENT) {
214-
if (event.KeyInput.Key == KEY_ESCAPE && event.KeyInput.PressedDown) {
218+
// clang-format off
219+
if ((event.KeyInput.Key == KEY_ESCAPE ||
220+
event.KeyInput.Key == KEY_CANCEL) &&
221+
event.KeyInput.PressedDown) {
215222
quitMenu();
216223
return true;
217224
}
225+
// clang-format on
218226
if (event.KeyInput.Key == KEY_RETURN && event.KeyInput.PressedDown) {
219227
acceptInput();
220228
if (processInput())
@@ -259,3 +267,39 @@ bool GUIPasswordChange::OnEvent(const SEvent &event)
259267

260268
return Parent ? Parent->OnEvent(event) : false;
261269
}
270+
271+
std::string GUIPasswordChange::getNameByID(s32 id)
272+
{
273+
switch (id) {
274+
case ID_oldPassword:
275+
return "old_password";
276+
case ID_newPassword1:
277+
return "new_password_1";
278+
case ID_newPassword2:
279+
return "new_password_2";
280+
}
281+
return "";
282+
}
283+
284+
#ifdef __ANDROID__
285+
bool GUIPasswordChange::getAndroidUIInput()
286+
{
287+
if (!hasAndroidUIInput())
288+
return false;
289+
290+
gui::IGUIElement *e = nullptr;
291+
if (m_jni_field_name == "old_password")
292+
e = getElementFromId(ID_oldPassword);
293+
else if (m_jni_field_name == "new_password_1")
294+
e = getElementFromId(ID_newPassword1);
295+
else if (m_jni_field_name == "new_password_2")
296+
e = getElementFromId(ID_newPassword2);
297+
298+
if (e) {
299+
std::string text = porting::getInputDialogValue();
300+
e->setText(utf8_to_wide(text).c_str());
301+
}
302+
m_jni_field_name.clear();
303+
return false;
304+
}
305+
#endif

‎src/gui/guiPasswordChange.h

+7
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ class GUIPasswordChange : public GUIModalMenu
4444
bool processInput();
4545

4646
bool OnEvent(const SEvent &event);
47+
#ifdef __ANDROID__
48+
bool getAndroidUIInput();
49+
#endif
50+
51+
protected:
52+
std::wstring getLabelByID(s32 id) { return L""; }
53+
std::string getNameByID(s32 id);
4754

4855
private:
4956
Client *m_client;

‎src/gui/guiPathSelectMenu.h

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class GUIFileSelectMenu : public GUIModalMenu
4444

4545
void setTextDest(TextDest *dest) { m_text_dst = dest; }
4646

47+
protected:
48+
std::wstring getLabelByID(s32 id) { return L""; }
49+
std::string getNameByID(s32 id) { return ""; }
50+
4751
private:
4852
void acceptInput();
4953

‎src/gui/guiVolumeChange.h

+4
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,8 @@ class GUIVolumeChange : public GUIModalMenu
4242
bool OnEvent(const SEvent& event);
4343

4444
bool pausesGame() { return true; }
45+
46+
protected:
47+
std::wstring getLabelByID(s32 id) { return L""; }
48+
std::string getNameByID(s32 id) { return ""; }
4549
};

‎src/gui/modalMenu.cpp

+283
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4+
Copyright (C) 2018 stujones11, Stuart Jones <stujones111@gmail.com>
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU Lesser General Public License as published by
8+
the Free Software Foundation; either version 2.1 of the License, or
9+
(at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU Lesser General Public License for more details.
15+
16+
You should have received a copy of the GNU Lesser General Public License along
17+
with this program; if not, write to the Free Software Foundation, Inc.,
18+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*/
20+
21+
#include <cstdlib>
22+
#include "modalMenu.h"
23+
#include "gettext.h"
24+
#include "porting.h"
25+
26+
#ifdef HAVE_TOUCHSCREENGUI
27+
#include "touchscreengui.h"
28+
#endif
29+
30+
// clang-format off
31+
GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id,
32+
IMenuManager *menumgr) :
33+
IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
34+
core::rect<s32>(0, 0, 100, 100)),
35+
#ifdef __ANDROID__
36+
m_jni_field_name(""),
37+
#endif
38+
m_menumgr(menumgr)
39+
{
40+
setVisible(true);
41+
Environment->setFocus(this);
42+
m_menumgr->createdMenu(this);
43+
}
44+
// clang-format on
45+
46+
GUIModalMenu::~GUIModalMenu()
47+
{
48+
m_menumgr->deletingMenu(this);
49+
}
50+
51+
void GUIModalMenu::allowFocusRemoval(bool allow)
52+
{
53+
m_allow_focus_removal = allow;
54+
}
55+
56+
bool GUIModalMenu::canTakeFocus(gui::IGUIElement *e)
57+
{
58+
return (e && (e == this || isMyChild(e))) || m_allow_focus_removal;
59+
}
60+
61+
void GUIModalMenu::draw()
62+
{
63+
if (!IsVisible)
64+
return;
65+
66+
video::IVideoDriver *driver = Environment->getVideoDriver();
67+
v2u32 screensize = driver->getScreenSize();
68+
if (screensize != m_screensize_old) {
69+
m_screensize_old = screensize;
70+
regenerateGui(screensize);
71+
}
72+
73+
drawMenu();
74+
}
75+
76+
/*
77+
This should be called when the menu wants to quit.
78+
79+
WARNING: THIS DEALLOCATES THE MENU FROM MEMORY. Return
80+
immediately if you call this from the menu itself.
81+
82+
(More precisely, this decrements the reference count.)
83+
*/
84+
void GUIModalMenu::quitMenu()
85+
{
86+
allowFocusRemoval(true);
87+
// This removes Environment's grab on us
88+
Environment->removeFocus(this);
89+
m_menumgr->deletingMenu(this);
90+
this->remove();
91+
#ifdef HAVE_TOUCHSCREENGUI
92+
if (g_touchscreengui && m_touchscreen_visible)
93+
g_touchscreengui->show();
94+
#endif
95+
}
96+
97+
void GUIModalMenu::removeChildren()
98+
{
99+
const core::list<gui::IGUIElement *> &children = getChildren();
100+
core::list<gui::IGUIElement *> children_copy;
101+
for (gui::IGUIElement *i : children) {
102+
children_copy.push_back(i);
103+
}
104+
105+
for (gui::IGUIElement *i : children_copy) {
106+
i->remove();
107+
}
108+
}
109+
110+
bool GUIModalMenu::preprocessEvent(const SEvent &event)
111+
{
112+
#ifdef __ANDROID__
113+
// clang-format off
114+
// display software keyboard when clicking edit boxes
115+
if (event.EventType == EET_MOUSE_INPUT_EVENT &&
116+
event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
117+
gui::IGUIElement *hovered =
118+
Environment->getRootGUIElement()->getElementFromPoint(
119+
core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
120+
if ((hovered) && (hovered->getType() == irr::gui::EGUIET_EDIT_BOX)) {
121+
bool retval = hovered->OnEvent(event);
122+
if (retval)
123+
Environment->setFocus(hovered);
124+
125+
std::string field_name = getNameByID(hovered->getID());
126+
// read-only field
127+
if (field_name.empty())
128+
return retval;
129+
130+
m_jni_field_name = field_name;
131+
std::string message = gettext("Enter ");
132+
std::string label = wide_to_utf8(getLabelByID(hovered->getID()));
133+
if (label.empty())
134+
label = "text";
135+
message += gettext(label) + ":";
136+
137+
// single line text input
138+
int type = 2;
139+
140+
// multi line text input
141+
if (((gui::IGUIEditBox *)hovered)->isMultiLineEnabled())
142+
type = 1;
143+
144+
// passwords are always single line
145+
if (((gui::IGUIEditBox *)hovered)->isPasswordBox())
146+
type = 3;
147+
148+
porting::showInputDialog(gettext("ok"), "",
149+
wide_to_utf8(((gui::IGUIEditBox *)hovered)->getText()), type);
150+
return retval;
151+
}
152+
}
153+
154+
if (event.EventType == EET_TOUCH_INPUT_EVENT) {
155+
SEvent translated;
156+
memset(&translated, 0, sizeof(SEvent));
157+
translated.EventType = EET_MOUSE_INPUT_EVENT;
158+
gui::IGUIElement *root = Environment->getRootGUIElement();
159+
160+
if (!root) {
161+
errorstream << "GUIModalMenu::preprocessEvent"
162+
<< " unable to get root element" << std::endl;
163+
return false;
164+
}
165+
gui::IGUIElement *hovered = root->getElementFromPoint(
166+
core::position2d<s32>(event.TouchInput.X, event.TouchInput.Y));
167+
168+
translated.MouseInput.X = event.TouchInput.X;
169+
translated.MouseInput.Y = event.TouchInput.Y;
170+
translated.MouseInput.Control = false;
171+
172+
bool dont_send_event = false;
173+
174+
if (event.TouchInput.touchedCount == 1) {
175+
switch (event.TouchInput.Event) {
176+
case ETIE_PRESSED_DOWN:
177+
m_pointer = v2s32(event.TouchInput.X, event.TouchInput.Y);
178+
translated.MouseInput.Event = EMIE_LMOUSE_PRESSED_DOWN;
179+
translated.MouseInput.ButtonStates = EMBSM_LEFT;
180+
m_down_pos = m_pointer;
181+
break;
182+
case ETIE_MOVED:
183+
m_pointer = v2s32(event.TouchInput.X, event.TouchInput.Y);
184+
translated.MouseInput.Event = EMIE_MOUSE_MOVED;
185+
translated.MouseInput.ButtonStates = EMBSM_LEFT;
186+
break;
187+
case ETIE_LEFT_UP:
188+
translated.MouseInput.Event = EMIE_LMOUSE_LEFT_UP;
189+
translated.MouseInput.ButtonStates = 0;
190+
hovered = root->getElementFromPoint(m_down_pos);
191+
// we don't have a valid pointer element use last
192+
// known pointer pos
193+
translated.MouseInput.X = m_pointer.X;
194+
translated.MouseInput.Y = m_pointer.Y;
195+
196+
// reset down pos
197+
m_down_pos = v2s32(0, 0);
198+
break;
199+
default:
200+
dont_send_event = true;
201+
// this is not supposed to happen
202+
errorstream << "GUIModalMenu::preprocessEvent"
203+
<< " unexpected usecase Event="
204+
<< event.TouchInput.Event << std::endl;
205+
}
206+
} else if ((event.TouchInput.touchedCount == 2) &&
207+
(event.TouchInput.Event == ETIE_PRESSED_DOWN)) {
208+
hovered = root->getElementFromPoint(m_down_pos);
209+
210+
translated.MouseInput.Event = EMIE_RMOUSE_PRESSED_DOWN;
211+
translated.MouseInput.ButtonStates = EMBSM_LEFT | EMBSM_RIGHT;
212+
translated.MouseInput.X = m_pointer.X;
213+
translated.MouseInput.Y = m_pointer.Y;
214+
if (hovered) {
215+
hovered->OnEvent(translated);
216+
}
217+
218+
translated.MouseInput.Event = EMIE_RMOUSE_LEFT_UP;
219+
translated.MouseInput.ButtonStates = EMBSM_LEFT;
220+
221+
if (hovered) {
222+
hovered->OnEvent(translated);
223+
}
224+
dont_send_event = true;
225+
}
226+
// ignore unhandled 2 touch events ... accidental moving for example
227+
else if (event.TouchInput.touchedCount == 2) {
228+
dont_send_event = true;
229+
}
230+
else if (event.TouchInput.touchedCount > 2) {
231+
errorstream << "GUIModalMenu::preprocessEvent"
232+
<< " to many multitouch events "
233+
<< event.TouchInput.touchedCount << " ignoring them"
234+
<< std::endl;
235+
}
236+
237+
if (dont_send_event) {
238+
return true;
239+
}
240+
241+
// check if translated event needs to be preprocessed again
242+
if (preprocessEvent(translated)) {
243+
return true;
244+
}
245+
if (hovered) {
246+
grab();
247+
bool retval = hovered->OnEvent(translated);
248+
249+
if (event.TouchInput.Event == ETIE_LEFT_UP) {
250+
// reset pointer
251+
m_pointer = v2s32(0, 0);
252+
}
253+
drop();
254+
return retval;
255+
}
256+
}
257+
// clang-format on
258+
#endif
259+
return false;
260+
}
261+
262+
#ifdef __ANDROID__
263+
bool GUIModalMenu::hasAndroidUIInput()
264+
{
265+
// no dialog shown
266+
if (m_jni_field_name.empty()) {
267+
return false;
268+
}
269+
270+
// still waiting
271+
if (porting::getInputDialogState() == -1) {
272+
return true;
273+
}
274+
275+
// no value abort dialog processing
276+
if (porting::getInputDialogState() != 0) {
277+
m_jni_field_name.clear();
278+
return false;
279+
}
280+
281+
return true;
282+
}
283+
#endif

‎src/gui/modalMenu.h

+28-85
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2020
#pragma once
2121

2222
#include "irrlichttypes_extrabloated.h"
23-
#ifdef HAVE_TOUCHSCREENGUI
24-
#include "touchscreengui.h"
25-
#endif
23+
#include "util/string.h"
2624

2725
class GUIModalMenu;
2826

@@ -34,101 +32,46 @@ class IMenuManager
3432
virtual void deletingMenu(gui::IGUIElement *menu) = 0;
3533
};
3634

37-
/*
38-
Remember to drop() the menu after creating, so that it can
39-
remove itself when it wants to.
40-
*/
35+
// Remember to drop() the menu after creating, so that it can
36+
// remove itself when it wants to.
4137

4238
class GUIModalMenu : public gui::IGUIElement
4339
{
4440
public:
4541
GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id,
46-
IMenuManager *menumgr):
47-
IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
48-
core::rect<s32>(0,0,100,100))
49-
{
50-
m_menumgr = menumgr;
51-
52-
setVisible(true);
53-
Environment->setFocus(this);
54-
m_menumgr->createdMenu(this);
55-
}
56-
57-
virtual ~GUIModalMenu()
58-
{
59-
m_menumgr->deletingMenu(this);
60-
}
61-
62-
void allowFocusRemoval(bool allow)
63-
{
64-
m_allow_focus_removal = allow;
65-
}
66-
67-
bool canTakeFocus(gui::IGUIElement *e)
68-
{
69-
return (e && (e == this || isMyChild(e))) || m_allow_focus_removal;
70-
}
71-
72-
void draw()
73-
{
74-
if(!IsVisible)
75-
return;
76-
77-
video::IVideoDriver* driver = Environment->getVideoDriver();
78-
v2u32 screensize = driver->getScreenSize();
79-
if(screensize != m_screensize_old /*|| m_force_regenerate_gui*/)
80-
{
81-
m_screensize_old = screensize;
82-
regenerateGui(screensize);
83-
//m_force_regenerate_gui = false;
84-
}
85-
86-
drawMenu();
87-
}
42+
IMenuManager *menumgr);
43+
virtual ~GUIModalMenu();
8844

89-
/*
90-
This should be called when the menu wants to quit.
91-
92-
WARNING: THIS DEALLOCATES THE MENU FROM MEMORY. Return
93-
immediately if you call this from the menu itself.
94-
95-
(More precisely, this decrements the reference count.)
96-
*/
97-
void quitMenu()
98-
{
99-
allowFocusRemoval(true);
100-
// This removes Environment's grab on us
101-
Environment->removeFocus(this);
102-
m_menumgr->deletingMenu(this);
103-
this->remove();
104-
#ifdef HAVE_TOUCHSCREENGUI
105-
if (g_touchscreengui)
106-
g_touchscreengui->show();
107-
#endif
108-
}
109-
110-
void removeChildren()
111-
{
112-
const core::list<gui::IGUIElement*> &children = getChildren();
113-
core::list<gui::IGUIElement*> children_copy;
114-
for (gui::IGUIElement *i : children) {
115-
children_copy.push_back(i);
116-
}
117-
118-
for (gui::IGUIElement *i : children_copy) {
119-
i->remove();
120-
}
121-
}
45+
void allowFocusRemoval(bool allow);
46+
bool canTakeFocus(gui::IGUIElement *e);
47+
void draw();
48+
void quitMenu();
49+
void removeChildren();
12250

12351
virtual void regenerateGui(v2u32 screensize) = 0;
12452
virtual void drawMenu() = 0;
125-
virtual bool preprocessEvent(const SEvent& event) { return false; };
53+
virtual bool preprocessEvent(const SEvent& event);
12654
virtual bool OnEvent(const SEvent& event) { return false; };
127-
virtual bool pausesGame(){ return false; } // Used for pause menu
55+
virtual bool pausesGame() { return false; } // Used for pause menu
56+
#ifdef __ANDROID__
57+
virtual bool getAndroidUIInput() { return false; }
58+
bool hasAndroidUIInput();
59+
#endif
12860

12961
protected:
130-
//bool m_force_regenerate_gui;
62+
virtual std::wstring getLabelByID(s32 id) = 0;
63+
virtual std::string getNameByID(s32 id) = 0;
64+
65+
v2s32 m_pointer;
66+
v2s32 m_old_pointer; // Mouse position after previous mouse event
13167
v2u32 m_screensize_old;
68+
#ifdef __ANDROID__
69+
v2s32 m_down_pos;
70+
std::string m_jni_field_name;
71+
#endif
72+
#ifdef HAVE_TOUCHSCREENGUI
73+
bool m_touchscreen_visible = true;
74+
#endif
13275
private:
13376
IMenuManager *m_menumgr;
13477
// This might be necessary to expose to the implementation if it

0 commit comments

Comments
 (0)
Please sign in to comment.