Some notes and ideas how to implement a Window Manager feature for the ui toolkit.
The WM would support creating multiple Window widgets which can be dragged around by their title bar and be focused, placed on top of other windows, and have form controls like Buttons and other widgets embedded.
List of milestones:
- Enable one Window to be dragged by its title bar.
- Add a "Focus" concept to the Supervisor so the most recently clicked Window takes the focus.
- Store the focus history for multiple windows with most recently focused on top. A linked list may be a good data structure for this.
- When Supervisor is considering running an event for e.g. a Button:
- Check its parent tree to see if the Button is part of a Window that is not focused. If so, do not trigger events.
- If not in a window OR the window has focus, do trigger events.
- For simple first pass, widgets in a window are not interactable if their window is not focused.
- Add nice title bar button support: minimize, maximize, close.
(resolved) Hard bug to follow up on later:
If two windows overlap each other with the Focused window on top, and you click into the focused window in a slot covering the lower (Unfocused) window, the Unfocused window will come to the front when it shouldn't.
Root is somewhere in the event handlers for SDL's click event. Debug it like:
Set DebugClickEvents=true in lib/render/sdl/events.go
Code path is like:
- First call to MainWindow.Loop()
- engine.Poll() reads a click event from raw SDL: "[1194 ms] tick:0 MouseButton type:1025 id:0 x:483 y:285 button:1 state:1"
- Supervisor.Loop() called.
- Top focused window has its MouseDown event called. Supervisor prevents calling events on the un-focused window cuz the focused one handled it.
- Next call to MainWindow.Loop(). the ev.State is still the same as last tick: Button1=true etc.; SDL didn't emit any event to change our state.
The state of the code as of
- We have basic draggable, focusable, overlapping windows working.
- Supervisor events are done in two passes:
- First only widgets managed by the focused window have events run. If any widget handled one, skip step 2.
- Only widgets that are NOT owned by windows at all have their events run.
- The effect is: if you mouse over buttons in a background window (not the focused window), the buttons don't light up or respond to the hover events. It's supposed to also be, that clicking the button won't trigger its Click event either. The click should first focus the window of the button, and then you can interact with the button normally.
- What happens is: the lower window rises to top and the button is immediately pressed in by the cursor.
- Also: if the lower window is obscured by the top window, you can click in the top window but activate the lower one!
Deleting a branch is permanent. It CANNOT be undone. Continue?