From 7123ecf8bad982eddec9304270dcd014da19e8aa Mon Sep 17 00:00:00 2001 From: Ottatop Date: Mon, 7 Aug 2023 19:48:18 -0500 Subject: [PATCH 1/4] Add vt switching --- src/backend/udev.rs | 2 +- src/input.rs | 148 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 129 insertions(+), 21 deletions(-) diff --git a/src/backend/udev.rs b/src/backend/udev.rs index 21a01ae..6166e0e 100644 --- a/src/backend/udev.rs +++ b/src/backend/udev.rs @@ -122,7 +122,7 @@ struct UdevOutputId { } pub struct UdevData { - session: LibSeatSession, + pub session: LibSeatSession, display_handle: DisplayHandle, dmabuf_state: Option<(DmabufState, DmabufGlobal)>, primary_gpu: DrmNode, diff --git a/src/input.rs b/src/input.rs index 70d21a6..9c33dd5 100644 --- a/src/input.rs +++ b/src/input.rs @@ -8,10 +8,10 @@ use crate::{ window::WindowElement, }; use smithay::{ - backend::input::{ + backend::{input::{ AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent, KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent, - }, + }, session::Session}, desktop::{layer_map_for_output, space::SpaceElement}, input::{ keyboard::{keysyms, FilterResult}, @@ -304,6 +304,26 @@ impl State { .axis(self, frame); } + +} + +impl State { + pub fn process_input_event(&mut self, event: InputEvent) { + match event { + // TODO: rest of input events + + // InputEvent::DeviceAdded { device } => todo!(), + // InputEvent::DeviceRemoved { device } => todo!(), + InputEvent::Keyboard { event } => self.keyboard::(event), + // InputEvent::PointerMotion { event } => {} + InputEvent::PointerMotionAbsolute { event } => self.pointer_motion_absolute::(event), + InputEvent::PointerButton { event } => self.pointer_button::(event), + InputEvent::PointerAxis { event } => self.pointer_axis::(event), + + _ => (), + } + } + fn keyboard(&mut self, event: I::KeyboardKeyEvent) { let serial = SERIAL_COUNTER.next_serial(); let time = event.time_msec(); @@ -351,6 +371,13 @@ impl State { && keysym.modified_sym() == keysyms::KEY_Escape { return FilterResult::Intercept(CallbackId(999999)); + } else if modifiers.ctrl && modifiers.alt { + if let mut vt @ keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 = + keysym.modified_sym() { + vt = vt - keysyms::KEY_XF86Switch_VT_1 + 1; + tracing::info!("Switching to vt {vt}"); + + } } } @@ -387,24 +414,6 @@ impl State { } } } -} - -impl State { - pub fn process_input_event(&mut self, event: InputEvent) { - match event { - // TODO: rest of input events - - // InputEvent::DeviceAdded { device } => todo!(), - // InputEvent::DeviceRemoved { device } => todo!(), - InputEvent::Keyboard { event } => self.keyboard::(event), - // InputEvent::PointerMotion { event } => {} - InputEvent::PointerMotionAbsolute { event } => self.pointer_motion_absolute::(event), - InputEvent::PointerButton { event } => self.pointer_button::(event), - InputEvent::PointerAxis { event } => self.pointer_axis::(event), - - _ => (), - } - } fn pointer_motion_absolute(&mut self, event: I::PointerMotionAbsoluteEvent) { let Some(output) = self.space.outputs().next() else { return; }; @@ -470,6 +479,105 @@ impl State { } } + fn keyboard(&mut self, event: I::KeyboardKeyEvent) { + let serial = SERIAL_COUNTER.next_serial(); + let time = event.time_msec(); + let press_state = event.state(); + let mut move_mode = false; + let action = self + .seat + .get_keyboard() + .expect("Seat has no keyboard") // FIXME: handle err + .input( + self, + event.key_code(), + press_state, + serial, + time, + |state, modifiers, keysym| { + if press_state == KeyState::Pressed { + let mut modifier_mask = Vec::::new(); + if modifiers.alt { + modifier_mask.push(Modifier::Alt); + } + if modifiers.shift { + modifier_mask.push(Modifier::Shift); + } + if modifiers.ctrl { + modifier_mask.push(Modifier::Ctrl); + } + if modifiers.logo { + modifier_mask.push(Modifier::Super); + } + let raw_sym = if keysym.raw_syms().len() == 1 { + keysym.raw_syms()[0] + } else { + keysyms::KEY_NoSymbol + }; + if let Some(callback_id) = state + .input_state + .keybinds + .get(&(modifier_mask.into(), raw_sym)) + { + return FilterResult::Intercept(*callback_id); + } else if modifiers.ctrl + && modifiers.shift + && modifiers.alt + && keysym.modified_sym() == keysyms::KEY_Escape + { + return FilterResult::Intercept(CallbackId(999999)); + } else if modifiers.ctrl && modifiers.alt { + if let mut vt @ keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 = + keysym.modified_sym() { + vt = vt - keysyms::KEY_XF86Switch_VT_1 + 1; + return FilterResult::Intercept(CallbackId(1000000 + vt)); + } + } + } + + if keysym.modified_sym() == keysyms::KEY_Control_L { + match press_state { + KeyState::Pressed => { + move_mode = true; + } + KeyState::Released => { + move_mode = false; + } + } + } + FilterResult::Forward + }, + ); + + self.move_mode = move_mode; + + if let Some(callback_id) = action { + if callback_id.0 == 999999 { + self.loop_signal.stop(); + return; + } + if callback_id.0 > 1000000 { + let vt = callback_id.0 - 1000000; + tracing::info!("Switching to vt {vt}"); + if let Err(err) = self.backend_data.session.change_vt(vt as i32) { + tracing::error!("Failed to switch to vt {vt}: {err}"); + } + return; + } + if let Some(stream) = self.api_state.stream.as_ref() { + if let Err(err) = crate::api::send_to_client( + &mut stream.lock().expect("Could not lock stream mutex"), + &OutgoingMsg::CallCallback { + callback_id, + args: None, + }, + ) { + tracing::warn!("error sending msg to client: {err}"); + } + } + } + } + fn pointer_motion(&mut self, event: I::PointerMotionEvent) { let serial = SERIAL_COUNTER.next_serial(); self.pointer_location += event.delta(); From c153eb6abb993b514ae7a25e294a6a6908490801 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Tue, 8 Aug 2023 10:55:06 -0500 Subject: [PATCH 2/4] Dedup and clean up code --- src/backend/udev.rs | 26 ++-- src/input.rs | 304 ++++++++++++++++---------------------------- 2 files changed, 123 insertions(+), 207 deletions(-) diff --git a/src/backend/udev.rs b/src/backend/udev.rs index 6166e0e..a741d72 100644 --- a/src/backend/udev.rs +++ b/src/backend/udev.rs @@ -303,8 +303,18 @@ pub fn run_udev() -> Result<(), Box> { libinput_context.suspend(); tracing::info!("pausing session"); - for backend in data.state.backend_data.backends.values() { + for backend in data.state.backend_data.backends.values_mut() { backend.drm.pause(); + for surface in backend.surfaces.values_mut() { + if let Err(err) = surface.compositor.surface().reset_state() { + tracing::warn!("Failed to reset drm surface state: {}", err); + } + // reset the buffers after resume to trigger a full redraw + // this is important after a vt switch as the primary plane + // has no content and damage tracking may prevent a redraw + // otherwise + surface.compositor.reset_buffers(); + } } } session::Event::ActivateSession => { @@ -1076,9 +1086,7 @@ impl State { } fn device_removed(&mut self, node: DrmNode) { - let device = if let Some(device) = self.backend_data.backends.get_mut(&node) { - device - } else { + let Some(device) = self.backend_data.backends.get_mut(&node) else { return; }; @@ -1291,15 +1299,11 @@ impl State { } fn render_surface(&mut self, node: DrmNode, crtc: crtc::Handle) { - let device = if let Some(device) = self.backend_data.backends.get_mut(&node) { - device - } else { + let Some(device) = self.backend_data.backends.get_mut(&node) else { return; }; - let surface = if let Some(surface) = device.surfaces.get_mut(&crtc) { - surface - } else { + let Some(surface) = device.surfaces.get_mut(&crtc) else { return; }; @@ -1584,7 +1588,7 @@ fn render_surface<'a>( let time = clock.now(); // We need to send frames to the cursor surface so that xwayland windows will properly - // update on motion. + // update the cursor on motion. if let CursorImageStatus::Surface(surf) = cursor_status { send_frames_surface_tree(surf, output, time, Some(Duration::ZERO), |_, _| None); } diff --git a/src/input.rs b/src/input.rs index 9c33dd5..15a7071 100644 --- a/src/input.rs +++ b/src/input.rs @@ -8,10 +8,13 @@ use crate::{ window::WindowElement, }; use smithay::{ - backend::{input::{ - AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent, - KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent, - }, session::Session}, + backend::{ + input::{ + AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent, + KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent, + }, + session::Session, + }, desktop::{layer_map_for_output, space::SpaceElement}, input::{ keyboard::{keysyms, FilterResult}, @@ -87,6 +90,107 @@ impl State { }) } + fn keyboard(&mut self, event: I::KeyboardKeyEvent) { + let serial = SERIAL_COUNTER.next_serial(); + let time = event.time_msec(); + let press_state = event.state(); + let mut move_mode = false; + let action = self + .seat + .get_keyboard() + .expect("Seat has no keyboard") // FIXME: handle err + .input( + self, + event.key_code(), + press_state, + serial, + time, + |state, modifiers, keysym| { + if press_state == KeyState::Pressed { + let mut modifier_mask = Vec::::new(); + if modifiers.alt { + modifier_mask.push(Modifier::Alt); + } + if modifiers.shift { + modifier_mask.push(Modifier::Shift); + } + if modifiers.ctrl { + modifier_mask.push(Modifier::Ctrl); + } + if modifiers.logo { + modifier_mask.push(Modifier::Super); + } + let raw_sym = if keysym.raw_syms().len() == 1 { + keysym.raw_syms()[0] + } else { + keysyms::KEY_NoSymbol + }; + if let Some(callback_id) = state + .input_state + .keybinds + .get(&(modifier_mask.into(), raw_sym)) + { + return FilterResult::Intercept(*callback_id); + } else if modifiers.ctrl + && modifiers.shift + && modifiers.alt + && keysym.modified_sym() == keysyms::KEY_Escape + { + return FilterResult::Intercept(CallbackId(999999)); + } else if let mut vt @ keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 = + keysym.modified_sym() { + vt = vt - keysyms::KEY_XF86Switch_VT_1 + 1; + tracing::info!("Switching to vt {vt}"); + return FilterResult::Intercept(CallbackId(1000000 + vt)); + } + + } + + if keysym.modified_sym() == keysyms::KEY_Control_L { + match press_state { + KeyState::Pressed => { + move_mode = true; + } + KeyState::Released => { + move_mode = false; + } + } + } + FilterResult::Forward + }, + ); + + self.move_mode = move_mode; + + if let Some(callback_id) = action { + if callback_id.0 == 999999 { + self.loop_signal.stop(); + return; + } + if callback_id.0 > 1000000 { + let vt = callback_id.0 - 1000000; + if let Some(st) = (self as &mut dyn std::any::Any).downcast_mut::>() + { + if let Err(err) = st.backend_data.session.change_vt(vt as i32) { + tracing::error!("Failed to switch to vt {vt}: {err}"); + } + } + return; + } + if let Some(stream) = self.api_state.stream.as_ref() { + if let Err(err) = crate::api::send_to_client( + &mut stream.lock().expect("Could not lock stream mutex"), + &OutgoingMsg::CallCallback { + callback_id, + args: None, + }, + ) { + tracing::warn!("error sending msg to client: {err}"); + } + } + } + } + fn pointer_button(&mut self, event: I::PointerButtonEvent) { let pointer = self.seat.get_pointer().expect("Seat has no pointer"); // FIXME: handle err let keyboard = self.seat.get_keyboard().expect("Seat has no keyboard"); // FIXME: handle err @@ -303,8 +407,6 @@ impl State { .expect("Seat has no pointer") .axis(self, frame); } - - } impl State { @@ -324,97 +426,6 @@ impl State { } } - fn keyboard(&mut self, event: I::KeyboardKeyEvent) { - let serial = SERIAL_COUNTER.next_serial(); - let time = event.time_msec(); - let press_state = event.state(); - let mut move_mode = false; - let action = self - .seat - .get_keyboard() - .expect("Seat has no keyboard") // FIXME: handle err - .input( - self, - event.key_code(), - press_state, - serial, - time, - |state, modifiers, keysym| { - if press_state == KeyState::Pressed { - let mut modifier_mask = Vec::::new(); - if modifiers.alt { - modifier_mask.push(Modifier::Alt); - } - if modifiers.shift { - modifier_mask.push(Modifier::Shift); - } - if modifiers.ctrl { - modifier_mask.push(Modifier::Ctrl); - } - if modifiers.logo { - modifier_mask.push(Modifier::Super); - } - let raw_sym = if keysym.raw_syms().len() == 1 { - keysym.raw_syms()[0] - } else { - keysyms::KEY_NoSymbol - }; - if let Some(callback_id) = state - .input_state - .keybinds - .get(&(modifier_mask.into(), raw_sym)) - { - return FilterResult::Intercept(*callback_id); - } else if modifiers.ctrl - && modifiers.shift - && modifiers.alt - && keysym.modified_sym() == keysyms::KEY_Escape - { - return FilterResult::Intercept(CallbackId(999999)); - } else if modifiers.ctrl && modifiers.alt { - if let mut vt @ keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 = - keysym.modified_sym() { - vt = vt - keysyms::KEY_XF86Switch_VT_1 + 1; - tracing::info!("Switching to vt {vt}"); - - } - } - } - - if keysym.modified_sym() == keysyms::KEY_Control_L { - match press_state { - KeyState::Pressed => { - move_mode = true; - } - KeyState::Released => { - move_mode = false; - } - } - } - FilterResult::Forward - }, - ); - - self.move_mode = move_mode; - - if let Some(callback_id) = action { - if callback_id.0 == 999999 { - self.loop_signal.stop(); - } - if let Some(stream) = self.api_state.stream.as_ref() { - if let Err(err) = crate::api::send_to_client( - &mut stream.lock().expect("Could not lock stream mutex"), - &OutgoingMsg::CallCallback { - callback_id, - args: None, - }, - ) { - tracing::warn!("error sending msg to client: {err}"); - } - } - } - } - fn pointer_motion_absolute(&mut self, event: I::PointerMotionAbsoluteEvent) { let Some(output) = self.space.outputs().next() else { return; }; let output_geo = self @@ -479,105 +490,6 @@ impl State { } } - fn keyboard(&mut self, event: I::KeyboardKeyEvent) { - let serial = SERIAL_COUNTER.next_serial(); - let time = event.time_msec(); - let press_state = event.state(); - let mut move_mode = false; - let action = self - .seat - .get_keyboard() - .expect("Seat has no keyboard") // FIXME: handle err - .input( - self, - event.key_code(), - press_state, - serial, - time, - |state, modifiers, keysym| { - if press_state == KeyState::Pressed { - let mut modifier_mask = Vec::::new(); - if modifiers.alt { - modifier_mask.push(Modifier::Alt); - } - if modifiers.shift { - modifier_mask.push(Modifier::Shift); - } - if modifiers.ctrl { - modifier_mask.push(Modifier::Ctrl); - } - if modifiers.logo { - modifier_mask.push(Modifier::Super); - } - let raw_sym = if keysym.raw_syms().len() == 1 { - keysym.raw_syms()[0] - } else { - keysyms::KEY_NoSymbol - }; - if let Some(callback_id) = state - .input_state - .keybinds - .get(&(modifier_mask.into(), raw_sym)) - { - return FilterResult::Intercept(*callback_id); - } else if modifiers.ctrl - && modifiers.shift - && modifiers.alt - && keysym.modified_sym() == keysyms::KEY_Escape - { - return FilterResult::Intercept(CallbackId(999999)); - } else if modifiers.ctrl && modifiers.alt { - if let mut vt @ keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 = - keysym.modified_sym() { - vt = vt - keysyms::KEY_XF86Switch_VT_1 + 1; - return FilterResult::Intercept(CallbackId(1000000 + vt)); - } - } - } - - if keysym.modified_sym() == keysyms::KEY_Control_L { - match press_state { - KeyState::Pressed => { - move_mode = true; - } - KeyState::Released => { - move_mode = false; - } - } - } - FilterResult::Forward - }, - ); - - self.move_mode = move_mode; - - if let Some(callback_id) = action { - if callback_id.0 == 999999 { - self.loop_signal.stop(); - return; - } - if callback_id.0 > 1000000 { - let vt = callback_id.0 - 1000000; - tracing::info!("Switching to vt {vt}"); - if let Err(err) = self.backend_data.session.change_vt(vt as i32) { - tracing::error!("Failed to switch to vt {vt}: {err}"); - } - return; - } - if let Some(stream) = self.api_state.stream.as_ref() { - if let Err(err) = crate::api::send_to_client( - &mut stream.lock().expect("Could not lock stream mutex"), - &OutgoingMsg::CallCallback { - callback_id, - args: None, - }, - ) { - tracing::warn!("error sending msg to client: {err}"); - } - } - } - } - fn pointer_motion(&mut self, event: I::PointerMotionEvent) { let serial = SERIAL_COUNTER.next_serial(); self.pointer_location += event.delta(); From bfe4ca937b332341935a92941072132aa56c5ea3 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Tue, 8 Aug 2023 12:50:43 -0500 Subject: [PATCH 3/4] Use enum for actions instead of all callback ids --- src/backend/udev.rs | 10 --------- src/input.rs | 49 ++++++++++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/backend/udev.rs b/src/backend/udev.rs index a741d72..a30d1a8 100644 --- a/src/backend/udev.rs +++ b/src/backend/udev.rs @@ -305,16 +305,6 @@ pub fn run_udev() -> Result<(), Box> { for backend in data.state.backend_data.backends.values_mut() { backend.drm.pause(); - for surface in backend.surfaces.values_mut() { - if let Err(err) = surface.compositor.surface().reset_state() { - tracing::warn!("Failed to reset drm surface state: {}", err); - } - // reset the buffers after resume to trigger a full redraw - // this is important after a vt switch as the primary plane - // has no content and damage tracking may prevent a redraw - // otherwise - surface.compositor.reset_buffers(); - } } } session::Event::ActivateSession => { diff --git a/src/input.rs b/src/input.rs index 15a7071..47fba54 100644 --- a/src/input.rs +++ b/src/input.rs @@ -44,6 +44,13 @@ impl InputState { } } +#[derive(Debug)] +enum KeyAction { + CallCallback(CallbackId), + Quit, + SwitchVt(i32), +} + impl State { pub fn surface_under

(&self, point: P) -> Option<(FocusTarget, Point)> where @@ -130,18 +137,18 @@ impl State { .keybinds .get(&(modifier_mask.into(), raw_sym)) { - return FilterResult::Intercept(*callback_id); + return FilterResult::Intercept(KeyAction::CallCallback(*callback_id)); } else if modifiers.ctrl && modifiers.shift && modifiers.alt && keysym.modified_sym() == keysyms::KEY_Escape { - return FilterResult::Intercept(CallbackId(999999)); + return FilterResult::Intercept(KeyAction::Quit); } else if let mut vt @ keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 = keysym.modified_sym() { vt = vt - keysyms::KEY_XF86Switch_VT_1 + 1; tracing::info!("Switching to vt {vt}"); - return FilterResult::Intercept(CallbackId(1000000 + vt)); + return FilterResult::Intercept(KeyAction::SwitchVt(vt as i32)); } } @@ -162,32 +169,32 @@ impl State { self.move_mode = move_mode; - if let Some(callback_id) = action { - if callback_id.0 == 999999 { - self.loop_signal.stop(); - return; + match action { + Some(KeyAction::CallCallback(callback_id)) => { + if let Some(stream) = self.api_state.stream.as_ref() { + if let Err(err) = crate::api::send_to_client( + &mut stream.lock().expect("Could not lock stream mutex"), + &OutgoingMsg::CallCallback { + callback_id, + args: None, + }, + ) { + tracing::error!("error sending msg to client: {err}"); + } + } } - if callback_id.0 > 1000000 { - let vt = callback_id.0 - 1000000; + Some(KeyAction::SwitchVt(vt)) => { if let Some(st) = (self as &mut dyn std::any::Any).downcast_mut::>() { - if let Err(err) = st.backend_data.session.change_vt(vt as i32) { + if let Err(err) = st.backend_data.session.change_vt(vt) { tracing::error!("Failed to switch to vt {vt}: {err}"); } } - return; } - if let Some(stream) = self.api_state.stream.as_ref() { - if let Err(err) = crate::api::send_to_client( - &mut stream.lock().expect("Could not lock stream mutex"), - &OutgoingMsg::CallCallback { - callback_id, - args: None, - }, - ) { - tracing::warn!("error sending msg to client: {err}"); - } + Some(KeyAction::Quit) => { + self.loop_signal.stop(); } + _ => {} } } From 858e6c21ce06dba488d6710e402a95ac9bcb7c91 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Tue, 8 Aug 2023 12:53:04 -0500 Subject: [PATCH 4/4] Update README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f3c20a8..acfe6e1 100644 --- a/README.md +++ b/README.md @@ -59,14 +59,14 @@ So, this is my attempt at making an Awesome-esque Wayland compositor. ## Dependencies You'll need the following packages, as specified by [Smithay](https://github.com/Smithay/smithay): -`libwayland libxkbcommon libudev libinput libgdm libseat` +`libwayland libxkbcommon libudev libinput libgdm libseat`, as well as `xwayland`. - Arch: ``` - sudo pacman -S wayland wayland-protocols libxkbcommon systemd-libs libinput mesa seatd + sudo pacman -S wayland wayland-protocols libxkbcommon systemd-libs libinput mesa seatda xwayland ``` - Debian: ``` - sudo apt install libwayland-dev libxkbcommon-dev libudev-dev libinput-dev libgdm-dev libseat-dev + sudo apt install libwayland-dev libxkbcommon-dev libudev-dev libinput-dev libgdm-dev libseat-dev xwayland ``` - NixOS: Use the provided [`shell.nix`](shell.nix). - TODO: other distros.