C++: add WindowAdaptor::update_window_properties

This commit is contained in:
Olivier Goffart 2023-08-25 13:58:55 +02:00 committed by GitHub
parent e7a883348b
commit d23ba885ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 140 additions and 8 deletions

View file

@ -261,7 +261,7 @@ set(generated_headers
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_color_internal.h ${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_color_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_pathdata_internal.h ${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_pathdata_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_qt_internal.h ${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_qt_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_backend_internal.h ${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_platform_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_generated_public.h ${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_generated_public.h
) )

View file

@ -730,7 +730,7 @@ fn gen_backend_qt(
Ok(()) Ok(())
} }
fn gen_backend( fn gen_platform(
root_dir: &Path, root_dir: &Path,
include_dir: &Path, include_dir: &Path,
dependencies: &mut Vec<PathBuf>, dependencies: &mut Vec<PathBuf>,
@ -746,9 +746,15 @@ fn gen_backend(
.with_crate(crate_dir) .with_crate(crate_dir)
.with_include("slint_image_internal.h") .with_include("slint_image_internal.h")
.with_include("slint_internal.h") .with_include("slint_internal.h")
.with_after_include(
r"
namespace slint::platform { struct WindowProperties; }
namespace slint::cbindgen_private { using platform::WindowProperties; }
",
)
.generate() .generate()
.context("Unable to generate bindings for slint_backend_internal.h")? .context("Unable to generate bindings for slint_platform_internal.h")?
.write_to_file(include_dir.join("slint_backend_internal.h")); .write_to_file(include_dir.join("slint_platform_internal.h"));
Ok(()) Ok(())
} }
@ -871,7 +877,7 @@ pub fn gen_all(
builtin_structs(include_dir)?; builtin_structs(include_dir)?;
gen_corelib(root_dir, include_dir, &mut deps, enabled_features)?; gen_corelib(root_dir, include_dir, &mut deps, enabled_features)?;
gen_backend_qt(root_dir, include_dir, &mut deps)?; gen_backend_qt(root_dir, include_dir, &mut deps)?;
gen_backend(root_dir, include_dir, &mut deps)?; gen_platform(root_dir, include_dir, &mut deps)?;
if enabled_features.interpreter { if enabled_features.interpreter {
gen_interpreter(root_dir, include_dir, &mut deps)?; gen_interpreter(root_dir, include_dir, &mut deps)?;
} }

View file

@ -45,6 +45,63 @@ namespace slint {
/// Another important class to subclass is the WindowAdapter. /// Another important class to subclass is the WindowAdapter.
namespace platform { namespace platform {
/// This struct contains getters that provide access to properties of the Window
/// element, and is used with WindowAdapter::update_window_properties().
struct WindowProperties
{
/// Returns the title of the window.
SharedString title() const
{
SharedString out;
cbindgen_private::slint_window_properties_get_title(this, &out);
return out;
}
/// Returns the background brush of the window.
Brush background() const
{
Brush out;
cbindgen_private::slint_window_properties_get_background(this, &out);
return out;
}
/// This struct describes the layout constraints of a window.
///
/// It is the return value of WindowProperties::layout_constraints().
struct LayoutConstraints
{
/// This represents the minimum size the window can be. If this is set, the window should
/// not be able to be resized smaller than this size. If it is left unset, there is no
/// minimum size.
std::optional<LogicalSize> min;
// This represents the maximum size the window can be. If this is set, the window should
/// not be able to be resized larger than this size. If it is left unset, there is no
/// maximum size.
std::optional<LogicalSize> max;
/// This represents the preferred size of the window. This is the size the window
/// should have by default
LogicalSize preferred;
};
/// Returns the layout constraints of the window
LayoutConstraints layout_constraints() const
{
auto lc = cbindgen_private::slint_window_properties_get_layout_constraints(this);
return LayoutConstraints {
.min = lc.has_min ? std::optional(LogicalSize(lc.min)) : std::nullopt,
.max = lc.has_max ? std::optional(LogicalSize(lc.max)) : std::nullopt,
.preferred = LogicalSize(lc.preferred)
};
}
private:
/// This struct is opaque and cannot be constructed by C++
WindowProperties() = delete;
~WindowProperties() = delete;
WindowProperties(const WindowProperties &) = delete;
WindowProperties &operator=(const WindowProperties &) = delete;
};
/// Internal interface for a renderer for use with the WindowAdapter. /// Internal interface for a renderer for use with the WindowAdapter.
/// ///
/// This class is not intended to be re-implemented. In places where this class is required, use /// This class is not intended to be re-implemented. In places where this class is required, use
@ -130,6 +187,9 @@ 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, const WindowProperties *p) {
reinterpret_cast<WindowAdapter *>(wa)->update_window_properties(*p);
},
&self); &self);
was_initialized = true; was_initialized = true;
return self; return self;
@ -161,6 +221,14 @@ public:
/// 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;
/// Re-implement this function to update the properties such as window title or layout
/// constraints.
///
/// This function is called before `set_visible(true)`, and will be called again when the
/// properties that were queried on the last call are changed. If you do not query any
/// properties, it may not be called again.
virtual void update_window_properties(const WindowProperties &) { }
/// Re-implement this function to provide a reference to the renderer for use with the window /// Re-implement this function to provide a reference to the renderer for use with the window
/// adapter. /// adapter.
/// ///

View file

@ -11,7 +11,7 @@
#include "slint_internal.h" #include "slint_internal.h"
#include "slint_size.h" #include "slint_size.h"
#include "slint_point.h" #include "slint_point.h"
#include "slint_backend_internal.h" #include "slint_platform_internal.h"
#include "slint_qt_internal.h" #include "slint_qt_internal.h"
#include "slint_window.h" #include "slint_window.h"

View file

@ -4,12 +4,13 @@
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::rc::Rc; use alloc::rc::Rc;
use core::ffi::c_void; use core::ffi::c_void;
use i_slint_core::api::{PhysicalSize, Window}; use i_slint_core::api::{LogicalSize, PhysicalSize, Window};
use i_slint_core::graphics::IntSize; use i_slint_core::graphics::IntSize;
use i_slint_core::platform::{Platform, PlatformError}; use i_slint_core::platform::{Platform, PlatformError};
use i_slint_core::renderer::Renderer; use i_slint_core::renderer::Renderer;
use i_slint_core::window::ffi::WindowAdapterRcOpaque; use i_slint_core::window::ffi::WindowAdapterRcOpaque;
use i_slint_core::window::WindowAdapter; use i_slint_core::window::{WindowAdapter, WindowProperties};
use i_slint_core::SharedString;
type WindowAdapterUserData = *mut c_void; type WindowAdapterUserData = *mut c_void;
@ -29,6 +30,7 @@ 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,
update_window_properties: unsafe extern "C" fn(WindowAdapterUserData, &WindowProperties),
} }
impl Drop for CppWindowAdapter { impl Drop for CppWindowAdapter {
@ -59,6 +61,51 @@ impl WindowAdapter for CppWindowAdapter {
fn request_redraw(&self) { fn request_redraw(&self) {
unsafe { (self.request_redraw)(self.user_data) } unsafe { (self.request_redraw)(self.user_data) }
} }
fn update_window_properties(&self, properties: WindowProperties<'_>) {
unsafe { (self.update_window_properties)(self.user_data, &properties) }
}
}
#[no_mangle]
pub extern "C" fn slint_window_properties_get_title(wp: &WindowProperties, out: &mut SharedString) {
*out = wp.title();
}
#[no_mangle]
pub extern "C" fn slint_window_properties_get_background(
wp: &WindowProperties,
out: &mut i_slint_core::Brush,
) {
*out = wp.background();
}
#[repr(C)]
#[derive(Clone, Copy)]
/// a Repr(C) variant of slint::platform::LayoutConstraints
pub struct LayoutConstraintsReprC {
pub min: i_slint_core::graphics::Size,
pub max: i_slint_core::graphics::Size,
pub preferred: i_slint_core::graphics::Size,
pub has_min: bool,
pub has_max: bool,
}
#[no_mangle]
pub extern "C" fn slint_window_properties_get_layout_constraints(
wp: &WindowProperties,
) -> LayoutConstraintsReprC {
let c = wp.layout_constraints();
LayoutConstraintsReprC {
min: i_slint_core::lengths::logical_size_from_api(c.min.unwrap_or_default()).to_untyped(),
max: i_slint_core::lengths::logical_size_from_api(
c.max.unwrap_or(LogicalSize { width: f32::MAX, height: f32::MAX }),
)
.to_untyped(),
preferred: i_slint_core::lengths::logical_size_from_api(c.preferred).to_untyped(),
has_min: c.min.is_some(),
has_max: c.max.is_some(),
}
} }
#[no_mangle] #[no_mangle]
@ -69,6 +116,7 @@ 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,
update_window_properties: unsafe extern "C" fn(WindowAdapterUserData, &WindowProperties),
target: *mut WindowAdapterRcOpaque, target: *mut WindowAdapterRcOpaque,
) { ) {
let window = Rc::<CppWindowAdapter>::new_cyclic(|w| CppWindowAdapter { let window = Rc::<CppWindowAdapter>::new_cyclic(|w| CppWindowAdapter {
@ -79,6 +127,7 @@ pub unsafe extern "C" fn slint_window_adapter_new(
set_visible, set_visible,
request_redraw, request_redraw,
size, size,
update_window_properties,
}); });
core::ptr::write(target as *mut Rc<dyn WindowAdapter>, window); core::ptr::write(target as *mut Rc<dyn WindowAdapter>, window);

View file

@ -260,6 +260,15 @@ public:
void request_redraw() override { requestUpdate(); } void request_redraw() override { requestUpdate(); }
void update_window_properties(const slint::platform::WindowProperties &props) override
{
QWindow::setTitle(QString::fromUtf8(props.title().data()));
auto c = props.layout_constraints();
QWindow::setMaximumSize(c.max ? QSize(c.max->width, c.max->height)
: QSize(1 << 15, 1 << 15));
QWindow::setMinimumSize(c.min ? QSize(c.min->width, c.min->height) : QSize());
}
void resizeEvent(QResizeEvent *ev) override void resizeEvent(QResizeEvent *ev) override
{ {
auto logicalSize = ev->size(); auto logicalSize = ev->size();