keyboard works

This commit is contained in:
galister
2025-06-20 05:31:37 +09:00
parent b9edb75867
commit d9b3b99e0d
6 changed files with 86 additions and 27 deletions

View File

@@ -296,8 +296,14 @@ impl Layout {
}, },
)?; )?;
let root_size = self.tree.layout(self.root_node).unwrap().size; let root_size = self.tree.layout(self.root_node).unwrap().size;
log::debug!(
"content size {:.0}x{:.0} → {:.0}x{:.0}",
self.content_size.x,
self.content_size.y,
root_size.width,
root_size.height
);
self.content_size = vec2(root_size.width, root_size.height); self.content_size = vec2(root_size.width, root_size.height);
log::error!("ContentSize: {:?}", self.content_size);
} }
Ok(()) Ok(())
} }

View File

@@ -297,16 +297,19 @@ impl WidgetState {
) -> EventResult { ) -> EventResult {
let hovered = event.test_mouse_within_transform(params.transform_stack.get()); let hovered = event.test_mouse_within_transform(params.transform_stack.get());
// buttons don't need to be tracked separately as long as we stick to VR use.
let mut pressed_changed_button = None; let mut pressed_changed_button = None;
let mut hovered_changed = false; let mut hovered_changed = false;
match &event { match &event {
Event::MouseDown(e) => { Event::MouseDown(e) => {
if hovered {
pressed_changed_button = self pressed_changed_button = self
.data .data
.set_device_pressed(e.device, true) .set_device_pressed(e.device, true)
.then_some(e.button); .then_some(e.button);
} }
}
Event::MouseUp(e) => { Event::MouseUp(e) => {
pressed_changed_button = self pressed_changed_button = self
.data .data
@@ -314,7 +317,7 @@ impl WidgetState {
.then_some(e.button); .then_some(e.button);
} }
Event::MouseWheel(e) => { Event::MouseWheel(e) => {
if self.process_wheel(params, e) { if hovered && self.process_wheel(params, e) {
return EventResult::Consumed; return EventResult::Consumed;
} }
} }

View File

@@ -1,11 +1,12 @@
<layout> <layout>
<!-- The keyboard is build from the xkb keymap. This file is for customizing the keycaps. -->
<!-- Key cap with a single label. --> <!-- Key cap with a single label. -->
<!-- Used for special keys. --> <!-- Used for special keys. -->
<template name="KeySpecial"> <template name="KeySpecial">
<div width="${width}" height="${height}" min_width="${width}" min_height="${height}" max_width="${width}" max_height="${height}"> <div width="${width}" height="${height}" min_width="${width}" min_height="${height}" max_width="${width}" max_height="${height}">
<rectangle id="${id}" <rectangle id="${id}"
margin="4" width="100%" overflow="hidden" box_sizing="border_box" margin="2" width="100%" overflow="hidden" box_sizing="border_box"
border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical" border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical"
align_items="center" align_items="center"
justify_content="center"> justify_content="center">
@@ -17,9 +18,9 @@
<!-- Key cap with a single label. --> <!-- Key cap with a single label. -->
<!-- Used for letter keys on layouts without AltGr. --> <!-- Used for letter keys on layouts without AltGr. -->
<template name="KeyLetter"> <template name="KeyLetter">
<div id="${id}" width="${width}" height="${height}" min_width="${width}" min_height="${height}" max_width="${width}" max_height="${height}"> <div width="${width}" height="${height}" min_width="${width}" min_height="${height}" max_width="${width}" max_height="${height}">
<rectangle id="${id}" <rectangle id="${id}"
margin="4" width="100%" overflow="hidden" box_sizing="border_box" margin="2" width="100%" overflow="hidden" box_sizing="border_box"
border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical" border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical"
align_items="center" align_items="center"
justify_content="center"> justify_content="center">
@@ -33,7 +34,7 @@
<template name="KeyLetterAltGr"> <template name="KeyLetterAltGr">
<div width="${width}" height="${height}" min_width="${width}" min_height="${height}" max_width="${width}" max_height="${height}"> <div width="${width}" height="${height}" min_width="${width}" min_height="${height}" max_width="${width}" max_height="${height}">
<rectangle id="${id}" <rectangle id="${id}"
margin="4" width="100%" overflow="hidden" box_sizing="border_box" margin="2" width="100%" overflow="hidden" box_sizing="border_box"
border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical" border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical"
gap="4" gap="4"
flex_direction="column" flex_direction="column"
@@ -50,7 +51,7 @@
<template name="KeySymbol"> <template name="KeySymbol">
<div width="${width}" height="${height}" min_width="${width}" min_height="${height}" max_width="${width}" max_height="${height}"> <div width="${width}" height="${height}" min_width="${width}" min_height="${height}" max_width="${width}" max_height="${height}">
<rectangle id="${id}" <rectangle id="${id}"
margin="4" width="100%" overflow="hidden" box_sizing="border_box" margin="2" width="100%" overflow="hidden" box_sizing="border_box"
border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical" border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical"
gap="4" gap="4"
flex_direction="column" flex_direction="column"
@@ -68,7 +69,7 @@
<template name="KeySymbolAltGr"> <template name="KeySymbolAltGr">
<div width="${width}" height="${height}" min_width="${width}" min_height="${height}" max_width="${width}" max_height="${height}"> <div width="${width}" height="${height}" min_width="${width}" min_height="${height}" max_width="${width}" max_height="${height}">
<rectangle id="${id}" <rectangle id="${id}"
margin="4" width="100%" overflow="hidden" box_sizing="border_box" margin="2" width="100%" overflow="hidden" box_sizing="border_box"
border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical" border_color="#0044CC" border="2" round="8" color="#000A1C" color2="#000002" gradient="vertical"
flex_direction="row" flex_direction="row"
flex_wrap="wrap" flex_wrap="wrap"

View File

@@ -80,7 +80,7 @@ impl InteractionHandler for GuiPanel {
self.layout self.layout
.push_event(&WguiEvent::MouseWheel(MouseWheelEvent { .push_event(&WguiEvent::MouseWheel(MouseWheelEvent {
shift: vec2(delta_x, delta_y), shift: vec2(delta_x, delta_y),
pos: hit.uv, pos: hit.uv * self.layout.content_size,
device: hit.pointer, device: hit.pointer,
})) }))
.unwrap(); .unwrap();
@@ -89,7 +89,7 @@ impl InteractionHandler for GuiPanel {
fn on_hover(&mut self, _app: &mut AppState, hit: &PointerHit) -> Option<Haptics> { fn on_hover(&mut self, _app: &mut AppState, hit: &PointerHit) -> Option<Haptics> {
self.layout self.layout
.push_event(&WguiEvent::MouseMotion(MouseMotionEvent { .push_event(&WguiEvent::MouseMotion(MouseMotionEvent {
pos: hit.uv, pos: hit.uv * self.layout.content_size,
device: hit.pointer, device: hit.pointer,
})) }))
.unwrap(); .unwrap();
@@ -114,7 +114,7 @@ impl InteractionHandler for GuiPanel {
if pressed { if pressed {
self.layout self.layout
.push_event(&WguiEvent::MouseDown(MouseDownEvent { .push_event(&WguiEvent::MouseDown(MouseDownEvent {
pos: hit.uv, pos: hit.uv * self.layout.content_size,
button, button,
device: hit.pointer, device: hit.pointer,
})) }))
@@ -122,7 +122,7 @@ impl InteractionHandler for GuiPanel {
} else { } else {
self.layout self.layout
.push_event(&WguiEvent::MouseUp(MouseUpEvent { .push_event(&WguiEvent::MouseUp(MouseUpEvent {
pos: hit.uv, pos: hit.uv * self.layout.content_size,
button, button,
device: hit.pointer, device: hit.pointer,
})) }))

View File

@@ -3,6 +3,7 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc};
use glam::{Affine2, vec2, vec3a}; use glam::{Affine2, vec2, vec3a};
use wgui::{ use wgui::{
animation::{Animation, AnimationEasing}, animation::{Animation, AnimationEasing},
drawing::Color,
event::{self, EventListener}, event::{self, EventListener},
taffy::{self, prelude::length}, taffy::{self, prelude::length},
widget::{ widget::{
@@ -20,7 +21,8 @@ use crate::{
}; };
use super::{ use super::{
KEYBOARD_NAME, KeyState, KeyboardBackend, KeyboardState, handle_press, handle_release, KEYBOARD_NAME, KeyButtonData, KeyState, KeyboardBackend, KeyboardState, handle_press,
handle_release,
layout::{self, AltModifier, KeyCapType}, layout::{self, AltModifier, KeyCapType},
}; };
@@ -74,8 +76,10 @@ where
keymap = None; keymap = None;
} }
let (_, mut gui_state_key) = let (_, mut gui_state_key) = wgui::parser::new_layout_from_assets(
wgui::parser::new_layout_from_assets(Box::new(gui::asset::GuiAsset {}), "keyboard.xml")?; Box::new(gui::asset::GuiAsset {}),
"gui/keyboard.xml",
)?;
for row in 0..layout.key_sizes.len() { for row in 0..layout.key_sizes.len() {
let (div, _) = panel.layout.add_child( let (div, _) = panel.layout.add_child(
@@ -114,6 +118,11 @@ where
let my_id: Rc<str> = Rc::from(format!("key-{row}-{col}")); let my_id: Rc<str> = Rc::from(format!("key-{row}-{col}"));
let my_modifier = match key.button_state {
KeyButtonData::Modifier { modifier, .. } => Some(modifier),
_ => None,
};
// todo: make this easier to maintain somehow // todo: make this easier to maintain somehow
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new(); let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
params.insert(Rc::from("id"), my_id.clone()); params.insert(Rc::from("id"), my_id.clone());
@@ -167,6 +176,7 @@ where
color: rect.params.color, color: rect.params.color,
color2: rect.params.color2, color2: rect.params.color2,
border_color: rect.params.border_color, border_color: rect.params.border_color,
drawn_state: false.into(),
}) })
}; };
@@ -193,8 +203,8 @@ where
EventListener::MousePress(Box::new({ EventListener::MousePress(Box::new({
let (k, kb) = (key_state.clone(), state.clone()); let (k, kb) = (key_state.clone(), state.clone());
move |data, button| { move |data, button| {
on_press_anim(k.clone(), data);
handle_press(k.clone(), kb.clone(), button); handle_press(k.clone(), kb.clone(), button);
on_press_anim(k.clone(), data);
} }
})), })),
); );
@@ -203,11 +213,34 @@ where
EventListener::MouseRelease(Box::new({ EventListener::MouseRelease(Box::new({
let (k, kb) = (key_state.clone(), state.clone()); let (k, kb) = (key_state.clone(), state.clone());
move |data, button| { move |data, button| {
if handle_release(k.clone(), kb.clone(), button) {
on_release_anim(k.clone(), data); on_release_anim(k.clone(), data);
handle_release(k.clone(), kb.clone(), button); }
} }
})), })),
); );
if let Some(modifier) = my_modifier {
panel.layout.add_event_listener(
*widget_id,
EventListener::InternalStateChange(Box::new({
let (k, kb) = (key_state.clone(), state.clone());
move |data| {
if (kb.borrow().modifiers & modifier) != 0 {
if !k.drawn_state.get() {
on_press_anim(k.clone(), data);
k.drawn_state.set(true);
}
} else if k.drawn_state.get() {
on_release_anim(k.clone(), data);
k.drawn_state.set(false);
}
}
})),
);
}
} else {
log::warn!("No ID for key at ({row}, {col})");
} }
} }
} }
@@ -279,9 +312,9 @@ fn on_leave_anim(
)); ));
} }
fn on_press_anim(key_state: Rc<KeyState>, data: &mut event::CallbackData) { fn on_press_anim(_: Rc<KeyState>, data: &mut event::CallbackData) {
let rect = data.obj.get_as_mut::<Rectangle>(); let rect = data.obj.get_as_mut::<Rectangle>();
rect.params.border_color = key_state.border_color; rect.params.border_color = Color::new(1.0, 1.0, 1.0, 1.0);
data.needs_redraw = true; data.needs_redraw = true;
} }

