kms: Add key repetition for shortcuts

This commit is contained in:
Victoria Brekenfeld 2023-07-06 18:20:10 +02:00
parent 99f29187af
commit 235248d445
6 changed files with 86 additions and 43 deletions

View file

@ -155,7 +155,7 @@ pub fn init_backend(
if let &mut InputEvent::DeviceAdded { ref mut device } = &mut event { if let &mut InputEvent::DeviceAdded { ref mut device } = &mut event {
data.state.common.config.read_device(device); data.state.common.config.read_device(device);
} }
data.state.process_input_event(event); data.state.process_input_event(event, true);
for output in data.state.common.shell.outputs() { for output in data.state.common.shell.outputs() {
if let Err(err) = data.state.backend.kms().schedule_render( if let Err(err) = data.state.backend.kms().schedule_render(
&data.state.common.event_loop_handle, &data.state.common.event_loop_handle,

View file

@ -360,7 +360,7 @@ impl State {
render_ping.ping(); render_ping.ping();
} }
WinitEvent::Refresh => render_ping.ping(), WinitEvent::Refresh => render_ping.ping(),
WinitEvent::Input(event) => self.process_input_event(event), WinitEvent::Input(event) => self.process_input_event(event, false),
_ => {} _ => {}
}; };
} }

View file

