Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scrollbar doesn't move if cursor moves outside control while dragging #374

Open
nanodeath opened this issue Mar 16, 2021 · 4 comments
Open
Labels
bug Bugs within the program

Comments

@nanodeath
Copy link
Contributor

There is one problem with the ScrollBar though and I don't know a good solution for this. If you drag the scroll button itself, move it hen move the mouse out of the scroll bar, then it no longer receives mouse events (since the mouse is no longer over it). I think there might be a solution for this somehow using event bubbling, but I'm not 100% sure.

Originally posted by @adam-arold in #25 (comment)

@adam-arold adam-arold added the bug Bugs within the program label Mar 28, 2021
@nanodeath
Copy link
Contributor Author

I put together a quick proof-of-concept fix for this; this is the diff:

diff --git a/zircon.core/src/commonMain/kotlin/org/hexworks/zircon/internal/uievent/impl/UIEventToComponentDispatcher.kt b/zircon.core/src/commonMain/kotlin/org/hexworks/zircon/internal/uievent/impl/UIEventToComponentDispatcher.kt
index 8c1e9b180..e0765354a 100644
--- a/zircon.core/src/commonMain/kotlin/org/hexworks/zircon/internal/uievent/impl/UIEventToComponentDispatcher.kt
+++ b/zircon.core/src/commonMain/kotlin/org/hexworks/zircon/internal/uievent/impl/UIEventToComponentDispatcher.kt
@@ -39,6 +39,7 @@ class UIEventToComponentDispatcher(
 
     private var lastMousePosition = Position.unknown()
     private var lastHoveredComponent: InternalComponent = root
+    private var lastPressedComponent: InternalComponent? = null
 
     private val shortcutsConfig = RuntimeConfig.config.shortcutsConfig
 
@@ -192,13 +193,23 @@ class UIEventToComponentDispatcher(
         phase: UIEventPhase,
         previousResult: UIEventResponse
     ): UIEventResponse {
+        val realComponent = lastPressedComponent
+            ?.takeIf { phase == TARGET && (event.type == MOUSE_DRAGGED || event.type == MOUSE_RELEASED) }
+            ?: component
         var result = previousResult
-        result = result.pickByPrecedence(component.process(event, phase))
+        result = result.pickByPrecedence(realComponent.process(event, phase))
         if (result.shouldStopPropagation()) {
 //            logger.debug("Propagation was stopped by component: $component.")
         } else if (result.allowsDefaults()) {
 //            logger.debug("Trying defaults for component $component, with event $event and phase $phase")
-            result = result.pickByPrecedence(tryDefaultsFor(component, event, phase))
+            result = result.pickByPrecedence(tryDefaultsFor(realComponent, event, phase))
+            if (phase == TARGET) {
+                if (event.type == MOUSE_PRESSED) {
+                    lastPressedComponent = component
+                } else if (lastPressedComponent != null && event.type == MOUSE_RELEASED) {
+                    lastPressedComponent = null
+                }
+            }
         }
         return result
     }

This works for me -- you can start clicking on the scrollbar and then keep moving even when the cursor has moved outside the control. Thoughts, @adam-arold?

In fact, this even works if you move the cursor outside the window, but only for the top and left edges, for some reason. Fixing that is out of scope for this issue and, IMO, low priority anyway. But scrollbars near the right and bottom edge of a windowed game might be significantly affected.

There are some weird edge cases I didn't really try to address here. If you start dragging with your left mouse button, and then start dragging with your right mouse button without letting up on the left button...well, maybe it'd work? Hurts to think about. Don't do that 😛

@adam-arold
Copy link
Member

I dig this. 👍 I'm pretty sure there are some bugs lurking there, but we'll go through that bridge when we get there.

@nanodeath
Copy link
Contributor Author

Agree that the potential for edge cases not covered here is high. Like if I let go while outside the control, does that work? What if I'm outside the window? Does this impact non-scroll controls in a meaningful way? (though at least on Windows, if you click on a button, then move the mouse somewhere else, then come back to the button and release your click, it'll act as if it was a simple down-up click. So maybe we want this code change to affect everything.)

@adam-arold
Copy link
Member

We do have a state transition lookup so it shouldn't mess with component states. The logic itself seems sound. I'd merge this then we can play around with the examples and see if something blows up. If the tests pass there is a good chance that this will be OK.

nanodeath added a commit to nanodeath/zircon that referenced this issue May 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bugs within the program
Projects
None yet
Development

No branches or pull requests

2 participants