| 1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
| 2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 |
| 3 | |
| 4 | use super::{RepaintBufferType, SoftwareRenderer}; |
| 5 | use crate::api::Window; |
| 6 | use crate::platform::Renderer; |
| 7 | use crate::window::WindowAdapter; |
| 8 | use alloc::rc::{Rc, Weak}; |
| 9 | use core::cell::Cell; |
| 10 | |
| 11 | /// This is a minimal adapter for a Window that doesn't have any other feature than rendering |
| 12 | /// using the software renderer. |
| 13 | pub struct MinimalSoftwareWindow { |
| 14 | window: Window, |
| 15 | renderer: SoftwareRenderer, |
| 16 | needs_redraw: Cell<bool>, |
| 17 | size: Cell<crate::api::PhysicalSize>, |
| 18 | } |
| 19 | |
| 20 | impl MinimalSoftwareWindow { |
| 21 | /// Instantiate a new MinimalWindowAdaptor |
| 22 | /// |
| 23 | /// The `repaint_buffer_type` parameter specify what kind of buffer are passed to the [`SoftwareRenderer`] |
| 24 | pub fn new(repaint_buffer_type: RepaintBufferType) -> Rc<Self> { |
| 25 | Rc::new_cyclic(|w: &Weak<Self>| Self { |
| 26 | window: Window::new(w.clone()), |
| 27 | renderer: SoftwareRenderer::new_with_repaint_buffer_type(repaint_buffer_type), |
| 28 | needs_redraw: Default::default(), |
| 29 | size: Default::default(), |
| 30 | }) |
| 31 | } |
| 32 | /// If the window needs to be redrawn, the callback will be called with the |
| 33 | /// [renderer](SoftwareRenderer) that should be used to do the drawing. |
| 34 | /// |
| 35 | /// [`SoftwareRenderer::render()`] or [`SoftwareRenderer::render_by_line()`] should be called |
| 36 | /// in that callback. |
| 37 | /// |
| 38 | /// Return true if something was redrawn. |
| 39 | pub fn draw_if_needed(&self, render_callback: impl FnOnce(&SoftwareRenderer)) -> bool { |
| 40 | if self.needs_redraw.replace(false) || self.renderer.rendering_metrics_collector.is_some() { |
| 41 | render_callback(&self.renderer); |
| 42 | true |
| 43 | } else { |
| 44 | false |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | #[cfg (feature = "experimental" )] |
| 49 | #[rustversion::since (1.85)] |
| 50 | /// If the window needs to be redrawn, the callback will be called with the |
| 51 | /// [renderer](SoftwareRenderer) that should be used to do the drawing. |
| 52 | /// |
| 53 | /// [`SoftwareRenderer::render()`] or [`SoftwareRenderer::render_by_line()`] should be called |
| 54 | /// in that callback. |
| 55 | /// |
| 56 | /// Return true if something was redrawn. |
| 57 | pub async fn draw_async_if_needed( |
| 58 | &self, |
| 59 | render_callback: impl AsyncFnOnce(&SoftwareRenderer), |
| 60 | ) -> bool { |
| 61 | if self.needs_redraw.replace(false) || self.renderer.rendering_metrics_collector.is_some() { |
| 62 | render_callback(&self.renderer).await; |
| 63 | true |
| 64 | } else { |
| 65 | false |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | #[doc (hidden)] |
| 70 | /// Forward to the window through Deref |
| 71 | /// (Before 1.1, WindowAdapter didn't have set_size, so the one from Deref was used. |
| 72 | /// But in Slint 1.1, if one had imported the WindowAdapter trait, the other one would be found) |
| 73 | pub fn set_size(&self, size: impl Into<crate::api::WindowSize>) { |
| 74 | self.window.set_size(size); |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | impl WindowAdapter for MinimalSoftwareWindow { |
| 79 | fn window(&self) -> &Window { |
| 80 | &self.window |
| 81 | } |
| 82 | |
| 83 | fn renderer(&self) -> &dyn Renderer { |
| 84 | &self.renderer |
| 85 | } |
| 86 | |
| 87 | fn size(&self) -> crate::api::PhysicalSize { |
| 88 | self.size.get() |
| 89 | } |
| 90 | fn set_size(&self, size: crate::api::WindowSize) { |
| 91 | let sf: f32 = self.window.scale_factor(); |
| 92 | self.size.set(val:size.to_physical(scale_factor:sf)); |
| 93 | self.window |
| 94 | .dispatch_event(crate::platform::WindowEvent::Resized { size: size.to_logical(scale_factor:sf) }) |
| 95 | } |
| 96 | |
| 97 | fn request_redraw(&self) { |
| 98 | self.needs_redraw.set(val:true); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | impl core::ops::Deref for MinimalSoftwareWindow { |
| 103 | type Target = Window; |
| 104 | fn deref(&self) -> &Self::Target { |
| 105 | &self.window |
| 106 | } |
| 107 | } |
| 108 | |