Skip to content

Commit 9d29482

Browse files
committed
Move internal events to a separate enum.
1 parent f3a755f commit 9d29482

File tree

9 files changed

+205
-143
lines changed

9 files changed

+205
-143
lines changed

druid/src/core.rs

Lines changed: 101 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ use crate::bloom::Bloom;
2222
use crate::kurbo::{Affine, Insets, Rect, Shape, Size};
2323
use crate::piet::RenderContext;
2424
use crate::{
25-
BoxConstraints, Command, Data, Env, Event, EventCtx, LayoutCtx, LifeCycle, LifeCycleCtx,
26-
PaintCtx, Target, UpdateCtx, Widget, WidgetId,
25+
BoxConstraints, Command, Data, Env, Event, EventCtx, InternalEvent, InternalLifeCycle,
26+
LayoutCtx, LifeCycle, LifeCycleCtx, PaintCtx, Target, UpdateCtx, Widget, WidgetId,
2727
};
2828

2929
/// Our queue type
@@ -366,7 +366,7 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
366366
}
367367

368368
// log if we seem not to be laid out when we should be
369-
if !matches!(event, Event::WindowConnected | Event::Size(_))
369+
if !matches!(event, Event::WindowConnected | Event::Internal(InternalEvent::Size(_)))
370370
&& self.state.layout_rect.is_none()
371371
{
372372
log::warn!(
@@ -403,12 +403,40 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
403403
let mut recurse = true;
404404
let mut hot_changed = None;
405405
let child_event = match event {
406+
Event::Internal(internal) => match internal {
407+
InternalEvent::Size(size) => {
408+
child_ctx.request_layout();
409+
recurse = ctx.is_root;
410+
Event::Internal(InternalEvent::Size(*size))
411+
}
412+
InternalEvent::MouseLeave => {
413+
let had_hot = child_ctx.base_state.is_hot;
414+
child_ctx.base_state.is_hot = false;
415+
if had_hot {
416+
hot_changed = Some(false);
417+
}
418+
recurse = had_active || had_hot;
419+
Event::Internal(InternalEvent::MouseLeave)
420+
}
421+
InternalEvent::TargetedCommand(target, cmd) => {
422+
match target {
423+
Target::Window(_) => Event::Command(cmd.clone()),
424+
Target::Widget(id) if *id == child_ctx.widget_id() => {
425+
Event::Command(cmd.clone())
426+
}
427+
Target::Widget(id) => {
428+
// Recurse when the target widget could be our descendant.
429+
// The bloom filter we're checking can return false positives.
430+
recurse = child_ctx.base_state.children.may_contain(id);
431+
Event::Internal(InternalEvent::TargetedCommand(*target, cmd.clone()))
432+
}
433+
Target::Global => {
434+
panic!("Target::Global should be converted before WidgetPod")
435+
}
436+
}
437+
}
438+
},
406439
Event::WindowConnected => Event::WindowConnected,
407-
Event::Size(size) => {
408-
child_ctx.request_layout();
409-
recurse = ctx.is_root;
410-
Event::Size(*size)
411-
}
412440
Event::MouseDown(mouse_event) => {
413441
let had_hot = child_ctx.base_state.is_hot;
414442
let now_hot = rect.winding(mouse_event.pos) != 0;
@@ -438,15 +466,6 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
438466
mouse_event.pos -= rect.origin().to_vec2();
439467
Event::MouseMove(mouse_event)
440468
}
441-
Event::MouseLeave => {
442-
let had_hot = child_ctx.base_state.is_hot;
443-
child_ctx.base_state.is_hot = false;
444-
if had_hot {
445-
hot_changed = Some(false);
446-
}
447-
recurse = had_active || had_hot;
448-
Event::MouseLeave
449-
}
450469
Event::KeyDown(e) => {
451470
recurse = child_ctx.has_focus();
452471
Event::KeyDown(*e)
@@ -472,17 +491,6 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
472491
Event::Timer(*id)
473492
}
474493
Event::Command(cmd) => Event::Command(cmd.clone()),
475-
Event::TargetedCommand(target, cmd) => match target {
476-
Target::Window(_) => Event::Command(cmd.clone()),
477-
Target::Widget(id) if *id == child_ctx.widget_id() => Event::Command(cmd.clone()),
478-
Target::Widget(id) => {
479-
// Recurse when the target widget could be our descendant.
480-
// The bloom filter we're checking can return false positives.
481-
recurse = child_ctx.base_state.children.may_contain(id);
482-
Event::TargetedCommand(*target, cmd.clone())
483-
}
484-
Target::Global => panic!("Target::Global should be converted before WidgetPod"),
485-
},
486494
};
487495
if let Some(is_hot) = hot_changed {
488496
let hot_changed_event = LifeCycle::HotChanged(is_hot);
@@ -502,6 +510,70 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
502510

503511
pub fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) {
504512
let recurse = match event {
513+
LifeCycle::Internal(internal) => match internal {
514+
InternalLifeCycle::RouteWidgetAdded => {
515+
// if this is called either we were just created, in
516+
// which case we need to change lifecycle event to
517+
// WidgetAdded or in case we were already created
518+
// we just pass this event down
519+
if self.old_data.is_none() {
520+
self.lifecycle(ctx, &LifeCycle::WidgetAdded, data, env);
521+
return;
522+
} else {
523+
if self.state.children_changed {
524+
self.state.children.clear();
525+
self.state.focus_chain.clear();
526+
}
527+
self.state.children_changed
528+
}
529+
}
530+
InternalLifeCycle::RouteFocusChanged { old, new } => {
531+
self.state.request_focus = None;
532+
533+
let this_changed = if *old == Some(self.state.id) {
534+
Some(false)
535+
} else if *new == Some(self.state.id) {
536+
Some(true)
537+
} else {
538+
None
539+
};
540+
541+
if let Some(change) = this_changed {
542+
// Only send FocusChanged in case there's actual change
543+
if old != new {
544+
self.state.has_focus = change;
545+
let event = LifeCycle::FocusChanged(change);
546+
self.inner.lifecycle(ctx, &event, data, env);
547+
}
548+
false
549+
} else {
550+
self.state.has_focus = false;
551+
// Recurse when the target widgets could be our descendants.
552+
// The bloom filter we're checking can return false positives.
553+
match (old, new) {
554+
(Some(old), _) if self.state.children.may_contain(old) => true,
555+
(_, Some(new)) if self.state.children.may_contain(new) => true,
556+
_ => false,
557+
}
558+
}
559+
}
560+
#[cfg(test)]
561+
InternalLifeCycle::DebugRequestState { widget, state_cell } => {
562+
if *widget == self.id() {
563+
state_cell.set(self.state.clone());
564+
false
565+
} else {
566+
// Recurse when the target widget could be our descendant.
567+
// The bloom filter we're checking can return false positives.
568+
self.state.children.may_contain(&widget)
569+
}
570+
}
571+
#[cfg(test)]
572+
InternalLifeCycle::DebugInspectState(f) => {
573+
f.call(&self.state);
574+
true
575+
}
576+
},
505577
LifeCycle::AnimFrame(_) => {
506578
let r = self.state.request_anim;
507579
self.state.request_anim = false;
@@ -515,74 +587,12 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
515587

516588
true
517589
}
518-
LifeCycle::RouteWidgetAdded => {
519-
// if this is called either we were just created, in
520-
// which case we need to change lifecycle event to
521-
// WidgetAdded or in case we were already created
522-
// we just pass this event down
523-
if self.old_data.is_none() {
524-
self.lifecycle(ctx, &LifeCycle::WidgetAdded, data, env);
525-
return;
526-
} else {
527-
if self.state.children_changed {
528-
self.state.children.clear();
529-
self.state.focus_chain.clear();
530-
}
531-
self.state.children_changed
532-
}
533-
}
534590
LifeCycle::HotChanged(_) => false,
535-
LifeCycle::RouteFocusChanged { old, new } => {
536-
self.state.request_focus = None;
537-
538-
let this_changed = if *old == Some(self.state.id) {
539-
Some(false)
540-
} else if *new == Some(self.state.id) {
541-
Some(true)
542-
} else {
543-
None
544-
};
545-
546-
if let Some(change) = this_changed {
547-
// Only send FocusChanged in case there's actual change
548-
if old != new {
549-
self.state.has_focus = change;
550-
let event = LifeCycle::FocusChanged(change);
551-
self.inner.lifecycle(ctx, &event, data, env);
552-
}
553-
false
554-
} else {
555-
self.state.has_focus = false;
556-
// Recurse when the target widgets could be our descendants.
557-
// The bloom filter we're checking can return false positives.
558-
match (old, new) {
559-
(Some(old), _) if self.state.children.may_contain(old) => true,
560-
(_, Some(new)) if self.state.children.may_contain(new) => true,
561-
_ => false,
562-
}
563-
}
564-
}
565591
LifeCycle::FocusChanged(_) => {
566592
// We are a descendant of a widget that has/had focus.
567593
// Descendants don't inherit focus, so don't recurse.
568594
false
569595
}
570-
#[cfg(test)]
571-
LifeCycle::DebugRequestState { widget, state_cell } => {
572-
if *widget == self.id() {
573-
state_cell.set(self.state.clone());
574-
false
575-
} else {
576-
// Recurse when the target widget could be our descendant.
577-
// The bloom filter we're checking can return false positives.
578-
self.state.children.may_contain(&widget)
579-
}
580-
}
581-
#[cfg(test)]
582-
LifeCycle::DebugInspectState(f) => {
583-
f.call(&self.state);
584-
true
585-
}
586596
};
587597

588598
if recurse {
@@ -598,7 +608,7 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
598608

599609
// we need to (re)register children in case of one of the following events
600610
match event {
601-
LifeCycle::WidgetAdded | LifeCycle::RouteWidgetAdded => {
611+
LifeCycle::WidgetAdded | LifeCycle::Internal(InternalLifeCycle::RouteWidgetAdded) => {
602612
self.state.children_changed = false;
603613
ctx.base_state.children = ctx.base_state.children.union(self.state.children);
604614
ctx.base_state.focus_chain.extend(&self.state.focus_chain);

druid/src/event.rs

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,6 @@ pub enum Event {
5656
///
5757
/// [`LifeCycle::WidgetAdded`]: enum.LifeCycle.html#variant.WidgetAdded
5858
WindowConnected,
59-
/// Called on the root widget when the window size changes.
60-
///
61-
/// Discussion: it's not obvious this should be propagated to user
62-
/// widgets. It *is* propagated through the RootWidget and handled
63-
/// in the WindowPod, but after that it might be considered better
64-
/// to just handle it in `layout`.
65-
///
66-
/// The propagation logic of "just the root" requires a little bit
67-
/// of complexity and state in EventCtx, so if it's not useful it
68-
/// should be removed.
69-
Size(Size),
7059
/// Called when a mouse button is pressed.
7160
MouseDown(MouseEvent),
7261
/// Called when a mouse button is released.
@@ -84,10 +73,6 @@ pub enum Event {
8473
///
8574
/// [`set_cursor`]: struct.EventCtx.html#method.set_cursor
8675
MouseMove(MouseEvent),
87-
/// Called when the mouse has left the window.
88-
///
89-
/// The `MouseLeave` event is propagated to both active and hot widgets.
90-
MouseLeave,
9176
/// Called when a key is pressed.
9277
///
9378
/// Note: the intent is for each physical key press to correspond to
@@ -131,9 +116,31 @@ pub enum Event {
131116
/// [`Widget`]: trait.Widget.html
132117
/// [`EventCtx::submit_command`]: struct.EventCtx.html#method.submit_command
133118
Command(Command),
134-
/// A command still in the process of being dispatched. This is an internal
135-
/// event and should generally not be handled directly by widgets, but is
136-
/// important for containers to dispatch to their children.
119+
/// Internal druid event.
120+
///
121+
/// This should always be passed down to descendant [`WidgetPod`]s.
122+
///
123+
/// [`WidgetPod`]: struct.WidgetPod.html
124+
Internal(InternalEvent),
125+
}
126+
127+
/// Internal events used by druid inside [`WidgetPod`].
128+
///
129+
/// These events are translated into regular [`Event`]s
130+
/// and should not be used directly.
131+
///
132+
/// [`WidgetPod`]: struct.WidgetPod.html
133+
/// [`Event`]: enum.Event.html
134+
#[derive(Debug, Clone)]
135+
pub enum InternalEvent {
136+
/// Sent to the root widget when the window size changes.
137+
Size(Size),
138+
/// Sent in some cases when the mouse has left the window.
139+
///
140+
/// This is used in cases when the platform no longer sends mouse events,
141+
/// but we know that we've stopped receiving the mouse events.
142+
MouseLeave,
143+
/// A command still in the process of being dispatched.
137144
TargetedCommand(Target, Command),
138145
}
139146

@@ -164,8 +171,6 @@ pub enum LifeCycle {
164171
/// [`WidgetPod`]: struct.WidgetPod.html
165172
/// [`LifeCycleCtx::register_for_focus`]: struct.LifeCycleCtx.html#method.register_for_focus
166173
WidgetAdded,
167-
/// Used internally by the framework to route WidgetAdded to the required widgets.
168-
RouteWidgetAdded,
169174
/// Called at the beginning of a new animation frame.
170175
///
171176
/// On the first frame when transitioning from idle to animating, `interval`
@@ -181,13 +186,6 @@ pub enum LifeCycle {
181186
/// See [`is_hot`](struct.EventCtx.html#method.is_hot) for
182187
/// discussion about the hot status.
183188
HotChanged(bool),
184-
/// Internal: used by the framework to route the `FocusChanged` event.
185-
RouteFocusChanged {
186-
/// the widget that is losing focus, if any
187-
old: Option<WidgetId>,
188-
/// the widget that is gaining focus, if any
189-
new: Option<WidgetId>,
190-
},
191189
/// Called when the focus status changes.
192190
///
193191
/// This will always be called immediately after a new widget gains focus.
@@ -198,6 +196,32 @@ pub enum LifeCycle {
198196
///
199197
/// [`EventCtx::is_focused`]: struct.EventCtx.html#method.is_focused
200198
FocusChanged(bool),
199+
/// Internal druid lifecycle event.
200+
///
201+
/// This should always be passed down to descendant [`WidgetPod`]s.
202+
///
203+
/// [`WidgetPod`]: struct.WidgetPod.html
204+
Internal(InternalLifeCycle),
205+
}
206+
207+
/// Internal lifecycle events used by druid inside [`WidgetPod`].
208+
///
209+
/// These events are translated into regular [`LifeCycle`] events
210+
/// and should not be used directly.
211+
///
212+
/// [`WidgetPod`]: struct.WidgetPod.html
213+
/// [`LifeCycle`]: enum.LifeCycle.html
214+
#[derive(Debug, Clone)]
215+
pub enum InternalLifeCycle {
216+
/// Used to route the `WidgetAdded` event to the required widgets.
217+
RouteWidgetAdded,
218+
/// Used to route the `FocusChanged` event.
219+
RouteFocusChanged {
220+
/// the widget that is losing focus, if any
221+
old: Option<WidgetId>,
222+
/// the widget that is gaining focus, if any
223+
new: Option<WidgetId>,
224+
},
201225
/// Testing only: request the `BaseState` of a specific widget.
202226
///
203227
/// During testing, you may wish to verify that the state of a widget

druid/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ pub use command::{sys as commands, Command, Selector, Target};
151151
pub use contexts::{EventCtx, LayoutCtx, LifeCycleCtx, PaintCtx, Region, UpdateCtx};
152152
pub use data::Data;
153153
pub use env::{Env, Key, KeyOrValue, Value, ValueType};
154-
pub use event::{Event, LifeCycle, WheelEvent};
154+
pub use event::{Event, InternalEvent, InternalLifeCycle, LifeCycle, WheelEvent};
155155
pub use ext_event::{ExtEventError, ExtEventSink};
156156
pub use lens::{Lens, LensExt, LensWrap};
157157
pub use localization::LocalizedString;

0 commit comments

Comments
 (0)