Add support for set_position(), position(), and set_physical_size() to the C++ WindowAdapter (#3367)

Closes #3349
This commit is contained in:
Simon Hausmann 2023-08-28 18:43:04 +02:00 committed by GitHub
parent d3b89df095
commit d160eb7a31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 137 additions and 2 deletions

View file

@ -201,9 +201,25 @@ class WindowAdapter
[](void *wa) -> cbindgen_private::IntSize {
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) {
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);
was_initialized = true;
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.
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
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
/// constraints.
///

View file

@ -5,7 +5,10 @@ use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::string::String;
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::platform::{Clipboard, Platform, PlatformError};
use i_slint_core::renderer::Renderer;
@ -31,7 +34,11 @@ pub struct CppWindowAdapter {
set_visible: unsafe extern "C" fn(WindowAdapterUserData, bool),
request_redraw: unsafe extern "C" fn(WindowAdapterUserData),
size: unsafe extern "C" fn(WindowAdapterUserData) -> IntSize,
set_size: unsafe extern "C" fn(WindowAdapterUserData, IntSize),
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 {
@ -50,6 +57,29 @@ impl WindowAdapter for CppWindowAdapter {
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 {
let s = unsafe { (self.size)(self.user_data) };
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),
request_redraw: unsafe extern "C" fn(WindowAdapterUserData),
size: unsafe extern "C" fn(WindowAdapterUserData) -> IntSize,
set_size: unsafe extern "C" fn(WindowAdapterUserData, IntSize),
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,
) {
let window = Rc::<CppWindowAdapter>::new_cyclic(|w| CppWindowAdapter {
@ -128,7 +164,10 @@ pub unsafe extern "C" fn slint_window_adapter_new(
set_visible,
request_redraw,
size,
set_size,
update_window_properties,
position,
set_position,
});
core::ptr::write(target as *mut Rc<dyn WindowAdapter>, window);