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
|
|
@ -6,8 +6,7 @@ linear_ids!(OutputIds, OutputId);
|
|||
linear_ids!(KeyboardIds, KeyboardId);
|
||||
linear_ids!(MouseIds, MouseId);
|
||||
|
||||
pub trait Backend {
|
||||
}
|
||||
pub trait Backend {}
|
||||
|
||||
pub trait Output {
|
||||
fn id(&self) -> OutputId;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
use std::rc::Rc;
|
||||
use crate::backend::Backend;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct DummyBackend {
|
||||
|
||||
}
|
||||
pub struct DummyBackend {}
|
||||
|
||||
impl DummyBackend {
|
||||
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 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::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
|
||||
use crate::drm::{ModifiedFormat, INVALID_MODIFIER};
|
||||
|
|
@ -211,8 +214,7 @@ pub struct XorgBackend {
|
|||
b: Cell<f32>,
|
||||
}
|
||||
|
||||
impl Backend for XorgBackend {
|
||||
}
|
||||
impl Backend for XorgBackend {}
|
||||
|
||||
fn get_drm(con: &XcbCon) -> Result<Drm, XorgBackendError> {
|
||||
unsafe {
|
||||
|
|
@ -1098,7 +1100,9 @@ impl Keyboard for XorgSeat {
|
|||
0,
|
||||
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) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
|
|
@ -1110,7 +1114,9 @@ impl Keyboard for XorgSeat {
|
|||
log::error!("Could not grab device {}: status = {}", self.kb, res.status);
|
||||
}
|
||||
} 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) {
|
||||
log::error!("Could not ungrab device {}: {}", self.kb, ErrorFmt(e));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::backend::{KeyboardId, MouseId};
|
||||
use crate::ifs::wl_seat::{SeatId, WlSeatGlobal};
|
||||
use crate::state::{DeviceHandlerData};
|
||||
use crate::state::DeviceHandlerData;
|
||||
use crate::tree::ContainerSplit;
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::utils::debug_fn::debug_fn;
|
||||
|
|
@ -54,7 +54,7 @@ impl ConfigProxyHandler {
|
|||
msg: &str,
|
||||
file: Option<&str>,
|
||||
line: Option<u32>,
|
||||
) -> Result<(), LogError> {
|
||||
) {
|
||||
let level = match level {
|
||||
LogLevel::Error => Level::Error,
|
||||
LogLevel::Warn => Level::Warn,
|
||||
|
|
@ -74,10 +74,9 @@ impl ConfigProxyHandler {
|
|||
Ok(())
|
||||
});
|
||||
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 seat = WlSeatGlobal::new(global_name, name, &self.state);
|
||||
self.state.globals.add_global(&self.state, &seat);
|
||||
|
|
@ -86,7 +85,6 @@ impl ConfigProxyHandler {
|
|||
seat: Seat(seat.id().raw() as _),
|
||||
},
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_parse_keymap(&self, keymap: &str) -> Result<(), ParseKeymapError> {
|
||||
|
|
@ -248,7 +246,7 @@ impl ConfigProxyHandler {
|
|||
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 matches = |dhd: &DeviceHandlerData| {
|
||||
let id = match id {
|
||||
|
|
@ -280,10 +278,9 @@ impl ConfigProxyHandler {
|
|||
self.send(&ServerMessage::Response {
|
||||
response: Response::GetInputDevices { devices: res },
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_get_seats(&self) -> Result<(), GetSeatsError> {
|
||||
fn handle_get_seats(&self) {
|
||||
let seats = {
|
||||
let seats = self.state.globals.seats.lock();
|
||||
seats
|
||||
|
|
@ -294,7 +291,6 @@ impl ConfigProxyHandler {
|
|||
self.send(&ServerMessage::Response {
|
||||
response: Response::GetSeats { seats },
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_run(
|
||||
|
|
@ -311,16 +307,78 @@ impl ConfigProxyHandler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_grab(
|
||||
&self,
|
||||
kb: Keyboard,
|
||||
grab: bool,
|
||||
) -> Result<(), GrabError> {
|
||||
fn handle_grab(&self, kb: Keyboard, grab: bool) -> Result<(), GrabError> {
|
||||
let kb = self.get_kb(kb)?;
|
||||
kb.grab(grab);
|
||||
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]) {
|
||||
if let Err(e) = self.handle_request_(msg) {
|
||||
log::error!("Could not handle client request: {}", ErrorFmt(e));
|
||||
|
|
@ -339,8 +397,8 @@ impl ConfigProxyHandler {
|
|||
msg,
|
||||
file,
|
||||
line,
|
||||
} => self.handle_log_request(level, msg, file, line)?,
|
||||
ClientMessage::CreateSeat { name } => self.handle_create_seat(name)?,
|
||||
} => 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::SeatSetKeymap { seat, keymap } => {
|
||||
self.handle_set_keymap(seat, keymap)?
|
||||
|
|
@ -360,11 +418,22 @@ impl ConfigProxyHandler {
|
|||
}
|
||||
ClientMessage::Focus { seat, direction } => self.handle_focus(seat, direction)?,
|
||||
ClientMessage::Move { seat, direction } => {}
|
||||
ClientMessage::GetInputDevices { seat } => self.handle_get_input_devices(seat)?,
|
||||
ClientMessage::GetSeats => self.handle_get_seats()?,
|
||||
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::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(())
|
||||
}
|
||||
|
|
@ -372,10 +441,6 @@ impl ConfigProxyHandler {
|
|||
|
||||
#[derive(Debug, Error)]
|
||||
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")]
|
||||
ParseKeymapError(#[from] ParseKeymapError),
|
||||
#[error("Could not process a `set_seat` request")]
|
||||
|
|
@ -384,10 +449,6 @@ enum CphError {
|
|||
AddShortcutError(#[from] AddShortcutError),
|
||||
#[error("Could not process a `remove_shortcut` request")]
|
||||
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")]
|
||||
SeatSetKeymapError(#[from] SeatSetKeymapError),
|
||||
#[error("Could not process a `get_repeat_rate` request")]
|
||||
|
|
@ -404,6 +465,12 @@ enum CphError {
|
|||
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 `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")]
|
||||
DeviceDoesNotExist(InputDevice),
|
||||
#[error("Device {0:?} does not exist")]
|
||||
|
|
@ -416,12 +483,6 @@ enum CphError {
|
|||
ParsingFailed(#[source] DecodeError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum LogError {}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum CreateSeatError {}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum ParseKeymapError {
|
||||
#[error("Parsing failed")]
|
||||
|
|
@ -449,12 +510,6 @@ enum RemoveShortcutError {
|
|||
}
|
||||
efrom!(RemoveShortcutError, CphError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum GetInputDevicesError {}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum GetSeatsError {}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum SeatSetKeymapError {
|
||||
#[error(transparent)]
|
||||
|
|
@ -513,3 +568,26 @@ enum GrabError {
|
|||
CphError(#[from] Box<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)
|
||||
}
|
||||
|
||||
pub fn create_split(&self, axis: ContainerSplit) {
|
||||
self.keyboard_node.get().create_split(axis)
|
||||
}
|
||||
|
||||
pub fn get_rate(&self) -> (i32, i32) {
|
||||
self.repeat_rate.get()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ impl PointerOwner for DefaultPointerOwner {
|
|||
}
|
||||
if (stack.len(), found_tree.len()) == (divergence, divergence) {
|
||||
if let Some(node) = found_tree.last() {
|
||||
node.node
|
||||
node.node.clone()
|
||||
.motion(seat, x.apply_fract(node.x), y.apply_fract(node.y));
|
||||
}
|
||||
} else {
|
||||
|
|
@ -242,7 +242,7 @@ impl PointerOwner for GrabPointerOwner {
|
|||
let (x, y) = seat.pos.get();
|
||||
let pos = self.node.absolute_position();
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -618,6 +618,10 @@ impl Node for WlSurface {
|
|||
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) {
|
||||
let xdg = match self.xdg.get() {
|
||||
Some(x) => x,
|
||||
|
|
@ -670,8 +674,8 @@ impl Node for WlSurface {
|
|||
seat.enter_surface(&self, x, y)
|
||||
}
|
||||
|
||||
fn motion(&self, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||
seat.motion_surface(self, x, y)
|
||||
fn motion(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||
seat.motion_surface(&*self, x, y)
|
||||
}
|
||||
|
||||
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
|
||||
|
|
|
|||
|
|
@ -83,6 +83,10 @@ pub trait XdgSurfaceExt: Debug {
|
|||
let _ = split;
|
||||
}
|
||||
|
||||
fn create_split(self: Rc<Self>, split: ContainerSplit) {
|
||||
let _ = split;
|
||||
}
|
||||
|
||||
fn move_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||
let _ = seat;
|
||||
let _ = direction;
|
||||
|
|
@ -158,6 +162,10 @@ impl XdgSurface {
|
|||
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) {
|
||||
let ext = match self.ext.get() {
|
||||
None => return,
|
||||
|
|
|
|||
|
|
@ -373,6 +373,7 @@ impl XdgToplevel {
|
|||
&workspace,
|
||||
workspace.clone(),
|
||||
self.clone(),
|
||||
ContainerSplit::Horizontal,
|
||||
));
|
||||
workspace.set_container(&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));
|
||||
}
|
||||
|
||||
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) {
|
||||
let pn = match self.parent_node.get() {
|
||||
Some(pn) => pn,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
use crate::acceptor::AcceptorError;
|
||||
use crate::async_engine::AsyncError;
|
||||
use crate::backends::dummy::DummyBackend;
|
||||
use crate::backends::xorg::{XorgBackend, XorgBackendError};
|
||||
use crate::client::Clients;
|
||||
use crate::clientmem::ClientMemError;
|
||||
|
|
@ -26,6 +27,7 @@ use crate::render::RenderError;
|
|||
use crate::sighand::SighandError;
|
||||
use crate::state::State;
|
||||
use crate::tree::{DisplayNode, NodeIds};
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::errorfmt::ErrorFmt;
|
||||
use crate::utils::numcell::NumCell;
|
||||
use crate::utils::queue::AsyncQueue;
|
||||
|
|
@ -40,8 +42,6 @@ use std::ops::Deref;
|
|||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use wheel::Wheel;
|
||||
use crate::backends::dummy::DummyBackend;
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
|
@ -71,6 +71,7 @@ mod servermem;
|
|||
mod sighand;
|
||||
mod state;
|
||||
mod tasks;
|
||||
mod theme;
|
||||
mod time;
|
||||
mod tree;
|
||||
mod utils;
|
||||
|
|
@ -153,6 +154,8 @@ fn main_() -> Result<(), MainError> {
|
|||
config: Default::default(),
|
||||
mouse_ids: Default::default(),
|
||||
kb_handlers: Default::default(),
|
||||
theme: Default::default(),
|
||||
pending_layout: Default::default(),
|
||||
});
|
||||
forker.install(&state);
|
||||
let backend = XorgBackend::new(&state)?;
|
||||
|
|
@ -161,6 +164,7 @@ fn main_() -> Result<(), MainError> {
|
|||
state.config.set(Some(Rc::new(config)));
|
||||
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 _do_layout = engine.spawn(tasks::do_layout(state.clone()));
|
||||
let socket_path = Acceptor::install(&state)?;
|
||||
forker.setenv(b"WAYLAND_DISPLAY", socket_path.as_bytes());
|
||||
el.run()?;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ impl Framebuffer {
|
|||
let mut renderer = Renderer {
|
||||
ctx: &self.ctx,
|
||||
fb: &self.gl,
|
||||
state,
|
||||
};
|
||||
node.render(&mut renderer, 0, 0);
|
||||
if let Some(rect) = cursor_rect {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ use crate::render::sys::{glDisable, glEnable, GL_BLEND};
|
|||
use crate::render::Texture;
|
||||
use crate::tree::{
|
||||
ContainerFocus, ContainerNode, ContainerSplit, FloatNode, OutputNode, WorkspaceNode,
|
||||
CONTAINER_BORDER, CONTAINER_TITLE_HEIGHT,
|
||||
};
|
||||
use crate::State;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
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(super) ctx: &'a RenderContext,
|
||||
pub(super) fb: &'a GlFrameBuffer,
|
||||
pub(super) state: &'a State,
|
||||
}
|
||||
|
||||
impl Renderer<'_> {
|
||||
|
|
@ -104,21 +100,22 @@ impl Renderer<'_> {
|
|||
}
|
||||
|
||||
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 cheight = container.height.get();
|
||||
let num_children = container.num_children();
|
||||
let title_rect =
|
||||
Rect::new_sized(x, y, container.width.get(), CONTAINER_TITLE_HEIGHT - 1).unwrap();
|
||||
let title_rect = Rect::new_sized(x, y, container.width.get(), title_height).unwrap();
|
||||
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() {
|
||||
let space_per_child = cwidth / num_children as i32;
|
||||
let mut rem = cwidth % num_children as i32;
|
||||
let mut pos = x;
|
||||
let (r, g, b) = focus_color(ContainerFocus::None);
|
||||
self.fill_boxes(slice::from_ref(&title_rect), r, g, b, 1.0);
|
||||
let (r, g, b) = BORDER_COLOR;
|
||||
self.fill_boxes(slice::from_ref(&underline_rect), r, g, b, 1.0);
|
||||
let c = self.state.theme.border_color.get();
|
||||
self.fill_boxes(slice::from_ref(&underline_rect), c.r, c.g, c.b, c.a);
|
||||
for child in container.children.iter() {
|
||||
let focus = child.focus.get();
|
||||
let (r, g, b) = focus_color(focus);
|
||||
|
|
@ -128,7 +125,7 @@ impl Renderer<'_> {
|
|||
width += 1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
pos += width as i32;
|
||||
|
|
@ -157,48 +154,50 @@ impl Renderer<'_> {
|
|||
let border_rect = if split == ContainerSplit::Horizontal {
|
||||
Rect::new_sized(
|
||||
x + body.x2(),
|
||||
y + body.y1() - CONTAINER_TITLE_HEIGHT,
|
||||
CONTAINER_BORDER,
|
||||
y + body.y1() - title_height - 1,
|
||||
border_width,
|
||||
container.height.get(),
|
||||
)
|
||||
.unwrap()
|
||||
} else {
|
||||
title_rects.push(Rect::new_sized(
|
||||
x,
|
||||
y + body.y2() + CONTAINER_BORDER,
|
||||
container.width.get(),
|
||||
CONTAINER_TITLE_HEIGHT - 1,
|
||||
).unwrap());
|
||||
underline_rects.push(Rect::new_sized(
|
||||
x,
|
||||
y + body.y2() + CONTAINER_BORDER + CONTAINER_TITLE_HEIGHT - 1,
|
||||
container.width.get(),
|
||||
1,
|
||||
).unwrap());
|
||||
Rect::new_sized(
|
||||
x,
|
||||
y + body.y2(),
|
||||
container.width.get(),
|
||||
CONTAINER_BORDER,
|
||||
)
|
||||
.unwrap()
|
||||
title_rects.push(
|
||||
Rect::new_sized(
|
||||
x,
|
||||
y + body.y2() + border_width,
|
||||
container.width.get(),
|
||||
title_height,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
underline_rects.push(
|
||||
Rect::new_sized(
|
||||
x,
|
||||
y + body.y2() + border_width + title_height,
|
||||
container.width.get(),
|
||||
1,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
Rect::new_sized(x, y + body.y2(), container.width.get(), border_width)
|
||||
.unwrap()
|
||||
};
|
||||
border_rects.push(border_rect);
|
||||
}
|
||||
}
|
||||
{
|
||||
let (r, g, b) = TITLE_COLOR;
|
||||
self.fill_boxes(&title_rects, r, g, b, 1.0);
|
||||
let (r, g, b) = UNDERLINE_COLOR;
|
||||
self.fill_boxes(&underline_rects, r, g, b, 1.0);
|
||||
let (r, g, b) = BORDER_COLOR;
|
||||
self.fill_boxes(&border_rects, r, g, b, 1.0);
|
||||
let c = self.state.theme.title_color.get();
|
||||
self.fill_boxes(&title_rects, c.r, c.g, c.b, c.a);
|
||||
let c = self.state.theme.underline_color.get();
|
||||
self.fill_boxes(&underline_rects, c.r, c.g, c.b, c.a);
|
||||
let c = self.state.theme.border_color.get();
|
||||
self.fill_boxes(&border_rects, c.r, c.g, c.b, c.a);
|
||||
}
|
||||
for child in container.children.iter() {
|
||||
let body = child.body.get();
|
||||
if body.x1() >= cwidth || body.y1() >= cheight {
|
||||
break;
|
||||
}
|
||||
let body = body.move_(container.abs_x1.get(), container.abs_y1.get());
|
||||
unsafe {
|
||||
with_scissor(&body, || {
|
||||
let content = child.content.get();
|
||||
|
|
@ -323,7 +322,6 @@ impl Renderer<'_> {
|
|||
}
|
||||
|
||||
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() {
|
||||
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::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::config::ConfigProxy;
|
||||
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_surface::NoneSurfaceExt;
|
||||
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::copyhashmap::CopyHashMap;
|
||||
use crate::utils::linkedlist::LinkedList;
|
||||
|
|
@ -51,6 +55,8 @@ pub struct State {
|
|||
pub none_surface_ext: Rc<NoneSurfaceExt>,
|
||||
pub tree_changed_sent: Cell<bool>,
|
||||
pub config: CloneCell<Option<Rc<ConfigProxy>>>,
|
||||
pub theme: Theme,
|
||||
pub pending_layout: AsyncQueue<Rc<dyn Node>>,
|
||||
}
|
||||
|
||||
pub struct MouseData {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,12 @@ impl DeviceApi for dyn Keyboard {
|
|||
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(
|
||||
self.id(),
|
||||
KeyboardData {
|
||||
|
|
@ -83,7 +88,12 @@ impl DeviceApi for dyn Mouse {
|
|||
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(
|
||||
self.id(),
|
||||
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 };
|
||||
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(),
|
||||
seat_state: Default::default(),
|
||||
});
|
||||
on.workspaces.borrow_mut().push(workspace.clone());
|
||||
on.workspace.set(Some(workspace));
|
||||
self.state.root.outputs.set(self.output.id(), on.clone());
|
||||
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::fixed::Fixed;
|
||||
use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT};
|
||||
use crate::rect::Rect;
|
||||
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::linkedlist::{LinkedList, LinkedNode, NodeRef};
|
||||
use crate::{NumCell, State};
|
||||
|
|
@ -51,9 +51,6 @@ pub enum ContainerFocus {
|
|||
|
||||
tree_id!(ContainerNodeId);
|
||||
|
||||
pub const CONTAINER_TITLE_HEIGHT: i32 = 18;
|
||||
pub const CONTAINER_BORDER: i32 = 4;
|
||||
|
||||
pub struct ContainerNode {
|
||||
pub id: ContainerNodeId,
|
||||
pub parent: CloneCell<Rc<dyn Node>>,
|
||||
|
|
@ -67,12 +64,16 @@ pub struct ContainerNode {
|
|||
pub height: Cell<i32>,
|
||||
pub content_width: 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>,
|
||||
pub children: LinkedList<ContainerChild>,
|
||||
child_nodes: RefCell<AHashMap<NodeId, LinkedNode<ContainerChild>>>,
|
||||
seat_state: NodeSeatState,
|
||||
workspace: CloneCell<Rc<WorkspaceNode>>,
|
||||
seats: RefCell<AHashMap<SeatId, SeatState>>,
|
||||
state: Rc<State>,
|
||||
}
|
||||
|
||||
impl Debug for ContainerNode {
|
||||
|
|
@ -116,10 +117,11 @@ impl ContainerChild {
|
|||
|
||||
impl ContainerNode {
|
||||
pub fn new(
|
||||
state: &State,
|
||||
state: &Rc<State>,
|
||||
workspace: &Rc<WorkspaceNode>,
|
||||
parent: Rc<dyn Node>,
|
||||
child: Rc<dyn Node>,
|
||||
split: ContainerSplit,
|
||||
) -> Self {
|
||||
child.clone().set_workspace(workspace);
|
||||
let children = LinkedList::new();
|
||||
|
|
@ -137,7 +139,7 @@ impl ContainerNode {
|
|||
Self {
|
||||
id: state.node_ids.next(),
|
||||
parent: CloneCell::new(parent),
|
||||
split: Cell::new(ContainerSplit::Horizontal),
|
||||
split: Cell::new(split),
|
||||
mono_child: CloneCell::new(None),
|
||||
mono_body: Cell::new(Default::default()),
|
||||
mono_content: Cell::new(Default::default()),
|
||||
|
|
@ -147,12 +149,16 @@ impl ContainerNode {
|
|||
height: Cell::new(0),
|
||||
content_width: 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),
|
||||
children,
|
||||
child_nodes: RefCell::new(child_nodes),
|
||||
seat_state: Default::default(),
|
||||
workspace: CloneCell::new(workspace.clone()),
|
||||
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 (content_size, other_content_size) = match split {
|
||||
ContainerSplit::Horizontal => (self.content_width.get(), self.content_height.get()),
|
||||
|
|
@ -243,20 +261,15 @@ impl ContainerNode {
|
|||
remaining_content_size -= body_size;
|
||||
let (x1, y1, width, height) = match split {
|
||||
ContainerSplit::Horizontal => {
|
||||
(pos, CONTAINER_TITLE_HEIGHT, body_size, other_content_size)
|
||||
(pos, title_height + 1, body_size, other_content_size)
|
||||
}
|
||||
_ => (
|
||||
0,
|
||||
pos + CONTAINER_TITLE_HEIGHT,
|
||||
other_content_size,
|
||||
body_size,
|
||||
),
|
||||
_ => (0, pos + title_height + 1, other_content_size, body_size),
|
||||
};
|
||||
let body = Rect::new_sized(x1, y1, width, height).unwrap();
|
||||
child.body.set(body);
|
||||
pos += body_size + CONTAINER_BORDER;
|
||||
pos += body_size + border_width;
|
||||
if split == ContainerSplit::Vertical {
|
||||
pos += CONTAINER_TITLE_HEIGHT;
|
||||
pos += title_height + 1;
|
||||
}
|
||||
}
|
||||
if remaining_content_size > 0 {
|
||||
|
|
@ -273,13 +286,7 @@ impl ContainerNode {
|
|||
let (x1, y1, width, height, size) = match split {
|
||||
ContainerSplit::Horizontal => {
|
||||
let width = body.width() + add;
|
||||
(
|
||||
pos,
|
||||
CONTAINER_TITLE_HEIGHT,
|
||||
width,
|
||||
other_content_size,
|
||||
width,
|
||||
)
|
||||
(pos, title_height + 1, width, other_content_size, width)
|
||||
}
|
||||
_ => {
|
||||
let height = body.height() + add;
|
||||
|
|
@ -288,12 +295,14 @@ impl ContainerNode {
|
|||
};
|
||||
body = Rect::new_sized(x1, y1, width, height).unwrap();
|
||||
child.body.set(body);
|
||||
pos += size + CONTAINER_BORDER;
|
||||
pos += size + border_width;
|
||||
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() {
|
||||
let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get());
|
||||
child.node.clone().change_extents(&body);
|
||||
|
|
@ -302,29 +311,32 @@ impl ContainerNode {
|
|||
}
|
||||
|
||||
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();
|
||||
match self.split.get() {
|
||||
ContainerSplit::Horizontal => {
|
||||
let new_content_size = self
|
||||
.width
|
||||
.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_height
|
||||
.set(self.height.get().saturating_sub(CONTAINER_TITLE_HEIGHT));
|
||||
.set(self.height.get().saturating_sub(title_height + 1));
|
||||
}
|
||||
ContainerSplit::Vertical => {
|
||||
let new_content_size = self.height.get().saturating_sub(
|
||||
CONTAINER_TITLE_HEIGHT
|
||||
+ (nc - 1) as i32 * (CONTAINER_BORDER + CONTAINER_TITLE_HEIGHT),
|
||||
title_height + 1 + (nc - 1) as i32 * (border_width + title_height + 1),
|
||||
);
|
||||
self.content_height.set(new_content_size);
|
||||
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 seat_state = seats.entry(seat.id()).or_insert_with(|| SeatState {
|
||||
cursor: KnownCursor::Default,
|
||||
|
|
@ -350,9 +362,7 @@ impl ContainerNode {
|
|||
let (prev_factor, child_factor) = match self.split.get() {
|
||||
ContainerSplit::Horizontal => {
|
||||
let cw = self.content_width.get();
|
||||
if prev_body.x1() + dist_left > x || x + dist_right > child_body.x2() {
|
||||
return;
|
||||
}
|
||||
x = x.max(prev_body.x1() + dist_left).min(child_body.x2() - dist_right);
|
||||
let prev_factor = (x - prev_body.x1() - dist_left) as f64 / cw as f64;
|
||||
let child_factor =
|
||||
(child_body.x2() - x - dist_right) as f64 / cw as f64;
|
||||
|
|
@ -360,16 +370,14 @@ impl ContainerNode {
|
|||
}
|
||||
ContainerSplit::Vertical => {
|
||||
let ch = self.content_height.get();
|
||||
if prev_body.y1() + dist_left > y || y + dist_right > child_body.y2() {
|
||||
return;
|
||||
}
|
||||
y = y.max(prev_body.y1() + dist_left).min(child_body.y2() - dist_right);
|
||||
let prev_factor = (y - prev_body.y1() - dist_left) as f64 / ch as f64;
|
||||
let child_factor =
|
||||
(child_body.y2() - y - dist_right) as f64 / ch as f64;
|
||||
(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
|
||||
+ child_factor;
|
||||
prev.factor.set(prev_factor);
|
||||
|
|
@ -382,7 +390,7 @@ impl ContainerNode {
|
|||
let new_cursor = if self.mono_child.get().is_some() {
|
||||
KnownCursor::Default
|
||||
} else if self.split.get() == ContainerSplit::Horizontal {
|
||||
if y < CONTAINER_TITLE_HEIGHT {
|
||||
if y < title_height + 1 {
|
||||
KnownCursor::Default
|
||||
} else {
|
||||
KnownCursor::ResizeLeftRight
|
||||
|
|
@ -392,7 +400,7 @@ impl ContainerNode {
|
|||
for child in self.children.iter() {
|
||||
let body = child.body.get();
|
||||
if body.y1() > y {
|
||||
if body.y1() - y > CONTAINER_TITLE_HEIGHT {
|
||||
if body.y1() - y > title_height + 1 {
|
||||
cursor = KnownCursor::ResizeTopBottom
|
||||
}
|
||||
break;
|
||||
|
|
@ -440,14 +448,22 @@ impl Node for ContainerNode {
|
|||
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> {
|
||||
Some(self.split.get())
|
||||
}
|
||||
|
||||
fn set_split(&self, split: ContainerSplit) {
|
||||
fn set_split(self: Rc<Self>, split: ContainerSplit) {
|
||||
self.split.set(split);
|
||||
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) {
|
||||
|
|
@ -519,6 +535,7 @@ impl Node for ContainerNode {
|
|||
if button != BTN_LEFT {
|
||||
return;
|
||||
}
|
||||
let title_height = self.state.theme.title_height.get();
|
||||
let mut seat_datas = self.seats.borrow_mut();
|
||||
let seat_data = match seat_datas.get_mut(&seat.id()) {
|
||||
Some(s) => s,
|
||||
|
|
@ -562,7 +579,7 @@ impl Node for ContainerNode {
|
|||
for child in self.children.iter() {
|
||||
let body = child.body.get();
|
||||
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 {
|
||||
dist_left: seat_data.y - child.prev().unwrap().body.get().y2(),
|
||||
dist_right: body.y1() - seat_data.y,
|
||||
|
|
@ -611,7 +628,25 @@ impl Node for ContainerNode {
|
|||
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()) {
|
||||
Some(c) => c.to_ref(),
|
||||
None => return,
|
||||
|
|
@ -619,7 +654,7 @@ impl Node for ContainerNode {
|
|||
let num_children = self.num_children.fetch_sub(1) - 1;
|
||||
if num_children == 0 {
|
||||
self.seats.borrow_mut().clear();
|
||||
self.parent.get().remove_child(self);
|
||||
self.parent.get().remove_child(&*self);
|
||||
return;
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
@ -690,8 +725,9 @@ impl Node for ContainerNode {
|
|||
size_changed |= self.height.replace(rect.height()) != rect.height();
|
||||
if size_changed {
|
||||
self.update_content_size();
|
||||
self.apply_factors(1.0);
|
||||
self.do_apply_factors();
|
||||
self.cancel_seat_ops();
|
||||
self.parent.get().child_size_changed(&*self, rect.width(), rect.height());
|
||||
} else {
|
||||
for child in self.children.iter() {
|
||||
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 destroy_node(&self, detach: bool);
|
||||
|
||||
fn needs_layout(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn do_layout(&self) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
fn get_parent_split(&self) -> Option<ContainerSplit> {
|
||||
None
|
||||
}
|
||||
|
|
@ -79,7 +87,11 @@ pub trait Node {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +166,12 @@ pub trait Node {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -180,7 +197,7 @@ pub trait Node {
|
|||
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 _ = x;
|
||||
let _ = y;
|
||||
|
|
@ -258,6 +275,7 @@ pub struct DisplayNode {
|
|||
pub outputs: CopyHashMap<OutputId, Rc<OutputNode>>,
|
||||
pub stacked: LinkedList<Rc<dyn Node>>,
|
||||
pub seat_state: NodeSeatState,
|
||||
pub needs_layout: Cell<bool>,
|
||||
}
|
||||
|
||||
impl DisplayNode {
|
||||
|
|
@ -267,6 +285,7 @@ impl DisplayNode {
|
|||
outputs: Default::default(),
|
||||
stacked: 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);
|
||||
}
|
||||
|
||||
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 {
|
||||
for stacked in self.stacked.rev_iter() {
|
||||
let ext = stacked.absolute_position();
|
||||
|
|
@ -365,7 +396,7 @@ impl Node for OutputNode {
|
|||
|
||||
fn destroy_node(&self, detach: bool) {
|
||||
if detach {
|
||||
self.display.remove_child(self);
|
||||
self.display.clone().remove_child(self);
|
||||
}
|
||||
let mut workspaces = self.workspaces.borrow_mut();
|
||||
for workspace in workspaces.drain(..) {
|
||||
|
|
@ -374,6 +405,13 @@ impl Node for OutputNode {
|
|||
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 {
|
||||
self.position.get()
|
||||
}
|
||||
|
|
@ -390,7 +428,7 @@ impl Node for OutputNode {
|
|||
FindTreeResult::AcceptsInput
|
||||
}
|
||||
|
||||
fn remove_child(&self, _child: &dyn Node) {
|
||||
fn remove_child(self: Rc<Self>, _child: &dyn Node) {
|
||||
self.workspace.set(None);
|
||||
}
|
||||
|
||||
|
|
@ -464,7 +502,7 @@ impl Node for FloatNode {
|
|||
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.display_link.set(None);
|
||||
self.workspace_link.set(None);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,15 @@ impl Node for WorkspaceNode {
|
|||
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 {
|
||||
self.output.get().position.get()
|
||||
}
|
||||
|
|
@ -63,7 +72,7 @@ impl Node for WorkspaceNode {
|
|||
FindTreeResult::AcceptsInput
|
||||
}
|
||||
|
||||
fn remove_child(&self, _child: &dyn Node) {
|
||||
fn remove_child(self: Rc<Self>, _child: &dyn Node) {
|
||||
self.container.set(None);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue