Skip to content

Commit a0278cb

Browse files
authored
Move internal events to a separate enum. (#833)
* Move internal events to a separate enum. * Rename Size event to WindowSize.
1 parent f3a755f commit a0278cb

File tree

9 files changed

+195
-134
lines changed

9 files changed

+195
-134
lines changed

druid/src/core.rs

Lines changed: 98 additions & 88 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::WindowSize(_))
370370
&& self.state.layout_rect.is_none()
371371
{
372372
log::warn!(
@@ -403,11 +403,39 @@ 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::MouseLeave => {
408+
let had_hot = child_ctx.base_state.is_hot;
409+
child_ctx.base_state.is_hot = false;
410+
if had_hot {
411+
hot_changed = Some(false);
412+
}
413+
recurse = had_active || had_hot;
414+
Event::Internal(InternalEvent::MouseLeave)
415+
}
416+
InternalEvent::TargetedCommand(target, cmd) => {
417+
match target {
418+
Target::Window(_) => Event::Command(cmd.clone()),
419+
Target::Widget(id) if *id == child_ctx.widget_id() => {
420+
Event::Command(cmd.clone())
421+
}
422+
Target::Widget(id) => {
423+
// Recurse when the target widget could be our descendant.
424+
// The bloom filter we're checking can return false positives.
425+
recurse = child_ctx.base_state.children.may_contain(id);
426+
Event::Internal(InternalEvent::TargetedCommand(*target, cmd.clone()))
427+
}
428+
Target::Global => {
429+
panic!("Target::Global should be converted before WidgetPod")
430+
}
431+
}
432+
}
433+
},
406434
Event::WindowConnected => Event::WindowConnected,
407-
Event::Size(size) => {
435+
Event::WindowSize(size) => {
408436
child_ctx.request_layout();
409437
recurse = ctx.is_root;
410-
Event::Size(*size)
438+
Event::WindowSize(*size)
411439
}
412440
Event::MouseDown(mouse_event) => {
413441
let had_hot = child_ctx.base_state.is_hot;
@@ -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: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,7 @@ pub enum Event {
6262
/// widgets. It *is* propagated through the RootWidget and handled
6363
/// in the WindowPod, but after that it might be considered better
6464
/// 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),
65+
WindowSize(Size),
7066
/// Called when a mouse button is pressed.
7167
MouseDown(MouseEvent),
7268
/// Called when a mouse button is released.
@@ -84,10 +80,6 @@ pub enum Event {
8480
///
8581
/// [`set_cursor`]: struct.EventCtx.html#method.set_cursor
8682
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,
9183
/// Called when a key is pressed.
9284
///
9385
/// Note: the intent is for each physical key press to correspond to
@@ -131,9 +123,29 @@ pub enum Event {
131123
/// [`Widget`]: trait.Widget.html
132124
/// [`EventCtx::submit_command`]: struct.EventCtx.html#method.submit_command
133125
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.
126+
/// Internal druid event.
127+
///
128+
/// This should always be passed down to descendant [`WidgetPod`]s.
129+
///
130+
/// [`WidgetPod`]: struct.WidgetPod.html
131+
Internal(InternalEvent),
132+
}
133+
134+
/// Internal events used by druid inside [`WidgetPod`].
135+
///
136+
/// These events are translated into regular [`Event`]s
137+
/// and should not be used directly.
138+
///
139+
/// [`WidgetPod`]: struct.WidgetPod.html
140+
/// [`Event`]: enum.Event.html
141+
#[derive(Debug, Clone)]
142+
pub enum InternalEvent {
143+
/// Sent in some cases when the mouse has left the window.
144+
///
145+
/// This is used in cases when the platform no longer sends mouse events,
146+
/// but we know that we've stopped receiving the mouse events.
147+
MouseLeave,
148+
/// A command still in the process of being dispatched.
137149
TargetedCommand(Target, Command),
138150
}
139151

@@ -164,8 +176,6 @@ pub enum LifeCycle {
164176
/// [`WidgetPod`]: struct.WidgetPod.html
165177
/// [`LifeCycleCtx::register_for_focus`]: struct.LifeCycleCtx.html#method.register_for_focus
166178
WidgetAdded,
167-
/// Used internally by the framework to route WidgetAdded to the required widgets.
168-
RouteWidgetAdded,
169179
/// Called at the beginning of a new animation frame.
170180
///
171181
/// On the first frame when transitioning from idle to animating, `interval`
@@ -181,13 +191,6 @@ pub enum LifeCycle {
181191
/// See [`is_hot`](struct.EventCtx.html#method.is_hot) for
182192
/// discussion about the hot status.
183193
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-
},
191194
/// Called when the focus status changes.
192195
///
193196
/// This will always be called immediately after a new widget gains focus.
@@ -198,6 +201,32 @@ pub enum LifeCycle {
198201
///
199202
/// [`EventCtx::is_focused`]: struct.EventCtx.html#method.is_focused
200203
FocusChanged(bool),
204+
/// Internal druid lifecycle event.
205+
///
206+
/// This should always be passed down to descendant [`WidgetPod`]s.
207+
///
208+
/// [`WidgetPod`]: struct.WidgetPod.html
209+
Internal(InternalLifeCycle),
210+
}
211+
212+
/// Internal lifecycle events used by druid inside [`WidgetPod`].
213+
///
214+
/// These events are translated into regular [`LifeCycle`] events
215+
/// and should not be used directly.
216+
///
217+
/// [`WidgetPod`]: struct.WidgetPod.html
218+
/// [`LifeCycle`]: enum.LifeCycle.html
219+
#[derive(Debug, Clone)]
220+
pub enum InternalLifeCycle {
221+
/// Used to route the `WidgetAdded` event to the required widgets.
222+
RouteWidgetAdded,
223+
/// Used to route the `FocusChanged` event.
224+
RouteFocusChanged {
225+
/// the widget that is losing focus, if any
226+
old: Option<WidgetId>,
227+
/// the widget that is gaining focus, if any
228+
new: Option<WidgetId>,
229+
},
201230
/// Testing only: request the `BaseState` of a specific widget.
202231
///
203232
/// 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)