mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 18:58:36 +00:00
api: Change logical/physical position and size on window (#1620)
* Add `RequestedSize` and `RequestedPosition` enum to enable asking for logical or physical size/position. * Rename `Window::size()` to `Window::physical_size()` * Make `Window::set_size(...)` take an `Into<RequestedSize>` * Rename `Window::position()` to `Window::physical_position()` * Make `Window::set_position(...)` take an `Into<RequestedPosition>` * Change `WindowAdapter` and related classes to be able to handle requests being made in the either physical or logical units. Implement this for C++, Rust and node.
This commit is contained in:
parent
9bef6f519a
commit
53a3c72b57
11 changed files with 298 additions and 85 deletions
|
@ -313,9 +313,11 @@ fn gen_corelib(
|
|||
"slint_windowrc_request_redraw",
|
||||
"slint_windowrc_on_close_requested",
|
||||
"slint_windowrc_position",
|
||||
"slint_windowrc_set_position",
|
||||
"slint_windowrc_set_logical_position",
|
||||
"slint_windowrc_set_physical_position",
|
||||
"slint_windowrc_size",
|
||||
"slint_windowrc_set_size",
|
||||
"slint_windowrc_set_logical_size",
|
||||
"slint_windowrc_set_physical_size",
|
||||
"slint_new_path_elements",
|
||||
"slint_new_path_events",
|
||||
"slint_color_brighter",
|
||||
|
|
|
@ -25,6 +25,8 @@ struct ComponentVTable;
|
|||
struct ItemVTable;
|
||||
}
|
||||
#include "slint_internal.h"
|
||||
#include "slint_size.h"
|
||||
#include "slint_point.h"
|
||||
#include "slint_backend_internal.h"
|
||||
#include "slint_qt_internal.h"
|
||||
#include "slint_selector_internal.h"
|
||||
|
@ -178,23 +180,33 @@ public:
|
|||
|
||||
void request_redraw() const { cbindgen_private::slint_windowrc_request_redraw(&inner); }
|
||||
|
||||
slint::Point<int> position() const
|
||||
slint::PhysicalPosition position() const
|
||||
{
|
||||
slint::Point<int> pos { 0, 0 };
|
||||
slint::PhysicalPosition pos { 0, 0 };
|
||||
cbindgen_private::slint_windowrc_position(&inner, &pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
void set_position(const slint::Point<int> &pos)
|
||||
void set_logical_position(const slint::LogicalPosition &pos)
|
||||
{
|
||||
cbindgen_private::slint_windowrc_set_position(&inner, &pos);
|
||||
cbindgen_private::slint_windowrc_set_logical_position(&inner, &pos);
|
||||
}
|
||||
|
||||
slint::Size<unsigned int> size() const { return cbindgen_private::slint_windowrc_size(&inner); }
|
||||
|
||||
void set_size(const slint::Size<unsigned int> &size)
|
||||
void set_physical_position(const slint::PhysicalPosition &pos)
|
||||
{
|
||||
cbindgen_private::slint_windowrc_set_size(&inner, &size);
|
||||
cbindgen_private::slint_windowrc_set_physical_position(&inner, &pos);
|
||||
}
|
||||
|
||||
slint::PhysicalSize size() const { return cbindgen_private::slint_windowrc_size(&inner); }
|
||||
|
||||
void set_logical_size(const slint::LogicalSize &size)
|
||||
{
|
||||
cbindgen_private::slint_windowrc_set_logical_size(&inner, &size);
|
||||
}
|
||||
|
||||
void set_physical_size(const slint::PhysicalSize &size)
|
||||
{
|
||||
cbindgen_private::slint_windowrc_set_physical_size(&inner, &size);
|
||||
}
|
||||
|
||||
/// Registers a font by the specified path. The path must refer to an existing
|
||||
|
@ -416,20 +428,27 @@ public:
|
|||
|
||||
/// Returns the position of the window on the screen, in physical screen coordinates and
|
||||
/// including a window frame (if present).
|
||||
slint::Point<int> position() const { return inner.position(); }
|
||||
slint::PhysicalPosition position() const { return inner.position(); }
|
||||
|
||||
/// Sets the position of the window on the screen, in physical screen coordinates and including
|
||||
/// a window frame (if present).
|
||||
/// 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); }
|
||||
void set_position(const slint::LogicalPosition &pos) { inner.set_logical_position(pos); }
|
||||
/// Sets the position of the window on the screen, in physical screen coordinates and including
|
||||
/// a window frame (if present).
|
||||
/// Note that on some windowing systems, such as Wayland, this functionality is not available.
|
||||
void set_position(const slint::PhysicalPosition &pos) { inner.set_physical_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(); }
|
||||
slint::PhysicalSize size() const { return inner.size(); }
|
||||
|
||||
/// Resizes the window to the specified size on the screen, in logical pixels and excluding
|
||||
/// a window frame (if present).
|
||||
void set_size(const slint::LogicalSize &size) { inner.set_logical_size(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); }
|
||||
void set_size(const slint::PhysicalSize &size) { inner.set_physical_size(size); }
|
||||
|
||||
/// \private
|
||||
private_api::WindowAdapterRc &window_handle() { return inner; }
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace slint {
|
||||
|
||||
/// The Point structure is used to represent a two-dimensional point
|
||||
|
@ -26,4 +28,9 @@ template<typename T>
|
|||
using Point2D = Point<T>;
|
||||
}
|
||||
|
||||
/// A position in logical pixel coordinates
|
||||
using LogicalPosition = Point<float>;
|
||||
/// A position in physical pixel coordinates
|
||||
using PhysicalPosition = Point<int32_t>;
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace slint {
|
||||
|
||||
/// The Size structure is used to represent a two-dimensional size
|
||||
|
@ -26,4 +28,9 @@ template<typename T>
|
|||
using Size2D = Size<T>;
|
||||
}
|
||||
|
||||
/// A size given in logical pixels
|
||||
using LogicalSize = Size<float>;
|
||||
/// A size given in physical pixels.
|
||||
using PhysicalSize = Size<uint32_t>;
|
||||
|
||||
}
|
||||
|
|
|
@ -55,20 +55,22 @@ class Component {
|
|||
}
|
||||
|
||||
interface Point {
|
||||
x: Number;
|
||||
y: Number;
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface Size {
|
||||
width: Number;
|
||||
height: Number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
interface SlintWindow {
|
||||
show(): void;
|
||||
hide(): void;
|
||||
position: Point;
|
||||
size: Size;
|
||||
logical_position: Point;
|
||||
physical_position: Point;
|
||||
logical_size: Size;
|
||||
physical_size: Size;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,17 +89,29 @@ class WindowAPI implements SlintWindow {
|
|||
hide(): void {
|
||||
this.impl.hide();
|
||||
}
|
||||
get position(): Point {
|
||||
return this.impl.get_position();
|
||||
get logical_position(): Point {
|
||||
return this.impl.get_logical_position();
|
||||
}
|
||||
set position(pos: Point) {
|
||||
this.impl.set_position(pos);
|
||||
set logical_position(pos: Point) {
|
||||
this.impl.set_logical_position(pos);
|
||||
}
|
||||
get size(): Size {
|
||||
return this.impl.get_size();
|
||||
get physical_position(): Point {
|
||||
return this.impl.get_physical_position();
|
||||
}
|
||||
set size(size: Size) {
|
||||
this.impl.set_size(size);
|
||||
set physical_position(pos: Point) {
|
||||
this.impl.set_physical_position(pos);
|
||||
}
|
||||
get logical_size(): Size {
|
||||
return this.impl.get_logical_size();
|
||||
}
|
||||
set logical_size(size: Size) {
|
||||
this.impl.set_logical_size(size);
|
||||
}
|
||||
get physical_size(): Size {
|
||||
return this.impl.get_physical_size();
|
||||
}
|
||||
set physical_size(size: Size) {
|
||||
this.impl.set_physical_size(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -491,24 +491,24 @@ declare_types! {
|
|||
method show(mut cx) {
|
||||
let this = cx.this();
|
||||
let window = cx.borrow(&this, |x| x.0.as_ref().cloned());
|
||||
let window = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
window.show();
|
||||
let window_adapter = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
window_adapter.show();
|
||||
Ok(JsUndefined::new().as_value(&mut cx))
|
||||
}
|
||||
|
||||
method hide(mut cx) {
|
||||
let this = cx.this();
|
||||
let window = cx.borrow(&this, |x| x.0.as_ref().cloned());
|
||||
let window = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
window.hide();
|
||||
let window_adapter = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
window_adapter.hide();
|
||||
Ok(JsUndefined::new().as_value(&mut cx))
|
||||
}
|
||||
|
||||
method get_position(mut cx) {
|
||||
method get_logical_position(mut cx) {
|
||||
let this = cx.this();
|
||||
let window = cx.borrow(&this, |x| x.0.as_ref().cloned());
|
||||
let window = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
let pos = window.position();
|
||||
let window_adapter = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
let pos = window_adapter.position().to_logical(window_adapter.window().scale_factor());
|
||||
|
||||
let point_object = JsObject::new(&mut cx);
|
||||
let x_value = JsNumber::new(&mut cx, pos.x).as_value(&mut cx);
|
||||
|
@ -518,21 +518,63 @@ declare_types! {
|
|||
Ok(point_object.as_value(&mut cx))
|
||||
}
|
||||
|
||||
method set_position(mut cx) {
|
||||
method get_physical_position(mut cx) {
|
||||
let this = cx.this();
|
||||
let window = cx.borrow(&this, |x| x.0.as_ref().cloned());
|
||||
let window = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
let window_adapter = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
let pos = window_adapter.position();
|
||||
|
||||
let point_object = JsObject::new(&mut cx);
|
||||
let x_value = JsNumber::new(&mut cx, pos.x).as_value(&mut cx);
|
||||
point_object.set(&mut cx, "x", x_value)?;
|
||||
let y_value = JsNumber::new(&mut cx, pos.y).as_value(&mut cx);
|
||||
point_object.set(&mut cx, "y", y_value)?;
|
||||
Ok(point_object.as_value(&mut cx))
|
||||
}
|
||||
|
||||
method set_logical_position(mut cx) {
|
||||
let this = cx.this();
|
||||
let window = cx.borrow(&this, |x| x.0.as_ref().cloned());
|
||||
let window_adapter = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
|
||||
let point_object = cx.argument::<JsObject>(0)?;
|
||||
let x = point_object.get(&mut cx, "x")?.downcast_or_throw::<JsNumber, _>(&mut cx)?.value();
|
||||
let y = point_object.get(&mut cx, "y")?.downcast_or_throw::<JsNumber, _>(&mut cx)?.value();
|
||||
|
||||
window.set_position(i_slint_core::api::PhysicalPosition::new(x as i32, y as i32));
|
||||
window_adapter.set_position(i_slint_core::api::LogicalPosition::new(x as f32, y as f32).into());
|
||||
|
||||
Ok(JsUndefined::new().as_value(&mut cx))
|
||||
}
|
||||
|
||||
method get_size(mut cx) {
|
||||
method set_physical_position(mut cx) {
|
||||
let this = cx.this();
|
||||
let window = cx.borrow(&this, |x| x.0.as_ref().cloned());
|
||||
let window_adapter = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
|
||||
let point_object = cx.argument::<JsObject>(0)?;
|
||||
let x = point_object.get(&mut cx, "x")?.downcast_or_throw::<JsNumber, _>(&mut cx)?.value();
|
||||
let y = point_object.get(&mut cx, "y")?.downcast_or_throw::<JsNumber, _>(&mut cx)?.value();
|
||||
|
||||
window_adapter.set_position(i_slint_core::api::PhysicalPosition::new(x as i32, y as i32).into());
|
||||
|
||||
Ok(JsUndefined::new().as_value(&mut cx))
|
||||
}
|
||||
|
||||
method get_logical_size(mut cx) {
|
||||
let this = cx.this();
|
||||
let window_adapter = cx.borrow(&this, |x| x.0.as_ref().cloned());
|
||||
let window_adapter = window_adapter.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
let size = window_adapter.window().size().to_logical(window_adapter.window().scale_factor());
|
||||
|
||||
let size_object = JsObject::new(&mut cx);
|
||||
let width_value = JsNumber::new(&mut cx, size.width).as_value(&mut cx);
|
||||
size_object.set(&mut cx, "width", width_value)?;
|
||||
let height_value = JsNumber::new(&mut cx, size.height).as_value(&mut cx);
|
||||
size_object.set(&mut cx, "height", height_value)?;
|
||||
Ok(size_object.as_value(&mut cx))
|
||||
}
|
||||
|
||||
method get_physical_size(mut cx) {
|
||||
let this = cx.this();
|
||||
let window_adapter = cx.borrow(&this, |x| x.0.as_ref().cloned());
|
||||
let window_adapter = window_adapter.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
|
@ -546,7 +588,22 @@ declare_types! {
|
|||
Ok(size_object.as_value(&mut cx))
|
||||
}
|
||||
|
||||
method set_size(mut cx) {
|
||||
method set_logical_size(mut cx) {
|
||||
let this = cx.this();
|
||||
let window_adapter = cx.borrow(&this, |x| x.0.as_ref().cloned());
|
||||
let window_adapter = window_adapter.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
let window = window_adapter.window();
|
||||
|
||||
let size_object = cx.argument::<JsObject>(0)?;
|
||||
let width = size_object.get(&mut cx, "width")?.downcast_or_throw::<JsNumber, _>(&mut cx)?.value();
|
||||
let height = size_object.get(&mut cx, "height")?.downcast_or_throw::<JsNumber, _>(&mut cx)?.value();
|
||||
|
||||
window.set_size(i_slint_core::api::LogicalSize::new(width as f32, height as f32));
|
||||
|
||||
Ok(JsUndefined::new().as_value(&mut cx))
|
||||
}
|
||||
|
||||
method set_physical_size(mut cx) {
|
||||
let this = cx.this();
|
||||
let window_adapter = cx.borrow(&this, |x| x.0.as_ref().cloned());
|
||||
let window_adapter = window_adapter.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
|
|
|
@ -1576,20 +1576,28 @@ impl WindowAdapterSealed for QtWindow {
|
|||
let qp = cpp! {unsafe [widget_ptr as "QWidget*"] -> qttypes::QPoint as "QPoint" {
|
||||
return widget_ptr->pos();
|
||||
}};
|
||||
i_slint_core::api::PhysicalPosition::new(qp.x as _, qp.y as _)
|
||||
// Qt returns logical coordinates, so scale those!
|
||||
i_slint_core::api::LogicalPosition::new(qp.x as _, qp.y as _)
|
||||
.to_physical(self.window().scale_factor())
|
||||
}
|
||||
|
||||
fn set_position(&self, position: i_slint_core::api::PhysicalPosition) {
|
||||
fn set_position(&self, position: i_slint_core::api::RequestedPosition) {
|
||||
let physical_position = position.to_physical(self.window().scale_factor());
|
||||
let widget_ptr = self.widget_ptr();
|
||||
let pos = qttypes::QPoint { x: position.x as _, y: position.y as _ };
|
||||
let pos = qttypes::QPoint { x: physical_position.x as _, y: physical_position.y as _ };
|
||||
cpp! {unsafe [widget_ptr as "QWidget*", pos as "QPoint"] {
|
||||
widget_ptr->move(pos);
|
||||
}};
|
||||
}
|
||||
|
||||
fn set_inner_size(&self, size: i_slint_core::api::PhysicalSize) {
|
||||
fn set_size(&self, size: i_slint_core::api::RequestedSize) {
|
||||
let logical_size = size.to_logical(self.window().scale_factor());
|
||||
let widget_ptr = self.widget_ptr();
|
||||
let sz = qttypes::QSize { width: size.width as _, height: size.height as _ };
|
||||
let sz = qttypes::QSize {
|
||||
width: logical_size.width.round() as _,
|
||||
height: logical_size.height.round() as _,
|
||||
};
|
||||
// Qt uses logical units!
|
||||
cpp! {unsafe [widget_ptr as "QWidget*", sz as "QSize"] {
|
||||
widget_ptr->resize(sz);
|
||||
}};
|
||||
|
|
|
@ -59,7 +59,7 @@ impl WindowAdapterSealed for TestingWindow {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_position(&self, _position: i_slint_core::api::PhysicalPosition) {
|
||||
fn set_position(&self, _position: i_slint_core::api::RequestedPosition) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,28 @@ use corelib::{graphics::*, Coord};
|
|||
use i_slint_core as corelib;
|
||||
use winit::dpi::LogicalSize;
|
||||
|
||||
fn position_to_winit(pos: &corelib::api::RequestedPosition) -> winit::dpi::Position {
|
||||
match pos {
|
||||
corelib::api::RequestedPosition::Logical(pos) => {
|
||||
winit::dpi::Position::new(winit::dpi::LogicalPosition::new(pos.x, pos.y))
|
||||
}
|
||||
corelib::api::RequestedPosition::Physical(pos) => {
|
||||
winit::dpi::Position::new(winit::dpi::PhysicalPosition::new(pos.x, pos.y))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size_to_winit(pos: &corelib::api::RequestedSize) -> winit::dpi::Size {
|
||||
match pos {
|
||||
corelib::api::RequestedSize::Logical(size) => {
|
||||
winit::dpi::Size::new(winit::dpi::LogicalSize::new(size.width, size.height))
|
||||
}
|
||||
corelib::api::RequestedSize::Physical(size) => {
|
||||
winit::dpi::Size::new(winit::dpi::PhysicalSize::new(size.width, size.height))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// GraphicsWindow is an implementation of the [WindowAdapter][`crate::eventloop::WindowAdapter`] trait. This is
|
||||
/// typically instantiated by entry factory functions of the different graphics back ends.
|
||||
pub(crate) struct GLWindow<Renderer: WinitCompatibleRenderer + 'static> {
|
||||
|
@ -318,9 +340,7 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WindowAdapterSealed for GLWind
|
|||
if must_resize {
|
||||
let win = self.window();
|
||||
|
||||
win.set_size(
|
||||
i_slint_core::api::LogicalSize::new(width, height).to_physical(win.scale_factor()),
|
||||
);
|
||||
win.set_size(i_slint_core::api::LogicalSize::new(width, height));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,12 +478,20 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WindowAdapterSealed for GLWind
|
|||
))
|
||||
}
|
||||
|
||||
if let Some(requested_size) = requested_size {
|
||||
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),
|
||||
))
|
||||
if let Some(sf) = scale_factor_override {
|
||||
let physical_size = requested_size.to_physical(sf as f32);
|
||||
window_builder.with_inner_size(winit::dpi::Size::new(
|
||||
winit::dpi::PhysicalSize::new(
|
||||
physical_size.width,
|
||||
physical_size.height,
|
||||
),
|
||||
))
|
||||
} else {
|
||||
window_builder.with_inner_size(size_to_winit(requested_size))
|
||||
}
|
||||
} 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.
|
||||
|
@ -477,10 +505,8 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WindowAdapterSealed for GLWind
|
|||
let window_builder =
|
||||
if no_frame { window_builder.with_decorations(false) } else { window_builder };
|
||||
|
||||
let window_builder = if let Some(requested_position) = requested_position {
|
||||
window_builder.with_position(winit::dpi::Position::new(
|
||||
winit::dpi::PhysicalPosition::new(requested_position.x, requested_position.y),
|
||||
))
|
||||
let window_builder = if let Some(pos) = &requested_position {
|
||||
window_builder.with_position(position_to_winit(pos))
|
||||
} else {
|
||||
window_builder
|
||||
};
|
||||
|
@ -590,9 +616,10 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WindowAdapterSealed for GLWind
|
|||
|
||||
fn position(&self) -> corelib::api::PhysicalPosition {
|
||||
match &*self.map_state.borrow() {
|
||||
GraphicsWindowBackendState::Unmapped { requested_position, .. } => {
|
||||
requested_position.unwrap_or_default()
|
||||
}
|
||||
GraphicsWindowBackendState::Unmapped { requested_position, .. } => requested_position
|
||||
.as_ref()
|
||||
.map(|p| p.to_physical(self.window().scale_factor()))
|
||||
.unwrap_or_default(),
|
||||
GraphicsWindowBackendState::Mapped(mapped_window) => mapped_window
|
||||
.canvas
|
||||
.with_window_handle(|winit_window| match winit_window.outer_position() {
|
||||
|
@ -604,22 +631,20 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WindowAdapterSealed for GLWind
|
|||
}
|
||||
}
|
||||
|
||||
fn set_position(&self, position: corelib::api::PhysicalPosition) {
|
||||
fn set_position(&self, position: corelib::api::RequestedPosition) {
|
||||
match &mut *self.map_state.borrow_mut() {
|
||||
GraphicsWindowBackendState::Unmapped { requested_position, .. } => {
|
||||
*requested_position = Some(position)
|
||||
}
|
||||
GraphicsWindowBackendState::Mapped(mapped_window) => {
|
||||
mapped_window.canvas.with_window_handle(|winit_window| {
|
||||
winit_window.set_outer_position(winit::dpi::Position::new(
|
||||
winit::dpi::PhysicalPosition::new(position.x, position.y),
|
||||
))
|
||||
winit_window.set_outer_position(position_to_winit(&position))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_inner_size(&self, size: corelib::api::PhysicalSize) {
|
||||
fn set_size(&self, size: corelib::api::RequestedSize) {
|
||||
if let Ok(mut map_state) = self.map_state.try_borrow_mut() {
|
||||
// otherwise we are called from the resize event
|
||||
match &mut *map_state {
|
||||
|
@ -628,8 +653,7 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WindowAdapterSealed for GLWind
|
|||
}
|
||||
GraphicsWindowBackendState::Mapped(mapped_window) => {
|
||||
mapped_window.canvas.with_window_handle(|winit_window| {
|
||||
winit_window
|
||||
.set_inner_size(winit::dpi::PhysicalSize::new(size.width, size.height));
|
||||
winit_window.set_inner_size(size_to_winit(&size));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -650,8 +674,8 @@ struct MappedWindow<Renderer: WinitCompatibleRenderer> {
|
|||
|
||||
enum GraphicsWindowBackendState<Renderer: WinitCompatibleRenderer> {
|
||||
Unmapped {
|
||||
requested_position: Option<corelib::api::PhysicalPosition>,
|
||||
requested_size: Option<corelib::api::PhysicalSize>,
|
||||
requested_position: Option<corelib::api::RequestedPosition>,
|
||||
requested_size: Option<corelib::api::RequestedSize>,
|
||||
},
|
||||
Mapped(MappedWindow<Renderer>),
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ impl LogicalPosition {
|
|||
|
||||
/// A position represented in the coordinate space of physical device pixels. That is the space after applying
|
||||
/// a display device specific scale factor to pixels from the logical coordinate space.
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct PhysicalPosition {
|
||||
/// The x coordinate.
|
||||
pub x: i32,
|
||||
|
@ -81,9 +81,28 @@ impl PhysicalPosition {
|
|||
}
|
||||
}
|
||||
|
||||
/// The requested position to render the window at.
|
||||
#[derive(Clone, Debug, derive_more::From, PartialEq)]
|
||||
pub enum RequestedPosition {
|
||||
/// In physical screen coordinates
|
||||
Physical(PhysicalPosition),
|
||||
/// In logical screen coordinates
|
||||
Logical(LogicalPosition),
|
||||
}
|
||||
|
||||
impl RequestedPosition {
|
||||
/// Turn the `RequestedPosition` into a `PhysicalPosition`.
|
||||
pub fn to_physical(&self, scale_factor: f32) -> PhysicalPosition {
|
||||
match self {
|
||||
RequestedPosition::Physical(pos) => pos.clone(),
|
||||
RequestedPosition::Logical(pos) => pos.to_physical(scale_factor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A size represented in the coordinate space of logical pixels. That is the space before applying
|
||||
/// a display device specific scale factor.
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq)]
|
||||
pub struct LogicalSize {
|
||||
/// The width in logical pixels.
|
||||
pub width: f32,
|
||||
|
@ -122,7 +141,7 @@ impl LogicalSize {
|
|||
|
||||
/// A size represented in the coordinate space of physical device pixels. That is the space after applying
|
||||
/// a display device specific scale factor to pixels from the logical coordinate space.
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct PhysicalSize {
|
||||
/// The width in physical pixels.
|
||||
pub width: u32,
|
||||
|
@ -158,6 +177,33 @@ impl PhysicalSize {
|
|||
}
|
||||
}
|
||||
|
||||
/// The requested size to render the window.
|
||||
#[derive(Clone, Debug, derive_more::From, PartialEq)]
|
||||
pub enum RequestedSize {
|
||||
/// In physical screen pixels.
|
||||
Physical(PhysicalSize),
|
||||
/// In logical screen pixels.
|
||||
Logical(LogicalSize),
|
||||
}
|
||||
|
||||
impl RequestedSize {
|
||||
/// Turn the `RequestedSize` into a `PhysicalSize`.
|
||||
pub fn to_physical(&self, scale_factor: f32) -> PhysicalSize {
|
||||
match self {
|
||||
RequestedSize::Physical(size) => size.clone(),
|
||||
RequestedSize::Logical(size) => size.to_physical(scale_factor),
|
||||
}
|
||||
}
|
||||
|
||||
/// Turn the `RequestedSize` into a `LogicalSize`.
|
||||
pub fn to_logical(&self, scale_factor: f32) -> LogicalSize {
|
||||
match self {
|
||||
RequestedSize::Physical(size) => size.to_logical(scale_factor),
|
||||
RequestedSize::Logical(size) => size.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This enum describes a low-level access to specific graphics APIs used
|
||||
/// by the renderer.
|
||||
#[derive(Clone)]
|
||||
|
@ -344,7 +390,8 @@ impl Window {
|
|||
/// Sets the position of the window on the screen, in physical screen coordinates and including
|
||||
/// a window frame (if present).
|
||||
/// Note that on some windowing systems, such as Wayland, this functionality is not available.
|
||||
pub fn set_position(&self, position: PhysicalPosition) {
|
||||
pub fn set_position(&self, position: impl Into<RequestedPosition>) {
|
||||
let position = position.into();
|
||||
self.0.window_adapter().set_position(position)
|
||||
}
|
||||
|
||||
|
@ -356,11 +403,14 @@ impl Window {
|
|||
|
||||
/// 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: PhysicalSize) {
|
||||
pub fn set_size(&self, size: impl Into<RequestedSize>) {
|
||||
let size = size.into();
|
||||
let l = size.to_logical(self.scale_factor());
|
||||
let p = size.to_physical(self.scale_factor());
|
||||
|
||||
self.0.set_window_item_geometry(l.width as _, l.height as _);
|
||||
if self.0.inner_size.replace(size) != size {
|
||||
self.0.window_adapter().set_inner_size(size);
|
||||
if self.0.inner_size.replace(p) != p {
|
||||
self.0.window_adapter().set_size(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
#![warn(missing_docs)]
|
||||
//! Exposed Window API
|
||||
|
||||
use crate::api::{CloseRequestResponse, PhysicalPosition, PhysicalSize, Window};
|
||||
use crate::api::{
|
||||
CloseRequestResponse, PhysicalPosition, PhysicalSize, RequestedPosition, RequestedSize, Window,
|
||||
};
|
||||
use crate::component::{ComponentRc, ComponentRef, ComponentVTable, ComponentWeak};
|
||||
use crate::graphics::{Point, Rect, Size};
|
||||
use crate::input::{
|
||||
|
@ -123,13 +125,13 @@ pub trait WindowAdapterSealed {
|
|||
/// a window frame (if present).
|
||||
///
|
||||
/// The default implementation does nothing
|
||||
fn set_position(&self, _position: PhysicalPosition) {}
|
||||
fn set_position(&self, _position: RequestedPosition) {}
|
||||
|
||||
/// Resizes the window to the specified size on the screen, in physical pixels and excluding
|
||||
/// a window frame (if present).
|
||||
/// Resizes the window to the specified size on the screen, in physical or logical pixels
|
||||
/// and excluding a window frame (if present).
|
||||
///
|
||||
/// The default implementation does nothing
|
||||
fn set_inner_size(&self, _size: PhysicalSize) {}
|
||||
fn set_size(&self, _size: RequestedSize) {}
|
||||
|
||||
/// Return the renderer
|
||||
fn renderer(&self) -> &dyn Renderer;
|
||||
|
@ -928,12 +930,24 @@ pub mod ffi {
|
|||
/// a window frame (if present).
|
||||
/// Note that on some windowing systems, such as Wayland, this functionality is not available.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_set_position(
|
||||
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));
|
||||
window_adapter.set_position(crate::api::PhysicalPosition::new(pos.x, pos.y).into());
|
||||
}
|
||||
|
||||
/// Sets the position of the window on the screen, in physical screen coordinates and including
|
||||
/// a window frame (if present).
|
||||
/// Note that on some windowing systems, such as Wayland, this functionality is not available.
|
||||
#[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());
|
||||
}
|
||||
|
||||
/// Returns the size of the window on the screen, in physical screen coordinates and excluding
|
||||
|
@ -947,11 +961,22 @@ pub mod ffi {
|
|||
/// 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(
|
||||
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.set_inner_size(crate::api::PhysicalSize::new(size.width, size.height));
|
||||
window_adapter.set_size(crate::api::PhysicalSize::new(size.width, size.height).into());
|
||||
}
|
||||
|
||||
/// 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_logical_size(
|
||||
handle: *const WindowAdapterRcOpaque,
|
||||
size: &Size,
|
||||
) {
|
||||
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
|
||||
window_adapter.set_size(crate::api::LogicalSize::new(size.width, size.height).into());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue