wgui: components base, anyhow event listener callbacks, 📦📎-fixes, typo fixes

This commit is contained in:
Aleksander
2025-08-13 17:10:00 +02:00
parent 93a3fee349
commit a79ed0839b
23 changed files with 104 additions and 72 deletions

View File

@@ -2,6 +2,7 @@
name = "uidev"
version = "0.1.0"
edition = "2024"
description = "wgui library testing using winit backend"
[dependencies]
anyhow = { workspace = true }

View File

@@ -92,7 +92,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
};
let mut recreate = false;
let mut last_draw = std::time::Instant::now();
let mut scale = window.scale_factor() as f32;
@@ -302,8 +301,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let tgt = images[image_index as usize].clone();
last_draw = std::time::Instant::now();
let mut cmd_buf = gfx
.create_gfx_command_buffer(CommandBufferUsage::OneTimeSubmit)
.unwrap();
@@ -337,9 +334,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
profiler.end();
}
Event::AboutToWait => {
if last_draw.elapsed().as_millis() > 16 {
window.request_redraw();
}
// should be limited to vsync
window.request_redraw();
}
_ => (),
}

View File

@@ -33,12 +33,13 @@ fn button_click_callback(
Translation::from_raw_text(text),
);
// FIXME: remove unwrap
button.try_cast::<ComponentButton>().unwrap().set_text(
button.try_cast::<ComponentButton>()?.set_text(
e.state,
e.alterables,
Translation::from_raw_text("this button has been clicked"),
);
Ok(())
})
}
@@ -70,6 +71,7 @@ impl TestbedGeneric {
e.alterables,
Translation::from_raw_text("congrats!"),
);
Ok(())
}));
let button_red = state.fetch_component_as::<ComponentButton>("button_red")?;

View File

@@ -3,7 +3,7 @@ use taffy::{AlignItems, JustifyContent, prelude::length};
use crate::{
animation::{Animation, AnimationEasing},
components::{Component, ComponentTrait, InitData},
components::{Component, ComponentBase, ComponentTrait, InitData},
drawing::{self, Color},
event::{EventAlterables, EventListenerCollection, EventListenerKind, ListenerHandleVec},
i18n::Translation,
@@ -42,7 +42,7 @@ pub struct ButtonClickEvent<'a> {
pub state: &'a LayoutState,
pub alterables: &'a mut EventAlterables,
}
pub type ButtonClickCallback = Box<dyn Fn(ButtonClickEvent)>;
pub type ButtonClickCallback = Box<dyn Fn(ButtonClickEvent) -> anyhow::Result<()>>;
struct State {
hovered: bool,
@@ -59,14 +59,16 @@ struct Data {
}
pub struct ComponentButton {
base: ComponentBase,
data: Rc<Data>,
state: Rc<RefCell<State>>,
#[allow(dead_code)]
listener_handles: ListenerHandleVec,
}
impl ComponentTrait for ComponentButton {
fn base(&mut self) -> &mut ComponentBase {
&mut self.base
}
fn init(&self, _data: &mut InitData) {}
}
@@ -143,6 +145,7 @@ fn register_event_mouse_enter<U1, U2>(
.alterables
.animate(anim_hover_in(data.clone(), event_data.widget_id));
state.borrow_mut().hovered = true;
Ok(())
}),
);
}
@@ -163,6 +166,7 @@ fn register_event_mouse_leave<U1, U2>(
.alterables
.animate(anim_hover_out(data.clone(), event_data.widget_id));
state.borrow_mut().hovered = false;
Ok(())
}),
);
}
@@ -184,6 +188,8 @@ fn register_event_mouse_press<U1, U2>(
if state.hovered {
state.down = true;
}
Ok(())
}),
);
}
@@ -209,11 +215,12 @@ fn register_event_mouse_release<U1, U2>(
if let Some(on_click) = &state.on_click {
on_click(ButtonClickEvent {
state: common.state,
alterables: &mut common.alterables,
});
alterables: common.alterables,
})?;
}
}
}
Ok(())
}),
);
}
@@ -286,18 +293,14 @@ pub fn construct<U1, U2>(
on_click: None,
}));
let mut lhandles = ListenerHandleVec::default();
let mut base = ComponentBase::default();
register_event_mouse_enter(data.clone(), state.clone(), listeners, &mut lhandles);
register_event_mouse_leave(data.clone(), state.clone(), listeners, &mut lhandles);
register_event_mouse_press(data.clone(), state.clone(), listeners, &mut lhandles);
register_event_mouse_release(data.clone(), state.clone(), listeners, &mut lhandles);
register_event_mouse_enter(data.clone(), state.clone(), listeners, &mut base.lhandles);
register_event_mouse_leave(data.clone(), state.clone(), listeners, &mut base.lhandles);
register_event_mouse_press(data.clone(), state.clone(), listeners, &mut base.lhandles);
register_event_mouse_release(data.clone(), state.clone(), listeners, &mut base.lhandles);
let button = Rc::new(ComponentButton {
data,
state,
listener_handles: lhandles,
});
let button = Rc::new(ComponentButton { base, data, state });
layout.defer_component_init(Component(button.clone()));
Ok(button)

