mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-30 20:34:49 +01:00
Add unwrap warning, deal with some unwraps
This commit is contained in:
parent
d6504b0b82
commit
2b50e7d31a
11 changed files with 210 additions and 140 deletions
27
src/api.rs
27
src/api.rs
|
@ -54,14 +54,17 @@ use self::msg::{Msg, OutgoingMsg};
|
||||||
|
|
||||||
const SOCKET_PATH: &str = "/tmp/pinnacle_socket";
|
const SOCKET_PATH: &str = "/tmp/pinnacle_socket";
|
||||||
|
|
||||||
fn handle_client(mut stream: UnixStream, sender: Sender<Msg>) {
|
fn handle_client(
|
||||||
|
mut stream: UnixStream,
|
||||||
|
sender: Sender<Msg>,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
loop {
|
loop {
|
||||||
let mut len_marker_bytes = [0u8; 4];
|
let mut len_marker_bytes = [0u8; 4];
|
||||||
if let Err(err) = stream.read_exact(&mut len_marker_bytes) {
|
if let Err(err) = stream.read_exact(&mut len_marker_bytes) {
|
||||||
if err.kind() == io::ErrorKind::UnexpectedEof {
|
if err.kind() == io::ErrorKind::UnexpectedEof {
|
||||||
tracing::warn!("stream closed: {}", err);
|
tracing::warn!("stream closed: {}", err);
|
||||||
stream.shutdown(std::net::Shutdown::Both).unwrap();
|
stream.shutdown(std::net::Shutdown::Both)?;
|
||||||
break;
|
break Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,15 +74,14 @@ fn handle_client(mut stream: UnixStream, sender: Sender<Msg>) {
|
||||||
if let Err(err) = stream.read_exact(msg_bytes.as_mut_slice()) {
|
if let Err(err) = stream.read_exact(msg_bytes.as_mut_slice()) {
|
||||||
if err.kind() == io::ErrorKind::UnexpectedEof {
|
if err.kind() == io::ErrorKind::UnexpectedEof {
|
||||||
tracing::warn!("stream closed: {}", err);
|
tracing::warn!("stream closed: {}", err);
|
||||||
stream.shutdown(std::net::Shutdown::Both).unwrap();
|
stream.shutdown(std::net::Shutdown::Both)?;
|
||||||
break;
|
break Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let msg: Msg = rmp_serde::from_slice(msg_bytes.as_slice()).unwrap(); // TODO: handle error
|
let msg: Msg = rmp_serde::from_slice(msg_bytes.as_slice())?; // TODO: handle error
|
||||||
|
|
||||||
sender.send(msg).unwrap();
|
sender.send(msg)?;
|
||||||
}
|
}
|
||||||
tracing::info!("end of handle_client");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PinnacleSocketSource {
|
pub struct PinnacleSocketSource {
|
||||||
|
@ -151,10 +153,15 @@ impl EventSource for PinnacleSocketSource {
|
||||||
.process_events(readiness, token, |_readiness, listener| {
|
.process_events(readiness, token, |_readiness, listener| {
|
||||||
while let Ok((stream, _sock_addr)) = listener.accept() {
|
while let Ok((stream, _sock_addr)) = listener.accept() {
|
||||||
let sender = self.sender.clone();
|
let sender = self.sender.clone();
|
||||||
let callback_stream = stream.try_clone().unwrap(); // TODO: error
|
let callback_stream = match stream.try_clone() {
|
||||||
|
Ok(callback_stream) => callback_stream,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
};
|
||||||
callback(callback_stream, &mut ());
|
callback(callback_stream, &mut ());
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
handle_client(stream, sender);
|
if let Err(err) = handle_client(stream, sender) {
|
||||||
|
tracing::error!("handle_client errored: {err}");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,14 +52,6 @@ pub enum Msg {
|
||||||
callback_id: Option<CallbackId>,
|
callback_id: Option<CallbackId>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Run a command using the optionally specified shell and callback.
|
|
||||||
SpawnShell {
|
|
||||||
shell: Option<String>,
|
|
||||||
command: Vec<String>,
|
|
||||||
#[serde(default)]
|
|
||||||
callback_id: Option<CallbackId>,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Pinnacle management
|
// Pinnacle management
|
||||||
/// Quit the compositor.
|
/// Quit the compositor.
|
||||||
Quit,
|
Quit,
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
// from anvil
|
// from anvil
|
||||||
// TODO: figure out what this stuff does
|
// TODO: figure out what this stuff does
|
||||||
|
|
||||||
|
#![allow(clippy::unwrap_used)] // I don't know what this stuff does yet
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
error::Error,
|
error::Error,
|
||||||
|
|
|
@ -142,7 +142,7 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let dmabuf_default_feedback = DmabufFeedbackBuilder::new(node.dev_id(), dmabuf_formats)
|
let dmabuf_default_feedback = DmabufFeedbackBuilder::new(node.dev_id(), dmabuf_formats)
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.expect("DmabufFeedbackBuilder error");
|
||||||
Some(dmabuf_default_feedback)
|
Some(dmabuf_default_feedback)
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
|
@ -260,9 +260,9 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
||||||
states
|
states
|
||||||
.data_map
|
.data_map
|
||||||
.get::<Mutex<CursorImageAttributes>>()
|
.get::<Mutex<CursorImageAttributes>>()
|
||||||
.unwrap()
|
.expect("Mutex<CursorImageAttributes> wasn't in the data map")
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.expect("Failed to lock Mutex<CursorImageAttributes>")
|
||||||
.hotspot
|
.hotspot
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -291,7 +291,8 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
// render_output()
|
// render_output()
|
||||||
let space_render_elements =
|
let space_render_elements =
|
||||||
space::space_render_elements(renderer, [&state.space], &output, 1.0).unwrap();
|
space::space_render_elements(renderer, [&state.space], &output, 1.0)
|
||||||
|
.expect("Failed to get render elements");
|
||||||
|
|
||||||
let mut output_render_elements = Vec::<
|
let mut output_render_elements = Vec::<
|
||||||
OutputRenderElements<GlesRenderer, WaylandSurfaceRenderElement<GlesRenderer>>,
|
OutputRenderElements<GlesRenderer, WaylandSurfaceRenderElement<GlesRenderer>>,
|
||||||
|
|
|
@ -77,7 +77,9 @@ impl<B: Backend> CompositorHandler for State<B> {
|
||||||
});
|
});
|
||||||
if let Some(dmabuf) = maybe_dmabuf {
|
if let Some(dmabuf) = maybe_dmabuf {
|
||||||
if let Ok((blocker, source)) = dmabuf.generate_blocker(Interest::READ) {
|
if let Ok((blocker, source)) = dmabuf.generate_blocker(Interest::READ) {
|
||||||
let client = surface.client().unwrap();
|
let client = surface
|
||||||
|
.client()
|
||||||
|
.expect("Surface has no client/is no longer alive");
|
||||||
let res = state.loop_handle.insert_source(source, move |_, _, data| {
|
let res = state.loop_handle.insert_source(source, move |_, _, data| {
|
||||||
data.state
|
data.state
|
||||||
.client_compositor_state(&client)
|
.client_compositor_state(&client)
|
||||||
|
@ -124,7 +126,10 @@ impl<B: Backend> CompositorHandler for State<B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
|
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
|
||||||
&client.get_data::<ClientState>().unwrap().compositor_state
|
&client
|
||||||
|
.get_data::<ClientState>()
|
||||||
|
.expect("ClientState wasn't in client's data map")
|
||||||
|
.compositor_state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delegate_compositor!(@<B: Backend> State<B>);
|
delegate_compositor!(@<B: Backend> State<B>);
|
||||||
|
@ -135,9 +140,9 @@ fn ensure_initial_configure<B: Backend>(surface: &WlSurface, state: &mut State<B
|
||||||
states
|
states
|
||||||
.data_map
|
.data_map
|
||||||
.get::<XdgToplevelSurfaceData>()
|
.get::<XdgToplevelSurfaceData>()
|
||||||
.unwrap()
|
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
|
||||||
.initial_configure_sent
|
.initial_configure_sent
|
||||||
});
|
});
|
||||||
// println!("initial_configure_sent is {}", initial_configure_sent);
|
// println!("initial_configure_sent is {}", initial_configure_sent);
|
||||||
|
@ -155,9 +160,9 @@ fn ensure_initial_configure<B: Backend>(surface: &WlSurface, state: &mut State<B
|
||||||
states
|
states
|
||||||
.data_map
|
.data_map
|
||||||
.get::<XdgPopupSurfaceData>()
|
.get::<XdgPopupSurfaceData>()
|
||||||
.unwrap()
|
.expect("XdgPopupSurfaceData wasn't in popup's data map")
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.expect("Failed to lock Mutex<XdgPopupSurfaceData>")
|
||||||
.initial_configure_sent
|
.initial_configure_sent
|
||||||
});
|
});
|
||||||
if !initial_configure_sent {
|
if !initial_configure_sent {
|
||||||
|
@ -221,11 +226,15 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
||||||
|
|
||||||
self.space.map_element(window.clone(), (0, 0), true);
|
self.space.map_element(window.clone(), (0, 0), true);
|
||||||
self.loop_handle.insert_idle(move |data| {
|
self.loop_handle.insert_idle(move |data| {
|
||||||
data.state.seat.get_keyboard().unwrap().set_focus(
|
data.state
|
||||||
&mut data.state,
|
.seat
|
||||||
Some(window.toplevel().wl_surface().clone()),
|
.get_keyboard()
|
||||||
SERIAL_COUNTER.next_serial(),
|
.expect("Seat had no keyboard") // FIXME: actually handle error
|
||||||
);
|
.set_focus(
|
||||||
|
&mut data.state,
|
||||||
|
Some(window.toplevel().wl_surface().clone()),
|
||||||
|
SERIAL_COUNTER.next_serial(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
let windows: Vec<Window> = self.space.elements().cloned().collect();
|
let windows: Vec<Window> = self.space.elements().cloned().collect();
|
||||||
|
|
||||||
|
@ -245,11 +254,11 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
||||||
.map(|win| win.toplevel().wl_surface().clone());
|
.map(|win| win.toplevel().wl_surface().clone());
|
||||||
self.seat
|
self.seat
|
||||||
.get_keyboard()
|
.get_keyboard()
|
||||||
.unwrap()
|
.expect("Seat had no keyboard")
|
||||||
.set_focus(self, focus, SERIAL_COUNTER.next_serial());
|
.set_focus(self, focus, SERIAL_COUNTER.next_serial());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_popup(&mut self, surface: PopupSurface, positioner: PositionerState) {
|
fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) {
|
||||||
if let Err(err) = self.popup_manager.track_popup(PopupKind::from(surface)) {
|
if let Err(err) = self.popup_manager.track_popup(PopupKind::from(surface)) {
|
||||||
tracing::warn!("failed to track popup: {}", err);
|
tracing::warn!("failed to track popup: {}", err);
|
||||||
}
|
}
|
||||||
|
@ -259,7 +268,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
||||||
crate::xdg::request::move_request(
|
crate::xdg::request::move_request(
|
||||||
self,
|
self,
|
||||||
&surface,
|
&surface,
|
||||||
&Seat::from_resource(&seat).unwrap(),
|
&Seat::from_resource(&seat).expect("Couldn't get seat from WlSeat"),
|
||||||
serial,
|
serial,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -275,7 +284,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
||||||
crate::xdg::request::resize_request(
|
crate::xdg::request::resize_request(
|
||||||
self,
|
self,
|
||||||
&surface,
|
&surface,
|
||||||
&Seat::from_resource(&seat).unwrap(),
|
&Seat::from_resource(&seat).expect("Couldn't get seat from WlSeat"),
|
||||||
serial,
|
serial,
|
||||||
edges,
|
edges,
|
||||||
BUTTON_LEFT,
|
BUTTON_LEFT,
|
||||||
|
@ -296,7 +305,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn grab(&mut self, surface: PopupSurface, seat: WlSeat, serial: Serial) {
|
fn grab(&mut self, surface: PopupSurface, seat: WlSeat, serial: Serial) {
|
||||||
let seat: Seat<Self> = Seat::from_resource(&seat).unwrap();
|
let seat: Seat<Self> = Seat::from_resource(&seat).expect("Couldn't get seat from WlSeat");
|
||||||
let popup_kind = PopupKind::Xdg(surface);
|
let popup_kind = PopupKind::Xdg(surface);
|
||||||
if let Some(root) = find_popup_root_surface(&popup_kind)
|
if let Some(root) = find_popup_root_surface(&popup_kind)
|
||||||
.ok()
|
.ok()
|
||||||
|
|
155
src/input.rs
155
src/input.rs
|
@ -53,8 +53,8 @@ impl<B: Backend> State<B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pointer_button<I: InputBackend>(&mut self, event: I::PointerButtonEvent) {
|
fn pointer_button<I: InputBackend>(&mut self, event: I::PointerButtonEvent) {
|
||||||
let pointer = self.seat.get_pointer().unwrap();
|
let pointer = self.seat.get_pointer().expect("Seat has no pointer"); // FIXME: handle err
|
||||||
let keyboard = self.seat.get_keyboard().unwrap();
|
let keyboard = self.seat.get_keyboard().expect("Seat has no keyboard"); // FIXME: handle err
|
||||||
|
|
||||||
// A serial is a number sent with a event that is sent back to the
|
// A serial is a number sent with a event that is sent back to the
|
||||||
// server by the clients in further requests. This allows the server to
|
// server by the clients in further requests. This allows the server to
|
||||||
|
@ -198,7 +198,10 @@ impl<B: Backend> State<B> {
|
||||||
frame = frame.stop(Axis::Vertical);
|
frame = frame.stop(Axis::Vertical);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.seat.get_pointer().unwrap().axis(self, frame);
|
self.seat
|
||||||
|
.get_pointer()
|
||||||
|
.expect("Seat has no pointer")
|
||||||
|
.axis(self, frame); // FIXME: handle err
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyboard<I: InputBackend>(&mut self, event: I::KeyboardKeyEvent) {
|
fn keyboard<I: InputBackend>(&mut self, event: I::KeyboardKeyEvent) {
|
||||||
|
@ -206,58 +209,62 @@ impl<B: Backend> State<B> {
|
||||||
let time = event.time_msec();
|
let time = event.time_msec();
|
||||||
let press_state = event.state();
|
let press_state = event.state();
|
||||||
let mut move_mode = false;
|
let mut move_mode = false;
|
||||||
let action = self.seat.get_keyboard().unwrap().input(
|
let action = self
|
||||||
self,
|
.seat
|
||||||
event.key_code(),
|
.get_keyboard()
|
||||||
press_state,
|
.expect("Seat has no keyboard") // FIXME: handle err
|
||||||
serial,
|
.input(
|
||||||
time,
|
self,
|
||||||
|state, modifiers, keysym| {
|
event.key_code(),
|
||||||
if press_state == KeyState::Pressed {
|
press_state,
|
||||||
let mut modifier_mask = Vec::<Modifiers>::new();
|
serial,
|
||||||
if modifiers.alt {
|
time,
|
||||||
modifier_mask.push(Modifiers::Alt);
|
|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(*callback_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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(*callback_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if keysym.modified_sym() == keysyms::KEY_Control_L {
|
if keysym.modified_sym() == keysyms::KEY_Control_L {
|
||||||
match press_state {
|
match press_state {
|
||||||
KeyState::Pressed => {
|
KeyState::Pressed => {
|
||||||
move_mode = true;
|
move_mode = true;
|
||||||
}
|
}
|
||||||
KeyState::Released => {
|
KeyState::Released => {
|
||||||
move_mode = false;
|
move_mode = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
FilterResult::Forward
|
||||||
|
} else {
|
||||||
|
FilterResult::Forward
|
||||||
}
|
}
|
||||||
FilterResult::Forward
|
},
|
||||||
} else {
|
);
|
||||||
FilterResult::Forward
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
self.move_mode = move_mode;
|
self.move_mode = move_mode;
|
||||||
|
|
||||||
if let Some(callback_id) = action {
|
if let Some(callback_id) = action {
|
||||||
if let Some(stream) = self.api_state.stream.as_ref() {
|
if let Some(stream) = self.api_state.stream.as_ref() {
|
||||||
if let Err(err) = crate::api::send_to_client(
|
if let Err(err) = crate::api::send_to_client(
|
||||||
&mut stream.lock().unwrap(),
|
&mut stream.lock().expect("Could not lock stream mutex"),
|
||||||
&OutgoingMsg::CallCallback {
|
&OutgoingMsg::CallCallback {
|
||||||
callback_id,
|
callback_id,
|
||||||
args: None,
|
args: None,
|
||||||
|
@ -288,11 +295,14 @@ impl State<WinitData> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pointer_motion_absolute<I: InputBackend>(&mut self, event: I::PointerMotionAbsoluteEvent) {
|
fn pointer_motion_absolute<I: InputBackend>(&mut self, event: I::PointerMotionAbsoluteEvent) {
|
||||||
let output = self.space.outputs().next().unwrap();
|
let Some(output) = self.space.outputs().next() else { return; };
|
||||||
let output_geo = self.space.output_geometry(output).unwrap();
|
let output_geo = self
|
||||||
|
.space
|
||||||
|
.output_geometry(output)
|
||||||
|
.expect("Output geometry doesn't exist");
|
||||||
let pointer_loc = event.position_transformed(output_geo.size) + output_geo.loc.to_f64();
|
let pointer_loc = event.position_transformed(output_geo.size) + output_geo.loc.to_f64();
|
||||||
let serial = SERIAL_COUNTER.next_serial();
|
let serial = SERIAL_COUNTER.next_serial();
|
||||||
let pointer = self.seat.get_pointer().unwrap();
|
let pointer = self.seat.get_pointer().expect("Seat has no pointer"); // FIXME: handle err
|
||||||
|
|
||||||
// tracing::info!("pointer_loc: {:?}", pointer_loc);
|
// tracing::info!("pointer_loc: {:?}", pointer_loc);
|
||||||
|
|
||||||
|
@ -407,16 +417,35 @@ impl State<UdevData> {
|
||||||
let serial = SERIAL_COUNTER.next_serial();
|
let serial = SERIAL_COUNTER.next_serial();
|
||||||
|
|
||||||
let max_x = self.space.outputs().fold(0, |acc, o| {
|
let max_x = self.space.outputs().fold(0, |acc, o| {
|
||||||
acc + self.space.output_geometry(o).unwrap().size.w
|
acc + self
|
||||||
|
.space
|
||||||
|
.output_geometry(o)
|
||||||
|
.expect("Output geometry doesn't exist")
|
||||||
|
.size
|
||||||
|
.w
|
||||||
});
|
});
|
||||||
|
|
||||||
let max_h_output = self
|
let Some(max_h_output) = self
|
||||||
.space
|
.space
|
||||||
.outputs()
|
.outputs()
|
||||||
.max_by_key(|o| self.space.output_geometry(o).unwrap().size.h)
|
.max_by_key(|o| {
|
||||||
.unwrap();
|
self.space
|
||||||
|
.output_geometry(o)
|
||||||
|
.expect("Output geometry doesn't exist")
|
||||||
|
.size
|
||||||
|
.h
|
||||||
|
})
|
||||||
|
else {
|
||||||
|
tracing::warn!("Pointer moved, but there was no output");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let max_y = self.space.output_geometry(max_h_output).unwrap().size.h;
|
let max_y = self
|
||||||
|
.space
|
||||||
|
.output_geometry(max_h_output)
|
||||||
|
.expect("Output geometry doesn't exist")
|
||||||
|
.size
|
||||||
|
.h;
|
||||||
|
|
||||||
self.pointer_location.x = event.x_transformed(max_x);
|
self.pointer_location.x = event.x_transformed(max_x);
|
||||||
self.pointer_location.y = event.y_transformed(max_y);
|
self.pointer_location.y = event.y_transformed(max_y);
|
||||||
|
@ -447,17 +476,31 @@ impl State<UdevData> {
|
||||||
|
|
||||||
let (pos_x, pos_y) = pos.into();
|
let (pos_x, pos_y) = pos.into();
|
||||||
let max_x = self.space.outputs().fold(0, |acc, o| {
|
let max_x = self.space.outputs().fold(0, |acc, o| {
|
||||||
acc + self.space.output_geometry(o).unwrap().size.w
|
acc + self
|
||||||
|
.space
|
||||||
|
.output_geometry(o)
|
||||||
|
.expect("Output geometry doesn't exist")
|
||||||
|
.size
|
||||||
|
.w
|
||||||
});
|
});
|
||||||
let clamped_x = pos_x.clamp(0.0, max_x as f64);
|
let clamped_x = pos_x.clamp(0.0, max_x as f64);
|
||||||
let max_y = self
|
let max_y = self
|
||||||
.space
|
.space
|
||||||
.outputs()
|
.outputs()
|
||||||
.find(|o| {
|
.find(|o| {
|
||||||
let geo = self.space.output_geometry(o).unwrap();
|
let geo = self
|
||||||
|
.space
|
||||||
|
.output_geometry(o)
|
||||||
|
.expect("Output geometry doesn't exist");
|
||||||
geo.contains((clamped_x as i32, 0))
|
geo.contains((clamped_x as i32, 0))
|
||||||
})
|
})
|
||||||
.map(|o| self.space.output_geometry(o).unwrap().size.h);
|
.map(|o| {
|
||||||
|
self.space
|
||||||
|
.output_geometry(o)
|
||||||
|
.expect("Output geometry doesn't exist")
|
||||||
|
.size
|
||||||
|
.h
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(max_y) = max_y {
|
if let Some(max_y) = max_y {
|
||||||
let clamped_y = pos_y.clamp(0.0, max_y as f64);
|
let clamped_y = pos_y.clamp(0.0, max_y as f64);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
//! contribute or learn how building something like this works.
|
//! contribute or learn how building something like this works.
|
||||||
|
|
||||||
#![deny(unused_imports)] // gonna force myself to keep stuff clean
|
#![deny(unused_imports)] // gonna force myself to keep stuff clean
|
||||||
|
#![warn(clippy::unwrap_used)]
|
||||||
|
|
||||||
mod api;
|
mod api;
|
||||||
mod backend;
|
mod backend;
|
||||||
|
|
|
@ -24,7 +24,10 @@ impl OutputState {
|
||||||
.user_data()
|
.user_data()
|
||||||
.insert_if_missing(|| RefCell::<Self>::default);
|
.insert_if_missing(|| RefCell::<Self>::default);
|
||||||
|
|
||||||
let state = output.user_data().get::<RefCell<Self>>().unwrap();
|
let state = output
|
||||||
|
.user_data()
|
||||||
|
.get::<RefCell<Self>>()
|
||||||
|
.expect("RefCell doesn't exist in data map (This should NEVER happen. If you see this, something oofed big-time.)");
|
||||||
|
|
||||||
func(&mut state.borrow_mut())
|
func(&mut state.borrow_mut())
|
||||||
}
|
}
|
||||||
|
|
96
src/state.rs
96
src/state.rs
|
@ -115,18 +115,19 @@ impl<B: Backend> State<B> {
|
||||||
//
|
//
|
||||||
// To fix this, I just set the limit to be higher. As Pinnacle is the whole graphical
|
// To fix this, I just set the limit to be higher. As Pinnacle is the whole graphical
|
||||||
// environment, I *think* this is ok.
|
// environment, I *think* this is ok.
|
||||||
smithay::reexports::nix::sys::resource::setrlimit(
|
if let Err(err) = smithay::reexports::nix::sys::resource::setrlimit(
|
||||||
smithay::reexports::nix::sys::resource::Resource::RLIMIT_NOFILE,
|
smithay::reexports::nix::sys::resource::Resource::RLIMIT_NOFILE,
|
||||||
65536,
|
65536,
|
||||||
65536 * 2,
|
65536 * 2,
|
||||||
)
|
) {
|
||||||
.unwrap();
|
tracing::error!("Could not raise fd limit: errno {err}");
|
||||||
|
}
|
||||||
|
|
||||||
loop_handle.insert_source(socket, |stream, _metadata, data| {
|
loop_handle.insert_source(socket, |stream, _metadata, data| {
|
||||||
data.display
|
data.display
|
||||||
.handle()
|
.handle()
|
||||||
.insert_client(stream, Arc::new(ClientState::default()))
|
.insert_client(stream, Arc::new(ClientState::default()))
|
||||||
.unwrap();
|
.expect("Could not insert client into loop handle");
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
loop_handle.insert_source(
|
loop_handle.insert_source(
|
||||||
|
@ -180,11 +181,6 @@ impl<B: Backend> State<B> {
|
||||||
} => {
|
} => {
|
||||||
data.state.handle_spawn(command, callback_id);
|
data.state.handle_spawn(command, callback_id);
|
||||||
}
|
}
|
||||||
Msg::SpawnShell {
|
|
||||||
shell,
|
|
||||||
command,
|
|
||||||
callback_id,
|
|
||||||
} => todo!(),
|
|
||||||
Msg::MoveToTag { tag } => todo!(),
|
Msg::MoveToTag { tag } => todo!(),
|
||||||
Msg::ToggleTag { tag } => todo!(),
|
Msg::ToggleTag { tag } => todo!(),
|
||||||
|
|
||||||
|
@ -215,9 +211,9 @@ impl<B: Backend> State<B> {
|
||||||
let lock = states.
|
let lock = states.
|
||||||
data_map
|
data_map
|
||||||
.get::<XdgToplevelSurfaceData>()
|
.get::<XdgToplevelSurfaceData>()
|
||||||
.unwrap()
|
.expect("XdgToplevelSurfaceData doesn't exist")
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap();
|
.expect("Couldn't lock XdgToplevelSurfaceData");
|
||||||
(lock.app_id.clone(), lock.title.clone())
|
(lock.app_id.clone(), lock.title.clone())
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -234,8 +230,8 @@ impl<B: Backend> State<B> {
|
||||||
location: location.into(),
|
location: location.into(),
|
||||||
floating,
|
floating,
|
||||||
};
|
};
|
||||||
let stream = data.state.api_state.stream.as_ref().unwrap();
|
let stream = data.state.api_state.stream.as_ref().expect("Stream doesn't exist");
|
||||||
let mut stream = stream.lock().unwrap();
|
let mut stream = stream.lock().expect("Couldn't lock stream");
|
||||||
crate::api::send_to_client(
|
crate::api::send_to_client(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
&OutgoingMsg::RequestResponse {
|
&OutgoingMsg::RequestResponse {
|
||||||
|
@ -243,7 +239,7 @@ impl<B: Backend> State<B> {
|
||||||
response: RequestResponse::Window { window: props }
|
response: RequestResponse::Window { window: props }
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.unwrap();
|
.expect("Send to client failed");
|
||||||
},
|
},
|
||||||
Request::GetAllWindows { id } => {
|
Request::GetAllWindows { id } => {
|
||||||
let window_props = data.state.space.elements().map(|win| {
|
let window_props = data.state.space.elements().map(|win| {
|
||||||
|
@ -254,9 +250,9 @@ impl<B: Backend> State<B> {
|
||||||
let lock = states.
|
let lock = states.
|
||||||
data_map
|
data_map
|
||||||
.get::<XdgToplevelSurfaceData>()
|
.get::<XdgToplevelSurfaceData>()
|
||||||
.unwrap()
|
.expect("XdgToplevelSurfaceData doesn't exist")
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap();
|
.expect("Couldn't lock XdgToplevelSurfaceData");
|
||||||
(lock.app_id.clone(), lock.title.clone())
|
(lock.app_id.clone(), lock.title.clone())
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -264,7 +260,7 @@ impl<B: Backend> State<B> {
|
||||||
(state.id, state.floating.is_floating())
|
(state.id, state.floating.is_floating())
|
||||||
});
|
});
|
||||||
// TODO: unwrap
|
// TODO: unwrap
|
||||||
let location = data.state.space.element_location(win).unwrap();
|
let location = data.state.space.element_location(win).expect("Window location doesn't exist");
|
||||||
WindowProperties {
|
WindowProperties {
|
||||||
id: window_id,
|
id: window_id,
|
||||||
app_id,
|
app_id,
|
||||||
|
@ -275,8 +271,9 @@ impl<B: Backend> State<B> {
|
||||||
}
|
}
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
let stream = data.state.api_state.stream.as_ref().unwrap();
|
// FIXME: figure out what to do if error
|
||||||
let mut stream = stream.lock().unwrap();
|
let stream = data.state.api_state.stream.as_ref().expect("Stream doesn't exist");
|
||||||
|
let mut stream = stream.lock().expect("Couldn't lock stream");
|
||||||
crate::api::send_to_client(
|
crate::api::send_to_client(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
&OutgoingMsg::RequestResponse {
|
&OutgoingMsg::RequestResponse {
|
||||||
|
@ -284,7 +281,7 @@ impl<B: Backend> State<B> {
|
||||||
response: RequestResponse::GetAllWindows { windows: window_props },
|
response: RequestResponse::GetAllWindows { windows: window_props },
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.unwrap();
|
.expect("Couldn't send to client");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -305,13 +302,13 @@ impl<B: Backend> State<B> {
|
||||||
{
|
{
|
||||||
old_stream
|
old_stream
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.expect("Couldn't lock old stream")
|
||||||
.shutdown(std::net::Shutdown::Both)
|
.shutdown(std::net::Shutdown::Both)
|
||||||
.unwrap();
|
.expect("Couldn't shutdown old stream");
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let (executor, sched) = calloop::futures::executor::<()>().unwrap();
|
let (executor, sched) = calloop::futures::executor::<()>().expect("Couldn't create executor");
|
||||||
loop_handle.insert_source(executor, |_, _, _| {})?;
|
loop_handle.insert_source(executor, |_, _, _| {})?;
|
||||||
|
|
||||||
// TODO: move all this into the lua api
|
// TODO: move all this into the lua api
|
||||||
|
@ -324,7 +321,7 @@ impl<B: Backend> State<B> {
|
||||||
|
|
||||||
let lua_path = std::env::var("LUA_PATH").expect("Lua is not installed!");
|
let lua_path = std::env::var("LUA_PATH").expect("Lua is not installed!");
|
||||||
let mut local_lua_path = std::env::current_dir()
|
let mut local_lua_path = std::env::current_dir()
|
||||||
.unwrap()
|
.expect("Couldn't get current dir")
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.to_string();
|
.to_string();
|
||||||
local_lua_path.push_str("/api/lua"); // TODO: get from crate root and do dynamically
|
local_lua_path.push_str("/api/lua"); // TODO: get from crate root and do dynamically
|
||||||
|
@ -339,7 +336,7 @@ impl<B: Backend> State<B> {
|
||||||
.env("LUA_PATH", new_lua_path)
|
.env("LUA_PATH", new_lua_path)
|
||||||
.env("LUA_CPATH", new_lua_cpath)
|
.env("LUA_CPATH", new_lua_cpath)
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.expect("Could not start config process");
|
||||||
|
|
||||||
let display_handle = display.handle();
|
let display_handle = display.handle();
|
||||||
let mut seat_state = SeatState::new();
|
let mut seat_state = SeatState::new();
|
||||||
|
@ -381,13 +378,14 @@ impl<B: Backend> State<B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_spawn(&self, command: Vec<String>, callback_id: Option<CallbackId>) {
|
pub fn handle_spawn(&self, command: Vec<String>, callback_id: Option<CallbackId>) {
|
||||||
let mut command = command.into_iter().peekable();
|
let mut command = command.into_iter();
|
||||||
if command.peek().is_none() {
|
let Some(program) = command.next() else {
|
||||||
// TODO: notify that command was nothing
|
// TODO: notify that command was nothing
|
||||||
return;
|
return;
|
||||||
}
|
};
|
||||||
|
|
||||||
let mut child = async_process::Command::new(OsString::from(command.next().unwrap()))
|
let program = OsString::from(program);
|
||||||
|
let Ok(mut child) = async_process::Command::new(&program)
|
||||||
.env("WAYLAND_DISPLAY", self.socket_name.clone())
|
.env("WAYLAND_DISPLAY", self.socket_name.clone())
|
||||||
.stdin(if callback_id.is_some() {
|
.stdin(if callback_id.is_some() {
|
||||||
Stdio::piped()
|
Stdio::piped()
|
||||||
|
@ -408,13 +406,17 @@ impl<B: Backend> State<B> {
|
||||||
})
|
})
|
||||||
.args(command)
|
.args(command)
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap(); // TODO: handle unwrap
|
else {
|
||||||
|
// TODO: notify user that program doesn't exist
|
||||||
|
tracing::warn!("tried to run {}, but it doesn't exist", program.to_string_lossy());
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: find a way to make this hellish code look better, deal with unwraps
|
// TODO: find a way to make this hellish code look better, deal with unwraps
|
||||||
if let Some(callback_id) = callback_id {
|
if let Some(callback_id) = callback_id {
|
||||||
let stdout = child.stdout.take();
|
let stdout = child.stdout.take();
|
||||||
let stderr = child.stderr.take();
|
let stderr = child.stderr.take();
|
||||||
let stream_out = self.api_state.stream.as_ref().unwrap().clone();
|
let stream_out = self.api_state.stream.as_ref().expect("Stream doesn't exist").clone();
|
||||||
let stream_err = stream_out.clone();
|
let stream_err = stream_out.clone();
|
||||||
let stream_exit = stream_out.clone();
|
let stream_exit = stream_out.clone();
|
||||||
|
|
||||||
|
@ -427,7 +429,7 @@ impl<B: Backend> State<B> {
|
||||||
match reader.read_line(&mut buf).await {
|
match reader.read_line(&mut buf).await {
|
||||||
Ok(0) => break,
|
Ok(0) => break,
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let mut stream = stream_out.lock().unwrap();
|
let mut stream = stream_out.lock().expect("Couldn't lock stream");
|
||||||
crate::api::send_to_client(
|
crate::api::send_to_client(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
&OutgoingMsg::CallCallback {
|
&OutgoingMsg::CallCallback {
|
||||||
|
@ -440,7 +442,7 @@ impl<B: Backend> State<B> {
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap();
|
.expect("Send to client failed"); // TODO: notify instead of crash
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::warn!("child read err: {err}");
|
tracing::warn!("child read err: {err}");
|
||||||
|
@ -449,7 +451,11 @@ impl<B: Backend> State<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.async_scheduler.schedule(future).unwrap();
|
|
||||||
|
// This is not important enough to crash on error, so just print the error instead
|
||||||
|
if let Err(err) = self.async_scheduler.schedule(future) {
|
||||||
|
tracing::error!("Failed to schedule future: {err}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Some(stderr) = stderr {
|
if let Some(stderr) = stderr {
|
||||||
let future = async move {
|
let future = async move {
|
||||||
|
@ -459,7 +465,7 @@ impl<B: Backend> State<B> {
|
||||||
match reader.read_line(&mut buf).await {
|
match reader.read_line(&mut buf).await {
|
||||||
Ok(0) => break,
|
Ok(0) => break,
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let mut stream = stream_err.lock().unwrap();
|
let mut stream = stream_err.lock().expect("Couldn't lock stream");
|
||||||
crate::api::send_to_client(
|
crate::api::send_to_client(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
&OutgoingMsg::CallCallback {
|
&OutgoingMsg::CallCallback {
|
||||||
|
@ -472,7 +478,7 @@ impl<B: Backend> State<B> {
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap();
|
.expect("Send to client failed"); // TODO: notify instead of crash
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::warn!("child read err: {err}");
|
tracing::warn!("child read err: {err}");
|
||||||
|
@ -481,13 +487,15 @@ impl<B: Backend> State<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.async_scheduler.schedule(future).unwrap();
|
if let Err(err) = self.async_scheduler.schedule(future) {
|
||||||
|
tracing::error!("Failed to schedule future: {err}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let future = async move {
|
let future = async move {
|
||||||
match child.status().await {
|
match child.status().await {
|
||||||
Ok(exit_status) => {
|
Ok(exit_status) => {
|
||||||
let mut stream = stream_exit.lock().unwrap();
|
let mut stream = stream_exit.lock().expect("Couldn't lock stream");
|
||||||
crate::api::send_to_client(
|
crate::api::send_to_client(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
&OutgoingMsg::CallCallback {
|
&OutgoingMsg::CallCallback {
|
||||||
|
@ -500,14 +508,16 @@ impl<B: Backend> State<B> {
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap()
|
.expect("Send to client failed"); // TODO: notify instead of crash
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::warn!("child wait() err: {err}");
|
tracing::warn!("child wait() err: {err}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.async_scheduler.schedule(future).unwrap();
|
if let Err(err) = self.async_scheduler.schedule(future) {
|
||||||
|
tracing::error!("Failed to schedule future: {err}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,10 @@ pub trait SurfaceState: Default + 'static {
|
||||||
{
|
{
|
||||||
compositor::with_states(wl_surface, |states| {
|
compositor::with_states(wl_surface, |states| {
|
||||||
states.data_map.insert_if_missing(RefCell::<Self>::default);
|
states.data_map.insert_if_missing(RefCell::<Self>::default);
|
||||||
let state = states.data_map.get::<RefCell<Self>>().unwrap();
|
let state = states
|
||||||
|
.data_map
|
||||||
|
.get::<RefCell<Self>>()
|
||||||
|
.expect("This should never happen");
|
||||||
|
|
||||||
function(&mut state.borrow_mut())
|
function(&mut state.borrow_mut())
|
||||||
})
|
})
|
||||||
|
|
|
@ -119,7 +119,7 @@ impl WindowState {
|
||||||
let mut state = window
|
let mut state = window
|
||||||
.user_data()
|
.user_data()
|
||||||
.get::<RefCell<Self>>()
|
.get::<RefCell<Self>>()
|
||||||
.unwrap()
|
.expect("This should never happen")
|
||||||
.borrow_mut();
|
.borrow_mut();
|
||||||
func(&mut state)
|
func(&mut state)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue