diff --git a/irr/include/IEventReceiver.h b/irr/include/IEventReceiver.h index e0660a6f13bd3..d5922eae678b8 100644 --- a/irr/include/IEventReceiver.h +++ b/irr/include/IEventReceiver.h @@ -7,6 +7,7 @@ #include "ILogger.h" #include "Keycodes.h" #include "irrString.h" +#include namespace irr { @@ -297,6 +298,11 @@ enum EGUI_EVENT_TYPE //! SEvents hold information about an event. See irr::IEventReceiver for details on event handling. struct SEvent { + SEvent() + { + memset(this, 0, sizeof(*this)); + } + //! Any kind of GUI event. struct SGUIEvent { @@ -345,6 +351,9 @@ struct SEvent //! Type of mouse event EMOUSE_INPUT_EVENT Event; + + //! Is this a simulated mouse event generated by Minetest itself? + bool Simulated; }; //! Any kind of keyboard event. diff --git a/src/client/game.cpp b/src/client/game.cpp index 0123e10d10a74..bc0533c75354e 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content/subgames.h" #include "client/event_manager.h" #include "fontengine.h" +#include "gui/pointer_type.h" #include "gui/touchscreengui.h" #include "itemdef.h" #include "log.h" @@ -1235,6 +1236,7 @@ void Game::shutdown() // Clear text when exiting. m_game_ui->clearText(); + g_touchscreengui_tsrc = nullptr; if (g_touchscreengui) g_touchscreengui->hide(); @@ -1566,8 +1568,9 @@ bool Game::initGui() gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(), -1, chat_backend, client, &g_menumgr); - if (g_settings->getBool("enable_touch")) - g_touchscreengui = new TouchScreenGUI(device, texture_src); + g_touchscreengui_tsrc = texture_src; + if (g_last_pointer_type == PointerType::Touch) + g_touchscreengui = new TouchScreenGUI(device, g_touchscreengui_tsrc); return true; } @@ -2621,7 +2624,7 @@ void Game::updateCameraDirection(CameraOrientation *cam, float dtime) cur_control->setVisible(false); } - if (m_first_loop_after_window_activation) { + if (m_first_loop_after_window_activation && !g_touchscreengui) { m_first_loop_after_window_activation = false; input->setMousePos(driver->getScreenSize().Width / 2, diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index 6dfd2ad35532f..c6771d230d0bc 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "gui/pointer_type.h" #include "util/numeric.h" #include "inputhandler.h" #include "gui/mainmenumanager.h" @@ -113,6 +114,11 @@ bool MyEventReceiver::OnEvent(const SEvent &event) return true; } + if (event.EventType == EET_MOUSE_INPUT_EVENT && !event.MouseInput.Simulated) + g_last_pointer_type = PointerType::Mouse; + else if (event.EventType == EET_TOUCH_INPUT_EVENT) + g_last_pointer_type = PointerType::Touch; + // Let the menu handle events, if one is active. if (isMenuActive()) { if (g_touchscreengui) @@ -120,6 +126,17 @@ bool MyEventReceiver::OnEvent(const SEvent &event) return g_menumgr.preprocessEvent(event); } + if (g_touchscreengui_tsrc && g_last_pointer_type == PointerType::Mouse && + g_touchscreengui) { + g_touchscreengui->hide(); + delete g_touchscreengui; + g_touchscreengui = nullptr; + } else if (g_touchscreengui_tsrc && g_last_pointer_type == PointerType::Touch && + !g_touchscreengui) { + g_touchscreengui = new TouchScreenGUI(RenderingEngine::get_raw_device(), + g_touchscreengui_tsrc); + } + // Remember whether each key is down or up if (event.EventType == irr::EET_KEY_INPUT_EVENT) { const KeyPress keyCode(event.KeyInput); diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 7ac391c83ac23..9a7d4244c680a 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "constants.h" #include "gamedef.h" #include "client/keycode.h" +#include "gui/pointer_type.h" #include "util/strfnd.h" #include #include @@ -3770,7 +3771,7 @@ void GUIFormSpecMenu::showTooltip(const std::wstring &text, int tooltip_offset_x = m_btn_height; int tooltip_offset_y = m_btn_height; - if (m_pointer_type == PointerType::Touch) { + if (g_last_pointer_type == PointerType::Touch) { tooltip_offset_x *= 3; tooltip_offset_y = 0; if (m_pointer.X > (s32)screenSize.X / 2) diff --git a/src/gui/guiInventoryList.cpp b/src/gui/guiInventoryList.cpp index 02505d436a4d1..d49aeec024de2 100644 --- a/src/gui/guiInventoryList.cpp +++ b/src/gui/guiInventoryList.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "guiInventoryList.h" +#include "gui/pointer_type.h" #include "guiFormSpecMenu.h" #include "client/hud.h" #include "client/client.h" @@ -153,7 +154,7 @@ void GUIInventoryList::draw() // Add hovering tooltip bool show_tooltip = !item.empty() && hovering && !selected_item; // Make it possible to see item tooltips on touchscreens - if (m_fs_menu->getPointerType() == PointerType::Touch) { + if (g_last_pointer_type == PointerType::Touch) { show_tooltip |= hovering && selected && m_fs_menu->getSelectedAmount() != 0; } if (show_tooltip) { diff --git a/src/gui/modalMenu.cpp b/src/gui/modalMenu.cpp index bb287ecd160ec..444c1cf240691 100644 --- a/src/gui/modalMenu.cpp +++ b/src/gui/modalMenu.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/renderingengine.h" #include "modalMenu.h" #include "gettext.h" +#include "gui/pointer_type.h" #include "porting.h" #include "settings.h" #include "touchscreengui.h" @@ -165,6 +166,7 @@ bool GUIModalMenu::simulateMouseEvent(ETOUCH_INPUT_EVENT touch_event, bool secon mouse_event.EventType = EET_MOUSE_INPUT_EVENT; mouse_event.MouseInput.X = m_pointer.X; mouse_event.MouseInput.Y = m_pointer.Y; + mouse_event.MouseInput.Simulated = true; switch (touch_event) { case ETIE_PRESSED_DOWN: mouse_event.MouseInput.Event = EMIE_LMOUSE_PRESSED_DOWN; @@ -188,7 +190,6 @@ bool GUIModalMenu::simulateMouseEvent(ETOUCH_INPUT_EVENT touch_event, bool secon } bool retval; - m_simulated_mouse = true; do { if (preprocessEvent(mouse_event)) { retval = true; @@ -200,7 +201,6 @@ bool GUIModalMenu::simulateMouseEvent(ETOUCH_INPUT_EVENT touch_event, bool secon } retval = target->OnEvent(mouse_event); } while (false); - m_simulated_mouse = false; if (!retval && !second_try) return simulateMouseEvent(touch_event, true); @@ -303,7 +303,6 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) holder.grab(this); // keep this alive until return (it might be dropped downstream [?]) if (event.TouchInput.touchedCount == 1) { - m_pointer_type = PointerType::Touch; m_pointer = v2s32(event.TouchInput.X, event.TouchInput.Y); gui::IGUIElement *hovered = Environment->getRootGUIElement()->getElementFromPoint(core::position2d(m_pointer)); @@ -354,9 +353,8 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) } if (event.EventType == EET_MOUSE_INPUT_EVENT) { - if (!m_simulated_mouse) { - // Only set the pointer type to mouse if this is a real mouse event. - m_pointer_type = PointerType::Mouse; + if (!event.MouseInput.Simulated) { + // Only process if this is a real mouse event. m_pointer = v2s32(event.MouseInput.X, event.MouseInput.Y); m_touch_hovered.reset(); } diff --git a/src/gui/modalMenu.h b/src/gui/modalMenu.h index 9bb55ffec0af5..2c634cd06a9bc 100644 --- a/src/gui/modalMenu.h +++ b/src/gui/modalMenu.h @@ -26,10 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #endif -enum class PointerType { - Mouse, - Touch, -}; class GUIModalMenu; @@ -66,14 +62,10 @@ class GUIModalMenu : public gui::IGUIElement porting::AndroidDialogState getAndroidUIInputState(); #endif - PointerType getPointerType() { return m_pointer_type; }; - protected: virtual std::wstring getLabelByID(s32 id) = 0; virtual std::string getNameByID(s32 id) = 0; - // Stores the last known pointer type. - PointerType m_pointer_type = PointerType::Mouse; // Stores the last known pointer position. // If the last input event was a mouse event, it's the cursor position. // If the last input event was a touch event, it's the finger position. @@ -88,9 +80,6 @@ class GUIModalMenu : public gui::IGUIElement // This is set to true if the menu is currently processing a second-touch event. bool m_second_touch = false; - // This is set to true if the menu is currently processing a mouse event - // that was synthesized by the menu itself from a touch event. - bool m_simulated_mouse = false; private: IMenuManager *m_menumgr; diff --git a/src/gui/pointer_type.h b/src/gui/pointer_type.h new file mode 100644 index 0000000000000..50cfde9044044 --- /dev/null +++ b/src/gui/pointer_type.h @@ -0,0 +1,10 @@ +#pragma once +#include "client/texturesource.h" + +enum class PointerType { + Mouse, + Touch, +}; + +inline PointerType g_last_pointer_type = PointerType::Mouse; +inline ITextureSource *g_touchscreengui_tsrc = nullptr; diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp index d35d6f18dadfe..ea014eb2020a7 100644 --- a/src/gui/touchscreengui.cpp +++ b/src/gui/touchscreengui.cpp @@ -900,6 +900,7 @@ void TouchScreenGUI::emitMouseEvent(EMOUSE_INPUT_EVENT type) event.MouseInput.Control = false; event.MouseInput.ButtonStates = 0; event.MouseInput.Event = type; + event.MouseInput.Simulated = true; m_receiver->OnEvent(event); }