diff --git a/default-config/src/lib.rs b/default-config/src/lib.rs index 0ff7591a..55e0ba5c 100644 --- a/default-config/src/lib.rs +++ b/default-config/src/lib.rs @@ -1,6 +1,7 @@ +use jay_config::drm::{get_connector, on_connector_connected, on_new_connector}; use jay_config::embedded::grab_input_device; use jay_config::input::capability::{CAP_KEYBOARD, CAP_POINTER}; -use jay_config::input::InputDevice; +use jay_config::input::{create_seat, input_devices, on_new_input_device, InputDevice, Seat}; use jay_config::keyboard::mods::{Modifiers, ALT, CTRL, SHIFT}; use jay_config::keyboard::syms::{ SYM_Super_L, SYM_b, SYM_d, SYM_f, SYM_h, SYM_j, SYM_k, SYM_l, SYM_m, SYM_p, SYM_q, SYM_t, @@ -10,10 +11,7 @@ use jay_config::keyboard::syms::{ }; use jay_config::Axis::{Horizontal, Vertical}; use jay_config::Direction::{Down, Left, Right, Up}; -use jay_config::{ - config, create_seat, get_workspace, input_devices, on_new_input_device, quit, switch_to_vt, - Command, Seat, -}; +use jay_config::{config, get_workspace, quit, switch_to_vt, Command}; const MOD: Modifiers = ALT; @@ -96,6 +94,18 @@ pub fn configure() { }; input_devices().into_iter().for_each(handle_input_device); on_new_input_device(handle_input_device); + + let connectors_changed = || { + let left = get_connector("HDMI-A-1"); + let right = get_connector("DP-1"); + if left.connected() && right.connected() { + left.set_position(0, 0); + right.set_position(left.width(), 0); + } + }; + on_new_connector(move |_| connectors_changed()); + on_connector_connected(move |_| connectors_changed()); + connectors_changed(); } config!(configure); diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index 610a0e51..a450838b 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -2,13 +2,14 @@ use crate::_private::ipc::{ClientMessage, InitMessage, Response, ServerMessage}; use crate::_private::{bincode_ops, logging, Config, ConfigEntry, ConfigEntryGen, VERSION}; -use crate::drm::Connector; +use crate::drm::connector_type::{ConnectorType, CON_UNKNOWN}; +use crate::drm::{Connector, Mode}; use crate::input::acceleration::AccelProfile; use crate::input::capability::Capability; -use crate::input::InputDevice; +use crate::input::{InputDevice, Seat}; use crate::keyboard::keymap::Keymap; use crate::theme::Color; -use crate::{Axis, Command, Direction, LogLevel, ModifiedKeySym, Seat, Workspace}; +use crate::{Axis, Command, Direction, LogLevel, ModifiedKeySym, Workspace}; use std::cell::{Cell, RefCell}; use std::collections::hash_map::Entry; use std::collections::HashMap; @@ -127,6 +128,18 @@ pub unsafe extern "C" fn handle_msg(data: *const u8, msg: *const u8, size: usize }); } +macro_rules! get_response { + ($res:expr, $def:expr, $ty:ident, $($field:ident),+) => { + let ($($field,)+) = match $res { + Response::$ty { $($field,)+ } => ($($field,)+), + _ => { + log::error!("Server did not send a response to a {} request", stringify!($ty)); + return $def; + } + }; + } +} + impl Client { fn send(&self, msg: &ClientMessage) { let mut buf = self.bufs.borrow_mut().pop().unwrap_or_default(); @@ -138,6 +151,10 @@ impl Client { self.bufs.borrow_mut().push(buf); } + fn send_with_response(&self, msg: &ClientMessage) -> Response { + self.with_response(|| self.send(msg)) + } + pub fn spawn(&self, command: &Command) { let env = command .env @@ -185,36 +202,27 @@ impl Client { } pub fn seats(&self) -> Vec { - let response = self.with_response(|| self.send(&ClientMessage::GetSeats)); - match response { - Response::GetSeats { seats } => seats, - _ => { - log::error!("Server did not send a response to a get_seats request"); - vec![] - } - } + let res = self.with_response(|| self.send(&ClientMessage::GetSeats)); + get_response!(res, vec![], GetSeats, seats); + seats } pub fn mono(&self, seat: Seat) -> bool { let res = self.with_response(|| self.send(&ClientMessage::GetMono { seat })); - match res { - Response::GetMono { mono } => mono, - _ => { - log::error!("Server did not send a response to a get_mono request"); - false - } - } + get_response!(res, false, GetMono, mono); + mono } pub fn get_workspace(&self, name: &str) -> Workspace { let res = self.with_response(|| self.send(&ClientMessage::GetWorkspace { name })); - match res { - Response::GetWorkspace { workspace } => workspace, - _ => { - log::error!("Server did not send a response to a get_workspace request"); - Workspace(0) - } - } + get_response!(res, Workspace(0), GetWorkspace, workspace); + workspace + } + + pub fn get_connector(&self, ty: ConnectorType, idx: u32) -> Connector { + let res = self.with_response(|| self.send(&ClientMessage::GetConnector { ty, idx })); + get_response!(res, Connector(0), GetConnector, connector); + connector } pub fn show_workspace(&self, seat: Seat, workspace: Workspace) { @@ -223,13 +231,8 @@ impl Client { pub fn split(&self, seat: Seat) -> Axis { let res = self.with_response(|| self.send(&ClientMessage::GetSplit { seat })); - match res { - Response::GetSplit { axis } => axis, - _ => { - log::error!("Server did not send a response to a get_split request"); - Axis::Horizontal - } - } + get_response!(res, Axis::Horizontal, GetSplit, axis); + axis } pub fn toggle_floating(&self, seat: Seat) { @@ -253,25 +256,15 @@ impl Client { } pub fn get_title_height(&self) -> i32 { - let resp = self.with_response(|| self.send(&ClientMessage::GetTitleHeight)); - match resp { - Response::GetTitleHeight { height } => height, - _ => { - log::warn!("Server did not reply to a get_title_height request"); - 0 - } - } + let res = self.with_response(|| self.send(&ClientMessage::GetTitleHeight)); + get_response!(res, 0, GetTitleHeight, height); + height } pub fn get_border_width(&self) -> i32 { - let resp = self.with_response(|| self.send(&ClientMessage::GetBorderWidth)); - match resp { - Response::GetBorderWidth { width } => width, - _ => { - log::warn!("Server did not reply to a get_border_width request"); - 0 - } - } + let res = self.with_response(|| self.send(&ClientMessage::GetBorderWidth)); + get_response!(res, 0, GetBorderWidth, width); + width } pub fn set_title_height(&self, height: i32) { @@ -299,25 +292,15 @@ impl Client { } pub fn create_seat(&self, name: &str) -> Seat { - let response = self.with_response(|| self.send(&ClientMessage::CreateSeat { name })); - match response { - Response::CreateSeat { seat } => seat, - _ => { - log::error!("Server did not send a response to a create_seat request"); - Seat(0) - } - } + let res = self.with_response(|| self.send(&ClientMessage::CreateSeat { name })); + get_response!(res, Seat(0), CreateSeat, seat); + seat } pub fn get_input_devices(&self, seat: Option) -> Vec { let res = self.with_response(|| self.send(&ClientMessage::GetInputDevices { seat })); - match res { - Response::GetInputDevices { devices } => devices, - _ => { - log::error!("Server did not send a response to a get_input_devices request"); - vec![] - } - } + get_response!(res, vec!(), GetInputDevices, devices); + devices } pub fn on_new_seat(&self, f: F) { @@ -336,6 +319,47 @@ impl Client { *self.on_new_input_device.borrow_mut() = Some(Rc::new(f)); } + pub fn connector_set_position(&self, connector: Connector, x: i32, y: i32) { + self.send(&ClientMessage::ConnectorSetPosition { connector, x, y }); + } + + pub fn connector_connected(&self, connector: Connector) -> bool { + let res = self.send_with_response(&ClientMessage::ConnectorConnected { connector }); + get_response!(res, false, ConnectorConnected, connected); + connected + } + + pub fn connector_type(&self, connector: Connector) -> ConnectorType { + let res = self.send_with_response(&ClientMessage::ConnectorType { connector }); + get_response!(res, CON_UNKNOWN, ConnectorType, ty); + ty + } + + pub fn connector_mode(&self, connector: Connector) -> Mode { + let res = self.send_with_response(&ClientMessage::ConnectorMode { connector }); + get_response!( + res, + Mode::zeroed(), + ConnectorMode, + width, + height, + refresh_millihz + ); + Mode { + width, + height, + refresh_millihz, + } + } + + pub fn on_new_connector(&self, f: F) { + *self.on_new_connector.borrow_mut() = Some(Rc::new(f)); + } + + pub fn on_connector_connected(&self, f: F) { + *self.on_connector_connected.borrow_mut() = Some(Rc::new(f)); + } + pub fn set_seat(&self, device: InputDevice, seat: Seat) { self.send(&ClientMessage::SetSeat { device, seat }) } @@ -361,24 +385,14 @@ impl Client { pub fn device_name(&self, device: InputDevice) -> String { let res = self.with_response(|| self.send(&ClientMessage::GetDeviceName { device })); - match res { - Response::GetDeviceName { name } => name, - _ => { - log::error!("Server did not send a response to a get_device_name request"); - String::new() - } - } + get_response!(res, String::new(), GetDeviceName, name); + name } pub fn has_capability(&self, device: InputDevice, cap: Capability) -> bool { let res = self.with_response(|| self.send(&ClientMessage::HasCapability { device, cap })); - match res { - Response::HasCapability { has } => has, - _ => { - log::error!("Server did not send a response to a has_capability request"); - false - } - } + get_response!(res, false, HasCapability, has); + has } pub fn seat_set_keymap(&self, seat: Seat, keymap: Keymap) { @@ -391,24 +405,14 @@ impl Client { pub fn seat_get_repeat_rate(&self, seat: Seat) -> (i32, i32) { let res = self.with_response(|| self.send(&ClientMessage::SeatGetRepeatRate { seat })); - match res { - Response::GetRepeatRate { rate, delay } => (rate, delay), - _ => { - log::error!("Server did not send a response to a get_repeat_rate request"); - (25, 250) - } - } + get_response!(res, (25, 250), GetRepeatRate, rate, delay); + (rate, delay) } pub fn parse_keymap(&self, keymap: &str) -> Keymap { let res = self.with_response(|| self.send(&ClientMessage::ParseKeymap { keymap })); - match res { - Response::ParseKeymap { keymap } => keymap, - _ => { - log::error!("Server did not send a response to a parse_keymap request"); - Keymap(0) - } - } + get_response!(res, Keymap(0), ParseKeymap, keymap); + keymap } pub fn bind, F: Fn() + 'static>(&self, seat: Seat, mod_sym: T, f: F) { diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index a1dce1c9..6f1ad38f 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -1,12 +1,13 @@ +use crate::drm::connector_type::ConnectorType; use crate::drm::Connector; use crate::input::acceleration::AccelProfile; use crate::input::capability::Capability; -use crate::input::InputDevice; +use crate::input::{InputDevice, Seat}; use crate::keyboard::keymap::Keymap; use crate::keyboard::mods::Modifiers; use crate::keyboard::syms::KeySym; use crate::theme::Color; -use crate::{Axis, Direction, LogLevel, Seat, Workspace}; +use crate::{Axis, Direction, LogLevel, Workspace}; use bincode::{BorrowDecode, Decode, Encode}; #[derive(Encode, BorrowDecode, Debug)] @@ -178,6 +179,24 @@ pub enum ClientMessage<'a> { GetWorkspace { name: &'a str, }, + GetConnector { + ty: ConnectorType, + idx: u32, + }, + ConnectorConnected { + connector: Connector, + }, + ConnectorType { + connector: Connector, + }, + ConnectorMode { + connector: Connector, + }, + ConnectorSetPosition { + connector: Connector, + x: i32, + y: i32, + }, ShowWorkspace { seat: Seat, workspace: Workspace, @@ -187,18 +206,57 @@ pub enum ClientMessage<'a> { #[derive(Encode, Decode, Debug)] pub enum Response { None, - GetSeats { seats: Vec }, - GetSplit { axis: Axis }, - GetMono { mono: bool }, - GetRepeatRate { rate: i32, delay: i32 }, - ParseKeymap { keymap: Keymap }, - CreateSeat { seat: Seat }, - GetInputDevices { devices: Vec }, - GetTitleHeight { height: i32 }, - GetBorderWidth { width: i32 }, - HasCapability { has: bool }, - GetDeviceName { name: String }, - GetWorkspace { workspace: Workspace }, + GetSeats { + seats: Vec, + }, + GetSplit { + axis: Axis, + }, + GetMono { + mono: bool, + }, + GetRepeatRate { + rate: i32, + delay: i32, + }, + ParseKeymap { + keymap: Keymap, + }, + CreateSeat { + seat: Seat, + }, + GetInputDevices { + devices: Vec, + }, + GetTitleHeight { + height: i32, + }, + GetBorderWidth { + width: i32, + }, + HasCapability { + has: bool, + }, + GetDeviceName { + name: String, + }, + GetWorkspace { + workspace: Workspace, + }, + GetConnector { + connector: Connector, + }, + ConnectorConnected { + connected: bool, + }, + ConnectorType { + ty: ConnectorType, + }, + ConnectorMode { + width: i32, + height: i32, + refresh_millihz: u32, + }, } #[derive(Encode, Decode, Debug)] diff --git a/jay-config/src/drm.rs b/jay-config/src/drm.rs index 6e955e07..842f3e7e 100644 --- a/jay-config/src/drm.rs +++ b/jay-config/src/drm.rs @@ -1,4 +1,181 @@ +use crate::drm::connector_type::{ + ConnectorType, CON_9PIN_DIN, CON_COMPONENT, CON_COMPOSITE, CON_DISPLAY_PORT, CON_DPI, CON_DSI, + CON_DVIA, CON_DVID, CON_DVII, CON_EDP, CON_EMBEDDED_WINDOW, CON_HDMIA, CON_HDMIB, CON_LVDS, + CON_SPI, CON_SVIDEO, CON_TV, CON_UNKNOWN, CON_USB, CON_VGA, CON_VIRTUAL, CON_WRITEBACK, +}; use bincode::{Decode, Encode}; +use std::str::FromStr; + +#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] +pub struct Mode { + pub(crate) width: i32, + pub(crate) height: i32, + pub(crate) refresh_millihz: u32, +} + +impl Mode { + pub fn width(&self) -> i32 { + self.width + } + + pub fn height(&self) -> i32 { + self.height + } + + pub fn refresh_rate(&self) -> u32 { + self.refresh_millihz + } + + pub(crate) fn zeroed() -> Self { + Self { + width: 0, + height: 0, + refresh_millihz: 0, + } + } +} #[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] pub struct Connector(pub u64); + +impl Connector { + pub fn exists(self) -> bool { + self.0 != 0 + } + + pub fn connected(self) -> bool { + if !self.exists() { + return false; + } + get!(false).connector_connected(self) + } + + pub fn ty(self) -> ConnectorType { + if !self.exists() { + return CON_UNKNOWN; + } + get!(CON_UNKNOWN).connector_type(self) + } + + pub fn mode(self) -> Mode { + if !self.exists() { + return Mode::zeroed(); + } + get!(Mode::zeroed()).connector_mode(self) + } + + pub fn width(self) -> i32 { + self.mode().width + } + + pub fn height(self) -> i32 { + self.mode().height + } + + pub fn refresh_rate(self) -> u32 { + self.mode().refresh_millihz + } + + pub fn set_position(self, x: i32, y: i32) { + if !self.exists() { + log::warn!("set_position called on a connector that does not exist"); + return; + } + get!().connector_set_position(self, x, y); + } +} + +pub fn on_new_connector(f: F) { + get!().on_new_connector(f) +} + +pub fn on_connector_connected(f: F) { + get!().on_connector_connected(f) +} + +pub fn get_connector(id: impl ToConnectorId) -> Connector { + let (ty, idx) = match id.to_connector_id() { + Ok(id) => id, + Err(e) => { + log::error!("{}", e); + return Connector(0); + } + }; + get!(Connector(0)).get_connector(ty, idx) +} + +pub trait ToConnectorId { + fn to_connector_id(&self) -> Result<(ConnectorType, u32), String>; +} + +impl ToConnectorId for (ConnectorType, u32) { + fn to_connector_id(&self) -> Result<(ConnectorType, u32), String> { + Ok(*self) + } +} + +impl ToConnectorId for &'_ str { + fn to_connector_id(&self) -> Result<(ConnectorType, u32), String> { + let pairs = [ + ("DP-", CON_DISPLAY_PORT), + ("eDP-", CON_EDP), + ("HDMI-A-", CON_HDMIA), + ("HDMI-B-", CON_HDMIB), + ("EmbeddedWindow-", CON_EMBEDDED_WINDOW), + ("VGA-", CON_VGA), + ("DVI-I-", CON_DVII), + ("DVI-D-", CON_DVID), + ("DVI-A-", CON_DVIA), + ("Composite-", CON_COMPOSITE), + ("SVIDEO-", CON_SVIDEO), + ("LVDS-", CON_LVDS), + ("Component-", CON_COMPONENT), + ("DIN-", CON_9PIN_DIN), + ("TV-", CON_TV), + ("Virtual-", CON_VIRTUAL), + ("DSI-", CON_DSI), + ("DPI-", CON_DPI), + ("Writeback-", CON_WRITEBACK), + ("SPI-", CON_SPI), + ("USB-", CON_USB), + ]; + for (prefix, ty) in pairs { + if let Some(suffix) = self.strip_prefix(prefix) { + if let Ok(idx) = u32::from_str(suffix) { + return Ok((ty, idx)); + } + } + } + Err(format!("`{}` is not a valid connector identifier", self)) + } +} + +pub mod connector_type { + use bincode::{Decode, Encode}; + + #[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] + pub struct ConnectorType(pub u32); + + pub const CON_UNKNOWN: ConnectorType = ConnectorType(0); + pub const CON_VGA: ConnectorType = ConnectorType(1); + pub const CON_DVII: ConnectorType = ConnectorType(2); + pub const CON_DVID: ConnectorType = ConnectorType(3); + pub const CON_DVIA: ConnectorType = ConnectorType(4); + pub const CON_COMPOSITE: ConnectorType = ConnectorType(5); + pub const CON_SVIDEO: ConnectorType = ConnectorType(6); + pub const CON_LVDS: ConnectorType = ConnectorType(7); + pub const CON_COMPONENT: ConnectorType = ConnectorType(8); + pub const CON_9PIN_DIN: ConnectorType = ConnectorType(9); + pub const CON_DISPLAY_PORT: ConnectorType = ConnectorType(10); + pub const CON_HDMIA: ConnectorType = ConnectorType(11); + pub const CON_HDMIB: ConnectorType = ConnectorType(12); + pub const CON_TV: ConnectorType = ConnectorType(13); + pub const CON_EDP: ConnectorType = ConnectorType(14); + pub const CON_VIRTUAL: ConnectorType = ConnectorType(15); + pub const CON_DSI: ConnectorType = ConnectorType(16); + pub const CON_DPI: ConnectorType = ConnectorType(17); + pub const CON_WRITEBACK: ConnectorType = ConnectorType(18); + pub const CON_SPI: ConnectorType = ConnectorType(19); + pub const CON_USB: ConnectorType = ConnectorType(20); + pub const CON_EMBEDDED_WINDOW: ConnectorType = ConnectorType(u32::MAX); +} diff --git a/jay-config/src/input.rs b/jay-config/src/input.rs index 822772f8..e00eb06a 100644 --- a/jay-config/src/input.rs +++ b/jay-config/src/input.rs @@ -3,7 +3,7 @@ pub mod capability; use crate::input::acceleration::AccelProfile; use crate::input::capability::Capability; -use crate::Seat; +use crate::{Axis, Direction, Keymap, ModifiedKeySym, Workspace}; use bincode::{Decode, Encode}; #[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] @@ -38,3 +38,126 @@ impl InputDevice { get!(String::new()).device_name(self) } } + +impl Seat { + #[doc(hidden)] + pub fn raw(self) -> u64 { + self.0 + } + + #[doc(hidden)] + pub fn from_raw(raw: u64) -> Self { + Self(raw) + } + + pub fn bind, F: Fn() + 'static>(self, mod_sym: T, f: F) { + get!().bind(self, mod_sym, f) + } + + pub fn unbind>(self, mod_sym: T) { + get!().unbind(self, mod_sym) + } + + pub fn focus(self, direction: Direction) { + get!().focus(self, direction) + } + + pub fn move_(self, direction: Direction) { + get!().move_(self, direction) + } + + pub fn set_keymap(self, keymap: Keymap) { + get!().seat_set_keymap(self, keymap) + } + + pub fn repeat_rate(self) -> (i32, i32) { + let mut res = (25, 250); + (|| res = get!().seat_get_repeat_rate(self))(); + res + } + + pub fn set_repeat_rate(self, rate: i32, delay: i32) { + get!().seat_set_repeat_rate(self, rate, delay) + } + + pub fn mono(self) -> bool { + let mut res = false; + (|| res = get!().mono(self))(); + res + } + + pub fn set_mono(self, mono: bool) { + get!().set_mono(self, mono) + } + + pub fn split(self) -> Axis { + let mut res = Axis::Horizontal; + (|| res = get!().split(self))(); + res + } + + pub fn set_split(self, axis: Axis) { + get!().set_split(self, axis) + } + + pub fn input_devices(self) -> Vec { + let mut res = vec![]; + (|| res = get!().get_input_devices(Some(self)))(); + res + } + + pub fn create_split(self, axis: Axis) { + get!().create_split(self, axis); + } + + pub fn focus_parent(self) { + get!().focus_parent(self); + } + + pub fn toggle_floating(self) { + get!().toggle_floating(self); + } + + pub fn show_workspace(self, workspace: Workspace) { + get!().show_workspace(self, workspace) + } +} + +pub fn get_seats() -> Vec { + let mut res = vec![]; + (|| res = get!().seats())(); + res +} + +pub fn input_devices() -> Vec { + let mut res = vec![]; + (|| res = get!().get_input_devices(None))(); + res +} + +pub fn remove_all_seats() {} + +pub fn create_seat(name: &str) -> Seat { + let mut res = Seat(0); + (|| res = get!().create_seat(name))(); + res +} + +pub fn on_new_seat(f: F) { + get!().on_new_seat(f) +} + +pub fn on_new_input_device(f: F) { + get!().on_new_input_device(f) +} + +#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] +pub struct Seat(pub u64); + +impl Seat { + pub const INVALID: Self = Self(0); + + pub fn is_invalid(self) -> bool { + self == Self::INVALID + } +} diff --git a/jay-config/src/lib.rs b/jay-config/src/lib.rs index 4a811715..4a6dca93 100644 --- a/jay-config/src/lib.rs +++ b/jay-config/src/lib.rs @@ -1,4 +1,3 @@ -use crate::input::InputDevice; use crate::keyboard::keymap::Keymap; use crate::keyboard::ModifiedKeySym; use bincode::{Decode, Encode}; @@ -31,17 +30,6 @@ pub enum Direction { Right, } -#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] -pub struct Seat(pub u64); - -impl Seat { - pub const INVALID: Self = Self(0); - - pub fn is_invalid(self) -> bool { - self == Self::INVALID - } -} - #[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum Axis { Horizontal, @@ -57,118 +45,6 @@ impl Axis { } } -impl Seat { - #[doc(hidden)] - pub fn raw(self) -> u64 { - self.0 - } - - #[doc(hidden)] - pub fn from_raw(raw: u64) -> Self { - Self(raw) - } - - pub fn bind, F: Fn() + 'static>(self, mod_sym: T, f: F) { - get!().bind(self, mod_sym, f) - } - - pub fn unbind>(self, mod_sym: T) { - get!().unbind(self, mod_sym) - } - - pub fn focus(self, direction: Direction) { - get!().focus(self, direction) - } - - pub fn move_(self, direction: Direction) { - get!().move_(self, direction) - } - - pub fn set_keymap(self, keymap: Keymap) { - get!().seat_set_keymap(self, keymap) - } - - pub fn repeat_rate(self) -> (i32, i32) { - let mut res = (25, 250); - (|| res = get!().seat_get_repeat_rate(self))(); - res - } - - pub fn set_repeat_rate(self, rate: i32, delay: i32) { - get!().seat_set_repeat_rate(self, rate, delay) - } - - pub fn mono(self) -> bool { - let mut res = false; - (|| res = get!().mono(self))(); - res - } - - pub fn set_mono(self, mono: bool) { - get!().set_mono(self, mono) - } - - pub fn split(self) -> Axis { - let mut res = Axis::Horizontal; - (|| res = get!().split(self))(); - res - } - - pub fn set_split(self, axis: Axis) { - get!().set_split(self, axis) - } - - pub fn input_devices(self) -> Vec { - let mut res = vec![]; - (|| res = get!().get_input_devices(Some(self)))(); - res - } - - pub fn create_split(self, axis: Axis) { - get!().create_split(self, axis); - } - - pub fn focus_parent(self) { - get!().focus_parent(self); - } - - pub fn toggle_floating(self) { - get!().toggle_floating(self); - } - - pub fn show_workspace(self, workspace: Workspace) { - get!().show_workspace(self, workspace) - } -} - -pub fn get_seats() -> Vec { - let mut res = vec![]; - (|| res = get!().seats())(); - res -} - -pub fn input_devices() -> Vec { - let mut res = vec![]; - (|| res = get!().get_input_devices(None))(); - res -} - -pub fn remove_all_seats() {} - -pub fn create_seat(name: &str) -> Seat { - let mut res = Seat(0); - (|| res = get!().create_seat(name))(); - res -} - -pub fn on_new_seat(f: F) { - get!().on_new_seat(f) -} - -pub fn on_new_input_device(f: F) { - get!().on_new_input_device(f) -} - pub fn quit() { get!().quit() } diff --git a/src/backend.rs b/src/backend.rs index 02006e9b..1c12d105 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -30,12 +30,12 @@ pub struct MonitorInfo { pub struct ConnectorKernelId { pub ty: ConnectorType, - pub id: u32, + pub idx: u32, } impl Display for ConnectorKernelId { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}-{}", self.ty, self.id) + write!(f, "{}-{}", self.ty, self.idx) } } diff --git a/src/backends/dummy.rs b/src/backends/dummy.rs index a673d471..d2c95a54 100644 --- a/src/backends/dummy.rs +++ b/src/backends/dummy.rs @@ -22,7 +22,7 @@ impl Connector for DummyOutput { fn kernel_id(&self) -> ConnectorKernelId { ConnectorKernelId { ty: ConnectorType::Unknown(0), - id: 0, + idx: 0, } } diff --git a/src/backends/metal.rs b/src/backends/metal.rs index 8df14dbe..b4ccc76a 100644 --- a/src/backends/metal.rs +++ b/src/backends/metal.rs @@ -23,7 +23,7 @@ use crate::logind::{LogindError, Session}; use crate::render::RenderError; use crate::state::State; use crate::udev::{Udev, UdevError, UdevMonitor}; -use crate::utils::clonecell::CloneCell; +use crate::utils::clonecell::{CloneCell, UnsafeCellCloneSafe}; use crate::utils::copyhashmap::CopyHashMap; use crate::utils::errorfmt::ErrorFmt; use crate::utils::oserror::OsError; @@ -226,6 +226,8 @@ enum MetalDevice { Drm(Rc), } +unsafe impl UnsafeCellCloneSafe for MetalDevice {} + struct DeviceHolder { devices: CopyHashMap, input_devices: RefCell>>>, diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 3d687de6..0c4c89c1 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -1,5 +1,7 @@ use crate::async_engine::{AsyncFd, SpawnedFuture}; -use crate::backend::{BackendEvent, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, MonitorInfo}; +use crate::backend::{ + BackendEvent, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, MonitorInfo, +}; use crate::backends::metal::{DrmId, MetalBackend, MetalError}; use crate::drm::drm::{ drm_mode_modeinfo, Change, ConnectorStatus, ConnectorType, DrmBlob, DrmConnector, DrmCrtc, @@ -9,11 +11,13 @@ use crate::drm::drm::{ }; use crate::drm::gbm::{GbmDevice, GBM_BO_USE_RENDERING, GBM_BO_USE_SCANOUT}; use crate::drm::{ModifiedFormat, INVALID_MODIFIER}; +use crate::edid::Descriptor; use crate::format::{Format, XRGB8888}; use crate::render::{Framebuffer, RenderContext}; use crate::state::State; use crate::utils::bitflags::BitflagsExt; use crate::utils::clonecell::CloneCell; +use crate::utils::debug_fn::debug_fn; use crate::utils::errorfmt::ErrorFmt; use crate::utils::numcell::NumCell; use crate::utils::oserror::OsError; @@ -25,7 +29,6 @@ use std::ffi::CString; use std::fmt::{Debug, Formatter}; use std::rc::Rc; use uapi::c; -use crate::edid::Descriptor; pub struct PendingDrmDevice { pub id: DrmId, @@ -126,7 +129,7 @@ impl Connector for MetalConnector { fn kernel_id(&self) -> ConnectorKernelId { ConnectorKernelId { ty: self.connector_type, - id: self.connector_type_id, + idx: self.connector_type_id, } } @@ -224,11 +227,12 @@ fn create_connector( } } let props = collect_properties(&dev.master, connector)?; - let connection = ConnectorStatus::from(info.connection); - let connector_type = ConnectorType::from(info.connector_type); + let connection = ConnectorStatus::from_drm(info.connection); + let connector_type = ConnectorType::from_drm(info.connector_type); let mut name = String::new(); let mut manufacturer = String::new(); let mut serial_number = String::new(); + let connector_name = debug_fn(|f| write!(f, "{}-{}", connector_type, info.connector_type_id)); 'fetch_edid: { if connection != ConnectorStatus::Connected { break 'fetch_edid; @@ -236,21 +240,32 @@ fn create_connector( let edid = match props.get("EDID") { Ok(e) => e, _ => { - log::warn!("Connector {}-{} is connected but has no EDID blob", connector_type, info.connector_type_id); + log::warn!( + "Connector {} is connected but has no EDID blob", + connector_name, + ); break 'fetch_edid; } }; let blob = match dev.master.getblob_vec::(DrmBlob(edid.value.get() as _)) { Ok(b) => b, Err(e) => { - log::error!("Could not fetch edid property of connector {}-{}: {}", connector_type, info.connector_type_id, ErrorFmt(e)); + log::error!( + "Could not fetch edid property of connector {}: {}", + connector_name, + ErrorFmt(e) + ); break 'fetch_edid; } }; let edid = match crate::edid::parse(&blob) { Ok(e) => e, Err(e) => { - log::error!("Could not parse edid property of connector {}-{}: {}", connector_type, info.connector_type_id, ErrorFmt(e)); + log::error!( + "Could not parse edid property of connector {}: {}", + connector_name, + ErrorFmt(e) + ); break 'fetch_edid; } }; @@ -264,14 +279,21 @@ fn create_connector( Descriptor::DisplayProductName(s) => { name = s.to_string(); } - _ => { }, + _ => {} } } } if name.is_empty() { - log::warn!("The display attached to connector {}-{} does not have a product name descriptor", connector_type, info.connector_type_id); + log::warn!( + "The display attached to connector {} does not have a product name descriptor", + connector_name, + ); } if serial_number.is_empty() { + log::warn!( + "The display attached to connector {} does not have a serial number descriptor", + connector_name, + ); serial_number = edid.base_block.id_serial_number.to_string(); } } @@ -547,25 +569,31 @@ impl MetalBackend { .push(BackendEvent::NewConnector(connector.clone())); if connector.connection == ConnectorStatus::Connected { if connector.primary_plane.get().is_none() { - log::error!("Connector {}-{} is connected but does not have a primary plane", connector.connector_type, connector.connector_type_id); + log::error!( + "Connector {}-{} is connected but does not have a primary plane", + connector.connector_type, + connector.connector_type_id + ); continue; } let mut prev_mode = None; - let mut modes = vec!(); + let mut modes = vec![]; for mode in connector.modes.iter().map(|m| m.to_backend()) { if prev_mode.replace(mode) != Some(mode) { modes.push(mode); } } - connector.events.push(ConnectorEvent::Connected(MonitorInfo { - modes, - manufacturer: connector.monitor_manufacturer.clone(), - product: connector.monitor_name.clone(), - serial_number: connector.monitor_serial_number.clone(), - initial_mode: connector.mode.get().unwrap().to_backend(), - width_mm: connector.mm_width as _, - height_mm: connector.mm_height as _, - })); + connector + .events + .push(ConnectorEvent::Connected(MonitorInfo { + modes, + manufacturer: connector.monitor_manufacturer.clone(), + product: connector.monitor_name.clone(), + serial_number: connector.monitor_serial_number.clone(), + initial_mode: connector.mode.get().unwrap().to_backend(), + width_mm: connector.mm_width as _, + height_mm: connector.mm_height as _, + })); self.start_connector(connector); } } diff --git a/src/backends/x.rs b/src/backends/x.rs index 1104a9a4..ae94b8bc 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -1,5 +1,9 @@ use crate::async_engine::{Phase, SpawnedFuture}; -use crate::backend::{Backend, BackendEvent, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent, KeyState, Mode, MonitorInfo, ScrollAxis}; +use crate::backend::{ + Backend, BackendEvent, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, InputDevice, + InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent, KeyState, Mode, + MonitorInfo, ScrollAxis, +}; use crate::drm::drm::{ConnectorType, Drm, DrmError}; use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING}; use crate::drm::{ModifiedFormat, INVALID_MODIFIER}; @@ -878,7 +882,7 @@ impl Connector for XOutput { fn kernel_id(&self) -> ConnectorKernelId { ConnectorKernelId { ty: ConnectorType::EmbeddedWindow, - id: self.id.raw(), + idx: self.id.raw(), } } diff --git a/src/client.rs b/src/client.rs index 975d1737..9b58b1f9 100644 --- a/src/client.rs +++ b/src/client.rs @@ -9,6 +9,7 @@ use crate::object::{Interface, Object, ObjectId, WL_DISPLAY_ID}; use crate::state::State; use crate::utils::asyncevent::AsyncEvent; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError, OutBufferSwapchain}; +use crate::utils::copyhashmap::Locked; use crate::utils::errorfmt::ErrorFmt; use crate::utils::numcell::NumCell; use crate::utils::queue::AsyncQueue; @@ -16,7 +17,7 @@ use crate::wire::WlRegistryId; use crate::xwayland::XWaylandEvent; use ahash::AHashMap; pub use error::{ClientError, ObjectError}; -use std::cell::{Cell, RefCell, RefMut}; +use std::cell::{Cell, RefCell}; use std::error::Error; use std::fmt::{Debug, Display, Formatter}; use std::mem; @@ -335,7 +336,7 @@ impl Client { self.checking_queue_size.set(false); } - pub fn lock_registries(&self) -> RefMut>> { + pub fn lock_registries(&self) -> Locked> { self.objects.registries() } diff --git a/src/client/objects.rs b/src/client/objects.rs index 83c32234..6748ad10 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -15,13 +15,12 @@ use crate::ifs::xdg_wm_base::XdgWmBase; use crate::object::{Object, ObjectId}; use crate::tree::Node; use crate::utils::clonecell::CloneCell; -use crate::utils::copyhashmap::CopyHashMap; +use crate::utils::copyhashmap::{CopyHashMap, Locked}; use crate::wire::{ WlBufferId, WlDataSourceId, WlOutputId, WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId, XdgPositionerId, XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwpPrimarySelectionSourceV1Id, }; -use ahash::AHashMap; -use std::cell::{RefCell, RefMut}; +use std::cell::RefCell; use std::mem; use std::ops::DerefMut; use std::rc::Rc; @@ -167,7 +166,7 @@ impl Objects { Ok(()) } - pub fn registries(&self) -> RefMut>> { + pub fn registries(&self) -> Locked> { self.registries.lock() } diff --git a/src/compositor.rs b/src/compositor.rs index 059095c2..e278dcde 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -33,6 +33,8 @@ use std::rc::Rc; use std::sync::Arc; use thiserror::Error; +pub const MAX_EXTENTS: i32 = (1 << 24) - 1; + pub fn start_compositor(global: GlobalArgs, args: RunArgs) { let forker = match ForkerProxy::create() { Ok(f) => Rc::new(f), @@ -120,10 +122,13 @@ fn main_(forker: Rc, logger: Arc, _args: &RunArgs) -> Resul global: Rc::new(WlOutputGlobal::new( state.globals.name(), &Rc::new(ConnectorData { - connector: Rc::new(DummyOutput { id: state.connector_ids.next() }), + connector: Rc::new(DummyOutput { + id: state.connector_ids.next(), + }), monitor_info: Default::default(), handler: Cell::new(None), - node: Default::default() + node: Default::default(), + connected: Cell::new(true), }), 0, &backend::Mode { diff --git a/src/config.rs b/src/config.rs index 014e8555..ec6f96ee 100644 --- a/src/config.rs +++ b/src/config.rs @@ -9,9 +9,8 @@ use crate::utils::ptr_ext::PtrExt; use jay_config::_private::ipc::{InitMessage, ServerMessage, V1InitMessage}; use jay_config::_private::{bincode_ops, ConfigEntry, VERSION}; use jay_config::drm::Connector; -use jay_config::input::InputDevice; +use jay_config::input::{InputDevice, Seat}; use jay_config::keyboard::ModifiedKeySym; -use jay_config::Seat; use libloading::Library; use std::cell::Cell; use std::ptr; diff --git a/src/config/handler.rs b/src/config/handler.rs index 00767373..bf9468ab 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -1,7 +1,10 @@ use crate::backend; -use crate::backend::{InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId}; +use crate::backend::{ + ConnectorId, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, Mode, +}; +use crate::compositor::MAX_EXTENTS; use crate::ifs::wl_seat::{SeatId, WlSeatGlobal}; -use crate::state::{DeviceHandlerData, State}; +use crate::state::{ConnectorData, DeviceHandlerData, State}; use crate::tree::walker::NodeVisitorBase; use crate::tree::{ContainerNode, ContainerSplit, FloatNode, Node}; use crate::utils::copyhashmap::CopyHashMap; @@ -9,20 +12,21 @@ use crate::utils::debug_fn::debug_fn; use crate::utils::errorfmt::ErrorFmt; use crate::utils::numcell::NumCell; use crate::utils::stack::Stack; -use crate::xkbcommon::XkbKeymap; +use crate::xkbcommon::{XkbCommonError, XkbKeymap}; use bincode::error::DecodeError; use jay_config::_private::bincode_ops; use jay_config::_private::ipc::{ClientMessage, Response, ServerMessage}; +use jay_config::drm::Connector; use jay_config::input::acceleration::{AccelProfile, ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT}; use jay_config::input::capability::{ Capability, CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD, CAP_TABLET_TOOL, CAP_TOUCH, }; -use jay_config::input::InputDevice; +use jay_config::input::{InputDevice, Seat}; use jay_config::keyboard::keymap::Keymap; use jay_config::keyboard::mods::Modifiers; use jay_config::keyboard::syms::KeySym; -use jay_config::{Axis, Direction, LogLevel, Seat, Workspace}; +use jay_config::{Axis, Direction, LogLevel, Workspace}; use libloading::Library; use log::Level; use std::cell::Cell; @@ -101,20 +105,20 @@ impl ConfigProxyHandler { }); } - fn handle_parse_keymap(&self, keymap: &str) -> Result<(), ParseKeymapError> { + fn handle_parse_keymap(&self, keymap: &str) -> Result<(), CphError> { let (keymap, res) = match self.state.xkb_ctx.keymap_from_str(keymap) { Ok(keymap) => { let id = Keymap(self.id()); self.keymaps.set(id, keymap); (id, Ok(())) } - _ => (Keymap::INVALID, Err(ParseKeymapError::ParsingFailed)), + Err(e) => (Keymap::INVALID, Err(CphError::ParseKeymapError(e))), }; self.respond(Response::ParseKeymap { keymap }); res } - fn handle_set_keymap(&self, seat: Seat, keymap: Keymap) -> Result<(), SeatSetKeymapError> { + fn handle_set_keymap(&self, seat: Seat, keymap: Keymap) -> Result<(), CphError> { let seat = self.get_seat(seat)?; let keymap = if keymap.is_invalid() { self.state.default_keymap.clone() @@ -125,37 +129,32 @@ impl ConfigProxyHandler { Ok(()) } - fn handle_focus(&self, seat: Seat, direction: Direction) -> Result<(), FocusError> { + fn handle_focus(&self, seat: Seat, direction: Direction) -> Result<(), CphError> { let seat = self.get_seat(seat)?; seat.move_focus(direction); Ok(()) } - fn handle_move(&self, seat: Seat, direction: Direction) -> Result<(), MoveError> { + fn handle_move(&self, seat: Seat, direction: Direction) -> Result<(), CphError> { let seat = self.get_seat(seat)?; seat.move_focused(direction); Ok(()) } - fn handle_get_repeat_rate(&self, seat: Seat) -> Result<(), SeatGetRepeatRateError> { + fn handle_get_repeat_rate(&self, seat: Seat) -> Result<(), CphError> { let seat = self.get_seat(seat)?; let (rate, delay) = seat.get_rate(); self.respond(Response::GetRepeatRate { rate, delay }); Ok(()) } - fn handle_set_repeat_rate( - &self, - seat: Seat, - rate: i32, - delay: i32, - ) -> Result<(), SeatSetRepeatRateError> { + fn handle_set_repeat_rate(&self, seat: Seat, rate: i32, delay: i32) -> Result<(), CphError> { let seat = self.get_seat(seat)?; if rate < 0 { - return Err(SeatSetRepeatRateError::NegativeRate); + return Err(CphError::NegativeRepeatRate); } if delay < 0 { - return Err(SeatSetRepeatRateError::NegativeDelay); + return Err(CphError::NegativeRepeatDelay); } seat.set_rate(rate, delay); Ok(()) @@ -184,6 +183,17 @@ impl ConfigProxyHandler { } } + fn get_connector(&self, connector: Connector) -> Result, CphError> { + let data = self + .state + .connectors + .get(&ConnectorId::from_raw(connector.0 as _)); + match data { + Some(d) => Ok(d), + _ => Err(CphError::ConnectorDoesNotExist(connector)), + } + } + fn get_seat(&self, seat: Seat) -> Result, CphError> { let seats = self.state.globals.seats.lock(); for seat_global in seats.values() { @@ -209,7 +219,7 @@ impl ConfigProxyHandler { } } - fn handle_set_seat(&self, device: InputDevice, seat: Seat) -> Result<(), SetSeatError> { + fn handle_set_seat(&self, device: InputDevice, seat: Seat) -> Result<(), CphError> { let seat = if seat.is_invalid() { None } else { @@ -224,7 +234,7 @@ impl ConfigProxyHandler { &self, device: InputDevice, left_handed: bool, - ) -> Result<(), SetLeftHandedError> { + ) -> Result<(), CphError> { let dev = self.get_device_handler_data(device)?; dev.device.set_left_handed(left_handed); Ok(()) @@ -234,22 +244,18 @@ impl ConfigProxyHandler { &self, device: InputDevice, accel_profile: AccelProfile, - ) -> Result<(), SetAccelProfileError> { + ) -> Result<(), CphError> { let dev = self.get_device_handler_data(device)?; let profile = match accel_profile { ACCEL_PROFILE_FLAT => InputDeviceAccelProfile::Flat, ACCEL_PROFILE_ADAPTIVE => InputDeviceAccelProfile::Adaptive, - _ => return Err(SetAccelProfileError::UnknownAccelProfile(accel_profile)), + _ => return Err(CphError::UnknownAccelProfile(accel_profile)), }; dev.device.set_accel_profile(profile); Ok(()) } - fn handle_set_accel_speed( - &self, - device: InputDevice, - speed: f64, - ) -> Result<(), SetAccelSpeedError> { + fn handle_set_accel_speed(&self, device: InputDevice, speed: f64) -> Result<(), CphError> { let dev = self.get_device_handler_data(device)?; dev.device.set_accel_speed(speed); Ok(()) @@ -259,7 +265,7 @@ impl ConfigProxyHandler { &self, device: InputDevice, matrix: [[f64; 2]; 2], - ) -> Result<(), SetTransformMatrixError> { + ) -> Result<(), CphError> { let dev = self.get_device_handler_data(device)?; dev.device.set_transform_matrix(matrix); Ok(()) @@ -281,14 +287,14 @@ impl ConfigProxyHandler { }); } - fn handle_show_workspace(&self, seat: Seat, ws: Workspace) -> Result<(), ShowWorkspaceError> { + fn handle_show_workspace(&self, seat: Seat, ws: Workspace) -> Result<(), CphError> { let seat = self.get_seat(seat)?; let name = self.get_workspace(ws)?; self.state.show_workspace(&seat, &name); Ok(()) } - fn handle_get_device_name(&self, device: InputDevice) -> Result<(), GetDeviceNameError> { + fn handle_get_device_name(&self, device: InputDevice) -> Result<(), CphError> { let dev = self.get_device_handler_data(device)?; let name = dev.device.name(); self.respond(Response::GetDeviceName { @@ -297,11 +303,72 @@ impl ConfigProxyHandler { Ok(()) } - fn handle_has_capability( + fn handle_connector_connected(&self, connector: Connector) -> Result<(), CphError> { + let connector = self.get_connector(connector)?; + self.respond(Response::ConnectorConnected { + connected: connector.connected.get(), + }); + Ok(()) + } + + fn handle_connector_type(&self, connector: Connector) -> Result<(), CphError> { + let connector = self.get_connector(connector)?; + self.respond(Response::ConnectorType { + ty: connector.connector.kernel_id().ty.to_config(), + }); + Ok(()) + } + + fn handle_connector_mode(&self, connector: Connector) -> Result<(), CphError> { + let connector = self.get_connector(connector)?; + let mut mode = Mode::default(); + if let Some(node) = connector.node.get() { + mode = node.global.mode.get(); + } + self.respond(Response::ConnectorMode { + width: mode.width, + height: mode.height, + refresh_millihz: mode.refresh_rate_millihz, + }); + Ok(()) + } + + fn handle_connector_set_position( &self, - device: InputDevice, - cap: Capability, - ) -> Result<(), HasCapabilityError> { + connector: Connector, + x: i32, + y: i32, + ) -> Result<(), CphError> { + let connector = self.get_connector(connector)?; + if x < 0 || y < 0 || x > MAX_EXTENTS || y > MAX_EXTENTS { + return Err(CphError::InvalidConnectorPosition(x, y)); + } + if let Some(node) = connector.node.get() { + node.set_position(x, y); + } + Ok(()) + } + + fn handle_get_connector( + &self, + ty: jay_config::drm::connector_type::ConnectorType, + idx: u32, + ) -> Result<(), CphError> { + let connectors = self.state.connectors.lock(); + let connector = 'get_connector: { + for connector in connectors.values() { + let kid = connector.connector.kernel_id(); + if ty == kid.ty.to_config() && idx == kid.idx { + break 'get_connector Connector(connector.connector.id().raw() as _); + } + } + Connector(0) + }; + self.respond(Response::GetConnector { connector }); + Ok(()) + } + + fn handle_has_capability(&self, device: InputDevice, cap: Capability) -> Result<(), CphError> { let dev = self.get_device_handler_data(device)?; let mut is_unknown = false; let has_cap = 'has_cap: { @@ -322,13 +389,13 @@ impl ConfigProxyHandler { }; self.respond(Response::HasCapability { has: has_cap }); if is_unknown { - Err(HasCapabilityError::UnknownCapability(cap)) + Err(CphError::UnknownCapability(cap)) } else { Ok(()) } } - fn handle_get_mono(&self, seat: Seat) -> Result<(), GetMonoError> { + fn handle_get_mono(&self, seat: Seat) -> Result<(), CphError> { let seat = self.get_seat(seat)?; self.respond(Response::GetMono { mono: seat.get_mono().unwrap_or(false), @@ -336,13 +403,13 @@ impl ConfigProxyHandler { Ok(()) } - fn handle_set_mono(&self, seat: Seat, mono: bool) -> Result<(), SetMonoError> { + fn handle_set_mono(&self, seat: Seat, mono: bool) -> Result<(), CphError> { let seat = self.get_seat(seat)?; seat.set_mono(mono); Ok(()) } - fn handle_get_split(&self, seat: Seat) -> Result<(), GetSplitError> { + fn handle_get_split(&self, seat: Seat) -> Result<(), CphError> { let seat = self.get_seat(seat)?; self.respond(Response::GetSplit { axis: seat @@ -353,7 +420,7 @@ impl ConfigProxyHandler { Ok(()) } - fn handle_set_split(&self, seat: Seat, axis: Axis) -> Result<(), SetSplitError> { + fn handle_set_split(&self, seat: Seat, axis: Axis) -> Result<(), CphError> { let seat = self.get_seat(seat)?; seat.set_split(axis.into()); Ok(()) @@ -364,7 +431,7 @@ impl ConfigProxyHandler { seat: Seat, mods: Modifiers, sym: KeySym, - ) -> Result<(), AddShortcutError> { + ) -> Result<(), CphError> { let seat = self.get_seat(seat)?; seat.add_shortcut(mods, sym); Ok(()) @@ -375,7 +442,7 @@ impl ConfigProxyHandler { seat: Seat, mods: Modifiers, sym: KeySym, - ) -> Result<(), AddShortcutError> { + ) -> Result<(), CphError> { let seat = self.get_seat(seat)?; seat.remove_shortcut(mods, sym); Ok(()) @@ -421,16 +488,16 @@ impl ConfigProxyHandler { prog: &str, args: Vec, env: Vec<(String, String)>, - ) -> Result<(), RunError> { + ) -> Result<(), CphError> { let forker = match self.state.forker.get() { Some(f) => f, - _ => return Err(RunError::NoForker), + _ => return Err(CphError::NoForker), }; forker.spawn(prog.to_string(), args, env, None); Ok(()) } - fn handle_grab(&self, kb: InputDevice, grab: bool) -> Result<(), GrabError> { + fn handle_grab(&self, kb: InputDevice, grab: bool) -> Result<(), CphError> { let kb = self.get_kb(kb)?; kb.grab(grab); Ok(()) @@ -448,13 +515,13 @@ impl ConfigProxyHandler { }); } - fn handle_create_split(&self, seat: Seat, axis: Axis) -> Result<(), CreateSplitError> { + fn handle_create_split(&self, seat: Seat, axis: Axis) -> Result<(), CphError> { let seat = self.get_seat(seat)?; seat.create_split(axis.into()); Ok(()) } - fn handle_focus_parent(&self, seat: Seat) -> Result<(), FocusParentError> { + fn handle_focus_parent(&self, seat: Seat) -> Result<(), CphError> { let seat = self.get_seat(seat)?; seat.focus_parent(); Ok(()) @@ -472,7 +539,7 @@ impl ConfigProxyHandler { } } - fn handle_toggle_floating(&self, seat: Seat) -> Result<(), FocusParentError> { + fn handle_toggle_floating(&self, seat: Seat) -> Result<(), CphError> { let seat = self.get_seat(seat)?; seat.toggle_floating(); Ok(()) @@ -508,24 +575,24 @@ impl ConfigProxyHandler { self.state.root.clone().visit(&mut V); } - fn handle_set_title_height(&self, height: i32) -> Result<(), SetTitleHeightError> { + fn handle_set_title_height(&self, height: i32) -> Result<(), CphError> { if height < 0 { - return Err(SetTitleHeightError::Negative(height)); + return Err(CphError::NegativeTitleHeight(height)); } if height > 1000 { - return Err(SetTitleHeightError::Excessive(height)); + return Err(CphError::ExcessiveTitleHeight(height)); } self.state.theme.title_height.set(height); self.spaces_change(); Ok(()) } - fn handle_set_border_width(&self, width: i32) -> Result<(), SetBorderWidthError> { + fn handle_set_border_width(&self, width: i32) -> Result<(), CphError> { if width < 0 { - return Err(SetBorderWidthError::Negative(width)); + return Err(CphError::NegativeBorderWidth(width)); } if width > 1000 { - return Err(SetBorderWidthError::Excessive(width)); + return Err(CphError::ExcessiveBorderWidth(width)); } self.state.theme.border_width.set(width); self.spaces_change(); @@ -569,34 +636,54 @@ impl ConfigProxyHandler { line, } => self.handle_log_request(level, msg, file, line), ClientMessage::CreateSeat { name } => self.handle_create_seat(name), - ClientMessage::ParseKeymap { keymap } => self.handle_parse_keymap(keymap)?, + ClientMessage::ParseKeymap { keymap } => { + self.handle_parse_keymap(keymap).wrn("parse_keymap")? + } ClientMessage::SeatSetKeymap { seat, keymap } => { - self.handle_set_keymap(seat, keymap)? + self.handle_set_keymap(seat, keymap).wrn("set_keymap")? } - ClientMessage::SeatGetRepeatRate { seat } => self.handle_get_repeat_rate(seat)?, - ClientMessage::SeatSetRepeatRate { seat, rate, delay } => { - self.handle_set_repeat_rate(seat, rate, delay)? + ClientMessage::SeatGetRepeatRate { seat } => { + self.handle_get_repeat_rate(seat).wrn("get_repeat_rate")? } - ClientMessage::SetSeat { device, seat } => self.handle_set_seat(device, seat)?, - ClientMessage::GetMono { seat } => self.handle_get_mono(seat)?, - ClientMessage::SetMono { seat, mono } => self.handle_set_mono(seat, mono)?, - ClientMessage::GetSplit { seat } => self.handle_get_split(seat)?, - ClientMessage::SetSplit { seat, axis } => self.handle_set_split(seat, axis)?, - ClientMessage::AddShortcut { seat, mods, sym } => { - self.handle_add_shortcut(seat, mods, sym)? + ClientMessage::SeatSetRepeatRate { seat, rate, delay } => self + .handle_set_repeat_rate(seat, rate, delay) + .wrn("set_repeat_rate")?, + ClientMessage::SetSeat { device, seat } => { + self.handle_set_seat(device, seat).wrn("set_seat")? } - ClientMessage::RemoveShortcut { seat, mods, sym } => { - self.handle_remove_shortcut(seat, mods, sym)? + ClientMessage::GetMono { seat } => self.handle_get_mono(seat).wrn("get_mono")?, + ClientMessage::SetMono { seat, mono } => { + self.handle_set_mono(seat, mono).wrn("set_mono")? + } + ClientMessage::GetSplit { seat } => self.handle_get_split(seat).wrn("get_split")?, + ClientMessage::SetSplit { seat, axis } => { + self.handle_set_split(seat, axis).wrn("set_split")? + } + ClientMessage::AddShortcut { seat, mods, sym } => self + .handle_add_shortcut(seat, mods, sym) + .wrn("add_shortcut")?, + ClientMessage::RemoveShortcut { seat, mods, sym } => self + .handle_remove_shortcut(seat, mods, sym) + .wrn("remove_shortcut")?, + ClientMessage::Focus { seat, direction } => { + self.handle_focus(seat, direction).wrn("focus")? + } + ClientMessage::Move { seat, direction } => { + self.handle_move(seat, direction).wrn("move")? } - ClientMessage::Focus { seat, direction } => self.handle_focus(seat, direction)?, - ClientMessage::Move { seat, direction } => self.handle_move(seat, direction)?, ClientMessage::GetInputDevices { seat } => self.handle_get_input_devices(seat), ClientMessage::GetSeats => self.handle_get_seats(), ClientMessage::RemoveSeat { .. } => {} - ClientMessage::Run { prog, args, env } => self.handle_run(prog, args, env)?, - ClientMessage::GrabKb { kb, grab } => self.handle_grab(kb, grab)?, - ClientMessage::SetTitleHeight { height } => self.handle_set_title_height(height)?, - ClientMessage::SetBorderWidth { width } => self.handle_set_border_width(width)?, + ClientMessage::Run { prog, args, env } => { + self.handle_run(prog, args, env).wrn("run")? + } + ClientMessage::GrabKb { kb, grab } => self.handle_grab(kb, grab).wrn("grab")?, + ClientMessage::SetTitleHeight { height } => self + .handle_set_title_height(height) + .wrn("set_title_height")?, + ClientMessage::SetBorderWidth { width } => self + .handle_set_border_width(width) + .wrn("set_bordre_width")?, ClientMessage::SetTitleColor { color } => self.handle_set_title_color(color), ClientMessage::SetTitleUnderlineColor { color } => { self.handle_set_title_underline_color(color) @@ -605,32 +692,57 @@ impl ConfigProxyHandler { ClientMessage::SetBackgroundColor { color } => self.handle_set_background_color(color), ClientMessage::GetTitleHeight => self.handle_get_title_height(), ClientMessage::GetBorderWidth => self.handle_get_border_width(), - ClientMessage::CreateSplit { seat, axis } => self.handle_create_split(seat, axis)?, - ClientMessage::FocusParent { seat } => self.handle_focus_parent(seat)?, - ClientMessage::ToggleFloating { seat } => self.handle_toggle_floating(seat)?, + ClientMessage::CreateSplit { seat, axis } => { + self.handle_create_split(seat, axis).wrn("create_split")? + } + ClientMessage::FocusParent { seat } => { + self.handle_focus_parent(seat).wrn("focus_parent")? + } + ClientMessage::ToggleFloating { seat } => { + self.handle_toggle_floating(seat).wrn("toggle_floating")? + } ClientMessage::Quit => self.handle_quit(), ClientMessage::SwitchTo { vtnr } => self.handle_switch_to(vtnr), - ClientMessage::HasCapability { device, cap } => { - self.handle_has_capability(device, cap)? - } + ClientMessage::HasCapability { device, cap } => self + .handle_has_capability(device, cap) + .wrn("has_capability")?, ClientMessage::SetLeftHanded { device, left_handed, - } => self.handle_set_left_handed(device, left_handed)?, - ClientMessage::SetAccelProfile { device, profile } => { - self.handle_set_accel_profile(device, profile)? + } => self + .handle_set_left_handed(device, left_handed) + .wrn("set_left_handed")?, + ClientMessage::SetAccelProfile { device, profile } => self + .handle_set_accel_profile(device, profile) + .wrn("set_accel_profile")?, + ClientMessage::SetAccelSpeed { device, speed } => self + .handle_set_accel_speed(device, speed) + .wrn("set_accel_speed")?, + ClientMessage::SetTransformMatrix { device, matrix } => self + .handle_set_transform_matrix(device, matrix) + .wrn("set_transform_matrix")?, + ClientMessage::GetDeviceName { device } => { + self.handle_get_device_name(device).wrn("get_device_name")? } - ClientMessage::SetAccelSpeed { device, speed } => { - self.handle_set_accel_speed(device, speed)? - } - ClientMessage::SetTransformMatrix { device, matrix } => { - self.handle_set_transform_matrix(device, matrix)? - } - ClientMessage::GetDeviceName { device } => self.handle_get_device_name(device)?, ClientMessage::GetWorkspace { name } => self.handle_get_workspace(name), - ClientMessage::ShowWorkspace { seat, workspace } => { - self.handle_show_workspace(seat, workspace)? + ClientMessage::ShowWorkspace { seat, workspace } => self + .handle_show_workspace(seat, workspace) + .wrn("show_workspace")?, + ClientMessage::GetConnector { ty, idx } => { + self.handle_get_connector(ty, idx).wrn("get_connector")? } + ClientMessage::ConnectorConnected { connector } => self + .handle_connector_connected(connector) + .wrn("connector_connected")?, + ClientMessage::ConnectorType { connector } => self + .handle_connector_type(connector) + .wrn("connector_type")?, + ClientMessage::ConnectorMode { connector } => self + .handle_connector_mode(connector) + .wrn("connector_mode")?, + ClientMessage::ConnectorSetPosition { connector, x, y } => self + .handle_connector_set_position(connector, x, y) + .wrn("connector_set_position")?, } Ok(()) } @@ -638,63 +750,33 @@ impl ConfigProxyHandler { #[derive(Debug, Error)] enum CphError { - #[error("Could not process a `parse_keymap` request")] - ParseKeymapError(#[from] ParseKeymapError), - #[error("Could not process a `set_seat` request")] - SetSeatError(#[from] SetSeatError), - #[error("Could not process a `add_shortcut` request")] - AddShortcutError(#[from] AddShortcutError), - #[error("Could not process a `remove_shortcut` request")] - RemoveShortcutError(#[from] RemoveShortcutError), - #[error("Could not process a `set_keymap` request")] - SeatSetKeymapError(#[from] SeatSetKeymapError), - #[error("Could not process a `get_repeat_rate` request")] - SeatGetRepeatRateError(#[from] SeatGetRepeatRateError), - #[error("Could not process a `set_repeat_rate` request")] - SeatSetRepeatRateError(#[from] SeatSetRepeatRateError), - #[error("Could not process a `focus` request")] - FocusError(#[from] FocusError), - #[error("Could not process a `move` request")] - MoveError(#[from] MoveError), - #[error("Could not process a `set_mono` request")] - SetMonoError(#[from] SetMonoError), - #[error("Could not process a `get_mono` request")] - GetMonoError(#[from] GetMonoError), - #[error("Could not process a `set_split` request")] - SetSplitError(#[from] SetSplitError), - #[error("Could not process a `get_split` request")] - GetSplitError(#[from] GetSplitError), - #[error("Could not process a `run` request")] - RunError(#[from] RunError), - #[error("Could not process a `grab` request")] - GrabError(#[from] GrabError), - #[error("Could not process a `create_split` request")] - CreateSplitError(#[from] CreateSplitError), - #[error("Could not process a `focus_parent` request")] - FocusParentError(#[from] FocusParentError), - #[error("Could not process a `toggle_floating` request")] - ToggleFloatingError(#[from] ToggleFloatingError), - #[error("Could not process a `set_title_height` request")] - SetTitleHeightError(#[from] SetTitleHeightError), - #[error("Could not process a `set_border_width` request")] - SetBorderWidthError(#[from] SetBorderWidthError), - #[error("Could not process a `has_capability` request")] - HasCapabilityError(#[from] HasCapabilityError), - #[error("Could not process a `set_left_handed` request")] - SetLeftHandedError(#[from] SetLeftHandedError), - #[error("Could not process a `set_accel_profile` request")] - SetAccelProfileError(#[from] SetAccelProfileError), - #[error("Could not process a `set_accel_speed` request")] - SetAccelSpeedError(#[from] SetAccelSpeedError), - #[error("Could not process a `set_transform_matrix` request")] - SetTransformMatrixError(#[from] SetTransformMatrixError), - #[error("Could not process a `get_device_name` request")] - GetDeviceNameError(#[from] GetDeviceNameError), - #[error("Could not process a `show_workspace` request")] - ShowWorkspaceError(#[from] ShowWorkspaceError), + #[error("Tried to set an unknown accel profile: {}", (.0).0)] + UnknownAccelProfile(AccelProfile), + #[error("Queried unknown capability: {}", (.0).0)] + UnknownCapability(Capability), + #[error("The height {0} is negative")] + NegativeTitleHeight(i32), + #[error("The height {0} is larger than the maximum 1000")] + ExcessiveTitleHeight(i32), + #[error("The width {0} is negative")] + NegativeBorderWidth(i32), + #[error("The width {0} is larger than the maximum 1000")] + ExcessiveBorderWidth(i32), + #[error("The ol' forker is not available")] + NoForker, + #[error("Repeat rate is negative")] + NegativeRepeatRate, + #[error("Repeat delay is negative")] + NegativeRepeatDelay, + #[error("Parsing failed")] + ParseKeymapError(#[from] XkbCommonError), #[error("Device {0:?} does not exist")] DeviceDoesNotExist(InputDevice), - #[error("Device {0:?} does not exist")] + #[error("Connector {0:?} does not exist")] + ConnectorDoesNotExist(Connector), + #[error("{0}x{1} is not a valid connector position")] + InvalidConnectorPosition(i32, i32), + #[error("Keymap {0:?} does not exist")] KeymapDoesNotExist(Keymap), #[error("Seat {0:?} does not exist")] SeatDoesNotExist(Seat), @@ -704,201 +786,16 @@ enum CphError { KeyboardDoesNotExist(InputDevice), #[error("Could not parse the message")] ParsingFailed(#[source] DecodeError), + #[error("Could not process a `{0}` request")] + FailedRequest(&'static str, #[source] Box), } -#[derive(Debug, Error)] -enum ParseKeymapError { - #[error("Parsing failed")] - ParsingFailed, +trait WithRequestName { + fn wrn(self, request: &'static str) -> Result<(), CphError>; } -#[derive(Debug, Error)] -enum SetSeatError { - #[error(transparent)] - CphError(#[from] Box), +impl WithRequestName for Result<(), CphError> { + fn wrn(self, request: &'static str) -> Result<(), CphError> { + self.map_err(move |e| CphError::FailedRequest(request, Box::new(e))) + } } -efrom!(SetSeatError, CphError); - -#[derive(Debug, Error)] -enum SetLeftHandedError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(SetLeftHandedError, CphError); - -#[derive(Debug, Error)] -enum SetAccelProfileError { - #[error(transparent)] - CphError(#[from] Box), - #[error("Tried to set an unknown accel profile: {}", (.0).0)] - UnknownAccelProfile(AccelProfile), -} -efrom!(SetAccelProfileError, CphError); - -#[derive(Debug, Error)] -enum SetAccelSpeedError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(SetAccelSpeedError, CphError); - -#[derive(Debug, Error)] -enum SetTransformMatrixError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(SetTransformMatrixError, CphError); - -#[derive(Debug, Error)] -enum GetDeviceNameError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(GetDeviceNameError, CphError); - -#[derive(Debug, Error)] -enum ShowWorkspaceError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(ShowWorkspaceError, CphError); - -#[derive(Debug, Error)] -enum HasCapabilityError { - #[error(transparent)] - CphError(#[from] Box), - #[error("Queried unknown capability: {}", (.0).0)] - UnknownCapability(Capability), -} -efrom!(HasCapabilityError, CphError); - -#[derive(Debug, Error)] -enum AddShortcutError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(AddShortcutError, CphError); - -#[derive(Debug, Error)] -enum RemoveShortcutError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(RemoveShortcutError, CphError); - -#[derive(Debug, Error)] -enum SeatSetKeymapError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(SeatSetKeymapError, CphError); - -#[derive(Debug, Error)] -enum SeatSetRepeatRateError { - #[error(transparent)] - CphError(#[from] Box), - #[error("Rate is negative")] - NegativeRate, - #[error("Delay is negative")] - NegativeDelay, -} -efrom!(SeatSetRepeatRateError, CphError); - -#[derive(Debug, Error)] -enum SeatGetRepeatRateError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(SeatGetRepeatRateError, CphError); - -#[derive(Debug, Error)] -enum FocusError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(FocusError, CphError); - -#[derive(Debug, Error)] -enum MoveError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(MoveError, CphError); - -#[derive(Debug, Error)] -enum SetMonoError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(SetMonoError, CphError); - -#[derive(Debug, Error)] -enum GetMonoError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(GetMonoError, CphError); - -#[derive(Debug, Error)] -enum SetSplitError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(SetSplitError, CphError); - -#[derive(Debug, Error)] -enum GetSplitError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(GetSplitError, CphError); - -#[derive(Debug, Error)] -enum RunError { - #[error("The ol' forker is not available")] - NoForker, -} - -#[derive(Debug, Error)] -enum GrabError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(GrabError, CphError); - -#[derive(Debug, Error)] -enum SetTitleHeightError { - #[error("The height {0} is negative")] - Negative(i32), - #[error("The height {0} is larger than the maximum 1000")] - Excessive(i32), -} - -#[derive(Debug, Error)] -enum SetBorderWidthError { - #[error("The width {0} is negative")] - Negative(i32), - #[error("The width {0} is larger than the maximum 1000")] - Excessive(i32), -} - -#[derive(Debug, Error)] -enum CreateSplitError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(CreateSplitError, CphError); - -#[derive(Debug, Error)] -enum FocusParentError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(FocusParentError, CphError); - -#[derive(Debug, Error)] -enum ToggleFloatingError { - #[error(transparent)] - CphError(#[from] Box), -} -efrom!(ToggleFloatingError, CphError); diff --git a/src/drm/drm.rs b/src/drm/drm.rs index c23db579..f30a8d5e 100644 --- a/src/drm/drm.rs +++ b/src/drm/drm.rs @@ -23,6 +23,7 @@ use std::rc::{Rc, Weak}; use thiserror::Error; use uapi::{c, Errno, OwnedFd, Pod, Ustring}; +use crate::backend; use crate::drm::dma::DmaBuf; use crate::drm::INVALID_MODIFIER; use crate::utils::errorfmt::ErrorFmt; @@ -33,7 +34,6 @@ pub use sys::{ drm_mode_modeinfo, DRM_CLIENT_CAP_ATOMIC, DRM_MODE_ATOMIC_ALLOW_MODESET, DRM_MODE_ATOMIC_NONBLOCK, DRM_MODE_PAGE_FLIP_EVENT, }; -use crate::backend; #[derive(Debug, Error)] pub enum DrmError { @@ -737,6 +737,90 @@ pub enum ConnectorType { EmbeddedWindow, } +impl ConnectorType { + pub fn from_drm(v: u32) -> Self { + match v { + sys::DRM_MODE_CONNECTOR_VGA => Self::VGA, + sys::DRM_MODE_CONNECTOR_DVII => Self::DVII, + sys::DRM_MODE_CONNECTOR_DVID => Self::DVID, + sys::DRM_MODE_CONNECTOR_DVIA => Self::DVIA, + sys::DRM_MODE_CONNECTOR_Composite => Self::Composite, + sys::DRM_MODE_CONNECTOR_SVIDEO => Self::SVIDEO, + sys::DRM_MODE_CONNECTOR_LVDS => Self::LVDS, + sys::DRM_MODE_CONNECTOR_Component => Self::Component, + sys::DRM_MODE_CONNECTOR_9PinDIN => Self::_9PinDIN, + sys::DRM_MODE_CONNECTOR_DisplayPort => Self::DisplayPort, + sys::DRM_MODE_CONNECTOR_HDMIA => Self::HDMIA, + sys::DRM_MODE_CONNECTOR_HDMIB => Self::HDMIB, + sys::DRM_MODE_CONNECTOR_TV => Self::TV, + sys::DRM_MODE_CONNECTOR_eDP => Self::eDP, + sys::DRM_MODE_CONNECTOR_VIRTUAL => Self::VIRTUAL, + sys::DRM_MODE_CONNECTOR_DSI => Self::DSI, + sys::DRM_MODE_CONNECTOR_DPI => Self::DPI, + sys::DRM_MODE_CONNECTOR_WRITEBACK => Self::WRITEBACK, + sys::DRM_MODE_CONNECTOR_SPI => Self::SPI, + sys::DRM_MODE_CONNECTOR_USB => Self::USB, + _ => Self::Unknown(v), + } + } + + #[allow(dead_code)] + pub fn to_drm(self) -> u32 { + match self { + Self::Unknown(n) => n, + Self::VGA => sys::DRM_MODE_CONNECTOR_VGA, + Self::DVII => sys::DRM_MODE_CONNECTOR_DVII, + Self::DVID => sys::DRM_MODE_CONNECTOR_DVID, + Self::DVIA => sys::DRM_MODE_CONNECTOR_DVIA, + Self::Composite => sys::DRM_MODE_CONNECTOR_Composite, + Self::SVIDEO => sys::DRM_MODE_CONNECTOR_SVIDEO, + Self::LVDS => sys::DRM_MODE_CONNECTOR_LVDS, + Self::Component => sys::DRM_MODE_CONNECTOR_Component, + Self::_9PinDIN => sys::DRM_MODE_CONNECTOR_9PinDIN, + Self::DisplayPort => sys::DRM_MODE_CONNECTOR_DisplayPort, + Self::HDMIA => sys::DRM_MODE_CONNECTOR_HDMIA, + Self::HDMIB => sys::DRM_MODE_CONNECTOR_HDMIB, + Self::TV => sys::DRM_MODE_CONNECTOR_TV, + Self::eDP => sys::DRM_MODE_CONNECTOR_eDP, + Self::VIRTUAL => sys::DRM_MODE_CONNECTOR_VIRTUAL, + Self::DSI => sys::DRM_MODE_CONNECTOR_DSI, + Self::DPI => sys::DRM_MODE_CONNECTOR_DPI, + Self::WRITEBACK => sys::DRM_MODE_CONNECTOR_WRITEBACK, + Self::SPI => sys::DRM_MODE_CONNECTOR_SPI, + Self::USB => sys::DRM_MODE_CONNECTOR_USB, + Self::EmbeddedWindow => sys::DRM_MODE_CONNECTOR_Unknown, + } + } + + pub fn to_config(self) -> jay_config::drm::connector_type::ConnectorType { + use jay_config::drm::connector_type::*; + match self { + Self::Unknown(_) => CON_UNKNOWN, + Self::VGA => CON_VGA, + Self::DVII => CON_DVII, + Self::DVID => CON_DVID, + Self::DVIA => CON_DVIA, + Self::Composite => CON_COMPOSITE, + Self::SVIDEO => CON_SVIDEO, + Self::LVDS => CON_LVDS, + Self::Component => CON_COMPONENT, + Self::_9PinDIN => CON_9PIN_DIN, + Self::DisplayPort => CON_DISPLAY_PORT, + Self::HDMIA => CON_HDMIA, + Self::HDMIB => CON_HDMIB, + Self::TV => CON_TV, + Self::eDP => CON_EDP, + Self::VIRTUAL => CON_VIRTUAL, + Self::DSI => CON_DSI, + Self::DPI => CON_DPI, + Self::WRITEBACK => CON_WRITEBACK, + Self::SPI => CON_SPI, + Self::USB => CON_USB, + Self::EmbeddedWindow => CON_EMBEDDED_WINDOW, + } + } +} + impl Display for ConnectorType { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let s = match self { @@ -767,63 +851,6 @@ impl Display for ConnectorType { } } -impl From for ConnectorType { - fn from(v: u32) -> Self { - match v { - sys::DRM_MODE_CONNECTOR_VGA => Self::VGA, - sys::DRM_MODE_CONNECTOR_DVII => Self::DVII, - sys::DRM_MODE_CONNECTOR_DVID => Self::DVID, - sys::DRM_MODE_CONNECTOR_DVIA => Self::DVIA, - sys::DRM_MODE_CONNECTOR_Composite => Self::Composite, - sys::DRM_MODE_CONNECTOR_SVIDEO => Self::SVIDEO, - sys::DRM_MODE_CONNECTOR_LVDS => Self::LVDS, - sys::DRM_MODE_CONNECTOR_Component => Self::Component, - sys::DRM_MODE_CONNECTOR_9PinDIN => Self::_9PinDIN, - sys::DRM_MODE_CONNECTOR_DisplayPort => Self::DisplayPort, - sys::DRM_MODE_CONNECTOR_HDMIA => Self::HDMIA, - sys::DRM_MODE_CONNECTOR_HDMIB => Self::HDMIB, - sys::DRM_MODE_CONNECTOR_TV => Self::TV, - sys::DRM_MODE_CONNECTOR_eDP => Self::eDP, - sys::DRM_MODE_CONNECTOR_VIRTUAL => Self::VIRTUAL, - sys::DRM_MODE_CONNECTOR_DSI => Self::DSI, - sys::DRM_MODE_CONNECTOR_DPI => Self::DPI, - sys::DRM_MODE_CONNECTOR_WRITEBACK => Self::WRITEBACK, - sys::DRM_MODE_CONNECTOR_SPI => Self::SPI, - sys::DRM_MODE_CONNECTOR_USB => Self::USB, - _ => Self::Unknown(v), - } - } -} - -impl Into for ConnectorType { - fn into(self) -> u32 { - match self { - Self::Unknown(n) => n, - Self::VGA => sys::DRM_MODE_CONNECTOR_VGA, - Self::DVII => sys::DRM_MODE_CONNECTOR_DVII, - Self::DVID => sys::DRM_MODE_CONNECTOR_DVID, - Self::DVIA => sys::DRM_MODE_CONNECTOR_DVIA, - Self::Composite => sys::DRM_MODE_CONNECTOR_Composite, - Self::SVIDEO => sys::DRM_MODE_CONNECTOR_SVIDEO, - Self::LVDS => sys::DRM_MODE_CONNECTOR_LVDS, - Self::Component => sys::DRM_MODE_CONNECTOR_Component, - Self::_9PinDIN => sys::DRM_MODE_CONNECTOR_9PinDIN, - Self::DisplayPort => sys::DRM_MODE_CONNECTOR_DisplayPort, - Self::HDMIA => sys::DRM_MODE_CONNECTOR_HDMIA, - Self::HDMIB => sys::DRM_MODE_CONNECTOR_HDMIB, - Self::TV => sys::DRM_MODE_CONNECTOR_TV, - Self::eDP => sys::DRM_MODE_CONNECTOR_eDP, - Self::VIRTUAL => sys::DRM_MODE_CONNECTOR_VIRTUAL, - Self::DSI => sys::DRM_MODE_CONNECTOR_DSI, - Self::DPI => sys::DRM_MODE_CONNECTOR_DPI, - Self::WRITEBACK => sys::DRM_MODE_CONNECTOR_WRITEBACK, - Self::SPI => sys::DRM_MODE_CONNECTOR_SPI, - Self::USB => sys::DRM_MODE_CONNECTOR_USB, - Self::EmbeddedWindow => sys::DRM_MODE_CONNECTOR_Unknown, - } - } -} - #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum ConnectorStatus { Connected, @@ -832,8 +859,8 @@ pub enum ConnectorStatus { Other(u32), } -impl From for ConnectorStatus { - fn from(v: u32) -> Self { +impl ConnectorStatus { + pub fn from_drm(v: u32) -> Self { match v { sys::CONNECTOR_STATUS_CONNECTED => Self::Connected, sys::CONNECTOR_STATUS_DISCONNECTED => Self::Disconnected, diff --git a/src/event_loop.rs b/src/event_loop.rs index 78777032..436b4034 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -1,3 +1,4 @@ +use crate::utils::clonecell::UnsafeCellCloneSafe; use crate::utils::copyhashmap::CopyHashMap; use crate::utils::numcell::NumCell; use std::cell::{Cell, RefCell}; @@ -43,6 +44,8 @@ struct Entry { dispatcher: Rc, } +unsafe impl UnsafeCellCloneSafe for Entry {} + pub struct EventLoop { destroyed: Cell, epoll: OwnedFd, diff --git a/src/globals.rs b/src/globals.rs index 27d99b02..b4ebaefb 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -17,10 +17,8 @@ use crate::ifs::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1Global; use crate::ifs::zxdg_output_manager_v1::ZxdgOutputManagerV1Global; use crate::object::{Interface, ObjectId}; use crate::state::State; -use crate::utils::copyhashmap::CopyHashMap; +use crate::utils::copyhashmap::{CopyHashMap, Locked}; use crate::utils::numcell::NumCell; -use ahash::AHashMap; -use std::cell::RefMut; use std::error::Error; use std::fmt::{Display, Formatter}; use std::rc::Rc; @@ -153,7 +151,7 @@ impl Globals { Ok(()) } - pub fn lock_seats(&self) -> RefMut>> { + pub fn lock_seats(&self) -> Locked> { self.seats.lock() } diff --git a/src/ifs/wl_output.rs b/src/ifs/wl_output.rs index eeb1ea1b..f54572f6 100644 --- a/src/ifs/wl_output.rs +++ b/src/ifs/wl_output.rs @@ -192,7 +192,6 @@ impl WlOutput { fn send_mode(&self) { let mode = self.global.mode.get(); - let pos = self.global.pos.get(); let event = Mode { self_id: self.id, flags: MODE_CURRENT, diff --git a/src/state.rs b/src/state.rs index 8a91a5cf..ab8adcc1 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,5 +1,8 @@ use crate::async_engine::{AsyncEngine, SpawnedFuture}; -use crate::backend::{Backend, BackendEvent, Connector, ConnectorId, ConnectorIds, InputDevice, InputDeviceId, InputDeviceIds, MonitorInfo}; +use crate::backend::{ + Backend, BackendEvent, Connector, ConnectorId, ConnectorIds, InputDevice, InputDeviceId, + InputDeviceIds, MonitorInfo, +}; use crate::client::{Client, Clients}; use crate::config::ConfigProxy; use crate::cursor::ServerCursors; @@ -83,6 +86,7 @@ pub struct ConnectorData { pub monitor_info: CloneCell>>, pub handler: Cell>>, pub node: CloneCell>>, + pub connected: Cell, } impl State { diff --git a/src/tasks/backend.rs b/src/tasks/backend.rs index c7ce0943..afbdd379 100644 --- a/src/tasks/backend.rs +++ b/src/tasks/backend.rs @@ -1,4 +1,4 @@ -use crate::backend::{BackendEvent}; +use crate::backend::BackendEvent; use crate::state::State; use crate::tasks::{connector, input_device}; use std::rc::Rc; diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index 82ae4c9e..3a0b751e 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -5,7 +5,7 @@ use crate::state::{ConnectorData, State}; use crate::tree::{OutputNode, OutputRenderData}; use crate::utils::asyncevent::AsyncEvent; use crate::utils::clonecell::CloneCell; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::rc::Rc; pub fn handle(state: &Rc, connector: &Rc) { @@ -15,6 +15,7 @@ pub fn handle(state: &Rc, connector: &Rc) { monitor_info: Default::default(), handler: Default::default(), node: Default::default(), + connected: Cell::new(false), }); let oh = ConnectorHandler { id, @@ -60,7 +61,12 @@ impl ConnectorHandler { } async fn handle_connected(&self, ae: &Rc, info: MonitorInfo) { - log::info!("Connector {} connected: {:#?}", self.data.connector.kernel_id(), info); + log::info!( + "Connector {} connected: {:#?}", + self.data.connector.kernel_id(), + info + ); + self.data.connected.set(true); self.data.monitor_info.set(Some(Rc::new(info.clone()))); let name = self.state.globals.name(); let x1 = self @@ -124,5 +130,6 @@ impl ConnectorHandler { global.node.set(None); let _ = self.state.remove_global(&*global); self.state.root.outputs.remove(&self.id); + self.data.connected.set(false); } } diff --git a/src/tree/output.rs b/src/tree/output.rs index 35f8c4ed..8e7dc4d0 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -126,13 +126,27 @@ impl OutputNode { .unwrap() } + pub fn set_position(&self, x: i32, y: i32) { + let pos = self.global.pos.get(); + if (pos.x1(), pos.y1()) == (x, y) { + return; + } + let rect = pos.at_point(x, y); + self.change_extents_(&rect); + } + pub fn update_mode(&self, mode: Mode) { if self.global.mode.get() == mode { return; } + self.global.mode.set(mode); let pos = self.global.pos.get(); let rect = Rect::new_sized(pos.x1(), pos.y1(), mode.width, mode.height).unwrap(); - self.global.pos.set(rect); + self.change_extents_(&rect); + } + + fn change_extents_(&self, rect: &Rect) { + self.global.pos.set(*rect); if let Some(c) = self.workspace.get() { c.change_extents(&self.workspace_rect()); } diff --git a/src/utils/clonecell.rs b/src/utils/clonecell.rs index 442175b9..7d935136 100644 --- a/src/utils/clonecell.rs +++ b/src/utils/clonecell.rs @@ -1,5 +1,6 @@ use crate::utils::linkedlist::NodeRef; use crate::utils::ptr_ext::{MutPtrExt, PtrExt}; +use jay_config::keyboard::mods::Modifiers; use std::cell::UnsafeCell; use std::fmt::{Debug, Formatter}; use std::mem; @@ -65,3 +66,6 @@ unsafe impl UnsafeCellCloneSafe for Weak {} unsafe impl UnsafeCellCloneSafe for NodeRef {} unsafe impl UnsafeCellCloneSafe for () {} +unsafe impl UnsafeCellCloneSafe for u64 {} + +unsafe impl UnsafeCellCloneSafe for Modifiers {} diff --git a/src/utils/copyhashmap.rs b/src/utils/copyhashmap.rs index d55ee385..c32c281c 100644 --- a/src/utils/copyhashmap.rs +++ b/src/utils/copyhashmap.rs @@ -1,12 +1,15 @@ +use crate::utils::clonecell::UnsafeCellCloneSafe; +use crate::utils::ptr_ext::{MutPtrExt, PtrExt}; use ahash::AHashMap; use std::borrow::Borrow; -use std::cell::{RefCell, RefMut}; +use std::cell::UnsafeCell; use std::fmt::{Debug, Formatter}; use std::hash::Hash; use std::mem; +use std::ops::{Deref, DerefMut}; pub struct CopyHashMap { - map: RefCell>, + map: UnsafeCell>, } impl Debug for CopyHashMap { @@ -29,20 +32,22 @@ impl CopyHashMap { } pub fn set(&self, k: K, v: V) { - self.map.borrow_mut().insert(k, v); + unsafe { + self.map.get().deref_mut().insert(k, v); + } } pub fn get(&self, k: &Q) -> Option where - V: Clone, + V: UnsafeCellCloneSafe, Q: Hash + Eq, K: Borrow, { - self.map.borrow_mut().get(k).cloned() + unsafe { self.map.get().deref().get(k).cloned() } } pub fn remove(&self, k: &K) -> Option { - self.map.borrow_mut().remove(k) + unsafe { self.map.get().deref_mut().remove(k) } } pub fn contains(&self, k: &Q) -> bool @@ -50,18 +55,48 @@ impl CopyHashMap { Q: Hash + Eq, K: Borrow, { - self.map.borrow_mut().contains_key(k) + unsafe { self.map.get().deref().contains_key(k) } } - pub fn lock(&self) -> RefMut> { - self.map.borrow_mut() + pub fn lock(&self) -> Locked { + Locked { + source: self, + map: self.clear(), + } } - pub fn clear(&self) { - mem::take(&mut *self.map.borrow_mut()); + pub fn clear(&self) -> AHashMap { + unsafe { mem::take(self.map.get().deref_mut()) } } pub fn is_empty(&self) -> bool { - self.map.borrow_mut().is_empty() + unsafe { self.map.get().deref().is_empty() } + } +} + +pub struct Locked<'a, K, V> { + source: &'a CopyHashMap, + map: AHashMap, +} + +impl<'a, K, V> Drop for Locked<'a, K, V> { + fn drop(&mut self) { + unsafe { + mem::swap(&mut self.map, self.source.map.get().deref_mut()); + } + } +} + +impl<'a, K, V> Deref for Locked<'a, K, V> { + type Target = AHashMap; + + fn deref(&self) -> &Self::Target { + &self.map + } +} + +impl<'a, K, V> DerefMut for Locked<'a, K, V> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.map } } diff --git a/src/utils/debug_fn.rs b/src/utils/debug_fn.rs index 58c808a5..7f09a9f3 100644 --- a/src/utils/debug_fn.rs +++ b/src/utils/debug_fn.rs @@ -1,17 +1,26 @@ -use std::fmt::{Debug, Formatter}; +use std::fmt::{Debug, Display, Formatter}; -pub fn debug_fn(f: F) -> impl Debug +pub fn debug_fn(f: F) -> Printable where F: Fn(&mut Formatter<'_>) -> std::fmt::Result, { - DebugFn { f } + Printable { f } } -struct DebugFn { +pub struct Printable { f: F, } -impl Debug for DebugFn +impl Debug for Printable +where + F: Fn(&mut Formatter<'_>) -> std::fmt::Result, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + (self.f)(f) + } +} + +impl Display for Printable where F: Fn(&mut Formatter<'_>) -> std::fmt::Result, {