diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 8fd287c84e879..84ade453f921d 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -4200,14 +4200,16 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } /* Mouse event other than movement, or crossing the border of inventory - field while holding left, right, or middle mouse button + field while holding left, right, or middle mouse button + or touch event (for touch screen devices) */ - if (event.EventType == EET_MOUSE_INPUT_EVENT && - (event.MouseInput.Event != EMIE_MOUSE_MOVED || - ((event.MouseInput.isLeftPressed() || - event.MouseInput.isRightPressed() || - event.MouseInput.isMiddlePressed()) && - getItemAtPos(m_pointer).i != getItemAtPos(m_old_pointer).i))) { + if ((event.EventType == EET_MOUSE_INPUT_EVENT && + (event.MouseInput.Event != EMIE_MOUSE_MOVED || + ((event.MouseInput.isLeftPressed() || + event.MouseInput.isRightPressed() || + event.MouseInput.isMiddlePressed()) && + getItemAtPos(m_pointer).i != getItemAtPos(m_old_pointer).i))) || + event.EventType == EET_TOUCH_INPUT_EVENT) { // Get selected item and hovered/clicked item (s) @@ -4276,37 +4278,50 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) ButtonEventType button = BET_OTHER; ButtonEventType updown = BET_OTHER; - switch (event.MouseInput.Event) { - case EMIE_LMOUSE_PRESSED_DOWN: - button = BET_LEFT; updown = BET_DOWN; - break; - case EMIE_RMOUSE_PRESSED_DOWN: - button = BET_RIGHT; updown = BET_DOWN; - break; - case EMIE_MMOUSE_PRESSED_DOWN: - button = BET_MIDDLE; updown = BET_DOWN; - break; - case EMIE_MOUSE_WHEEL: - button = (event.MouseInput.Wheel > 0) ? - BET_WHEEL_UP : BET_WHEEL_DOWN; - updown = BET_DOWN; - break; - case EMIE_LMOUSE_LEFT_UP: - button = BET_LEFT; updown = BET_UP; - break; - case EMIE_RMOUSE_LEFT_UP: - button = BET_RIGHT; updown = BET_UP; - break; - case EMIE_MMOUSE_LEFT_UP: - button = BET_MIDDLE; updown = BET_UP; - break; - case EMIE_MOUSE_MOVED: - updown = BET_MOVE; - break; - default: - break; + bool mouse_shift = false; + if (event.EventType == EET_MOUSE_INPUT_EVENT) { + mouse_shift = event.MouseInput.Shift; + switch (event.MouseInput.Event) { + case EMIE_LMOUSE_PRESSED_DOWN: + button = BET_LEFT; updown = BET_DOWN; + break; + case EMIE_RMOUSE_PRESSED_DOWN: + button = BET_RIGHT; updown = BET_DOWN; + break; + case EMIE_MMOUSE_PRESSED_DOWN: + button = BET_MIDDLE; updown = BET_DOWN; + break; + case EMIE_MOUSE_WHEEL: + button = (event.MouseInput.Wheel > 0) ? + BET_WHEEL_UP : BET_WHEEL_DOWN; + updown = BET_DOWN; + break; + case EMIE_LMOUSE_LEFT_UP: + button = BET_LEFT; updown = BET_UP; + break; + case EMIE_RMOUSE_LEFT_UP: + button = BET_RIGHT; updown = BET_UP; + break; + case EMIE_MMOUSE_LEFT_UP: + button = BET_MIDDLE; updown = BET_UP; + break; + case EMIE_MOUSE_MOVED: + updown = BET_MOVE; + break; + default: + break; + } } +#ifdef HAVE_TOUCHSCREENGUI + // The second touch (see GUIModalMenu::preprocessEvent() function) + ButtonEventType touch = BET_OTHER; + if (event.EventType == EET_TOUCH_INPUT_EVENT) { + if (event.TouchInput.Event == ETIE_LEFT_UP) + touch = BET_RIGHT; + } +#endif + // Set this number to a positive value to generate a move action // from m_selected_item to s. u32 move_amount = 0; @@ -4332,6 +4347,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) if (m_held_mouse_button != BET_OTHER) break; + if (button == BET_LEFT || button == BET_RIGHT || button == BET_MIDDLE) m_held_mouse_button = button; @@ -4351,13 +4367,13 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) // Craft preview has been clicked: craft if (button == BET_MIDDLE) craft_amount = 10; - else if (event.MouseInput.Shift && button == BET_LEFT) + else if (mouse_shift && button == BET_LEFT) craft_amount = list_s->getItem(s.i).getStackMax(m_client->idef()); else craft_amount = 1; // Holding shift moves the crafted item to the inventory - m_shift_move_after_craft = event.MouseInput.Shift; + m_shift_move_after_craft = mouse_shift; } else if (!m_selected_item && button != BET_WHEEL_UP && !empty) { // Non-empty stack has been clicked: select or shift-move it @@ -4371,7 +4387,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) else if (button == BET_LEFT) count = s_count; - if (event.MouseInput.Shift) { + if (mouse_shift) { // Shift pressed: move item, right click moves 1 shift_move_amount = button == BET_RIGHT ? 1 : count; } else { @@ -4392,7 +4408,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) else if (button == BET_LEFT) move_amount = m_selected_amount; - if (event.MouseInput.Shift && !identical && matching) { + if (mouse_shift && !identical && matching) { // Shift-move all items the same as the selected item to the next list move_amount = 0; @@ -4530,7 +4546,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) if (!s.isValid() || s.listname == "craftpreview") break; - if (!m_selected_item && event.MouseInput.Shift) { + if (!m_selected_item && mouse_shift) { // Shift-move items while dragging if (m_held_mouse_button == BET_RIGHT) shift_move_amount = 1; @@ -4580,7 +4596,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) case BET_OTHER: { // Some other mouse event has occured // Currently only left-double-click should trigger this - if (!s.isValid() || event.MouseInput.Event != EMIE_LMOUSE_DOUBLE_CLICK) + if (!s.isValid() || event.EventType != EET_MOUSE_INPUT_EVENT || + event.MouseInput.Event != EMIE_LMOUSE_DOUBLE_CLICK) break; // Only do the pickup all thing when putting down an item. @@ -4648,6 +4665,28 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) break; } +#ifdef HAVE_TOUCHSCREENGUI + if (touch == BET_RIGHT && m_selected_item && !m_left_dragging) { + if (!s.isValid()) { + // Not a valid slot + if (!getAbsoluteClippingRect().isPointInside(m_pointer)) + // Is outside the menu + drop_amount = 1; + } else { + // Over a valid slot + move_amount = 1; + if (identical) { + // Change the selected amount instead of moving + if (move_amount >= m_selected_amount) + m_selected_amount = 0; + else + m_selected_amount -= move_amount; + move_amount = 0; + } + } + } +#endif + // Update left-dragged slots if (m_left_dragging && m_left_drag_stacks.size() > 1) { // The split amount will always at least one, because the number @@ -5014,6 +5053,11 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } } +#ifdef HAVE_TOUCHSCREENGUI + if (m_second_touch) + return true; // Stop propagating the event +#endif + return Parent ? Parent->OnEvent(event) : false; } diff --git a/src/gui/modalMenu.cpp b/src/gui/modalMenu.cpp index c231f1e722182..0f5ec787a38d8 100644 --- a/src/gui/modalMenu.cpp +++ b/src/gui/modalMenu.cpp @@ -278,12 +278,9 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) irr_ptr holder; holder.grab(this); // keep this alive until return (it might be dropped downstream [?]) - switch ((int)event.TouchInput.touchedCount) { - case 1: { + if (event.TouchInput.ID == 0) { if (event.TouchInput.Event == ETIE_PRESSED_DOWN || event.TouchInput.Event == ETIE_MOVED) m_pointer = v2s32(event.TouchInput.X, event.TouchInput.Y); - if (event.TouchInput.Event == ETIE_PRESSED_DOWN) - m_down_pos = m_pointer; gui::IGUIElement *hovered = Environment->getRootGUIElement()->getElementFromPoint(core::position2d(m_pointer)); if (event.TouchInput.Event == ETIE_PRESSED_DOWN) Environment->setFocus(hovered); @@ -298,26 +295,19 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) if (event.TouchInput.Event == ETIE_LEFT_UP) leave(); return ret; - } - case 2: { - if (event.TouchInput.Event != ETIE_PRESSED_DOWN) + } else if (event.TouchInput.ID == 1) { + if (event.TouchInput.Event != ETIE_LEFT_UP) return true; // ignore auto focused = Environment->getFocus(); if (!focused) return true; - SEvent rclick_event{}; - rclick_event.EventType = EET_MOUSE_INPUT_EVENT; - rclick_event.MouseInput.Event = EMIE_RMOUSE_PRESSED_DOWN; - rclick_event.MouseInput.ButtonStates = EMBSM_LEFT | EMBSM_RIGHT; - rclick_event.MouseInput.X = m_pointer.X; - rclick_event.MouseInput.Y = m_pointer.Y; - focused->OnEvent(rclick_event); - rclick_event.MouseInput.Event = EMIE_RMOUSE_LEFT_UP; - rclick_event.MouseInput.ButtonStates = EMBSM_LEFT; - focused->OnEvent(rclick_event); + // The second-touch event is propagated as is (not converted). + m_second_touch = true; + focused->OnEvent(event); + m_second_touch = false; return true; - } - default: // ignored + } else { + // Any other touch after the second touch is ignored. return true; } } diff --git a/src/gui/modalMenu.h b/src/gui/modalMenu.h index e37c41533636f..f811bafc97781 100644 --- a/src/gui/modalMenu.h +++ b/src/gui/modalMenu.h @@ -77,7 +77,8 @@ class GUIModalMenu : public gui::IGUIElement std::string m_jni_field_name; #endif #ifdef HAVE_TOUCHSCREENGUI - v2s32 m_down_pos; + // This is set to true if the menu is currently processing a second-touch event. + bool m_second_touch = false; bool m_touchscreen_visible = true; #endif