View File

@@ -51,6 +51,10 @@ impl InteractionHandler for KeyboardBackend {
pressed: bool, pressed: bool,
) { ) {
self.panel.on_pointer(app, hit, pressed); self.panel.on_pointer(app, hit, pressed);
let _ = self
.panel
.layout
.push_event(&wgui::event::Event::InternalStateChange);
} }
fn on_scroll( fn on_scroll(
&mut self, &mut self,
@@ -98,7 +102,10 @@ impl OverlayRenderer for KeyboardBackend {
self.panel.pause(app) self.panel.pause(app)
} }
fn resume(&mut self, app: &mut AppState) -> anyhow::Result<()> { fn resume(&mut self, app: &mut AppState) -> anyhow::Result<()> {
self.panel.resume(app) self.panel.resume(app)?;
self.panel
.layout
.push_event(&wgui::event::Event::InternalStateChange)
} }
} }
@@ -117,6 +124,7 @@ struct KeyState {
color: drawing::Color, color: drawing::Color,
color2: drawing::Color, color2: drawing::Color,
border_color: drawing::Color, border_color: drawing::Color,
drawn_state: Cell<bool>,
} }
enum KeyButtonData { enum KeyButtonData {
@@ -194,7 +202,11 @@ fn handle_press(key: Rc<KeyState>, keyboard: Rc<RefCell<KeyboardState>>, button:
} }
} }
fn handle_release(key: Rc<KeyState>, keyboard: Rc<RefCell<KeyboardState>>, _button: MouseButton) { fn handle_release(
key: Rc<KeyState>,
keyboard: Rc<RefCell<KeyboardState>>,
_button: MouseButton,
) -> bool {
let mut keyboard = keyboard.borrow_mut(); let mut keyboard = keyboard.borrow_mut();
match &key.button_state { match &key.button_state {
KeyButtonData::Key { vk, pressed } => { KeyButtonData::Key { vk, pressed } => {
@@ -208,6 +220,7 @@ fn handle_release(key: Rc<KeyState>, keyboard: Rc<RefCell<KeyboardState>>, _butt
let mut hid = keyboard.hid.borrow_mut(); let mut hid = keyboard.hid.borrow_mut();
hid.send_key_routed(*vk, false); hid.send_key_routed(*vk, false);
hid.set_modifiers_routed(keyboard.modifiers); hid.set_modifiers_routed(keyboard.modifiers);
true
} }
KeyButtonData::Modifier { modifier, sticky } => { KeyButtonData::Modifier { modifier, sticky } => {
if !sticky.get() { if !sticky.get() {
@@ -216,7 +229,9 @@ fn handle_release(key: Rc<KeyState>, keyboard: Rc<RefCell<KeyboardState>>, _butt
.hid .hid
.borrow_mut() .borrow_mut()
.set_modifiers_routed(keyboard.modifiers); .set_modifiers_routed(keyboard.modifiers);
return true;
} }
false
} }
KeyButtonData::Exec { KeyButtonData::Exec {
release_program, release_program,
@@ -233,7 +248,8 @@ fn handle_release(key: Rc<KeyState>, keyboard: Rc<RefCell<KeyboardState>>, _butt
keyboard.processes.push(child); keyboard.processes.push(child);
} }
} }
true
} }
_ => {} _ => true,
} }
} }