summaryrefslogtreecommitdiffstats
path: root/winit/src/program.rs
diff options
context:
space:
mode:
Diffstat (limited to 'winit/src/program.rs')
-rw-r--r--winit/src/program.rs579
1 files changed, 303 insertions, 276 deletions
diff --git a/winit/src/program.rs b/winit/src/program.rs
index 8d1eec3a..5387e5e5 100644
--- a/winit/src/program.rs
+++ b/winit/src/program.rs
@@ -8,10 +8,11 @@ use crate::conversion;
use crate::core;
use crate::core::mouse;
use crate::core::renderer;
+use crate::core::theme;
use crate::core::time::Instant;
use crate::core::widget::operation;
use crate::core::window;
-use crate::core::{Color, Element, Point, Size, Theme};
+use crate::core::{Element, Point, Size};
use crate::futures::futures::channel::mpsc;
use crate::futures::futures::channel::oneshot;
use crate::futures::futures::task;
@@ -46,7 +47,7 @@ use std::sync::Arc;
pub trait Program
where
Self: Sized,
- Self::Theme: DefaultStyle,
+ Self::Theme: theme::Base,
{
/// The type of __messages__ your [`Program`] will produce.
type Message: std::fmt::Debug + Send;
@@ -106,8 +107,8 @@ where
fn theme(&self, window: window::Id) -> Self::Theme;
/// Returns the `Style` variation of the `Theme`.
- fn style(&self, theme: &Self::Theme) -> Appearance {
- theme.default_style()
+ fn style(&self, theme: &Self::Theme) -> theme::Style {
+ theme::Base::base(theme)
}
/// Returns the event `Subscription` for the current state of the
@@ -138,37 +139,6 @@ where
}
}
-/// The appearance of a program.
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub struct Appearance {
- /// The background [`Color`] of the application.
- pub background_color: Color,
-
- /// The default text [`Color`] of the application.
- pub text_color: Color,
-}
-
-/// The default style of a [`Program`].
-pub trait DefaultStyle {
- /// Returns the default style of a [`Program`].
- fn default_style(&self) -> Appearance;
-}
-
-impl DefaultStyle for Theme {
- fn default_style(&self) -> Appearance {
- default(self)
- }
-}
-
-/// The default [`Appearance`] of a [`Program`] with the built-in [`Theme`].
-pub fn default(theme: &Theme) -> Appearance {
- let palette = theme.extended_palette();
-
- Appearance {
- background_color: palette.background.base.color,
- text_color: palette.background.base.text,
- }
-}
/// Runs a [`Program`] with an executor, compositor, and the provided
/// settings.
pub fn run<P, C>(
@@ -180,7 +150,7 @@ pub fn run<P, C>(
where
P: Program + 'static,
C: Compositor<Renderer = P::Renderer> + 'static,
- P::Theme: DefaultStyle,
+ P::Theme: theme::Base,
{
use winit::event_loop::EventLoop;
@@ -222,7 +192,6 @@ where
runtime.enter(|| program.subscription().map(Action::Output)),
));
- let (boot_sender, boot_receiver) = oneshot::channel();
let (event_sender, event_receiver) = mpsc::unbounded();
let (control_sender, control_receiver) = mpsc::unbounded();
@@ -231,133 +200,49 @@ where
runtime,
proxy.clone(),
debug,
- boot_receiver,
event_receiver,
control_sender,
is_daemon,
+ graphics_settings,
+ settings.fonts,
));
let context = task::Context::from_waker(task::noop_waker_ref());
- struct Runner<Message: 'static, F, C> {
+ struct Runner<Message: 'static, F> {
instance: std::pin::Pin<Box<F>>,
context: task::Context<'static>,
id: Option<String>,
- boot: Option<BootConfig<C>>,
sender: mpsc::UnboundedSender<Event<Action<Message>>>,
receiver: mpsc::UnboundedReceiver<Control>,
error: Option<Error>,
#[cfg(target_arch = "wasm32")]
- is_booted: std::rc::Rc<std::cell::RefCell<bool>>,
- #[cfg(target_arch = "wasm32")]
canvas: Option<web_sys::HtmlCanvasElement>,
}
- struct BootConfig<C> {
- sender: oneshot::Sender<Boot<C>>,
- fonts: Vec<Cow<'static, [u8]>>,
- graphics_settings: graphics::Settings,
- }
-
let runner = Runner {
instance,
context,
id: settings.id,
- boot: Some(BootConfig {
- sender: boot_sender,
- fonts: settings.fonts,
- graphics_settings,
- }),
sender: event_sender,
receiver: control_receiver,
error: None,
#[cfg(target_arch = "wasm32")]
- is_booted: std::rc::Rc::new(std::cell::RefCell::new(false)),
- #[cfg(target_arch = "wasm32")]
canvas: None,
};
- impl<Message, F, C> winit::application::ApplicationHandler<Action<Message>>
- for Runner<Message, F, C>
+ impl<Message, F> winit::application::ApplicationHandler<Action<Message>>
+ for Runner<Message, F>
where
Message: std::fmt::Debug,
F: Future<Output = ()>,
- C: Compositor + 'static,
{
- fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
- let Some(BootConfig {
- sender,
- fonts,
- graphics_settings,
- }) = self.boot.take()
- else {
- return;
- };
-
- let window = {
- let attributes = winit::window::WindowAttributes::default();
-
- #[cfg(target_os = "windows")]
- let attributes = {
- use winit::platform::windows::WindowAttributesExtWindows;
- attributes.with_drag_and_drop(false)
- };
-
- match event_loop.create_window(attributes.with_visible(false)) {
- Ok(window) => Arc::new(window),
- Err(error) => {
- self.error = Some(Error::WindowCreationFailed(error));
- event_loop.exit();
- return;
- }
- }
- };
-
- #[cfg(target_arch = "wasm32")]
- {
- use winit::platform::web::WindowExtWebSys;
- self.canvas = window.canvas();
- }
-
- let finish_boot = async move {
- let mut compositor =
- C::new(graphics_settings, window.clone()).await?;
-
- for font in fonts {
- compositor.load_font(font);
- }
-
- sender
- .send(Boot { compositor })
- .ok()
- .expect("Send boot event");
-
- Ok::<_, graphics::Error>(())
- };
-
- #[cfg(not(target_arch = "wasm32"))]
- if let Err(error) =
- crate::futures::futures::executor::block_on(finish_boot)
- {
- self.error = Some(Error::GraphicsCreationFailed(error));
- event_loop.exit();
- }
-
- #[cfg(target_arch = "wasm32")]
- {
- let is_booted = self.is_booted.clone();
-
- wasm_bindgen_futures::spawn_local(async move {
- finish_boot.await.expect("Finish boot!");
-
- *is_booted.borrow_mut() = true;
- });
-
- event_loop
- .set_control_flow(winit::event_loop::ControlFlow::Poll);
- }
+ fn resumed(
+ &mut self,
+ _event_loop: &winit::event_loop::ActiveEventLoop,
+ ) {
}
fn new_events(
@@ -365,15 +250,6 @@ where
event_loop: &winit::event_loop::ActiveEventLoop,
cause: winit::event::StartCause,
) {
- if self.boot.is_some() {
- return;
- }
-
- #[cfg(target_arch = "wasm32")]
- if !*self.is_booted.borrow() {
- return;
- }
-
self.process_event(
event_loop,
Event::EventLoopAwakened(winit::event::Event::NewEvents(cause)),
@@ -452,11 +328,6 @@ where
&mut self,
event_loop: &winit::event_loop::ActiveEventLoop,
) {
- #[cfg(target_arch = "wasm32")]
- if !*self.is_booted.borrow() {
- return;
- }
-
self.process_event(
event_loop,
Event::EventLoopAwakened(winit::event::Event::AboutToWait),
@@ -464,10 +335,9 @@ where
}
}
- impl<Message, F, C> Runner<Message, F, C>
+ impl<Message, F> Runner<Message, F>
where
F: Future<Output = ()>,
- C: Compositor,
{
fn process_event(
&mut self,
@@ -538,10 +408,25 @@ where
log::info!("Window attributes for id `{id:#?}`: {window_attributes:#?}");
+ // On macOS, the `position` in `WindowAttributes` represents the "inner"
+ // position of the window; while on other platforms it's the "outer" position.
+ // We fix the inconsistency on macOS by positioning the window after creation.
+ #[cfg(target_os = "macos")]
+ let mut window_attributes = window_attributes;
+
+ #[cfg(target_os = "macos")]
+ let position =
+ window_attributes.position.take();
+
let window = event_loop
.create_window(window_attributes)
.expect("Create window");
+ #[cfg(target_os = "macos")]
+ if let Some(position) = position {
+ window.set_outer_position(position);
+ }
+
#[cfg(target_arch = "wasm32")]
{
use winit::platform::web::WindowExtWebSys;
@@ -592,7 +477,7 @@ where
event_loop,
Event::WindowCreated {
id,
- window,
+ window: Arc::new(window),
exit_on_close_request,
make_visible: visible,
on_open,
@@ -602,6 +487,10 @@ where
Control::Exit => {
event_loop.exit();
}
+ Control::Crash(error) => {
+ self.error = Some(error);
+ event_loop.exit();
+ }
},
_ => {
break;
@@ -633,15 +522,11 @@ where
}
}
-struct Boot<C> {
- compositor: C,
-}
-
#[derive(Debug)]
enum Event<Message: 'static> {
WindowCreated {
id: window::Id,
- window: winit::window::Window,
+ window: Arc<winit::window::Window>,
exit_on_close_request: bool,
make_visible: bool,
on_open: oneshot::Sender<window::Id>,
@@ -653,6 +538,7 @@ enum Event<Message: 'static> {
enum Control {
ChangeFlow(winit::event_loop::ControlFlow),
Exit,
+ Crash(Error),
CreateWindow {
id: window::Id,
settings: window::Settings,
@@ -667,23 +553,23 @@ async fn run_instance<P, C>(
mut runtime: Runtime<P::Executor, Proxy<P::Message>, Action<P::Message>>,
mut proxy: Proxy<P::Message>,
mut debug: Debug,
- boot: oneshot::Receiver<Boot<C>>,
mut event_receiver: mpsc::UnboundedReceiver<Event<Action<P::Message>>>,
mut control_sender: mpsc::UnboundedSender<Control>,
is_daemon: bool,
+ graphics_settings: graphics::Settings,
+ default_fonts: Vec<Cow<'static, [u8]>>,
) where
P: Program + 'static,
C: Compositor<Renderer = P::Renderer> + 'static,
- P::Theme: DefaultStyle,
+ P::Theme: theme::Base,
{
use winit::event;
use winit::event_loop::ControlFlow;
- let Boot { mut compositor } = boot.await.expect("Receive boot");
-
let mut window_manager = WindowManager::new();
let mut is_window_opening = !is_daemon;
+ let mut compositor = None;
let mut events = Vec::new();
let mut messages = Vec::new();
let mut actions = 0;
@@ -691,12 +577,35 @@ async fn run_instance<P, C>(
let mut ui_caches = FxHashMap::default();
let mut user_interfaces = ManuallyDrop::new(FxHashMap::default());
let mut clipboard = Clipboard::unconnected();
+ let mut compositor_receiver: Option<oneshot::Receiver<_>> = None;
debug.startup_finished();
loop {
+ let event = if compositor_receiver.is_some() {
+ let compositor_receiver =
+ compositor_receiver.take().expect("Waiting for compositor");
+
+ match compositor_receiver.await {
+ Ok(Ok((new_compositor, event))) => {
+ compositor = Some(new_compositor);
+
+ Some(event)
+ }
+ Ok(Err(error)) => {
+ control_sender
+ .start_send(Control::Crash(
+ Error::GraphicsCreationFailed(error),
+ ))
+ .expect("Send control action");
+ break;
+ }
+ Err(error) => {
+ panic!("Compositor initialization failed: {error}")
+ }
+ }
// Empty the queue if possible
- let event = if let Ok(event) = event_receiver.try_next() {
+ } else if let Ok(event) = event_receiver.try_next() {
event
} else {
event_receiver.next().await
@@ -714,11 +623,63 @@ async fn run_instance<P, C>(
make_visible,
on_open,
} => {
+ if compositor.is_none() {
+ let (compositor_sender, new_compositor_receiver) =
+ oneshot::channel();
+
+ compositor_receiver = Some(new_compositor_receiver);
+
+ let create_compositor = {
+ let default_fonts = default_fonts.clone();
+
+ async move {
+ let mut compositor =
+ C::new(graphics_settings, window.clone()).await;
+
+ if let Ok(compositor) = &mut compositor {
+ for font in default_fonts {
+ compositor.load_font(font.clone());
+ }
+ }
+
+ compositor_sender
+ .send(compositor.map(|compositor| {
+ (
+ compositor,
+ Event::WindowCreated {
+ id,
+ window,
+ exit_on_close_request,
+ make_visible,
+ on_open,
+ },
+ )
+ }))
+ .ok()
+ .expect("Send compositor");
+ }
+ };
+
+ #[cfg(not(target_arch = "wasm32"))]
+ crate::futures::futures::executor::block_on(
+ create_compositor,
+ );
+
+ #[cfg(target_arch = "wasm32")]
+ {
+ wasm_bindgen_futures::spawn_local(create_compositor);
+ }
+
+ continue;
+ }
+
let window = window_manager.insert(
id,
- Arc::new(window),
+ window,
&program,
- &mut compositor,
+ compositor
+ .as_mut()
+ .expect("Compositor must be initialized"),
exit_on_close_request,
);
@@ -758,12 +719,23 @@ async fn run_instance<P, C>(
}
Event::EventLoopAwakened(event) => {
match event {
+ event::Event::NewEvents(event::StartCause::Init) => {
+ for (_id, window) in window_manager.iter_mut() {
+ window.raw.request_redraw();
+ }
+ }
event::Event::NewEvents(
- event::StartCause::Init
- | event::StartCause::ResumeTimeReached { .. },
+ event::StartCause::ResumeTimeReached { .. },
) => {
+ let now = Instant::now();
+
for (_id, window) in window_manager.iter_mut() {
- window.raw.request_redraw();
+ if let Some(redraw_at) = window.redraw_at {
+ if redraw_at <= now {
+ window.raw.request_redraw();
+ window.redraw_at = None;
+ }
+ }
}
}
event::Event::PlatformSpecific(
@@ -801,17 +773,49 @@ async fn run_instance<P, C>(
event: event::WindowEvent::RedrawRequested,
..
} => {
+ let Some(compositor) = &mut compositor else {
+ continue;
+ };
+
let Some((id, window)) =
window_manager.get_mut_alias(id)
else {
continue;
};
- // TODO: Avoid redrawing all the time by forcing widgets to
- // request redraws on state changes
- //
- // Then, we can use the `interface_state` here to decide if a redraw
- // is needed right away, or simply wait until a specific time.
+ let physical_size = window.state.physical_size();
+
+ if physical_size.width == 0 || physical_size.height == 0
+ {
+ continue;
+ }
+
+ if window.viewport_version
+ != window.state.viewport_version()
+ {
+ let logical_size = window.state.logical_size();
+
+ debug.layout_started();
+ let ui = user_interfaces
+ .remove(&id)
+ .expect("Remove user interface");
+
+ let _ = user_interfaces.insert(
+ id,
+ ui.relayout(logical_size, &mut window.renderer),
+ );
+ debug.layout_finished();
+
+ compositor.configure_surface(
+ &mut window.surface,
+ physical_size.width,
+ physical_size.height,
+ );
+
+ window.viewport_version =
+ window.state.viewport_version();
+ }
+
let redraw_event = core::Event::Window(
window::Event::RedrawRequested(Instant::now()),
);
@@ -857,81 +861,18 @@ async fn run_instance<P, C>(
status: core::event::Status::Ignored,
});
- let _ = control_sender.start_send(Control::ChangeFlow(
- match ui_state {
- user_interface::State::Updated {
- redraw_request: Some(redraw_request),
- } => match redraw_request {
- window::RedrawRequest::NextFrame => {
- window.raw.request_redraw();
-
- ControlFlow::Wait
- }
- window::RedrawRequest::At(at) => {
- ControlFlow::WaitUntil(at)
- }
- },
- _ => ControlFlow::Wait,
- },
- ));
-
- let physical_size = window.state.physical_size();
-
- if physical_size.width == 0 || physical_size.height == 0
- {
- continue;
- }
-
- if window.viewport_version
- != window.state.viewport_version()
+ if let user_interface::State::Updated {
+ redraw_request: Some(redraw_request),
+ } = ui_state
{
- let logical_size = window.state.logical_size();
-
- debug.layout_started();
- let ui = user_interfaces
- .remove(&id)
- .expect("Remove user interface");
-
- let _ = user_interfaces.insert(
- id,
- ui.relayout(logical_size, &mut window.renderer),
- );
- debug.layout_finished();
-
- debug.draw_started();
- let new_mouse_interaction = user_interfaces
- .get_mut(&id)
- .expect("Get user interface")
- .draw(
- &mut window.renderer,
- window.state.theme(),
- &renderer::Style {
- text_color: window.state.text_color(),
- },
- window.state.cursor(),
- );
- debug.draw_finished();
-
- if new_mouse_interaction != window.mouse_interaction
- {
- window.raw.set_cursor(
- conversion::mouse_interaction(
- new_mouse_interaction,
- ),
- );
-
- window.mouse_interaction =
- new_mouse_interaction;
+ match redraw_request {
+ window::RedrawRequest::NextFrame => {
+ window.raw.request_redraw();
+ }
+ window::RedrawRequest::At(at) => {
+ window.redraw_at = Some(at);
+ }
}
-
- compositor.configure_surface(
- &mut window.surface,
- physical_size.width,
- physical_size.height,
- );
-
- window.viewport_version =
- window.state.viewport_version();
}
debug.render_started();
@@ -995,6 +936,13 @@ async fn run_instance<P, C>(
if matches!(
window_event,
+ winit::event::WindowEvent::Resized(_)
+ ) {
+ window.raw.request_redraw();
+ }
+
+ if matches!(
+ window_event,
winit::event::WindowEvent::CloseRequested
) && window.exit_on_close_request
{
@@ -1031,7 +979,10 @@ async fn run_instance<P, C>(
}
}
event::Event::AboutToWait => {
- if events.is_empty() && messages.is_empty() {
+ if events.is_empty()
+ && messages.is_empty()
+ && window_manager.is_idle()
+ {
continue;
}
@@ -1065,13 +1016,27 @@ async fn run_instance<P, C>(
&mut messages,
);
+ #[cfg(feature = "unconditional-rendering")]
window.raw.request_redraw();
- if !uis_stale {
- uis_stale = matches!(
- ui_state,
- user_interface::State::Outdated
- );
+ match ui_state {
+ #[cfg(not(
+ feature = "unconditional-rendering"
+ ))]
+ user_interface::State::Updated {
+ redraw_request: Some(redraw_request),
+ } => match redraw_request {
+ window::RedrawRequest::NextFrame => {
+ window.raw.request_redraw();
+ }
+ window::RedrawRequest::At(at) => {
+ window.redraw_at = Some(at);
+ }
+ },
+ user_interface::State::Outdated => {
+ uis_stale = true;
+ }
+ user_interface::State::Updated { .. } => {}
}
for (event, status) in window_events
@@ -1139,6 +1104,17 @@ async fn run_instance<P, C>(
actions = 0;
}
}
+
+ if let Some(redraw_at) = window_manager.redraw_at() {
+ let _ =
+ control_sender.start_send(Control::ChangeFlow(
+ ControlFlow::WaitUntil(redraw_at),
+ ));
+ } else {
+ let _ = control_sender.start_send(
+ Control::ChangeFlow(ControlFlow::Wait),
+ );
+ }
}
_ => {}
}
@@ -1159,7 +1135,7 @@ fn build_user_interface<'a, P: Program>(
id: window::Id,
) -> UserInterface<'a, P::Message, P::Theme, P::Renderer>
where
- P::Theme: DefaultStyle,
+ P::Theme: theme::Base,
{
debug.view_started();
let view = program.view(id);
@@ -1178,7 +1154,7 @@ fn update<P: Program, E: Executor>(
debug: &mut Debug,
messages: &mut Vec<P::Message>,
) where
- P::Theme: DefaultStyle,
+ P::Theme: theme::Base,
{
for message in messages.drain(..) {
debug.log_message(&message);
@@ -1199,7 +1175,7 @@ fn update<P: Program, E: Executor>(
fn run_action<P, C>(
action: Action<P::Message>,
program: &P,
- compositor: &mut C,
+ compositor: &mut Option<C>,
events: &mut Vec<(window::Id, core::Event)>,
messages: &mut Vec<P::Message>,
clipboard: &mut Clipboard,
@@ -1215,7 +1191,7 @@ fn run_action<P, C>(
) where
P: Program,
C: Compositor<Renderer = P::Renderer> + 'static,
- P::Theme: DefaultStyle,
+ P::Theme: theme::Base,
{
use crate::runtime::clipboard;
use crate::runtime::system;
@@ -1267,6 +1243,10 @@ fn run_action<P, C>(
core::Event::Window(core::window::Event::Closed),
));
}
+
+ if window_manager.is_empty() {
+ *compositor = None;
+ }
}
window::Action::GetOldest(channel) => {
let id =
@@ -1285,6 +1265,13 @@ fn run_action<P, C>(
let _ = window.raw.drag_window();
}
}
+ window::Action::DragResize(id, direction) => {
+ if let Some(window) = window_manager.get_mut(id) {
+ let _ = window.raw.drag_resize_window(
+ conversion::resize_direction(direction),
+ );
+ }
+ }
window::Action::Resize(id, size) => {
if let Some(window) = window_manager.get_mut(id) {
let _ = window.raw.request_inner_size(
@@ -1295,6 +1282,41 @@ fn run_action<P, C>(
);
}
}
+ window::Action::SetMinSize(id, size) => {
+ if let Some(window) = window_manager.get_mut(id) {
+ window.raw.set_min_inner_size(size.map(|size| {
+ winit::dpi::LogicalSize {
+ width: size.width,
+ height: size.height,
+ }
+ }));
+ }
+ }
+ window::Action::SetMaxSize(id, size) => {
+ if let Some(window) = window_manager.get_mut(id) {
+ window.raw.set_max_inner_size(size.map(|size| {
+ winit::dpi::LogicalSize {
+ width: size.width,
+ height: size.height,
+ }
+ }));
+ }
+ }
+ window::Action::SetResizeIncrements(id, increments) => {
+ if let Some(window) = window_manager.get_mut(id) {
+ window.raw.set_resize_increments(increments.map(|size| {
+ winit::dpi::LogicalSize {
+ width: size.width,
+ height: size.height,
+ }
+ }));
+ }
+ }
+ window::Action::SetResizable(id, resizable) => {
+ if let Some(window) = window_manager.get_mut(id) {
+ window.raw.set_resizable(resizable);
+ }
+ }
window::Action::GetSize(id, channel) => {
if let Some(window) = window_manager.get_mut(id) {
let size = window
@@ -1329,7 +1351,7 @@ fn run_action<P, C>(
if let Some(window) = window_manager.get(id) {
let position = window
.raw
- .inner_position()
+ .outer_position()
.map(|position| {
let position = position
.to_logical::<f32>(window.raw.scale_factor());
@@ -1358,7 +1380,7 @@ fn run_action<P, C>(
);
}
}
- window::Action::ChangeMode(id, mode) => {
+ window::Action::SetMode(id, mode) => {
if let Some(window) = window_manager.get_mut(id) {
window.raw.set_visible(conversion::visible(mode));
window.raw.set_fullscreen(conversion::fullscreen(
@@ -1367,7 +1389,7 @@ fn run_action<P, C>(
));
}
}
- window::Action::ChangeIcon(id, icon) => {
+ window::Action::SetIcon(id, icon) => {
if let Some(window) = window_manager.get_mut(id) {
window.raw.set_window_icon(conversion::icon(icon));
}
@@ -1405,7 +1427,7 @@ fn run_action<P, C>(
window.raw.focus_window();
}
}
- window::Action::ChangeLevel(id, level) => {
+ window::Action::SetLevel(id, level) => {
if let Some(window) = window_manager.get_mut(id) {
window
.raw
@@ -1443,19 +1465,20 @@ fn run_action<P, C>(
}
window::Action::Screenshot(id, channel) => {
if let Some(window) = window_manager.get_mut(id) {
- let bytes = compositor.screenshot(
- &mut window.renderer,
- &mut window.surface,
- window.state.viewport(),
- window.state.background_color(),
- &debug.overlay(),
- );
+ if let Some(compositor) = compositor {
+ let bytes = compositor.screenshot(
+ &mut window.renderer,
+ window.state.viewport(),
+ window.state.background_color(),
+ &debug.overlay(),
+ );
- let _ = channel.send(window::Screenshot::new(
- bytes,
- window.state.physical_size(),
- window.state.viewport().scale_factor(),
- ));
+ let _ = channel.send(core::window::Screenshot::new(
+ bytes,
+ window.state.physical_size(),
+ window.state.viewport().scale_factor(),
+ ));
+ }
}
}
window::Action::EnableMousePassthrough(id) => {
@@ -1473,14 +1496,16 @@ fn run_action<P, C>(
system::Action::QueryInformation(_channel) => {
#[cfg(feature = "system")]
{
- let graphics_info = compositor.fetch_information();
+ if let Some(compositor) = compositor {
+ let graphics_info = compositor.fetch_information();
- let _ = std::thread::spawn(move || {
- let information =
- crate::system::information(graphics_info);
+ let _ = std::thread::spawn(move || {
+ let information =
+ crate::system::information(graphics_info);
- let _ = _channel.send(information);
- });
+ let _ = _channel.send(information);
+ });
+ }
}
}
},
@@ -1504,10 +1529,12 @@ fn run_action<P, C>(
}
}
Action::LoadFont { bytes, channel } => {
- // TODO: Error handling (?)
- compositor.load_font(bytes.clone());
+ if let Some(compositor) = compositor {
+ // TODO: Error handling (?)
+ compositor.load_font(bytes.clone());
- let _ = channel.send(Ok(()));
+ let _ = channel.send(Ok(()));
+ }
}
Action::Exit => {
control_sender
@@ -1526,7 +1553,7 @@ pub fn build_user_interfaces<'a, P: Program, C>(
) -> FxHashMap<window::Id, UserInterface<'a, P::Message, P::Theme, P::Renderer>>
where
C: Compositor<Renderer = P::Renderer>,
- P::Theme: DefaultStyle,
+ P::Theme: theme::Base,
{
cached_user_interfaces
.drain()