mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-01 20:31:27 +00:00
Invert slint:🪟:WindowInner and PlatformWindow ownership
Previously: Window is an Rc<WindowInner>, which has an Rc<dyn PLatformWindow> - and weak references the other way around. Now: Rc<dyn PlatformWindow> is the root of window ownership. The impl PlatformWindow has a slint::api::Window, which just holds a WindowInner. This change is incomplete on a few levels, mainly that neither of the code generators nor the interpreter is ported.
This commit is contained in:
parent
f88b688fbf
commit
af86f36157
32 changed files with 494 additions and 533 deletions
|
|
@ -135,7 +135,7 @@ fn gen_corelib(
|
|||
config.export.include = [
|
||||
"ComponentVTable",
|
||||
"Slice",
|
||||
"WindowRcOpaque",
|
||||
"PlatformWindowRcOpaque",
|
||||
"PropertyAnimation",
|
||||
"EasingCurve",
|
||||
"TextHorizontalAlignment",
|
||||
|
|
|
|||
|
|
@ -86,7 +86,9 @@ inline void assert_main_thread()
|
|||
class WindowRc
|
||||
{
|
||||
public:
|
||||
explicit WindowRc(cbindgen_private::WindowRcOpaque adopted_inner) : inner(adopted_inner) { }
|
||||
explicit WindowRc(cbindgen_private::PlatformWindowRcOpaque adopted_inner) : inner(adopted_inner)
|
||||
{
|
||||
}
|
||||
WindowRc() { cbindgen_private::slint_windowrc_init(&inner); }
|
||||
~WindowRc() { cbindgen_private::slint_windowrc_drop(&inner); }
|
||||
WindowRc(const WindowRc &other)
|
||||
|
|
@ -223,7 +225,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
cbindgen_private::WindowRcOpaque inner;
|
||||
cbindgen_private::PlatformWindowRcOpaque inner;
|
||||
};
|
||||
|
||||
constexpr inline ItemTreeNode make_item_node(uint32_t child_count, uint32_t child_index,
|
||||
|
|
|
|||
|
|
@ -564,7 +564,7 @@ public:
|
|||
/// such as the position on the screen.
|
||||
const slint::Window &window()
|
||||
{
|
||||
const cbindgen_private::WindowRcOpaque *win_ptr = nullptr;
|
||||
const cbindgen_private::PlatformWindowRcOpaque *win_ptr = nullptr;
|
||||
cbindgen_private::slint_interpreter_component_instance_window(inner(), &win_ptr);
|
||||
return *reinterpret_cast<const slint::Window *>(win_ptr);
|
||||
}
|
||||
|
|
@ -582,7 +582,7 @@ public:
|
|||
/// it may return nullptr if the Qt backend is not used at runtime.
|
||||
QWidget *qwidget() const
|
||||
{
|
||||
const cbindgen_private::WindowRcOpaque *win_ptr = nullptr;
|
||||
const cbindgen_private::PlatformWindowRcOpaque *win_ptr = nullptr;
|
||||
cbindgen_private::slint_interpreter_component_instance_window(inner(), &win_ptr);
|
||||
auto wid = reinterpret_cast<QWidget *>(cbindgen_private::slint_qt_get_widget(
|
||||
reinterpret_cast<const cbindgen_private::WindowRc *>(win_ptr)));
|
||||
|
|
@ -1010,7 +1010,7 @@ inline void send_keyboard_string_sequence(const slint::interpreter::ComponentIns
|
|||
const slint::SharedString &str,
|
||||
KeyboardModifiers modifiers = {})
|
||||
{
|
||||
const cbindgen_private::WindowRcOpaque *win_ptr = nullptr;
|
||||
const cbindgen_private::PlatformWindowRcOpaque *win_ptr = nullptr;
|
||||
cbindgen_private::slint_interpreter_component_instance_window(
|
||||
reinterpret_cast<const cbindgen_private::ErasedComponentBox *>(component), &win_ptr);
|
||||
cbindgen_private::send_keyboard_string_sequence(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
use core::ffi::c_void;
|
||||
use i_slint_backend_selector::backend;
|
||||
use i_slint_core::api::Window;
|
||||
use i_slint_core::window::{ffi::WindowRcOpaque, WindowRc};
|
||||
use i_slint_core::window::{ffi::PlatformWindowRcOpaque, PlatformWindowRc};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cold]
|
||||
|
|
@ -18,9 +17,12 @@ pub fn use_modules() -> usize {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_init(out: *mut WindowRcOpaque) {
|
||||
assert_eq!(core::mem::size_of::<Window>(), core::mem::size_of::<WindowRcOpaque>());
|
||||
core::ptr::write(out as *mut Window, crate::backend().create_window());
|
||||
pub unsafe extern "C" fn slint_windowrc_init(out: *mut PlatformWindowRcOpaque) {
|
||||
assert_eq!(
|
||||
core::mem::size_of::<PlatformWindowRc>(),
|
||||
core::mem::size_of::<PlatformWindowRcOpaque>()
|
||||
);
|
||||
core::ptr::write(out as *mut PlatformWindowRc, crate::backend().create_window());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
@ -63,14 +65,17 @@ pub unsafe extern "C" fn slint_quit_event_loop() {
|
|||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_register_font_from_path(
|
||||
win: *const WindowRcOpaque,
|
||||
win: *const PlatformWindowRcOpaque,
|
||||
path: &i_slint_core::SharedString,
|
||||
error_str: *mut i_slint_core::SharedString,
|
||||
) {
|
||||
let window = &*(win as *const WindowRc);
|
||||
let platform_window = &*(win as *const PlatformWindowRc);
|
||||
core::ptr::write(
|
||||
error_str,
|
||||
match window.renderer().register_font_from_path(std::path::Path::new(path.as_str())) {
|
||||
match platform_window
|
||||
.renderer()
|
||||
.register_font_from_path(std::path::Path::new(path.as_str()))
|
||||
{
|
||||
Ok(()) => Default::default(),
|
||||
Err(err) => err.to_string().into(),
|
||||
},
|
||||
|
|
@ -79,14 +84,14 @@ pub unsafe extern "C" fn slint_register_font_from_path(
|
|||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_register_font_from_data(
|
||||
win: *const WindowRcOpaque,
|
||||
win: *const PlatformWindowRcOpaque,
|
||||
data: i_slint_core::slice::Slice<'static, u8>,
|
||||
error_str: *mut i_slint_core::SharedString,
|
||||
) {
|
||||
let window = &*(win as *const WindowRc);
|
||||
let platform_window = &*(win as *const PlatformWindowRc);
|
||||
core::ptr::write(
|
||||
error_str,
|
||||
match window.renderer().register_font_from_memory(data.as_slice()) {
|
||||
match platform_window.renderer().register_font_from_memory(data.as_slice()) {
|
||||
Ok(()) => Default::default(),
|
||||
Err(err) => err.to_string().into(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ pub mod re_exports {
|
|||
pub use i_slint_core::model::*;
|
||||
pub use i_slint_core::properties::{set_state_binding, Property, PropertyTracker, StateInfo};
|
||||
pub use i_slint_core::slice::Slice;
|
||||
pub use i_slint_core::window::{WindowHandleAccess, WindowInner, WindowRc};
|
||||
pub use i_slint_core::window::{PlatformWindowRc, WindowHandleAccess, WindowInner};
|
||||
pub use i_slint_core::Color;
|
||||
pub use i_slint_core::ComponentVTable_static;
|
||||
pub use i_slint_core::Coord;
|
||||
|
|
@ -435,9 +435,8 @@ pub mod internal {
|
|||
|
||||
/// Creates a new window to render components in.
|
||||
#[doc(hidden)]
|
||||
pub fn create_window() -> re_exports::WindowRc {
|
||||
use i_slint_core::window::WindowHandleAccess;
|
||||
i_slint_backend_selector::backend().create_window().window_handle().clone()
|
||||
pub fn create_window() -> re_exports::PlatformWindowRc {
|
||||
i_slint_backend_selector::backend().create_window()
|
||||
}
|
||||
|
||||
/// Enters the main event loop. This is necessary in order to receive
|
||||
|
|
@ -478,7 +477,7 @@ pub mod testing {
|
|||
) {
|
||||
let rc = component.clone_strong().into();
|
||||
let dyn_rc = vtable::VRc::into_dyn(rc.clone());
|
||||
i_slint_core::tests::slint_send_mouse_click(&dyn_rc, x, y, &rc.window_handle().clone());
|
||||
i_slint_core::tests::slint_send_mouse_click(&dyn_rc, x, y, rc.window_handle());
|
||||
}
|
||||
|
||||
/// Simulate a change in keyboard modifiers being pressed
|
||||
|
|
@ -506,7 +505,7 @@ pub mod testing {
|
|||
i_slint_core::tests::send_keyboard_string_sequence(
|
||||
&super::SharedString::from(sequence),
|
||||
KEYBOARD_MODIFIERS.with(|x| x.get()),
|
||||
&component.window_handle().clone(),
|
||||
component.window_handle(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,21 +113,21 @@ mod the_backend {
|
|||
use alloc::rc::{Rc, Weak};
|
||||
use alloc::string::String;
|
||||
use core::cell::RefCell;
|
||||
use i_slint_core::window::WindowInner;
|
||||
use i_slint_core::window::{PlatformWindow, WindowRc};
|
||||
use i_slint_core::api::Window;
|
||||
use i_slint_core::window::{PlatformWindow, PlatformWindowRc, WindowHandleAccess};
|
||||
|
||||
thread_local! { static WINDOWS: RefCell<Option<Rc<McuWindow>>> = RefCell::new(None) }
|
||||
thread_local! { static EVENT_QUEUE: RefCell<VecDeque<McuEvent>> = Default::default() }
|
||||
|
||||
pub struct McuWindow {
|
||||
window_inner_weak: Weak<WindowInner>,
|
||||
window: Window,
|
||||
self_weak: Weak<Self>,
|
||||
renderer: crate::renderer::SoftwareRenderer,
|
||||
}
|
||||
|
||||
impl PlatformWindow for McuWindow {
|
||||
fn show(&self) {
|
||||
let w = self.window_inner_weak.upgrade().unwrap();
|
||||
let w = self.window.window_handle();
|
||||
w.set_scale_factor(
|
||||
option_env!("SLINT_SCALE_FACTOR").and_then(|x| x.parse().ok()).unwrap_or(1.),
|
||||
);
|
||||
|
|
@ -149,8 +149,8 @@ mod the_backend {
|
|||
self
|
||||
}
|
||||
|
||||
fn window(&self) -> WindowRc {
|
||||
self.window_inner_weak.upgrade().unwrap()
|
||||
fn window(&self) -> &Window {
|
||||
&self.window
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ mod the_backend {
|
|||
}
|
||||
|
||||
fn draw(&self, window: Rc<McuWindow>) {
|
||||
let runtime_window = window.window_inner_weak.upgrade().unwrap();
|
||||
let runtime_window = window.window.window_handle();
|
||||
runtime_window.update_window_properties();
|
||||
|
||||
DEVICES.with(|devices| {
|
||||
|
|
@ -202,11 +202,7 @@ mod the_backend {
|
|||
runtime_window.set_window_item_geometry(size.width as _, size.height as _);
|
||||
|
||||
if let Some(buffer) = devices.get_buffer() {
|
||||
window.renderer.render(
|
||||
&runtime_window.into(),
|
||||
buffer,
|
||||
screen_size.width_length(),
|
||||
);
|
||||
window.renderer.render(&window.window, buffer, screen_size.width_length());
|
||||
|
||||
devices.flush_frame();
|
||||
frame_profiler.stop_profiling(&mut **devices, "=> frame total");
|
||||
|
|
@ -263,24 +259,21 @@ mod the_backend {
|
|||
devices: &mut **devices,
|
||||
};
|
||||
|
||||
window.renderer.render_by_line(&runtime_window.into(), buffer_provider);
|
||||
window.renderer.render_by_line(&window.window, buffer_provider);
|
||||
frame_profiler.stop_profiling(&mut **devices, "=> frame total");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl i_slint_core::backend::Backend for MCUBackend {
|
||||
fn create_window(&self) -> i_slint_core::api::Window {
|
||||
i_slint_core::window::WindowInner::new(|window| {
|
||||
fn create_window(&self) -> PlatformWindowRc {
|
||||
Rc::new_cyclic(|self_weak| McuWindow {
|
||||
window_inner_weak: window.clone(),
|
||||
window: Window::new(self_weak.clone() as _),
|
||||
self_weak: self_weak.clone(),
|
||||
renderer: crate::renderer::SoftwareRenderer::new(
|
||||
crate::renderer::DirtyTracking::DoubleBuffer,
|
||||
),
|
||||
})
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
fn run_event_loop(&self, behavior: i_slint_core::backend::EventLoopQuitBehavior) {
|
||||
|
|
@ -302,7 +295,7 @@ mod the_backend {
|
|||
let e = devices.borrow_mut().as_mut().unwrap().read_touch_event();
|
||||
if let Some(mut event) = e {
|
||||
if let Some(window) = WINDOWS.with(|x| x.borrow().clone()) {
|
||||
let w = window.window_inner_weak.upgrade().unwrap();
|
||||
let w = window.window.window_handle();
|
||||
// scale the event by the scale factor:
|
||||
if let Some(p) = event.position() {
|
||||
event.translate((p.cast() / w.scale_factor()).cast() - p);
|
||||
|
|
|
|||
|
|
@ -65,16 +65,13 @@ thread_local! { static WINDOW: RefCell<Option<Rc<PicoWindow>>> = RefCell::new(No
|
|||
|
||||
struct PicoBackend;
|
||||
impl i_slint_core::backend::Backend for PicoBackend {
|
||||
fn create_window(&self) -> i_slint_core::api::Window {
|
||||
i_slint_core::window::WindowInner::new(|window| {
|
||||
fn create_window(&self) -> i_slint_core::window::PlatformWindowRc {
|
||||
Rc::new_cyclic(|self_weak| PicoWindow {
|
||||
window_inner_weak: window.clone(),
|
||||
window: i_slint_core::api::Window::new(self_weak.clone() as _),
|
||||
self_weak: self_weak.clone(),
|
||||
renderer: renderer::SoftwareRenderer::new(renderer::DirtyTracking::SingleBuffer),
|
||||
needs_redraw: Default::default(),
|
||||
})
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
fn run_event_loop(&self, _behavior: i_slint_core::backend::EventLoopQuitBehavior) {
|
||||
|
|
@ -200,11 +197,8 @@ fn run_event_loop() -> ! {
|
|||
i_slint_core::timers::update_timers();
|
||||
|
||||
if let Some(window) = WINDOW.with(|x| x.borrow().clone()) {
|
||||
let runtime_window =
|
||||
i_slint_core::api::Window::from(window.window_inner_weak.upgrade().unwrap());
|
||||
|
||||
if window.needs_redraw.replace(false) {
|
||||
window.renderer.render_by_line(&runtime_window, &mut buffer_provider);
|
||||
window.renderer.render_by_line(&window.window, &mut buffer_provider);
|
||||
buffer_provider.flush_frame();
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +211,7 @@ fn run_event_loop() -> ! {
|
|||
.map(|point| {
|
||||
let size = DISPLAY_SIZE.to_f32();
|
||||
let position = euclid::point2(point.x * size.width, point.y * size.height)
|
||||
/ runtime_window.scale_factor();
|
||||
/ window.window.scale_factor().get();
|
||||
match last_touch.replace(position) {
|
||||
Some(_) => PointerEvent::Moved { position },
|
||||
None => PointerEvent::Pressed { position, button },
|
||||
|
|
@ -227,7 +221,7 @@ fn run_event_loop() -> ! {
|
|||
last_touch.take().map(|position| PointerEvent::Released { position, button })
|
||||
})
|
||||
{
|
||||
runtime_window.dispatch_pointer_event(event);
|
||||
window.window.dispatch_pointer_event(event);
|
||||
// Don't go to sleep after a touch event that forces a redraw
|
||||
continue;
|
||||
}
|
||||
|
|
@ -287,7 +281,7 @@ impl<TO: WriteTarget<TransmittedWord = u8> + FullDuplex<u8>, CH: SingleChannel>
|
|||
}
|
||||
|
||||
struct PicoWindow {
|
||||
window_inner_weak: Weak<i_slint_core::window::WindowInner>,
|
||||
window: i_slint_core::api::Window,
|
||||
self_weak: Weak<Self>,
|
||||
renderer: crate::renderer::SoftwareRenderer,
|
||||
needs_redraw: Cell<bool>,
|
||||
|
|
@ -295,9 +289,7 @@ struct PicoWindow {
|
|||
|
||||
impl i_slint_core::window::PlatformWindow for PicoWindow {
|
||||
fn show(&self) {
|
||||
let runtime_window =
|
||||
i_slint_core::api::Window::from(self.window_inner_weak.upgrade().unwrap());
|
||||
runtime_window.set_size(DISPLAY_SIZE.cast());
|
||||
self.window.set_size(DISPLAY_SIZE.cast());
|
||||
WINDOW.with(|x| *x.borrow_mut() = Some(self.self_weak.upgrade().unwrap()))
|
||||
}
|
||||
fn hide(&self) {
|
||||
|
|
@ -315,8 +307,8 @@ impl i_slint_core::window::PlatformWindow for PicoWindow {
|
|||
self
|
||||
}
|
||||
|
||||
fn window(&self) -> i_slint_core::window::WindowRc {
|
||||
self.window_inner_weak.upgrade().unwrap()
|
||||
fn window(&self) -> &i_slint_core::api::Window {
|
||||
&self.window
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use i_slint_core::api::{euclid, PhysicalPx};
|
|||
use i_slint_core::component::ComponentRc;
|
||||
use i_slint_core::input::KeyboardModifiers;
|
||||
use i_slint_core::layout::Orientation;
|
||||
use i_slint_core::window::{PlatformWindow, WindowRc};
|
||||
use i_slint_core::window::{PlatformWindow, PlatformWindowRc, WindowHandleAccess};
|
||||
use i_slint_core::Coord;
|
||||
use rgb::FromSlice;
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ use glcontext::*;
|
|||
use i_slint_core::swrenderer::SoftwareRenderer;
|
||||
|
||||
pub struct SimulatorWindow {
|
||||
window_inner_weak: Weak<i_slint_core::window::WindowInner>,
|
||||
window: i_slint_core::api::Window,
|
||||
self_weak: Weak<Self>,
|
||||
keyboard_modifiers: std::cell::Cell<KeyboardModifiers>,
|
||||
currently_pressed_key_code: std::cell::Cell<Option<winit::event::VirtualKeyCode>>,
|
||||
|
|
@ -40,7 +40,7 @@ pub struct SimulatorWindow {
|
|||
}
|
||||
|
||||
impl SimulatorWindow {
|
||||
pub(crate) fn new(window_weak: &Weak<i_slint_core::window::WindowInner>) -> Rc<Self> {
|
||||
pub(crate) fn new() -> Rc<Self> {
|
||||
let window_builder = winit::window::WindowBuilder::new().with_visible(false);
|
||||
|
||||
let opengl_context = OpenGLContext::new_context(window_builder);
|
||||
|
|
@ -56,7 +56,7 @@ impl SimulatorWindow {
|
|||
let canvas = Rc::new(RefCell::new(canvas));
|
||||
|
||||
let window_rc = Rc::new_cyclic(|self_weak| Self {
|
||||
window_inner_weak: window_weak.clone(),
|
||||
window: i_slint_core::api::Window::new(self_weak.clone() as _),
|
||||
self_weak: self_weak.clone(),
|
||||
keyboard_modifiers: Default::default(),
|
||||
currently_pressed_key_code: Default::default(),
|
||||
|
|
@ -68,7 +68,7 @@ impl SimulatorWindow {
|
|||
renderer: Default::default(),
|
||||
});
|
||||
|
||||
let runtime_window = window_weak.upgrade().unwrap();
|
||||
let runtime_window = window_rc.window.window_handle();
|
||||
runtime_window.set_scale_factor(window_rc.opengl_context.window().scale_factor() as _);
|
||||
|
||||
window_rc
|
||||
|
|
@ -89,7 +89,7 @@ impl PlatformWindow for SimulatorWindow {
|
|||
|
||||
self.visible.set(true);
|
||||
|
||||
let runtime_window = self.window();
|
||||
let runtime_window = self.window.window_handle();
|
||||
let component_rc = runtime_window.component();
|
||||
let component = ComponentRc::borrow_pin(&component_rc);
|
||||
|
||||
|
|
@ -178,8 +178,8 @@ impl PlatformWindow for SimulatorWindow {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
fn window(&self) -> WindowRc {
|
||||
self.window_inner_weak.upgrade().unwrap()
|
||||
fn window(&self) -> &i_slint_core::api::Window {
|
||||
&self.window
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -193,8 +193,6 @@ impl WinitWindow for SimulatorWindow {
|
|||
}
|
||||
|
||||
fn draw(&self) {
|
||||
let runtime_window = self.window_inner_weak.upgrade().unwrap();
|
||||
|
||||
let size = self.opengl_context.window().inner_size();
|
||||
|
||||
self.opengl_context.with_current_context(|opengl_context| {
|
||||
|
|
@ -237,8 +235,7 @@ impl WinitWindow for SimulatorWindow {
|
|||
});
|
||||
}
|
||||
}
|
||||
self.renderer
|
||||
.render_by_line(&runtime_window.into(), BufferProvider { devices: display });
|
||||
self.renderer.render_by_line(&self.window, BufferProvider { devices: display });
|
||||
|
||||
let output_image = display
|
||||
.to_rgb_output_image(&embedded_graphics_simulator::OutputSettings::default());
|
||||
|
|
@ -301,8 +298,8 @@ impl WinitWindow for SimulatorWindow {
|
|||
pub struct SimulatorBackend;
|
||||
|
||||
impl i_slint_core::backend::Backend for SimulatorBackend {
|
||||
fn create_window(&self) -> i_slint_core::api::Window {
|
||||
i_slint_core::window::WindowInner::new(|window| SimulatorWindow::new(window)).into()
|
||||
fn create_window(&self) -> PlatformWindowRc {
|
||||
SimulatorWindow::new()
|
||||
}
|
||||
|
||||
fn run_event_loop(&self, behavior: i_slint_core::backend::EventLoopQuitBehavior) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ pub fn use_modules() -> usize {
|
|||
mod ffi {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_qt_get_widget(
|
||||
_: &i_slint_core::window::WindowRc,
|
||||
_: &i_slint_core::window::PlatformWindowRc,
|
||||
) -> *mut std::ffi::c_void {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
|
|
@ -122,6 +122,7 @@ pub type NativeGlobals = ();
|
|||
|
||||
pub const HAS_NATIVE_STYLE: bool = cfg!(not(no_qt));
|
||||
|
||||
use i_slint_core::window::PlatformWindowRc;
|
||||
#[cfg(not(no_qt))]
|
||||
pub use qt_widgets::{native_style_metrics_deinit, native_style_metrics_init};
|
||||
#[cfg(no_qt)]
|
||||
|
|
@ -135,12 +136,12 @@ pub fn native_style_metrics_deinit(_: core::pin::Pin<&mut native_widgets::Native
|
|||
|
||||
pub struct Backend;
|
||||
impl i_slint_core::backend::Backend for Backend {
|
||||
fn create_window(&self) -> i_slint_core::api::Window {
|
||||
fn create_window(&self) -> PlatformWindowRc {
|
||||
#[cfg(no_qt)]
|
||||
panic!("The Qt backend needs Qt");
|
||||
#[cfg(not(no_qt))]
|
||||
{
|
||||
i_slint_core::window::WindowInner::new(|window| qt_window::QtWindow::new(window)).into()
|
||||
qt_window::QtWindow::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use crate::accessible_generated::*;
|
|||
use i_slint_core::accessibility::AccessibleStringProperty;
|
||||
use i_slint_core::item_tree::{ItemRc, ItemWeak};
|
||||
use i_slint_core::properties::{PropertyDirtyHandler, PropertyTracker};
|
||||
use i_slint_core::window::WindowHandleAccess;
|
||||
use i_slint_core::SharedVector;
|
||||
|
||||
use cpp::*;
|
||||
|
|
@ -327,9 +328,9 @@ cpp! {{
|
|||
};
|
||||
|
||||
void *root_item_for_window(void *rustWindow) {
|
||||
return rust!(root_item_for_window_ [rustWindow: &i_slint_core::window::WindowInner as "void*"]
|
||||
return rust!(root_item_for_window_ [rustWindow: &std::rc::Weak<crate::qt_window::QtWindow> as "void*"]
|
||||
-> *mut c_void as "void*" {
|
||||
let root_item = Box::new(ItemRc::new(rustWindow.component(), 0).downgrade());
|
||||
let root_item = Box::new(ItemRc::new(rustWindow.upgrade().unwrap().window.window_handle().component(), 0).downgrade());
|
||||
Box::into_raw(root_item) as _
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ use i_slint_core::items::{Item, ItemConsts, ItemRc, ItemVTable, RenderingResult,
|
|||
use i_slint_core::layout::{LayoutInfo, Orientation};
|
||||
#[cfg(feature = "rtti")]
|
||||
use i_slint_core::rtti::*;
|
||||
use i_slint_core::window::WindowInner;
|
||||
use i_slint_core::window::{WindowHandleAccess, WindowInner};
|
||||
use i_slint_core::{
|
||||
declare_item_vtable, Callback, ItemVTable_static, Property, SharedString, SharedVector,
|
||||
};
|
||||
|
|
@ -59,7 +59,7 @@ macro_rules! fn_render {
|
|||
let $dpr: f32 = backend.scale_factor();
|
||||
|
||||
let window = backend.window();
|
||||
let active: bool = window.active();
|
||||
let active: bool = window.window_handle().active();
|
||||
// This should include self.enabled() as well, but not every native widget
|
||||
// has that property right now.
|
||||
let $initial_state = cpp!(unsafe [ active as "bool" ] -> i32 as "int" {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use i_slint_core::items::{
|
|||
PointerEventButton, RenderingResult, TextOverflow, TextWrap,
|
||||
};
|
||||
use i_slint_core::layout::Orientation;
|
||||
use i_slint_core::window::{PlatformWindow, WindowRc};
|
||||
use i_slint_core::window::{PlatformWindow, PlatformWindowRc, WindowHandleAccess};
|
||||
use i_slint_core::{ImageInner, PathData, Property, SharedString};
|
||||
use items::{ImageFit, TextHorizontalAlignment, TextVerticalAlignment};
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ cpp! {{
|
|||
void customEvent(QEvent *event) override {
|
||||
if (event->type() == QEvent::User) {
|
||||
rust!(Slint_updateWindowProps [rust_window: &QtWindow as "void*"] {
|
||||
if let Some(window) = rust_window.self_weak.upgrade() { window.update_window_properties() }
|
||||
rust_window.window.window_handle().update_window_properties()
|
||||
});
|
||||
} else {
|
||||
QWidget::customEvent(event);
|
||||
|
|
@ -200,7 +200,7 @@ cpp! {{
|
|||
if (event->type() == QEvent::ActivationChange) {
|
||||
bool active = isActiveWindow();
|
||||
rust!(Slint_updateWindowActivation [rust_window: &QtWindow as "void*", active: bool as "bool"] {
|
||||
if let Some(window) = rust_window.self_weak.upgrade() { window.set_active(active) }
|
||||
rust_window.window.window_handle().set_active(active)
|
||||
});
|
||||
}
|
||||
QWidget::changeEvent(event);
|
||||
|
|
@ -208,10 +208,7 @@ cpp! {{
|
|||
|
||||
void closeEvent(QCloseEvent *event) override {
|
||||
bool accepted = rust!(Slint_requestClose [rust_window: &QtWindow as "void*"] -> bool as "bool" {
|
||||
if let Some(window) = rust_window.self_weak.upgrade() {
|
||||
return window.request_close();
|
||||
}
|
||||
true
|
||||
return rust_window.window.window_handle().request_close();
|
||||
});
|
||||
if (accepted) {
|
||||
event->accept();
|
||||
|
|
@ -222,7 +219,7 @@ cpp! {{
|
|||
|
||||
QSize sizeHint() const override {
|
||||
auto preferred_size = rust!(Slint_sizeHint [rust_window: &QtWindow as "void*"] -> qttypes::QSize as "QSize" {
|
||||
let component_rc = rust_window.self_weak.upgrade().unwrap().component();
|
||||
let component_rc = rust_window.window.window_handle().component();
|
||||
let component = ComponentRc::borrow_pin(&component_rc);
|
||||
let layout_info_h = component.as_ref().layout_info(Orientation::Horizontal);
|
||||
let layout_info_v = component.as_ref().layout_info(Orientation::Vertical);
|
||||
|
|
@ -451,7 +448,7 @@ fn adjust_rect_and_border_for_inner_drawing(rect: &mut qttypes::QRectF, border_w
|
|||
struct QtItemRenderer<'a> {
|
||||
painter: QPainterPtr,
|
||||
cache: &'a ItemCache<qttypes::QPixmap>,
|
||||
window: WindowRc,
|
||||
window: &'a i_slint_core::api::Window,
|
||||
metrics: RenderingMetrics,
|
||||
}
|
||||
|
||||
|
|
@ -516,7 +513,7 @@ impl ItemRenderer for QtItemRenderer<'_> {
|
|||
let rect: qttypes::QRectF = get_geometry!(items::Text, text);
|
||||
let fill_brush: qttypes::QBrush = into_qbrush(text.color(), rect.width, rect.height);
|
||||
let mut string: qttypes::QString = text.text().as_str().into();
|
||||
let font: QFont = get_font(text.font_request(&self.window));
|
||||
let font: QFont = get_font(text.font_request(self.window.window_handle()));
|
||||
let flags = match text.horizontal_alignment() {
|
||||
TextHorizontalAlignment::Left => key_generated::Qt_AlignmentFlag_AlignLeft,
|
||||
TextHorizontalAlignment::Center => key_generated::Qt_AlignmentFlag_AlignHCenter,
|
||||
|
|
@ -607,7 +604,7 @@ impl ItemRenderer for QtItemRenderer<'_> {
|
|||
}}
|
||||
}
|
||||
|
||||
let font: QFont = get_font(text_input.font_request(&self.window));
|
||||
let font: QFont = get_font(text_input.font_request(self.window.window_handle()));
|
||||
let flags = match text_input.horizontal_alignment() {
|
||||
TextHorizontalAlignment::Left => key_generated::Qt_AlignmentFlag_AlignLeft,
|
||||
TextHorizontalAlignment::Center => key_generated::Qt_AlignmentFlag_AlignHCenter,
|
||||
|
|
@ -925,8 +922,8 @@ impl ItemRenderer for QtItemRenderer<'_> {
|
|||
}}
|
||||
}
|
||||
|
||||
fn window(&self) -> WindowRc {
|
||||
self.window.clone()
|
||||
fn window(&self) -> &i_slint_core::api::Window {
|
||||
&self.window
|
||||
}
|
||||
|
||||
fn as_any(&mut self) -> Option<&mut dyn std::any::Any> {
|
||||
|
|
@ -1202,7 +1199,8 @@ cpp_class!(unsafe struct QWidgetPtr as "std::unique_ptr<QWidget>");
|
|||
|
||||
pub struct QtWindow {
|
||||
widget_ptr: QWidgetPtr,
|
||||
pub(crate) self_weak: Weak<i_slint_core::window::WindowInner>,
|
||||
pub(crate) window: i_slint_core::api::Window,
|
||||
self_weak: Weak<Self>,
|
||||
|
||||
rendering_metrics_collector: RefCell<Option<Rc<RenderingMetricsCollector>>>,
|
||||
|
||||
|
|
@ -1212,8 +1210,9 @@ pub struct QtWindow {
|
|||
}
|
||||
|
||||
impl QtWindow {
|
||||
pub fn new(window_weak: &Weak<i_slint_core::window::WindowInner>) -> Rc<Self> {
|
||||
let window_ptr = window_weak.clone().into_raw();
|
||||
pub fn new() -> Rc<Self> {
|
||||
let rc = Rc::new_cyclic(|self_weak| {
|
||||
let window_ptr = self_weak.clone().into_raw();
|
||||
let widget_ptr = cpp! {unsafe [window_ptr as "void*"] -> QWidgetPtr as "std::unique_ptr<QWidget>" {
|
||||
ensure_initialized(true);
|
||||
auto widget = std::make_unique<SlintWidget>();
|
||||
|
|
@ -1223,20 +1222,22 @@ impl QtWindow {
|
|||
|
||||
return widget;
|
||||
}};
|
||||
let rc = Rc::new(QtWindow {
|
||||
|
||||
QtWindow {
|
||||
widget_ptr,
|
||||
self_weak: window_weak.clone(),
|
||||
window: i_slint_core::api::Window::new(self_weak.clone() as _),
|
||||
self_weak: self_weak.clone(),
|
||||
rendering_metrics_collector: Default::default(),
|
||||
cache: Default::default(),
|
||||
tree_structure_changed: RefCell::new(false),
|
||||
}
|
||||
});
|
||||
let self_weak = Rc::downgrade(&rc);
|
||||
let widget_ptr = rc.widget_ptr();
|
||||
let rust_window = Rc::as_ptr(&rc);
|
||||
cpp! {unsafe [widget_ptr as "SlintWidget*", rust_window as "void*"] {
|
||||
widget_ptr->rust_window = rust_window;
|
||||
}};
|
||||
ALL_WINDOWS.with(|aw| aw.borrow_mut().push(self_weak));
|
||||
ALL_WINDOWS.with(|aw| aw.borrow_mut().push(rc.self_weak.clone()));
|
||||
rc
|
||||
}
|
||||
|
||||
|
|
@ -1246,13 +1247,13 @@ impl QtWindow {
|
|||
}
|
||||
|
||||
fn paint_event(&self, painter: QPainterPtr) {
|
||||
let runtime_window = self.self_weak.upgrade().unwrap();
|
||||
runtime_window.clone().draw_contents(|components| {
|
||||
let runtime_window = self.window.window_handle();
|
||||
runtime_window.draw_contents(|components| {
|
||||
i_slint_core::animations::update_animations();
|
||||
let mut renderer = QtItemRenderer {
|
||||
painter,
|
||||
cache: &self.cache,
|
||||
window: runtime_window,
|
||||
window: &self.window,
|
||||
metrics: RenderingMetrics { layers_created: Some(0) },
|
||||
};
|
||||
|
||||
|
|
@ -1295,12 +1296,11 @@ impl QtWindow {
|
|||
}
|
||||
|
||||
fn resize_event(&self, size: qttypes::QSize) {
|
||||
i_slint_core::api::Window::from(self.self_weak.upgrade().unwrap())
|
||||
.set_size(euclid::size2(size.width, size.height));
|
||||
self.window.set_size(euclid::size2(size.width, size.height));
|
||||
}
|
||||
|
||||
fn mouse_event(&self, event: MouseEvent) {
|
||||
self.self_weak.upgrade().unwrap().process_mouse_input(event);
|
||||
self.window.window_handle().process_mouse_input(event);
|
||||
timer_event();
|
||||
}
|
||||
|
||||
|
|
@ -1321,13 +1321,13 @@ impl QtWindow {
|
|||
text,
|
||||
modifiers,
|
||||
};
|
||||
self.self_weak.upgrade().unwrap().process_key_input(&event);
|
||||
self.window.window_handle().process_key_input(&event);
|
||||
|
||||
timer_event();
|
||||
}
|
||||
|
||||
fn close_popup(&self) {
|
||||
self.self_weak.upgrade().unwrap().close_popup();
|
||||
self.window.window_handle().close_popup();
|
||||
}
|
||||
|
||||
fn free_graphics_resources(&self, component: ComponentRef) {
|
||||
|
|
@ -1339,7 +1339,7 @@ impl QtWindow {
|
|||
#[allow(unused)]
|
||||
impl PlatformWindow for QtWindow {
|
||||
fn show(&self) {
|
||||
let component_rc = self.self_weak.upgrade().unwrap().component();
|
||||
let component_rc = self.window.window_handle().component();
|
||||
let component = ComponentRc::borrow_pin(&component_rc);
|
||||
let root_item = component.as_ref().get_item_ref(0);
|
||||
if let Some(window_item) = ItemRef::downcast_pin(root_item) {
|
||||
|
|
@ -1478,12 +1478,8 @@ impl PlatformWindow for QtWindow {
|
|||
self.tree_structure_changed.replace(true);
|
||||
}
|
||||
|
||||
fn create_popup(&self, geometry: Rect) -> Option<i_slint_core::api::Window> {
|
||||
let window = i_slint_core::window::WindowInner::new(|window| QtWindow::new(window));
|
||||
let popup_window: &QtWindow =
|
||||
<dyn std::any::Any>::downcast_ref(window.as_ref().as_any()).unwrap();
|
||||
|
||||
let runtime_window = self.self_weak.upgrade().unwrap();
|
||||
fn create_popup(&self, geometry: Rect) -> Option<PlatformWindowRc> {
|
||||
let popup_window = QtWindow::new();
|
||||
|
||||
let size = qttypes::QSize { width: geometry.width() as _, height: geometry.height() as _ };
|
||||
|
||||
|
|
@ -1495,7 +1491,7 @@ impl PlatformWindow for QtWindow {
|
|||
popup_ptr->setGeometry(QRect(pos + widget_ptr->mapToGlobal(QPoint(0,0)), size));
|
||||
popup_ptr->show();
|
||||
}};
|
||||
Some(window.into())
|
||||
Some(popup_window as _)
|
||||
}
|
||||
|
||||
fn set_mouse_cursor(&self, cursor: MouseCursor) {
|
||||
|
|
@ -1583,8 +1579,8 @@ impl PlatformWindow for QtWindow {
|
|||
}};
|
||||
}
|
||||
|
||||
fn window(&self) -> WindowRc {
|
||||
self.self_weak.upgrade().unwrap()
|
||||
fn window(&self) -> &i_slint_core::api::Window {
|
||||
&self.window
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1609,8 +1605,7 @@ impl Renderer for QtWindow {
|
|||
}
|
||||
let rect: qttypes::QRectF = get_geometry!(items::TextInput, text_input);
|
||||
let pos = qttypes::QPointF { x: pos.x as _, y: pos.y as _ };
|
||||
let runtime_window = self.self_weak.upgrade().unwrap();
|
||||
let font: QFont = get_font(text_input.font_request(&runtime_window));
|
||||
let font: QFont = get_font(text_input.font_request(self.window.window_handle()));
|
||||
let string = qttypes::QString::from(text_input.text().as_str());
|
||||
let flags = match text_input.horizontal_alignment() {
|
||||
TextHorizontalAlignment::Left => key_generated::Qt_AlignmentFlag_AlignLeft,
|
||||
|
|
@ -1665,8 +1660,7 @@ impl Renderer for QtWindow {
|
|||
byte_offset: usize,
|
||||
) -> Rect {
|
||||
let rect: qttypes::QRectF = get_geometry!(items::TextInput, text_input);
|
||||
let runtime_window = self.self_weak.upgrade().unwrap();
|
||||
let font: QFont = get_font(text_input.font_request(&runtime_window));
|
||||
let font: QFont = get_font(text_input.font_request(self.window.window_handle()));
|
||||
let text = text_input.text();
|
||||
let mut string = qttypes::QString::from(text.as_str());
|
||||
let offset: u32 = utf8_byte_offset_to_utf16_units(text.as_str(), byte_offset) as _;
|
||||
|
|
@ -1943,8 +1937,10 @@ pub(crate) mod ffi {
|
|||
use super::QtWindow;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_qt_get_widget(window: &i_slint_core::window::WindowRc) -> *mut c_void {
|
||||
<dyn std::any::Any>::downcast_ref(window.as_any())
|
||||
pub extern "C" fn slint_qt_get_widget(
|
||||
platform_window: &i_slint_core::window::PlatformWindowRc,
|
||||
) -> *mut c_void {
|
||||
<dyn std::any::Any>::downcast_ref(platform_window.as_any())
|
||||
.map_or(std::ptr::null_mut(), |win: &QtWindow| {
|
||||
win.widget_ptr().cast::<c_void>().as_ptr()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,14 +6,12 @@
|
|||
|
||||
use i_slint_core::api::euclid;
|
||||
use i_slint_core::api::PhysicalPx;
|
||||
use i_slint_core::api::Window;
|
||||
use i_slint_core::graphics::{Point, Rect, Size};
|
||||
use i_slint_core::renderer::Renderer;
|
||||
use i_slint_core::window::WindowRc;
|
||||
use i_slint_core::window::{PlatformWindow, WindowInner};
|
||||
use i_slint_core::window::PlatformWindow;
|
||||
use i_slint_core::window::PlatformWindowRc;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::rc::Weak;
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -22,9 +20,10 @@ pub struct TestingBackend {
|
|||
}
|
||||
|
||||
impl i_slint_core::backend::Backend for TestingBackend {
|
||||
fn create_window(&self) -> Window {
|
||||
WindowInner::new(|window_weak| Rc::new(TestingWindow { self_weak: window_weak.clone() }))
|
||||
.into()
|
||||
fn create_window(&self) -> PlatformWindowRc {
|
||||
Rc::new_cyclic(|self_weak| TestingWindow {
|
||||
window: i_slint_core::api::Window::new(self_weak.clone() as _),
|
||||
})
|
||||
}
|
||||
|
||||
fn run_event_loop(&self, _behavior: i_slint_core::backend::EventLoopQuitBehavior) {
|
||||
|
|
@ -52,7 +51,7 @@ impl i_slint_core::backend::Backend for TestingBackend {
|
|||
}
|
||||
|
||||
pub struct TestingWindow {
|
||||
self_weak: Weak<i_slint_core::window::WindowInner>,
|
||||
window: i_slint_core::api::Window,
|
||||
}
|
||||
|
||||
impl PlatformWindow for TestingWindow {
|
||||
|
|
@ -104,8 +103,8 @@ impl PlatformWindow for TestingWindow {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
fn window(&self) -> WindowRc {
|
||||
self.self_weak.upgrade().unwrap()
|
||||
fn window(&self) -> &i_slint_core::api::Window {
|
||||
&self.window
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ pub trait WinitWindow: PlatformWindow {
|
|||
let max_width = constraints_horizontal.max.max(constraints_horizontal.min) as f32;
|
||||
let max_height = constraints_vertical.max.max(constraints_vertical.min) as f32;
|
||||
|
||||
let sf = self.window().scale_factor();
|
||||
let sf = self.window().scale_factor().get();
|
||||
|
||||
winit_window.set_resizable(true);
|
||||
winit_window.set_min_inner_size(if min_width > 0. || min_height > 0. {
|
||||
|
|
@ -123,7 +123,7 @@ pub trait WinitWindow: PlatformWindow {
|
|||
must_resize = true;
|
||||
|
||||
let winit_size =
|
||||
winit_window.inner_size().to_logical(self.window().scale_factor() as f64);
|
||||
winit_window.inner_size().to_logical(self.window().scale_factor().get() as f64);
|
||||
|
||||
if width <= 0. {
|
||||
width = winit_size.width;
|
||||
|
|
@ -133,7 +133,8 @@ pub trait WinitWindow: PlatformWindow {
|
|||
}
|
||||
}
|
||||
|
||||
let existing_size: LogicalSize = self.inner_size().cast() / self.window().scale();
|
||||
let existing_size: LogicalSize =
|
||||
self.inner_size().cast() / self.window().scale_factor();
|
||||
|
||||
if (existing_size.width as f32 - width).abs() > 1.
|
||||
|| (existing_size.height as f32 - height).abs() > 1.
|
||||
|
|
@ -148,7 +149,7 @@ pub trait WinitWindow: PlatformWindow {
|
|||
});
|
||||
|
||||
if must_resize {
|
||||
let win = i_slint_core::api::Window::from(self.window());
|
||||
let win = self.window();
|
||||
let f = win.scale_factor().0;
|
||||
win.set_size(euclid::size2((width as f32 * f) as _, (height as f32 * f) as _));
|
||||
}
|
||||
|
|
@ -380,7 +381,7 @@ fn process_window_event(
|
|||
event
|
||||
}
|
||||
|
||||
let runtime_window = window.window();
|
||||
let runtime_window = window.window().window_handle();
|
||||
match event {
|
||||
WindowEvent::Resized(size) => {
|
||||
window.resize_event(size);
|
||||
|
|
@ -651,7 +652,7 @@ pub fn run(quit_behavior: i_slint_core::backend::EventLoopQuitBehavior) {
|
|||
.drain(..)
|
||||
.flat_map(|window_id| window_by_id(window_id))
|
||||
{
|
||||
window.window().update_window_properties();
|
||||
window.window().window_handle().update_window_properties();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use corelib::component::ComponentRc;
|
|||
use corelib::input::KeyboardModifiers;
|
||||
use corelib::items::{ItemRef, MouseCursor};
|
||||
use corelib::layout::Orientation;
|
||||
use corelib::window::{PlatformWindow, WindowRc};
|
||||
use corelib::window::{PlatformWindow, PlatformWindowRc, WindowHandleAccess};
|
||||
use corelib::Property;
|
||||
use corelib::{graphics::*, Coord};
|
||||
use i_slint_core as corelib;
|
||||
|
|
@ -26,7 +26,7 @@ use winit::dpi::LogicalSize;
|
|||
/// GraphicsWindow is an implementation of the [PlatformWindow][`crate::eventloop::PlatformWindow`] trait. This is
|
||||
/// typically instantiated by entry factory functions of the different graphics back ends.
|
||||
pub(crate) struct GLWindow<Renderer: WinitCompatibleRenderer + 'static> {
|
||||
window_inner_weak: Weak<corelib::window::WindowInner>,
|
||||
window: corelib::api::Window,
|
||||
self_weak: Weak<Self>,
|
||||
map_state: RefCell<GraphicsWindowBackendState<Renderer>>,
|
||||
keyboard_modifiers: std::cell::Cell<KeyboardModifiers>,
|
||||
|
|
@ -38,19 +38,16 @@ pub(crate) struct GLWindow<Renderer: WinitCompatibleRenderer + 'static> {
|
|||
virtual_keyboard_helper: RefCell<Option<super::wasm_input_helper::WasmInputHelper>>,
|
||||
}
|
||||
|
||||
impl<Renderer: WinitCompatibleRenderer> GLWindow<Renderer> {
|
||||
impl<Renderer: WinitCompatibleRenderer + 'static> GLWindow<Renderer> {
|
||||
/// Creates a new reference-counted instance.
|
||||
///
|
||||
/// Arguments:
|
||||
/// * `graphics_backend_factory`: The factor function stored in the GraphicsWindow that's called when the state
|
||||
/// of the window changes to mapped. The event loop and window builder parameters can be used to create a
|
||||
/// backing window.
|
||||
pub(crate) fn new(
|
||||
window_weak: &Weak<corelib::window::WindowInner>,
|
||||
#[cfg(target_arch = "wasm32")] canvas_id: String,
|
||||
) -> Rc<Self> {
|
||||
Rc::new_cyclic(|self_weak| Self {
|
||||
window_inner_weak: window_weak.clone(),
|
||||
pub(crate) fn new(#[cfg(target_arch = "wasm32")] canvas_id: String) -> PlatformWindowRc {
|
||||
let self_rc = Rc::new_cyclic(|self_weak| Self {
|
||||
window: corelib::api::Window::new(self_weak.clone() as _),
|
||||
self_weak: self_weak.clone(),
|
||||
map_state: RefCell::new(GraphicsWindowBackendState::Unmapped {
|
||||
requested_position: None,
|
||||
|
|
@ -59,13 +56,14 @@ impl<Renderer: WinitCompatibleRenderer> GLWindow<Renderer> {
|
|||
keyboard_modifiers: Default::default(),
|
||||
currently_pressed_key_code: Default::default(),
|
||||
renderer: Renderer::new(
|
||||
&window_weak,
|
||||
&(self_weak.clone() as _),
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
canvas_id,
|
||||
),
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
virtual_keyboard_helper: Default::default(),
|
||||
})
|
||||
});
|
||||
self_rc as _
|
||||
}
|
||||
|
||||
fn is_mapped(&self) -> bool {
|
||||
|
|
@ -192,8 +190,7 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WinitWindow for GLWindow<Rende
|
|||
|
||||
fn resize_event(&self, size: winit::dpi::PhysicalSize<u32>) {
|
||||
if let Some(mapped_window) = self.borrow_mapped_window() {
|
||||
i_slint_core::api::Window::from(self.window())
|
||||
.set_size(euclid::size2(size.width, size.height));
|
||||
self.window().set_size(euclid::size2(size.width, size.height));
|
||||
mapped_window.canvas.resize_event()
|
||||
}
|
||||
}
|
||||
|
|
@ -270,7 +267,7 @@ impl<Renderer: WinitCompatibleRenderer + 'static> PlatformWindow for GLWindow<Re
|
|||
GraphicsWindowBackendState::Mapped(_) => return,
|
||||
};
|
||||
|
||||
let runtime_window = self.window();
|
||||
let runtime_window = self.window().window_handle();
|
||||
let component_rc = runtime_window.component();
|
||||
let component = ComponentRc::borrow_pin(&component_rc);
|
||||
|
||||
|
|
@ -345,12 +342,11 @@ impl<Renderer: WinitCompatibleRenderer + 'static> PlatformWindow for GLWindow<Re
|
|||
|
||||
let canvas = self.renderer.create_canvas(window_builder);
|
||||
|
||||
let id = canvas.with_window_handle(|window| {
|
||||
let runtime_window = self.window_inner_weak.upgrade().unwrap();
|
||||
runtime_window.set_scale_factor(
|
||||
scale_factor_override.unwrap_or_else(|| window.scale_factor()) as _,
|
||||
let id = canvas.with_window_handle(|winit_window| {
|
||||
self.window.window_handle().set_scale_factor(
|
||||
scale_factor_override.unwrap_or_else(|| winit_window.scale_factor()) as _,
|
||||
);
|
||||
window.id()
|
||||
winit_window.id()
|
||||
});
|
||||
|
||||
self.map_state.replace(GraphicsWindowBackendState::Mapped(MappedWindow {
|
||||
|
|
@ -483,8 +479,8 @@ impl<Renderer: WinitCompatibleRenderer + 'static> PlatformWindow for GLWindow<Re
|
|||
}
|
||||
}
|
||||
|
||||
fn window(&self) -> WindowRc {
|
||||
self.window_inner_weak.upgrade().unwrap()
|
||||
fn window(&self) -> &corelib::api::Window {
|
||||
&self.window
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,13 +18,14 @@ mod glcontext;
|
|||
use glcontext::*;
|
||||
pub(crate) mod event_loop;
|
||||
mod renderer {
|
||||
use std::rc::Weak;
|
||||
|
||||
use i_slint_core::window::PlatformWindowWeak;
|
||||
|
||||
pub(crate) trait WinitCompatibleRenderer: i_slint_core::renderer::Renderer {
|
||||
type Canvas: WinitCompatibleCanvas;
|
||||
|
||||
fn new(
|
||||
window_weak: &Weak<i_slint_core::window::WindowInner>,
|
||||
platform_window_weak: &PlatformWindowWeak,
|
||||
#[cfg(target_arch = "wasm32")] canvas_id: String,
|
||||
) -> Self;
|
||||
|
||||
|
|
@ -57,11 +58,8 @@ pub(crate) mod wasm_input_helper;
|
|||
mod stylemetrics;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn create_gl_window_with_canvas_id(canvas_id: String) -> i_slint_core::api::Window {
|
||||
i_slint_core::window::WindowInner::new(|window| {
|
||||
GLWindow::<crate::renderer::femtovg::FemtoVGRenderer>::new(window, canvas_id)
|
||||
})
|
||||
.into()
|
||||
pub fn create_gl_window_with_canvas_id(canvas_id: String) -> PlatformWindowRc {
|
||||
GLWindow::<crate::renderer::femtovg::FemtoVGRenderer>::new(canvas_id)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
|
@ -76,60 +74,45 @@ pub mod native_widgets {
|
|||
}
|
||||
pub const HAS_NATIVE_STYLE: bool = false;
|
||||
|
||||
use i_slint_core::window::PlatformWindowRc;
|
||||
pub use stylemetrics::native_style_metrics_deinit;
|
||||
pub use stylemetrics::native_style_metrics_init;
|
||||
|
||||
pub struct Backend {
|
||||
window_factory_fn: Mutex<Box<dyn Fn() -> i_slint_core::api::Window + Send>>,
|
||||
window_factory_fn: Mutex<Box<dyn Fn() -> PlatformWindowRc + Send>>,
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
pub fn new(renderer_name: Option<&str>) -> Self {
|
||||
#[cfg(feature = "renderer-femtovg")]
|
||||
let (default_renderer, default_renderer_factory) = ("FemtoVG", || {
|
||||
i_slint_core::window::WindowInner::new(|window| {
|
||||
GLWindow::<renderer::femtovg::FemtoVGRenderer>::new(
|
||||
window,
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
"canvas".into(),
|
||||
)
|
||||
})
|
||||
.into()
|
||||
});
|
||||
#[cfg(all(not(feature = "renderer-femtovg"), feature = "renderer-skia"))]
|
||||
let (default_renderer, default_renderer_factory) = ("Skia", || {
|
||||
i_slint_core::window::WindowInner::new(|window| {
|
||||
GLWindow::<renderer::skia::SkiaRenderer>::new(
|
||||
window,
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
"canvas".into(),
|
||||
)
|
||||
})
|
||||
.into()
|
||||
});
|
||||
|
||||
let factory_fn = match renderer_name {
|
||||
#[cfg(feature = "renderer-femtovg")]
|
||||
Some("gl") | Some("femtovg") => || {
|
||||
i_slint_core::window::WindowInner::new(|window| {
|
||||
GLWindow::<renderer::femtovg::FemtoVGRenderer>::new(
|
||||
window,
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
"canvas".into(),
|
||||
)
|
||||
})
|
||||
.into()
|
||||
},
|
||||
#[cfg(feature = "renderer-skia")]
|
||||
Some("skia") => || {
|
||||
i_slint_core::window::WindowInner::new(|window| {
|
||||
GLWindow::<renderer::skia::SkiaRenderer>::new(
|
||||
window,
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
"canvas".into(),
|
||||
)
|
||||
})
|
||||
.into()
|
||||
},
|
||||
None => default_renderer_factory,
|
||||
Some(renderer_name) => {
|
||||
|
|
@ -145,7 +128,7 @@ impl Backend {
|
|||
}
|
||||
|
||||
impl i_slint_core::backend::Backend for Backend {
|
||||
fn create_window(&self) -> i_slint_core::api::Window {
|
||||
fn create_window(&self) -> PlatformWindowRc {
|
||||
self.window_factory_fn.lock().unwrap()()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
pin::Pin,
|
||||
rc::{Rc, Weak},
|
||||
};
|
||||
use std::{cell::RefCell, pin::Pin, rc::Rc};
|
||||
|
||||
use i_slint_core::{
|
||||
api::{euclid, GraphicsAPI, RenderingNotifier, RenderingState, SetRenderingNotifierError},
|
||||
graphics::rendering_metrics_collector::RenderingMetricsCollector,
|
||||
graphics::{Point, Rect, Size},
|
||||
renderer::Renderer,
|
||||
Coord,
|
||||
use i_slint_core::api::{
|
||||
euclid, GraphicsAPI, RenderingNotifier, RenderingState, SetRenderingNotifierError,
|
||||
};
|
||||
use i_slint_core::graphics::{
|
||||
rendering_metrics_collector::RenderingMetricsCollector, Point, Rect, Size,
|
||||
};
|
||||
use i_slint_core::renderer::Renderer;
|
||||
use i_slint_core::window::{PlatformWindowWeak, WindowHandleAccess};
|
||||
use i_slint_core::Coord;
|
||||
|
||||
use crate::WindowSystemName;
|
||||
|
||||
|
|
@ -26,7 +24,7 @@ mod itemrenderer;
|
|||
const PASSWORD_CHARACTER: &str = "●";
|
||||
|
||||
pub struct FemtoVGRenderer {
|
||||
window_weak: Weak<i_slint_core::window::WindowInner>,
|
||||
platform_window_weak: PlatformWindowWeak,
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
canvas_id: String,
|
||||
rendering_notifier: RefCell<Option<Box<dyn RenderingNotifier>>>,
|
||||
|
|
@ -36,11 +34,11 @@ impl super::WinitCompatibleRenderer for FemtoVGRenderer {
|
|||
type Canvas = FemtoVGCanvas;
|
||||
|
||||
fn new(
|
||||
window_weak: &Weak<i_slint_core::window::WindowInner>,
|
||||
platform_window_weak: &PlatformWindowWeak,
|
||||
#[cfg(target_arch = "wasm32")] canvas_id: String,
|
||||
) -> Self {
|
||||
Self {
|
||||
window_weak: window_weak.clone(),
|
||||
platform_window_weak: platform_window_weak.clone(),
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
canvas_id,
|
||||
rendering_notifier: Default::default(),
|
||||
|
|
@ -55,7 +53,7 @@ impl super::WinitCompatibleRenderer for FemtoVGRenderer {
|
|||
);
|
||||
|
||||
let rendering_metrics_collector = RenderingMetricsCollector::new(
|
||||
self.window_weak.clone(),
|
||||
self.platform_window_weak.clone(),
|
||||
&format!(
|
||||
"FemtoVG renderer (windowing system: {})",
|
||||
opengl_context.window().winsys_name()
|
||||
|
|
@ -125,7 +123,7 @@ impl super::WinitCompatibleRenderer for FemtoVGRenderer {
|
|||
}
|
||||
|
||||
fn render(&self, canvas: &FemtoVGCanvas) {
|
||||
let window = match self.window_weak.upgrade() {
|
||||
let platform_window = match self.platform_window_weak.upgrade() {
|
||||
Some(window) => window,
|
||||
None => return,
|
||||
};
|
||||
|
|
@ -136,6 +134,8 @@ impl super::WinitCompatibleRenderer for FemtoVGRenderer {
|
|||
|
||||
canvas.opengl_context.make_current();
|
||||
|
||||
let window = platform_window.window().window_handle();
|
||||
|
||||
window.draw_contents(|components| {
|
||||
{
|
||||
let mut femtovg_canvas = canvas.canvas.as_ref().borrow_mut();
|
||||
|
|
@ -170,8 +170,12 @@ impl super::WinitCompatibleRenderer for FemtoVGRenderer {
|
|||
.with_graphics_api(|api| callback.notify(RenderingState::BeforeRendering, &api))
|
||||
}
|
||||
|
||||
let mut item_renderer =
|
||||
self::itemrenderer::GLItemRenderer::new(canvas, &window, width, height);
|
||||
let mut item_renderer = self::itemrenderer::GLItemRenderer::new(
|
||||
canvas,
|
||||
platform_window.window(),
|
||||
width,
|
||||
height,
|
||||
);
|
||||
|
||||
for (component, origin) in components {
|
||||
i_slint_core::item_rendering::render_component_items(
|
||||
|
|
@ -218,11 +222,13 @@ impl Renderer for FemtoVGRenderer {
|
|||
text_input: Pin<&i_slint_core::items::TextInput>,
|
||||
pos: Point,
|
||||
) -> usize {
|
||||
let window = match self.window_weak.upgrade() {
|
||||
let platform_window = match self.platform_window_weak.upgrade() {
|
||||
Some(window) => window,
|
||||
None => return 0,
|
||||
};
|
||||
|
||||
let window = platform_window.window().window_handle();
|
||||
|
||||
let scale_factor = window.scale_factor();
|
||||
let pos = pos * scale_factor;
|
||||
let text = text_input.text();
|
||||
|
|
@ -295,11 +301,13 @@ impl Renderer for FemtoVGRenderer {
|
|||
text_input: Pin<&i_slint_core::items::TextInput>,
|
||||
byte_offset: usize,
|
||||
) -> Rect {
|
||||
let window = match self.window_weak.upgrade() {
|
||||
let platform_window = match self.platform_window_weak.upgrade() {
|
||||
Some(window) => window,
|
||||
None => return Default::default(),
|
||||
};
|
||||
|
||||
let window = platform_window.window().window_handle();
|
||||
|
||||
let text = text_input.text();
|
||||
let scale_factor = window.scale_factor();
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use i_slint_core::items::{
|
|||
self, Clip, FillRule, ImageFit, ImageRendering, InputType, Item, ItemRc, Layer, Opacity,
|
||||
RenderingResult,
|
||||
};
|
||||
use i_slint_core::window::WindowRc;
|
||||
use i_slint_core::window::WindowHandleAccess;
|
||||
use i_slint_core::{Brush, Color, ImageInner, Property, SharedString};
|
||||
|
||||
use super::fonts;
|
||||
|
|
@ -66,7 +66,7 @@ pub struct GLItemRenderer<'a> {
|
|||
// because that can only happen after calling `flush`. Otherwise femtovg ends up processing
|
||||
// `set_render_target` commands with image ids that have been deleted.
|
||||
layer_images_to_delete_after_flush: Vec<Rc<super::images::Texture>>,
|
||||
window: Rc<i_slint_core::window::WindowInner>,
|
||||
window: &'a i_slint_core::api::Window,
|
||||
scale_factor: f32,
|
||||
/// track the state manually since femtovg don't have accessor for its state
|
||||
state: Vec<State>,
|
||||
|
|
@ -240,7 +240,7 @@ impl<'a> ItemRenderer for GLItemRenderer<'a> {
|
|||
let string = string.as_str();
|
||||
let font = fonts::FONT_CACHE.with(|cache| {
|
||||
cache.borrow_mut().font(
|
||||
text.font_request(&self.window),
|
||||
text.font_request(self.window.window_handle()),
|
||||
self.scale_factor,
|
||||
&text.text(),
|
||||
)
|
||||
|
|
@ -278,7 +278,7 @@ impl<'a> ItemRenderer for GLItemRenderer<'a> {
|
|||
|
||||
let font = fonts::FONT_CACHE.with(|cache| {
|
||||
cache.borrow_mut().font(
|
||||
text_input.font_request(&self.window),
|
||||
text_input.font_request(self.window.window_handle()),
|
||||
self.scale_factor,
|
||||
&text_input.text(),
|
||||
)
|
||||
|
|
@ -819,8 +819,8 @@ impl<'a> ItemRenderer for GLItemRenderer<'a> {
|
|||
canvas.fill_text(0., 0., string, paint).unwrap();
|
||||
}
|
||||
|
||||
fn window(&self) -> WindowRc {
|
||||
self.window.clone()
|
||||
fn window(&self) -> &i_slint_core::api::Window {
|
||||
self.window
|
||||
}
|
||||
|
||||
fn as_any(&mut self) -> Option<&mut dyn std::any::Any> {
|
||||
|
|
@ -873,17 +873,17 @@ impl<'a> ItemRenderer for GLItemRenderer<'a> {
|
|||
impl<'a> GLItemRenderer<'a> {
|
||||
pub fn new(
|
||||
canvas: &'a super::FemtoVGCanvas,
|
||||
window: &Rc<i_slint_core::window::WindowInner>,
|
||||
window: &'a i_slint_core::api::Window,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Self {
|
||||
let scale_factor = window.scale_factor();
|
||||
let scale_factor = window.scale_factor().get();
|
||||
Self {
|
||||
graphics_cache: &canvas.graphics_cache,
|
||||
texture_cache: &canvas.texture_cache,
|
||||
canvas: canvas.canvas.clone(),
|
||||
layer_images_to_delete_after_flush: Default::default(),
|
||||
window: window.clone(),
|
||||
window,
|
||||
scale_factor,
|
||||
state: vec![State {
|
||||
scissor: Rect::new(
|
||||
|
|
@ -1112,7 +1112,7 @@ impl<'a> GLItemRenderer<'a> {
|
|||
let target_size_for_scalable_source = matches!(image_inner, ImageInner::Svg(..))
|
||||
.then(|| {
|
||||
// get the scale factor as a property again, to ensure the cache is invalidated when the scale factor changes
|
||||
let scale_factor = self.window.scale_factor();
|
||||
let scale_factor = self.window.scale_factor().get();
|
||||
[
|
||||
(target_width.get() * scale_factor) as u32,
|
||||
(target_height.get() * scale_factor) as u32,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
rc::{Rc, Weak},
|
||||
};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use i_slint_core::{
|
||||
api::{GraphicsAPI, RenderingNotifier, RenderingState, SetRenderingNotifierError},
|
||||
graphics::rendering_metrics_collector::RenderingMetricsCollector,
|
||||
item_rendering::ItemCache,
|
||||
use i_slint_core::api::{
|
||||
GraphicsAPI, RenderingNotifier, RenderingState, SetRenderingNotifierError,
|
||||
};
|
||||
use i_slint_core::graphics::rendering_metrics_collector::RenderingMetricsCollector;
|
||||
use i_slint_core::item_rendering::ItemCache;
|
||||
use i_slint_core::window::{PlatformWindowWeak, WindowHandleAccess};
|
||||
|
||||
use crate::WindowSystemName;
|
||||
|
||||
|
|
@ -38,22 +36,25 @@ cfg_if::cfg_if! {
|
|||
}
|
||||
|
||||
pub struct SkiaRenderer {
|
||||
window_weak: Weak<i_slint_core::window::WindowInner>,
|
||||
platform_window_weak: PlatformWindowWeak,
|
||||
rendering_notifier: RefCell<Option<Box<dyn RenderingNotifier>>>,
|
||||
}
|
||||
|
||||
impl super::WinitCompatibleRenderer for SkiaRenderer {
|
||||
type Canvas = SkiaCanvas<DefaultSurface>;
|
||||
|
||||
fn new(window_weak: &std::rc::Weak<i_slint_core::window::WindowInner>) -> Self {
|
||||
Self { window_weak: window_weak.clone(), rendering_notifier: Default::default() }
|
||||
fn new(platform_window_weak: &PlatformWindowWeak) -> Self {
|
||||
Self {
|
||||
platform_window_weak: platform_window_weak.clone(),
|
||||
rendering_notifier: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_canvas(&self, window_builder: winit::window::WindowBuilder) -> Self::Canvas {
|
||||
let surface = DefaultSurface::new(window_builder);
|
||||
|
||||
let rendering_metrics_collector = RenderingMetricsCollector::new(
|
||||
self.window_weak.clone(),
|
||||
self.platform_window_weak.clone(),
|
||||
&format!(
|
||||
"Skia renderer (windowing system: {}; skia backend {})",
|
||||
surface.with_window_handle(|winit_window| winit_window.winsys_name()),
|
||||
|
|
@ -82,11 +83,13 @@ impl super::WinitCompatibleRenderer for SkiaRenderer {
|
|||
}
|
||||
|
||||
fn render(&self, canvas: &Self::Canvas) {
|
||||
let window = match self.window_weak.upgrade() {
|
||||
let platform_window = match self.platform_window_weak.upgrade() {
|
||||
Some(window) => window,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let window = platform_window.window().window_handle();
|
||||
|
||||
canvas.surface.render(|skia_canvas, gr_context| {
|
||||
window.draw_contents(|components| {
|
||||
if let Some(window_item) = window.window_item() {
|
||||
|
|
@ -105,8 +108,11 @@ impl super::WinitCompatibleRenderer for SkiaRenderer {
|
|||
})
|
||||
}
|
||||
|
||||
let mut item_renderer =
|
||||
itemrenderer::SkiaRenderer::new(skia_canvas, &window, &canvas.image_cache);
|
||||
let mut item_renderer = itemrenderer::SkiaRenderer::new(
|
||||
skia_canvas,
|
||||
platform_window.window(),
|
||||
&canvas.image_cache,
|
||||
);
|
||||
|
||||
for (component, origin) in components {
|
||||
i_slint_core::item_rendering::render_component_items(
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
||||
use i_slint_core::graphics::euclid;
|
||||
use i_slint_core::item_rendering::{ItemCache, ItemRenderer};
|
||||
use i_slint_core::items::{ImageFit, ImageRendering, ItemRc, Layer, Opacity, RenderingResult};
|
||||
use i_slint_core::window::WindowHandleAccess;
|
||||
use i_slint_core::{items, Brush, Color, Property};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
|
@ -16,8 +16,8 @@ struct RenderState {
|
|||
|
||||
pub struct SkiaRenderer<'a> {
|
||||
pub canvas: &'a mut skia_safe::Canvas,
|
||||
pub window: Rc<i_slint_core::window::WindowInner>,
|
||||
pub scale_factor: f32,
|
||||
pub window: &'a i_slint_core::api::Window,
|
||||
state_stack: Vec<RenderState>,
|
||||
current_state: RenderState,
|
||||
image_cache: &'a ItemCache<Option<skia_safe::Image>>,
|
||||
|
|
@ -26,13 +26,13 @@ pub struct SkiaRenderer<'a> {
|
|||
impl<'a> SkiaRenderer<'a> {
|
||||
pub fn new(
|
||||
canvas: &'a mut skia_safe::Canvas,
|
||||
window: &Rc<i_slint_core::window::WindowInner>,
|
||||
window: &'a i_slint_core::api::Window,
|
||||
image_cache: &'a ItemCache<Option<skia_safe::Image>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
canvas,
|
||||
window: window.clone(),
|
||||
scale_factor: window.scale_factor(),
|
||||
scale_factor: window.scale_factor().get(),
|
||||
window,
|
||||
state_stack: vec![],
|
||||
current_state: RenderState { alpha: 1.0 },
|
||||
image_cache,
|
||||
|
|
@ -351,7 +351,7 @@ impl<'a> ItemRenderer for SkiaRenderer<'a> {
|
|||
|
||||
let string = text.text();
|
||||
let string = string.as_str();
|
||||
let font_request = text.font_request(&self.window);
|
||||
let font_request = text.font_request(self.window.window_handle());
|
||||
|
||||
let paint = match self.brush_to_paint(text.color(), max_width, max_height) {
|
||||
Some(paint) => paint,
|
||||
|
|
@ -599,8 +599,8 @@ impl<'a> ItemRenderer for SkiaRenderer<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
fn window(&self) -> i_slint_core::window::WindowRc {
|
||||
self.window.clone()
|
||||
fn window(&self) -> &i_slint_core::api::Window {
|
||||
self.window
|
||||
}
|
||||
|
||||
fn as_any(&mut self) -> Option<&mut dyn core::any::Any> {
|
||||
|
|
|
|||
|
|
@ -18,9 +18,10 @@
|
|||
//! we just simulate a few backspaces.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::rc::Rc;
|
||||
|
||||
use i_slint_core::input::{KeyEvent, KeyEventType, KeyboardModifiers};
|
||||
use i_slint_core::window::{PlatformWindowWeak, WindowHandleAccess};
|
||||
use i_slint_core::SharedString;
|
||||
use wasm_bindgen::closure::Closure;
|
||||
use wasm_bindgen::convert::FromWasmAbi;
|
||||
|
|
@ -65,10 +66,7 @@ impl WasmInputState {
|
|||
|
||||
impl WasmInputHelper {
|
||||
#[allow(unused)]
|
||||
pub fn new(
|
||||
window: Weak<i_slint_core::window::WindowInner>,
|
||||
canvas: web_sys::HtmlCanvasElement,
|
||||
) -> Self {
|
||||
pub fn new(platform_window: PlatformWindowWeak, canvas: web_sys::HtmlCanvasElement) -> Self {
|
||||
let input = web_sys::window()
|
||||
.unwrap()
|
||||
.document()
|
||||
|
|
@ -91,23 +89,24 @@ impl WasmInputHelper {
|
|||
|
||||
let shared_state = Rc::new(RefCell::new(WasmInputState::default()));
|
||||
|
||||
let win = window.clone();
|
||||
let win = platform_window.clone();
|
||||
h.add_event_listener("blur", move |_: web_sys::Event| {
|
||||
// Make sure that the window gets marked as unfocused when the focus leaves the input
|
||||
if let Some(window) = win.upgrade() {
|
||||
if let Some(platform_window) = win.upgrade() {
|
||||
let window = platform_window.window().window_handle();
|
||||
if !canvas.matches(":focus").unwrap_or(false) {
|
||||
window.set_active(false);
|
||||
window.set_focus(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
let win = window.clone();
|
||||
let win = platform_window.clone();
|
||||
let shared_state2 = shared_state.clone();
|
||||
h.add_event_listener("keydown", move |e: web_sys::KeyboardEvent| {
|
||||
if let (Some(window), Some(text)) = (win.upgrade(), event_text(&e)) {
|
||||
if let (Some(platform_window), Some(text)) = (win.upgrade(), event_text(&e)) {
|
||||
e.prevent_default();
|
||||
shared_state2.borrow_mut().has_key_down = true;
|
||||
window.process_key_input(&KeyEvent {
|
||||
platform_window.window().window_handle().process_key_input(&KeyEvent {
|
||||
modifiers: modifiers(&e),
|
||||
text,
|
||||
event_type: KeyEventType::KeyPressed,
|
||||
|
|
@ -115,13 +114,13 @@ impl WasmInputHelper {
|
|||
}
|
||||
});
|
||||
|
||||
let win = window.clone();
|
||||
let win = platform_window.clone();
|
||||
let shared_state2 = shared_state.clone();
|
||||
h.add_event_listener("keyup", move |e: web_sys::KeyboardEvent| {
|
||||
if let (Some(window), Some(text)) = (win.upgrade(), event_text(&e)) {
|
||||
if let (Some(platform_window), Some(text)) = (win.upgrade(), event_text(&e)) {
|
||||
e.prevent_default();
|
||||
shared_state2.borrow_mut().has_key_down = false;
|
||||
window.process_key_input(&KeyEvent {
|
||||
platform_window.window().window_handle().process_key_input(&KeyEvent {
|
||||
modifiers: modifiers(&e),
|
||||
text,
|
||||
event_type: KeyEventType::KeyReleased,
|
||||
|
|
@ -129,13 +128,14 @@ impl WasmInputHelper {
|
|||
}
|
||||
});
|
||||
|
||||
let win = window.clone();
|
||||
let win = platform_window.clone();
|
||||
let shared_state2 = shared_state.clone();
|
||||
let input = h.input.clone();
|
||||
h.add_event_listener("input", move |e: web_sys::InputEvent| {
|
||||
if let (Some(window), Some(data)) = (win.upgrade(), e.data()) {
|
||||
if let (Some(platform_window), Some(data)) = (win.upgrade(), e.data()) {
|
||||
if !e.is_composing() && e.input_type() != "insertCompositionText" {
|
||||
if !shared_state2.borrow_mut().has_key_down {
|
||||
let window = platform_window.window().window_handle();
|
||||
let text = SharedString::from(data.as_str());
|
||||
window.process_key_input(&KeyEvent {
|
||||
modifiers: Default::default(),
|
||||
|
|
@ -155,11 +155,12 @@ impl WasmInputHelper {
|
|||
});
|
||||
|
||||
for event in ["compositionend", "compositionupdate"] {
|
||||
let win = window.clone();
|
||||
let win = platform_window.clone();
|
||||
let shared_state2 = shared_state.clone();
|
||||
let input = h.input.clone();
|
||||
h.add_event_listener(event, move |e: web_sys::CompositionEvent| {
|
||||
if let (Some(window), Some(data)) = (win.upgrade(), e.data()) {
|
||||
if let (Some(platform_window), Some(data)) = (win.upgrade(), e.data()) {
|
||||
let window = platform_window.window().window_handle();
|
||||
let is_end = event == "compositionend";
|
||||
let (text, to_delete) =
|
||||
shared_state2.borrow_mut().text_from_compose(data, is_end);
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@ This module contains types that are public and re-exported in the slint-rs as we
|
|||
*/
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::rc::Rc;
|
||||
|
||||
use crate::component::ComponentVTable;
|
||||
use crate::window::WindowRc;
|
||||
use crate::window::WindowInner;
|
||||
|
||||
pub use crate::lengths::LogicalPx;
|
||||
pub use crate::lengths::PhysicalPx;
|
||||
|
|
@ -97,14 +96,7 @@ pub enum SetRenderingNotifierError {
|
|||
/// scene of a component. It provides API to control windowing system specific aspects such
|
||||
/// as the position on the screen.
|
||||
#[repr(transparent)]
|
||||
pub struct Window(WindowRc);
|
||||
|
||||
#[doc(hidden)]
|
||||
impl From<WindowRc> for Window {
|
||||
fn from(window: WindowRc) -> Self {
|
||||
Self(window)
|
||||
}
|
||||
}
|
||||
pub struct Window(WindowInner);
|
||||
|
||||
/// This enum describes whether a Window is allowed to be hidden when the user tries to close the window.
|
||||
/// It is the return type of the callback provided to [Window::on_close_requested].
|
||||
|
|
@ -122,6 +114,10 @@ impl Default for CloseRequestResponse {
|
|||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(platform_window_weak: alloc::rc::Weak<dyn crate::window::PlatformWindow>) -> Self {
|
||||
Self(WindowInner::new(platform_window_weak))
|
||||
}
|
||||
|
||||
/// Registers the window with the windowing system in order to make it visible on the screen.
|
||||
pub fn show(&self) {
|
||||
self.0.show();
|
||||
|
|
@ -138,7 +134,7 @@ impl Window {
|
|||
&self,
|
||||
callback: impl FnMut(RenderingState, &GraphicsAPI) + 'static,
|
||||
) -> Result<(), SetRenderingNotifierError> {
|
||||
self.0.renderer().set_rendering_notifier(Box::new(callback))
|
||||
self.0.platform_window().renderer().set_rendering_notifier(Box::new(callback))
|
||||
}
|
||||
|
||||
/// This function allows registering a callback that's invoked when the user tries to close a window.
|
||||
|
|
@ -149,7 +145,7 @@ impl Window {
|
|||
|
||||
/// This function issues a request to the windowing system to redraw the contents of the window.
|
||||
pub fn request_redraw(&self) {
|
||||
self.0.request_redraw();
|
||||
self.0.platform_window().request_redraw();
|
||||
|
||||
// When this function is called by the user, we want it to translate to a requestAnimationFrame()
|
||||
// on the web. If called through the rendering notifier (so from within the event loop processing),
|
||||
|
|
@ -169,14 +165,14 @@ impl Window {
|
|||
/// Returns the position of the window on the screen, in physical screen coordinates and including
|
||||
/// a window frame (if present).
|
||||
pub fn position(&self) -> euclid::Point2D<i32, PhysicalPx> {
|
||||
self.0.position()
|
||||
self.0.platform_window().position()
|
||||
}
|
||||
|
||||
/// Sets the position of the window on the screen, in physical screen coordinates and including
|
||||
/// a window frame (if present).
|
||||
/// Note that on some windowing systems, such as Wayland, this functionality is not available.
|
||||
pub fn set_position(&self, position: euclid::Point2D<i32, PhysicalPx>) {
|
||||
self.0.set_position(position)
|
||||
self.0.platform_window().set_position(position)
|
||||
}
|
||||
|
||||
/// Returns the size of the window on the screen, in physical screen coordinates and excluding
|
||||
|
|
@ -194,7 +190,7 @@ impl Window {
|
|||
|
||||
let l = size.cast() / self.scale_factor();
|
||||
self.0.set_window_item_geometry(l.width as _, l.height as _);
|
||||
self.0.set_inner_size(size)
|
||||
self.0.platform_window().set_inner_size(size)
|
||||
}
|
||||
|
||||
/// Dispatch a pointer event (touch or mouse) to the window
|
||||
|
|
@ -204,12 +200,12 @@ impl Window {
|
|||
/// Note: This function is usually called by the Slint backend. You should only call this function
|
||||
/// if implementing your own backend or for testing purposes.
|
||||
pub fn dispatch_pointer_event(&self, event: PointerEvent) {
|
||||
self.0.clone().process_mouse_input(event.into())
|
||||
self.0.process_mouse_input(event.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::window::WindowHandleAccess for Window {
|
||||
fn window_handle(&self) -> &Rc<crate::window::WindowInner> {
|
||||
fn window_handle(&self) -> &crate::window::WindowInner {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use once_cell::sync::OnceCell;
|
|||
|
||||
#[cfg(all(not(feature = "std"), feature = "unsafe_single_core"))]
|
||||
use crate::unsafe_single_core::OnceCell;
|
||||
use crate::window::PlatformWindowRc;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
/// Behavior describing how the event loop should terminate.
|
||||
|
|
@ -26,7 +27,7 @@ pub enum EventLoopQuitBehavior {
|
|||
/// Interface implemented by back-ends
|
||||
pub trait Backend: Send + Sync {
|
||||
/// Instantiate a window for a component.
|
||||
fn create_window(&self) -> crate::api::Window;
|
||||
fn create_window(&self) -> PlatformWindowRc;
|
||||
|
||||
/// Spins an event loop and renders the visible windows.
|
||||
fn run_event_loop(&self, _behavior: EventLoopQuitBehavior) {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use crate::item_tree::{
|
|||
use crate::items::{AccessibleRole, ItemVTable};
|
||||
use crate::layout::{LayoutInfo, Orientation};
|
||||
use crate::slice::Slice;
|
||||
use crate::window::WindowInner;
|
||||
use crate::window::{PlatformWindowRc, WindowHandleAccess};
|
||||
use crate::SharedString;
|
||||
use vtable::*;
|
||||
|
||||
|
|
@ -114,10 +114,12 @@ pub type ComponentWeak = vtable::VWeak<ComponentVTable, Dyn>;
|
|||
pub fn register_component<Base>(
|
||||
base: core::pin::Pin<&Base>,
|
||||
item_array: &[vtable::VOffset<Base, ItemVTable, vtable::AllowPin>],
|
||||
window: &WindowInner,
|
||||
platform_window: &PlatformWindowRc,
|
||||
) {
|
||||
item_array.iter().for_each(|item| item.apply_pin(base).as_ref().init(window));
|
||||
window.register_component();
|
||||
item_array.iter().for_each(|item| {
|
||||
item.apply_pin(base).as_ref().init(platform_window.window().window_handle())
|
||||
});
|
||||
platform_window.register_component();
|
||||
}
|
||||
|
||||
/// Free the backend graphics resources allocated by the component's items.
|
||||
|
|
@ -125,30 +127,32 @@ pub fn unregister_component<Base>(
|
|||
base: core::pin::Pin<&Base>,
|
||||
component: ComponentRef,
|
||||
item_array: &[vtable::VOffset<Base, ItemVTable, vtable::AllowPin>],
|
||||
window: &WindowInner,
|
||||
platform_window: &PlatformWindowRc,
|
||||
) {
|
||||
window.unregister_component(component, &mut item_array.iter().map(|item| item.apply_pin(base)));
|
||||
platform_window
|
||||
.unregister_component(component, &mut item_array.iter().map(|item| item.apply_pin(base)));
|
||||
}
|
||||
|
||||
#[cfg(feature = "ffi")]
|
||||
pub(crate) mod ffi {
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use crate::window::PlatformWindowRc;
|
||||
|
||||
use super::*;
|
||||
use crate::window::WindowRc;
|
||||
|
||||
/// Call init() on the ItemVTable of each item in the item array.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_register_component(
|
||||
component: ComponentRefPin,
|
||||
item_array: Slice<vtable::VOffset<u8, ItemVTable, vtable::AllowPin>>,
|
||||
window_handle: *const crate::window::ffi::WindowRcOpaque,
|
||||
window_handle: *const crate::window::ffi::PlatformWindowRcOpaque,
|
||||
) {
|
||||
let window = &*(window_handle as *const WindowRc);
|
||||
let platform_window = &*(window_handle as *const PlatformWindowRc);
|
||||
super::register_component(
|
||||
core::pin::Pin::new_unchecked(&*(component.as_ptr() as *const u8)),
|
||||
item_array.as_slice(),
|
||||
window,
|
||||
platform_window,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -157,14 +161,14 @@ pub(crate) mod ffi {
|
|||
pub unsafe extern "C" fn slint_unregister_component(
|
||||
component: ComponentRefPin,
|
||||
item_array: Slice<vtable::VOffset<u8, ItemVTable, vtable::AllowPin>>,
|
||||
window_handle: *const crate::window::ffi::WindowRcOpaque,
|
||||
window_handle: *const crate::window::ffi::PlatformWindowRcOpaque,
|
||||
) {
|
||||
let window = &*(window_handle as *const WindowRc);
|
||||
let platform_window = &*(window_handle as *const PlatformWindowRc);
|
||||
super::unregister_component(
|
||||
core::pin::Pin::new_unchecked(&*(component.as_ptr() as *const u8)),
|
||||
core::pin::Pin::into_inner(component),
|
||||
item_array.as_slice(),
|
||||
window,
|
||||
platform_window,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ This module contains a simple helper type to measure the average number of frame
|
|||
*/
|
||||
|
||||
use crate::timers::*;
|
||||
use crate::window::PlatformWindowWeak;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryFrom;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::rc::Rc;
|
||||
|
||||
enum RefreshMode {
|
||||
Lazy, // render only when necessary (default)
|
||||
|
|
@ -59,7 +60,7 @@ pub struct RenderingMetricsCollector {
|
|||
refresh_mode: RefreshMode,
|
||||
output_console: bool,
|
||||
output_overlay: bool,
|
||||
window: Weak<crate::window::WindowInner>,
|
||||
platform_window: PlatformWindowWeak,
|
||||
}
|
||||
|
||||
impl RenderingMetricsCollector {
|
||||
|
|
@ -72,7 +73,7 @@ impl RenderingMetricsCollector {
|
|||
///
|
||||
/// If enabled, this will also print out some system information such as whether
|
||||
/// this is a debug or release build, as well as the provided winsys_info string.
|
||||
pub fn new(window: Weak<crate::window::WindowInner>, winsys_info: &str) -> Option<Rc<Self>> {
|
||||
pub fn new(platform_window: PlatformWindowWeak, winsys_info: &str) -> Option<Rc<Self>> {
|
||||
let options = match std::env::var("SLINT_DEBUG_PERFORMANCE") {
|
||||
Ok(var) => var,
|
||||
_ => return None,
|
||||
|
|
@ -101,7 +102,7 @@ impl RenderingMetricsCollector {
|
|||
refresh_mode,
|
||||
output_console,
|
||||
output_overlay,
|
||||
window,
|
||||
platform_window,
|
||||
});
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
|
|
@ -170,7 +171,7 @@ impl RenderingMetricsCollector {
|
|||
.borrow_mut()
|
||||
.push(FrameData { timestamp: instant::Instant::now(), metrics: renderer.metrics() });
|
||||
if matches!(self.refresh_mode, RefreshMode::FullSpeed) {
|
||||
if let Some(window) = self.window.upgrade() {
|
||||
if let Some(window) = self.platform_window.upgrade() {
|
||||
window.request_redraw();
|
||||
}
|
||||
crate::animations::CURRENT_ANIMATION_DRIVER
|
||||
|
|
|
|||
|
|
@ -345,7 +345,7 @@ pub trait ItemRenderer {
|
|||
(self.get_current_clip().intersects(&item_geometry), item_geometry)
|
||||
}
|
||||
|
||||
fn window(&self) -> crate::window::WindowRc;
|
||||
fn window(&self) -> &crate::api::Window;
|
||||
|
||||
/// Return the internal renderer
|
||||
fn as_any(&mut self) -> Option<&mut dyn core::any::Any>;
|
||||
|
|
@ -547,7 +547,7 @@ impl<'a, T: ItemRenderer> ItemRenderer for PartialRenderer<'a, T> {
|
|||
self.actual_renderer.draw_string(string, color)
|
||||
}
|
||||
|
||||
fn window(&self) -> crate::window::WindowRc {
|
||||
fn window(&self) -> &crate::api::Window {
|
||||
self.actual_renderer.window()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ impl Item for TouchArea {
|
|||
let hovering = !matches!(event, MouseEvent::Exit);
|
||||
Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(hovering);
|
||||
if hovering {
|
||||
window.set_mouse_cursor(self.mouse_cursor());
|
||||
window.platform_window().set_mouse_cursor(self.mouse_cursor());
|
||||
}
|
||||
InputEventFilterResult::ForwardAndInterceptGrab
|
||||
}
|
||||
|
|
@ -395,7 +395,7 @@ impl Item for TouchArea {
|
|||
) -> InputEventResult {
|
||||
if matches!(event, MouseEvent::Exit) {
|
||||
Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(false);
|
||||
window.set_mouse_cursor(MouseCursor::Default);
|
||||
window.platform_window().set_mouse_cursor(MouseCursor::Default);
|
||||
}
|
||||
if !self.enabled() {
|
||||
return InputEventResult::EventIgnored;
|
||||
|
|
|
|||
|
|
@ -62,8 +62,9 @@ impl Item for Text {
|
|||
}
|
||||
|
||||
fn layout_info(self: Pin<&Self>, orientation: Orientation, window: &WindowInner) -> LayoutInfo {
|
||||
let platform_window = window.platform_window();
|
||||
let implicit_size = |max_width| {
|
||||
window.renderer().text_size(
|
||||
platform_window.renderer().text_size(
|
||||
self.font_request(window),
|
||||
self.text().as_str(),
|
||||
max_width,
|
||||
|
|
@ -79,7 +80,7 @@ impl Item for Text {
|
|||
let implicit_size = implicit_size(None);
|
||||
let min = match self.overflow() {
|
||||
TextOverflow::Elide => implicit_size.width.min(
|
||||
window
|
||||
platform_window
|
||||
.renderer()
|
||||
.text_size(self.font_request(window), "…", None, window.scale_factor())
|
||||
.width,
|
||||
|
|
@ -231,7 +232,7 @@ impl Item for TextInput {
|
|||
fn layout_info(self: Pin<&Self>, orientation: Orientation, window: &WindowInner) -> LayoutInfo {
|
||||
let text = self.text();
|
||||
let implicit_size = |max_width| {
|
||||
window.renderer().text_size(
|
||||
window.platform_window().renderer().text_size(
|
||||
self.font_request(window),
|
||||
{
|
||||
if text.is_empty() {
|
||||
|
|
@ -290,10 +291,12 @@ impl Item for TextInput {
|
|||
if !self.enabled() {
|
||||
return InputEventResult::EventIgnored;
|
||||
}
|
||||
let platform_window = window.platform_window();
|
||||
match event {
|
||||
MouseEvent::Pressed { position, button: PointerEventButton::Left } => {
|
||||
let clicked_offset =
|
||||
window.renderer().text_input_byte_offset_for_position(self, position) as i32;
|
||||
platform_window.renderer().text_input_byte_offset_for_position(self, position)
|
||||
as i32;
|
||||
self.as_ref().pressed.set(true);
|
||||
self.as_ref().anchor_position.set(clicked_offset);
|
||||
self.set_cursor_position(clicked_offset, true, window);
|
||||
|
|
@ -306,8 +309,9 @@ impl Item for TextInput {
|
|||
}
|
||||
MouseEvent::Moved { position } => {
|
||||
if self.as_ref().pressed.get() {
|
||||
let clicked_offset =
|
||||
window.renderer().text_input_byte_offset_for_position(self, position)
|
||||
let clicked_offset = platform_window
|
||||
.renderer()
|
||||
.text_input_byte_offset_for_position(self, position)
|
||||
as i32;
|
||||
self.set_cursor_position(clicked_offset, true, window);
|
||||
}
|
||||
|
|
@ -445,12 +449,12 @@ impl Item for TextInput {
|
|||
FocusEvent::FocusIn | FocusEvent::WindowReceivedFocus => {
|
||||
self.has_focus.set(true);
|
||||
self.show_cursor(window);
|
||||
window.show_virtual_keyboard(self.input_type());
|
||||
window.platform_window().show_virtual_keyboard(self.input_type());
|
||||
}
|
||||
FocusEvent::FocusOut | FocusEvent::WindowLostFocus => {
|
||||
self.has_focus.set(false);
|
||||
self.hide_cursor();
|
||||
window.hide_virtual_keyboard();
|
||||
window.platform_window().hide_virtual_keyboard();
|
||||
}
|
||||
}
|
||||
FocusEventResult::FocusAccepted
|
||||
|
|
@ -544,15 +548,16 @@ impl TextInput {
|
|||
return false;
|
||||
}
|
||||
|
||||
let platform_window = window.platform_window();
|
||||
let renderer = platform_window.renderer();
|
||||
|
||||
let last_cursor_pos = (self.cursor_position() as usize).max(0).min(text.len());
|
||||
|
||||
let mut grapheme_cursor =
|
||||
unicode_segmentation::GraphemeCursor::new(last_cursor_pos, text.len(), true);
|
||||
|
||||
let font_height = window
|
||||
.renderer()
|
||||
.text_size(self.font_request(window), " ", None, window.scale_factor())
|
||||
.height;
|
||||
let font_height =
|
||||
renderer.text_size(self.font_request(window), " ", None, window.scale_factor()).height;
|
||||
|
||||
let mut reset_preferred_x_pos = true;
|
||||
|
||||
|
|
@ -567,23 +572,23 @@ impl TextInput {
|
|||
reset_preferred_x_pos = false;
|
||||
|
||||
let cursor_rect =
|
||||
window.renderer().text_input_cursor_rect_for_byte_offset(self, last_cursor_pos);
|
||||
renderer.text_input_cursor_rect_for_byte_offset(self, last_cursor_pos);
|
||||
let mut cursor_xy_pos = cursor_rect.center();
|
||||
|
||||
cursor_xy_pos.y += font_height;
|
||||
cursor_xy_pos.x = self.preferred_x_pos.get();
|
||||
window.renderer().text_input_byte_offset_for_position(self, cursor_xy_pos)
|
||||
renderer.text_input_byte_offset_for_position(self, cursor_xy_pos)
|
||||
}
|
||||
TextCursorDirection::PreviousLine => {
|
||||
reset_preferred_x_pos = false;
|
||||
|
||||
let cursor_rect =
|
||||
window.renderer().text_input_cursor_rect_for_byte_offset(self, last_cursor_pos);
|
||||
renderer.text_input_cursor_rect_for_byte_offset(self, last_cursor_pos);
|
||||
let mut cursor_xy_pos = cursor_rect.center();
|
||||
|
||||
cursor_xy_pos.y -= font_height;
|
||||
cursor_xy_pos.x = self.preferred_x_pos.get();
|
||||
window.renderer().text_input_byte_offset_for_position(self, cursor_xy_pos)
|
||||
renderer.text_input_byte_offset_for_position(self, cursor_xy_pos)
|
||||
}
|
||||
TextCursorDirection::PreviousCharacter => {
|
||||
let mut i = last_cursor_pos;
|
||||
|
|
@ -615,19 +620,19 @@ impl TextInput {
|
|||
}
|
||||
TextCursorDirection::StartOfLine => {
|
||||
let cursor_rect =
|
||||
window.renderer().text_input_cursor_rect_for_byte_offset(self, last_cursor_pos);
|
||||
renderer.text_input_cursor_rect_for_byte_offset(self, last_cursor_pos);
|
||||
let mut cursor_xy_pos = cursor_rect.center();
|
||||
|
||||
cursor_xy_pos.x = 0 as Coord;
|
||||
window.renderer().text_input_byte_offset_for_position(self, cursor_xy_pos)
|
||||
renderer.text_input_byte_offset_for_position(self, cursor_xy_pos)
|
||||
}
|
||||
TextCursorDirection::EndOfLine => {
|
||||
let cursor_rect =
|
||||
window.renderer().text_input_cursor_rect_for_byte_offset(self, last_cursor_pos);
|
||||
renderer.text_input_cursor_rect_for_byte_offset(self, last_cursor_pos);
|
||||
let mut cursor_xy_pos = cursor_rect.center();
|
||||
|
||||
cursor_xy_pos.x = Coord::MAX;
|
||||
window.renderer().text_input_byte_offset_for_position(self, cursor_xy_pos)
|
||||
renderer.text_input_byte_offset_for_position(self, cursor_xy_pos)
|
||||
}
|
||||
TextCursorDirection::StartOfParagraph => text
|
||||
.as_bytes()
|
||||
|
|
@ -674,6 +679,7 @@ impl TextInput {
|
|||
self.cursor_position.set(new_position);
|
||||
if new_position >= 0 {
|
||||
let pos = window
|
||||
.platform_window()
|
||||
.renderer()
|
||||
.text_input_cursor_rect_for_byte_offset(self, new_position as usize)
|
||||
.origin;
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ use crate::lengths::{
|
|||
};
|
||||
use crate::renderer::Renderer;
|
||||
use crate::textlayout::{FontMetrics as _, TextParagraphLayout};
|
||||
use crate::window::WindowHandleAccess;
|
||||
use crate::window::{WindowHandleAccess, WindowInner};
|
||||
use crate::{Color, Coord, ImageInner, StaticTextures};
|
||||
use alloc::rc::Rc;
|
||||
use alloc::{vec, vec::Vec};
|
||||
use core::cell::{Cell, RefCell};
|
||||
use core::pin::Pin;
|
||||
|
|
@ -105,7 +104,7 @@ impl SoftwareRenderer {
|
|||
buffer: &mut [impl TargetPixel],
|
||||
buffer_stride: PhysicalLength,
|
||||
) {
|
||||
let window = window.window_handle().clone();
|
||||
let window = window.window_handle();
|
||||
let factor = ScaleFactor::new(window.scale_factor());
|
||||
let (size, background) = if let Some(window_item) =
|
||||
window.window_item().as_ref().map(|item| item.as_pin_ref())
|
||||
|
|
@ -127,7 +126,7 @@ impl SoftwareRenderer {
|
|||
let buffer_renderer = SceneBuilder::new(
|
||||
size,
|
||||
factor,
|
||||
window.clone(),
|
||||
window,
|
||||
RenderToBuffer { buffer, stride: buffer_stride },
|
||||
);
|
||||
let mut renderer = crate::item_rendering::PartialRenderer::new(
|
||||
|
|
@ -234,13 +233,13 @@ impl Renderer for SoftwareRenderer {
|
|||
}
|
||||
|
||||
fn render_window_frame_by_line(
|
||||
runtime_window: Rc<crate::window::WindowInner>,
|
||||
window: &WindowInner,
|
||||
background: Color,
|
||||
size: PhysicalSize,
|
||||
renderer: &SoftwareRenderer,
|
||||
mut line_buffer: impl LineBufferProvider,
|
||||
) {
|
||||
let mut scene = prepare_scene(runtime_window, size, renderer);
|
||||
let mut scene = prepare_scene(window, size, renderer);
|
||||
|
||||
let dirty_region = scene.dirty_region;
|
||||
|
||||
|
|
@ -556,14 +555,9 @@ struct RoundedRectangle {
|
|||
bottom_clip: PhysicalLength,
|
||||
}
|
||||
|
||||
fn prepare_scene(
|
||||
runtime_window: Rc<crate::window::WindowInner>,
|
||||
size: PhysicalSize,
|
||||
swrenderer: &SoftwareRenderer,
|
||||
) -> Scene {
|
||||
let factor = ScaleFactor::new(runtime_window.scale_factor());
|
||||
let prepare_scene =
|
||||
SceneBuilder::new(size, factor, runtime_window.clone(), PrepareScene::default());
|
||||
fn prepare_scene(window: &WindowInner, size: PhysicalSize, swrenderer: &SoftwareRenderer) -> Scene {
|
||||
let factor = ScaleFactor::new(window.scale_factor());
|
||||
let prepare_scene = SceneBuilder::new(size, factor, window, PrepareScene::default());
|
||||
let mut renderer = crate::item_rendering::PartialRenderer::new(
|
||||
&swrenderer.partial_cache,
|
||||
swrenderer.force_dirty.take(),
|
||||
|
|
@ -571,7 +565,7 @@ fn prepare_scene(
|
|||
);
|
||||
|
||||
let mut dirty_region = PhysicalRect::default();
|
||||
runtime_window.draw_contents(|components| {
|
||||
window.draw_contents(|components| {
|
||||
for (component, origin) in components {
|
||||
renderer.compute_dirty_regions(component, *origin);
|
||||
}
|
||||
|
|
@ -717,19 +711,19 @@ impl ProcessScene for PrepareScene {
|
|||
}
|
||||
}
|
||||
|
||||
struct SceneBuilder<T> {
|
||||
struct SceneBuilder<'a, T> {
|
||||
processor: T,
|
||||
state_stack: Vec<RenderState>,
|
||||
current_state: RenderState,
|
||||
scale_factor: ScaleFactor,
|
||||
window: Rc<crate::window::WindowInner>,
|
||||
window: &'a WindowInner,
|
||||
}
|
||||
|
||||
impl<T: ProcessScene> SceneBuilder<T> {
|
||||
impl<'a, T: ProcessScene> SceneBuilder<'a, T> {
|
||||
fn new(
|
||||
size: PhysicalSize,
|
||||
scale_factor: ScaleFactor,
|
||||
window: Rc<crate::window::WindowInner>,
|
||||
window: &'a WindowInner,
|
||||
processor: T,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
|
@ -900,7 +894,7 @@ struct RenderState {
|
|||
clip: LogicalRect,
|
||||
}
|
||||
|
||||
impl<T: ProcessScene> crate::item_rendering::ItemRenderer for SceneBuilder<T> {
|
||||
impl<'a, T: ProcessScene> crate::item_rendering::ItemRenderer for SceneBuilder<'a, T> {
|
||||
fn draw_rectangle(&mut self, rect: Pin<&crate::items::Rectangle>, _: &ItemRc) {
|
||||
let geom = LogicalRect::new(LogicalPoint::default(), rect.logical_geometry().size_length());
|
||||
if self.should_draw(&geom) {
|
||||
|
|
@ -1060,7 +1054,7 @@ impl<T: ProcessScene> crate::item_rendering::ItemRenderer for SceneBuilder<T> {
|
|||
return;
|
||||
}
|
||||
|
||||
let font_request = text.font_request(&self.window);
|
||||
let font_request = text.font_request(self.window);
|
||||
let font = fonts::match_font(&font_request, self.scale_factor);
|
||||
let layout = fonts::text_layout_for_font(&font, &font_request, self.scale_factor);
|
||||
|
||||
|
|
@ -1199,7 +1193,7 @@ impl<T: ProcessScene> crate::item_rendering::ItemRenderer for SceneBuilder<T> {
|
|||
todo!()
|
||||
}
|
||||
|
||||
fn window(&self) -> crate::window::WindowRc {
|
||||
fn window(&self) -> &crate::api::Window {
|
||||
unreachable!("this backend don't query the window")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#![allow(unsafe_code)]
|
||||
|
||||
use crate::input::{KeyEvent, KeyEventType, KeyboardModifiers, MouseEvent};
|
||||
use crate::window::WindowRc;
|
||||
use crate::Coord;
|
||||
use crate::SharedString;
|
||||
|
||||
|
|
@ -29,7 +28,7 @@ pub extern "C" fn slint_send_mouse_click(
|
|||
component: &crate::component::ComponentRc,
|
||||
x: Coord,
|
||||
y: Coord,
|
||||
window: &WindowRc,
|
||||
window: &crate::window::WindowInner,
|
||||
) {
|
||||
let mut state = crate::input::MouseInputState::default();
|
||||
let position = euclid::point2(x, y);
|
||||
|
|
@ -60,7 +59,7 @@ pub extern "C" fn slint_send_mouse_click(
|
|||
pub extern "C" fn send_keyboard_string_sequence(
|
||||
sequence: &crate::SharedString,
|
||||
modifiers: KeyboardModifiers,
|
||||
window: &WindowRc,
|
||||
window: &crate::window::WindowInner,
|
||||
) {
|
||||
for ch in sequence.chars() {
|
||||
let mut modifiers = modifiers;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ pub trait PlatformWindow {
|
|||
///
|
||||
/// If this function return None (the default implementation), then the
|
||||
/// popup will be rendered within the window itself.
|
||||
fn create_popup(&self, _geometry: Rect) -> Option<Window> {
|
||||
fn create_popup(&self, _geometry: Rect) -> Option<PlatformWindowRc> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
@ -117,9 +117,8 @@ pub trait PlatformWindow {
|
|||
/// Return the renderer
|
||||
fn renderer(&self) -> &dyn Renderer;
|
||||
|
||||
/// Temporary function to provide access to the WindowInner. This should, in the future, return
|
||||
/// a &Window
|
||||
fn window(&self) -> WindowRc;
|
||||
/// Returns the window API.
|
||||
fn window(&self) -> &Window;
|
||||
}
|
||||
|
||||
struct WindowPropertiesTracker {
|
||||
|
|
@ -149,7 +148,7 @@ impl crate::properties::PropertyDirtyHandler for WindowRedrawTracker {
|
|||
/// This enum describes the different ways a popup can be rendered by the back-end.
|
||||
pub enum PopupWindowLocation {
|
||||
/// The popup is rendered in its own top-level window that is know to the windowing system.
|
||||
TopLevel(Window),
|
||||
TopLevel(PlatformWindowRc),
|
||||
/// The popup is rendered as an embedded child window at the given position.
|
||||
ChildWindow(Point),
|
||||
}
|
||||
|
|
@ -165,13 +164,11 @@ pub struct PopupWindow {
|
|||
|
||||
/// Inner datastructure for the [`crate::api::Window`]
|
||||
pub struct WindowInner {
|
||||
/// FIXME! use Box instead;
|
||||
platform_window: once_cell::unsync::OnceCell<Rc<dyn PlatformWindow>>,
|
||||
platform_window_weak: Weak<dyn PlatformWindow>,
|
||||
component: RefCell<ComponentWeak>,
|
||||
mouse_input_state: Cell<MouseInputState>,
|
||||
redraw_tracker: once_cell::unsync::OnceCell<Pin<Box<PropertyTracker<WindowRedrawTracker>>>>,
|
||||
window_properties_tracker:
|
||||
once_cell::unsync::OnceCell<Pin<Box<PropertyTracker<WindowPropertiesTracker>>>>,
|
||||
redraw_tracker: Pin<Box<PropertyTracker<WindowRedrawTracker>>>,
|
||||
window_properties_tracker: Pin<Box<PropertyTracker<WindowPropertiesTracker>>>,
|
||||
/// Gets dirty when the layout restrictions, or some other property of the windows change
|
||||
meta_properties_tracker: Pin<Rc<PropertyTracker>>,
|
||||
|
||||
|
|
@ -197,35 +194,16 @@ impl Drop for WindowInner {
|
|||
|
||||
impl WindowInner {
|
||||
/// Create a new instance of the window, given the platform_window factory fn
|
||||
pub fn new(
|
||||
platform_window_fn: impl FnOnce(&Weak<WindowInner>) -> Rc<dyn PlatformWindow>,
|
||||
) -> Rc<Self> {
|
||||
pub fn new(platform_window_weak: Weak<dyn PlatformWindow>) -> Self {
|
||||
#![allow(unused_mut)]
|
||||
let window = Rc::new(Self {
|
||||
platform_window: Default::default(),
|
||||
component: Default::default(),
|
||||
mouse_input_state: Default::default(),
|
||||
redraw_tracker: Default::default(),
|
||||
window_properties_tracker: Default::default(),
|
||||
meta_properties_tracker: Rc::pin(Default::default()),
|
||||
focus_item: Default::default(),
|
||||
cursor_blinker: Default::default(),
|
||||
scale_factor: Box::pin(Property::new_named(1., "i_slint_core::Window::scale_factor")),
|
||||
active: Box::pin(Property::new_named(false, "i_slint_core::Window::active")),
|
||||
active_popup: Default::default(),
|
||||
close_requested: Default::default(),
|
||||
inner_size: Default::default(),
|
||||
});
|
||||
let window_weak = Rc::downgrade(&window);
|
||||
window.platform_window.set(platform_window_fn(&window_weak)).ok().unwrap();
|
||||
|
||||
let mut window_properties_tracker =
|
||||
PropertyTracker::new_with_dirty_handler(WindowPropertiesTracker {
|
||||
platform_window_weak: Rc::downgrade(&window.platform_window.get().unwrap()),
|
||||
platform_window_weak: platform_window_weak.clone(),
|
||||
});
|
||||
|
||||
let mut redraw_tracker = PropertyTracker::new_with_dirty_handler(WindowRedrawTracker {
|
||||
platform_window_weak: Rc::downgrade(&window.platform_window.get().unwrap()),
|
||||
platform_window_weak: platform_window_weak.clone(),
|
||||
});
|
||||
|
||||
#[cfg(slint_debug_property)]
|
||||
|
|
@ -235,10 +213,21 @@ impl WindowInner {
|
|||
redraw_tracker.set_debug_name("i_slint_core::Window::redraw_tracker".into());
|
||||
}
|
||||
|
||||
// We need to use a OnceCell only so we can have a cycle with the Weak.
|
||||
// Rust 1.60's Rc::new_cyclic would allow to avoid that.
|
||||
window.window_properties_tracker.set(Box::pin(window_properties_tracker)).ok().unwrap();
|
||||
window.redraw_tracker.set(Box::pin(redraw_tracker)).ok().unwrap();
|
||||
let window = Self {
|
||||
platform_window_weak,
|
||||
component: Default::default(),
|
||||
mouse_input_state: Default::default(),
|
||||
redraw_tracker: Box::pin(redraw_tracker),
|
||||
window_properties_tracker: Box::pin(window_properties_tracker),
|
||||
meta_properties_tracker: Rc::pin(Default::default()),
|
||||
focus_item: Default::default(),
|
||||
cursor_blinker: Default::default(),
|
||||
scale_factor: Box::pin(Property::new_named(1., "i_slint_core::Window::scale_factor")),
|
||||
active: Box::pin(Property::new_named(false, "i_slint_core::Window::active")),
|
||||
active_popup: Default::default(),
|
||||
close_requested: Default::default(),
|
||||
inner_size: Default::default(),
|
||||
};
|
||||
|
||||
window
|
||||
}
|
||||
|
|
@ -251,8 +240,9 @@ impl WindowInner {
|
|||
self.mouse_input_state.replace(Default::default());
|
||||
self.component.replace(ComponentRc::downgrade(component));
|
||||
self.meta_properties_tracker.set_dirty(); // component changed, layout constraints for sure must be re-calculated
|
||||
self.request_window_properties_update();
|
||||
self.request_redraw();
|
||||
let platform_window = self.platform_window();
|
||||
platform_window.request_window_properties_update();
|
||||
platform_window.request_redraw();
|
||||
}
|
||||
|
||||
/// return the component.
|
||||
|
|
@ -314,7 +304,7 @@ impl WindowInner {
|
|||
self.mouse_input_state.set(crate::input::process_mouse_input(
|
||||
component,
|
||||
event,
|
||||
&self.window_rc(),
|
||||
self,
|
||||
self.mouse_input_state.take(),
|
||||
));
|
||||
|
||||
|
|
@ -339,7 +329,7 @@ impl WindowInner {
|
|||
// Reset the focus... not great, but better than keeping it.
|
||||
self.take_focus_item();
|
||||
} else {
|
||||
if focus_item.borrow().as_ref().key_event(event, &self.window_rc())
|
||||
if focus_item.borrow().as_ref().key_event(event, self)
|
||||
== crate::input::KeyEventResult::EventAccepted
|
||||
{
|
||||
return;
|
||||
|
|
@ -377,7 +367,7 @@ impl WindowInner {
|
|||
pub fn set_focus_item(&self, focus_item: &ItemRc) {
|
||||
let old = self.take_focus_item();
|
||||
let new = self.clone().move_focus(focus_item.clone(), next_focus_item);
|
||||
self.platform_window.get().unwrap().handle_focus_change(old, new);
|
||||
self.platform_window().handle_focus_change(old, new);
|
||||
}
|
||||
|
||||
/// Sets the focus on the window to true or false, depending on the have_focus argument.
|
||||
|
|
@ -390,7 +380,7 @@ impl WindowInner {
|
|||
};
|
||||
|
||||
if let Some(focus_item) = self.focus_item.borrow().upgrade() {
|
||||
focus_item.borrow().as_ref().focus_event(&event, &self.window_rc());
|
||||
focus_item.borrow().as_ref().focus_event(&event, self);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -401,10 +391,7 @@ impl WindowInner {
|
|||
let focus_item = self.focus_item.take();
|
||||
|
||||
if let Some(focus_item_rc) = focus_item.upgrade() {
|
||||
focus_item_rc
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.focus_event(&crate::input::FocusEvent::FocusOut, &self.window_rc());
|
||||
focus_item_rc.borrow().as_ref().focus_event(&crate::input::FocusEvent::FocusOut, self);
|
||||
Some(focus_item_rc)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -418,9 +405,7 @@ impl WindowInner {
|
|||
match item {
|
||||
Some(item) => {
|
||||
*self.focus_item.borrow_mut() = item.downgrade();
|
||||
item.borrow()
|
||||
.as_ref()
|
||||
.focus_event(&crate::input::FocusEvent::FocusIn, &self.window_rc())
|
||||
item.borrow().as_ref().focus_event(&crate::input::FocusEvent::FocusIn, self)
|
||||
}
|
||||
None => {
|
||||
*self.focus_item.borrow_mut() = Default::default();
|
||||
|
|
@ -457,7 +442,7 @@ impl WindowInner {
|
|||
.map(next_focus_item)
|
||||
.unwrap_or_else(|| ItemRc::new(component, 0));
|
||||
let end_item = self.move_focus(start_item.clone(), next_focus_item);
|
||||
self.platform_window.get().unwrap().handle_focus_change(Some(start_item), end_item);
|
||||
self.platform_window().handle_focus_change(Some(start_item), end_item);
|
||||
}
|
||||
|
||||
/// Move keyboard focus to the previous item.
|
||||
|
|
@ -467,7 +452,7 @@ impl WindowInner {
|
|||
self.take_focus_item().unwrap_or_else(|| ItemRc::new(component, 0)),
|
||||
);
|
||||
let end_item = self.move_focus(start_item.clone(), previous_focus_item);
|
||||
self.platform_window.get().unwrap().handle_focus_change(Some(start_item), end_item);
|
||||
self.platform_window().handle_focus_change(Some(start_item), end_item);
|
||||
}
|
||||
|
||||
/// Marks the window to be the active window. This typically coincides with the keyboard
|
||||
|
|
@ -486,19 +471,14 @@ impl WindowInner {
|
|||
/// If the component's root item is a Window element, then this function synchronizes its properties, such as the title
|
||||
/// for example, with the properties known to the windowing system.
|
||||
pub fn update_window_properties(&self) {
|
||||
if let Some(window_properties_tracker) = self.window_properties_tracker.get() {
|
||||
// No `if !dirty { return; }` check here because the backend window may be newly mapped and not up-to-date, so force
|
||||
// an evaluation.
|
||||
window_properties_tracker.as_ref().evaluate_as_dependency_root(|| {
|
||||
self.window_properties_tracker.as_ref().evaluate_as_dependency_root(|| {
|
||||
if let Some(window_item) = self.window_item() {
|
||||
self.platform_window
|
||||
.get()
|
||||
.unwrap()
|
||||
.apply_window_properties(window_item.as_pin_ref());
|
||||
self.platform_window().apply_window_properties(window_item.as_pin_ref());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls the render_components to render the main component and any sub-window components, tracked by a
|
||||
/// property dependency tracker.
|
||||
|
|
@ -508,7 +488,7 @@ impl WindowInner {
|
|||
let component = ComponentRc::borrow_pin(&component_rc);
|
||||
|
||||
self.meta_properties_tracker.as_ref().evaluate_if_dirty(|| {
|
||||
self.apply_geometry_constraint(
|
||||
self.platform_window().apply_geometry_constraint(
|
||||
component.as_ref().layout_info(crate::layout::Orientation::Horizontal),
|
||||
component.as_ref().layout_info(crate::layout::Orientation::Vertical),
|
||||
);
|
||||
|
|
@ -532,23 +512,19 @@ impl WindowInner {
|
|||
}
|
||||
};
|
||||
|
||||
if let Some(redraw_tracker) = self.redraw_tracker.get() {
|
||||
redraw_tracker.as_ref().evaluate_as_dependency_root(draw_fn)
|
||||
} else {
|
||||
draw_fn()
|
||||
}
|
||||
self.redraw_tracker.as_ref().evaluate_as_dependency_root(draw_fn)
|
||||
}
|
||||
|
||||
/// Registers the window with the windowing system, in order to render the component's items and react
|
||||
/// to input events once the event loop spins.
|
||||
pub fn show(&self) {
|
||||
self.platform_window.get().unwrap().clone().show();
|
||||
self.platform_window().show();
|
||||
self.update_window_properties();
|
||||
}
|
||||
|
||||
/// De-registers the window with the windowing system.
|
||||
pub fn hide(&self) {
|
||||
self.platform_window.get().unwrap().clone().hide();
|
||||
self.platform_window().hide();
|
||||
}
|
||||
|
||||
/// Show a popup at the given position relative to the item
|
||||
|
|
@ -603,16 +579,15 @@ impl WindowInner {
|
|||
height_property.set(size.height);
|
||||
};
|
||||
|
||||
let location =
|
||||
match self.platform_window.get().unwrap().create_popup(Rect::new(position, size)) {
|
||||
let location = match self.platform_window().create_popup(Rect::new(position, size)) {
|
||||
None => {
|
||||
self.meta_properties_tracker.set_dirty();
|
||||
PopupWindowLocation::ChildWindow(position)
|
||||
}
|
||||
|
||||
Some(window) => {
|
||||
window.window_handle().set_component(popup_componentrc);
|
||||
PopupWindowLocation::TopLevel(window)
|
||||
Some(platform_window) => {
|
||||
platform_window.window().window_handle().set_component(popup_componentrc);
|
||||
PopupWindowLocation::TopLevel(platform_window)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -632,8 +607,9 @@ impl WindowInner {
|
|||
.translate(offset.to_vector());
|
||||
|
||||
if !popup_region.is_empty() {
|
||||
self.renderer().mark_dirty_region(popup_region.to_box2d());
|
||||
self.request_redraw();
|
||||
let platform_window = self.platform_window();
|
||||
platform_window.renderer().mark_dirty_region(popup_region.to_box2d());
|
||||
platform_window.request_redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -696,29 +672,22 @@ impl WindowInner {
|
|||
}
|
||||
}
|
||||
|
||||
/// Temporary function to turn an `&WindowInner` into an `Rc<WindowInner>` for use with the item vtable functions.
|
||||
pub fn window_rc(&self) -> WindowRc {
|
||||
self.platform_window.get().unwrap().as_ref().window()
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Deref for WindowInner {
|
||||
type Target = dyn PlatformWindow;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.platform_window.get().unwrap().as_ref()
|
||||
/// Returns the upgraded rlatform window.
|
||||
pub fn platform_window(&self) -> PlatformWindowRc {
|
||||
self.platform_window_weak.upgrade().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Internal trait used by generated code to access window internals.
|
||||
pub trait WindowHandleAccess {
|
||||
/// Returns a reference to the window implementation.
|
||||
fn window_handle(&self) -> &Rc<WindowInner>;
|
||||
fn window_handle(&self) -> &WindowInner;
|
||||
}
|
||||
|
||||
/// Internal alias for Rc<Window> so that it can be used in the vtable
|
||||
/// functions and generate a good signature.
|
||||
pub type WindowRc = Rc<WindowInner>;
|
||||
/// Internal alias for Rc<dyn PlatformWindow>.
|
||||
pub type PlatformWindowRc = Rc<dyn PlatformWindow>;
|
||||
/// Internal convenience alias for Weak<dyn PlatformWindow>.
|
||||
pub type PlatformWindowWeak = Weak<dyn PlatformWindow>;
|
||||
|
||||
/// This module contains the functions needed to interface with the event loop and window traits
|
||||
/// from outside the Rust language.
|
||||
|
|
@ -742,101 +711,112 @@ pub mod ffi {
|
|||
#[allow(non_camel_case_types)]
|
||||
type c_void = ();
|
||||
|
||||
/// Same layout as WindowRc
|
||||
/// Same layout as PlatformWindowRc
|
||||
#[repr(C)]
|
||||
pub struct WindowRcOpaque(*const c_void);
|
||||
pub struct PlatformWindowRcOpaque(*const c_void, *const c_void);
|
||||
|
||||
/// Releases the reference to the windowrc held by handle.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_drop(handle: *mut WindowRcOpaque) {
|
||||
assert_eq!(core::mem::size_of::<WindowRc>(), core::mem::size_of::<WindowRcOpaque>());
|
||||
core::ptr::read(handle as *mut WindowRc);
|
||||
pub unsafe extern "C" fn slint_windowrc_drop(handle: *mut PlatformWindowRcOpaque) {
|
||||
assert_eq!(
|
||||
core::mem::size_of::<PlatformWindowRc>(),
|
||||
core::mem::size_of::<PlatformWindowRcOpaque>()
|
||||
);
|
||||
core::ptr::read(handle as *mut PlatformWindowRc);
|
||||
}
|
||||
|
||||
/// Releases the reference to the component window held by handle.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_clone(
|
||||
source: *const WindowRcOpaque,
|
||||
target: *mut WindowRcOpaque,
|
||||
source: *const PlatformWindowRcOpaque,
|
||||
target: *mut PlatformWindowRcOpaque,
|
||||
) {
|
||||
assert_eq!(core::mem::size_of::<WindowRc>(), core::mem::size_of::<WindowRcOpaque>());
|
||||
let window = &*(source as *const WindowRc);
|
||||
core::ptr::write(target as *mut WindowRc, window.clone());
|
||||
assert_eq!(
|
||||
core::mem::size_of::<PlatformWindowRc>(),
|
||||
core::mem::size_of::<PlatformWindowRcOpaque>()
|
||||
);
|
||||
let window = &*(source as *const PlatformWindowRc);
|
||||
core::ptr::write(target as *mut PlatformWindowRc, window.clone());
|
||||
}
|
||||
|
||||
/// Spins an event loop and renders the items of the provided component in this window.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_show(handle: *const WindowRcOpaque) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.show();
|
||||
pub unsafe extern "C" fn slint_windowrc_show(handle: *const PlatformWindowRcOpaque) {
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.show();
|
||||
}
|
||||
|
||||
/// Spins an event loop and renders the items of the provided component in this window.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_hide(handle: *const WindowRcOpaque) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
pub unsafe extern "C" fn slint_windowrc_hide(handle: *const PlatformWindowRcOpaque) {
|
||||
let window = &*(handle as *const PlatformWindowRc);
|
||||
window.hide();
|
||||
}
|
||||
|
||||
/// Returns the window scale factor.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_get_scale_factor(handle: *const WindowRcOpaque) -> f32 {
|
||||
assert_eq!(core::mem::size_of::<WindowRc>(), core::mem::size_of::<WindowRcOpaque>());
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.scale_factor()
|
||||
pub unsafe extern "C" fn slint_windowrc_get_scale_factor(
|
||||
handle: *const PlatformWindowRcOpaque,
|
||||
) -> f32 {
|
||||
assert_eq!(
|
||||
core::mem::size_of::<PlatformWindowRc>(),
|
||||
core::mem::size_of::<PlatformWindowRcOpaque>()
|
||||
);
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.window().window_handle().scale_factor()
|
||||
}
|
||||
|
||||
/// Sets the window scale factor, merely for testing purposes.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_set_scale_factor(
|
||||
handle: *const WindowRcOpaque,
|
||||
handle: *const PlatformWindowRcOpaque,
|
||||
value: f32,
|
||||
) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.set_scale_factor(value)
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.window().window_handle().set_scale_factor(value)
|
||||
}
|
||||
|
||||
/// Sets the focus item.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_set_focus_item(
|
||||
handle: *const WindowRcOpaque,
|
||||
handle: *const PlatformWindowRcOpaque,
|
||||
focus_item: &ItemRc,
|
||||
) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.set_focus_item(focus_item)
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.window().window_handle().set_focus_item(focus_item)
|
||||
}
|
||||
|
||||
/// Associates the window with the given component.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_set_component(
|
||||
handle: *const WindowRcOpaque,
|
||||
handle: *const PlatformWindowRcOpaque,
|
||||
component: &ComponentRc,
|
||||
) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.set_component(component)
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.window().window_handle().set_component(component)
|
||||
}
|
||||
|
||||
/// Show a popup.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_show_popup(
|
||||
handle: *const WindowRcOpaque,
|
||||
handle: *const PlatformWindowRcOpaque,
|
||||
popup: &ComponentRc,
|
||||
position: crate::graphics::Point,
|
||||
parent_item: &ItemRc,
|
||||
) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.show_popup(popup, position, parent_item);
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.window().window_handle().show_popup(popup, position, parent_item);
|
||||
}
|
||||
/// Close the current popup
|
||||
pub unsafe extern "C" fn slint_windowrc_close_popup(handle: *const WindowRcOpaque) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.close_popup();
|
||||
pub unsafe extern "C" fn slint_windowrc_close_popup(handle: *const PlatformWindowRcOpaque) {
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.window().window_handle().close_popup();
|
||||
}
|
||||
|
||||
/// C binding to the set_rendering_notifier() API of Window
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_set_rendering_notifier(
|
||||
handle: *const WindowRcOpaque,
|
||||
handle: *const PlatformWindowRcOpaque,
|
||||
callback: extern "C" fn(
|
||||
rendering_state: RenderingState,
|
||||
graphics_api: GraphicsAPI,
|
||||
|
|
@ -872,7 +852,7 @@ pub mod ffi {
|
|||
}
|
||||
}
|
||||
|
||||
let window = &*(handle as *const WindowRc);
|
||||
let window = &*(handle as *const PlatformWindowRc);
|
||||
match window.renderer().set_rendering_notifier(Box::new(CNotifier {
|
||||
callback,
|
||||
drop_user_data,
|
||||
|
|
@ -889,7 +869,7 @@ pub mod ffi {
|
|||
/// C binding to the on_close_requested() API of Window
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_on_close_requested(
|
||||
handle: *const WindowRcOpaque,
|
||||
handle: *const PlatformWindowRcOpaque,
|
||||
callback: extern "C" fn(user_data: *mut c_void) -> CloseRequestResponse,
|
||||
drop_user_data: extern "C" fn(user_data: *mut c_void),
|
||||
user_data: *mut c_void,
|
||||
|
|
@ -914,26 +894,26 @@ pub mod ffi {
|
|||
|
||||
let with_user_data = WithUserData { callback, drop_user_data, user_data };
|
||||
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.on_close_requested(move || with_user_data.call());
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.window().on_close_requested(move || with_user_data.call());
|
||||
}
|
||||
|
||||
/// This function issues a request to the windowing system to redraw the contents of the window.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_request_redraw(handle: *const WindowRcOpaque) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.request_redraw();
|
||||
pub unsafe extern "C" fn slint_windowrc_request_redraw(handle: *const PlatformWindowRcOpaque) {
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.request_redraw();
|
||||
}
|
||||
|
||||
/// Returns the position of the window on the screen, in physical screen coordinates and including
|
||||
/// a window frame (if present).
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_position(
|
||||
handle: *const WindowRcOpaque,
|
||||
handle: *const PlatformWindowRcOpaque,
|
||||
pos: &mut euclid::default::Point2D<i32>,
|
||||
) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
*pos = window.position().to_untyped()
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
*pos = platform_window.position().to_untyped()
|
||||
}
|
||||
|
||||
/// Sets the position of the window on the screen, in physical screen coordinates and including
|
||||
|
|
@ -941,29 +921,29 @@ pub mod ffi {
|
|||
/// Note that on some windowing systems, such as Wayland, this functionality is not available.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_set_position(
|
||||
handle: *const WindowRcOpaque,
|
||||
handle: *const PlatformWindowRcOpaque,
|
||||
pos: &euclid::default::Point2D<i32>,
|
||||
) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.set_position(euclid::Point2D::from_untyped(*pos));
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.set_position(euclid::Point2D::from_untyped(*pos));
|
||||
}
|
||||
|
||||
/// Returns the size of the window on the screen, in physical screen coordinates and excluding
|
||||
/// a window frame (if present).
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_size(handle: *const WindowRcOpaque) -> IntSize {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.inner_size.get().to_untyped()
|
||||
pub unsafe extern "C" fn slint_windowrc_size(handle: *const PlatformWindowRcOpaque) -> IntSize {
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.window().window_handle().inner_size.get().to_untyped().cast()
|
||||
}
|
||||
|
||||
/// Resizes the window to the specified size on the screen, in physical pixels and excluding
|
||||
/// a window frame (if present).
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_set_size(
|
||||
handle: *const WindowRcOpaque,
|
||||
handle: *const PlatformWindowRcOpaque,
|
||||
size: &IntSize,
|
||||
) {
|
||||
let window = &*(handle as *const WindowRc);
|
||||
window.set_inner_size([size.width, size.height].into());
|
||||
let platform_window = &*(handle as *const PlatformWindowRc);
|
||||
platform_window.set_inner_size([size.width, size.height].into());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -560,11 +560,11 @@ pub extern "C" fn slint_interpreter_component_instance_show(
|
|||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_component_instance_window(
|
||||
inst: &ErasedComponentBox,
|
||||
out: *mut *const i_slint_core::window::ffi::WindowRcOpaque,
|
||||
out: *mut *const i_slint_core::window::ffi::PlatformWindowRcOpaque,
|
||||
) {
|
||||
assert_eq!(
|
||||
core::mem::size_of::<WindowRc>(),
|
||||
core::mem::size_of::<i_slint_core::window::ffi::WindowRcOpaque>()
|
||||
core::mem::size_of::<i_slint_core::window::ffi::PlatformWindowRcOpaque>()
|
||||
);
|
||||
core::ptr::write(out as *mut *const WindowRc, inst.window().window_handle() as *const _)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue