From 2c965931b4e5d6372d513e67410103d90344e0e6 Mon Sep 17 00:00:00 2001 From: Psycast Date: Tue, 25 Aug 2026 06:35:23 -0230 Subject: [PATCH 1/3] Restore Right, Middle, and double click handling. --- src/System/System.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/System/System.cpp b/src/System/System.cpp index c2f5071f..c35e14b6 100644 --- a/src/System/System.cpp +++ b/src/System/System.cpp @@ -820,32 +820,37 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) { } break; } - case SDL_EVENT_MOUSE_BUTTON_DOWN: - if (event->button.button == SDL_BUTTON_LEFT) { + case SDL_EVENT_MOUSE_BUTTON_DOWN: { + mc = event->button.button; + if (mc >= SDL_BUTTON_LEFT && mc <= SDL_BUTTON_RIGHT) { SDL_CaptureMouse(true); if (myIsInsideMessageLoop) { + auto mdc = mcodes[mc]; float x, y; SDL_GetMouseState(&x, &y); - myEvents.addMousePress(Mouse::LMB, static_cast(x), - static_cast(y), - gSystem->getKeyFlags(), false); - myMouseState.set(Mouse::LMB); + myEvents.addMousePress( + mcodes[mc], static_cast(x), static_cast(y), + gSystem->getKeyFlags(), event->button.clicks >= 2); + myMouseState.set(mcodes[mc]); } } break; - case SDL_EVENT_MOUSE_BUTTON_UP: - if (event->button.button == SDL_BUTTON_LEFT) { + } + case SDL_EVENT_MOUSE_BUTTON_UP: { + mc = event->button.button; + if (mc >= SDL_BUTTON_LEFT && mc <= SDL_BUTTON_RIGHT) { SDL_CaptureMouse(false); if (myIsInsideMessageLoop) { float x, y; SDL_GetMouseState(&x, &y); - myEvents.addMouseRelease(Mouse::LMB, static_cast(x), + myEvents.addMouseRelease(mcodes[mc], static_cast(x), static_cast(y), gSystem->getKeyFlags()); - myMouseState.reset(Mouse::LMB); + myMouseState.reset(mcodes[mc]); } } break; + } case SDL_EVENT_TEXT_INPUT: { const char* wp = event->text.text; const char n = '\n'; From 9ca38aa666b745326879d3f8a3d55049f27bd148 Mon Sep 17 00:00:00 2001 From: Psycast Date: Wed, 26 Aug 2026 03:40:10 -0230 Subject: [PATCH 2/3] Standardize MousePress All other input events use the property instead of using a get/set. This makes all input event structures the same. --- src/Core/GuiDialog.cpp | 4 ++-- src/Core/Input.cpp | 14 -------------- src/Core/Input.h | 8 +------- src/Core/WidgetsColor.cpp | 6 +++--- src/Core/WidgetsScroll.cpp | 8 ++++---- src/Core/WidgetsSelect.cpp | 14 +++++++------- src/Core/WidgetsSimple.cpp | 12 ++++++------ src/Core/WidgetsText.cpp | 8 ++++---- src/Dialogs/ChartList.cpp | 4 ++-- src/Dialogs/LabelBreakdown.cpp | 4 ++-- src/Dialogs/TempoBreakdown.cpp | 4 ++-- src/Editor/Editing.cpp | 4 ++-- src/Editor/Minimap.cpp | 4 ++-- src/Editor/Selection.cpp | 8 ++++---- src/Editor/TextOverlay.cpp | 8 ++++---- src/Editor/View.cpp | 12 ++++++------ 16 files changed, 51 insertions(+), 71 deletions(-) diff --git a/src/Core/GuiDialog.cpp b/src/Core/GuiDialog.cpp index 846da54c..2ec8a921 100644 --- a/src/Core/GuiDialog.cpp +++ b/src/Core/GuiDialog.cpp @@ -138,7 +138,7 @@ void DialogData::onMousePress(MousePress& evt) { stopCapturingMouse(); recti r = rect_; if (isMouseOver()) { - if (evt.button == Mouse::LMB && evt.unhandled()) { + if (evt.button == Mouse::LMB && !evt.handled) { auto actionType = GetAction(evt.x, evt.y); if (actionType != ACT_NONE || IsInside(r, evt.x, evt.y)) { @@ -158,7 +158,7 @@ void DialogData::onMousePress(MousePress& evt) { request_pin_ = true; } } - evt.setHandled(); + evt.handled = true; } } diff --git a/src/Core/Input.cpp b/src/Core/Input.cpp index b3b17fc6..ecad5b33 100644 --- a/src/Core/Input.cpp +++ b/src/Core/Input.cpp @@ -353,18 +353,4 @@ void InputHandler::handleInputs(InputEvents& events) { } } -// ================================================================================================ -// InputHandler :: events structs. - -void MousePress::setHandled() { handled = true; } - -MousePress::MousePress(Mouse::Code code, int x, int y, int keyflags, - bool doubleClick, bool handled) - : button(code), - x(x), - y(y), - keyflags(keyflags), - doubleClick(doubleClick), - handled(handled) {} - } // namespace Vortex diff --git a/src/Core/Input.h b/src/Core/Input.h index 97f1e984..0347d826 100644 --- a/src/Core/Input.h +++ b/src/Core/Input.h @@ -184,18 +184,12 @@ struct MouseMove { /// Contains data from a mouse button press event. struct MousePress { - MousePress(Mouse::Code code, int x, int y, int keyflags, bool doubleClick, - bool handled); Mouse::Code button; ///< The mouse button that was pressed. int x, y; ///< The position of the mouse cursor. int keyflags; ///< Keyflag values of modifier keys that were down. bool doubleClick; ///< True if the press is the second press of a double ///< click. - bool unhandled() const { return !handled; } - void setHandled(); - - private: - bool handled; ///< Used to track if the event is handled. + bool handled; ///< Used to track if the event is handled. }; /// Contains data from a mouse button release event. diff --git a/src/Core/WidgetsColor.cpp b/src/Core/WidgetsColor.cpp index 810aefe9..6b36c283 100644 --- a/src/Core/WidgetsColor.cpp +++ b/src/Core/WidgetsColor.cpp @@ -230,21 +230,21 @@ void WgColorPicker::onMousePress(MousePress& evt) { evt.button == Mouse::LMB) { colorpicker_expanded_->startDrag(evt.x, evt.y); startCapturingMouse(); - evt.setHandled(); + evt.handled = true; } else { delete colorpicker_expanded_; colorpicker_expanded_ = nullptr; stopCapturingFocus(); } } else if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { startCapturingMouse(); startCapturingFocus(); colorpicker_expanded_ = new Expanded; colorpicker_expanded_->tick(rect_, gui_); } - evt.setHandled(); + evt.handled = true; } } diff --git a/src/Core/WidgetsScroll.cpp b/src/Core/WidgetsScroll.cpp index 6505ad04..b3f7f755 100644 --- a/src/Core/WidgetsScroll.cpp +++ b/src/Core/WidgetsScroll.cpp @@ -110,7 +110,7 @@ void WgScrollbar::setPage(int size) { scrollbar_page_ = size; } void WgScrollbar::onMousePress(MousePress& evt) { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { uint32_t action = GetScrollbarActionAtPosition(evt.x, evt.y); if (action) { startCapturingMouse(); @@ -128,7 +128,7 @@ void WgScrollbar::onMousePress(MousePress& evt) { scrollbar_action_ = ACT_DRAGGING_V; } } - evt.setHandled(); + evt.handled = true; } } @@ -240,7 +240,7 @@ void WgScrollRegion::onMouseScroll(MouseScroll& evt) { void WgScrollRegion::onMousePress(MousePress& evt) { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { uint32_t action = getScrollRegionActionAt_(evt.x, evt.y); if (action) { startCapturingMouse(); @@ -260,7 +260,7 @@ void WgScrollRegion::onMousePress(MousePress& evt) { scroll_region_action_ = ACT_DRAGGING_V; } } - evt.setHandled(); + evt.handled = true; } } diff --git a/src/Core/WidgetsSelect.cpp b/src/Core/WidgetsSelect.cpp index 4764a12c..8a14c207 100644 --- a/src/Core/WidgetsSelect.cpp +++ b/src/Core/WidgetsSelect.cpp @@ -40,7 +40,7 @@ void WgSelectList::clearItems() { selectlist_items_.clear(); } void WgSelectList::onMousePress(MousePress& evt) { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { startCapturingMouse(); // Handle interaction with the item list. @@ -53,7 +53,7 @@ void WgSelectList::onMousePress(MousePress& evt) { } } } - evt.setHandled(); + evt.handled = true; } } @@ -181,12 +181,12 @@ void WgDroplist::onMousePress(MousePress& evt) { recti r = selectlist_widget_->getRect(); if (evt.button == Mouse::RMB || !IsInside(r, evt.x, evt.y)) { CloseDroplist(); - evt.setHandled(); + evt.handled = true; } } else if (isMouseOver()) { int numItems = droplist_items_.size(); if (isEnabled() && numItems && evt.button == Mouse::LMB && - evt.unhandled()) { + !evt.handled) { int h = min( numItems * static_cast(18 * gSystem->getScaleFactor()) + 8, static_cast(128 * gSystem->getScaleFactor())); @@ -206,7 +206,7 @@ void WgDroplist::onMousePress(MousePress& evt) { startCapturingMouse(); startCapturingFocus(); } - evt.setHandled(); + evt.handled = true; } } @@ -317,7 +317,7 @@ void WgCycleButton::onMousePress(MousePress& evt) { int numItems = cycle_items_.size(); if (isMouseOver()) { if (numItems > 1 && isEnabled() && evt.button == Mouse::LMB && - evt.unhandled()) { + !evt.handled) { stopCapturingText(); startCapturingMouse(); if (evt.x > CenterX(rect_)) { @@ -327,7 +327,7 @@ void WgCycleButton::onMousePress(MousePress& evt) { } onChange.call(); } - evt.setHandled(); + evt.handled = true; } } diff --git a/src/Core/WidgetsSimple.cpp b/src/Core/WidgetsSimple.cpp index 9a8154d1..a417d211 100644 --- a/src/Core/WidgetsSimple.cpp +++ b/src/Core/WidgetsSimple.cpp @@ -49,13 +49,13 @@ WgButton::WgButton(GuiContext* gui) : GuiWidget(gui) {} void WgButton::onMousePress(MousePress& evt) { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { startCapturingMouse(); isDown.set(true); counter.set(counter.get() + 1); onPress.call(); } - evt.setHandled(); + evt.handled = true; } } @@ -98,12 +98,12 @@ WgCheckbox::WgCheckbox(GuiContext* gui) : GuiWidget(gui) {} void WgCheckbox::onMousePress(MousePress& evt) { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { startCapturingMouse(); value.set(!value.get()); onChange.call(); } - evt.setHandled(); + evt.handled = true; } } @@ -161,11 +161,11 @@ void WgSlider::setRange(double begin, double end) { void WgSlider::onMousePress(MousePress& evt) { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { startCapturingMouse(); SliderDrag(evt.x, evt.y); } - evt.setHandled(); + evt.handled = true; } } diff --git a/src/Core/WidgetsText.cpp b/src/Core/WidgetsText.cpp index 8202c111..34c5bbdd 100644 --- a/src/Core/WidgetsText.cpp +++ b/src/Core/WidgetsText.cpp @@ -127,7 +127,7 @@ void WgLineEdit::onKeyRelease(KeyRelease& evt) { void WgLineEdit::onMousePress(MousePress& evt) { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { if (isCapturingText() && evt.doubleClick) { lineedit_cursor_.x = 0; lineedit_cursor_.y = static_cast(lineedit_text_.length()); @@ -150,7 +150,7 @@ void WgLineEdit::onMousePress(MousePress& evt) { startCapturingMouse(); lineedit_blink_time_ = 0.f; - evt.setHandled(); + evt.handled = true; } } else deselect(); @@ -382,7 +382,7 @@ WgSpinner::WgSpinner(GuiContext* gui) : GuiWidget(gui) { void WgSpinner::onMousePress(MousePress& evt) { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { spinner_lineedit_->deselect(); startCapturingMouse(); recti r = SpinnerButtonRect(); @@ -391,7 +391,7 @@ void WgSpinner::onMousePress(MousePress& evt) { SpinnerUpdateValue(value.get() + spinner_step_size_ * sign); spinner_repeat_timer_ = 0.5f; } - evt.setHandled(); + evt.handled = true; } } diff --git a/src/Dialogs/ChartList.cpp b/src/Dialogs/ChartList.cpp index 843f5a01..978ad804 100644 --- a/src/Dialogs/ChartList.cpp +++ b/src/Dialogs/ChartList.cpp @@ -28,11 +28,11 @@ struct DialogChartList::ChartButton : public GuiWidget { void onMousePress(MousePress& evt) override { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { startCapturingMouse(); gSimfile->openChart(myChartIndex); } - evt.setHandled(); + evt.handled = true; } } diff --git a/src/Dialogs/LabelBreakdown.cpp b/src/Dialogs/LabelBreakdown.cpp index 1892595c..73dd9b60 100644 --- a/src/Dialogs/LabelBreakdown.cpp +++ b/src/Dialogs/LabelBreakdown.cpp @@ -33,11 +33,11 @@ struct DialogLabelBreakdown::LabelButton : public GuiWidget { void onMousePress(MousePress& evt) override { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { startCapturingMouse(); gView->setCursorRow(myRow); } - evt.setHandled(); + evt.handled = true; } } diff --git a/src/Dialogs/TempoBreakdown.cpp b/src/Dialogs/TempoBreakdown.cpp index 43782ae7..07743c79 100644 --- a/src/Dialogs/TempoBreakdown.cpp +++ b/src/Dialogs/TempoBreakdown.cpp @@ -71,11 +71,11 @@ struct DialogTempoBreakdown::TempoList : public WgScrollRegion { void onMousePress(MousePress& evt) override { if (isMouseOver()) { - if (isEnabled() && evt.button == Mouse::LMB && evt.unhandled()) { + if (isEnabled() && evt.button == Mouse::LMB && !evt.handled) { auto seg = getSegmentUnderMouse(gui_->getMousePos()); if (seg) { gView->setCursorRow(seg->row); - evt.setHandled(); + evt.handled = true; } } } diff --git a/src/Editor/Editing.cpp b/src/Editor/Editing.cpp index d8882b8d..5d52d120 100755 --- a/src/Editor/Editing.cpp +++ b/src/Editor/Editing.cpp @@ -296,9 +296,9 @@ struct EditingImpl : public Editing { // Finish tweaking. int mode = gTempo->getTweakMode(); if ((evt.button == Mouse::LMB || evt.button == Mouse::RMB) && mode && - evt.unhandled()) { + !evt.handled) { gTempo->stopTweaking(evt.button == Mouse::LMB); - evt.setHandled(); + evt.handled = true; } } diff --git a/src/Editor/Minimap.cpp b/src/Editor/Minimap.cpp index 33cf74ff..9a85f2a7 100755 --- a/src/Editor/Minimap.cpp +++ b/src/Editor/Minimap.cpp @@ -313,11 +313,11 @@ struct MinimapImpl : public Minimap { void onMousePress(MousePress& evt) override { if (evt.button == Mouse::LMB && !gTextOverlay->isOpen() && - evt.unhandled()) { + !evt.handled) { if (IsInside(rect_, evt.x, evt.y)) { gView->setCursorOffset(myGetMapOffset(evt.y)); myIsDragging = true; - evt.setHandled(); + evt.handled = true; } } } diff --git a/src/Editor/Selection.cpp b/src/Editor/Selection.cpp index 481275dc..6e7315f1 100755 --- a/src/Editor/Selection.cpp +++ b/src/Editor/Selection.cpp @@ -89,19 +89,19 @@ struct SelectionImpl : public Selection { void onMousePress(MousePress& evt) override { // Start dragging a selection box. - if (evt.button == Mouse::LMB && evt.unhandled()) { + if (evt.button == Mouse::LMB && !evt.handled) { myIsDraggingSelection = true; myDragSelectionX = evt.x; myDragSelectionTor = gView->yToOffset(evt.y); - evt.setHandled(); + evt.handled = true; } // Clear selection. - if (evt.button == Mouse::RMB && evt.unhandled()) { + if (evt.button == Mouse::RMB && !evt.handled) { gNotes->deselectAll(); gTempoBoxes->deselectAll(); this->setRegion(0, 0); - evt.setHandled(); + evt.handled = true; } } diff --git a/src/Editor/TextOverlay.cpp b/src/Editor/TextOverlay.cpp index 739e9a42..d076ebe7 100644 --- a/src/Editor/TextOverlay.cpp +++ b/src/Editor/TextOverlay.cpp @@ -522,8 +522,8 @@ struct TextOverlayImpl : public TextOverlay { gSystem->setCursor(Cursor::HAND); MousePress* mp = nullptr; if (gSystem->getEvents().next(mp)) { - if (mp->unhandled()) { - mp->setHandled(); + if (!mp->handled) { + mp->handled = true; gSystem->openWebpage( reinterpret_cast(supportLink)); } @@ -534,8 +534,8 @@ struct TextOverlayImpl : public TextOverlay { gSystem->setCursor(Cursor::HAND); MousePress* mp = nullptr; if (gSystem->getEvents().next(mp)) { - if (mp->unhandled()) { - mp->setHandled(); + if (!mp->handled) { + mp->handled = true; gSystem->openWebpage( reinterpret_cast(githubLink)); } diff --git a/src/Editor/View.cpp b/src/Editor/View.cpp index 25c1646e..e4a638dd 100755 --- a/src/Editor/View.cpp +++ b/src/Editor/View.cpp @@ -129,23 +129,23 @@ struct ViewImpl : public View, public InputHandler { void onMousePress(MousePress& evt) override { // Dragging the preview receptors. if (evt.button == Mouse::LMB && - isMouseOverReceptorsPreview(evt.x, evt.y) && evt.unhandled()) { + isMouseOverReceptorsPreview(evt.x, evt.y) && !evt.handled) { myIsDraggingReceptorsPreview = true; - evt.setHandled(); + evt.handled = true; } // Dragging the receptors. else if (evt.button == Mouse::LMB && - isMouseOverReceptors(evt.x, evt.y) && evt.unhandled()) { + isMouseOverReceptors(evt.x, evt.y) && !evt.handled) { myIsDraggingReceptors = true; - evt.setHandled(); + evt.handled = true; } - if (evt.unhandled() && evt.button == Mouse::MMB) { + if (!evt.handled && evt.button == Mouse::MMB) { Vortex::vec2i mouse_pos = gSystem->getMousePos(); Vortex::ChartOffset ofs = gView->yToOffset(mouse_pos.y); setCursorRow(snapRow(offsetToRow(ofs), SnapDir::SNAP_CLOSEST)); - evt.setHandled(); + evt.handled = true; } } From cce236b4a5530aa5b906da38463fd0bc73763ed8 Mon Sep 17 00:00:00 2001 From: uvcat Date: Sat, 29 Aug 2026 14:49:53 -0700 Subject: [PATCH 3/3] add fixes for linux --- src/Editor/Menubar.cpp | 4 ++-- src/System/System.cpp | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Editor/Menubar.cpp b/src/Editor/Menubar.cpp index 74a40505..2ddb708b 100644 --- a/src/Editor/Menubar.cpp +++ b/src/Editor/Menubar.cpp @@ -862,7 +862,7 @@ struct MenuBarImpl : public Menubar { void onMousePress(MousePress& evt) override { #ifdef GL_MENU_BAR - if (evt.button != Mouse::LMB || !evt.unhandled()) return; + if (evt.button != Mouse::LMB || evt.handled) return; auto handle_menu = [&](MenuItem* menu) { int i = 0; for (auto it : menu->getMenuData()) { @@ -876,7 +876,7 @@ struct MenuBarImpl : public Menubar { else { Action::perform(it.action); } - evt.setHandled(); + evt.handled = true; return false; } return true; diff --git a/src/System/System.cpp b/src/System/System.cpp index b6e28239..db06d458 100644 --- a/src/System/System.cpp +++ b/src/System/System.cpp @@ -810,9 +810,10 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) { auto mdc = mcodes[mc]; float x, y; SDL_GetMouseState(&x, &y); - myEvents.addMousePress( - mcodes[mc], static_cast(x), static_cast(y), - gSystem->getKeyFlags(), event->button.clicks >= 2); + myMousePos = windowMouseToApp(x, y); + myEvents.addMousePress(mcodes[mc], myMousePos.x, + myMousePos.y, gSystem->getKeyFlags(), + event->button.clicks >= 2); myMouseState.set(mcodes[mc]); } } @@ -825,8 +826,9 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) { if (myIsInsideMessageLoop) { float x, y; SDL_GetMouseState(&x, &y); - myEvents.addMouseRelease(mcodes[mc], static_cast(x), - static_cast(y), + myMousePos = windowMouseToApp(x, y); + myEvents.addMouseRelease(mcodes[mc], myMousePos.x, + myMousePos.y, gSystem->getKeyFlags()); myMouseState.reset(mcodes[mc]); }