less refcells; haptics

This commit is contained in:
galister
2025-06-20 17:47:39 +09:00
parent 887a2f6bde
commit df320a5c7b
14 changed files with 159 additions and 153 deletions

View File

@@ -21,8 +21,7 @@ use crate::{
};
use super::{
KEYBOARD_NAME, KeyButtonData, KeyState, KeyboardBackend, KeyboardState, handle_press,
handle_release,
KEYBOARD_NAME, KeyButtonData, KeyState, KeyboardBackend, KeyboardState,
layout::{self, AltModifier, KeyCapType},
};
@@ -39,8 +38,7 @@ where
{
let layout = layout::Layout::load_from_disk();
let state = Rc::new(RefCell::new(KeyboardState {
hid: app.hid_provider.clone(),
audio: app.audio_provider.clone(),
invoke_action: None,
modifiers: 0,
alt_modifier: match layout.alt_modifier {
AltModifier::Shift => SHIFT,
@@ -185,6 +183,7 @@ where
EventListener::MouseEnter(Box::new({
let (k, kb) = (key_state.clone(), state.clone());
move |data| {
data.trigger_haptics = true;
on_enter_anim(k.clone(), kb.clone(), data);
}
})),
@@ -194,6 +193,7 @@ where
EventListener::MouseLeave(Box::new({
let (k, kb) = (key_state.clone(), state.clone());
move |data| {
data.trigger_haptics = true;
on_leave_anim(k.clone(), kb.clone(), data);
}
})),
@@ -203,7 +203,11 @@ where
EventListener::MousePress(Box::new({
let (k, kb) = (key_state.clone(), state.clone());
move |data, button| {
handle_press(k.clone(), kb.clone(), button);
kb.borrow_mut().invoke_action = Some(super::InvokeAction {
key: k.clone(),
button,
pressed: true,
});
on_press_anim(k.clone(), data);
}
})),
@@ -213,7 +217,12 @@ where
EventListener::MouseRelease(Box::new({
let (k, kb) = (key_state.clone(), state.clone());
move |data, button| {
if handle_release(k.clone(), kb.clone(), button) {
kb.borrow_mut().invoke_action = Some(super::InvokeAction {
key: k.clone(),
button,
pressed: false,
});
if !matches!(&k.button_state, KeyButtonData::Modifier { sticky, .. } if sticky.get()) {
on_release_anim(k.clone(), data);
}
}
@@ -227,13 +236,9 @@ where
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_press_anim(k.clone(), data);
} else {
on_release_anim(k.clone(), data);
k.drawn_state.set(false);
}
}
})),
@@ -312,14 +317,22 @@ fn on_leave_anim(
));
}
fn on_press_anim(_: Rc<KeyState>, data: &mut event::CallbackData) {
fn on_press_anim(key_state: Rc<KeyState>, data: &mut event::CallbackData) {
if key_state.drawn_state.get() {
return;
}
let rect = data.obj.get_as_mut::<Rectangle>();
rect.params.border_color = Color::new(1.0, 1.0, 1.0, 1.0);
data.needs_redraw = true;
key_state.drawn_state.set(true);
}
fn on_release_anim(key_state: Rc<KeyState>, data: &mut event::CallbackData) {
if !key_state.drawn_state.get() {
return;
}
let rect = data.obj.get_as_mut::<Rectangle>();
rect.params.border_color = key_state.border_color;
data.needs_redraw = true;
key_state.drawn_state.set(false);
}

View File

@@ -10,17 +10,13 @@ use wgui::{drawing, event::MouseButton};
use crate::{
backend::{
input::InteractionHandler,
input::{Haptics, InteractionHandler, PointerHit},
overlay::{FrameMeta, OverlayBackend, OverlayRenderer, ShouldRender},
},
graphics::CommandBuffers,
gui::panel::GuiPanel,
state::AppState,
subsystem::{
audio::{AudioOutput, AudioRole},
hid::{ALT, CTRL, KeyModifier, META, SHIFT, SUPER, VirtualKey},
input::HidWrapper,
},
subsystem::hid::{ALT, CTRL, KeyModifier, META, SHIFT, SUPER, VirtualKey},
};
pub mod builder;
@@ -34,6 +30,21 @@ struct KeyboardBackend {
state: Rc<RefCell<KeyboardState>>,
}
impl KeyboardBackend {
fn handle_invoke(&mut self, app: &mut AppState) {
let mut keyboard = self.state.borrow_mut();
let Some(action) = keyboard.invoke_action.take() else {
return;
};
if action.pressed {
handle_press(app, &action.key, &mut keyboard, action.button);
} else {
handle_release(app, &action.key, &mut keyboard);
}
}
}
impl OverlayBackend for KeyboardBackend {
fn set_interaction(&mut self, interaction: Box<dyn crate::backend::input::InteractionHandler>) {
self.panel.set_interaction(interaction);
@@ -44,35 +55,20 @@ impl OverlayBackend for KeyboardBackend {
}
impl InteractionHandler for KeyboardBackend {
fn on_pointer(
&mut self,
app: &mut AppState,
hit: &crate::backend::input::PointerHit,
pressed: bool,
) {
fn on_pointer(&mut self, app: &mut AppState, hit: &PointerHit, pressed: bool) {
self.panel.on_pointer(app, hit, pressed);
let _ = self
.panel
.layout
.push_event(&wgui::event::Event::InternalStateChange);
}
fn on_scroll(
&mut self,
app: &mut AppState,
hit: &crate::backend::input::PointerHit,
delta_y: f32,
delta_x: f32,
) {
fn on_scroll(&mut self, app: &mut AppState, hit: &PointerHit, delta_y: f32, delta_x: f32) {
self.panel.on_scroll(app, hit, delta_y, delta_x);
}
fn on_left(&mut self, app: &mut AppState, pointer: usize) {
self.panel.on_left(app, pointer);
}
fn on_hover(
&mut self,
app: &mut AppState,
hit: &crate::backend::input::PointerHit,
) -> Option<crate::backend::input::Haptics> {
fn on_hover(&mut self, app: &mut AppState, hit: &PointerHit) -> Option<Haptics> {
self.panel.on_hover(app, hit)
}
}
@@ -98,20 +94,26 @@ impl OverlayRenderer for KeyboardBackend {
}
fn pause(&mut self, app: &mut AppState) -> anyhow::Result<()> {
self.state.borrow_mut().modifiers = 0;
app.hid_provider.borrow_mut().set_modifiers_routed(0);
app.hid_provider.set_modifiers_routed(0);
self.panel.pause(app)
}
fn resume(&mut self, app: &mut AppState) -> anyhow::Result<()> {
self.panel.resume(app)?;
self.panel
.layout
.push_event(&wgui::event::Event::InternalStateChange)
.push_event(&wgui::event::Event::InternalStateChange)?;
Ok(())
}
}
struct InvokeAction {
key: Rc<KeyState>,
button: MouseButton,
pressed: bool,
}
struct KeyboardState {
hid: Rc<RefCell<HidWrapper>>,
audio: Rc<RefCell<AudioOutput>>,
invoke_action: Option<InvokeAction>,
modifiers: KeyModifier,
alt_modifier: KeyModifier,
processes: Vec<Child>,
@@ -119,6 +121,10 @@ struct KeyboardState {
const KEY_AUDIO_WAV: &[u8] = include_bytes!("../../res/421581.wav");
fn play_key_click(app: &mut AppState) {
app.audio_provider.play(KEY_AUDIO_WAV);
}
struct KeyState {
button_state: KeyButtonData,
color: drawing::Color,
@@ -127,6 +133,7 @@ struct KeyState {
drawn_state: Cell<bool>,
}
#[derive(Debug)]
enum KeyButtonData {
Key {
vk: VirtualKey,
@@ -147,15 +154,12 @@ enum KeyButtonData {
},
}
fn play_key_click(keyboard: &KeyboardState) {
keyboard
.audio
.borrow_mut()
.play(AudioRole::Keyboard, KEY_AUDIO_WAV);
}
fn handle_press(key: Rc<KeyState>, keyboard: Rc<RefCell<KeyboardState>>, button: MouseButton) {
let mut keyboard = keyboard.borrow_mut();
fn handle_press(
app: &mut AppState,
key: &KeyState,
keyboard: &mut KeyboardState,
button: MouseButton,
) {
match &key.button_state {
KeyButtonData::Key { vk, pressed } => {
keyboard.modifiers |= match button {
@@ -164,29 +168,22 @@ fn handle_press(key: Rc<KeyState>, keyboard: Rc<RefCell<KeyboardState>>, button:
_ => 0,
};
{
let mut hid = keyboard.hid.borrow_mut();
hid.set_modifiers_routed(keyboard.modifiers);
hid.send_key_routed(*vk, true);
}
app.hid_provider.set_modifiers_routed(keyboard.modifiers);
app.hid_provider.send_key_routed(*vk, true);
pressed.set(true);
play_key_click(&keyboard);
play_key_click(app);
}
KeyButtonData::Modifier { modifier, sticky } => {
sticky.set(keyboard.modifiers & *modifier == 0);
keyboard.modifiers |= *modifier;
keyboard
.hid
.borrow_mut()
.set_modifiers_routed(keyboard.modifiers);
play_key_click(&keyboard);
app.hid_provider.set_modifiers_routed(keyboard.modifiers);
play_key_click(app);
}
KeyButtonData::Macro { verbs } => {
let hid = keyboard.hid.borrow_mut();
for (vk, press) in verbs {
hid.send_key_routed(*vk, *press);
app.hid_provider.send_key_routed(*vk, *press);
}
play_key_click(&keyboard);
play_key_click(app);
}
KeyButtonData::Exec { program, args, .. } => {
// Reap previous processes
@@ -197,17 +194,12 @@ fn handle_press(key: Rc<KeyState>, keyboard: Rc<RefCell<KeyboardState>>, button:
if let Ok(child) = Command::new(program).args(args).spawn() {
keyboard.processes.push(child);
}
play_key_click(&keyboard);
play_key_click(app);
}
}
}
fn handle_release(
key: Rc<KeyState>,
keyboard: Rc<RefCell<KeyboardState>>,
_button: MouseButton,
) -> bool {
let mut keyboard = keyboard.borrow_mut();
fn handle_release(app: &mut AppState, key: &KeyState, keyboard: &mut KeyboardState) {
match &key.button_state {
KeyButtonData::Key { vk, pressed } => {
pressed.set(false);
@@ -217,21 +209,14 @@ fn handle_release(
keyboard.modifiers &= !*m;
}
}
let mut hid = keyboard.hid.borrow_mut();
hid.send_key_routed(*vk, false);
hid.set_modifiers_routed(keyboard.modifiers);
true
app.hid_provider.send_key_routed(*vk, false);
app.hid_provider.set_modifiers_routed(keyboard.modifiers);
}
KeyButtonData::Modifier { modifier, sticky } => {
if !sticky.get() {
keyboard.modifiers &= !*modifier;
keyboard
.hid
.borrow_mut()
.set_modifiers_routed(keyboard.modifiers);
return true;
app.hid_provider.set_modifiers_routed(keyboard.modifiers);
}
false
}
KeyButtonData::Exec {
release_program,
@@ -248,8 +233,7 @@ fn handle_release(
keyboard.processes.push(child);
}
}
true
}
_ => true,
_ => {}
}
}

View File

@@ -131,7 +131,7 @@ impl InteractionHandler for ScreenInteractionHandler {
|| app.input_state.pointers[hit.pointer].now.move_mouse)
{
let pos = self.mouse_transform.transform_point2(hit.uv);
app.hid_provider.borrow_mut().inner.mouse_move(pos);
app.hid_provider.inner.mouse_move(pos);
set_next_move(u64::from(app.session.config.mouse_move_interval_ms));
}
None
@@ -147,19 +147,16 @@ impl InteractionHandler for ScreenInteractionHandler {
set_next_move(u64::from(app.session.config.click_freeze_time_ms));
}
let mut hid_provider = app.hid_provider.borrow_mut();
hid_provider.inner.send_button(btn, pressed);
app.hid_provider.inner.send_button(btn, pressed);
if !pressed {
return;
}
let pos = self.mouse_transform.transform_point2(hit.uv);
hid_provider.inner.mouse_move(pos);
app.hid_provider.inner.mouse_move(pos);
}
fn on_scroll(&mut self, app: &mut AppState, _hit: &PointerHit, delta_y: f32, delta_x: f32) {
app.hid_provider
.borrow_mut()
.inner
.wheel((delta_y * 64.) as i32, (delta_x * 64.) as i32);
}
@@ -892,11 +889,10 @@ pub fn create_screens_wayland(wl: &mut WlxClientAlias, app: &mut AppState) -> Sc
let extent = wl.get_desktop_extent();
let origin = wl.get_desktop_origin();
let mut hid_provider = app.hid_provider.borrow_mut();
hid_provider
app.hid_provider
.inner
.set_desktop_extent(vec2(extent.0 as f32, extent.1 as f32));
hid_provider
app.hid_provider
.inner
.set_desktop_origin(vec2(origin.0 as f32, origin.1 as f32));
@@ -995,9 +991,8 @@ pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateDa
})
.collect();
let mut hid_provider = app.hid_provider.borrow_mut();
hid_provider.inner.set_desktop_extent(extent);
hid_provider.inner.set_desktop_origin(vec2(0.0, 0.0));
app.hid_provider.inner.set_desktop_extent(extent);
app.hid_provider.inner.set_desktop_origin(vec2(0.0, 0.0));
Ok(ScreenCreateData { screens })
}
@@ -1054,9 +1049,8 @@ pub fn create_screens_xshm(app: &mut AppState) -> anyhow::Result<ScreenCreateDat
})
.collect();
let mut hid_provider = app.hid_provider.borrow_mut();
hid_provider.inner.set_desktop_extent(extent);
hid_provider.inner.set_desktop_origin(vec2(0.0, 0.0));
app.hid_provider.inner.set_desktop_extent(extent);
app.hid_provider.inner.set_desktop_origin(vec2(0.0, 0.0));
Ok(ScreenCreateData { screens })
}

View File

@@ -30,7 +30,6 @@ use crate::{
},
gui::panel::GuiPanel,
state::{AppState, LeftRight},
subsystem::audio::AudioRole,
};
const FONT_SIZE: isize = 16;
@@ -94,10 +93,8 @@ impl Toast {
let destroy_at = instant.add(std::time::Duration::from_secs_f32(self.timeout));
if self.sound {
app.audio_provider
.borrow_mut()
.play(AudioRole::Notification, app.toast_sound);
if self.sound && app.session.config.notifications_sound_enabled {
app.audio_provider.play(app.toast_sound);
}
// drop any toast that was created before us.