Skip to content

Commit 9d242fb

Browse files
committed
fix / refactor iced-sctk redraw & frame event handling
1 parent e419ad1 commit 9d242fb

11 files changed

Lines changed: 123 additions & 104 deletions

File tree

examples/sctk_todos/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2021"
66
publish = false
77

88
[dependencies]
9-
iced = { path = "../..", default-features=false, features = ["async-std", "wayland", "debug", "a11y"] }
9+
iced = { path = "../..", default-features=false, features = ["async-std", "wayland", "debug"] }
1010
serde = { version = "1.0", features = ["derive"] }
1111
serde_json = "1.0"
1212
once_cell = "1.15"

examples/sctk_todos/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,7 @@ impl Application for Todos {
210210
widget::focus_next()
211211
}
212212
}
213-
Message::CloseRequested(s) => {
214-
dbg!(s);
213+
Message::CloseRequested(_) => {
215214
std::process::exit(0);
216215
}
217216
Message::TextInputDragged(text_input_state) => {

examples/todos/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2021"
66
publish = false
77

88
[dependencies]
9-
iced = { path = "../..", features = ["async-std", "debug", "a11y"] }
9+
iced = { path = "../..", features = ["async-std", "debug"] }
1010
serde = { version = "1.0", features = ["derive"] }
1111
serde_json = "1.0"
1212
once_cell = "1.15"

sctk/src/application.rs

Lines changed: 96 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -304,15 +304,15 @@ where
304304

305305
let poll = instance.as_mut().poll(&mut context);
306306

307-
*control_flow = match poll {
307+
match poll {
308308
task::Poll::Pending => {
309309
if let Ok(Some(flow)) = control_receiver.try_next() {
310-
flow
311-
} else {
312-
ControlFlow::Wait
310+
*control_flow = flow
313311
}
314312
}
315-
task::Poll::Ready(_) => ControlFlow::ExitWithCode(1),
313+
task::Poll::Ready(_) => {
314+
*control_flow = ControlFlow::ExitWithCode(1)
315+
}
316316
};
317317
});
318318

@@ -700,14 +700,6 @@ where
700700
}
701701
SctkEvent::RemovedOutput( ..) => {
702702
}
703-
SctkEvent::Frame(surface) => {
704-
if let Some(id) = surface_ids.get(&surface.id()) {
705-
if let Some(state) = states.get_mut(&id.inner()) {
706-
// TODO set this to the callback?
707-
state.set_frame(Some(surface));
708-
}
709-
}
710-
},
711703
SctkEvent::ScaleFactorChanged { .. } => {}
712704
SctkEvent::DataSource(DataSourceEvent::DndFinished) | SctkEvent::DataSource(DataSourceEvent::DndCancelled)=> {
713705
surface_ids.retain(|id, surface_id| {
@@ -839,6 +831,13 @@ where
839831
interfaces.insert(native_id, user_interface);
840832
}
841833
IcedSctkEvent::MainEventsCleared => {
834+
if !redraw_pending
835+
&& sctk_events.is_empty()
836+
&& messages.is_empty()
837+
{
838+
continue;
839+
}
840+
842841
let mut i = 0;
843842
while i < sctk_events.len() {
844843
let remove = matches!(
@@ -897,6 +896,7 @@ where
897896
break 'main;
898897
}
899898
} else {
899+
let mut needs_update = false;
900900
for (object_id, surface_id) in &surface_ids {
901901
if matches!(surface_id, SurfaceIdWrapper::Dnd(_)) {
902902
continue;
@@ -1014,10 +1014,15 @@ where
10141014
user_interface::State::Outdated
10151015
)
10161016
{
1017-
state.set_needs_redraw(true);
1017+
state.set_needs_redraw(state.frame.is_some());
1018+
needs_update = !messages.is_empty()
1019+
|| matches!(
1020+
interface_state,
1021+
user_interface::State::Outdated
1022+
);
10181023
}
10191024
}
1020-
if states.iter().any(|(_, s)| s.needs_redraw) {
1025+
if needs_update {
10211026
let mut pure_states: HashMap<_, _> =
10221027
ManuallyDrop::into_inner(interfaces)
10231028
.drain()
@@ -1076,86 +1081,84 @@ where
10761081
&mut auto_size_surfaces,
10771082
&mut ev_proxy,
10781083
));
1084+
}
1085+
for (object_id, surface_id) in &surface_ids {
1086+
let state = match states.get_mut(&surface_id.inner()) {
1087+
Some(s) => {
1088+
if !s.needs_redraw() {
1089+
continue;
1090+
} else {
1091+
s.set_needs_redraw(false);
10791092

1080-
for (object_id, surface_id) in &surface_ids {
1081-
let state = match states
1082-
.get_mut(&surface_id.inner())
1083-
{
1084-
Some(s) => {
1085-
if !s.needs_redraw() || s.frame().is_none()
1086-
{
1087-
continue;
1088-
} else {
1089-
s
1090-
}
1093+
s
10911094
}
1092-
None => continue,
1095+
}
1096+
None => continue,
1097+
};
1098+
let Some(user_interface) = interfaces
1099+
.get_mut(&surface_id.inner()) else {
1100+
continue;
10931101
};
1094-
let Some(user_interface) = interfaces
1095-
.get_mut(&surface_id.inner()) else {
1096-
continue;
1097-
};
1098-
let redraw_event = CoreEvent::Window(
1099-
surface_id.inner(),
1100-
crate::core::window::Event::RedrawRequested(
1101-
Instant::now(),
1102-
),
1103-
);
1104-
1105-
let (interface_state, _) = user_interface.update(
1106-
&[redraw_event.clone()],
1107-
state.cursor(),
1108-
&mut renderer,
1109-
&mut simple_clipboard,
1110-
&mut messages,
1111-
);
11121102

1113-
debug.draw_started();
1114-
let new_mouse_interaction = user_interface.draw(
1115-
&mut renderer,
1116-
state.theme(),
1117-
&Style {
1118-
text_color: state.text_color(),
1119-
},
1120-
state.cursor(),
1121-
);
1122-
debug.draw_finished();
1103+
let redraw_event = CoreEvent::Window(
1104+
surface_id.inner(),
1105+
crate::core::window::Event::RedrawRequested(
1106+
Instant::now(),
1107+
),
1108+
);
11231109

1124-
if new_mouse_interaction != mouse_interaction {
1125-
mouse_interaction = new_mouse_interaction;
1126-
ev_proxy.send_event(Event::SetCursor(
1127-
mouse_interaction,
1128-
));
1129-
}
1110+
let (interface_state, _) = user_interface.update(
1111+
&[redraw_event.clone()],
1112+
state.cursor(),
1113+
&mut renderer,
1114+
&mut simple_clipboard,
1115+
&mut messages,
1116+
);
11301117

1131-
runtime.broadcast(redraw_event, Status::Ignored);
1118+
debug.draw_started();
1119+
let new_mouse_interaction = user_interface.draw(
1120+
&mut renderer,
1121+
state.theme(),
1122+
&Style {
1123+
text_color: state.text_color(),
1124+
},
1125+
state.cursor(),
1126+
);
1127+
debug.draw_finished();
11321128

1133-
ev_proxy.send_event(Event::SctkEvent(
1134-
IcedSctkEvent::RedrawRequested(
1135-
object_id.clone(),
1136-
),
1129+
if new_mouse_interaction != mouse_interaction {
1130+
mouse_interaction = new_mouse_interaction;
1131+
ev_proxy.send_event(Event::SetCursor(
1132+
mouse_interaction,
11371133
));
1138-
1139-
let _ =
1140-
control_sender
1141-
.start_send(match interface_state {
1142-
user_interface::State::Updated {
1143-
redraw_request: Some(redraw_request),
1144-
} => match redraw_request {
1145-
crate::core::window::RedrawRequest::NextFrame => {
1146-
ControlFlow::Poll
1147-
}
1148-
crate::core::window::RedrawRequest::At(at) => {
1149-
ControlFlow::WaitUntil(at)
1150-
}
1151-
},
1152-
_ => ControlFlow::Wait,
1153-
});
1154-
state.set_needs_redraw(false);
1155-
redraw_pending = false;
11561134
}
1135+
1136+
runtime.broadcast(redraw_event, Status::Ignored);
1137+
1138+
ev_proxy.send_event(Event::SctkEvent(
1139+
IcedSctkEvent::RedrawRequested(object_id.clone()),
1140+
));
1141+
1142+
let _ =
1143+
control_sender
1144+
.start_send(match interface_state {
1145+
user_interface::State::Updated {
1146+
redraw_request: Some(redraw_request),
1147+
} => {
1148+
match redraw_request {
1149+
crate::core::window::RedrawRequest::NextFrame => {
1150+
ControlFlow::Poll
1151+
}
1152+
crate::core::window::RedrawRequest::At(at) => {
1153+
ControlFlow::WaitUntil(at)
1154+
}
1155+
}},
1156+
_ => ControlFlow::Wait,
1157+
});
11571158
}
1159+
redraw_pending = false;
11581160
}
1161+
11591162
sctk_events.clear();
11601163
// clear the destroyed surfaces after they have been handled
11611164
destroyed_surface_ids.clear();
@@ -1369,6 +1372,14 @@ where
13691372
IcedSctkEvent::A11ySurfaceCreated(surface_id, adapter) => {
13701373
adapters.insert(surface_id.inner(), adapter);
13711374
}
1375+
IcedSctkEvent::Frame(surface) => {
1376+
if let Some(id) = surface_ids.get(&surface.id()) {
1377+
if let Some(state) = states.get_mut(&id.inner()) {
1378+
// TODO set this to the callback?
1379+
state.set_frame(Some(surface));
1380+
}
1381+
}
1382+
}
13721383
}
13731384
}
13741385

@@ -1960,8 +1971,7 @@ fn event_is_for_surface(
19601971
SctkEvent::WindowEvent { id, .. } => &id.id() == object_id,
19611972
SctkEvent::LayerSurfaceEvent { id, .. } => &id.id() == object_id,
19621973
SctkEvent::PopupEvent { id, .. } => &id.id() == object_id,
1963-
SctkEvent::Frame(_)
1964-
| SctkEvent::NewOutput { .. }
1974+
SctkEvent::NewOutput { .. }
19651975
| SctkEvent::UpdateOutput { .. }
19661976
| SctkEvent::RemovedOutput(_) => false,
19671977
SctkEvent::ScaleFactorChanged { id, .. } => &id.id() == object_id,

sctk/src/event_loop/mod.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ where
196196
dnd_source: None,
197197
_kbd_focus: None,
198198
sctk_events: Vec::new(),
199+
frame_events: Vec::new(),
199200
pending_user_events: Vec::new(),
200201
token_ctr: 0,
201202
selection_source: None,
@@ -300,6 +301,7 @@ where
300301

301302
let mut sctk_event_sink_back_buffer = Vec::new();
302303
let mut compositor_event_back_buffer = Vec::new();
304+
let mut frame_event_back_buffer = Vec::new();
303305

304306
// NOTE We break on errors from dispatches, since if we've got protocol error
305307
// libwayland-client/wayland-rs will inform us anyway, but crashing downstream is not
@@ -470,6 +472,20 @@ where
470472
}
471473
}
472474

475+
std::mem::swap(
476+
&mut frame_event_back_buffer,
477+
&mut self.state.frame_events,
478+
);
479+
480+
for event in frame_event_back_buffer.drain(..) {
481+
sticky_exit_callback(
482+
IcedSctkEvent::Frame(event),
483+
&self.state,
484+
&mut control_flow,
485+
&mut callback,
486+
);
487+
}
488+
473489
// The purpose of the back buffer and that swap is to not hold borrow_mut when
474490
// we're doing callback to the user, since we can double borrow if the user decides
475491
// to create a window in one of those callbacks.
@@ -503,12 +519,6 @@ where
503519
// Handle pending sctk events.
504520
for event in sctk_event_sink_back_buffer.drain(..) {
505521
match event {
506-
SctkEvent::Frame(id) => sticky_exit_callback(
507-
IcedSctkEvent::SctkEvent(SctkEvent::Frame(id)),
508-
&self.state,
509-
&mut control_flow,
510-
&mut callback,
511-
),
512522
SctkEvent::PopupEvent {
513523
variant: PopupEventVariant::Done,
514524
toplevel_id,

sctk/src/event_loop/state.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ pub struct SctkState<T> {
314314
/// A sink for window and device events that is being filled during dispatching
315315
/// event loop and forwarded downstream afterwards.
316316
pub(crate) sctk_events: Vec<SctkEvent>,
317+
pub(crate) frame_events: Vec<WlSurface>,
317318

318319
/// pending user events
319320
pub pending_user_events: Vec<Event<T>>,

sctk/src/handlers/compositor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl<T: Debug> CompositorHandler for SctkState<T> {
2727
surface: &wl_surface::WlSurface,
2828
_time: u32,
2929
) {
30-
self.sctk_events.push(SctkEvent::Frame(surface.clone()));
30+
self.frame_events.push(surface.clone());
3131
}
3232
}
3333

sctk/src/handlers/shell/layer.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ impl<T: Debug> LayerShellHandler for SctkState<T> {
7373
),
7474
id: layer.surface.wl_surface().clone(),
7575
});
76-
self.sctk_events
77-
.push(SctkEvent::Frame(layer.surface.wl_surface().clone()));
76+
self.frame_events.push(layer.surface.wl_surface().clone());
7877
}
7978
}
8079

sctk/src/handlers/shell/xdg_popup.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ impl<T: Debug> PopupHandler for SctkState<T> {
3636
SctkSurface::Popup(s) => s.clone(),
3737
},
3838
});
39-
self.sctk_events
40-
.push(SctkEvent::Frame(popup.wl_surface().clone()));
39+
self.frame_events.push(popup.wl_surface().clone());
4140
}
4241

4342
fn done(

sctk/src/handlers/shell/xdg_window.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl<T: Debug> WindowHandler for SctkState<T> {
9292
),
9393
id,
9494
});
95-
self.sctk_events.push(SctkEvent::Frame(wl_surface.clone()));
95+
self.frame_events.push(wl_surface.clone());
9696
}
9797
}
9898

0 commit comments

Comments
 (0)