#![warn(missing_docs)]
use crate::api::{
CloseRequestResponse, PhysicalPosition, PhysicalSize, Window, WindowPosition, WindowSize,
};
use crate::component::{ComponentRc, ComponentRef, ComponentVTable, ComponentWeak};
use crate::graphics::Point;
use crate::input::{
key_codes, InternalKeyboardModifierState, KeyEvent, KeyEventType, KeyInputEvent,
KeyboardModifiers, MouseEvent, MouseInputState, TextCursorBlinker,
};
use crate::item_tree::ItemRc;
use crate::items::{ItemRef, MouseCursor};
use crate::lengths::{LogicalLength, LogicalPoint, LogicalRect, LogicalSize, SizeLengths};
use crate::properties::{Property, PropertyTracker};
use crate::renderer::Renderer;
use crate::{Callback, Coord};
use alloc::boxed::Box;
use alloc::rc::{Rc, Weak};
use core::cell::{Cell, RefCell};
use core::pin::Pin;
use euclid::num::Zero;
use vtable::VRcMapped;
fn next_focus_item(item: ItemRc) -> ItemRc {
item.next_focus_item()
}
fn previous_focus_item(item: ItemRc) -> ItemRc {
item.previous_focus_item()
}
fn input_as_key_event(input: KeyInputEvent, modifiers: KeyboardModifiers) -> KeyEvent {
KeyEvent {
modifiers,
text: input.text,
event_type: input.event_type,
preedit_selection_start: input.preedit_selection_start,
preedit_selection_end: input.preedit_selection_end,
}
}
pub trait WindowAdapter: WindowAdapterSealed {
fn window(&self) -> &Window;
}
#[doc(hidden)]
pub trait WindowAdapterSealed {
fn show(&self) {}
fn hide(&self) {}
fn request_redraw(&self) {}
fn register_component(&self) {}
fn unregister_component<'a>(
&self,
_component: ComponentRef,
_items: &mut dyn Iterator<Item = Pin<ItemRef<'a>>>,
) {
}
fn create_popup(&self, _geometry: LogicalRect) -> Option<Rc<dyn WindowAdapter>> {
None
}
fn request_window_properties_update(&self) {}
fn apply_window_properties(&self, _window_item: Pin<&crate::items::WindowItem>) {}
fn apply_geometry_constraint(
&self,
_constraints_horizontal: crate::layout::LayoutInfo,
_constraints_vertical: crate::layout::LayoutInfo,
) {
}
fn set_mouse_cursor(&self, _cursor: MouseCursor) {}
fn enable_input_method(&self, _: crate::items::InputType) {}
fn disable_input_method(&self) {}
fn set_ime_position(&self, _: LogicalPoint) {}
fn as_any(&self) -> &dyn core::any::Any {
&()
}
fn handle_focus_change(&self, _old: Option<ItemRc>, _new: Option<ItemRc>) {}
fn position(&self) -> PhysicalPosition {
Default::default()
}
fn set_position(&self, _position: WindowPosition) {}
fn set_size(&self, _size: WindowSize) {}
fn dark_color_scheme(&self) -> bool {
false
}
fn renderer(&self) -> &dyn Renderer;
fn is_visible(&self) -> bool {
false
}
}
struct WindowPropertiesTracker {
window_adapter_weak: Weak<dyn WindowAdapter>,
}
impl crate::properties::PropertyDirtyHandler for WindowPropertiesTracker {
fn notify(&self) {
if let Some(window_adapter) = self.window_adapter_weak.upgrade() {
window_adapter.request_window_properties_update();
};
}
}
struct WindowRedrawTracker {
window_adapter_weak: Weak<dyn WindowAdapter>,
}
impl crate::properties::PropertyDirtyHandler for WindowRedrawTracker {
fn notify(&self) {
if let Some(window_adapter) = self.window_adapter_weak.upgrade() {
window_adapter.request_redraw();
};
}
}
enum PopupWindowLocation {
TopLevel(Rc<dyn WindowAdapter>),
ChildWindow(LogicalPoint),
}
struct PopupWindow {
location: PopupWindowLocation,
component: ComponentRc,
}
pub struct WindowInner {
window_adapter_weak: Weak<dyn WindowAdapter>,
component: RefCell<ComponentWeak>,
mouse_input_state: Cell<MouseInputState>,
modifiers: Cell<InternalKeyboardModifierState>,
redraw_tracker: Pin<Box<PropertyTracker<WindowRedrawTracker>>>,
window_properties_tracker: Pin<Box<PropertyTracker<WindowPropertiesTracker>>>,
focus_item: RefCell<crate::item_tree::ItemWeak>,
cursor_blinker: RefCell<pin_weak::rc::PinWeak<crate::input::TextCursorBlinker>>,
scale_factor: Pin<Box<Property<f32>>>,
active: Pin<Box<Property<bool>>>,
active_popup: RefCell<Option<PopupWindow>>,
close_requested: Callback<(), CloseRequestResponse>,
pub(crate) inner_size: Cell<PhysicalSize>,
}
impl Drop for WindowInner {
fn drop(&mut self) {
if let Some(existing_blinker) = self.cursor_blinker.borrow().upgrade() {
existing_blinker.stop();
}
}
}
impl WindowInner {
pub fn new(window_adapter_weak: Weak<dyn WindowAdapter>) -> Self {
#![allow(unused_mut)]
let mut window_properties_tracker =
PropertyTracker::new_with_dirty_handler(WindowPropertiesTracker {
window_adapter_weak: window_adapter_weak.clone(),
});
let mut redraw_tracker = PropertyTracker::new_with_dirty_handler(WindowRedrawTracker {
window_adapter_weak: window_adapter_weak.clone(),
});
#[cfg(slint_debug_property)]
{
window_properties_tracker
.set_debug_name("i_slint_core::Window::window_properties_tracker".into());
redraw_tracker.set_debug_name("i_slint_core::Window::redraw_tracker".into());
}
let window = Self {
window_adapter_weak,
component: Default::default(),
mouse_input_state: Default::default(),
modifiers: Default::default(),
redraw_tracker: Box::pin(redraw_tracker),
window_properties_tracker: Box::pin(window_properties_tracker),
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
}
pub fn set_component(&self, component: &ComponentRc) {
self.close_popup();
self.focus_item.replace(Default::default());
self.mouse_input_state.replace(Default::default());
self.modifiers.replace(Default::default());
self.component.replace(ComponentRc::downgrade(component));
self.window_properties_tracker.set_dirty(); let window_adapter = self.window_adapter();
{
let component = ComponentRc::borrow_pin(&component);
let root_item = component.as_ref().get_item_ref(0);
let window_item = ItemRef::downcast_pin::<crate::items::WindowItem>(root_item).unwrap();
let default_font_size_prop =
crate::items::WindowItem::FIELD_OFFSETS.default_font_size.apply_pin(window_item);
if default_font_size_prop.get().get() <= 0 as Coord {
default_font_size_prop.set(window_adapter.renderer().default_font_size());
}
}
window_adapter.request_window_properties_update();
window_adapter.request_redraw();
}
pub fn component(&self) -> ComponentRc {
self.component.borrow().upgrade().unwrap()
}
pub fn try_component(&self) -> Option<ComponentRc> {
self.component.borrow().upgrade()
}
pub fn process_mouse_input(&self, mut event: MouseEvent) {
crate::animations::update_animations();
let embedded_popup_component =
self.active_popup.borrow().as_ref().and_then(|popup| match popup.location {
PopupWindowLocation::TopLevel(_) => None,
PopupWindowLocation::ChildWindow(coordinates) => {
Some((popup.component.clone(), coordinates))
}
});
let component = embedded_popup_component
.as_ref()
.and_then(|(popup_component, coordinates)| {
event.translate(-coordinates.to_vector());
if let MouseEvent::Pressed { position, .. } = &event {
let geom = ComponentRc::borrow_pin(popup_component)
.as_ref()
.get_item_ref(0)
.as_ref()
.geometry();
if !geom.contains(*position) {
self.close_popup();
return None;
}
}
Some(popup_component.clone())
})
.or_else(|| self.component.borrow().upgrade());
let component = if let Some(component) = component {
component
} else {
return;
};
self.mouse_input_state.set(crate::input::process_mouse_input(
component,
event,
&self.window_adapter(),
self.mouse_input_state.take(),
));
if embedded_popup_component.is_some() {
if matches!(event, MouseEvent::Released { .. }) {
self.close_popup();
}
}
}
pub(crate) fn process_delayed_event(&self) {
self.mouse_input_state.set(crate::input::process_delayed_event(
&self.window_adapter(),
self.mouse_input_state.take(),
));
}
pub fn process_key_input(&self, event: KeyInputEvent) {
if let Some(updated_modifier) = self
.modifiers
.get()
.state_update(event.event_type == KeyEventType::KeyPressed, &event.text)
{
self.modifiers.set(updated_modifier);
}
let event = input_as_key_event(event, self.modifiers.get().into());
let mut item = self.focus_item.borrow().clone().upgrade();
while let Some(focus_item) = item {
if !focus_item.is_visible() {
self.take_focus_item();
} else {
if focus_item.borrow().as_ref().key_event(
&event,
&self.window_adapter(),
&focus_item,
) == crate::input::KeyEventResult::EventAccepted
{
return;
}
}
item = focus_item.parent_item();
}
if event.text.starts_with(key_codes::Tab)
&& !event.modifiers.shift
&& event.event_type == KeyEventType::KeyPressed
{
self.focus_next_item();
} else if (event.text.starts_with(key_codes::Backtab)
|| (event.text.starts_with(key_codes::Tab) && event.modifiers.shift))
&& event.event_type == KeyEventType::KeyPressed
{
self.focus_previous_item();
}
}
pub fn set_cursor_blink_binding(&self, prop: &crate::Property<bool>) {
let existing_blinker = self.cursor_blinker.borrow().clone();
let blinker = existing_blinker.upgrade().unwrap_or_else(|| {
let new_blinker = TextCursorBlinker::new();
*self.cursor_blinker.borrow_mut() =
pin_weak::rc::PinWeak::downgrade(new_blinker.clone());
new_blinker
});
TextCursorBlinker::set_binding(blinker, prop);
}
pub fn set_focus_item(&self, focus_item: &ItemRc) {
let old = self.take_focus_item();
let new = self.move_focus(focus_item.clone(), next_focus_item);
self.window_adapter().handle_focus_change(old, new);
}
pub fn set_focus(&self, have_focus: bool) {
let event = if have_focus {
crate::input::FocusEvent::WindowReceivedFocus
} else {
crate::input::FocusEvent::WindowLostFocus
};
if let Some(focus_item) = self.focus_item.borrow().upgrade() {
focus_item.borrow().as_ref().focus_event(&event, &self.window_adapter(), &focus_item);
}
if !have_focus {
self.modifiers.take();
}
}
fn take_focus_item(&self) -> Option<ItemRc> {
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_adapter(),
&focus_item_rc,
);
Some(focus_item_rc)
} else {
None
}
}
fn publish_focus_item(&self, item: &Option<ItemRc>) -> crate::input::FocusEventResult {
match item {
Some(item) => {
*self.focus_item.borrow_mut() = item.downgrade();
item.borrow().as_ref().focus_event(
&crate::input::FocusEvent::FocusIn,
&self.window_adapter(),
&item,
)
}
None => {
*self.focus_item.borrow_mut() = Default::default();
crate::input::FocusEventResult::FocusAccepted }
}
}
fn move_focus(&self, start_item: ItemRc, forward: impl Fn(ItemRc) -> ItemRc) -> Option<ItemRc> {
let mut current_item = start_item;
let mut visited = alloc::vec::Vec::new();
loop {
if current_item.is_visible()
&& self.publish_focus_item(&Some(current_item.clone()))
== crate::input::FocusEventResult::FocusAccepted
{
return Some(current_item); }
visited.push(current_item.clone());
current_item = forward(current_item);
if visited.iter().any(|i| *i == current_item) {
return None; }
}
}
pub fn focus_next_item(&self) {
let component = self.component();
let start_item = self
.take_focus_item()
.map(next_focus_item)
.unwrap_or_else(|| ItemRc::new(component, 0));
let end_item = self.move_focus(start_item.clone(), next_focus_item);
self.window_adapter().handle_focus_change(Some(start_item), end_item);
}
pub fn focus_previous_item(&self) {
let component = self.component();
let start_item = previous_focus_item(
self.take_focus_item().unwrap_or_else(|| ItemRc::new(component, 0)),
);
let end_item = self.move_focus(start_item.clone(), previous_focus_item);
self.window_adapter().handle_focus_change(Some(start_item), end_item);
}
pub fn set_active(&self, active: bool) {
self.active.as_ref().set(active);
}
pub fn active(&self) -> bool {
self.active.as_ref().get()
}
pub fn update_window_properties(&self) {
self.window_properties_tracker.as_ref().evaluate_as_dependency_root(|| {
let component = self.component();
let component = ComponentRc::borrow_pin(&component);
self.window_adapter().apply_geometry_constraint(
component.as_ref().layout_info(crate::layout::Orientation::Horizontal),
component.as_ref().layout_info(crate::layout::Orientation::Vertical),
);
if let Some(window_item) = self.window_item() {
self.window_adapter().apply_window_properties(window_item.as_pin_ref());
}
});
}
pub fn draw_contents(&self, render_components: impl FnOnce(&[(&ComponentRc, LogicalPoint)])) {
let draw_fn = || {
let component_rc = self.component();
let popup_component =
self.active_popup.borrow().as_ref().and_then(|popup| match popup.location {
PopupWindowLocation::TopLevel(_) => None,
PopupWindowLocation::ChildWindow(coordinates) => {
Some((popup.component.clone(), coordinates))
}
});
if let Some((popup_component, popup_coordinates)) = popup_component {
render_components(&[
(&component_rc, LogicalPoint::default()),
(&popup_component, popup_coordinates),
])
} else {
render_components(&[(&component_rc, LogicalPoint::default())]);
}
};
self.redraw_tracker.as_ref().evaluate_as_dependency_root(draw_fn)
}
pub fn show(&self) {
self.window_adapter().show();
self.update_window_properties();
}
pub fn hide(&self) {
self.window_adapter().hide();
}
pub fn show_popup(
&self,
popup_componentrc: &ComponentRc,
position: Point,
parent_item: &ItemRc,
) {
let position = parent_item.map_to_window(
parent_item.geometry().origin + LogicalPoint::from_untyped(position).to_vector(),
);
let popup_component = ComponentRc::borrow_pin(&popup_componentrc);
let popup_root = popup_component.as_ref().get_item_ref(0);
let (mut w, mut h) = if let Some(window_item) =
ItemRef::downcast_pin::<crate::items::WindowItem>(popup_root)
{
(window_item.width(), window_item.height())
} else {
(LogicalLength::zero(), LogicalLength::zero())
};
let layout_info_h =
popup_component.as_ref().layout_info(crate::layout::Orientation::Horizontal);
let layout_info_v =
popup_component.as_ref().layout_info(crate::layout::Orientation::Vertical);
if w <= LogicalLength::zero() {
w = LogicalLength::new(layout_info_h.preferred);
}
if h <= LogicalLength::zero() {
h = LogicalLength::new(layout_info_v.preferred);
}
w = w.max(LogicalLength::new(layout_info_h.min)).min(LogicalLength::new(layout_info_h.max));
h = h.max(LogicalLength::new(layout_info_v.min)).min(LogicalLength::new(layout_info_v.max));
let size = LogicalSize::from_lengths(w, h);
if let Some(window_item) = ItemRef::downcast_pin(popup_root) {
let width_property =
crate::items::WindowItem::FIELD_OFFSETS.width.apply_pin(window_item);
let height_property =
crate::items::WindowItem::FIELD_OFFSETS.height.apply_pin(window_item);
width_property.set(size.width_length());
height_property.set(size.height_length());
};
let location = match self.window_adapter().create_popup(LogicalRect::new(position, size)) {
None => {
self.window_adapter().request_redraw();
PopupWindowLocation::ChildWindow(position)
}
Some(window_adapter) => {
WindowInner::from_pub(window_adapter.window()).set_component(popup_componentrc);
PopupWindowLocation::TopLevel(window_adapter)
}
};
self.active_popup
.replace(Some(PopupWindow { location, component: popup_componentrc.clone() }));
}
pub fn close_popup(&self) {
if let Some(current_popup) = self.active_popup.replace(None) {
if let PopupWindowLocation::ChildWindow(offset) = current_popup.location {
let popup_region = crate::properties::evaluate_no_tracking(|| {
let popup_component = ComponentRc::borrow_pin(¤t_popup.component);
popup_component.as_ref().get_item_ref(0).as_ref().geometry()
})
.translate(offset.to_vector());
if !popup_region.is_empty() {
let window_adapter = self.window_adapter();
window_adapter.renderer().mark_dirty_region(popup_region.to_box2d());
window_adapter.request_redraw();
}
}
}
}
pub fn scale_factor(&self) -> f32 {
self.scale_factor.as_ref().get()
}
pub fn set_scale_factor(&self, factor: f32) {
self.scale_factor.as_ref().set(factor)
}
pub fn window_item(&self) -> Option<VRcMapped<ComponentVTable, crate::items::WindowItem>> {
self.try_component().and_then(|component_rc| {
ItemRc::new(component_rc, 0).downcast::<crate::items::WindowItem>()
})
}
pub fn set_window_item_geometry(&self, size: LogicalSize) {
if let Some(component_rc) = self.try_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::<crate::items::WindowItem>(root_item)
{
window_item.width.set(size.width_length());
window_item.height.set(size.height_length());
}
}
}
pub fn on_close_requested(&self, mut callback: impl FnMut() -> CloseRequestResponse + 'static) {
self.close_requested.set_handler(move |()| callback());
}
pub fn request_close(&self) -> bool {
match self.close_requested.call(&()) {
CloseRequestResponse::HideWindow => true,
CloseRequestResponse::KeepWindowShown => false,
}
}
pub fn window_adapter(&self) -> Rc<dyn WindowAdapter> {
self.window_adapter_weak.upgrade().unwrap()
}
pub fn from_pub(window: &crate::api::Window) -> &Self {
&window.0
}
}
pub type WindowAdapterRc = Rc<dyn WindowAdapter>;
#[cfg(feature = "ffi")]
pub mod ffi {
#![allow(unsafe_code)]
#![allow(clippy::missing_safety_doc)]
use super::*;
use crate::api::{RenderingNotifier, RenderingState, SetRenderingNotifierError};
use crate::graphics::IntSize;
use crate::graphics::Size;
#[repr(C)]
pub enum GraphicsAPI {
NativeOpenGL,
}
#[allow(non_camel_case_types)]
type c_void = ();
#[repr(C)]
pub struct WindowAdapterRcOpaque(*const c_void, *const c_void);
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_drop(handle: *mut WindowAdapterRcOpaque) {
assert_eq!(
core::mem::size_of::<Rc<dyn WindowAdapter>>(),
core::mem::size_of::<WindowAdapterRcOpaque>()
);
core::ptr::read(handle as *mut Rc<dyn WindowAdapter>);
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_clone(
source: *const WindowAdapterRcOpaque,
target: *mut WindowAdapterRcOpaque,
) {
assert_eq!(
core::mem::size_of::<Rc<dyn WindowAdapter>>(),
core::mem::size_of::<WindowAdapterRcOpaque>()
);
let window = &*(source as *const Rc<dyn WindowAdapter>);
core::ptr::write(target as *mut Rc<dyn WindowAdapter>, window.clone());
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_show(handle: *const WindowAdapterRcOpaque) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.show();
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_hide(handle: *const WindowAdapterRcOpaque) {
let window = &*(handle as *const Rc<dyn WindowAdapter>);
window.hide();
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_is_visible(
handle: *const WindowAdapterRcOpaque,
) -> bool {
let window = &*(handle as *const Rc<dyn WindowAdapter>);
window.is_visible()
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_get_scale_factor(
handle: *const WindowAdapterRcOpaque,
) -> f32 {
assert_eq!(
core::mem::size_of::<Rc<dyn WindowAdapter>>(),
core::mem::size_of::<WindowAdapterRcOpaque>()
);
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
WindowInner::from_pub(window_adapter.window()).scale_factor()
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_set_scale_factor(
handle: *const WindowAdapterRcOpaque,
value: f32,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
WindowInner::from_pub(window_adapter.window()).set_scale_factor(value)
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_set_focus_item(
handle: *const WindowAdapterRcOpaque,
focus_item: &ItemRc,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
WindowInner::from_pub(window_adapter.window()).set_focus_item(focus_item)
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_set_component(
handle: *const WindowAdapterRcOpaque,
component: &ComponentRc,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
WindowInner::from_pub(window_adapter.window()).set_component(component)
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_show_popup(
handle: *const WindowAdapterRcOpaque,
popup: &ComponentRc,
position: crate::graphics::Point,
parent_item: &ItemRc,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
WindowInner::from_pub(window_adapter.window()).show_popup(popup, position, parent_item);
}
pub unsafe extern "C" fn slint_windowrc_close_popup(handle: *const WindowAdapterRcOpaque) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
WindowInner::from_pub(window_adapter.window()).close_popup();
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_set_rendering_notifier(
handle: *const WindowAdapterRcOpaque,
callback: extern "C" fn(
rendering_state: RenderingState,
graphics_api: GraphicsAPI,
user_data: *mut c_void,
),
drop_user_data: extern "C" fn(user_data: *mut c_void),
user_data: *mut c_void,
error: *mut SetRenderingNotifierError,
) -> bool {
struct CNotifier {
callback: extern "C" fn(
rendering_state: RenderingState,
graphics_api: GraphicsAPI,
user_data: *mut c_void,
),
drop_user_data: extern "C" fn(*mut c_void),
user_data: *mut c_void,
}
impl Drop for CNotifier {
fn drop(&mut self) {
(self.drop_user_data)(self.user_data)
}
}
impl RenderingNotifier for CNotifier {
fn notify(&mut self, state: RenderingState, graphics_api: &crate::api::GraphicsAPI) {
let cpp_graphics_api = match graphics_api {
crate::api::GraphicsAPI::NativeOpenGL { .. } => GraphicsAPI::NativeOpenGL,
crate::api::GraphicsAPI::WebGL { .. } => unreachable!(), };
(self.callback)(state, cpp_graphics_api, self.user_data)
}
}
let window = &*(handle as *const Rc<dyn WindowAdapter>);
match window.renderer().set_rendering_notifier(Box::new(CNotifier {
callback,
drop_user_data,
user_data,
})) {
Ok(()) => true,
Err(err) => {
*error = err;
false
}
}
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_on_close_requested(
handle: *const WindowAdapterRcOpaque,
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,
) {
struct WithUserData {
callback: extern "C" fn(user_data: *mut c_void) -> CloseRequestResponse,
drop_user_data: extern "C" fn(*mut c_void),
user_data: *mut c_void,
}
impl Drop for WithUserData {
fn drop(&mut self) {
(self.drop_user_data)(self.user_data)
}
}
impl WithUserData {
fn call(&self) -> CloseRequestResponse {
(self.callback)(self.user_data)
}
}
let with_user_data = WithUserData { callback, drop_user_data, user_data };
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.window().on_close_requested(move || with_user_data.call());
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_request_redraw(handle: *const WindowAdapterRcOpaque) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.request_redraw();
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_position(
handle: *const WindowAdapterRcOpaque,
pos: &mut euclid::default::Point2D<i32>,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
*pos = window_adapter.position().to_euclid()
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_set_physical_position(
handle: *const WindowAdapterRcOpaque,
pos: &euclid::default::Point2D<i32>,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.set_position(crate::api::PhysicalPosition::new(pos.x, pos.y).into());
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_set_logical_position(
handle: *const WindowAdapterRcOpaque,
pos: &euclid::default::Point2D<f32>,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.set_position(crate::api::LogicalPosition::new(pos.x, pos.y).into());
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_size(handle: *const WindowAdapterRcOpaque) -> IntSize {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
WindowInner::from_pub(window_adapter.window()).inner_size.get().to_euclid().cast()
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_set_physical_size(
handle: *const WindowAdapterRcOpaque,
size: &IntSize,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.window().set_size(crate::api::PhysicalSize::new(size.width, size.height));
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_set_logical_size(
handle: *const WindowAdapterRcOpaque,
size: &Size,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.window().set_size(crate::api::LogicalSize::new(size.width, size.height));
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_dark_color_scheme(
handle: *const WindowAdapterRcOpaque,
) -> bool {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.dark_color_scheme()
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_dispatch_key_event(
handle: *const WindowAdapterRcOpaque,
event: crate::input::KeyInputEvent,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.window().0.process_key_input(event);
}
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_dispatch_pointer_event(
handle: *const WindowAdapterRcOpaque,
event: crate::input::MouseEvent,
) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.window().0.process_mouse_input(event);
}
}