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

Chaos when a new window is opened during a drag operation #465

Open
timboudreau opened this issue May 27, 2024 · 2 comments
Open

Chaos when a new window is opened during a drag operation #465

timboudreau opened this issue May 27, 2024 · 2 comments

Comments

@timboudreau
Copy link
Contributor

Given:

  • A view which has had draggable() called on it
  • which opens a new window in its drag start handler (and will close it on mouse-up)

things start to go very wrong:

  • Events are not delivered to the newly created window until the mouse-up over it that should end the drag operation
  • The drag operation, as far as the main window and drag-start view is concerned, never ends - any future mouse motion event over it will generate new drag events, but no mouse-up over the view will end the drag operation

It looks like the root problem here is that a distinct AppState is created for each WindowHandle - it isn't really "application state" (though it should be). So the tests of fields of cx.app_state in WindowHandle.event don't get the truth of the application's state, just what one window's handler's have been able to learn about the application's state.

It seems like a fix would start with AppState being shared in some fashion between windows and owned by the Application or ApplicationHandle instead of being created in isolation in WindowHandle.new().

@timboudreau
Copy link
Contributor Author

Thinking about how you'd solve this, and the difficulty of shared mutable data structures in Rust, if we don't want to introduce a global lock of some sort that needs to be taken on every event, the way to solve it might be:

  • Application or ApplicationHandle keeps a global AppState instance.
  • WindowHandle continues to have its own instance
  • Before dispatching an event to a WindowHandle, Application copies its global state into the window's AppState
  • After that call returns, the window's AppState is sync'd back to the global one

It's cheap, allows all windows in the Application to share state, and requires no modifications to anything below WindowHandle in the event processing chain.

@timboudreau
Copy link
Contributor Author

It seems like AppState contains a mixture of things that belong to a window and to the app globally:

  • focus - Window - separate windows can have their own last-focused view
  • active - Ambiguous, probably Application - if a view wants all events, it wants all events, period.
  • root_view_id - Window
  • root - Window
  • root_size - Window
  • scale - Window - this is a little ambiguous: The window scale reflects the monitor scale, which is shared by all windows on the same monitor, but is also settable. Probably window.
  • scheduled_updates - Window
  • request_compute_layout - Window
  • request_paint - Window
  • disabled - Window (could be global, but would require more bookkeeping when a window is closed)
  • keyboard_navigable - Application
  • draggable - Window (same as disabled, could be global)
  • dragging - Application
  • drag_start - Application
  • dragging_over - Application
  • screen_size_bp - Application
  • grid_bps - Window
  • clicking - Application
  • hovered - Application
  • cursor - Window
  • last_cursor - Window
  • keyboard_navigation - Window
  • window_menu - Ambiguous
  • context_menu - Window
  • capture - Window

some of these, if made global, risk leaking dead view ids into global state where they'd never be removed, so it may be best to simply split AppState into truly app-global and window-local properties.

At any rate, I'll experiment with the copy/sync approach to determine if it would even fix the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant