You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Event and Lifecycle are propagated down the entire tree but if every single events was processed by every widget that would cause performance issues.
The mechanism which decides which events and lifecycles will be propagated to which parts of the tree is the Pod
Some events are global (e.g. WindowSize) and are handled directly by the Pod and some are local and targeted to specific subset of widgets in the tree (e.g.MouseMove).
Targeted events are controlled by the IS_DISABLED, IS_HANDLED, HAS_ACTIVE, IS_HOT, and HAS_FOCUS flags.
Event Handling Infrastructure
The IS_HANDLED flag is set to false at the root of the tree by the Pod
The widget that processes the event must set the IS_HANDLED flag through its context.
The IS_HANDLED flag applies to keyboard and mouse events.
Each level in the tree checks the IS_HANDLED flag to decide propagation. The check happens in the Pod
Window Event Infrastructure
The fundamental window events are WindowConnected, WindowCloseRequested, and WindowDisconnected and are always sent to all widgets in the tree.
The WindowConfig controls the WindowSize event.
The WindowScale is sent every time the OS changes the resolution of the screen or scale of the screen.
The WindowSize and WindowScale are handled by the Pod and trigger a relayout.
The WindowConnected, WindowCloseRequested, WindowDisconnected, WindowScale, and WindowSize are the associated events to the window event infrastructure.
There are no associated lifecycles to the window event infrastructure.
The Pod is responsible for controlling the propagation of mouse event using the IS_HOT and HAS_ACTIVE flags.
The IS_HOT is an implicit control mechanism and the HAS_ACTIVE an explicit contorl mechanism for mouse events.
The Pod sets the IS_HOT flag for Widgets whose area intersects with the pointer. A widget will always receive mouse events when the IS_HOT flag is active.
If a widget wishes to receive event after the pointer has left its area the widget must set its IS_ACTIVE flags. When it no longer wishes to receive the mouse events it must reset it.
The HAS_ACTIVE flags is automatically set by the Pod for all the ancestors of any widget with an IS_ACTIVE flag.
The MouseDown(MouseEvent), MouseUp(MouseEvent), MouseMove(MouseEvent), MouseWheel(MouseEvent), MouseLeft() are the associated events to the mouse event infrastructure
The HotChanged is the associated lifecycle to the mouse event infrastructure.
pub(crate)enumCursorChange{/// No cursor has been set.Default,/// Someone set a cursor, but if a child widget also set their cursor then we'll use theirs/// instead of ours.Set(Cursor),/// Someone set a cursor, and we'll use it regardless of what the children say.Override(Cursor),}
Keyboard and IME Event Infrastructure
The keyboard can only be used by a single widget at a time.
Widgets can receive keyboard event implicitly by adding themselves to the focus chain using the register_for_focus() or explicitly by sending a request_focus() through their context. Explicit request take presedence over implicit requests. The last widget to request focus gets it. The App manages the focused widget.
Widgets must use register_text_input() when added to the tree.
A widget can check if it has keyboard focus using is_focused() or if any of it's descendant have focus using has_focus()
The HAS_FOCUS flag is automatically set by the Pod for all the ancestors of the widget with the active focus.
A widget can also transfer its keyboard focus to a specific widget using set_focus(IdPath), to the previous or next widget in the focus chain using focus_prev() or focus_next() respectively. A widget can also simply resign focus using resign_focus().
When the focus changes a LifeCycle::FocusChanged is sent.
The LifeCycle::RebuildFocusChain is sent whenever the tree is updated. The register_for_focus() is called when handling the lifecycle.
The KeyDown(KeyEvent), and KeyUp(KeyEvent) are the associated events to the keyboard event infrastructure.
The BuildFocusChain, and FocusChanged(bool) are the associated lifecycles to the keyboard event infrastructure.
pub(crate)enumFocusChange{/// The focused widget is giving up focus.Resign,/// A specific widget wants focusFocus(WidgetId),/// Focus should pass to the next focusable widgetNext,/// Focus should pass to the previous focusable widgetPrevious,}
Accessibility Infrastructure
Animated Frame Event Infrastructure
A widget requests an animated frame through its context.
The frame is routed to glazier and at a later time (implicit control) an AnimFrame is sent with the time ellapsed since the request was made. The widgets that wish to animate themselves can modify their internal state using that value.
If an an element transition is not finished widgets can keep requesting animated frames until they are done.
Widgets must remember to make a paint request for the changes to be shown on screen. They must also not request more animated events than necessary cause that can cause performance issues.
The AnimFrame(u64) is the associated event to the animated frame event infrastructure.
Timer Event Infrastructure
A widget requests a timer through its context.
The frame is routed to glazier and a TimerToken is returned. The framework track which IdPath is associated to which TimerToken
At a later time (explicit control) a TimerToken is sent and routed to the widget.
The Timer(TimerToken) is the associated event to the timer event infrastructure.
Disabled Widget Event Infrastructure
A widget is disabled if itself or an ancestor is
The disabled status is controlled by the widget itself and set through its context
A widget must adapt its event handling and rendering in response to its disabled status
The user can control the disabled status of of widgets by wrapping widgets with DisabledView and passing a callback with the disable condition.
When a widget's disabled status is changed a LifeCycle::DisabledChanged is sent
What's the purpose of children_disabled?
The DisabledChanged(bool) is the associated lifecycle to the disabled event infrastructure
View Context Changed Set Origin Infrstructure
A layout stage consists of a sizing and a positioning pass.
The size is calculated during and the positioning after layout().
If the size of an element changes between cycles a LifeCycle::Size(Size) is sent. The child will receive the LifeCycle::Size(Size) event informing them of the final Size.
A request to recalculate positioning is made during layout() by setting the NEEDS_SET_ORIGIN flag. The origin of a widget is calcualted in the paren't coordinate space and performed after layout() has finished
If the origin has indeed changed the VIEW_CONTEXT_CHANGED and CHILDREN_VIEW_CONTEXT_CHANGED flags are set and a Lifecycle::ViewContextChanged is sent. The hot state must be recalculated when processing the Lifecycle::ViewContextChanged.
The ViewContextChanged and Size(Size) are the associated lifecycles to view context infrastructure
Is there any special handling that needs to be made for the Paste(Clipboard), and Zoom(f64)?
Will Command and Notification be a thing in Xilem? I assume that messages will replace both mechanisms?
Are there any new events that need to be added?
Is the WidgetAdded lifecycle needed here?
Should InternalEvent and InternalLifeCycle be a thing in Xilem as well?
Is the simplification of the framework structs in Xilem intentional or a consequence of not having all the functionality Druid offers?
How do we decide what should be a lifecycle and what should be an event? My intuition tell me that anything generated externally to the framework (e.g. Glazier) should be an event. Anything generated by the framework should be a lifecycle.
Why does the key_down() return a bool?
Since the definitions of mouse is changed to pointer would it make sense to update glazier in the same PR?
Will the request_paint_rect() still be useful?
Which bits should be in both? Should I leave previous bit positions unchanged or can I rearrange stuff for ChangeFlags and PodFlags?
Some of these deserve deeper answers but I'm going to
I don't have any info at the top of my head about Paste and Zoom.
I think most of the uses of Command and Notification go away, as the primary method to update the widget tree is through the build and rebuild methods, and the view tree has its own set of mechanisms for moving data around. That said, we probably do need a way to route commands to widgets internal to the tree, for example for focus tabbing. I don't think we need to preserve this from Druid.
Re WidgetAdded I think I'll refer to xilem#54. One motivating use case for tracking widget tree structure is focus tabbing.
Not sure about InternalEvent and InternalLifeCycle. I think this is part of the lifecycle/event question.
The simplification is partially intentional. Basically if we can get rid of complexity, we should. The process of starting a new codebase, adapting things from the old one, is a way to do that.
The return value of key_down says whether the event is handled. On Windows, if this returns false, then the default windowproc is called. I don't have the specific use cases at the top of my mind, but in general I think it's good for there to be a chain, and when a handler in the chain does process the key, further dispatching is halted.
Yes, it would be good to get all mouse stuff changed to pointer as soon as possible.
request_paint_rect is part of the design for partial invalidation. Here's a Zulip thread with a bit more info. We do want to track damage regions and provide for partial invalidation.
It's fine to rearrange bits in ChangeFlags and PodFlags, people shouldn't be relying on the internal details.
Feel free to keep asking questions, here, on Zulip, and in office hours.
Some of these deserve deeper answers but I'm going to
I don't have any info at the top of my head about
Paste
andZoom
.I think most of the uses of
Command
andNotification
go away, as the primary method to update the widget tree is through the build and rebuild methods, and the view tree has its own set of mechanisms for moving data around. That said, we probably do need a way to route commands to widgets internal to the tree, for example for focus tabbing. I don't think we need to preserve this from Druid.Re
WidgetAdded
I think I'll refer to xilem#54. One motivating use case for tracking widget tree structure is focus tabbing.Not sure about
InternalEvent
andInternalLifeCycle
. I think this is part of the lifecycle/event question.The simplification is partially intentional. Basically if we can get rid of complexity, we should. The process of starting a new codebase, adapting things from the old one, is a way to do that.
The return value of
key_down
says whether the event is handled. On Windows, if this returnsfalse
, then the default windowproc is called. I don't have the specific use cases at the top of my mind, but in general I think it's good for there to be a chain, and when a handler in the chain does process the key, further dispatching is halted.Yes, it would be good to get all mouse stuff changed to pointer as soon as possible.
request_paint_rect
is part of the design for partial invalidation. Here's a Zulip thread with a bit more info. We do want to track damage regions and provide for partial invalidation.It's fine to rearrange bits in
ChangeFlags
andPodFlags
, people shouldn't be relying on the internal details.Feel free to keep asking questions, here, on Zulip, and in office hours.