Working MVP for setting keybinds through the api

This commit is contained in:
Seaotatop 2023-06-15 16:43:33 -05:00
parent 2b40019045
commit da783fcf7f
7 changed files with 236 additions and 9 deletions

View file

@ -9,7 +9,7 @@ edition = "2021"
pinnacle_api = { path = "../pinnacle_api" }
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
smithay = { git = "https://github.com/Smithay/smithay" }
smithay = { git = "https://github.com/Smithay/smithay", rev = "9b3d173" }
smithay-drm-extras = { git = "https://github.com/Smithay/smithay", optional = true }
thiserror = "1.0.40"
xcursor = {version = "0.3.4", optional = true }

View file

@ -1,3 +1,6 @@
use std::collections::HashMap;
use pinnacle_api::message::{ModifierMask, Modifiers};
use smithay::{
backend::input::{
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent,
@ -18,6 +21,10 @@ use crate::{
state::State,
};
pub struct InputState {
pub keybinds: HashMap<(ModifierMask, u32), u32>,
}
impl<B: Backend> State<B> {
pub fn surface_under<P>(&self, point: P) -> Option<(Window, Point<i32, Logical>)>
where
@ -189,8 +196,28 @@ impl<B: Backend> State<B> {
press_state,
serial,
time,
|state, _modifiers, keysym| {
|state, modifiers, keysym| {
if press_state == KeyState::Pressed {
let mut modifier_mask = Vec::<Modifiers>::new();
if modifiers.alt {
modifier_mask.push(Modifiers::Alt);
}
if modifiers.shift {
modifier_mask.push(Modifiers::Shift);
}
if modifiers.ctrl {
modifier_mask.push(Modifiers::Ctrl);
}
if modifiers.logo {
modifier_mask.push(Modifiers::Super);
}
if let Some(callback_id) = state
.input_state
.keybinds
.get(&(modifier_mask.into(), keysym.modified_sym()))
{
return FilterResult::Intercept(1);
}
match keysym.modified_sym() {
keysyms::KEY_L => return FilterResult::Intercept(1),
keysyms::KEY_K => return FilterResult::Intercept(2),

View file

@ -13,7 +13,7 @@ mod xdg;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
pinnacle_api::run()?;
// pinnacle_api::run()?;
match tracing_subscriber::EnvFilter::try_from_default_env() {
Ok(env_filter) => {

View file

@ -1,5 +1,6 @@
use std::{error::Error, os::fd::AsRawFd, sync::Arc};
use std::{collections::HashMap, error::Error, os::fd::AsRawFd, sync::Arc};
use pinnacle_api::{message::Msg, PinnacleSocketSource, PinnacleStreamSource};
use smithay::{
backend::renderer::element::RenderElementStates,
desktop::{
@ -34,7 +35,7 @@ use smithay::{
},
};
use crate::backend::Backend;
use crate::{backend::Backend, input::InputState};
pub struct State<B: Backend> {
pub backend_data: B,
@ -57,6 +58,7 @@ pub struct State<B: Backend> {
pub xdg_shell_state: XdgShellState,
pub viewporter_state: ViewporterState,
pub fractional_scale_manager_state: FractionalScaleManagerState,
pub input_state: InputState,
pub popup_manager: PopupManager,
@ -95,6 +97,29 @@ impl<B: Backend> State<B> {
},
)?;
loop_handle.insert_source(PinnacleSocketSource::new()?, |stream, _, data| {
data.state
.loop_handle
.insert_source(PinnacleStreamSource::new(stream), |msg, _, data| {
// TODO: do stuff with msg
match msg {
Msg::SetKeybind {
key,
modifiers,
callback_id,
} => {
tracing::info!("set keybind: {:?}, {}", modifiers, key);
data.state
.input_state
.keybinds
.insert((modifiers.into(), key), callback_id);
}
Msg::SetMousebind { button } => todo!(),
};
})
.unwrap();
})?;
let display_handle = display.handle();
let mut seat_state = SeatState::new();
let mut seat = seat_state.new_wl_seat(&display_handle, backend_data.seat_name());
@ -119,6 +144,9 @@ impl<B: Backend> State<B> {
fractional_scale_manager_state: FractionalScaleManagerState::new::<Self>(
&display_handle,
),
input_state: InputState {
keybinds: HashMap::new(),
},
seat,
@ -136,6 +164,17 @@ impl<B: Backend> State<B> {
.find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false))
.cloned()
}
pub fn handle_msg(msg: Msg) {
match msg {
Msg::SetKeybind {
key,
modifiers,
callback_id,
} => todo!(),
Msg::SetMousebind { button } => todo!(),
}
}
}
pub struct CalloopData<B: Backend> {

View file

@ -12,3 +12,4 @@ serde = { version = "1.0.164", features = ["derive"] }
serde_json = { version = "1.0.96" }
rmp-serde = { version = "1.1.1" }
xkbcommon = { version = "0.5.0" }
smithay = { git = "https://github.com/Smithay/smithay", rev = "9b3d173" }

View file

@ -1,9 +1,14 @@
use std::{
error::Error,
io,
os::unix::net::{UnixListener, UnixStream},
path::Path,
};
use smithay::reexports::calloop::{
self, generic::Generic, EventSource, Interest, Mode, PostAction,
};
use crate::message::Msg;
pub mod message;
@ -42,3 +47,143 @@ fn handle_client(stream: UnixStream) {
println!("{:?}", msg);
}
}
pub struct PinnacleSocketSource {
socket: Generic<UnixListener>,
}
impl PinnacleSocketSource {
pub fn new() -> Result<Self, io::Error> {
let socket_path = Path::new(SOCKET_PATH);
if socket_path.exists() {
std::fs::remove_file(socket_path)?;
}
let listener = UnixListener::bind(SOCKET_PATH)?;
let socket = Generic::new(listener, Interest::READ, Mode::Level);
Ok(Self { socket })
}
}
impl EventSource for PinnacleSocketSource {
type Event = UnixStream;
type Metadata = ();
type Ret = ();
type Error = io::Error;
fn process_events<F>(
&mut self,
readiness: calloop::Readiness,
token: calloop::Token,
mut callback: F,
) -> Result<calloop::PostAction, Self::Error>
where
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
{
self.socket
.process_events(readiness, token, |_readiness, listener| {
listener.set_nonblocking(true)?;
while let Ok((stream, _sock_addr)) = listener.accept() {
stream.set_nonblocking(true)?;
callback(stream, &mut ());
}
Ok(PostAction::Continue)
})
}
fn register(
&mut self,
poll: &mut calloop::Poll,
token_factory: &mut calloop::TokenFactory,
) -> calloop::Result<()> {
self.socket.register(poll, token_factory)
}
fn reregister(
&mut self,
poll: &mut calloop::Poll,
token_factory: &mut calloop::TokenFactory,
) -> calloop::Result<()> {
self.socket.reregister(poll, token_factory)
}
fn unregister(&mut self, poll: &mut calloop::Poll) -> calloop::Result<()> {
self.socket.unregister(poll)
}
}
pub struct PinnacleStreamSource {
stream: Generic<UnixStream>,
}
impl PinnacleStreamSource {
pub fn new(stream: UnixStream) -> Self {
Self {
stream: Generic::new(stream, Interest::READ, Mode::Level),
}
}
}
impl EventSource for PinnacleStreamSource {
type Event = Msg;
type Metadata = ();
type Ret = ();
type Error = io::Error;
fn process_events<F>(
&mut self,
readiness: calloop::Readiness,
token: calloop::Token,
mut callback: F,
) -> Result<PostAction, Self::Error>
where
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
{
self.stream
.process_events(readiness, token, |_readiness, stream| {
match rmp_serde::from_read(stream as &UnixStream) {
Ok(msg) => callback(msg, &mut ()),
Err(rmp_serde::decode::Error::InvalidMarkerRead(err))
if err.kind() == io::ErrorKind::UnexpectedEof =>
{
stream.shutdown(std::net::Shutdown::Both)?;
println!("Stream closed: {:?}", err);
return Ok(PostAction::Remove);
}
Err(err) => println!("{:?}", err),
}
Ok(PostAction::Continue)
})
}
fn register(
&mut self,
poll: &mut calloop::Poll,
token_factory: &mut calloop::TokenFactory,
) -> calloop::Result<()> {
self.stream.register(poll, token_factory)
}
fn reregister(
&mut self,
poll: &mut calloop::Poll,
token_factory: &mut calloop::TokenFactory,
) -> calloop::Result<()> {
self.stream.reregister(poll, token_factory)
}
fn unregister(&mut self, poll: &mut calloop::Poll) -> calloop::Result<()> {
self.stream.unregister(poll)
}
}

View file

@ -21,8 +21,23 @@ pub enum Action {
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub enum Modifiers {
Shift,
Ctrl,
Alt,
Super,
Shift = 0b0000_0001,
Ctrl = 0b0000_0010,
Alt = 0b0000_0100,
Super = 0b0000_1000,
}
/// A bitmask of [Modifiers] for the purpose of hashing.
#[derive(PartialEq, Eq, Hash)]
pub struct ModifierMask(u8);
impl<T: IntoIterator<Item = Modifiers>> From<T> for ModifierMask {
fn from(value: T) -> Self {
let value = value.into_iter();
let mut mask: u8 = 0b0000_0000;
for modifier in value {
mask |= modifier as u8;
}
Self(mask)
}
}