keyboard works
This commit is contained in:
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,15 +297,18 @@ 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) => {
|
||||||
pressed_changed_button = self
|
if hovered {
|
||||||
.data
|
pressed_changed_button = self
|
||||||
.set_device_pressed(e.device, true)
|
.data
|
||||||
.then_some(e.button);
|
.set_device_pressed(e.device, true)
|
||||||
|
.then_some(e.button);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Event::MouseUp(e) => {
|
Event::MouseUp(e) => {
|
||||||
pressed_changed_button = self
|
pressed_changed_button = self
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -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,
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -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| {
|
||||||
on_release_anim(k.clone(), data);
|
if handle_release(k.clone(), kb.clone(), button) {
|
||||||
handle_release(k.clone(), kb.clone(), button);
|
on_release_anim(k.clone(), data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user