Add API for setting and getting the size of a Window in Rust and C++

This commit is contained in:
Simon Hausmann 2022-07-07 21:42:49 +02:00 committed by Simon Hausmann
parent 372ad60a8f
commit 937c37677e
9 changed files with 146 additions and 8 deletions

View file

@ -303,6 +303,8 @@ fn gen_corelib(
"slint_windowrc_on_close_requested",
"slint_windowrc_position",
"slint_windowrc_set_position",
"slint_windowrc_size",
"slint_windowrc_set_size",
"slint_new_path_elements",
"slint_new_path_events",
"slint_color_brighter",

View file

@ -188,6 +188,13 @@ public:
cbindgen_private::slint_windowrc_set_position(&inner, pos.x, pos.y);
}
slint::Size<unsigned int> size() const { return cbindgen_private::slint_windowrc_size(&inner); }
void set_size(const slint::Size<unsigned int> &size)
{
cbindgen_private::slint_windowrc_set_size(&inner, &size);
}
private:
cbindgen_private::WindowRcOpaque inner;
};
@ -386,6 +393,14 @@ public:
/// Note that on some windowing systems, such as Wayland, this functionality is not available.
void set_position(const slint::Point<int> &pos) { inner.set_position(pos); }
/// Returns the size of the window on the screen, in physical screen coordinates and excluding
/// a window frame (if present).
slint::Size<unsigned int> size() const { return inner.size(); }
/// Resizes the window to the specified size on the screen, in physical pixels and excluding
/// a window frame (if present).
void set_size(const slint::Size<unsigned int> &size) { inner.set_size(size); }
/// \private
private_api::WindowRc &window_handle() { return inner; }
/// \private

View file

