Button state is delayed with a custom Platform implementation #7193
-
The disabled state of the button only activated when the cursor is moved: Screen.Recording.2024-12-22.at.01.26.56.movI was tried to look for what are missing from my implementation but can't figure out. How I implement the pub struct Window {
winit: Rc<winit::window::Window>,
slint: slint::Window,
renderer: SkiaRenderer,
visible: Cell<Option<bool>>, // Wayland does not support this so we need to emulate it.
pointer: Cell<LogicalPosition>,
}
impl RuntimeWindow for Window {
fn on_resized(
&self,
new: winit::dpi::PhysicalSize<u32>,
) -> Result<(), Box<dyn Error + Send + Sync>> {
let size = PhysicalSize::new(new.width, new.height);
let size = LogicalSize::from_physical(size, self.winit.scale_factor() as f32);
self.slint.dispatch_event(WindowEvent::Resized { size });
Ok(())
}
fn on_focused(&self, gained: bool) -> Result<(), Box<dyn Error + Send + Sync>> {
self.slint
.dispatch_event(WindowEvent::WindowActiveChanged(gained));
Ok(())
}
fn on_cursor_moved(
&self,
_: DeviceId,
pos: winit::dpi::PhysicalPosition<f64>,
) -> Result<(), Box<dyn Error + Send + Sync>> {
let pos = pos.to_logical(self.winit.scale_factor());
let position = LogicalPosition::new(pos.x, pos.y);
self.slint
.dispatch_event(WindowEvent::PointerMoved { position });
self.pointer.set(position);
Ok(())
}
fn on_cursor_left(&self, _: DeviceId) -> Result<(), Box<dyn Error + Send + Sync>> {
self.slint.dispatch_event(WindowEvent::PointerExited);
Ok(())
}
fn on_mouse_input(
&self,
_: DeviceId,
st: ElementState,
btn: MouseButton,
) -> Result<(), Box<dyn Error + Send + Sync>> {
// Map button.
let button = match btn {
MouseButton::Left => PointerEventButton::Left,
MouseButton::Right => PointerEventButton::Right,
MouseButton::Middle => PointerEventButton::Middle,
MouseButton::Back => PointerEventButton::Back,
MouseButton::Forward => PointerEventButton::Forward,
MouseButton::Other(_) => PointerEventButton::Other,
};
// Dispatch to Slint.
let position = self.pointer.get();
let ev = match st {
ElementState::Pressed => WindowEvent::PointerPressed { position, button },
ElementState::Released => WindowEvent::PointerReleased { position, button },
};
self.slint.dispatch_event(ev);
Ok(())
}
fn on_scale_factor_changed(
&self,
new: f64,
_: InnerSizeWriter,
) -> Result<(), Box<dyn Error + Send + Sync>> {
let scale_factor = new as f32;
self.slint
.dispatch_event(WindowEvent::ScaleFactorChanged { scale_factor });
Ok(())
}
fn on_redraw_requested(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
// Wayland will show the window on the first render so we need to check visibility flag
// here.
if self.visible.get().is_some_and(|v| v) {
self.renderer.render()?;
}
Ok(())
}
}
impl WindowAdapter for Window {
fn window(&self) -> &slint::Window {
&self.slint
}
fn set_visible(&self, visible: bool) -> Result<(), PlatformError> {
if visible {
assert!(self.visible.get().is_none());
self.winit.set_visible(true);
self.visible.set(Some(true));
} else {
assert_eq!(self.visible.get(), Some(true));
self.winit.set_visible(false);
self.visible.set(Some(false));
}
Ok(())
}
fn set_size(&self, size: WindowSize) {
todo!()
}
fn size(&self) -> PhysicalSize {
let s = self.winit.inner_size();
PhysicalSize::new(s.width, s.height)
}
fn request_redraw(&self) {
self.winit.request_redraw();
}
fn renderer(&self) -> &dyn Renderer {
&self.renderer
}
fn update_window_properties(&self, properties: WindowProperties) {
// Set window size.
let size = properties.layout_constraints();
let scale = self.winit.scale_factor() as f32;
let map = move |v: LogicalSize| {
let v = v.to_physical(scale);
let v = winit::dpi::PhysicalSize::new(v.width, v.height);
winit::dpi::Size::from(v)
};
self.winit.set_min_inner_size(size.min.map(&map));
self.winit.set_max_inner_size(size.max.map(&map));
let _ = self.winit.request_inner_size(map(size.preferred));
}
fn internal(&self, _: InternalToken) -> Option<&dyn WindowAdapterInternal> {
Some(self)
}
}
impl WindowAdapterInternal for Window {
fn as_any(&self) -> &dyn Any {
self
}
} The winit event loop will forward the event to the corresponding method on |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
This might likely involve an animation. Are you calling duration_until_next_timer_update() before sleep (use the return value) and update_timers_and_animations() on loop wake-up? see also https://docs.rs/slint/latest/slint/platform/index.html#functions and https://docs.rs/slint/latest/slint/struct.Window.html#method.has_active_animations - the latter to check if you need to re-schedule a redraw. |
Beta Was this translation helpful? Give feedback.
This might likely involve an animation. Are you calling duration_until_next_timer_update() before sleep (use the return value) and update_timers_and_animations() on loop wake-up?
see also https://docs.rs/slint/latest/slint/platform/index.html#functions and https://docs.rs/slint/latest/slint/struct.Window.html#method.has_active_animations - the latter to check if you need to re-schedule a redraw.