View File

@@ -1,6 +1,10 @@
use std::rc::Rc;
use crate::{any::AnyTrait, event::EventAlterables, layout::LayoutState};
use crate::{
any::AnyTrait,
event::{self, EventAlterables},
layout::LayoutState,
};
pub mod button;
pub mod slider;
@@ -10,7 +14,14 @@ pub struct InitData<'a> {
pub alterables: &'a mut EventAlterables,
}
// common component data
#[derive(Default)]
pub struct ComponentBase {
lhandles: event::ListenerHandleVec,
}
pub trait ComponentTrait: AnyTrait {
fn base(&mut self) -> &mut ComponentBase;
fn init(&self, data: &mut InitData);
}

View File

@@ -5,7 +5,7 @@ use taffy::prelude::{length, percent};
use crate::{
animation::{Animation, AnimationEasing},
components::{Component, ComponentTrait, InitData},
components::{Component, ComponentBase, ComponentTrait, InitData},
drawing::{self},
event::{
self, CallbackDataCommon, EventAlterables, EventListenerCollection, EventListenerKind,
@@ -63,11 +63,9 @@ struct Data {
}
pub struct ComponentSlider {
base: ComponentBase,
data: Rc<Data>,
state: Rc<RefCell<State>>,
#[allow(dead_code)]
listener_handles: ListenerHandleVec,
}
impl ComponentTrait for ComponentSlider {
@@ -76,6 +74,10 @@ impl ComponentTrait for ComponentSlider {
let value = state.values.value;
state.set_value(init_data.state, &self.data, init_data.alterables, value);
}
fn base(&mut self) -> &mut ComponentBase {
&mut self.base
}
}
// NOTICE: this can be re-used in the future
@@ -222,6 +224,7 @@ fn register_event_mouse_enter<U1, U2>(
common.alterables.trigger_haptics();
state.borrow_mut().hovered = true;
on_enter_anim(common, data.slider_handle_rect_id);
Ok(())
}),
);
}
@@ -240,6 +243,7 @@ fn register_event_mouse_leave<U1, U2>(
common.alterables.trigger_haptics();
state.borrow_mut().hovered = false;
on_leave_anim(common, data.slider_handle_rect_id);
Ok(())
}),
);
}
@@ -260,6 +264,8 @@ fn register_event_mouse_motion<U1, U2>(
if state.dragging {
state.update_value_to_mouse(event_data, &data, common);
}
Ok(())
}),
);
}
@@ -282,6 +288,8 @@ fn register_event_mouse_press<U1, U2>(
state.dragging = true;
state.update_value_to_mouse(event_data, &data, common)
}
Ok(())
}),
);
}
@@ -303,6 +311,8 @@ fn register_event_mouse_release<U1, U2>(
if state.dragging {
state.dragging = false;
}
Ok(())
}),
);
}
@@ -417,20 +427,16 @@ pub fn construct<U1, U2>(
let state = Rc::new(RefCell::new(state));
let mut lhandles = ListenerHandleVec::default();
let mut base = ComponentBase::default();
register_event_mouse_enter(data.clone(), state.clone(), listeners, &mut lhandles);
register_event_mouse_leave(data.clone(), state.clone(), listeners, &mut lhandles);
register_event_mouse_motion(data.clone(), state.clone(), listeners, &mut lhandles);
register_event_mouse_press(data.clone(), state.clone(), listeners, &mut lhandles);
register_event_mouse_leave(data.clone(), state.clone(), listeners, &mut lhandles);
register_event_mouse_release(data.clone(), state.clone(), listeners, &mut lhandles);
register_event_mouse_enter(data.clone(), state.clone(), listeners, &mut base.lhandles);
register_event_mouse_leave(data.clone(), state.clone(), listeners, &mut base.lhandles);
register_event_mouse_motion(data.clone(), state.clone(), listeners, &mut base.lhandles);
register_event_mouse_press(data.clone(), state.clone(), listeners, &mut base.lhandles);
register_event_mouse_leave(data.clone(), state.clone(), listeners, &mut base.lhandles);
register_event_mouse_release(data.clone(), state.clone(), listeners, &mut base.lhandles);
let slider = Rc::new(ComponentSlider {
data,
state,
listener_handles: lhandles,
});
let slider = Rc::new(ComponentSlider { base, data, state });
layout.defer_component_init(Component(slider.clone()));
Ok(slider)

View File

@@ -177,7 +177,7 @@ pub enum EventListenerKind {
}
pub type EventCallback<U1, U2> =
Box<dyn Fn(&mut CallbackDataCommon, &mut CallbackData, &mut U1, &mut U2)>;
Box<dyn Fn(&mut CallbackDataCommon, &mut CallbackData, &mut U1, &mut U2) -> anyhow::Result<()>>;
//for ref-counting
pub struct ListenerHandle {
@@ -209,7 +209,9 @@ impl<U1, U2> EventListener<U1, U2> {
pub fn callback_for_kind(
&self,
kind: EventListenerKind,
) -> Option<&impl Fn(&mut CallbackDataCommon, &mut CallbackData, &mut U1, &mut U2)> {
) -> Option<
&impl Fn(&mut CallbackDataCommon, &mut CallbackData, &mut U1, &mut U2) -> anyhow::Result<()>,
> {
if self.kind == kind {
Some(&self.callback)
} else {

View File

@@ -226,7 +226,7 @@ impl Layout {
event,
user_data,
&mut params,
) {
)? {
widget::EventResult::Pass => {
// go on
}

View File

@@ -205,7 +205,7 @@ macro_rules! call_event {
alterables: $params.alterables,
};
callback(&mut common, &mut data, $user_data.0, $user_data.1);
callback(&mut common, &mut data, $user_data.0, $user_data.1)?;
}
}
};
@@ -329,7 +329,7 @@ impl WidgetState {
event: &Event,
user_data: &mut (&mut U1, &mut U2),
params: &'a mut EventParams<'a>,
) -> EventResult {
) -> anyhow::Result<EventResult> {
let hovered = event.test_mouse_within_transform(params.alterables.transform_stack.get());
match &event {
@@ -415,7 +415,7 @@ impl WidgetState {
}
Event::MouseWheel(e) => {
if hovered && self.process_wheel(params, e) {
return EventResult::Consumed;
return Ok(EventResult::Consumed);
}
}
Event::MouseLeave(e) => {
@@ -449,6 +449,6 @@ impl WidgetState {
}
}
}
EventResult::Pass
Ok(EventResult::Pass)
}
}

View File

@@ -27,7 +27,7 @@ impl Display for FourCC {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for i in 0..4 {
if let Some(c) = char::from_u32((self.value >> (i * 8)) & 0xFF) {
write!(f, "{}", c)?
write!(f, "{c}")?
} else {
write!(f, "?")?
}

View File

@@ -170,10 +170,10 @@ impl WlxClient {
match reader.read() {
Ok(n) => match queue_mut.dispatch_pending(self) {
Ok(n2) => {
log::debug!("Read {}, dispatched {} pending events", n, n2);
log::debug!("Read {n}, dispatched {n2} pending events");
}
Err(err) => {
log::warn!("Error while dispatching {} pending events: {:?}", n, err);
log::warn!("Error while dispatching {n} pending events: {err:?}");
}
},
Err(err) => {
@@ -182,7 +182,7 @@ impl WlxClient {
return;
}
}
log::warn!("Error while reading from event queue: {:?}", err);
log::warn!("Error while reading from event queue: {err:?}");
}
}
} else {

View File

@@ -132,7 +132,8 @@ pub(super) unsafe fn create_overlay_session(
system_id: system,
};
let mut out = xr::sys::Session::NULL;
let x = unsafe { (instance.fp().create_session)(instance.as_raw(), &info, &mut out) };
let x =
unsafe { (instance.fp().create_session)(instance.as_raw(), &raw const info, &raw mut out) };
if x.into_raw() >= 0 { Ok(out) } else { Err(x) }
}

View File

@@ -121,6 +121,7 @@ impl LinePool {
let to_hmd = hmd.translation - from.translation;
let sides = [Vec3A::Z, Vec3A::X, Vec3A::NEG_Z, Vec3A::NEG_X];
#[allow(clippy::neg_multiply)]
let rotations = [
Affine3A::IDENTITY,
Affine3A::from_axis_angle(Vec3::Y, PI * 0.5),

View File

@@ -356,10 +356,7 @@ pub fn ui_transform(extent: [u32; 2]) -> Affine2 {
y: -1.0,
}
} else {
Vec2 {
x: 1.0,
y: -1.0 * aspect,
}
Vec2 { x: 1.0, y: -aspect }
};
let center = Vec2 { x: 0.5, y: 0.5 };
Affine2::from_scale_angle_translation(scale, 0.0, center)

View File

@@ -1,12 +1,12 @@
use smithay::backend::allocator::dmabuf::Dmabuf;
use smithay::backend::renderer::ImportDma;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::backend::renderer::utils::on_commit_buffer_handler;
use smithay::backend::renderer::ImportDma;
use smithay::input::{Seat, SeatHandler, SeatState};
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
use smithay::reexports::wayland_server;
use smithay::reexports::wayland_server::protocol::{wl_buffer, wl_seat, wl_surface};
use smithay::reexports::wayland_server::Resource;
use smithay::reexports::wayland_server::protocol::{wl_buffer, wl_seat, wl_surface};
use smithay::wayland::buffer::BufferHandler;
use smithay::wayland::dmabuf::{
DmabufFeedback, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier,
@@ -23,22 +23,22 @@ use std::sync::{Arc, Mutex};
use smithay::utils::Serial;
use smithay::wayland::compositor::{
self, with_surface_tree_downward, SurfaceAttributes, TraversalAction,
self, SurfaceAttributes, TraversalAction, with_surface_tree_downward,
};
use smithay::wayland::selection::SelectionHandler;
use smithay::wayland::selection::data_device::{
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
};
use smithay::wayland::selection::SelectionHandler;
use smithay::wayland::shell::xdg::{
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
};
use wayland_server::Client;
use wayland_server::backend::{ClientData, ClientId, DisconnectReason};
use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::Client;
use super::event_queue::SyncEventQueue;
use super::WayVRTask;
use super::event_queue::SyncEventQueue;
pub struct Application {
pub gles_renderer: GlesRenderer,
@@ -220,7 +220,7 @@ pub fn send_frames_surface_tree(surface: &wl_surface::WlSurface, time: u32) {
|_, _, &()| TraversalAction::DoChildren(()),
|_surf, states, &()| {
// the surface may not have any user_data if it is a subsurface and has not
// yet been commited
// yet been committed
for callback in states
.cached_state
.get::<SurfaceAttributes>()

View File

@@ -157,16 +157,16 @@ impl EGLData {
self.display.as_ptr(),
0,
std::ptr::null_mut(),
&mut num_formats,
&raw mut num_formats,
);
// Retrieve formt list
// Retrieve format list
let mut formats: Vec<i32> = vec![0; num_formats as usize];
egl_query_dmabuf_formats_ext(
self.display.as_ptr(),
num_formats,
formats.as_mut_ptr(),
&mut num_formats,
&raw mut num_formats,
);
/*for (idx, format) in formats.iter().enumerate() {
@@ -196,7 +196,7 @@ impl EGLData {
0,
std::ptr::null_mut(),
std::ptr::null_mut(),
&mut num_mods,
&raw mut num_mods,
);
if num_mods == 0 {
@@ -210,7 +210,7 @@ impl EGLData {
num_mods,
mods.as_mut_ptr(),
std::ptr::null_mut(),
&mut num_mods,
&raw mut num_mods,
);
if mods[0] == 0xFFFF_FFFF_FFFF_FFFF {

View File

@@ -25,7 +25,7 @@ pub fn create_framebuffer_texture(
) -> u32 {
unsafe {
let mut tex = 0;
gl.GenTextures(1, &mut tex);
gl.GenTextures(1, &raw mut tex);
gl.BindTexture(ffi::TEXTURE_2D, tex);
gl.TexParameteri(
ffi::TEXTURE_2D,

View File

@@ -9,6 +9,8 @@ pub const BAR_NAME: &str = "bar";
struct BarState {}
#[allow(clippy::significant_drop_tightening)]
#[allow(clippy::for_kv_map)] // TODO: remove later
#[allow(clippy::match_same_arms)] // TODO: remove later
pub fn create_bar<O>(app: &mut AppState) -> anyhow::Result<OverlayData<O>>
where
O: Default,

View File

@@ -10,6 +10,9 @@ use crate::{
const SETTINGS_NAME: &str = "settings";
#[allow(unreachable_code)]
#[allow(unused_variables)]
#[allow(dead_code)]
pub fn create_custom(
app: &mut AppState,
name: Arc<str>,

View File

@@ -194,6 +194,7 @@ where
move |common, data, _app, _state| {
common.alterables.trigger_haptics();
on_enter_anim(k.clone(), common, data);
Ok(())
}
}),
);
@@ -206,6 +207,7 @@ where
move |common, data, _app, _state| {
common.alterables.trigger_haptics();
on_leave_anim(k.clone(), common, data);
Ok(())
}
}),
);
@@ -222,6 +224,7 @@ where
handle_press(app, &k, state, button);
on_press_anim(k.clone(), common, data);
Ok(())
}
}),
);
@@ -235,6 +238,7 @@ where
if handle_release(app, &k, state) {
on_release_anim(k.clone(), common, data);
}
Ok(())
}
}),
);
@@ -252,6 +256,7 @@ where
} else {
on_release_anim(k.clone(), common, data);
}
Ok(())
}
}),
);

View File

@@ -93,6 +93,7 @@ where
EventListenerKind::InternalStateChange,
Box::new(move |common, data, _, _| {
clock_on_tick(&clock, common, data);
Ok(())
}),
);
}

View File

@@ -295,7 +295,7 @@ fn get_time() -> timeval {
tv_sec: 0,
tv_usec: 0,
};
unsafe { libc::gettimeofday(&mut time, std::ptr::null_mut()) };
unsafe { libc::gettimeofday(&raw mut time, std::ptr::null_mut()) };
time
}

View File

@@ -51,6 +51,7 @@ impl OscSender {
Ok(())
}
#[allow(clippy::too_many_lines)]
pub fn send_params<D>(
&mut self,
overlays: &OverlayContainer<D>,