@ -68,6 +68,7 @@ impl GLWindow {
self_weak: window_weak.clone(),
map_state: RefCell::new(GraphicsWindowBackendState::Unmapped {
requested_position: None,
requested_size: None,
}),
keyboard_modifiers: Default::default(),
currently_pressed_key_code: Default::default(),
@ -403,9 +404,9 @@ impl PlatformWindow for GLWindow {
}
fn show(self: Rc<Self>) {
let requested_position = match &*self.map_state.borrow() {
GraphicsWindowBackendState::Unmapped { requested_position } => {
requested_position.clone()
let (requested_position, requested_size) = match &*self.map_state.borrow() {
GraphicsWindowBackendState::Unmapped { requested_position, requested_size } => {
(requested_position.clone(), requested_size.clone())
}
GraphicsWindowBackendState::Mapped(_) => return,
};
@ -453,7 +454,13 @@ impl PlatformWindow for GLWindow {
layout_info_v.preferred_bounded(),
);
if s.width > 0 as Coord && s.height > 0 as Coord {
if let Some(requested_size) = requested_size {
// It would be nice to bound this with our constraints, but those are in logical coordinates
// and we don't know the scale factor yet...
window_builder.with_inner_size(winit::dpi::Size::new(
winit::dpi::PhysicalSize::new(requested_size.width, requested_size.height),
))
} else if s.width > 0 as Coord && s.height > 0 as Coord {
// Make sure that the window's inner size is in sync with the root window item's
// width/height.
runtime_window.set_window_item_geometry(s.width, s.height);
@ -556,7 +563,10 @@ impl PlatformWindow for GLWindow {
// Release GL textures and other GPU bound resources.
self.release_graphics_resources();
self.map_state.replace(GraphicsWindowBackendState::Unmapped { requested_position: None });
self.map_state.replace(GraphicsWindowBackendState::Unmapped {
requested_position: None,
requested_size: None,
});
/* FIXME:
if let Some(existing_blinker) = self.cursor_blinker.borrow().upgrade() {
existing_blinker.stop();
@ -774,7 +784,7 @@ impl PlatformWindow for GLWindow {
fn position(&self) -> euclid::Point2D<i32, PhysicalPx> {
match &*self.map_state.borrow() {
GraphicsWindowBackendState::Unmapped { requested_position } => {
GraphicsWindowBackendState::Unmapped { requested_position, .. } => {
requested_position.unwrap_or_default()
}
GraphicsWindowBackendState::Mapped(mapped_window) => {
@ -789,7 +799,7 @@ impl PlatformWindow for GLWindow {
fn set_position(&self, position: euclid::Point2D<i32, PhysicalPx>) {
match &mut *self.map_state.borrow_mut() {
GraphicsWindowBackendState::Unmapped { requested_position } => {
GraphicsWindowBackendState::Unmapped { requested_position, .. } => {
*requested_position = Some(position)
}
GraphicsWindowBackendState::Mapped(mapped_window) => {
@ -800,6 +810,34 @@ impl PlatformWindow for GLWindow {
}
}
}
fn inner_size(&self) -> euclid::Size2D<u32, PhysicalPx> {
match &*self.map_state.borrow() {
GraphicsWindowBackendState::Unmapped { requested_size, .. } => {
requested_size.unwrap_or_default()
}
GraphicsWindowBackendState::Mapped(mapped_window) => {
let winit_window = &*mapped_window.opengl_context.window();
let size = winit_window.inner_size();
euclid::Size2D::new(size.width, size.height)
}
}
}
fn set_inner_size(&self, size: euclid::Size2D<u32, PhysicalPx>) {
match &mut *self.map_state.borrow_mut() {
GraphicsWindowBackendState::Unmapped { requested_size, .. } => {
*requested_size = Some(size)
}
GraphicsWindowBackendState::Mapped(mapped_window) => {
let winit_window = &*mapped_window.opengl_context.window();
winit_window.set_inner_size(winit::dpi::Size::new(winit::dpi::PhysicalSize::new(
size.width,
size.height,
)))
}
}
}
}
impl Drop for GLWindow {
@ -832,7 +870,10 @@ impl Drop for MappedWindow {
}
enum GraphicsWindowBackendState {
Unmapped { requested_position: Option<euclid::Point2D<i32, PhysicalPx>> },
Unmapped {
requested_position: Option<euclid::Point2D<i32, PhysicalPx>>,
requested_size: Option<euclid::Size2D<u32, PhysicalPx>>,
},
Mapped(MappedWindow),
}

View file

@ -258,6 +258,14 @@ mod the_backend {
fn set_position(&self, _position: euclid::Point2D<i32, PhysicalPx>) {
unimplemented!()
}
fn inner_size(&self) -> euclid::Size2D<u32, PhysicalPx> {
unimplemented!()
}
fn set_inner_size(&self, _size: euclid::Size2D<u32, PhysicalPx>) {
unimplemented!()
}
}
enum McuEvent {

View file

@ -270,6 +270,14 @@ impl PlatformWindow for SimulatorWindow {
fn set_position(&self, _position: euclid::Point2D<i32, PhysicalPx>) {
unimplemented!()
}
fn inner_size(&self) -> euclid::Size2D<u32, PhysicalPx> {
unimplemented!()
}
fn set_inner_size(&self, _size: euclid::Size2D<u32, PhysicalPx>) {
unimplemented!()
}
}
impl WinitWindow for SimulatorWindow {

View file

@ -1768,6 +1768,22 @@ impl PlatformWindow for QtWindow {
widget_ptr->move(pos);
}};
}
fn inner_size(&self) -> euclid::Size2D<u32, PhysicalPx> {
let widget_ptr = self.widget_ptr();
let sz = cpp! {unsafe [widget_ptr as "QWidget*"] -> qttypes::QSize as "QSize" {
return widget_ptr->size();
}};
euclid::Size2D::new(sz.width as _, sz.height as _)
}
fn set_inner_size(&self, size: euclid::Size2D<u32, PhysicalPx>) {
let widget_ptr = self.widget_ptr();
let sz = qttypes::QSize { width: size.width as _, height: size.height as _ };
cpp! {unsafe [widget_ptr as "QWidget*", sz as "QSize"] {
widget_ptr->resize(sz);
}};
}
}
fn accessible_item(item: Option<ItemRc>) -> Option<ItemRc> {

View file

@ -159,6 +159,14 @@ impl PlatformWindow for TestingWindow {
fn set_position(&self, _position: euclid::Point2D<i32, PhysicalPx>) {
unimplemented!()
}
fn inner_size(&self) -> euclid::Size2D<u32, PhysicalPx> {
unimplemented!()
}
fn set_inner_size(&self, _size: euclid::Size2D<u32, PhysicalPx>) {
unimplemented!()
}
}
/// Initialize the testing backend.

View file

@ -178,6 +178,18 @@ impl Window {
pub fn set_position(&self, position: euclid::Point2D<i32, PhysicalPx>) {
self.0.set_position(position)
}
/// Returns the size of the window on the screen, in physical screen coordinates and excluding
/// a window frame (if present).
pub fn size(&self) -> euclid::Size2D<u32, PhysicalPx> {
self.0.inner_size()
}
/// Resizes the window to the specified size on the screen, in physical pixels and excluding
/// a window frame (if present).
pub fn set_size(&self, size: euclid::Size2D<u32, PhysicalPx>) {
self.0.set_inner_size(size)
}
}
impl crate::window::WindowHandleAccess for Window {

View file

@ -127,6 +127,14 @@ pub trait PlatformWindow {
/// Sets the position of the window on the screen, in physical screen coordinates and including
/// a window frame (if present).
fn set_position(&self, position: euclid::Point2D<i32, PhysicalPx>);
/// Returns the size of the window on the screen, in physical screen coordinates and excluding
/// a window frame (if present).
fn inner_size(&self) -> euclid::Size2D<u32, PhysicalPx>;
/// Resizes the window to the specified size on the screen, in physical pixels and excluding
/// a window frame (if present).
fn set_inner_size(&self, size: euclid::Size2D<u32, PhysicalPx>);
}
struct WindowPropertiesTracker {
@ -721,6 +729,7 @@ pub mod ffi {
use super::*;
use crate::api::{RenderingNotifier, RenderingState, SetRenderingNotifierError};
use crate::graphics::IntSize;
/// This enum describes a low-level access to specific graphics APIs used
/// by the renderer.
@ -942,4 +951,23 @@ pub mod ffi {
let window = &*(handle as *const WindowRc);
window.set_position([x, y].into());
}
/// 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().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,
size: &IntSize,
) {
let window = &*(handle as *const WindowRc);
window.set_inner_size([size.width, size.height].into());
}
}