@ -535,7 +535,7 @@ impl State {
_ => {} _ => {}
}; };
self.process_input_event(event); self.process_input_event(event, false);
// TODO actually figure out the output // TODO actually figure out the output
for output in self.common.shell.outputs() { for output in self.common.shell.outputs() {
self.backend.x11().schedule_render(output, None); self.backend.x11().schedule_render(output, None);

View file

@ -15,6 +15,7 @@ use crate::{
utils::prelude::*, utils::prelude::*,
wayland::{handlers::screencopy::ScreencopySessions, protocols::screencopy::Session}, wayland::{handlers::screencopy::ScreencopySessions, protocols::screencopy::Session},
}; };
use calloop::{timer::Timer, RegistrationToken};
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType; use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType;
use smithay::{ use smithay::{
backend::input::{ backend::input::{
@ -40,7 +41,11 @@ use smithay::{
use tracing::info; use tracing::info;
use tracing::{error, trace, warn}; use tracing::{error, trace, warn};
use std::{cell::RefCell, collections::HashMap}; use std::{
cell::RefCell,
collections::HashMap,
time::{Duration, Instant},
};
use xkbcommon::xkb::KEY_XF86Switch_VT_12; use xkbcommon::xkb::KEY_XF86Switch_VT_12;
crate::utils::id_gen!(next_seat_id, SEAT_ID, SEAT_IDS); crate::utils::id_gen!(next_seat_id, SEAT_ID, SEAT_IDS);
@ -49,7 +54,7 @@ crate::utils::id_gen!(next_seat_id, SEAT_ID, SEAT_IDS);
pub struct SeatId(pub usize); pub struct SeatId(pub usize);
pub struct ActiveOutput(pub RefCell<Output>); pub struct ActiveOutput(pub RefCell<Output>);
#[derive(Default)] #[derive(Default)]
pub struct SupressedKeys(RefCell<Vec<u32>>); pub struct SupressedKeys(RefCell<Vec<(u32, Option<RegistrationToken>)>>);
#[derive(Default)] #[derive(Default)]
pub struct Devices(RefCell<HashMap<String, Vec<DeviceCapability>>>); pub struct Devices(RefCell<HashMap<String, Vec<DeviceCapability>>>);
@ -66,17 +71,26 @@ impl Drop for SeatId {
} }
impl SupressedKeys { impl SupressedKeys {
fn add(&self, keysym: &KeysymHandle) { fn add(&self, keysym: &KeysymHandle, token: impl Into<Option<RegistrationToken>>) {
self.0.borrow_mut().push(keysym.raw_code()); self.0.borrow_mut().push((keysym.raw_code(), token.into()));
} }
fn filter(&self, keysym: &KeysymHandle) -> bool { fn filter(&self, keysym: &KeysymHandle) -> Option<Vec<RegistrationToken>> {
let mut keys = self.0.borrow_mut(); let mut keys = self.0.borrow_mut();
if let Some(i) = keys.iter().position(|x| *x == keysym.raw_code()) { let (removed, remaining) = keys
keys.remove(i); .drain(..)
true .partition(|(key, _)| *key == keysym.raw_code());
*keys = remaining;
let removed = removed
.into_iter()
.map(|(_, token)| token)
.flatten()
.collect::<Vec<_>>();
if removed.is_empty() {
None
} else { } else {
false Some(removed)
} }
} }
} }
@ -154,7 +168,11 @@ pub fn add_seat(
} }
impl State { impl State {
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) { pub fn process_input_event<B: InputBackend>(
&mut self,
event: InputEvent<B>,
needs_key_repetition: bool,
) {
use smithay::backend::input::Event; use smithay::backend::input::Event;
match event { match event {
@ -195,7 +213,9 @@ impl State {
InputEvent::Keyboard { event, .. } => { InputEvent::Keyboard { event, .. } => {
use smithay::backend::input::KeyboardKeyEvent; use smithay::backend::input::KeyboardKeyEvent;
let loop_handle = self.common.event_loop_handle.clone();
let device = event.device(); let device = event.device();
for seat in self.common.seats().cloned().collect::<Vec<_>>().iter() { for seat in self.common.seats().cloned().collect::<Vec<_>>().iter() {
let current_output = seat.active_output(); let current_output = seat.active_output();
let workspace = self.common.shell.active_space_mut(&current_output); let workspace = self.common.shell.active_space_mut(&current_output);
@ -251,7 +271,6 @@ impl State {
&& handle.raw_syms().contains(&action_pattern.key) && handle.raw_syms().contains(&action_pattern.key)
{ {
data.common.shell.set_resize_mode(None, &data.common.config, data.common.event_loop_handle.clone()); data.common.shell.set_resize_mode(None, &data.common.config, data.common.event_loop_handle.clone());
return FilterResult::Intercept(None);
} else if action_pattern.modifiers != *modifiers { } else if action_pattern.modifiers != *modifiers {
let mut new_pattern = action_pattern.clone(); let mut new_pattern = action_pattern.clone();
new_pattern.modifiers = modifiers.clone().into(); new_pattern.modifiers = modifiers.clone().into();
@ -280,10 +299,10 @@ impl State {
data.common.shell.resize_mode() data.common.shell.resize_mode()
{ {
let resize_edge = match handle.modified_sym() { let resize_edge = match handle.modified_sym() {
keysyms::KEY_Left | keysyms::KEY_H => Some(ResizeEdge::LEFT), keysyms::KEY_Left | keysyms::KEY_h | keysyms::KEY_H => Some(ResizeEdge::LEFT),
keysyms::KEY_Down | keysyms::KEY_J => Some(ResizeEdge::BOTTOM), keysyms::KEY_Down | keysyms::KEY_j | keysyms::KEY_J => Some(ResizeEdge::BOTTOM),
keysyms::KEY_Up | keysyms::KEY_K => Some(ResizeEdge::TOP), keysyms::KEY_Up | keysyms::KEY_k | keysyms::KEY_K => Some(ResizeEdge::TOP),
keysyms::KEY_Right | keysyms::KEY_L => Some(ResizeEdge::RIGHT), keysyms::KEY_Right | keysyms::KEY_l | keysyms::KEY_L => Some(ResizeEdge::RIGHT),
_ => None, _ => None,
}; };
@ -291,21 +310,51 @@ impl State {
if direction == ResizeDirection::Inwards { if direction == ResizeDirection::Inwards {
edge.flip_direction(); edge.flip_direction();
} }
let action = Action::_ResizingInternal(direction, edge, state);
let key_pattern = KeyPattern {
modifiers: modifiers.clone().into(),
key: handle.raw_code(),
};
if state == KeyState::Released {
if let Some(tokens) = userdata.get::<SupressedKeys>().unwrap().filter(&handle) {
for token in tokens {
loop_handle.remove(token);
}
}
} else {
let token = if needs_key_repetition {
let seat_clone = seat.clone();
let action_clone = action.clone();
let key_pattern_clone = key_pattern.clone();
let start = Instant::now();
loop_handle.insert_source(Timer::from_duration(Duration::from_millis(200)), move |current, _, data| {
let duration = current.duration_since(start).as_millis();
data.state.handle_action(action_clone.clone(), &seat_clone, serial, time.overflowing_add(duration as u32).0, key_pattern_clone.clone(), None);
calloop::timer::TimeoutAction::ToDuration(Duration::from_millis(25))
}).ok()
} else { None };
userdata
.get::<SupressedKeys>()
.unwrap()
.add(&handle, token);
}
return FilterResult::Intercept(Some(( return FilterResult::Intercept(Some((
Action::_ResizingInternal(direction, edge, state), action,
KeyPattern { key_pattern
modifiers: modifiers.clone().into(),
key: handle.raw_code(),
},
))); )));
} }
} }
// Skip released events for initially surpressed keys // Skip released events for initially surpressed keys
if state == KeyState::Released if state == KeyState::Released {
&& userdata.get::<SupressedKeys>().unwrap().filter(&handle) if let Some(tokens) = userdata.get::<SupressedKeys>().unwrap().filter(&handle) {
{ for token in tokens {
return FilterResult::Intercept(None); loop_handle.remove(token);
}
return FilterResult::Intercept(None);
}
} }
// Pass keys to debug interface, if it has focus // Pass keys to debug interface, if it has focus
@ -341,7 +390,7 @@ impl State {
) { ) {
error!(?err, "Failed switching virtual terminal."); error!(?err, "Failed switching virtual terminal.");
} }
userdata.get::<SupressedKeys>().unwrap().add(&handle); userdata.get::<SupressedKeys>().unwrap().add(&handle, None);
return FilterResult::Intercept(None); return FilterResult::Intercept(None);
} }
@ -357,7 +406,7 @@ impl State {
userdata userdata
.get::<SupressedKeys>() .get::<SupressedKeys>()
.unwrap() .unwrap()
.add(&handle); .add(&handle, None);
return FilterResult::Intercept(Some(( return FilterResult::Intercept(Some((
action.clone(), action.clone(),
binding.clone(), binding.clone(),
@ -1188,9 +1237,9 @@ impl State {
), ),
Action::_ResizingInternal(direction, edge, state) => { Action::_ResizingInternal(direction, edge, state) => {
if state == KeyState::Pressed { if state == KeyState::Pressed {
self.common.shell.start_resize(seat, direction, edge); self.common.shell.resize(seat, direction, edge);
} else { } else {
self.common.shell.stop_resize(seat, direction, edge); self.common.shell.finish_resize(direction, edge);
} }
} }
Action::ToggleOrientation => { Action::ToggleOrientation => {

View file

@ -129,6 +129,7 @@ impl CosmicStack {
for window in &windows { for window in &windows {
window.try_force_undecorated(true); window.try_force_undecorated(true);
window.set_tiled(true); window.set_tiled(true);
window.send_configure();
} }
let width = windows[0].geometry().size.w; let width = windows[0].geometry().size.w;

View file

@ -1249,6 +1249,9 @@ impl Shell {
} else { } else {
if let ResizeMode::Started(_, _, direction) = &self.resize_mode { if let ResizeMode::Started(_, _, direction) = &self.resize_mode {
self.resize_mode = ResizeMode::Ended(Instant::now(), *direction); self.resize_mode = ResizeMode::Ended(Instant::now(), *direction);
if let Some((_, direction, edge, _, _, _)) = self.resize_state.as_ref() {
self.finish_resize(*direction, *edge);
}
} }
} }
} }
@ -1591,12 +1594,7 @@ impl Shell {
} }
} }
pub fn start_resize( pub fn resize(&mut self, seat: &Seat<State>, direction: ResizeDirection, edge: ResizeEdge) {
&mut self,
seat: &Seat<State>,
direction: ResizeDirection,
edge: ResizeEdge,
) {
let output = seat.active_output(); let output = seat.active_output();
let (_, idx) = self.workspaces.active_num(&output); let (_, idx) = self.workspaces.active_num(&output);
let Some(focused) = seat.get_keyboard().unwrap().current_focus() else { return }; let Some(focused) = seat.get_keyboard().unwrap().current_focus() else { return };
@ -1615,12 +1613,7 @@ impl Shell {
} }
} }
pub fn stop_resize( pub fn finish_resize(&mut self, direction: ResizeDirection, edge: ResizeEdge) {
&mut self,
_seat: &Seat<State>,
direction: ResizeDirection,
edge: ResizeEdge,
) {
if let Some((old_focused, old_direction, old_edge, _, idx, output)) = if let Some((old_focused, old_direction, old_edge, _, idx, output)) =
self.resize_state.take() self.resize_state.take()
{ {