autocommit 2022-02-17 19:12:52 CET
This commit is contained in:
parent
cf322f05be
commit
195a92d98b
29 changed files with 610 additions and 175 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
|
@ -153,6 +153,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"i4config",
|
"i4config",
|
||||||
"log",
|
"log",
|
||||||
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -474,14 +475,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.4"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha",
|
"rand_chacha",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"rand_hc",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -503,15 +503,6 @@ dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_hc"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.5.4"
|
version = "1.5.4"
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,4 @@ crate-type = ["lib", "cdylib"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
i4config = { path = "../i4config" }
|
i4config = { path = "../i4config" }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
|
rand = "0.8.5"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
use i4config::keyboard::mods::{Modifiers, ALT, CTRL, SHIFT};
|
|
||||||
use i4config::keyboard::syms::{SYM_h, SYM_j, SYM_k, SYM_l, SYM_r, SYM_t, SYM_y, SYM_b, SYM_Super_L};
|
|
||||||
use i4config::Direction::{Down, Left, Right, Up};
|
|
||||||
use i4config::{config, create_seat, input_devices, on_new_input_device, Command, Seat, InputDevice};
|
|
||||||
use i4config::embedded::grab_keyboard;
|
use i4config::embedded::grab_keyboard;
|
||||||
|
use i4config::keyboard::mods::{Modifiers, ALT, CTRL, SHIFT};
|
||||||
|
use i4config::keyboard::syms::{SYM_Super_L, SYM_b, SYM_comma, SYM_h, SYM_j, SYM_k, SYM_l, SYM_period, SYM_r, SYM_t, SYM_y, SYM_d, SYM_v};
|
||||||
|
use i4config::theme::{get_title_height, set_title_color, set_title_height, Color};
|
||||||
|
use i4config::Direction::{Down, Left, Right, Up};
|
||||||
|
use i4config::{
|
||||||
|
config, create_seat, input_devices, on_new_input_device, Command, InputDevice, Seat,
|
||||||
|
};
|
||||||
|
use rand::Rng;
|
||||||
|
use i4config::Axis::{Horizontal, Vertical};
|
||||||
|
|
||||||
const MOD: Modifiers = ALT;
|
const MOD: Modifiers = ALT;
|
||||||
|
|
||||||
|
|
@ -20,11 +25,28 @@ fn configure_seat(s: Seat) {
|
||||||
s.bind(CTRL | SHIFT | SYM_l, move || change_rate(-1));
|
s.bind(CTRL | SHIFT | SYM_l, move || change_rate(-1));
|
||||||
s.bind(CTRL | SHIFT | SYM_r, move || change_rate(1));
|
s.bind(CTRL | SHIFT | SYM_r, move || change_rate(1));
|
||||||
|
|
||||||
|
s.bind(MOD | SYM_comma, move || {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
set_title_color(Color {
|
||||||
|
r: rng.gen(),
|
||||||
|
g: rng.gen(),
|
||||||
|
b: rng.gen(),
|
||||||
|
a: rng.gen(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
s.bind(MOD | SYM_period, move || {
|
||||||
|
set_title_height(get_title_height() + 1)
|
||||||
|
});
|
||||||
|
|
||||||
s.bind(MOD | SYM_h, move || s.focus(Left));
|
s.bind(MOD | SYM_h, move || s.focus(Left));
|
||||||
s.bind(MOD | SYM_j, move || s.focus(Down));
|
s.bind(MOD | SYM_j, move || s.focus(Down));
|
||||||
s.bind(MOD | SYM_k, move || s.focus(Up));
|
s.bind(MOD | SYM_k, move || s.focus(Up));
|
||||||
s.bind(MOD | SYM_l, move || s.focus(Right));
|
s.bind(MOD | SYM_l, move || s.focus(Right));
|
||||||
|
|
||||||
|
s.bind(MOD | SYM_d, move || s.create_split(Horizontal));
|
||||||
|
s.bind(MOD | SYM_v, move || s.create_split(Vertical));
|
||||||
|
|
||||||
s.bind(MOD | SYM_t, move || {
|
s.bind(MOD | SYM_t, move || {
|
||||||
s.set_split(s.split().other());
|
s.set_split(s.split().other());
|
||||||
});
|
});
|
||||||
|
|
@ -39,7 +61,11 @@ fn configure_seat(s: Seat) {
|
||||||
fn do_grab(s: Seat, grab: bool) {
|
fn do_grab(s: Seat, grab: bool) {
|
||||||
for device in s.input_devices() {
|
for device in s.input_devices() {
|
||||||
if let InputDevice::Keyboard(kb) = device {
|
if let InputDevice::Keyboard(kb) = device {
|
||||||
log::info!("{}rabbing keyboard {:?}", if grab { "G" } else { "Ung" }, kb.0);
|
log::info!(
|
||||||
|
"{}rabbing keyboard {:?}",
|
||||||
|
if grab { "G" } else { "Ung" },
|
||||||
|
kb.0
|
||||||
|
);
|
||||||
grab_keyboard(kb, grab);
|
grab_keyboard(kb, grab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::_private::ipc::{ClientMessage, InitMessage, Response, ServerMessage};
|
use crate::_private::ipc::{ClientMessage, InitMessage, Response, ServerMessage};
|
||||||
use crate::_private::{bincode_ops, logging, Config, ConfigEntry, ConfigEntryGen, VERSION};
|
use crate::_private::{bincode_ops, logging, Config, ConfigEntry, ConfigEntryGen, VERSION};
|
||||||
use crate::keyboard::keymap::Keymap;
|
use crate::keyboard::keymap::Keymap;
|
||||||
|
use crate::theme::Color;
|
||||||
use crate::{Axis, Command, Direction, InputDevice, Keyboard, LogLevel, ModifiedKeySym, Seat};
|
use crate::{Axis, Command, Direction, InputDevice, Keyboard, LogLevel, ModifiedKeySym, Seat};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
|
|
@ -195,10 +196,60 @@ impl Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_title_color(&self, color: Color) {
|
||||||
|
self.send(&ClientMessage::SetTitleColor { color });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_border_color(&self, color: Color) {
|
||||||
|
self.send(&ClientMessage::SetBorderColor { color });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_title_underline_color(&self, color: Color) {
|
||||||
|
self.send(&ClientMessage::SetTitleUnderlineColor { color });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_background_color(&self, color: Color) {
|
||||||
|
self.send(&ClientMessage::SetBackgroundColor { color });
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_title_height(&self, height: i32) {
|
||||||
|
self.send(&ClientMessage::SetTitleHeight { height })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_border_width(&self, width: i32) {
|
||||||
|
self.send(&ClientMessage::SetBorderWidth { width })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_split(&self, seat: Seat, axis: Axis) {
|
pub fn set_split(&self, seat: Seat, axis: Axis) {
|
||||||
self.send(&ClientMessage::SetSplit { seat, axis });
|
self.send(&ClientMessage::SetSplit { seat, axis });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_split(&self, seat: Seat, axis: Axis) {
|
||||||
|
self.send(&ClientMessage::CreateSplit { seat, axis });
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_seat(&self, name: &str) -> Seat {
|
pub fn create_seat(&self, name: &str) -> Seat {
|
||||||
let response = self.with_response(|| self.send(&ClientMessage::CreateSeat { name }));
|
let response = self.with_response(|| self.send(&ClientMessage::CreateSeat { name }));
|
||||||
match response {
|
match response {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::keyboard::keymap::Keymap;
|
use crate::keyboard::keymap::Keymap;
|
||||||
use crate::keyboard::mods::Modifiers;
|
use crate::keyboard::mods::Modifiers;
|
||||||
use crate::keyboard::syms::KeySym;
|
use crate::keyboard::syms::KeySym;
|
||||||
|
use crate::theme::Color;
|
||||||
use crate::{Axis, Direction, InputDevice, Keyboard, LogLevel, Seat};
|
use crate::{Axis, Direction, InputDevice, Keyboard, LogLevel, Seat};
|
||||||
use bincode::{BorrowDecode, Decode, Encode};
|
use bincode::{BorrowDecode, Decode, Encode};
|
||||||
|
|
||||||
|
|
@ -94,6 +95,30 @@ pub enum ClientMessage<'a> {
|
||||||
kb: Keyboard,
|
kb: Keyboard,
|
||||||
grab: bool,
|
grab: bool,
|
||||||
},
|
},
|
||||||
|
GetTitleHeight,
|
||||||
|
GetBorderWidth,
|
||||||
|
SetTitleHeight {
|
||||||
|
height: i32,
|
||||||
|
},
|
||||||
|
SetBorderWidth {
|
||||||
|
width: i32,
|
||||||
|
},
|
||||||
|
SetTitleColor {
|
||||||
|
color: Color,
|
||||||
|
},
|
||||||
|
SetTitleUnderlineColor {
|
||||||
|
color: Color,
|
||||||
|
},
|
||||||
|
SetBorderColor {
|
||||||
|
color: Color,
|
||||||
|
},
|
||||||
|
SetBackgroundColor {
|
||||||
|
color: Color,
|
||||||
|
},
|
||||||
|
CreateSplit {
|
||||||
|
seat: Seat,
|
||||||
|
axis: Axis,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug)]
|
#[derive(Encode, Decode, Debug)]
|
||||||
|
|
@ -105,6 +130,8 @@ pub enum Response {
|
||||||
ParseKeymap { keymap: Keymap },
|
ParseKeymap { keymap: Keymap },
|
||||||
CreateSeat { seat: Seat },
|
CreateSeat { seat: Seat },
|
||||||
GetInputDevices { devices: Vec<InputDevice> },
|
GetInputDevices { devices: Vec<InputDevice> },
|
||||||
|
GetTitleHeight { height: i32 },
|
||||||
|
GetBorderWidth { width: i32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug)]
|
#[derive(Encode, Decode, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,9 @@ use std::collections::HashMap;
|
||||||
mod macros;
|
mod macros;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod _private;
|
pub mod _private;
|
||||||
pub mod keyboard;
|
|
||||||
pub mod embedded;
|
pub mod embedded;
|
||||||
|
pub mod keyboard;
|
||||||
|
pub mod theme;
|
||||||
|
|
||||||
#[derive(Encode, Decode, Copy, Clone, Debug)]
|
#[derive(Encode, Decode, Copy, Clone, Debug)]
|
||||||
pub enum LogLevel {
|
pub enum LogLevel {
|
||||||
|
|
@ -129,6 +130,10 @@ impl Seat {
|
||||||
(|| res = get!().get_input_devices(Some(self)))();
|
(|| res = get!().get_input_devices(Some(self)))();
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_split(self, axis: Axis) {
|
||||||
|
get!().create_split(self, axis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_seats() -> Vec<Seat> {
|
pub fn get_seats() -> Vec<Seat> {
|
||||||
|
|
|
||||||
45
i4config/src/theme.rs
Normal file
45
i4config/src/theme.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
use bincode::{BorrowDecode, Encode};
|
||||||
|
|
||||||
|
#[derive(Encode, BorrowDecode, Debug)]
|
||||||
|
pub struct Color {
|
||||||
|
pub r: u8,
|
||||||
|
pub g: u8,
|
||||||
|
pub b: u8,
|
||||||
|
pub a: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_title_color(color: Color) {
|
||||||
|
get!().set_title_color(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_title_underline_color(color: Color) {
|
||||||
|
get!().set_title_underline_color(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_border_color(color: Color) {
|
||||||
|
get!().set_border_color(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_background_color(color: Color) {
|
||||||
|
get!().set_background_color(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_title_height() -> i32 {
|
||||||
|
let mut res = 0;
|
||||||
|
(|| res = get!().get_title_height())();
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_border_width() -> i32 {
|
||||||
|
let mut res = 0;
|
||||||
|
(|| res = get!().get_border_width())();
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_title_height(height: i32) {
|
||||||
|
get!().set_title_height(height)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_border_width(width: i32) {
|
||||||
|
get!().set_border_width(width)
|
||||||
|
}
|
||||||
|
|
@ -6,8 +6,7 @@ linear_ids!(OutputIds, OutputId);
|
||||||
linear_ids!(KeyboardIds, KeyboardId);
|
linear_ids!(KeyboardIds, KeyboardId);
|
||||||
linear_ids!(MouseIds, MouseId);
|
linear_ids!(MouseIds, MouseId);
|
||||||
|
|
||||||
pub trait Backend {
|
pub trait Backend {}
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Output {
|
pub trait Output {
|
||||||
fn id(&self) -> OutputId;
|
fn id(&self) -> OutputId;
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
use std::rc::Rc;
|
|
||||||
use crate::backend::Backend;
|
use crate::backend::Backend;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct DummyBackend {
|
pub struct DummyBackend {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DummyBackend {
|
impl DummyBackend {
|
||||||
pub fn new() -> Rc<Self> {
|
pub fn new() -> Rc<Self> {
|
||||||
Rc::new(Self { })
|
Rc::new(Self {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backend for DummyBackend {
|
impl Backend for DummyBackend {}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
pub mod xorg;
|
|
||||||
pub mod dummy;
|
pub mod dummy;
|
||||||
|
pub mod xorg;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
use crate::backend::{BackendEvent, KeyState, Keyboard, KeyboardEvent, KeyboardId, Mouse, MouseEvent, MouseId, Output, OutputId, ScrollAxis, Backend};
|
use crate::backend::{
|
||||||
|
Backend, BackendEvent, KeyState, Keyboard, KeyboardEvent, KeyboardId, Mouse, MouseEvent,
|
||||||
|
MouseId, Output, OutputId, ScrollAxis,
|
||||||
|
};
|
||||||
use crate::drm::drm::{Drm, DrmError};
|
use crate::drm::drm::{Drm, DrmError};
|
||||||
use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
|
use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
|
||||||
use crate::drm::{ModifiedFormat, INVALID_MODIFIER};
|
use crate::drm::{ModifiedFormat, INVALID_MODIFIER};
|
||||||
|
|
@ -211,8 +214,7 @@ pub struct XorgBackend {
|
||||||
b: Cell<f32>,
|
b: Cell<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backend for XorgBackend {
|
impl Backend for XorgBackend {}
|
||||||
}
|
|
||||||
|
|
||||||
fn get_drm(con: &XcbCon) -> Result<Drm, XorgBackendError> {
|
fn get_drm(con: &XcbCon) -> Result<Drm, XorgBackendError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -1098,7 +1100,9 @@ impl Keyboard for XorgSeat {
|
||||||
0,
|
0,
|
||||||
ptr::null(),
|
ptr::null(),
|
||||||
);
|
);
|
||||||
let res = con.input.xcb_input_xi_grab_device_reply(con.c, res, &mut err);
|
let res = con
|
||||||
|
.input
|
||||||
|
.xcb_input_xi_grab_device_reply(con.c, res, &mut err);
|
||||||
let res = match con.check(res, err) {
|
let res = match con.check(res, err) {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -1110,7 +1114,9 @@ impl Keyboard for XorgSeat {
|
||||||
log::error!("Could not grab device {}: status = {}", self.kb, res.status);
|
log::error!("Could not grab device {}: status = {}", self.kb, res.status);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let cookie = con.input.xcb_input_xi_ungrab_device_checked(con.c, 0, self.kb);
|
let cookie = con
|
||||||
|
.input
|
||||||
|
.xcb_input_xi_ungrab_device_checked(con.c, 0, self.kb);
|
||||||
if let Err(e) = con.check_cookie(cookie) {
|
if let Err(e) = con.check_cookie(cookie) {
|
||||||
log::error!("Could not ungrab device {}: {}", self.kb, ErrorFmt(e));
|
log::error!("Could not ungrab device {}: {}", self.kb, ErrorFmt(e));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::backend::{KeyboardId, MouseId};
|
use crate::backend::{KeyboardId, MouseId};
|
||||||
use crate::ifs::wl_seat::{SeatId, WlSeatGlobal};
|
use crate::ifs::wl_seat::{SeatId, WlSeatGlobal};
|
||||||
use crate::state::{DeviceHandlerData};
|
use crate::state::DeviceHandlerData;
|
||||||
use crate::tree::ContainerSplit;
|
use crate::tree::ContainerSplit;
|
||||||
use crate::utils::copyhashmap::CopyHashMap;
|
use crate::utils::copyhashmap::CopyHashMap;
|
||||||
use crate::utils::debug_fn::debug_fn;
|
use crate::utils::debug_fn::debug_fn;
|
||||||
|
|
@ -54,7 +54,7 @@ impl ConfigProxyHandler {
|
||||||
msg: &str,
|
msg: &str,
|
||||||
file: Option<&str>,
|
file: Option<&str>,
|
||||||
line: Option<u32>,
|
line: Option<u32>,
|
||||||
) -> Result<(), LogError> {
|
) {
|
||||||
let level = match level {
|
let level = match level {
|
||||||
LogLevel::Error => Level::Error,
|
LogLevel::Error => Level::Error,
|
||||||
LogLevel::Warn => Level::Warn,
|
LogLevel::Warn => Level::Warn,
|
||||||
|
|
@ -74,10 +74,9 @@ impl ConfigProxyHandler {
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
log::log!(level, "{:?}", debug);
|
log::log!(level, "{:?}", debug);
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_create_seat(&self, name: &str) -> Result<(), CreateSeatError> {
|
fn handle_create_seat(&self, name: &str) {
|
||||||
let global_name = self.state.globals.name();
|
let global_name = self.state.globals.name();
|
||||||
let seat = WlSeatGlobal::new(global_name, name, &self.state);
|
let seat = WlSeatGlobal::new(global_name, name, &self.state);
|
||||||
self.state.globals.add_global(&self.state, &seat);
|
self.state.globals.add_global(&self.state, &seat);
|
||||||
|
|
@ -86,7 +85,6 @@ impl ConfigProxyHandler {
|
||||||
seat: Seat(seat.id().raw() as _),
|
seat: Seat(seat.id().raw() as _),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_parse_keymap(&self, keymap: &str) -> Result<(), ParseKeymapError> {
|
fn handle_parse_keymap(&self, keymap: &str) -> Result<(), ParseKeymapError> {
|
||||||
|
|
@ -248,7 +246,7 @@ impl ConfigProxyHandler {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_get_input_devices(&self, seat: Option<Seat>) -> Result<(), GetInputDevicesError> {
|
fn handle_get_input_devices(&self, seat: Option<Seat>) {
|
||||||
let id = seat.map(|s| SeatId::from_raw(s.0 as _));
|
let id = seat.map(|s| SeatId::from_raw(s.0 as _));
|
||||||
let matches = |dhd: &DeviceHandlerData| {
|
let matches = |dhd: &DeviceHandlerData| {
|
||||||
let id = match id {
|
let id = match id {
|
||||||
|
|
@ -280,10 +278,9 @@ impl ConfigProxyHandler {
|
||||||
self.send(&ServerMessage::Response {
|
self.send(&ServerMessage::Response {
|
||||||
response: Response::GetInputDevices { devices: res },
|
response: Response::GetInputDevices { devices: res },
|
||||||
});
|
});
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_get_seats(&self) -> Result<(), GetSeatsError> {
|
fn handle_get_seats(&self) {
|
||||||
let seats = {
|
let seats = {
|
||||||
let seats = self.state.globals.seats.lock();
|
let seats = self.state.globals.seats.lock();
|
||||||
seats
|
seats
|
||||||
|
|
@ -294,7 +291,6 @@ impl ConfigProxyHandler {
|
||||||
self.send(&ServerMessage::Response {
|
self.send(&ServerMessage::Response {
|
||||||
response: Response::GetSeats { seats },
|
response: Response::GetSeats { seats },
|
||||||
});
|
});
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_run(
|
fn handle_run(
|
||||||
|
|
@ -311,16 +307,78 @@ impl ConfigProxyHandler {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_grab(
|
fn handle_grab(&self, kb: Keyboard, grab: bool) -> Result<(), GrabError> {
|
||||||
&self,
|
|
||||||
kb: Keyboard,
|
|
||||||
grab: bool,
|
|
||||||
) -> Result<(), GrabError> {
|
|
||||||
let kb = self.get_kb(kb)?;
|
let kb = self.get_kb(kb)?;
|
||||||
kb.grab(grab);
|
kb.grab(grab);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_get_title_height(&self) {
|
||||||
|
self.send(&ServerMessage::Response {
|
||||||
|
response: Response::GetTitleHeight {
|
||||||
|
height: self.state.theme.title_height.get(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_get_border_width(&self) {
|
||||||
|
self.send(&ServerMessage::Response {
|
||||||
|
response: Response::GetBorderWidth {
|
||||||
|
width: self.state.theme.border_width.get(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_create_split(&self, seat: Seat, axis: Axis) -> Result<(), CreateSplitError> {
|
||||||
|
let seat = self.get_seat(seat)?;
|
||||||
|
seat.create_split(axis.into());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_set_title_height(&self, height: i32) -> Result<(), SetTitleHeightError> {
|
||||||
|
if height < 0 {
|
||||||
|
return Err(SetTitleHeightError::Negative(height));
|
||||||
|
}
|
||||||
|
if height > 1000 {
|
||||||
|
return Err(SetTitleHeightError::Excessive(height));
|
||||||
|
}
|
||||||
|
self.state.theme.title_height.set(height);
|
||||||
|
self.state.theme.version.fetch_add(1);
|
||||||
|
self.state.root.needs_layout.set(true);
|
||||||
|
self.state.pending_layout.push(self.state.root.clone());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_set_border_width(&self, width: i32) -> Result<(), SetBorderWidthError> {
|
||||||
|
if width < 0 {
|
||||||
|
return Err(SetBorderWidthError::Negative(width));
|
||||||
|
}
|
||||||
|
if width > 1000 {
|
||||||
|
return Err(SetBorderWidthError::Excessive(width));
|
||||||
|
}
|
||||||
|
self.state.theme.border_width.set(width);
|
||||||
|
self.state.theme.version.fetch_add(1);
|
||||||
|
self.state.root.needs_layout.set(true);
|
||||||
|
self.state.pending_layout.push(self.state.root.clone());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_set_title_color(&self, color: i4config::theme::Color) {
|
||||||
|
self.state.theme.title_color.set(color.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_set_border_color(&self, color: i4config::theme::Color) {
|
||||||
|
self.state.theme.border_color.set(color.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_set_background_color(&self, color: i4config::theme::Color) {
|
||||||
|
self.state.theme.background_color.set(color.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_set_title_underline_color(&self, color: i4config::theme::Color) {
|
||||||
|
self.state.theme.underline_color.set(color.into());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_request(&self, msg: &[u8]) {
|
pub fn handle_request(&self, msg: &[u8]) {
|
||||||
if let Err(e) = self.handle_request_(msg) {
|
if let Err(e) = self.handle_request_(msg) {
|
||||||
log::error!("Could not handle client request: {}", ErrorFmt(e));
|
log::error!("Could not handle client request: {}", ErrorFmt(e));
|
||||||
|
|
@ -339,8 +397,8 @@ impl ConfigProxyHandler {
|
||||||
msg,
|
msg,
|
||||||
file,
|
file,
|
||||||
line,
|
line,
|
||||||
} => self.handle_log_request(level, msg, file, line)?,
|
} => self.handle_log_request(level, msg, file, line),
|
||||||
ClientMessage::CreateSeat { name } => self.handle_create_seat(name)?,
|
ClientMessage::CreateSeat { name } => self.handle_create_seat(name),
|
||||||
ClientMessage::ParseKeymap { keymap } => self.handle_parse_keymap(keymap)?,
|
ClientMessage::ParseKeymap { keymap } => self.handle_parse_keymap(keymap)?,
|
||||||
ClientMessage::SeatSetKeymap { seat, keymap } => {
|
ClientMessage::SeatSetKeymap { seat, keymap } => {
|
||||||
self.handle_set_keymap(seat, keymap)?
|
self.handle_set_keymap(seat, keymap)?
|
||||||
|
|
@ -360,11 +418,22 @@ impl ConfigProxyHandler {
|
||||||
}
|
}
|
||||||
ClientMessage::Focus { seat, direction } => self.handle_focus(seat, direction)?,
|
ClientMessage::Focus { seat, direction } => self.handle_focus(seat, direction)?,
|
||||||
ClientMessage::Move { seat, direction } => {}
|
ClientMessage::Move { seat, direction } => {}
|
||||||
ClientMessage::GetInputDevices { seat } => self.handle_get_input_devices(seat)?,
|
ClientMessage::GetInputDevices { seat } => self.handle_get_input_devices(seat),
|
||||||
ClientMessage::GetSeats => self.handle_get_seats()?,
|
ClientMessage::GetSeats => self.handle_get_seats(),
|
||||||
ClientMessage::RemoveSeat { .. } => {}
|
ClientMessage::RemoveSeat { .. } => {}
|
||||||
ClientMessage::Run { prog, args, env } => self.handle_run(prog, args, env)?,
|
ClientMessage::Run { prog, args, env } => self.handle_run(prog, args, env)?,
|
||||||
ClientMessage::GrabKb { kb, grab } => self.handle_grab(kb, grab)?,
|
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::SetTitleColor { color } => self.handle_set_title_color(color),
|
||||||
|
ClientMessage::SetTitleUnderlineColor { color } => {
|
||||||
|
self.handle_set_title_underline_color(color)
|
||||||
|
}
|
||||||
|
ClientMessage::SetBorderColor { color } => self.handle_set_border_color(color),
|
||||||
|
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)?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -372,10 +441,6 @@ impl ConfigProxyHandler {
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
enum CphError {
|
enum CphError {
|
||||||
#[error("Could not process a `log` request")]
|
|
||||||
LogError(#[from] LogError),
|
|
||||||
#[error("Could not process a `create_seat` request")]
|
|
||||||
CreateSeatError(#[from] CreateSeatError),
|
|
||||||
#[error("Could not process a `parse_keymap` request")]
|
#[error("Could not process a `parse_keymap` request")]
|
||||||
ParseKeymapError(#[from] ParseKeymapError),
|
ParseKeymapError(#[from] ParseKeymapError),
|
||||||
#[error("Could not process a `set_seat` request")]
|
#[error("Could not process a `set_seat` request")]
|
||||||
|
|
@ -384,10 +449,6 @@ enum CphError {
|
||||||
AddShortcutError(#[from] AddShortcutError),
|
AddShortcutError(#[from] AddShortcutError),
|
||||||
#[error("Could not process a `remove_shortcut` request")]
|
#[error("Could not process a `remove_shortcut` request")]
|
||||||
RemoveShortcutError(#[from] RemoveShortcutError),
|
RemoveShortcutError(#[from] RemoveShortcutError),
|
||||||
#[error("Could not process a `get_input_devices` request")]
|
|
||||||
GetInputDevicesError(#[from] GetInputDevicesError),
|
|
||||||
#[error("Could not process a `get_seats` request")]
|
|
||||||
GetSeatsError(#[from] GetSeatsError),
|
|
||||||
#[error("Could not process a `set_keymap` request")]
|
#[error("Could not process a `set_keymap` request")]
|
||||||
SeatSetKeymapError(#[from] SeatSetKeymapError),
|
SeatSetKeymapError(#[from] SeatSetKeymapError),
|
||||||
#[error("Could not process a `get_repeat_rate` request")]
|
#[error("Could not process a `get_repeat_rate` request")]
|
||||||
|
|
@ -404,6 +465,12 @@ enum CphError {
|
||||||
RunError(#[from] RunError),
|
RunError(#[from] RunError),
|
||||||
#[error("Could not process a `grab` request")]
|
#[error("Could not process a `grab` request")]
|
||||||
GrabError(#[from] GrabError),
|
GrabError(#[from] GrabError),
|
||||||
|
#[error("Could not process a `create_split` request")]
|
||||||
|
CreateSplitError(#[from] CreateSplitError),
|
||||||
|
#[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("Device {0:?} does not exist")]
|
#[error("Device {0:?} does not exist")]
|
||||||
DeviceDoesNotExist(InputDevice),
|
DeviceDoesNotExist(InputDevice),
|
||||||
#[error("Device {0:?} does not exist")]
|
#[error("Device {0:?} does not exist")]
|
||||||
|
|
@ -416,12 +483,6 @@ enum CphError {
|
||||||
ParsingFailed(#[source] DecodeError),
|
ParsingFailed(#[source] DecodeError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
enum LogError {}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
enum CreateSeatError {}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
enum ParseKeymapError {
|
enum ParseKeymapError {
|
||||||
#[error("Parsing failed")]
|
#[error("Parsing failed")]
|
||||||
|
|
@ -449,12 +510,6 @@ enum RemoveShortcutError {
|
||||||
}
|
}
|
||||||
efrom!(RemoveShortcutError, CphError);
|
efrom!(RemoveShortcutError, CphError);
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
enum GetInputDevicesError {}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
enum GetSeatsError {}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
enum SeatSetKeymapError {
|
enum SeatSetKeymapError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
@ -513,3 +568,26 @@ enum GrabError {
|
||||||
CphError(#[from] Box<CphError>),
|
CphError(#[from] Box<CphError>),
|
||||||
}
|
}
|
||||||
efrom!(GrabError, CphError);
|
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<CphError>),
|
||||||
|
}
|
||||||
|
efrom!(CreateSplitError, CphError);
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,10 @@ impl WlSeatGlobal {
|
||||||
self.keyboard_node.get().set_parent_split(axis)
|
self.keyboard_node.get().set_parent_split(axis)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_split(&self, axis: ContainerSplit) {
|
||||||
|
self.keyboard_node.get().create_split(axis)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_rate(&self) -> (i32, i32) {
|
pub fn get_rate(&self) -> (i32, i32) {
|
||||||
self.repeat_rate.get()
|
self.repeat_rate.get()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ impl PointerOwner for DefaultPointerOwner {
|
||||||
}
|
}
|
||||||
if (stack.len(), found_tree.len()) == (divergence, divergence) {
|
if (stack.len(), found_tree.len()) == (divergence, divergence) {
|
||||||
if let Some(node) = found_tree.last() {
|
if let Some(node) = found_tree.last() {
|
||||||
node.node
|
node.node.clone()
|
||||||
.motion(seat, x.apply_fract(node.x), y.apply_fract(node.y));
|
.motion(seat, x.apply_fract(node.x), y.apply_fract(node.y));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -242,7 +242,7 @@ impl PointerOwner for GrabPointerOwner {
|
||||||
let (x, y) = seat.pos.get();
|
let (x, y) = seat.pos.get();
|
||||||
let pos = self.node.absolute_position();
|
let pos = self.node.absolute_position();
|
||||||
let (x_int, y_int) = pos.translate(x.round_down(), y.round_down());
|
let (x_int, y_int) = pos.translate(x.round_down(), y.round_down());
|
||||||
self.node
|
self.node.clone()
|
||||||
.motion(seat, x.apply_fract(x_int), y.apply_fract(y_int));
|
.motion(seat, x.apply_fract(x_int), y.apply_fract(y_int));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -618,6 +618,10 @@ impl Node for WlSurface {
|
||||||
self.xdg.get().map(|x| x.set_split(split));
|
self.xdg.get().map(|x| x.set_split(split));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_split(self: Rc<Self>, split: ContainerSplit) {
|
||||||
|
self.xdg.get().map(|x| x.create_split(split));
|
||||||
|
}
|
||||||
|
|
||||||
fn move_focus(&self, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
fn move_focus(&self, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||||
let xdg = match self.xdg.get() {
|
let xdg = match self.xdg.get() {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
|
|
@ -670,8 +674,8 @@ impl Node for WlSurface {
|
||||||
seat.enter_surface(&self, x, y)
|
seat.enter_surface(&self, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn motion(&self, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
fn motion(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||||
seat.motion_surface(self, x, y)
|
seat.motion_surface(&*self, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
|
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,10 @@ pub trait XdgSurfaceExt: Debug {
|
||||||
let _ = split;
|
let _ = split;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_split(self: Rc<Self>, split: ContainerSplit) {
|
||||||
|
let _ = split;
|
||||||
|
}
|
||||||
|
|
||||||
fn move_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
fn move_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||||
let _ = seat;
|
let _ = seat;
|
||||||
let _ = direction;
|
let _ = direction;
|
||||||
|
|
@ -158,6 +162,10 @@ impl XdgSurface {
|
||||||
self.ext.get().map(|e| e.set_split(split));
|
self.ext.get().map(|e| e.set_split(split));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_split(&self, split: ContainerSplit) {
|
||||||
|
self.ext.get().map(|e| e.create_split(split));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn move_focus(&self, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
pub fn move_focus(&self, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||||
let ext = match self.ext.get() {
|
let ext = match self.ext.get() {
|
||||||
None => return,
|
None => return,
|
||||||
|
|
|
||||||
|
|
@ -373,6 +373,7 @@ impl XdgToplevel {
|
||||||
&workspace,
|
&workspace,
|
||||||
workspace.clone(),
|
workspace.clone(),
|
||||||
self.clone(),
|
self.clone(),
|
||||||
|
ContainerSplit::Horizontal,
|
||||||
));
|
));
|
||||||
workspace.set_container(&container);
|
workspace.set_container(&container);
|
||||||
self.parent_node.set(Some(container));
|
self.parent_node.set(Some(container));
|
||||||
|
|
@ -492,6 +493,26 @@ impl XdgSurfaceExt for XdgToplevel {
|
||||||
self.parent_node.get().map(|p| p.set_split(split));
|
self.parent_node.get().map(|p| p.set_split(split));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_split(self: Rc<Self>, split: ContainerSplit) {
|
||||||
|
let ws = match self.xdg.workspace.get() {
|
||||||
|
Some(ws) => ws,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let pn = match self.parent_node.get() {
|
||||||
|
Some(pn) => pn,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let cn = Rc::new(ContainerNode::new(
|
||||||
|
&self.xdg.surface.client.state,
|
||||||
|
&ws,
|
||||||
|
pn.clone(),
|
||||||
|
self.clone(),
|
||||||
|
split,
|
||||||
|
));
|
||||||
|
self.parent_node.set(Some(cn.clone()));
|
||||||
|
pn.replace_child(&*self, cn);
|
||||||
|
}
|
||||||
|
|
||||||
fn move_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
fn move_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||||
let pn = match self.parent_node.get() {
|
let pn = match self.parent_node.get() {
|
||||||
Some(pn) => pn,
|
Some(pn) => pn,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
use crate::acceptor::AcceptorError;
|
use crate::acceptor::AcceptorError;
|
||||||
use crate::async_engine::AsyncError;
|
use crate::async_engine::AsyncError;
|
||||||
|
use crate::backends::dummy::DummyBackend;
|
||||||
use crate::backends::xorg::{XorgBackend, XorgBackendError};
|
use crate::backends::xorg::{XorgBackend, XorgBackendError};
|
||||||
use crate::client::Clients;
|
use crate::client::Clients;
|
||||||
use crate::clientmem::ClientMemError;
|
use crate::clientmem::ClientMemError;
|
||||||
|
|
@ -26,6 +27,7 @@ use crate::render::RenderError;
|
||||||
use crate::sighand::SighandError;
|
use crate::sighand::SighandError;
|
||||||
use crate::state::State;
|
use crate::state::State;
|
||||||
use crate::tree::{DisplayNode, NodeIds};
|
use crate::tree::{DisplayNode, NodeIds};
|
||||||
|
use crate::utils::clonecell::CloneCell;
|
||||||
use crate::utils::errorfmt::ErrorFmt;
|
use crate::utils::errorfmt::ErrorFmt;
|
||||||
use crate::utils::numcell::NumCell;
|
use crate::utils::numcell::NumCell;
|
||||||
use crate::utils::queue::AsyncQueue;
|
use crate::utils::queue::AsyncQueue;
|
||||||
|
|
@ -40,8 +42,6 @@ use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use wheel::Wheel;
|
use wheel::Wheel;
|
||||||
use crate::backends::dummy::DummyBackend;
|
|
||||||
use crate::utils::clonecell::CloneCell;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
@ -71,6 +71,7 @@ mod servermem;
|
||||||
mod sighand;
|
mod sighand;
|
||||||
mod state;
|
mod state;
|
||||||
mod tasks;
|
mod tasks;
|
||||||
|
mod theme;
|
||||||
mod time;
|
mod time;
|
||||||
mod tree;
|
mod tree;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
@ -153,6 +154,8 @@ fn main_() -> Result<(), MainError> {
|
||||||
config: Default::default(),
|
config: Default::default(),
|
||||||
mouse_ids: Default::default(),
|
mouse_ids: Default::default(),
|
||||||
kb_handlers: Default::default(),
|
kb_handlers: Default::default(),
|
||||||
|
theme: Default::default(),
|
||||||
|
pending_layout: Default::default(),
|
||||||
});
|
});
|
||||||
forker.install(&state);
|
forker.install(&state);
|
||||||
let backend = XorgBackend::new(&state)?;
|
let backend = XorgBackend::new(&state)?;
|
||||||
|
|
@ -161,6 +164,7 @@ fn main_() -> Result<(), MainError> {
|
||||||
state.config.set(Some(Rc::new(config)));
|
state.config.set(Some(Rc::new(config)));
|
||||||
let _global_event_handler = engine.spawn(tasks::handle_backend_events(state.clone()));
|
let _global_event_handler = engine.spawn(tasks::handle_backend_events(state.clone()));
|
||||||
let _slow_client_handler = engine.spawn(tasks::handle_slow_clients(state.clone()));
|
let _slow_client_handler = engine.spawn(tasks::handle_slow_clients(state.clone()));
|
||||||
|
let _do_layout = engine.spawn(tasks::do_layout(state.clone()));
|
||||||
let socket_path = Acceptor::install(&state)?;
|
let socket_path = Acceptor::install(&state)?;
|
||||||
forker.setenv(b"WAYLAND_DISPLAY", socket_path.as_bytes());
|
forker.setenv(b"WAYLAND_DISPLAY", socket_path.as_bytes());
|
||||||
el.run()?;
|
el.run()?;
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ impl Framebuffer {
|
||||||
let mut renderer = Renderer {
|
let mut renderer = Renderer {
|
||||||
ctx: &self.ctx,
|
ctx: &self.ctx,
|
||||||
fb: &self.gl,
|
fb: &self.gl,
|
||||||
|
state,
|
||||||
};
|
};
|
||||||
node.render(&mut renderer, 0, 0);
|
node.render(&mut renderer, 0, 0);
|
||||||
if let Some(rect) = cursor_rect {
|
if let Some(rect) = cursor_rect {
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ use crate::render::sys::{glDisable, glEnable, GL_BLEND};
|
||||||
use crate::render::Texture;
|
use crate::render::Texture;
|
||||||
use crate::tree::{
|
use crate::tree::{
|
||||||
ContainerFocus, ContainerNode, ContainerSplit, FloatNode, OutputNode, WorkspaceNode,
|
ContainerFocus, ContainerNode, ContainerSplit, FloatNode, OutputNode, WorkspaceNode,
|
||||||
CONTAINER_BORDER, CONTAINER_TITLE_HEIGHT,
|
|
||||||
};
|
};
|
||||||
|
use crate::State;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
@ -33,14 +33,10 @@ fn focus_color(focus: ContainerFocus) -> (f32, f32, f32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const TITLE_COLOR: (f32, f32, f32) = ((0x46 as f32)/255., (0x04 as f32)/255., (0x17 as f32)/255.);
|
|
||||||
// const BORDER_COLOR: (f32, f32, f32) = ((0xba as f32)/255., (0x57 as f32)/255., (0x00 as f32)/255.);
|
|
||||||
const UNDERLINE_COLOR: (f32, f32, f32) = ((0x66 as f32)/255., (0x24 as f32)/255., (0x37 as f32)/255.);
|
|
||||||
const BORDER_COLOR: (f32, f32, f32) = ((0x36 as f32)/255., (0x00 as f32)/255., (0x07 as f32)/255.);
|
|
||||||
|
|
||||||
pub struct Renderer<'a> {
|
pub struct Renderer<'a> {
|
||||||
pub(super) ctx: &'a RenderContext,
|
pub(super) ctx: &'a RenderContext,
|
||||||
pub(super) fb: &'a GlFrameBuffer,
|
pub(super) fb: &'a GlFrameBuffer,
|
||||||
|
pub(super) state: &'a State,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer<'_> {
|
impl Renderer<'_> {
|
||||||
|
|
@ -104,21 +100,22 @@ impl Renderer<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_container(&mut self, container: &ContainerNode, x: i32, y: i32) {
|
pub fn render_container(&mut self, container: &ContainerNode, x: i32, y: i32) {
|
||||||
|
let border_width = self.state.theme.border_width.get();
|
||||||
|
let title_height = self.state.theme.title_height.get();
|
||||||
let cwidth = container.width.get();
|
let cwidth = container.width.get();
|
||||||
let cheight = container.height.get();
|
let cheight = container.height.get();
|
||||||
let num_children = container.num_children();
|
let num_children = container.num_children();
|
||||||
let title_rect =
|
let title_rect = Rect::new_sized(x, y, container.width.get(), title_height).unwrap();
|
||||||
Rect::new_sized(x, y, container.width.get(), CONTAINER_TITLE_HEIGHT - 1).unwrap();
|
|
||||||
let underline_rect =
|
let underline_rect =
|
||||||
Rect::new_sized(x, y + CONTAINER_TITLE_HEIGHT - 1, container.width.get(), 1).unwrap();
|
Rect::new_sized(x, y + title_height, container.width.get(), 1).unwrap();
|
||||||
if let Some(child) = container.mono_child.get() {
|
if let Some(child) = container.mono_child.get() {
|
||||||
let space_per_child = cwidth / num_children as i32;
|
let space_per_child = cwidth / num_children as i32;
|
||||||
let mut rem = cwidth % num_children as i32;
|
let mut rem = cwidth % num_children as i32;
|
||||||
let mut pos = x;
|
let mut pos = x;
|
||||||
let (r, g, b) = focus_color(ContainerFocus::None);
|
let (r, g, b) = focus_color(ContainerFocus::None);
|
||||||
self.fill_boxes(slice::from_ref(&title_rect), r, g, b, 1.0);
|
self.fill_boxes(slice::from_ref(&title_rect), r, g, b, 1.0);
|
||||||
let (r, g, b) = BORDER_COLOR;
|
let c = self.state.theme.border_color.get();
|
||||||
self.fill_boxes(slice::from_ref(&underline_rect), r, g, b, 1.0);
|
self.fill_boxes(slice::from_ref(&underline_rect), c.r, c.g, c.b, c.a);
|
||||||
for child in container.children.iter() {
|
for child in container.children.iter() {
|
||||||
let focus = child.focus.get();
|
let focus = child.focus.get();
|
||||||
let (r, g, b) = focus_color(focus);
|
let (r, g, b) = focus_color(focus);
|
||||||
|
|
@ -128,7 +125,7 @@ impl Renderer<'_> {
|
||||||
width += 1;
|
width += 1;
|
||||||
}
|
}
|
||||||
if focus != ContainerFocus::None {
|
if focus != ContainerFocus::None {
|
||||||
let rect = Rect::new_sized(pos, y, width, CONTAINER_TITLE_HEIGHT).unwrap();
|
let rect = Rect::new_sized(pos, y, width, title_height).unwrap();
|
||||||
self.fill_boxes(slice::from_ref(&rect), r, g, b, 1.0);
|
self.fill_boxes(slice::from_ref(&rect), r, g, b, 1.0);
|
||||||
}
|
}
|
||||||
pos += width as i32;
|
pos += width as i32;
|
||||||
|
|
@ -157,48 +154,50 @@ impl Renderer<'_> {
|
||||||
let border_rect = if split == ContainerSplit::Horizontal {
|
let border_rect = if split == ContainerSplit::Horizontal {
|
||||||
Rect::new_sized(
|
Rect::new_sized(
|
||||||
x + body.x2(),
|
x + body.x2(),
|
||||||
y + body.y1() - CONTAINER_TITLE_HEIGHT,
|
y + body.y1() - title_height - 1,
|
||||||
CONTAINER_BORDER,
|
border_width,
|
||||||
container.height.get(),
|
container.height.get(),
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
} else {
|
} else {
|
||||||
title_rects.push(Rect::new_sized(
|
title_rects.push(
|
||||||
x,
|
Rect::new_sized(
|
||||||
y + body.y2() + CONTAINER_BORDER,
|
x,
|
||||||
container.width.get(),
|
y + body.y2() + border_width,
|
||||||
CONTAINER_TITLE_HEIGHT - 1,
|
container.width.get(),
|
||||||
).unwrap());
|
title_height,
|
||||||
underline_rects.push(Rect::new_sized(
|
)
|
||||||
x,
|
.unwrap(),
|
||||||
y + body.y2() + CONTAINER_BORDER + CONTAINER_TITLE_HEIGHT - 1,
|
);
|
||||||
container.width.get(),
|
underline_rects.push(
|
||||||
1,
|
Rect::new_sized(
|
||||||
).unwrap());
|
x,
|
||||||
Rect::new_sized(
|
y + body.y2() + border_width + title_height,
|
||||||
x,
|
container.width.get(),
|
||||||
y + body.y2(),
|
1,
|
||||||
container.width.get(),
|
)
|
||||||
CONTAINER_BORDER,
|
.unwrap(),
|
||||||
)
|
);
|
||||||
.unwrap()
|
Rect::new_sized(x, y + body.y2(), container.width.get(), border_width)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
border_rects.push(border_rect);
|
border_rects.push(border_rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let (r, g, b) = TITLE_COLOR;
|
let c = self.state.theme.title_color.get();
|
||||||
self.fill_boxes(&title_rects, r, g, b, 1.0);
|
self.fill_boxes(&title_rects, c.r, c.g, c.b, c.a);
|
||||||
let (r, g, b) = UNDERLINE_COLOR;
|
let c = self.state.theme.underline_color.get();
|
||||||
self.fill_boxes(&underline_rects, r, g, b, 1.0);
|
self.fill_boxes(&underline_rects, c.r, c.g, c.b, c.a);
|
||||||
let (r, g, b) = BORDER_COLOR;
|
let c = self.state.theme.border_color.get();
|
||||||
self.fill_boxes(&border_rects, r, g, b, 1.0);
|
self.fill_boxes(&border_rects, c.r, c.g, c.b, c.a);
|
||||||
}
|
}
|
||||||
for child in container.children.iter() {
|
for child in container.children.iter() {
|
||||||
let body = child.body.get();
|
let body = child.body.get();
|
||||||
if body.x1() >= cwidth || body.y1() >= cheight {
|
if body.x1() >= cwidth || body.y1() >= cheight {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
let body = body.move_(container.abs_x1.get(), container.abs_y1.get());
|
||||||
unsafe {
|
unsafe {
|
||||||
with_scissor(&body, || {
|
with_scissor(&body, || {
|
||||||
let content = child.content.get();
|
let content = child.content.get();
|
||||||
|
|
@ -323,7 +322,6 @@ impl Renderer<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_floating(&mut self, floating: &FloatNode, x: i32, y: i32) {
|
pub fn render_floating(&mut self, floating: &FloatNode, x: i32, y: i32) {
|
||||||
log::info!("rendering at {}x{}", x, y);
|
|
||||||
if let Some(child) = floating.child.get() {
|
if let Some(child) = floating.child.get() {
|
||||||
child.render(self, x, y)
|
child.render(self, x, y)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
src/state.rs
10
src/state.rs
|
|
@ -1,5 +1,8 @@
|
||||||
use crate::async_engine::{AsyncEngine, SpawnedFuture};
|
use crate::async_engine::{AsyncEngine, SpawnedFuture};
|
||||||
use crate::backend::{Backend, BackendEvent, Keyboard, KeyboardId, KeyboardIds, MouseId, MouseIds, OutputId, OutputIds};
|
use crate::backend::{
|
||||||
|
Backend, BackendEvent, Keyboard, KeyboardId, KeyboardIds, MouseId, MouseIds, OutputId,
|
||||||
|
OutputIds,
|
||||||
|
};
|
||||||
use crate::client::{Client, Clients};
|
use crate::client::{Client, Clients};
|
||||||
use crate::config::ConfigProxy;
|
use crate::config::ConfigProxy;
|
||||||
use crate::cursor::ServerCursors;
|
use crate::cursor::ServerCursors;
|
||||||
|
|
@ -10,7 +13,8 @@ use crate::ifs::wl_output::WlOutputGlobal;
|
||||||
use crate::ifs::wl_seat::{SeatIds, WlSeatGlobal};
|
use crate::ifs::wl_seat::{SeatIds, WlSeatGlobal};
|
||||||
use crate::ifs::wl_surface::NoneSurfaceExt;
|
use crate::ifs::wl_surface::NoneSurfaceExt;
|
||||||
use crate::render::RenderContext;
|
use crate::render::RenderContext;
|
||||||
use crate::tree::{DisplayNode, NodeIds};
|
use crate::theme::Theme;
|
||||||
|
use crate::tree::{DisplayNode, Node, NodeIds};
|
||||||
use crate::utils::clonecell::CloneCell;
|
use crate::utils::clonecell::CloneCell;
|
||||||
use crate::utils::copyhashmap::CopyHashMap;
|
use crate::utils::copyhashmap::CopyHashMap;
|
||||||
use crate::utils::linkedlist::LinkedList;
|
use crate::utils::linkedlist::LinkedList;
|
||||||
|
|
@ -51,6 +55,8 @@ pub struct State {
|
||||||
pub none_surface_ext: Rc<NoneSurfaceExt>,
|
pub none_surface_ext: Rc<NoneSurfaceExt>,
|
||||||
pub tree_changed_sent: Cell<bool>,
|
pub tree_changed_sent: Cell<bool>,
|
||||||
pub config: CloneCell<Option<Rc<ConfigProxy>>>,
|
pub config: CloneCell<Option<Rc<ConfigProxy>>>,
|
||||||
|
pub theme: Theme,
|
||||||
|
pub pending_layout: AsyncQueue<Rc<dyn Node>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MouseData {
|
pub struct MouseData {
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,12 @@ impl DeviceApi for dyn Keyboard {
|
||||||
self.removed()
|
self.removed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(self: &Rc<Self>, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) {
|
fn add(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
state: &State,
|
||||||
|
handler: SpawnedFuture<()>,
|
||||||
|
data: Rc<DeviceHandlerData>,
|
||||||
|
) {
|
||||||
state.kb_handlers.borrow_mut().insert(
|
state.kb_handlers.borrow_mut().insert(
|
||||||
self.id(),
|
self.id(),
|
||||||
KeyboardData {
|
KeyboardData {
|
||||||
|
|
@ -83,7 +88,12 @@ impl DeviceApi for dyn Mouse {
|
||||||
self.removed()
|
self.removed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(self: &Rc<Self>, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) {
|
fn add(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
state: &State,
|
||||||
|
handler: SpawnedFuture<()>,
|
||||||
|
data: Rc<DeviceHandlerData>,
|
||||||
|
) {
|
||||||
state.mouse_handlers.borrow_mut().insert(
|
state.mouse_handlers.borrow_mut().insert(
|
||||||
self.id(),
|
self.id(),
|
||||||
MouseData {
|
MouseData {
|
||||||
|
|
|
||||||
0
src/tasks/layout.rs
Normal file
0
src/tasks/layout.rs
Normal file
|
|
@ -17,3 +17,12 @@ pub async fn handle_slow_clients(state: Rc<State>) {
|
||||||
let mut sch = SlowClientHandler { state };
|
let mut sch = SlowClientHandler { state };
|
||||||
sch.handle_events().await;
|
sch.handle_events().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn do_layout(state: Rc<State>) {
|
||||||
|
loop {
|
||||||
|
let node = state.pending_layout.pop().await;
|
||||||
|
if node.needs_layout() {
|
||||||
|
node.do_layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ impl OutputHandler {
|
||||||
stacked: Default::default(),
|
stacked: Default::default(),
|
||||||
seat_state: Default::default(),
|
seat_state: Default::default(),
|
||||||
});
|
});
|
||||||
|
on.workspaces.borrow_mut().push(workspace.clone());
|
||||||
on.workspace.set(Some(workspace));
|
on.workspace.set(Some(workspace));
|
||||||
self.state.root.outputs.set(self.output.id(), on.clone());
|
self.state.root.outputs.set(self.output.id(), on.clone());
|
||||||
self.state.add_global(&global);
|
self.state.add_global(&global);
|
||||||
|
|
|
||||||
60
src/theme.rs
Normal file
60
src/theme.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
use std::cell::Cell;
|
||||||
|
use crate::NumCell;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct Color {
|
||||||
|
pub r: f32,
|
||||||
|
pub g: f32,
|
||||||
|
pub b: f32,
|
||||||
|
pub a: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_f32(c: u8) -> f32 {
|
||||||
|
c as f32 / 255 as f32
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Color {
|
||||||
|
pub fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||||
|
Self {
|
||||||
|
r: to_f32(r),
|
||||||
|
g: to_f32(g),
|
||||||
|
b: to_f32(b),
|
||||||
|
a: to_f32(a),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i4config::theme::Color> for Color {
|
||||||
|
fn from(f: i4config::theme::Color) -> Self {
|
||||||
|
Self {
|
||||||
|
r: to_f32(f.r),
|
||||||
|
g: to_f32(f.g),
|
||||||
|
b: to_f32(f.b),
|
||||||
|
a: to_f32(f.a),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Theme {
|
||||||
|
pub background_color: Cell<Color>,
|
||||||
|
pub title_color: Cell<Color>,
|
||||||
|
pub underline_color: Cell<Color>,
|
||||||
|
pub border_color: Cell<Color>,
|
||||||
|
pub title_height: Cell<i32>,
|
||||||
|
pub border_width: Cell<i32>,
|
||||||
|
pub version: NumCell<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Theme {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
background_color: Cell::new(Color::from_rgba(0, 0, 0, 255)),
|
||||||
|
title_color: Cell::new(Color::from_rgba(0x46, 0x04, 0x17, 255)),
|
||||||
|
underline_color: Cell::new(Color::from_rgba(0x66, 0x24, 0x37, 255)),
|
||||||
|
border_color: Cell::new(Color::from_rgba(0x36, 0x00, 0x07, 255)),
|
||||||
|
title_height: Cell::new(17),
|
||||||
|
border_width: Cell::new(4),
|
||||||
|
version: NumCell::new(1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::backend::KeyState;
|
use crate::backend::{KeyState};
|
||||||
use crate::cursor::KnownCursor;
|
use crate::cursor::KnownCursor;
|
||||||
use crate::fixed::Fixed;
|
use crate::fixed::Fixed;
|
||||||
use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT};
|
use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT};
|
||||||
use crate::rect::Rect;
|
use crate::rect::Rect;
|
||||||
use crate::render::Renderer;
|
use crate::render::Renderer;
|
||||||
use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode};
|
use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode};
|
||||||
use crate::utils::clonecell::CloneCell;
|
use crate::utils::clonecell::CloneCell;
|
||||||
use crate::utils::linkedlist::{LinkedList, LinkedNode, NodeRef};
|
use crate::utils::linkedlist::{LinkedList, LinkedNode, NodeRef};
|
||||||
use crate::{NumCell, State};
|
use crate::{NumCell, State};
|
||||||
|
|
@ -51,9 +51,6 @@ pub enum ContainerFocus {
|
||||||
|
|
||||||
tree_id!(ContainerNodeId);
|
tree_id!(ContainerNodeId);
|
||||||
|
|
||||||
pub const CONTAINER_TITLE_HEIGHT: i32 = 18;
|
|
||||||
pub const CONTAINER_BORDER: i32 = 4;
|
|
||||||
|
|
||||||
pub struct ContainerNode {
|
pub struct ContainerNode {
|
||||||
pub id: ContainerNodeId,
|
pub id: ContainerNodeId,
|
||||||
pub parent: CloneCell<Rc<dyn Node>>,
|
pub parent: CloneCell<Rc<dyn Node>>,
|
||||||
|
|
@ -67,12 +64,16 @@ pub struct ContainerNode {
|
||||||
pub height: Cell<i32>,
|
pub height: Cell<i32>,
|
||||||
pub content_width: Cell<i32>,
|
pub content_width: Cell<i32>,
|
||||||
pub content_height: Cell<i32>,
|
pub content_height: Cell<i32>,
|
||||||
|
pub sum_factors: Cell<f64>,
|
||||||
|
pub theme_version: Cell<u32>,
|
||||||
|
pub needs_layout: Cell<bool>,
|
||||||
num_children: NumCell<usize>,
|
num_children: NumCell<usize>,
|
||||||
pub children: LinkedList<ContainerChild>,
|
pub children: LinkedList<ContainerChild>,
|
||||||
child_nodes: RefCell<AHashMap<NodeId, LinkedNode<ContainerChild>>>,
|
child_nodes: RefCell<AHashMap<NodeId, LinkedNode<ContainerChild>>>,
|
||||||
seat_state: NodeSeatState,
|
seat_state: NodeSeatState,
|
||||||
workspace: CloneCell<Rc<WorkspaceNode>>,
|
workspace: CloneCell<Rc<WorkspaceNode>>,
|
||||||
seats: RefCell<AHashMap<SeatId, SeatState>>,
|
seats: RefCell<AHashMap<SeatId, SeatState>>,
|
||||||
|
state: Rc<State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for ContainerNode {
|
impl Debug for ContainerNode {
|
||||||
|
|
@ -116,10 +117,11 @@ impl ContainerChild {
|
||||||
|
|
||||||
impl ContainerNode {
|
impl ContainerNode {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
state: &State,
|
state: &Rc<State>,
|
||||||
workspace: &Rc<WorkspaceNode>,
|
workspace: &Rc<WorkspaceNode>,
|
||||||
parent: Rc<dyn Node>,
|
parent: Rc<dyn Node>,
|
||||||
child: Rc<dyn Node>,
|
child: Rc<dyn Node>,
|
||||||
|
split: ContainerSplit,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
child.clone().set_workspace(workspace);
|
child.clone().set_workspace(workspace);
|
||||||
let children = LinkedList::new();
|
let children = LinkedList::new();
|
||||||
|
|
@ -137,7 +139,7 @@ impl ContainerNode {
|
||||||
Self {
|
Self {
|
||||||
id: state.node_ids.next(),
|
id: state.node_ids.next(),
|
||||||
parent: CloneCell::new(parent),
|
parent: CloneCell::new(parent),
|
||||||
split: Cell::new(ContainerSplit::Horizontal),
|
split: Cell::new(split),
|
||||||
mono_child: CloneCell::new(None),
|
mono_child: CloneCell::new(None),
|
||||||
mono_body: Cell::new(Default::default()),
|
mono_body: Cell::new(Default::default()),
|
||||||
mono_content: Cell::new(Default::default()),
|
mono_content: Cell::new(Default::default()),
|
||||||
|
|
@ -147,12 +149,16 @@ impl ContainerNode {
|
||||||
height: Cell::new(0),
|
height: Cell::new(0),
|
||||||
content_width: Cell::new(0),
|
content_width: Cell::new(0),
|
||||||
content_height: Cell::new(0),
|
content_height: Cell::new(0),
|
||||||
|
sum_factors: Cell::new(1.0),
|
||||||
|
theme_version: Cell::new(0),
|
||||||
|
needs_layout: Cell::new(false),
|
||||||
num_children: NumCell::new(1),
|
num_children: NumCell::new(1),
|
||||||
children,
|
children,
|
||||||
child_nodes: RefCell::new(child_nodes),
|
child_nodes: RefCell::new(child_nodes),
|
||||||
seat_state: Default::default(),
|
seat_state: Default::default(),
|
||||||
workspace: CloneCell::new(workspace.clone()),
|
workspace: CloneCell::new(workspace.clone()),
|
||||||
seats: RefCell::new(Default::default()),
|
seats: RefCell::new(Default::default()),
|
||||||
|
state: state.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,7 +232,19 @@ impl ContainerNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_factors(&self, sum_factors: f64) {
|
fn apply_factors(self: &Rc<Self>, sum_factors: f64) {
|
||||||
|
self.sum_factors.set(sum_factors);
|
||||||
|
self.needs_layout.set(true);
|
||||||
|
self.state.pending_layout.push(self.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_apply_factors(&self) {
|
||||||
|
if self.theme_version.get() != self.state.theme.version.get() {
|
||||||
|
self.update_content_size();
|
||||||
|
}
|
||||||
|
let sum_factors = self.sum_factors.get();
|
||||||
|
let border_width = self.state.theme.border_width.get();
|
||||||
|
let title_height = self.state.theme.title_height.get();
|
||||||
let split = self.split.get();
|
let split = self.split.get();
|
||||||
let (content_size, other_content_size) = match split {
|
let (content_size, other_content_size) = match split {
|
||||||
ContainerSplit::Horizontal => (self.content_width.get(), self.content_height.get()),
|
ContainerSplit::Horizontal => (self.content_width.get(), self.content_height.get()),
|
||||||
|
|
@ -243,20 +261,15 @@ impl ContainerNode {
|
||||||
remaining_content_size -= body_size;
|
remaining_content_size -= body_size;
|
||||||
let (x1, y1, width, height) = match split {
|
let (x1, y1, width, height) = match split {
|
||||||
ContainerSplit::Horizontal => {
|
ContainerSplit::Horizontal => {
|
||||||
(pos, CONTAINER_TITLE_HEIGHT, body_size, other_content_size)
|
(pos, title_height + 1, body_size, other_content_size)
|
||||||
}
|
}
|
||||||
_ => (
|
_ => (0, pos + title_height + 1, other_content_size, body_size),
|
||||||
0,
|
|
||||||
pos + CONTAINER_TITLE_HEIGHT,
|
|
||||||
other_content_size,
|
|
||||||
body_size,
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
let body = Rect::new_sized(x1, y1, width, height).unwrap();
|
let body = Rect::new_sized(x1, y1, width, height).unwrap();
|
||||||
child.body.set(body);
|
child.body.set(body);
|
||||||
pos += body_size + CONTAINER_BORDER;
|
pos += body_size + border_width;
|
||||||
if split == ContainerSplit::Vertical {
|
if split == ContainerSplit::Vertical {
|
||||||
pos += CONTAINER_TITLE_HEIGHT;
|
pos += title_height + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if remaining_content_size > 0 {
|
if remaining_content_size > 0 {
|
||||||
|
|
@ -273,13 +286,7 @@ impl ContainerNode {
|
||||||
let (x1, y1, width, height, size) = match split {
|
let (x1, y1, width, height, size) = match split {
|
||||||
ContainerSplit::Horizontal => {
|
ContainerSplit::Horizontal => {
|
||||||
let width = body.width() + add;
|
let width = body.width() + add;
|
||||||
(
|
(pos, title_height + 1, width, other_content_size, width)
|
||||||
pos,
|
|
||||||
CONTAINER_TITLE_HEIGHT,
|
|
||||||
width,
|
|
||||||
other_content_size,
|
|
||||||
width,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let height = body.height() + add;
|
let height = body.height() + add;
|
||||||
|
|
@ -288,12 +295,14 @@ impl ContainerNode {
|
||||||
};
|
};
|
||||||
body = Rect::new_sized(x1, y1, width, height).unwrap();
|
body = Rect::new_sized(x1, y1, width, height).unwrap();
|
||||||
child.body.set(body);
|
child.body.set(body);
|
||||||
pos += size + CONTAINER_BORDER;
|
pos += size + border_width;
|
||||||
if split == ContainerSplit::Vertical {
|
if split == ContainerSplit::Vertical {
|
||||||
pos += CONTAINER_TITLE_HEIGHT;
|
pos += title_height + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.sum_factors.set(1.0);
|
||||||
|
self.needs_layout.set(false);
|
||||||
for child in self.children.iter() {
|
for child in self.children.iter() {
|
||||||
let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get());
|
let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get());
|
||||||
child.node.clone().change_extents(&body);
|
child.node.clone().change_extents(&body);
|
||||||
|
|
@ -302,29 +311,32 @@ impl ContainerNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_content_size(&self) {
|
fn update_content_size(&self) {
|
||||||
|
let border_width = self.state.theme.border_width.get();
|
||||||
|
let title_height = self.state.theme.title_height.get();
|
||||||
let nc = self.num_children.get();
|
let nc = self.num_children.get();
|
||||||
match self.split.get() {
|
match self.split.get() {
|
||||||
ContainerSplit::Horizontal => {
|
ContainerSplit::Horizontal => {
|
||||||
let new_content_size = self
|
let new_content_size = self
|
||||||
.width
|
.width
|
||||||
.get()
|
.get()
|
||||||
.saturating_sub((nc - 1) as i32 * CONTAINER_BORDER);
|
.saturating_sub((nc - 1) as i32 * border_width);
|
||||||
self.content_width.set(new_content_size);
|
self.content_width.set(new_content_size);
|
||||||
self.content_height
|
self.content_height
|
||||||
.set(self.height.get().saturating_sub(CONTAINER_TITLE_HEIGHT));
|
.set(self.height.get().saturating_sub(title_height + 1));
|
||||||
}
|
}
|
||||||
ContainerSplit::Vertical => {
|
ContainerSplit::Vertical => {
|
||||||
let new_content_size = self.height.get().saturating_sub(
|
let new_content_size = self.height.get().saturating_sub(
|
||||||
CONTAINER_TITLE_HEIGHT
|
title_height + 1 + (nc - 1) as i32 * (border_width + title_height + 1),
|
||||||
+ (nc - 1) as i32 * (CONTAINER_BORDER + CONTAINER_TITLE_HEIGHT),
|
|
||||||
);
|
);
|
||||||
self.content_height.set(new_content_size);
|
self.content_height.set(new_content_size);
|
||||||
self.content_width.set(self.width.get());
|
self.content_width.set(self.width.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.theme_version.set(self.state.theme.version.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pointer_move(&self, seat: &Rc<WlSeatGlobal>, x: i32, y: i32) {
|
fn pointer_move(self: &Rc<Self>, seat: &Rc<WlSeatGlobal>, mut x: i32, mut y: i32) {
|
||||||
|
let title_height = self.state.theme.title_height.get();
|
||||||
let mut seats = self.seats.borrow_mut();
|
let mut seats = self.seats.borrow_mut();
|
||||||
let seat_state = seats.entry(seat.id()).or_insert_with(|| SeatState {
|
let seat_state = seats.entry(seat.id()).or_insert_with(|| SeatState {
|
||||||
cursor: KnownCursor::Default,
|
cursor: KnownCursor::Default,
|
||||||
|
|
@ -350,9 +362,7 @@ impl ContainerNode {
|
||||||
let (prev_factor, child_factor) = match self.split.get() {
|
let (prev_factor, child_factor) = match self.split.get() {
|
||||||
ContainerSplit::Horizontal => {
|
ContainerSplit::Horizontal => {
|
||||||
let cw = self.content_width.get();
|
let cw = self.content_width.get();
|
||||||
if prev_body.x1() + dist_left > x || x + dist_right > child_body.x2() {
|
x = x.max(prev_body.x1() + dist_left).min(child_body.x2() - dist_right);
|
||||||
return;
|
|
||||||
}
|
|
||||||
let prev_factor = (x - prev_body.x1() - dist_left) as f64 / cw as f64;
|
let prev_factor = (x - prev_body.x1() - dist_left) as f64 / cw as f64;
|
||||||
let child_factor =
|
let child_factor =
|
||||||
(child_body.x2() - x - dist_right) as f64 / cw as f64;
|
(child_body.x2() - x - dist_right) as f64 / cw as f64;
|
||||||
|
|
@ -360,16 +370,14 @@ impl ContainerNode {
|
||||||
}
|
}
|
||||||
ContainerSplit::Vertical => {
|
ContainerSplit::Vertical => {
|
||||||
let ch = self.content_height.get();
|
let ch = self.content_height.get();
|
||||||
if prev_body.y1() + dist_left > y || y + dist_right > child_body.y2() {
|
y = y.max(prev_body.y1() + dist_left).min(child_body.y2() - dist_right);
|
||||||
return;
|
|
||||||
}
|
|
||||||
let prev_factor = (y - prev_body.y1() - dist_left) as f64 / ch as f64;
|
let prev_factor = (y - prev_body.y1() - dist_left) as f64 / ch as f64;
|
||||||
let child_factor =
|
let child_factor =
|
||||||
(child_body.y2() - y - dist_right) as f64 / ch as f64;
|
(child_body.y2() - y - dist_right) as f64 / ch as f64;
|
||||||
(prev_factor, child_factor)
|
(prev_factor, child_factor)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let sum_factors = 1.0 - prev.factor.get() - op.child.factor.get()
|
let sum_factors = self.sum_factors.get() - prev.factor.get() - op.child.factor.get()
|
||||||
+ prev_factor
|
+ prev_factor
|
||||||
+ child_factor;
|
+ child_factor;
|
||||||
prev.factor.set(prev_factor);
|
prev.factor.set(prev_factor);
|
||||||
|
|
@ -382,7 +390,7 @@ impl ContainerNode {
|
||||||
let new_cursor = if self.mono_child.get().is_some() {
|
let new_cursor = if self.mono_child.get().is_some() {
|
||||||
KnownCursor::Default
|
KnownCursor::Default
|
||||||
} else if self.split.get() == ContainerSplit::Horizontal {
|
} else if self.split.get() == ContainerSplit::Horizontal {
|
||||||
if y < CONTAINER_TITLE_HEIGHT {
|
if y < title_height + 1 {
|
||||||
KnownCursor::Default
|
KnownCursor::Default
|
||||||
} else {
|
} else {
|
||||||
KnownCursor::ResizeLeftRight
|
KnownCursor::ResizeLeftRight
|
||||||
|
|
@ -392,7 +400,7 @@ impl ContainerNode {
|
||||||
for child in self.children.iter() {
|
for child in self.children.iter() {
|
||||||
let body = child.body.get();
|
let body = child.body.get();
|
||||||
if body.y1() > y {
|
if body.y1() > y {
|
||||||
if body.y1() - y > CONTAINER_TITLE_HEIGHT {
|
if body.y1() - y > title_height + 1 {
|
||||||
cursor = KnownCursor::ResizeTopBottom
|
cursor = KnownCursor::ResizeTopBottom
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -440,14 +448,22 @@ impl Node for ContainerNode {
|
||||||
self.seat_state.destroy_node(self);
|
self.seat_state.destroy_node(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn needs_layout(&self) -> bool {
|
||||||
|
self.needs_layout.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_layout(&self) {
|
||||||
|
self.do_apply_factors();
|
||||||
|
}
|
||||||
|
|
||||||
fn get_split(&self) -> Option<ContainerSplit> {
|
fn get_split(&self) -> Option<ContainerSplit> {
|
||||||
Some(self.split.get())
|
Some(self.split.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_split(&self, split: ContainerSplit) {
|
fn set_split(self: Rc<Self>, split: ContainerSplit) {
|
||||||
self.split.set(split);
|
self.split.set(split);
|
||||||
self.update_content_size();
|
self.update_content_size();
|
||||||
self.apply_factors(1.0);
|
self.apply_factors(self.sum_factors.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
fn do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||||
|
|
@ -519,6 +535,7 @@ impl Node for ContainerNode {
|
||||||
if button != BTN_LEFT {
|
if button != BTN_LEFT {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let title_height = self.state.theme.title_height.get();
|
||||||
let mut seat_datas = self.seats.borrow_mut();
|
let mut seat_datas = self.seats.borrow_mut();
|
||||||
let seat_data = match seat_datas.get_mut(&seat.id()) {
|
let seat_data = match seat_datas.get_mut(&seat.id()) {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
|
|
@ -562,7 +579,7 @@ impl Node for ContainerNode {
|
||||||
for child in self.children.iter() {
|
for child in self.children.iter() {
|
||||||
let body = child.body.get();
|
let body = child.body.get();
|
||||||
if seat_data.y < body.y1() {
|
if seat_data.y < body.y1() {
|
||||||
let op = if seat_data.y < body.y1() - CONTAINER_TITLE_HEIGHT {
|
let op = if seat_data.y < body.y1() - title_height - 1 {
|
||||||
SeatOpKind::Resize {
|
SeatOpKind::Resize {
|
||||||
dist_left: seat_data.y - child.prev().unwrap().body.get().y2(),
|
dist_left: seat_data.y - child.prev().unwrap().body.get().y2(),
|
||||||
dist_right: body.y1() - seat_data.y,
|
dist_right: body.y1() - seat_data.y,
|
||||||
|
|
@ -611,7 +628,25 @@ impl Node for ContainerNode {
|
||||||
FindTreeResult::AcceptsInput
|
FindTreeResult::AcceptsInput
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_child(&self, child: &dyn Node) {
|
fn replace_child(&self, old: &dyn Node, new: Rc<dyn Node>) {
|
||||||
|
let node = match self.child_nodes.borrow_mut().remove(&old.id()) {
|
||||||
|
Some(c) => c,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
let link= node.append(ContainerChild {
|
||||||
|
node: new.clone(),
|
||||||
|
body: Cell::new(node.body.get()),
|
||||||
|
content: Cell::new(node.content.get()),
|
||||||
|
factor: Cell::new(node.factor.get()),
|
||||||
|
focus: Cell::new(node.focus.get()),
|
||||||
|
});
|
||||||
|
self.child_nodes.borrow_mut().insert(new.id(), link);
|
||||||
|
new.clone().set_workspace(&self.workspace.get());
|
||||||
|
let body = node.body.get().move_(self.abs_x1.get(), self.abs_y1.get());
|
||||||
|
new.clone().change_extents(&body);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_child(self: Rc<Self>, child: &dyn Node) {
|
||||||
let node = match self.child_nodes.borrow_mut().remove(&child.id()) {
|
let node = match self.child_nodes.borrow_mut().remove(&child.id()) {
|
||||||
Some(c) => c.to_ref(),
|
Some(c) => c.to_ref(),
|
||||||
None => return,
|
None => return,
|
||||||
|
|
@ -619,7 +654,7 @@ impl Node for ContainerNode {
|
||||||
let num_children = self.num_children.fetch_sub(1) - 1;
|
let num_children = self.num_children.fetch_sub(1) - 1;
|
||||||
if num_children == 0 {
|
if num_children == 0 {
|
||||||
self.seats.borrow_mut().clear();
|
self.seats.borrow_mut().clear();
|
||||||
self.parent.get().remove_child(self);
|
self.parent.get().remove_child(&*self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.update_content_size();
|
self.update_content_size();
|
||||||
|
|
@ -670,7 +705,7 @@ impl Node for ContainerNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn motion(&self, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
fn motion(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||||
self.pointer_move(seat, x.round_down(), y.round_down());
|
self.pointer_move(seat, x.round_down(), y.round_down());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -690,8 +725,9 @@ impl Node for ContainerNode {
|
||||||
size_changed |= self.height.replace(rect.height()) != rect.height();
|
size_changed |= self.height.replace(rect.height()) != rect.height();
|
||||||
if size_changed {
|
if size_changed {
|
||||||
self.update_content_size();
|
self.update_content_size();
|
||||||
self.apply_factors(1.0);
|
self.do_apply_factors();
|
||||||
self.cancel_seat_ops();
|
self.cancel_seat_ops();
|
||||||
|
self.parent.get().child_size_changed(&*self, rect.width(), rect.height());
|
||||||
} else {
|
} else {
|
||||||
for child in self.children.iter() {
|
for child in self.children.iter() {
|
||||||
let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get());
|
let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get());
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,14 @@ pub trait Node {
|
||||||
fn seat_state(&self) -> &NodeSeatState;
|
fn seat_state(&self) -> &NodeSeatState;
|
||||||
fn destroy_node(&self, detach: bool);
|
fn destroy_node(&self, detach: bool);
|
||||||
|
|
||||||
|
fn needs_layout(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_layout(&self) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
fn get_parent_split(&self) -> Option<ContainerSplit> {
|
fn get_parent_split(&self) -> Option<ContainerSplit> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +87,11 @@ pub trait Node {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_split(&self, split: ContainerSplit) {
|
fn set_split(self: Rc<Self>, split: ContainerSplit) {
|
||||||
|
let _ = split;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_split(self: Rc<Self>, split: ContainerSplit) {
|
||||||
let _ = split;
|
let _ = split;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,7 +166,12 @@ pub trait Node {
|
||||||
FindTreeResult::Other
|
FindTreeResult::Other
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_child(&self, child: &dyn Node) {
|
fn replace_child(&self, old: &dyn Node, new: Rc<dyn Node>) {
|
||||||
|
let _ = old;
|
||||||
|
let _ = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_child(self: Rc<Self>, child: &dyn Node) {
|
||||||
let _ = child;
|
let _ = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,7 +197,7 @@ pub trait Node {
|
||||||
let _ = seat;
|
let _ = seat;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn motion(&self, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
fn motion(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||||
let _ = seat;
|
let _ = seat;
|
||||||
let _ = x;
|
let _ = x;
|
||||||
let _ = y;
|
let _ = y;
|
||||||
|
|
@ -258,6 +275,7 @@ pub struct DisplayNode {
|
||||||
pub outputs: CopyHashMap<OutputId, Rc<OutputNode>>,
|
pub outputs: CopyHashMap<OutputId, Rc<OutputNode>>,
|
||||||
pub stacked: LinkedList<Rc<dyn Node>>,
|
pub stacked: LinkedList<Rc<dyn Node>>,
|
||||||
pub seat_state: NodeSeatState,
|
pub seat_state: NodeSeatState,
|
||||||
|
pub needs_layout: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DisplayNode {
|
impl DisplayNode {
|
||||||
|
|
@ -267,6 +285,7 @@ impl DisplayNode {
|
||||||
outputs: Default::default(),
|
outputs: Default::default(),
|
||||||
stacked: Default::default(),
|
stacked: Default::default(),
|
||||||
seat_state: Default::default(),
|
seat_state: Default::default(),
|
||||||
|
needs_layout: Cell::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -292,6 +311,18 @@ impl Node for DisplayNode {
|
||||||
self.seat_state.destroy_node(self);
|
self.seat_state.destroy_node(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn needs_layout(&self) -> bool {
|
||||||
|
self.needs_layout.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_layout(&self) {
|
||||||
|
self.needs_layout.set(false);
|
||||||
|
let outputs = self.outputs.lock();
|
||||||
|
for output in outputs.values() {
|
||||||
|
output.do_layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
||||||
for stacked in self.stacked.rev_iter() {
|
for stacked in self.stacked.rev_iter() {
|
||||||
let ext = stacked.absolute_position();
|
let ext = stacked.absolute_position();
|
||||||
|
|
@ -365,7 +396,7 @@ impl Node for OutputNode {
|
||||||
|
|
||||||
fn destroy_node(&self, detach: bool) {
|
fn destroy_node(&self, detach: bool) {
|
||||||
if detach {
|
if detach {
|
||||||
self.display.remove_child(self);
|
self.display.clone().remove_child(self);
|
||||||
}
|
}
|
||||||
let mut workspaces = self.workspaces.borrow_mut();
|
let mut workspaces = self.workspaces.borrow_mut();
|
||||||
for workspace in workspaces.drain(..) {
|
for workspace in workspaces.drain(..) {
|
||||||
|
|
@ -374,6 +405,13 @@ impl Node for OutputNode {
|
||||||
self.seat_state.destroy_node(self);
|
self.seat_state.destroy_node(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_layout(&self) {
|
||||||
|
let workspaces = self.workspaces.borrow_mut();
|
||||||
|
for ws in workspaces.deref() {
|
||||||
|
ws.do_layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn absolute_position(&self) -> Rect {
|
fn absolute_position(&self) -> Rect {
|
||||||
self.position.get()
|
self.position.get()
|
||||||
}
|
}
|
||||||
|
|
@ -390,7 +428,7 @@ impl Node for OutputNode {
|
||||||
FindTreeResult::AcceptsInput
|
FindTreeResult::AcceptsInput
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_child(&self, _child: &dyn Node) {
|
fn remove_child(self: Rc<Self>, _child: &dyn Node) {
|
||||||
self.workspace.set(None);
|
self.workspace.set(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -464,7 +502,7 @@ impl Node for FloatNode {
|
||||||
child.find_tree_at(x, y, tree)
|
child.find_tree_at(x, y, tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_child(&self, _child: &dyn Node) {
|
fn remove_child(self: Rc<Self>, _child: &dyn Node) {
|
||||||
self.child.set(None);
|
self.child.set(None);
|
||||||
self.display_link.set(None);
|
self.display_link.set(None);
|
||||||
self.workspace_link.set(None);
|
self.workspace_link.set(None);
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,15 @@ impl Node for WorkspaceNode {
|
||||||
self.seat_state.destroy_node(self);
|
self.seat_state.destroy_node(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_layout(&self) {
|
||||||
|
if let Some(c) = self.container.get() {
|
||||||
|
c.do_layout();
|
||||||
|
}
|
||||||
|
for s in self.stacked.iter() {
|
||||||
|
s.do_layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn absolute_position(&self) -> Rect {
|
fn absolute_position(&self) -> Rect {
|
||||||
self.output.get().position.get()
|
self.output.get().position.get()
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +72,7 @@ impl Node for WorkspaceNode {
|
||||||
FindTreeResult::AcceptsInput
|
FindTreeResult::AcceptsInput
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_child(&self, _child: &dyn Node) {
|
fn remove_child(self: Rc<Self>, _child: &dyn Node) {
|
||||||
self.container.set(None);
|
self.container.set(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue