mirror of
https://github.com/slint-ui/slint.git
synced 2025-12-23 09:19:32 +00:00
Merge e4c102f407 into f59e8e0d78
This commit is contained in:
commit
55cd440891
36 changed files with 773 additions and 217 deletions
|
|
@ -722,6 +722,14 @@ fn gen_corelib(
|
|||
.body
|
||||
.insert("Flickable".to_owned(), " inline Flickable(); inline ~Flickable();".into());
|
||||
config.export.pre_body.insert("FlickableDataBox".to_owned(), "struct FlickableData;".into());
|
||||
config.export.body.insert(
|
||||
"MouseCursor".to_owned(),
|
||||
" constexpr MouseCursor(MouseCursor::Tag tag = Tag::Default) : tag(tag) {}
|
||||
MouseCursor(MouseCursor::Tag tag, Image image, int hotspot_x, int hotspot_y) : tag(tag), custom_cursor(image, hotspot_x, hotspot_y) {}
|
||||
MouseCursor& operator=(const MouseCursor &other) { tag = other.tag; custom_cursor = other.custom_cursor; return *this; }
|
||||
~MouseCursor() {}
|
||||
".into()
|
||||
);
|
||||
|
||||
cbindgen::Builder::new()
|
||||
.with_config(config)
|
||||
|
|
|
|||
|
|
@ -101,6 +101,17 @@ inline bool operator==(const EasingCurve &a, const EasingCurve &b)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
inline bool operator==(const MouseCursor &a, const MouseCursor &b)
|
||||
{
|
||||
if (a.tag != b.tag) {
|
||||
return false;
|
||||
} else if (a.tag == MouseCursor::Tag::CustomCursor) {
|
||||
return a.custom_cursor.image == b.custom_cursor.image
|
||||
&& a.custom_cursor.hotspot_x == b.custom_cursor.hotspot_x
|
||||
&& a.custom_cursor.hotspot_y == b.custom_cursor.hotspot_y;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace private_api {
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ pub fn to_value(env: &Env, unknown: JsUnknown, typ: &Type) -> Result<Value> {
|
|||
| Type::LayoutCache
|
||||
| Type::ArrayOfU16
|
||||
| Type::ElementReference
|
||||
| Type::StyledText => Err(napi::Error::from_reason("reason")),
|
||||
| Type::StyledText => Err(napi::Error::from_reason("reason")) | Type::Cursor,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1984,6 +1984,15 @@ impl WindowAdapterInternal for QtWindow {
|
|||
|
||||
fn set_mouse_cursor(&self, cursor: MouseCursor) {
|
||||
let widget_ptr = self.widget_ptr();
|
||||
if let MouseCursor::CustomCursor { image, hotspot_x, hotspot_y } = cursor {
|
||||
let pixmap: qttypes::QPixmap =
|
||||
crate::qt_window::image_to_pixmap((&image).into(), None).unwrap_or_default();
|
||||
cpp! {unsafe [widget_ptr as "QWidget*", pixmap as "QPixmap", hotspot_x as "int", hotspot_y as "int"] {
|
||||
widget_ptr->setCursor(QCursor{pixmap, hotspot_x, hotspot_y});
|
||||
}};
|
||||
return;
|
||||
}
|
||||
|
||||
//unidirectional resize cursors are replaced with bidirectional ones
|
||||
let cursor_shape = match cursor {
|
||||
MouseCursor::Default => key_generated::Qt_CursorShape_ArrowCursor,
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ pub struct TestingWindow {
|
|||
window: i_slint_core::api::Window,
|
||||
size: Cell<PhysicalSize>,
|
||||
pub ime_requests: RefCell<Vec<InputMethodRequest>>,
|
||||
pub mouse_cursor: Cell<i_slint_core::items::MouseCursor>,
|
||||
pub mouse_cursor: RefCell<i_slint_core::items::MouseCursor>,
|
||||
}
|
||||
|
||||
impl WindowAdapterInternal for TestingWindow {
|
||||
|
|
@ -117,7 +117,7 @@ impl WindowAdapterInternal for TestingWindow {
|
|||
}
|
||||
|
||||
fn set_mouse_cursor(&self, cursor: i_slint_core::items::MouseCursor) {
|
||||
self.mouse_cursor.set(cursor);
|
||||
self.mouse_cursor.replace(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
use crate::EventResult;
|
||||
use crate::drag_resize_window::{handle_cursor_move_for_resize, handle_resize};
|
||||
use crate::winitwindowadapter::WindowVisibility;
|
||||
use crate::winitwindowadapter::{WindowVisibility, WinitWindowAdapter};
|
||||
use crate::{SharedBackendData, SlintEvent};
|
||||
use corelib::graphics::euclid;
|
||||
use corelib::input::{KeyEvent, KeyEventType, MouseEvent};
|
||||
|
|
@ -175,6 +175,8 @@ impl winit::application::ApplicationHandler<SlintEvent> for EventLoopState {
|
|||
}
|
||||
|
||||
let runtime_window = WindowInner::from_pub(window.window());
|
||||
self.maybe_set_custom_cursor(&window, &event_loop);
|
||||
|
||||
match event {
|
||||
WindowEvent::RedrawRequested => {
|
||||
self.loop_error = window.draw().err();
|
||||
|
|
@ -603,6 +605,20 @@ impl EventLoopState {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets the cursor to a custom source, if it needs to be set.
|
||||
pub fn maybe_set_custom_cursor(
|
||||
&self,
|
||||
window: &WinitWindowAdapter,
|
||||
event_loop: &ActiveEventLoop,
|
||||
) {
|
||||
// If there is a new custom cursor, update it.
|
||||
let custom_cursor_source = window.custom_cursor_source.take();
|
||||
if let Some(source) = custom_cursor_source {
|
||||
let custom_cursor = event_loop.create_custom_cursor(source);
|
||||
window.winit_window().unwrap().set_cursor(custom_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs the event loop and renders the items in the provided `component` in its
|
||||
/// own window.
|
||||
#[cfg(all(not(target_arch = "wasm32"), not(ios_and_friends)))]
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ use i_slint_core::{self as corelib};
|
|||
use std::cell::OnceCell;
|
||||
#[cfg(any(enable_accesskit, muda))]
|
||||
use winit::event_loop::EventLoopProxy;
|
||||
use winit::window::{WindowAttributes, WindowButtons};
|
||||
use winit::window::{CustomCursor, CustomCursorSource, WindowAttributes, WindowButtons};
|
||||
|
||||
pub(crate) fn position_to_winit(pos: &corelib::api::WindowPosition) -> winit::dpi::Position {
|
||||
match pos {
|
||||
|
|
@ -368,6 +368,8 @@ pub struct WinitWindowAdapter {
|
|||
window_icon_cache_key: RefCell<Option<ImageCacheKey>>,
|
||||
|
||||
frame_throttle: Box<dyn crate::frame_throttle::FrameThrottle>,
|
||||
|
||||
pub(crate) custom_cursor_source: Cell<Option<CustomCursorSource>>,
|
||||
}
|
||||
|
||||
impl WinitWindowAdapter {
|
||||
|
|
@ -416,6 +418,7 @@ impl WinitWindowAdapter {
|
|||
self_weak.clone(),
|
||||
shared_backend_data.is_wayland,
|
||||
),
|
||||
custom_cursor_source: Cell::new(None),
|
||||
});
|
||||
|
||||
self_rc.shared_backend_data.register_inactive_window((self_rc.clone()) as _);
|
||||
|
|
@ -1324,41 +1327,66 @@ impl WindowAdapter for WinitWindowAdapter {
|
|||
|
||||
impl WindowAdapterInternal for WinitWindowAdapter {
|
||||
fn set_mouse_cursor(&self, cursor: MouseCursor) {
|
||||
let winit_cursor = match cursor {
|
||||
MouseCursor::Default => winit::window::CursorIcon::Default,
|
||||
MouseCursor::None => winit::window::CursorIcon::Default,
|
||||
MouseCursor::Help => winit::window::CursorIcon::Help,
|
||||
MouseCursor::Pointer => winit::window::CursorIcon::Pointer,
|
||||
MouseCursor::Progress => winit::window::CursorIcon::Progress,
|
||||
MouseCursor::Wait => winit::window::CursorIcon::Wait,
|
||||
MouseCursor::Crosshair => winit::window::CursorIcon::Crosshair,
|
||||
MouseCursor::Text => winit::window::CursorIcon::Text,
|
||||
MouseCursor::Alias => winit::window::CursorIcon::Alias,
|
||||
MouseCursor::Copy => winit::window::CursorIcon::Copy,
|
||||
MouseCursor::Move => winit::window::CursorIcon::Move,
|
||||
MouseCursor::NoDrop => winit::window::CursorIcon::NoDrop,
|
||||
MouseCursor::NotAllowed => winit::window::CursorIcon::NotAllowed,
|
||||
MouseCursor::Grab => winit::window::CursorIcon::Grab,
|
||||
MouseCursor::Grabbing => winit::window::CursorIcon::Grabbing,
|
||||
MouseCursor::ColResize => winit::window::CursorIcon::ColResize,
|
||||
MouseCursor::RowResize => winit::window::CursorIcon::RowResize,
|
||||
MouseCursor::NResize => winit::window::CursorIcon::NResize,
|
||||
MouseCursor::EResize => winit::window::CursorIcon::EResize,
|
||||
MouseCursor::SResize => winit::window::CursorIcon::SResize,
|
||||
MouseCursor::WResize => winit::window::CursorIcon::WResize,
|
||||
MouseCursor::NeResize => winit::window::CursorIcon::NeResize,
|
||||
MouseCursor::NwResize => winit::window::CursorIcon::NwResize,
|
||||
MouseCursor::SeResize => winit::window::CursorIcon::SeResize,
|
||||
MouseCursor::SwResize => winit::window::CursorIcon::SwResize,
|
||||
MouseCursor::EwResize => winit::window::CursorIcon::EwResize,
|
||||
MouseCursor::NsResize => winit::window::CursorIcon::NsResize,
|
||||
MouseCursor::NeswResize => winit::window::CursorIcon::NeswResize,
|
||||
MouseCursor::NwseResize => winit::window::CursorIcon::NwseResize,
|
||||
_ => winit::window::CursorIcon::Default,
|
||||
let winit_cursor = match &cursor {
|
||||
MouseCursor::Default => Some(winit::window::CursorIcon::Default),
|
||||
MouseCursor::None => Some(winit::window::CursorIcon::Default),
|
||||
MouseCursor::Help => Some(winit::window::CursorIcon::Help),
|
||||
MouseCursor::Pointer => Some(winit::window::CursorIcon::Pointer),
|
||||
MouseCursor::Progress => Some(winit::window::CursorIcon::Progress),
|
||||
MouseCursor::Wait => Some(winit::window::CursorIcon::Wait),
|
||||
MouseCursor::Crosshair => Some(winit::window::CursorIcon::Crosshair),
|
||||
MouseCursor::Text => Some(winit::window::CursorIcon::Text),
|
||||
MouseCursor::Alias => Some(winit::window::CursorIcon::Alias),
|
||||
MouseCursor::Copy => Some(winit::window::CursorIcon::Copy),
|
||||
MouseCursor::Move => Some(winit::window::CursorIcon::Move),
|
||||
MouseCursor::NoDrop => Some(winit::window::CursorIcon::NoDrop),
|
||||
MouseCursor::NotAllowed => Some(winit::window::CursorIcon::NotAllowed),
|
||||
MouseCursor::Grab => Some(winit::window::CursorIcon::Grab),
|
||||
MouseCursor::Grabbing => Some(winit::window::CursorIcon::Grabbing),
|
||||
MouseCursor::ColResize => Some(winit::window::CursorIcon::ColResize),
|
||||
MouseCursor::RowResize => Some(winit::window::CursorIcon::RowResize),
|
||||
MouseCursor::NResize => Some(winit::window::CursorIcon::NResize),
|
||||
MouseCursor::EResize => Some(winit::window::CursorIcon::EResize),
|
||||
MouseCursor::SResize => Some(winit::window::CursorIcon::SResize),
|
||||
MouseCursor::WResize => Some(winit::window::CursorIcon::WResize),
|
||||
MouseCursor::NeResize => Some(winit::window::CursorIcon::NeResize),
|
||||
MouseCursor::NwResize => Some(winit::window::CursorIcon::NwResize),
|
||||
MouseCursor::SeResize => Some(winit::window::CursorIcon::SeResize),
|
||||
MouseCursor::SwResize => Some(winit::window::CursorIcon::SwResize),
|
||||
MouseCursor::EwResize => Some(winit::window::CursorIcon::EwResize),
|
||||
MouseCursor::NsResize => Some(winit::window::CursorIcon::NsResize),
|
||||
MouseCursor::NeswResize => Some(winit::window::CursorIcon::NeswResize),
|
||||
MouseCursor::NwseResize => Some(winit::window::CursorIcon::NwseResize),
|
||||
MouseCursor::CustomCursor { image, hotspot_x, hotspot_y } => {
|
||||
if let Some(rgba8) = image.to_rgba8() {
|
||||
let rgba_vec = rgba8.as_slice().to_vec();
|
||||
let rgba = rgba_vec
|
||||
.iter()
|
||||
.map(|c| vec![c.r, c.g, c.b, c.a])
|
||||
.flatten()
|
||||
.collect::<Vec<u8>>();
|
||||
let size = image.size();
|
||||
let source = CustomCursor::from_rgba(
|
||||
rgba,
|
||||
size.width as u16,
|
||||
size.height as u16,
|
||||
*hotspot_x as u16,
|
||||
*hotspot_y as u16,
|
||||
);
|
||||
|
||||
// Custom cursors have to be set during the event loop
|
||||
self.custom_cursor_source.set(source.ok());
|
||||
}
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
if let Some(winit_window) = self.winit_window_or_none.borrow().as_window() {
|
||||
winit_window.set_cursor_visible(cursor != MouseCursor::None);
|
||||
winit_window.set_cursor(winit_cursor);
|
||||
|
||||
if let Some(cursor) = winit_cursor {
|
||||
winit_window.set_cursor(cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -187,77 +187,6 @@ macro_rules! for_each_enums {
|
|||
Forward,
|
||||
}
|
||||
|
||||
/// This enum represents different types of mouse cursors. It's a subset of the mouse cursors available in CSS.
|
||||
/// For details and pictograms see the [MDN Documentation for cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#values).
|
||||
/// Depending on the backend and used OS unidirectional resize cursors may be replaced with bidirectional ones.
|
||||
#[non_exhaustive]
|
||||
enum MouseCursor {
|
||||
/// The systems default cursor.
|
||||
Default,
|
||||
/// No cursor is displayed.
|
||||
None,
|
||||
//context_menu,
|
||||
/// A cursor indicating help information.
|
||||
Help,
|
||||
/// A pointing hand indicating a link.
|
||||
Pointer,
|
||||
/// The program is busy but can still be interacted with.
|
||||
Progress,
|
||||
/// The program is busy.
|
||||
Wait,
|
||||
//cell,
|
||||
/// A crosshair.
|
||||
Crosshair,
|
||||
/// A cursor indicating selectable text.
|
||||
Text,
|
||||
//vertical_text,
|
||||
/// An alias or shortcut is being created.
|
||||
Alias,
|
||||
/// A copy is being created.
|
||||
Copy,
|
||||
/// Something is to be moved.
|
||||
Move,
|
||||
/// Something can't be dropped here.
|
||||
NoDrop,
|
||||
/// An action isn't allowed
|
||||
NotAllowed,
|
||||
/// Something is grabbable.
|
||||
Grab,
|
||||
/// Something is being grabbed.
|
||||
Grabbing,
|
||||
//all_scroll,
|
||||
/// Indicating that a column is resizable horizontally.
|
||||
ColResize,
|
||||
/// Indicating that a row is resizable vertically.
|
||||
RowResize,
|
||||
/// Unidirectional resize north.
|
||||
NResize,
|
||||
/// Unidirectional resize east.
|
||||
EResize,
|
||||
/// Unidirectional resize south.
|
||||
SResize,
|
||||
/// Unidirectional resize west.
|
||||
WResize,
|
||||
/// Unidirectional resize north-east.
|
||||
NeResize,
|
||||
/// Unidirectional resize north-west.
|
||||
NwResize,
|
||||
/// Unidirectional resize south-east.
|
||||
SeResize,
|
||||
/// Unidirectional resize south-west.
|
||||
SwResize,
|
||||
/// Bidirectional resize east-west.
|
||||
EwResize,
|
||||
/// Bidirectional resize north-south.
|
||||
NsResize,
|
||||
/// Bidirectional resize north-east-south-west.
|
||||
NeswResize,
|
||||
/// Bidirectional resize north-west-south-east.
|
||||
NwseResize,
|
||||
//zoom_in,
|
||||
//zoom_out,
|
||||
}
|
||||
|
||||
/// This enum defines how the source image shall fit into an `Image` element.
|
||||
#[non_exhaustive]
|
||||
enum ImageFit {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
use crate::diagnostics::{BuildDiagnostics, Spanned};
|
||||
use crate::expression_tree::{
|
||||
BuiltinFunction, BuiltinMacroFunction, Callable, EasingCurve, Expression, MinMaxOp, Unit,
|
||||
BuiltinFunction, BuiltinMacroFunction, Callable, EasingCurve, Expression, ImageReference,
|
||||
MinMaxOp, MouseCursor, Unit,
|
||||
};
|
||||
use crate::langtype::Type;
|
||||
use crate::parser::NodeOrToken;
|
||||
|
|
@ -87,6 +88,69 @@ pub fn lower_macro(
|
|||
}
|
||||
BuiltinMacroFunction::Rgb => rgb_macro(n, sub_expr.collect(), diag),
|
||||
BuiltinMacroFunction::Hsv => hsv_macro(n, sub_expr.collect(), diag),
|
||||
BuiltinMacroFunction::CustomCursor => {
|
||||
let mut has_error = None;
|
||||
let image_expected_argument_type_error =
|
||||
"First argument to custom cursor must be image";
|
||||
let hotspot_expected_argument_type_error =
|
||||
"Last arguments to custom cursor must be number literal";
|
||||
let mut image = || match sub_expr.next() {
|
||||
None => {
|
||||
has_error.get_or_insert((n.to_source_location(), "Not enough arguments"));
|
||||
ImageReference::None
|
||||
}
|
||||
Some((Expression::ImageReference { resource_ref, .. }, _)) => resource_ref,
|
||||
Some((_, n)) => {
|
||||
has_error.get_or_insert((
|
||||
n.to_source_location(),
|
||||
image_expected_argument_type_error,
|
||||
));
|
||||
ImageReference::None
|
||||
}
|
||||
};
|
||||
let image = image();
|
||||
|
||||
let mut hotspot_coord = || match sub_expr.next() {
|
||||
None => {
|
||||
has_error.get_or_insert((n.to_source_location(), "Not enough arguments"));
|
||||
0
|
||||
}
|
||||
Some((Expression::NumberLiteral(val, Unit::None), _)) => val as i32,
|
||||
// handle negative numbers
|
||||
Some((Expression::UnaryOp { sub, op: '-' }, n)) => match *sub {
|
||||
Expression::NumberLiteral(val, Unit::None) => -val as i32,
|
||||
_ => {
|
||||
has_error.get_or_insert((
|
||||
n.to_source_location(),
|
||||
hotspot_expected_argument_type_error,
|
||||
));
|
||||
0
|
||||
}
|
||||
},
|
||||
Some((_, n)) => {
|
||||
has_error.get_or_insert((
|
||||
n.to_source_location(),
|
||||
hotspot_expected_argument_type_error,
|
||||
));
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
let expr = Expression::MouseCursor(MouseCursor::CustomCursor(
|
||||
image,
|
||||
hotspot_coord(),
|
||||
hotspot_coord(),
|
||||
));
|
||||
if let Some((_, n)) = sub_expr.next() {
|
||||
has_error
|
||||
.get_or_insert((n.to_source_location(), "Too many argument for custom cursor"));
|
||||
}
|
||||
if let Some((n, msg)) = has_error {
|
||||
diag.push_error(msg.into(), &n);
|
||||
}
|
||||
|
||||
expr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -348,6 +412,7 @@ fn to_debug_string(
|
|||
| Type::Brush
|
||||
| Type::Image
|
||||
| Type::Easing
|
||||
| Type::Cursor
|
||||
| Type::StyledText
|
||||
| Type::Array(_) => {
|
||||
Expression::StringLiteral("<debug-of-this-type-not-yet-implemented>".into())
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use smol_str::{SmolStr, format_smolstr};
|
|||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
||||
// FIXME remove the pub
|
||||
pub use crate::namedreference::NamedReference;
|
||||
pub use crate::passes::resolving;
|
||||
|
|
@ -144,6 +143,7 @@ pub enum BuiltinMacroFunction {
|
|||
Hsv,
|
||||
/// transform `debug(a, b, c)` into debug `a + " " + b + " " + c`
|
||||
Debug,
|
||||
CustomCursor,
|
||||
}
|
||||
|
||||
macro_rules! declare_builtin_function_types {
|
||||
|
|
@ -729,6 +729,8 @@ pub enum Expression {
|
|||
|
||||
EasingCurve(EasingCurve),
|
||||
|
||||
MouseCursor(MouseCursor),
|
||||
|
||||
LinearGradient {
|
||||
angle: Box<Expression>,
|
||||
/// First expression in the tuple is a color, second expression is the stop position
|
||||
|
|
@ -896,6 +898,7 @@ impl Expression {
|
|||
Expression::StoreLocalVariable { .. } => Type::Void,
|
||||
Expression::ReadLocalVariable { ty, .. } => ty.clone(),
|
||||
Expression::EasingCurve(_) => Type::Easing,
|
||||
Expression::MouseCursor(_) => Type::Cursor,
|
||||
Expression::LinearGradient { .. } => Type::Brush,
|
||||
Expression::RadialGradient { .. } => Type::Brush,
|
||||
Expression::ConicGradient { .. } => Type::Brush,
|
||||
|
|
@ -978,6 +981,7 @@ impl Expression {
|
|||
Expression::StoreLocalVariable { value, .. } => visitor(value),
|
||||
Expression::ReadLocalVariable { .. } => {}
|
||||
Expression::EasingCurve(_) => {}
|
||||
Expression::MouseCursor(_) => {}
|
||||
Expression::LinearGradient { angle, stops } => {
|
||||
visitor(angle);
|
||||
for (c, s) in stops {
|
||||
|
|
@ -1085,6 +1089,7 @@ impl Expression {
|
|||
Expression::StoreLocalVariable { value, .. } => visitor(value),
|
||||
Expression::ReadLocalVariable { .. } => {}
|
||||
Expression::EasingCurve(_) => {}
|
||||
Expression::MouseCursor(_) => {}
|
||||
Expression::LinearGradient { angle, stops } => {
|
||||
visitor(angle);
|
||||
for (c, s) in stops {
|
||||
|
|
@ -1192,6 +1197,7 @@ impl Expression {
|
|||
// We only load what we store, and stores are alredy checked
|
||||
Expression::ReadLocalVariable { .. } => true,
|
||||
Expression::EasingCurve(_) => true,
|
||||
Expression::MouseCursor(_) => true,
|
||||
Expression::LinearGradient { angle, stops } => {
|
||||
angle.is_constant(ga)
|
||||
&& stops.iter().all(|(c, s)| c.is_constant(ga) && s.is_constant(ga))
|
||||
|
|
@ -1449,6 +1455,7 @@ impl Expression {
|
|||
.collect(),
|
||||
},
|
||||
Type::Easing => Expression::EasingCurve(EasingCurve::default()),
|
||||
Type::Cursor => Expression::MouseCursor(MouseCursor::default()),
|
||||
Type::Brush => Expression::Cast {
|
||||
from: Box::new(Expression::default_value_for_type(&Type::Color)),
|
||||
to: Type::Brush,
|
||||
|
|
@ -1725,6 +1732,41 @@ pub enum EasingCurve {
|
|||
// Custom(Box<dyn Fn(f32)->f32>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub enum MouseCursor {
|
||||
#[default]
|
||||
Default,
|
||||
None,
|
||||
Help,
|
||||
Pointer,
|
||||
Progress,
|
||||
Wait,
|
||||
Crosshair,
|
||||
Text,
|
||||
Alias,
|
||||
Copy,
|
||||
Move,
|
||||
NoDrop,
|
||||
NotAllowed,
|
||||
Grab,
|
||||
Grabbing,
|
||||
ColResize,
|
||||
RowResize,
|
||||
NResize,
|
||||
EResize,
|
||||
SResize,
|
||||
WResize,
|
||||
NeResize,
|
||||
NwResize,
|
||||
SeResize,
|
||||
SwResize,
|
||||
EwResize,
|
||||
NsResize,
|
||||
NeswResize,
|
||||
NwseResize,
|
||||
CustomCursor(ImageReference, i32, i32),
|
||||
}
|
||||
|
||||
// The compiler generates ResourceReference::AbsolutePath for all references like @image-url("foo.png")
|
||||
// and the resource lowering path may change this to EmbeddedData if configured.
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -1841,6 +1883,7 @@ pub fn pretty_print(f: &mut dyn std::fmt::Write, expression: &Expression) -> std
|
|||
}
|
||||
Expression::PathData(data) => write!(f, "{data:?}"),
|
||||
Expression::EasingCurve(e) => write!(f, "{e:?}"),
|
||||
Expression::MouseCursor(m) => write!(f, "{m:?}"),
|
||||
Expression::LinearGradient { angle, stops } => {
|
||||
write!(f, "@linear-gradient(")?;
|
||||
pretty_print(f, angle)?;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
// cSpell:ignore cmath constexpr cstdlib decltype intptr itertools nullptr prepended struc subcomponent uintptr vals
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Write;
|
||||
use std::fmt::{Formatter, Write};
|
||||
use std::io::BufWriter;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
|
|
@ -457,7 +457,7 @@ pub mod cpp_ast {
|
|||
}
|
||||
|
||||
use crate::CompilerConfiguration;
|
||||
use crate::expression_tree::{BuiltinFunction, EasingCurve, MinMaxOp};
|
||||
use crate::expression_tree::{BuiltinFunction, EasingCurve, MinMaxOp, MouseCursor};
|
||||
use crate::langtype::{
|
||||
BuiltinPrivateStruct, BuiltinPublicStruct, Enumeration, EnumerationValue, NativeClass,
|
||||
StructName, Type,
|
||||
|
|
@ -559,6 +559,7 @@ impl CppType for Type {
|
|||
Type::ArrayOfU16 => Some("slint::SharedVector<uint16_t>".into()),
|
||||
Type::Easing => Some("slint::cbindgen_private::EasingCurve".into()),
|
||||
Type::StyledText => Some("slint::StyledText".into()),
|
||||
Type::Cursor => Some("slint::cbindgen_private::MouseCursor".into()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -3242,6 +3243,33 @@ fn native_prop_info<'a, 'b>(
|
|||
(&sub_component.items[*item_index].ty, prop_name)
|
||||
}
|
||||
|
||||
impl std::fmt::Display for crate::expression_tree::ImageReference {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
crate::expression_tree::ImageReference::None => write!(f, r#"slint::Image()"#),
|
||||
crate::expression_tree::ImageReference::AbsolutePath(path) => write!(
|
||||
f,
|
||||
r#"slint::Image::load_from_path(slint::SharedString(u8"{}"))"#,
|
||||
escape_string(path.as_str())
|
||||
),
|
||||
crate::expression_tree::ImageReference::EmbeddedData { resource_id, extension } => {
|
||||
let symbol = format!("slint_embedded_resource_{resource_id}");
|
||||
write!(
|
||||
f,
|
||||
r#"slint::private_api::load_image_from_embedded_data({symbol}, "{}")"#,
|
||||
escape_string(extension)
|
||||
)
|
||||
}
|
||||
crate::expression_tree::ImageReference::EmbeddedTexture { resource_id } => {
|
||||
write!(
|
||||
f,
|
||||
"slint::private_api::image_from_embedded_textures(&slint_embedded_resource_{resource_id})"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String {
|
||||
use llr::Expression;
|
||||
match expr {
|
||||
|
|
@ -3550,35 +3578,14 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
|
|||
Expression::UnaryOp { sub, op } => {
|
||||
format!("({op} {sub})", sub = compile_expression(sub, ctx), op = op,)
|
||||
}
|
||||
Expression::ImageReference { resource_ref, nine_slice } => {
|
||||
let image = match resource_ref {
|
||||
crate::expression_tree::ImageReference::None => r#"slint::Image()"#.to_string(),
|
||||
crate::expression_tree::ImageReference::AbsolutePath(path) => format!(
|
||||
r#"slint::Image::load_from_path(slint::SharedString(u8"{}"))"#,
|
||||
escape_string(path.as_str())
|
||||
),
|
||||
crate::expression_tree::ImageReference::EmbeddedData { resource_id, extension } => {
|
||||
let symbol = format!("slint_embedded_resource_{resource_id}");
|
||||
format!(
|
||||
r#"slint::private_api::load_image_from_embedded_data({symbol}, "{}")"#,
|
||||
escape_string(extension)
|
||||
)
|
||||
}
|
||||
crate::expression_tree::ImageReference::EmbeddedTexture { resource_id } => {
|
||||
format!(
|
||||
"slint::private_api::image_from_embedded_textures(&slint_embedded_resource_{resource_id})"
|
||||
)
|
||||
}
|
||||
};
|
||||
match &nine_slice {
|
||||
Some([a, b, c, d]) => {
|
||||
format!(
|
||||
"([&] {{ auto image = {image}; image.set_nine_slice_edges({a}, {b}, {c}, {d}); return image; }})()"
|
||||
)
|
||||
}
|
||||
None => image,
|
||||
Expression::ImageReference { resource_ref, nine_slice } => match &nine_slice {
|
||||
Some([a, b, c, d]) => {
|
||||
format!(
|
||||
"([&] {{ auto image = {resource_ref}; image.set_nine_slice_edges({a}, {b}, {c}, {d}); return image; }})()"
|
||||
)
|
||||
}
|
||||
}
|
||||
None => format!("{resource_ref}"),
|
||||
},
|
||||
Expression::Condition { condition, true_expr, false_expr } => {
|
||||
let ty = expr.ty(ctx);
|
||||
let cond_code = compile_expression(condition, ctx);
|
||||
|
|
@ -3643,6 +3650,96 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
|
|||
)
|
||||
}
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Default) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Default".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::None) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::None".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Help) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Help".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Pointer) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Pointer".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Progress) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Progress".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Wait) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Wait".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Crosshair) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Crosshair".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Text) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Text".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Alias) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Alias".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Copy) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Copy".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Move) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Move".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NoDrop) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::NoDrop".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NotAllowed) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::NotAllowed".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Grab) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Grab".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Grabbing) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::Grabbing".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::ColResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::ColResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::RowResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::RowResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::NResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::EResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::EResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::SResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::SResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::WResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::WResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NeResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::NeResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NwResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::NwResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::SeResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::SeResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::SwResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::SwResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::EwResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::EwResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NsResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::NsResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NeswResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::NeswResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NwseResize) => {
|
||||
"slint::cbindgen_private::MouseCursor::Tag::NwseResize".into()
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::CustomCursor(image, hotspot_x, hotspot_y)) => format!(
|
||||
"slint::cbindgen_private::MouseCursor(slint::cbindgen_private::MouseCursor::Tag::CustomCursor, {image}, {hotspot_x}, {hotspot_y})"
|
||||
),
|
||||
Expression::EasingCurve(EasingCurve::Linear) => {
|
||||
"slint::cbindgen_private::EasingCurve()".into()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Some convention used in the generated code:
|
|||
*/
|
||||
|
||||
use crate::CompilerConfiguration;
|
||||
use crate::expression_tree::{BuiltinFunction, EasingCurve, MinMaxOp, OperatorClass};
|
||||
use crate::expression_tree::{BuiltinFunction, EasingCurve, MinMaxOp, MouseCursor, OperatorClass};
|
||||
use crate::langtype::{Enumeration, EnumerationValue, Struct, StructName, Type};
|
||||
use crate::layout::Orientation;
|
||||
use crate::llr::{
|
||||
|
|
@ -24,7 +24,7 @@ use crate::object_tree::Document;
|
|||
use crate::typeloader::LibraryInfo;
|
||||
use itertools::Either;
|
||||
use proc_macro2::{Ident, TokenStream, TokenTree};
|
||||
use quote::{format_ident, quote};
|
||||
use quote::{ToTokens, format_ident, quote};
|
||||
use smol_str::SmolStr;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::str::FromStr;
|
||||
|
|
@ -82,6 +82,7 @@ pub fn rust_primitive_type(ty: &Type) -> Option<proc_macro2::TokenStream> {
|
|||
Type::String => Some(quote!(sp::SharedString)),
|
||||
Type::Color => Some(quote!(sp::Color)),
|
||||
Type::Easing => Some(quote!(sp::EasingCurve)),
|
||||
Type::Cursor => Some(quote!(sp::MouseCursor)),
|
||||
Type::ComponentFactory => Some(quote!(slint::ComponentFactory)),
|
||||
Type::Duration => Some(quote!(i64)),
|
||||
Type::Angle => Some(quote!(f32)),
|
||||
|
|
@ -127,6 +128,7 @@ fn rust_property_type(ty: &Type) -> Option<proc_macro2::TokenStream> {
|
|||
match ty {
|
||||
Type::LogicalLength => Some(quote!(sp::LogicalLength)),
|
||||
Type::Easing => Some(quote!(sp::EasingCurve)),
|
||||
Type::Cursor => Some(quote!(sp::MouseCursor)),
|
||||
_ => rust_primitive_type(ty),
|
||||
}
|
||||
}
|
||||
|
|
@ -2272,6 +2274,32 @@ fn access_item_rc(pr: &llr::MemberReference, ctx: &EvaluationContext) -> TokenSt
|
|||
quote!(&sp::ItemRc::new(#component_rc_tokens, #item_index_tokens))
|
||||
}
|
||||
|
||||
impl quote::ToTokens for crate::expression_tree::ImageReference {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let tks = match self {
|
||||
crate::expression_tree::ImageReference::None => {
|
||||
quote!(sp::Image::default())
|
||||
}
|
||||
crate::expression_tree::ImageReference::AbsolutePath(path) => {
|
||||
let path = path.as_str();
|
||||
quote!(sp::Image::load_from_path(::std::path::Path::new(#path)).unwrap_or_default())
|
||||
}
|
||||
crate::expression_tree::ImageReference::EmbeddedData { resource_id, extension } => {
|
||||
let symbol = format_ident!("SLINT_EMBEDDED_RESOURCE_{}", resource_id);
|
||||
let format = proc_macro2::Literal::byte_string(extension.as_bytes());
|
||||
quote!(sp::load_image_from_embedded_data(#symbol.into(), sp::Slice::from_slice(#format)))
|
||||
}
|
||||
crate::expression_tree::ImageReference::EmbeddedTexture { resource_id } => {
|
||||
let symbol = format_ident!("SLINT_EMBEDDED_RESOURCE_{}", resource_id);
|
||||
quote!(
|
||||
sp::Image::from(sp::ImageInner::StaticTextures(&#symbol))
|
||||
)
|
||||
}
|
||||
};
|
||||
tokens.extend(tks);
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream {
|
||||
match expr {
|
||||
Expression::StringLiteral(s) => {
|
||||
|
|
@ -2540,31 +2568,11 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
|
|||
quote!( (#op #sub) )
|
||||
}
|
||||
Expression::ImageReference { resource_ref, nine_slice } => {
|
||||
let image = match resource_ref {
|
||||
crate::expression_tree::ImageReference::None => {
|
||||
quote!(sp::Image::default())
|
||||
}
|
||||
crate::expression_tree::ImageReference::AbsolutePath(path) => {
|
||||
let path = path.as_str();
|
||||
quote!(sp::Image::load_from_path(::std::path::Path::new(#path)).unwrap_or_default())
|
||||
}
|
||||
crate::expression_tree::ImageReference::EmbeddedData { resource_id, extension } => {
|
||||
let symbol = format_ident!("SLINT_EMBEDDED_RESOURCE_{}", resource_id);
|
||||
let format = proc_macro2::Literal::byte_string(extension.as_bytes());
|
||||
quote!(sp::load_image_from_embedded_data(#symbol.into(), sp::Slice::from_slice(#format)))
|
||||
}
|
||||
crate::expression_tree::ImageReference::EmbeddedTexture { resource_id } => {
|
||||
let symbol = format_ident!("SLINT_EMBEDDED_RESOURCE_{}", resource_id);
|
||||
quote!(
|
||||
sp::Image::from(sp::ImageInner::StaticTextures(&#symbol))
|
||||
)
|
||||
}
|
||||
};
|
||||
match &nine_slice {
|
||||
Some([a, b, c, d]) => {
|
||||
quote! {{ let mut image = #image; image.set_nine_slice_edges(#a, #b, #c, #d); image }}
|
||||
quote! {{ let mut image = #resource_ref; image.set_nine_slice_edges(#a, #b, #c, #d); image }}
|
||||
}
|
||||
None => image,
|
||||
None => resource_ref.to_token_stream(),
|
||||
}
|
||||
}
|
||||
Expression::Condition { condition, true_expr, false_expr } => {
|
||||
|
|
@ -2628,6 +2636,96 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
|
|||
let name = ident(name);
|
||||
quote!(#name.clone())
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Default) => {
|
||||
quote!(sp::MouseCursor::Default)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::None) => {
|
||||
quote!(sp::MouseCursor::None)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Help) => {
|
||||
quote!(sp::MouseCursor::Help)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Pointer) => {
|
||||
quote!(sp::MouseCursor::Pointer)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Progress) => {
|
||||
quote!(sp::MouseCursor::Progress)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Wait) => {
|
||||
quote!(sp::MouseCursor::Wait)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Crosshair) => {
|
||||
quote!(sp::MouseCursor::Crosshair)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Text) => {
|
||||
quote!(sp::MouseCursor::Text)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Alias) => {
|
||||
quote!(sp::MouseCursor::Alias)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Copy) => {
|
||||
quote!(sp::MouseCursor::Copy)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Move) => {
|
||||
quote!(sp::MouseCursor::Move)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NoDrop) => {
|
||||
quote!(sp::MouseCursor::NoDrop)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NotAllowed) => {
|
||||
quote!(sp::MouseCursor::NotAllowed)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Grab) => {
|
||||
quote!(sp::MouseCursor::Grab)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::Grabbing) => {
|
||||
quote!(sp::MouseCursor::Grabbing)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::ColResize) => {
|
||||
quote!(sp::MouseCursor::ColResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::RowResize) => {
|
||||
quote!(sp::MouseCursor::RowResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NResize) => {
|
||||
quote!(sp::MouseCursor::NResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::EResize) => {
|
||||
quote!(sp::MouseCursor::EResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::SResize) => {
|
||||
quote!(sp::MouseCursor::SResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::WResize) => {
|
||||
quote!(sp::MouseCursor::WResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NeResize) => {
|
||||
quote!(sp::MouseCursor::NeResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NwResize) => {
|
||||
quote!(sp::MouseCursor::NwResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::SeResize) => {
|
||||
quote!(sp::MouseCursor::SeResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::SwResize) => {
|
||||
quote!(sp::MouseCursor::SwResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::EwResize) => {
|
||||
quote!(sp::MouseCursor::EwResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NsResize) => {
|
||||
quote!(sp::MouseCursor::NsResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NeswResize) => {
|
||||
quote!(sp::MouseCursor::NeswResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::NwseResize) => {
|
||||
quote!(sp::MouseCursor::NwseResize)
|
||||
}
|
||||
Expression::MouseCursor(MouseCursor::CustomCursor(image, hotspot_x, hotspot_y)) => {
|
||||
quote!(sp::MouseCursor::CustomCursor { image: #image, hotspot_y: #hotspot_x, hotspot_x: #hotspot_y })
|
||||
}
|
||||
Expression::EasingCurve(EasingCurve::Linear) => {
|
||||
quote!(sp::EasingCurve::Linear)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ pub enum Type {
|
|||
ArrayOfU16,
|
||||
|
||||
StyledText,
|
||||
Cursor,
|
||||
}
|
||||
|
||||
impl core::cmp::PartialEq for Type {
|
||||
|
|
@ -99,6 +100,7 @@ impl core::cmp::PartialEq for Type {
|
|||
Type::Model => matches!(other, Type::Model),
|
||||
Type::PathData => matches!(other, Type::PathData),
|
||||
Type::Easing => matches!(other, Type::Easing),
|
||||
Type::Cursor => matches!(other, Type::Cursor),
|
||||
Type::Brush => matches!(other, Type::Brush),
|
||||
Type::Array(a) => matches!(other, Type::Array(b) if a == b),
|
||||
Type::Struct(lhs) => {
|
||||
|
|
@ -164,6 +166,7 @@ impl Display for Type {
|
|||
Type::Struct(t) => write!(f, "{t}"),
|
||||
Type::PathData => write!(f, "pathdata"),
|
||||
Type::Easing => write!(f, "easing"),
|
||||
Type::Cursor => write!(f, "MouseCursor"),
|
||||
Type::Brush => write!(f, "brush"),
|
||||
Type::Enumeration(enumeration) => write!(f, "enum {}", enumeration.name),
|
||||
Type::UnitProduct(vec) => {
|
||||
|
|
@ -215,6 +218,7 @@ impl Type {
|
|||
| Self::Image
|
||||
| Self::Bool
|
||||
| Self::Easing
|
||||
| Self::Cursor
|
||||
| Self::Enumeration(_)
|
||||
| Self::ElementReference
|
||||
| Self::Struct { .. }
|
||||
|
|
@ -316,6 +320,7 @@ impl Type {
|
|||
Type::Model => None,
|
||||
Type::PathData => None,
|
||||
Type::Easing => None,
|
||||
Type::Cursor => None,
|
||||
Type::Brush => None,
|
||||
Type::Array(_) => None,
|
||||
Type::Struct { .. } => None,
|
||||
|
|
|
|||
|
|
@ -147,6 +147,8 @@ pub enum Expression {
|
|||
|
||||
EasingCurve(crate::expression_tree::EasingCurve),
|
||||
|
||||
MouseCursor(crate::expression_tree::MouseCursor),
|
||||
|
||||
LinearGradient {
|
||||
angle: Box<Expression>,
|
||||
/// First expression in the tuple is a color, second expression is the stop position
|
||||
|
|
@ -251,6 +253,7 @@ impl Expression {
|
|||
.collect::<Option<_>>()?,
|
||||
},
|
||||
Type::Easing => Expression::EasingCurve(crate::expression_tree::EasingCurve::default()),
|
||||
Type::Cursor => Expression::MouseCursor(crate::expression_tree::MouseCursor::default()),
|
||||
Type::Brush => Expression::Cast {
|
||||
from: Box::new(Expression::default_value_for_type(&Type::Color)?),
|
||||
to: Type::Brush,
|
||||
|
|
@ -309,6 +312,7 @@ impl Expression {
|
|||
Self::Array { element_ty, .. } => Type::Array(element_ty.clone().into()),
|
||||
Self::Struct { ty, .. } => ty.clone().into(),
|
||||
Self::EasingCurve(_) => Type::Easing,
|
||||
Self::MouseCursor(_) => Type::Cursor,
|
||||
Self::LinearGradient { .. } => Type::Brush,
|
||||
Self::RadialGradient { .. } => Type::Brush,
|
||||
Self::ConicGradient { .. } => Type::Brush,
|
||||
|
|
@ -369,6 +373,7 @@ macro_rules! visit_impl {
|
|||
Expression::Array { values, .. } => values.$iter().for_each($visitor),
|
||||
Expression::Struct { values, .. } => values.$values().for_each($visitor),
|
||||
Expression::EasingCurve(_) => {}
|
||||
Expression::MouseCursor(_) => {}
|
||||
Expression::LinearGradient { angle, stops } => {
|
||||
$visitor(angle);
|
||||
for (a, b) in stops {
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ pub fn lower_expression(
|
|||
},
|
||||
tree_Expression::PathData(data) => compile_path(data, ctx),
|
||||
tree_Expression::EasingCurve(x) => llr_Expression::EasingCurve(x.clone()),
|
||||
tree_Expression::MouseCursor(x) => llr_Expression::MouseCursor(x.clone()),
|
||||
tree_Expression::LinearGradient { angle, stops } => llr_Expression::LinearGradient {
|
||||
angle: Box::new(lower_expression(angle, ctx)),
|
||||
stops: stops
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ fn expression_cost(exp: &Expression, ctx: &EvaluationContext) -> isize {
|
|||
Expression::Array { .. } => return isize::MAX,
|
||||
Expression::Struct { .. } => 1,
|
||||
Expression::EasingCurve(_) => 1,
|
||||
Expression::MouseCursor(_) => 1,
|
||||
Expression::LinearGradient { .. } => ALLOC_COST,
|
||||
Expression::RadialGradient { .. } => ALLOC_COST,
|
||||
Expression::ConicGradient { .. } => ALLOC_COST,
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ impl<'a, T> Display for DisplayExpression<'a, T> {
|
|||
values.iter().map(|(k, v)| format!("{}: {}", k, e(v))).join(", ")
|
||||
),
|
||||
Expression::EasingCurve(x) => write!(f, "{x:?}"),
|
||||
Expression::MouseCursor(x) => write!(f, "{x:?}"),
|
||||
Expression::LinearGradient { angle, stops } => write!(
|
||||
f,
|
||||
"@linear-gradient({}, {})",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use std::rc::Rc;
|
|||
|
||||
use crate::diagnostics::{BuildDiagnostics, Spanned};
|
||||
use crate::expression_tree::{
|
||||
BuiltinFunction, BuiltinMacroFunction, Callable, EasingCurve, Expression, Unit,
|
||||
BuiltinFunction, BuiltinMacroFunction, Callable, EasingCurve, Expression, MouseCursor, Unit,
|
||||
};
|
||||
use crate::langtype::{ElementType, Enumeration, EnumerationValue, Type};
|
||||
use crate::namedreference::NamedReference;
|
||||
|
|
@ -117,6 +117,7 @@ pub enum LookupResultCallable {
|
|||
pub enum BuiltinNamespace {
|
||||
Colors,
|
||||
Easing,
|
||||
Cursor,
|
||||
Math,
|
||||
Key,
|
||||
SlintInternal,
|
||||
|
|
@ -198,6 +199,9 @@ impl LookupObject for LookupResult {
|
|||
LookupResult::Namespace(BuiltinNamespace::Easing) => {
|
||||
EasingSpecific.for_each_entry(ctx, f)
|
||||
}
|
||||
LookupResult::Namespace(BuiltinNamespace::Cursor) => {
|
||||
CursorSpecific.for_each_entry(ctx, f)
|
||||
}
|
||||
LookupResult::Namespace(BuiltinNamespace::Math) => MathFunctions.for_each_entry(ctx, f),
|
||||
LookupResult::Namespace(BuiltinNamespace::Key) => KeysLookup.for_each_entry(ctx, f),
|
||||
LookupResult::Namespace(BuiltinNamespace::SlintInternal) => {
|
||||
|
|
@ -215,6 +219,7 @@ impl LookupObject for LookupResult {
|
|||
(ColorSpecific, ColorFunctions).lookup(ctx, name)
|
||||
}
|
||||
LookupResult::Namespace(BuiltinNamespace::Easing) => EasingSpecific.lookup(ctx, name),
|
||||
LookupResult::Namespace(BuiltinNamespace::Cursor) => CursorSpecific.lookup(ctx, name),
|
||||
LookupResult::Namespace(BuiltinNamespace::Math) => MathFunctions.lookup(ctx, name),
|
||||
LookupResult::Namespace(BuiltinNamespace::Key) => KeysLookup.lookup(ctx, name),
|
||||
LookupResult::Namespace(BuiltinNamespace::SlintInternal) => {
|
||||
|
|
@ -591,6 +596,7 @@ impl LookupObject for ReturnTypeSpecificLookup {
|
|||
Type::Color => ColorSpecific.for_each_entry(ctx, f),
|
||||
Type::Brush => ColorSpecific.for_each_entry(ctx, f),
|
||||
Type::Easing => EasingSpecific.for_each_entry(ctx, f),
|
||||
Type::Cursor => CursorSpecific.for_each_entry(ctx, f),
|
||||
Type::Enumeration(enumeration) => enumeration.clone().for_each_entry(ctx, f),
|
||||
_ => None,
|
||||
}
|
||||
|
|
@ -601,6 +607,7 @@ impl LookupObject for ReturnTypeSpecificLookup {
|
|||
Type::Color => ColorSpecific.lookup(ctx, name),
|
||||
Type::Brush => ColorSpecific.lookup(ctx, name),
|
||||
Type::Easing => EasingSpecific.lookup(ctx, name),
|
||||
Type::Cursor => CursorSpecific.lookup(ctx, name),
|
||||
Type::Enumeration(enumeration) => enumeration.clone().lookup(ctx, name),
|
||||
_ => None,
|
||||
}
|
||||
|
|
@ -705,6 +712,48 @@ impl LookupObject for EasingSpecific {
|
|||
}
|
||||
}
|
||||
|
||||
struct CursorSpecific;
|
||||
impl LookupObject for CursorSpecific {
|
||||
fn for_each_entry<R>(
|
||||
&self,
|
||||
_ctx: &LookupCtx,
|
||||
f: &mut impl FnMut(&SmolStr, LookupResult) -> Option<R>,
|
||||
) -> Option<R> {
|
||||
let mut curve = |n, e| f(&SmolStr::new_static(n), Expression::MouseCursor(e).into());
|
||||
let r = None
|
||||
.or_else(|| curve("default", MouseCursor::Default))
|
||||
.or_else(|| curve("none", MouseCursor::None))
|
||||
.or_else(|| curve("help", MouseCursor::Help))
|
||||
.or_else(|| curve("pointer", MouseCursor::Pointer))
|
||||
.or_else(|| curve("progress", MouseCursor::Progress))
|
||||
.or_else(|| curve("wait", MouseCursor::Wait))
|
||||
.or_else(|| curve("crosshair", MouseCursor::Crosshair))
|
||||
.or_else(|| curve("text", MouseCursor::Text))
|
||||
.or_else(|| curve("alias", MouseCursor::Alias))
|
||||
.or_else(|| curve("copy", MouseCursor::Copy))
|
||||
.or_else(|| curve("move", MouseCursor::Move))
|
||||
.or_else(|| curve("no-drop", MouseCursor::NoDrop))
|
||||
.or_else(|| curve("not-allowed", MouseCursor::NotAllowed))
|
||||
.or_else(|| curve("grab", MouseCursor::Grab))
|
||||
.or_else(|| curve("grabbing", MouseCursor::Grabbing))
|
||||
.or_else(|| curve("col-resize", MouseCursor::ColResize))
|
||||
.or_else(|| curve("row-resize", MouseCursor::RowResize))
|
||||
.or_else(|| curve("n-resize", MouseCursor::NResize))
|
||||
.or_else(|| curve("e-resize", MouseCursor::EResize))
|
||||
.or_else(|| curve("s-resize", MouseCursor::SResize))
|
||||
.or_else(|| curve("w-resize", MouseCursor::WResize))
|
||||
.or_else(|| curve("ne-resize", MouseCursor::NeResize))
|
||||
.or_else(|| curve("nw-resize", MouseCursor::NwResize))
|
||||
.or_else(|| curve("se-resize", MouseCursor::SeResize))
|
||||
.or_else(|| curve("sw-resize", MouseCursor::SwResize))
|
||||
.or_else(|| curve("ew-resize", MouseCursor::EwResize))
|
||||
.or_else(|| curve("ns-resize", MouseCursor::NsResize))
|
||||
.or_else(|| curve("nesw-resize", MouseCursor::NeswResize))
|
||||
.or_else(|| curve("nwse-resize", MouseCursor::NwseResize));
|
||||
r.or_else(|| f(&SmolStr::new_static("custom"), BuiltinMacroFunction::CustomCursor.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl LookupObject for Rc<Enumeration> {
|
||||
fn for_each_entry<R>(
|
||||
&self,
|
||||
|
|
@ -848,6 +897,7 @@ impl LookupObject for BuiltinNamespaceLookup {
|
|||
let mut f = |s, res| f(&SmolStr::new_static(s), res);
|
||||
None.or_else(|| f("Colors", LookupResult::Namespace(BuiltinNamespace::Colors)))
|
||||
.or_else(|| f("Easing", LookupResult::Namespace(BuiltinNamespace::Easing)))
|
||||
.or_else(|| f("MouseCursor", LookupResult::Namespace(BuiltinNamespace::Cursor)))
|
||||
.or_else(|| f("Math", LookupResult::Namespace(BuiltinNamespace::Math)))
|
||||
.or_else(|| f("Key", LookupResult::Namespace(BuiltinNamespace::Key)))
|
||||
.or_else(|| {
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ fn without_side_effects(expression: &Expression) -> bool {
|
|||
Expression::Struct { ty: _, values } => values.values().all(without_side_effects),
|
||||
Expression::PathData(_) => true,
|
||||
Expression::EasingCurve(_) => true,
|
||||
Expression::MouseCursor(_) => true,
|
||||
Expression::LinearGradient { angle, stops } => {
|
||||
without_side_effects(angle)
|
||||
&& stops
|
||||
|
|
|
|||
49
internal/compiler/tests/syntax/elements/toucharea.slint
Normal file
49
internal/compiler/tests/syntax/elements/toucharea.slint
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
||||
|
||||
export component Def {
|
||||
// Unnamespaced access
|
||||
TouchArea {
|
||||
mouse-cursor: ew-resize;
|
||||
}
|
||||
|
||||
// Namespaced access
|
||||
TouchArea {
|
||||
mouse-cursor: MouseCursor.ew-resize;
|
||||
}
|
||||
|
||||
// Custom cursor macro
|
||||
TouchArea {
|
||||
mouse-cursor: MouseCursor.custom(@image-url("cursor.png"), 0, 0);
|
||||
}
|
||||
|
||||
// Invalid unnamespaced access
|
||||
TouchArea {
|
||||
mouse-cursor: square-resize;
|
||||
// > <error{Unknown unqualified identifier 'square-resize'}
|
||||
}
|
||||
|
||||
// Invalid namespaced access
|
||||
TouchArea {
|
||||
mouse-cursor: MouseCursor.square-resize;
|
||||
// > <error{'square-resize' is not a member of the namespace Cursor}
|
||||
}
|
||||
|
||||
// Custom cursor macro (one missing argument)
|
||||
TouchArea {
|
||||
mouse-cursor: MouseCursor.custom(@image-url("cursor.png"), 0);
|
||||
// > <error{Not enough arguments}
|
||||
}
|
||||
|
||||
// Custom cursor macro (two missing arguments)
|
||||
TouchArea {
|
||||
mouse-cursor: MouseCursor.custom(@image-url("cursor.png"));
|
||||
// > <error{Not enough arguments}
|
||||
}
|
||||
|
||||
// Custom cursor macro (missing all arguments)
|
||||
TouchArea {
|
||||
mouse-cursor: MouseCursor.custom();
|
||||
// > <error{Not enough arguments}
|
||||
}
|
||||
}
|
||||
|
|
@ -400,6 +400,7 @@ impl TypeRegister {
|
|||
register.insert_type(Type::Model);
|
||||
register.insert_type(Type::Percent);
|
||||
register.insert_type(Type::Easing);
|
||||
register.insert_type(Type::Cursor);
|
||||
register.insert_type(Type::Angle);
|
||||
register.insert_type(Type::Brush);
|
||||
register.insert_type(Type::Rem);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ pub use drag_n_drop::*;
|
|||
mod path;
|
||||
#[cfg(feature = "std")]
|
||||
pub use path::*;
|
||||
pub(crate) mod cursor;
|
||||
pub use cursor::*;
|
||||
|
||||
/// Alias for `&mut dyn ItemRenderer`. Required so cbindgen generates the ItemVTable
|
||||
/// despite the presence of trait object
|
||||
|
|
|
|||
79
internal/core/items/cursor.rs
Normal file
79
internal/core/items/cursor.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
||||
|
||||
/// This enum represents different types of mouse cursors. It's a subset of the mouse cursors available in CSS.
|
||||
/// For details and pictograms see the [MDN Documentation for cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#values).
|
||||
/// Depending on the backend and used OS unidirectional resize cursors may be replaced with bidirectional ones.
|
||||
#[non_exhaustive]
|
||||
#[repr(C, u32)]
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub enum MouseCursor {
|
||||
/// The systems default cursor.
|
||||
#[default]
|
||||
Default,
|
||||
/// No cursor is displayed.
|
||||
None,
|
||||
/// A cursor indicating help information.
|
||||
Help,
|
||||
/// A pointing hand indicating a link.
|
||||
Pointer,
|
||||
/// The program is busy but can still be interacted with.
|
||||
Progress,
|
||||
/// The program is busy.
|
||||
Wait,
|
||||
/// A crosshair.
|
||||
Crosshair,
|
||||
/// A cursor indicating selectable text.
|
||||
Text,
|
||||
/// An alias or shortcut is being created.
|
||||
Alias,
|
||||
/// A copy is being created.
|
||||
Copy,
|
||||
/// Something is to be moved.
|
||||
Move,
|
||||
/// Something can't be dropped here.
|
||||
NoDrop,
|
||||
/// An action isn't allowed
|
||||
NotAllowed,
|
||||
/// Something is grabbable.
|
||||
Grab,
|
||||
/// Something is being grabbed.
|
||||
Grabbing,
|
||||
/// Indicating that a column is resizable horizontally.
|
||||
ColResize,
|
||||
/// Indicating that a row is resizable vertically.
|
||||
RowResize,
|
||||
/// Unidirectional resize north.
|
||||
NResize,
|
||||
/// Unidirectional resize east.
|
||||
EResize,
|
||||
/// Unidirectional resize south.
|
||||
SResize,
|
||||
/// Unidirectional resize west.
|
||||
WResize,
|
||||
/// Unidirectional resize north-east.
|
||||
NeResize,
|
||||
/// Unidirectional resize north-west.
|
||||
NwResize,
|
||||
/// Unidirectional resize south-east.
|
||||
SeResize,
|
||||
/// Unidirectional resize south-west.
|
||||
SwResize,
|
||||
/// Bidirectional resize east-west.
|
||||
EwResize,
|
||||
/// Bidirectional resize north-south.
|
||||
NsResize,
|
||||
/// Bidirectional resize north-east-south-west.
|
||||
NeswResize,
|
||||
/// Bidirectional resize north-west-south-east.
|
||||
NwseResize,
|
||||
/// Custom cursor from an `Image`.
|
||||
CustomCursor {
|
||||
/// Image backing for this cursor.
|
||||
image: crate::graphics::Image,
|
||||
/// Hotspot X.
|
||||
hotspot_x: i32,
|
||||
/// Hotspot Y.
|
||||
hotspot_y: i32,
|
||||
},
|
||||
}
|
||||
|
|
@ -55,6 +55,7 @@ macro_rules! declare_ValueType_2 {
|
|||
crate::items::DropEvent,
|
||||
crate::model::ModelRc<crate::items::MenuEntry>,
|
||||
crate::api::StyledText,
|
||||
crate::items::MouseCursor,
|
||||
$(crate::items::$Name,)*
|
||||
];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -147,6 +147,8 @@ pub enum Value {
|
|||
StyledText(i_slint_core::api::StyledText) = 13,
|
||||
#[doc(hidden)]
|
||||
ArrayOfU16(SharedVector<u16>) = 14,
|
||||
/// A mouse cursor.
|
||||
MouseCursor(i_slint_core::items::MouseCursor) = 15,
|
||||
}
|
||||
|
||||
impl Value {
|
||||
|
|
@ -196,6 +198,7 @@ impl PartialEq for Value {
|
|||
Value::StyledText(lhs) => {
|
||||
matches!(other, Value::StyledText(rhs) if lhs == rhs)
|
||||
}
|
||||
Value::MouseCursor(lhs) => matches!(other, Value::MouseCursor(rhs) if lhs == rhs),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -224,6 +227,7 @@ impl std::fmt::Debug for Value {
|
|||
Value::ArrayOfU16(data) => {
|
||||
write!(f, "Value::ArrayOfU16({data:?})")
|
||||
}
|
||||
Value::MouseCursor(m) => write!(f, "Value::MouseCursor({m:?})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -264,6 +268,7 @@ declare_value_conversion!(Struct => [Struct] );
|
|||
declare_value_conversion!(Brush => [Brush] );
|
||||
declare_value_conversion!(PathData => [PathData]);
|
||||
declare_value_conversion!(EasingCurve => [i_slint_core::animations::EasingCurve]);
|
||||
declare_value_conversion!(MouseCursor => [i_slint_core::items::MouseCursor]);
|
||||
declare_value_conversion!(LayoutCache => [SharedVector<f32>] );
|
||||
declare_value_conversion!(ComponentFactory => [ComponentFactory] );
|
||||
declare_value_conversion!(StyledText => [i_slint_core::api::StyledText] );
|
||||
|
|
|
|||
|
|
@ -1243,6 +1243,7 @@ pub(crate) fn generate_item_tree<'id>(
|
|||
Type::Struct(_) => property_info::<Value>(),
|
||||
Type::Array(_) => property_info::<Value>(),
|
||||
Type::Easing => property_info::<i_slint_core::animations::EasingCurve>(),
|
||||
Type::Cursor => property_info::<i_slint_core::items::MouseCursor>(),
|
||||
Type::Percent => animated_property_info::<f32>(),
|
||||
Type::Enumeration(e) => {
|
||||
macro_rules! match_enum_type {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ use corelib::rtti::AnimatedBindingKind;
|
|||
use corelib::window::WindowInner;
|
||||
use corelib::{Brush, Color, PathData, SharedString, SharedVector};
|
||||
use i_slint_compiler::expression_tree::{
|
||||
BuiltinFunction, Callable, EasingCurve, Expression, MinMaxOp, Path as ExprPath,
|
||||
PathElement as ExprPathElement,
|
||||
BuiltinFunction, Callable, EasingCurve, Expression, ImageReference, MinMaxOp, MouseCursor,
|
||||
Path as ExprPath, PathElement as ExprPathElement,
|
||||
};
|
||||
use i_slint_compiler::langtype::Type;
|
||||
use i_slint_compiler::namedreference::NamedReference;
|
||||
|
|
@ -411,6 +411,54 @@ pub fn eval_expression(expression: &Expression, local_context: &mut EvalLocalCon
|
|||
corelib::animations::EasingCurve::CubicBezier([*a, *b, *c, *d])
|
||||
}
|
||||
}),
|
||||
Expression::MouseCursor(cursor) => Value::MouseCursor(match cursor {
|
||||
MouseCursor::Default => corelib::items::MouseCursor::Default,
|
||||
MouseCursor::None => corelib::items::MouseCursor::None,
|
||||
MouseCursor::Help => corelib::items::MouseCursor::Help,
|
||||
MouseCursor::Pointer => corelib::items::MouseCursor::Pointer,
|
||||
MouseCursor::Progress => corelib::items::MouseCursor::Progress,
|
||||
MouseCursor::Wait => corelib::items::MouseCursor::Wait,
|
||||
MouseCursor::Crosshair => corelib::items::MouseCursor::Crosshair,
|
||||
MouseCursor::Text => corelib::items::MouseCursor::Text,
|
||||
MouseCursor::Alias => corelib::items::MouseCursor::Alias,
|
||||
MouseCursor::Copy => corelib::items::MouseCursor::Copy,
|
||||
MouseCursor::Move => corelib::items::MouseCursor::Move,
|
||||
MouseCursor::NoDrop => corelib::items::MouseCursor::NoDrop,
|
||||
MouseCursor::NotAllowed => corelib::items::MouseCursor::NotAllowed,
|
||||
MouseCursor::Grab => corelib::items::MouseCursor::Grab,
|
||||
MouseCursor::Grabbing => corelib::items::MouseCursor::Grabbing,
|
||||
MouseCursor::ColResize => corelib::items::MouseCursor::ColResize,
|
||||
MouseCursor::RowResize => corelib::items::MouseCursor::RowResize,
|
||||
MouseCursor::NResize => corelib::items::MouseCursor::NResize,
|
||||
MouseCursor::EResize => corelib::items::MouseCursor::EResize,
|
||||
MouseCursor::SResize => corelib::items::MouseCursor::SResize,
|
||||
MouseCursor::WResize => corelib::items::MouseCursor::WResize,
|
||||
MouseCursor::NeResize => corelib::items::MouseCursor::NeResize,
|
||||
MouseCursor::NwResize => corelib::items::MouseCursor::NwResize,
|
||||
MouseCursor::SeResize => corelib::items::MouseCursor::SeResize,
|
||||
MouseCursor::SwResize => corelib::items::MouseCursor::SwResize,
|
||||
MouseCursor::EwResize => corelib::items::MouseCursor::EwResize,
|
||||
MouseCursor::NsResize => corelib::items::MouseCursor::NsResize,
|
||||
MouseCursor::NeswResize => corelib::items::MouseCursor::NeswResize,
|
||||
MouseCursor::NwseResize => corelib::items::MouseCursor::NwseResize,
|
||||
MouseCursor::CustomCursor(image, hotspot_x, hotspot_y) => {
|
||||
let image = match image {
|
||||
ImageReference::None => i_slint_core::graphics::Image::default(),
|
||||
ImageReference::AbsolutePath(path) => {
|
||||
i_slint_core::graphics::Image::load_from_path(std::path::Path::new(path))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
ImageReference::EmbeddedData { .. } => todo!(),
|
||||
ImageReference::EmbeddedTexture { .. } => todo!(),
|
||||
};
|
||||
|
||||
corelib::items::MouseCursor::CustomCursor {
|
||||
image,
|
||||
hotspot_x: *hotspot_x,
|
||||
hotspot_y: *hotspot_y,
|
||||
}
|
||||
}
|
||||
}),
|
||||
Expression::LinearGradient { angle, stops } => {
|
||||
let angle = eval_expression(angle, local_context);
|
||||
Value::Brush(Brush::LinearGradient(LinearGradientBrush::new(
|
||||
|
|
@ -1832,6 +1880,7 @@ fn check_value_type(value: &mut Value, ty: &Type) -> bool {
|
|||
}
|
||||
Type::PathData => matches!(value, Value::PathData(_)),
|
||||
Type::Easing => matches!(value, Value::EasingCurve(_)),
|
||||
Type::Cursor => matches!(value, Value::MouseCursor(_)),
|
||||
Type::Brush => matches!(value, Value::Brush(_)),
|
||||
Type::Array(inner) => {
|
||||
matches!(value, Value::Model(m) if m.iter().all(|mut v| check_value_type(&mut v, inner)))
|
||||
|
|
@ -2146,6 +2195,7 @@ pub fn default_value_for_type(ty: &Type) -> Value {
|
|||
e.values.get(e.default_value).unwrap().to_string(),
|
||||
),
|
||||
Type::Easing => Value::EasingCurve(Default::default()),
|
||||
Type::Cursor => Value::MouseCursor(Default::default()),
|
||||
Type::Void | Type::Invalid => Value::Void,
|
||||
Type::UnitProduct(_) => Value::Number(0.),
|
||||
Type::PathData => Value::PathData(Default::default()),
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ let double_click = |x, y| {
|
|||
slint_testing::send_mouse_click(&instance, x, y);
|
||||
};
|
||||
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
// Test clicks on end of rotated child rectangle of rotated rectangle.
|
||||
// Click locations come from a screenshot
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ let instance = TestCase::new().unwrap();
|
|||
slint_testing::send_mouse_click(&instance, x, y);
|
||||
};*/
|
||||
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
assert_eq!(instance.get_touch1(), 0);
|
||||
slint_testing::send_mouse_click(&instance, 1.0,1.0);
|
||||
assert_eq!(instance.get_touch1(), 1);
|
||||
|
|
|
|||
|
|
@ -37,26 +37,26 @@ use slint::{platform::WindowEvent, LogicalPosition};
|
|||
use slint::private_unstable_api::re_exports::MouseCursor;
|
||||
|
||||
let instance = TestCase::new().unwrap();
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(35.0, 35.0) });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Help);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Help);
|
||||
slint_testing::send_mouse_click(&instance, 35., 35.);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(135.0, 35.0) });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::NotAllowed);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::NotAllowed);
|
||||
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(35.0, 35.0) });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
// Close the popup
|
||||
|
||||
slint_testing::send_mouse_click(&instance, 135., 35.);
|
||||
// FIXME: it takes two events to get that correctly
|
||||
// assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Help);
|
||||
// assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Help);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(135.0, 35.0) });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Help);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Help);
|
||||
```
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -132,35 +132,35 @@ use slint::{platform::WindowEvent, platform::PointerEventButton, platform::Key,
|
|||
use slint::private_unstable_api::re_exports::MouseCursor;
|
||||
|
||||
let instance = TestCase::new().unwrap();
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
// does not click on anything
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq!(instance.get_touch1(), 0);
|
||||
assert_eq!(instance.get_touch2(), 0);
|
||||
assert_eq!(instance.get_touch3(), 0);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
// click on second one
|
||||
slint_testing::send_mouse_click(&instance, 101., 101.);
|
||||
assert_eq!(instance.get_touch1(), 0);
|
||||
assert_eq!(instance.get_touch2(), 1);
|
||||
assert_eq!(instance.get_touch3(), 0);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Pointer);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Pointer);
|
||||
|
||||
// click on first one only
|
||||
slint_testing::send_mouse_click(&instance, 108., 108.);
|
||||
assert_eq!(instance.get_touch1(), 1);
|
||||
assert_eq!(instance.get_touch2(), 1);
|
||||
assert_eq!(instance.get_touch3(), 0);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Move);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Move);
|
||||
|
||||
// click on the third
|
||||
slint_testing::send_mouse_click(&instance, 106., 103.);
|
||||
assert_eq!(instance.get_touch1(), 1);
|
||||
assert_eq!(instance.get_touch2(), 1);
|
||||
assert_eq!(instance.get_touch3(), 1);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
// The final moveother is added by the grab handler!
|
||||
assert_eq!(instance.get_pointer_event_test().as_str(), "moveotherdownleftclickupleftmoveother");
|
||||
|
|
@ -190,7 +190,7 @@ use slint::{platform::WindowEvent, platform::PointerEventButton, LogicalPosition
|
|||
use slint::private_unstable_api::re_exports::MouseCursor;
|
||||
|
||||
let instance = TestCase::new().unwrap();
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
// press on second one
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(102.0, 102.0) });
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ let double_click = |x, y| {
|
|||
};
|
||||
|
||||
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default,
|
||||
"Unexpected mousecursor at start");
|
||||
|
||||
// does not click on anything
|
||||
|
|
@ -271,7 +271,7 @@ assert_eq!(instance.get_touch3(), 0, "Mis-click registered at touch3");
|
|||
assert_eq!(instance.get_touch_double1(), 0, "Mis-click registered at touch1 as double-click");
|
||||
assert_eq!(instance.get_touch_double2(), 0, "Mis-click registered at touch2 as double-click");
|
||||
assert_eq!(instance.get_touch_double3(), 0, "Mis-click registered at touch3 as double-click");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default,
|
||||
"Mis-click changed mouse cursor");
|
||||
|
||||
// click on second one
|
||||
|
|
@ -284,7 +284,7 @@ assert_eq!(instance.get_touch3(), 0, "Click on 2 registered at touch3");
|
|||
assert_eq!(instance.get_touch_double1(), 0, "Click on 2 registered at touch1 as double-click");
|
||||
assert_eq!(instance.get_touch_double2(), 0, "Click on 2 registered at touch2 as double-click");
|
||||
assert_eq!(instance.get_touch_double3(), 0, "Click on 2 registered at touch3 as double-click");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Pointer,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Pointer,
|
||||
"Click on 1 did not change mouse pointer");
|
||||
|
||||
// click on first one only
|
||||
|
|
@ -296,7 +296,7 @@ assert_eq!(instance.get_touch3(), 0, "Click on 1 registered at touch3");
|
|||
assert_eq!(instance.get_touch_double1(), 0, "Click on 1 registered at touch1 as double-click");
|
||||
assert_eq!(instance.get_touch_double2(), 0, "Click on 1 registered at touch2 as double-click");
|
||||
assert_eq!(instance.get_touch_double3(), 0, "Click on 1 registered at touch3 as double-click");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Move,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Move,
|
||||
"Click on 2 did not change mouse pointer");
|
||||
|
||||
// click on the third
|
||||
|
|
@ -310,7 +310,7 @@ assert_eq!(instance.get_touch_double2(), 0, "Click on 3 registered at touch2 as
|
|||
assert_eq!(instance.get_touch_double3(), 0, "Click on 3 registered at touch3 as double-click");
|
||||
assert_eq!(instance.get_pointer_event_test().as_str(), "move.other:down.left:click:up.left:move.other:",
|
||||
"Click on 3 produced an unexpected sequence of events");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default,
|
||||
"Click on 3 did not change mouse pointer");
|
||||
|
||||
// does not double-click on anything
|
||||
|
|
@ -322,7 +322,7 @@ assert_eq!(instance.get_touch3(), 1, "Mis-double-click registered at touch3");
|
|||
assert_eq!(instance.get_touch_double1(), 0, "Mis-double-click registered at touch1 as double-click");
|
||||
assert_eq!(instance.get_touch_double2(), 0, "Mis-double-click registered at touch2 as double-click");
|
||||
assert_eq!(instance.get_touch_double3(), 0, "Mis-double-click registered at touch3 as double-click");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default,
|
||||
"Mis-double-click on 3 did not change mouse pointer");
|
||||
|
||||
// double-click on second one
|
||||
|
|
@ -337,7 +337,7 @@ assert_eq!(instance.get_touch_double2(), 1, "Double-click on 2 did not register
|
|||
assert_eq!(instance.get_touch_double3(), 0, "Double-click on 2 registered at touch1 as double-click");
|
||||
assert_eq!(instance.get_pointer_event_test().as_str(), "move.other:down.left:click:up.left:move.other:move.other:down.left:click:double_click:up.left:move.other:",
|
||||
"Double-click on 2 produced an unexpected sequence of events");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Pointer,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Pointer,
|
||||
"Double-click on 2 did not change mouse pointer");
|
||||
|
||||
// double-click on first one only
|
||||
|
|
@ -349,7 +349,7 @@ assert_eq!(instance.get_touch3(), 1, "Double-click on 1 registered at touch3");
|
|||
assert_eq!(instance.get_touch_double1(), 1, "Double-click on 1 did not register at touch1 as double-click");
|
||||
assert_eq!(instance.get_touch_double2(), 1, "Double-click on 1 registered at touch2 as double-click");
|
||||
assert_eq!(instance.get_touch_double3(), 0, "Double-click on 1 registered at touch3 as double-click");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Move,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Move,
|
||||
"Double-click on 1 did not change mouse pointer");
|
||||
|
||||
// double-click on the third
|
||||
|
|
@ -361,7 +361,7 @@ assert_eq!(instance.get_touch3(), 3, "Double-click on 3 did not registered at to
|
|||
assert_eq!(instance.get_touch_double1(), 1, "Double-click on 3 registered at touch1 as double-click");
|
||||
assert_eq!(instance.get_touch_double2(), 1, "Double-click on 3 registered at touch2 as double-click");
|
||||
assert_eq!(instance.get_touch_double3(), 1, "Double-click on 3 did not register at touch3 as double-click");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default,
|
||||
"Double-click on 3 did not change mouse pointer");
|
||||
|
||||
// triple-click on the third (treated as a double click, followed by a single click)
|
||||
|
|
@ -381,7 +381,7 @@ assert_eq!(instance.get_touch3(), 6, "Triple-click on 3 registered at touch1");
|
|||
assert_eq!(instance.get_touch_double1(), 1, "Triple-click on 3 registered at touch1");
|
||||
assert_eq!(instance.get_touch_double2(), 1, "Triple-click on 3 registered at touch2");
|
||||
assert_eq!(instance.get_touch_double3(), 2, "Triple-click on 3 did not register at touch3 as double-click");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default,
|
||||
"Triple-click on 3 did not change mouse pointer");
|
||||
|
||||
// click really quickly on two different mouse areas
|
||||
|
|
@ -398,7 +398,7 @@ assert_eq!(instance.get_touch3(), 6, "click on different touch areas registered
|
|||
assert_eq!(instance.get_touch_double1(), 1, "click on different touch areas registered on touch1 as double-click");
|
||||
assert_eq!(instance.get_touch_double2(), 1, "click on different touch areas registered on touch2 as double-click");
|
||||
assert_eq!(instance.get_touch_double3(), 2, "click on different touch areas registered on touch3 as double-click");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default,
|
||||
"click on different touch areas changed mouse pointer");
|
||||
assert_eq!(instance.get_pointer_event_test().as_str(), "move.other:down.left:click:up.left:move.other:",
|
||||
"click on different touch areas produced an unexpected sequence of events");
|
||||
|
|
@ -417,7 +417,7 @@ assert_eq!(instance.get_touch3(), 6, "Slow double click did not register on touc
|
|||
assert_eq!(instance.get_touch_double1(), 1, "Slow double click registered on touch1 as double-click");
|
||||
assert_eq!(instance.get_touch_double2(), 1, "Slow double click registered on touch2 as double-click");
|
||||
assert_eq!(instance.get_touch_double3(), 2, "Slow double click registered on touch3 as double-click");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default,
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default,
|
||||
"click on different touch areas changed mouse pointer");
|
||||
assert_eq!(instance.get_pointer_event_test().as_str(), "move.other:down.left:click:up.left:move.other:move.other:down.left:click:up.left:move.other:",
|
||||
"click on different touch areas produced an unexpected sequence of events");
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ let mut ime_requests = slint_testing::access_testing_window(instance.window(), |
|
|||
assert!(matches!(ime_requests.next(), Some(InputMethodRequest::Enable(props)) if props.input_type == InputType::Text));
|
||||
assert!(matches!(ime_requests.next(), Some(InputMethodRequest::Update(..))));
|
||||
assert!(ime_requests.next().is_none());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Text);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Text);
|
||||
|
||||
slint_testing::send_keyboard_string_sequence(&instance, "Only for field 1");
|
||||
assert_eq!(instance.get_input1_text(), "Only for field 1");
|
||||
|
|
@ -77,7 +77,7 @@ assert!(instance.get_input3_focused());
|
|||
let mut ime_requests = slint_testing::access_testing_window(instance.window(), |window| window.ime_requests.take()).into_iter();
|
||||
assert!(matches!(ime_requests.next(), Some(InputMethodRequest::Disable)));
|
||||
assert!(ime_requests.next().is_none());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Text);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Text);
|
||||
```
|
||||
|
||||
```cpp
|
||||
|
|
|
|||
|
|
@ -49,45 +49,45 @@ let instance = TestCase::new().unwrap();
|
|||
assert!(!instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(50.0, 50.0) });
|
||||
assert!(!instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(240.0, 150.0) });
|
||||
assert!(instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Copy);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Copy);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(290.0, 150.0) });
|
||||
// We Since the touch area are not children, only one is active
|
||||
assert!(!instance.get_has_hover1());
|
||||
assert!(instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
//FIXME: it currently takes two events for the mouse cursor to change when going from one MouseArea to another
|
||||
//assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Alias);
|
||||
//assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Alias);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(330.0, 150.0) });
|
||||
assert!(!instance.get_has_hover1());
|
||||
assert!(instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Alias);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Alias);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(370.0, 150.0) });
|
||||
assert!(!instance.get_has_hover1());
|
||||
// here 2 and 3 are both active since one is a children of the other
|
||||
assert!(instance.get_has_hover2());
|
||||
assert!(instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(390.0, 150.0) });
|
||||
assert!(!instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(510.0, 150.0) });
|
||||
assert!(!instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
// Now grab
|
||||
let button = PointerEventButton::Left;
|
||||
|
|
@ -95,37 +95,37 @@ instance.window().dispatch_event(WindowEvent::PointerPressed { position: Logical
|
|||
assert!(instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Copy);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Copy);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(290.0, 150.0) });
|
||||
assert!(instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Copy);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Copy);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(330.0, 150.0) });
|
||||
assert!(instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Copy);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Copy);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(370.0, 150.0) });
|
||||
assert!(instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Copy);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Copy);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(390.0, 150.0) });
|
||||
assert!(instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Copy);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Copy);
|
||||
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(510.0, 150.0) });
|
||||
assert!(instance.get_has_hover1());
|
||||
assert!(!instance.get_has_hover2());
|
||||
assert!(!instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Copy);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Copy);
|
||||
instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(370.0, 150.0), button });
|
||||
assert!(!instance.get_has_hover1());
|
||||
assert!(instance.get_has_hover2());
|
||||
assert!(instance.get_has_hover3());
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
```
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -50,13 +50,13 @@ assert_eq!(edits.borrow().clone(), vec!["h", "he", "hel", "hell", "hello"]);
|
|||
// Test mouse cursor for issue 6444
|
||||
use slint::{LogicalPosition, platform::{WindowEvent, PointerEventButton}};
|
||||
use slint::private_unstable_api::re_exports::MouseCursor;
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Text, "after previous click");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Text, "after previous click");
|
||||
instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(50.0, 50.0), button: PointerEventButton::Middle });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Text, "Middle button pressed");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Text, "Middle button pressed");
|
||||
instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(50.0, 50.0), button: PointerEventButton::Middle });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Text, "Middle button released");
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Text, "Middle button released");
|
||||
instance.window().dispatch_event(WindowEvent::PointerExited { });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.borrow().clone()), MouseCursor::Default);
|
||||
|
||||
// test page up/down
|
||||
for x in 0..10 {
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ pub struct HeadlessWindow {
|
|||
window: i_slint_core::api::Window,
|
||||
size: Cell<PhysicalSize>,
|
||||
pub ime_requests: RefCell<Vec<InputMethodRequest>>,
|
||||
pub mouse_cursor: Cell<i_slint_core::items::MouseCursor>,
|
||||
pub mouse_cursor: RefCell<i_slint_core::items::MouseCursor>,
|
||||
renderer: SkiaRenderer,
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ impl WindowAdapterInternal for HeadlessWindow {
|
|||
}
|
||||
|
||||
fn set_mouse_cursor(&self, cursor: i_slint_core::items::MouseCursor) {
|
||||
self.mouse_cursor.set(cursor);
|
||||
self.mouse_cursor.replace(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue