mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-26 20:09:53 +00:00
Add support for set_position(), position(), and set_physical_size() to the C++ WindowAdapter (#3367)
Closes #3349
This commit is contained in:
parent
d3b89df095
commit
d160eb7a31
5 changed files with 137 additions and 2 deletions
|
@ -201,9 +201,25 @@ class WindowAdapter
|
||||||
[](void *wa) -> cbindgen_private::IntSize {
|
[](void *wa) -> cbindgen_private::IntSize {
|
||||||
return reinterpret_cast<const WindowAdapter *>(wa)->physical_size();
|
return reinterpret_cast<const WindowAdapter *>(wa)->physical_size();
|
||||||
},
|
},
|
||||||
|
[](void *wa, cbindgen_private::IntSize size) {
|
||||||
|
reinterpret_cast<WindowAdapter *>(wa)->set_physical_size(
|
||||||
|
slint::PhysicalSize({ size.width, size.height }));
|
||||||
|
},
|
||||||
[](void *wa, const WindowProperties *p) {
|
[](void *wa, const WindowProperties *p) {
|
||||||
reinterpret_cast<WindowAdapter *>(wa)->update_window_properties(*p);
|
reinterpret_cast<WindowAdapter *>(wa)->update_window_properties(*p);
|
||||||
},
|
},
|
||||||
|
[](void *wa, cbindgen_private::Point2D<int32_t> *point) -> bool {
|
||||||
|
if (auto pos = reinterpret_cast<const WindowAdapter *>(wa)->position()) {
|
||||||
|
*point = *pos;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](void *wa, cbindgen_private::Point2D<int32_t> point) {
|
||||||
|
reinterpret_cast<WindowAdapter *>(wa)->set_position(
|
||||||
|
slint::PhysicalPosition({ point.x, point.y }));
|
||||||
|
},
|
||||||
&self);
|
&self);
|
||||||
was_initialized = true;
|
was_initialized = true;
|
||||||
return self;
|
return self;
|
||||||
|
@ -232,9 +248,37 @@ public:
|
||||||
/// do that in the next iteration of the event loop, or in a callback from the window manager.
|
/// do that in the next iteration of the event loop, or in a callback from the window manager.
|
||||||
virtual void request_redraw() { }
|
virtual void request_redraw() { }
|
||||||
|
|
||||||
|
/// Request a new size for the window to the specified size on the screen, in physical or
|
||||||
|
/// logical pixels and excluding a window frame (if present).
|
||||||
|
///
|
||||||
|
/// This is called from slint::Window::set_size().
|
||||||
|
///
|
||||||
|
/// The default implementation does nothing
|
||||||
|
///
|
||||||
|
/// This function should sent the size to the Windowing system. If the window size actually
|
||||||
|
/// changes, you should call slint::Window::dispatch_resize_event to propagate the new size
|
||||||
|
/// to the slint view.
|
||||||
|
virtual void set_physical_size(slint::PhysicalSize) { }
|
||||||
|
|
||||||
/// Returns the actual physical size of the window
|
/// Returns the actual physical size of the window
|
||||||
virtual slint::PhysicalSize physical_size() const = 0;
|
virtual slint::PhysicalSize physical_size() const = 0;
|
||||||
|
|
||||||
|
/// Sets the position of the window on the screen, in physical screen coordinates and including
|
||||||
|
/// a window frame (if present).
|
||||||
|
///
|
||||||
|
/// The default implementation does nothing
|
||||||
|
///
|
||||||
|
/// Called from slint::Window::set_position().
|
||||||
|
virtual void set_position(slint::PhysicalPosition) { }
|
||||||
|
|
||||||
|
/// Returns the position of the window on the screen, in physical screen coordinates and
|
||||||
|
/// including a window frame (if present).
|
||||||
|
///
|
||||||
|
/// The default implementation returns std::nullopt.
|
||||||
|
///
|
||||||
|
/// Called from slint::Window::position().
|
||||||
|
virtual std::optional<slint::PhysicalPosition> position() const { return std::nullopt; }
|
||||||
|
|
||||||
/// Re-implement this function to update the properties such as window title or layout
|
/// Re-implement this function to update the properties such as window title or layout
|
||||||
/// constraints.
|
/// constraints.
|
||||||
///
|
///
|
||||||
|
|
|
@ -5,7 +5,10 @@ use alloc::boxed::Box;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use core::ffi::c_void;
|
use core::ffi::c_void;
|
||||||
use i_slint_core::api::{LogicalSize, PhysicalSize, Window};
|
use i_slint_core::api::{
|
||||||
|
LogicalSize, PhysicalPosition, PhysicalSize, Window, WindowPosition, WindowSize,
|
||||||
|
};
|
||||||
|
use i_slint_core::graphics::euclid;
|
||||||
use i_slint_core::graphics::IntSize;
|
use i_slint_core::graphics::IntSize;
|
||||||
use i_slint_core::platform::{Clipboard, Platform, PlatformError};
|
use i_slint_core::platform::{Clipboard, Platform, PlatformError};
|
||||||
use i_slint_core::renderer::Renderer;
|
use i_slint_core::renderer::Renderer;
|
||||||
|
@ -31,7 +34,11 @@ pub struct CppWindowAdapter {
|
||||||
set_visible: unsafe extern "C" fn(WindowAdapterUserData, bool),
|
set_visible: unsafe extern "C" fn(WindowAdapterUserData, bool),
|
||||||
request_redraw: unsafe extern "C" fn(WindowAdapterUserData),
|
request_redraw: unsafe extern "C" fn(WindowAdapterUserData),
|
||||||
size: unsafe extern "C" fn(WindowAdapterUserData) -> IntSize,
|
size: unsafe extern "C" fn(WindowAdapterUserData) -> IntSize,
|
||||||
|
set_size: unsafe extern "C" fn(WindowAdapterUserData, IntSize),
|
||||||
update_window_properties: unsafe extern "C" fn(WindowAdapterUserData, &WindowProperties),
|
update_window_properties: unsafe extern "C" fn(WindowAdapterUserData, &WindowProperties),
|
||||||
|
position:
|
||||||
|
unsafe extern "C" fn(WindowAdapterUserData, &mut euclid::default::Point2D<i32>) -> bool,
|
||||||
|
set_position: unsafe extern "C" fn(WindowAdapterUserData, euclid::default::Point2D<i32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for CppWindowAdapter {
|
impl Drop for CppWindowAdapter {
|
||||||
|
@ -50,6 +57,29 @@ impl WindowAdapter for CppWindowAdapter {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn position(&self) -> Option<PhysicalPosition> {
|
||||||
|
let mut pos = euclid::default::Point2D::<i32>::default();
|
||||||
|
if unsafe { (self.position)(self.user_data, &mut pos) } {
|
||||||
|
Some(i_slint_core::graphics::ffi::physical_position_to_api(pos))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_position(&self, position: WindowPosition) {
|
||||||
|
let physical_position = i_slint_core::graphics::ffi::physical_position_from_api(
|
||||||
|
position.to_physical(self.window.scale_factor()),
|
||||||
|
);
|
||||||
|
unsafe { (self.set_position)(self.user_data, physical_position) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_size(&self, size: WindowSize) {
|
||||||
|
let physical_size = i_slint_core::graphics::ffi::physical_size_from_api(
|
||||||
|
size.to_physical(self.window.scale_factor()),
|
||||||
|
);
|
||||||
|
unsafe { (self.set_size)(self.user_data, physical_size) }
|
||||||
|
}
|
||||||
|
|
||||||
fn size(&self) -> PhysicalSize {
|
fn size(&self) -> PhysicalSize {
|
||||||
let s = unsafe { (self.size)(self.user_data) };
|
let s = unsafe { (self.size)(self.user_data) };
|
||||||
PhysicalSize::new(s.width, s.height)
|
PhysicalSize::new(s.width, s.height)
|
||||||
|
@ -117,7 +147,13 @@ pub unsafe extern "C" fn slint_window_adapter_new(
|
||||||
set_visible: unsafe extern "C" fn(WindowAdapterUserData, bool),
|
set_visible: unsafe extern "C" fn(WindowAdapterUserData, bool),
|
||||||
request_redraw: unsafe extern "C" fn(WindowAdapterUserData),
|
request_redraw: unsafe extern "C" fn(WindowAdapterUserData),
|
||||||
size: unsafe extern "C" fn(WindowAdapterUserData) -> IntSize,
|
size: unsafe extern "C" fn(WindowAdapterUserData) -> IntSize,
|
||||||
|
set_size: unsafe extern "C" fn(WindowAdapterUserData, IntSize),
|
||||||
update_window_properties: unsafe extern "C" fn(WindowAdapterUserData, &WindowProperties),
|
update_window_properties: unsafe extern "C" fn(WindowAdapterUserData, &WindowProperties),
|
||||||
|
position: unsafe extern "C" fn(
|
||||||
|
WindowAdapterUserData,
|
||||||
|
&mut euclid::default::Point2D<i32>,
|
||||||
|
) -> bool,
|
||||||
|
set_position: unsafe extern "C" fn(WindowAdapterUserData, euclid::default::Point2D<i32>),
|
||||||
target: *mut WindowAdapterRcOpaque,
|
target: *mut WindowAdapterRcOpaque,
|
||||||
) {
|
) {
|
||||||
let window = Rc::<CppWindowAdapter>::new_cyclic(|w| CppWindowAdapter {
|
let window = Rc::<CppWindowAdapter>::new_cyclic(|w| CppWindowAdapter {
|
||||||
|
@ -128,7 +164,10 @@ pub unsafe extern "C" fn slint_window_adapter_new(
|
||||||
set_visible,
|
set_visible,
|
||||||
request_redraw,
|
request_redraw,
|
||||||
size,
|
size,
|
||||||
|
set_size,
|
||||||
update_window_properties,
|
update_window_properties,
|
||||||
|
position,
|
||||||
|
set_position,
|
||||||
});
|
});
|
||||||
|
|
||||||
core::ptr::write(target as *mut Rc<dyn WindowAdapter>, window);
|
core::ptr::write(target as *mut Rc<dyn WindowAdapter>, window);
|
||||||
|
|
|
@ -256,6 +256,12 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_physical_size(slint::PhysicalSize size) override
|
||||||
|
{
|
||||||
|
float scale_factor = devicePixelRatio();
|
||||||
|
resize(size.width / scale_factor, size.height / scale_factor);
|
||||||
|
}
|
||||||
|
|
||||||
slint::PhysicalSize physical_size() const override
|
slint::PhysicalSize physical_size() const override
|
||||||
{
|
{
|
||||||
auto windowSize = slint::LogicalSize({ float(width()), float(height()) });
|
auto windowSize = slint::LogicalSize({ float(width()), float(height()) });
|
||||||
|
@ -264,6 +270,20 @@ public:
|
||||||
uint32_t(windowSize.height * scale_factor) });
|
uint32_t(windowSize.height * scale_factor) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_position(slint::PhysicalPosition position) override
|
||||||
|
{
|
||||||
|
float scale_factor = devicePixelRatio();
|
||||||
|
setFramePosition(QPointF(position.x / scale_factor, position.y / scale_factor).toPoint());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<slint::PhysicalPosition> position() const override
|
||||||
|
{
|
||||||
|
auto pos = framePosition();
|
||||||
|
float scale_factor = devicePixelRatio();
|
||||||
|
return { slint::PhysicalPosition(
|
||||||
|
{ int32_t(pos.x() * scale_factor), int32_t(pos.y() * scale_factor) }) };
|
||||||
|
}
|
||||||
|
|
||||||
void request_redraw() override { requestUpdate(); }
|
void request_redraw() override { requestUpdate(); }
|
||||||
|
|
||||||
void update_window_properties(const slint::platform::WindowProperties &props) override
|
void update_window_properties(const slint::platform::WindowProperties &props) override
|
||||||
|
|
|
@ -86,6 +86,11 @@ impl PhysicalPosition {
|
||||||
pub(crate) fn to_euclid(&self) -> crate::graphics::euclid::default::Point2D<i32> {
|
pub(crate) fn to_euclid(&self) -> crate::graphics::euclid::default::Point2D<i32> {
|
||||||
[self.x, self.y].into()
|
[self.x, self.y].into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
pub(crate) fn from_euclid(p: crate::graphics::euclid::default::Point2D<i32>) -> Self {
|
||||||
|
Self::new(p.x as _, p.y as _)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The position of the window in either physical or logical pixels. This is used
|
/// The position of the window in either physical or logical pixels. This is used
|
||||||
|
|
|
@ -162,8 +162,9 @@ impl FontRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Internal module for use by cbindgen and the C++ platform API layer.
|
||||||
#[cfg(feature = "ffi")]
|
#[cfg(feature = "ffi")]
|
||||||
pub(crate) mod ffi {
|
pub mod ffi {
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
/// Expand Rect so that cbindgen can see it. ( is in fact euclid::default::Rect<f32>)
|
/// Expand Rect so that cbindgen can see it. ( is in fact euclid::default::Rect<f32>)
|
||||||
|
@ -196,4 +197,30 @@ pub(crate) mod ffi {
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use super::path::ffi::*;
|
pub use super::path::ffi::*;
|
||||||
|
|
||||||
|
/// Conversion function used by C++ platform API layer to
|
||||||
|
/// convert the PhysicalSize used in the Rust WindowAdapter API
|
||||||
|
/// to the ffi.
|
||||||
|
pub fn physical_size_from_api(
|
||||||
|
size: crate::api::PhysicalSize,
|
||||||
|
) -> crate::graphics::euclid::default::Size2D<u32> {
|
||||||
|
size.to_euclid()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Conversion function used by C++ platform API layer to
|
||||||
|
/// convert the PhysicalPosition used in the Rust WindowAdapter API
|
||||||
|
/// to the ffi.
|
||||||
|
pub fn physical_position_from_api(
|
||||||
|
position: crate::api::PhysicalPosition,
|
||||||
|
) -> crate::graphics::euclid::default::Point2D<i32> {
|
||||||
|
position.to_euclid()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Conversion function used by C++ platform API layer to
|
||||||
|
/// convert from the ffi to PhysicalPosition.
|
||||||
|
pub fn physical_position_to_api(
|
||||||
|
position: crate::graphics::euclid::default::Point2D<i32>,
|
||||||
|
) -> crate::api::PhysicalPosition {
|
||||||
|
crate::api::PhysicalPosition::from_euclid(position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue