autocommit 2022-02-20 21:53:46 CET
This commit is contained in:
parent
fbb389b5e9
commit
292fa50fe7
18 changed files with 594 additions and 280 deletions
|
|
@ -58,6 +58,10 @@ fn configure_seat(s: Seat) {
|
|||
s.focus_parent();
|
||||
});
|
||||
|
||||
s.bind(MOD | SHIFT | SYM_f, move || {
|
||||
s.toggle_floating();
|
||||
});
|
||||
|
||||
s.bind(MOD | SHIFT | SYM_h, move || s.move_(Left));
|
||||
s.bind(MOD | SHIFT | SYM_j, move || s.move_(Down));
|
||||
s.bind(MOD | SHIFT | SYM_k, move || s.move_(Up));
|
||||
|
|
|
|||
|
|
@ -196,6 +196,10 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn toggle_floating(&self, seat: Seat) {
|
||||
self.send(&ClientMessage::ToggleFloating { seat });
|
||||
}
|
||||
|
||||
pub fn set_title_color(&self, color: Color) {
|
||||
self.send(&ClientMessage::SetTitleColor { color });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,9 @@ pub enum ClientMessage<'a> {
|
|||
FocusParent {
|
||||
seat: Seat,
|
||||
},
|
||||
ToggleFloating {
|
||||
seat: Seat,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, Debug)]
|
||||
|
|
|
|||
|
|
@ -138,6 +138,10 @@ impl Seat {
|
|||
pub fn focus_parent(self) {
|
||||
get!().focus_parent(self);
|
||||
}
|
||||
|
||||
pub fn toggle_floating(self) {
|
||||
get!().toggle_floating(self);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_seats() -> Vec<Seat> {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::backend::{KeyboardId, MouseId};
|
||||
use crate::ifs::wl_seat::{SeatId, WlSeatGlobal};
|
||||
use crate::state::DeviceHandlerData;
|
||||
use crate::tree::walker::visit_containers;
|
||||
use crate::tree::{ContainerSplit, Node};
|
||||
use crate::tree::walker::{NodeVisitorBase};
|
||||
use crate::tree::{ContainerNode, ContainerSplit, FloatNode, Node};
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::utils::debug_fn::debug_fn;
|
||||
use crate::utils::stack::Stack;
|
||||
|
|
@ -348,6 +348,42 @@ impl ConfigProxyHandler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_toggle_floating(&self, seat: Seat) -> Result<(), FocusParentError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
seat.toggle_floating();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn spaces_change(&self) {
|
||||
struct V;
|
||||
impl NodeVisitorBase for V {
|
||||
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
||||
node.on_spaces_changed();
|
||||
node.visit_children(self);
|
||||
}
|
||||
fn visit_float(&mut self, node: &Rc<FloatNode>) {
|
||||
node.on_spaces_changed();
|
||||
node.visit_children(self);
|
||||
}
|
||||
}
|
||||
self.state.root.clone().visit(&mut V);
|
||||
}
|
||||
|
||||
fn colors_change(&self) {
|
||||
struct V;
|
||||
impl NodeVisitorBase for V {
|
||||
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
||||
node.on_colors_changed();
|
||||
node.visit_children(self);
|
||||
}
|
||||
fn visit_float(&mut self, node: &Rc<FloatNode>) {
|
||||
node.on_colors_changed();
|
||||
node.visit_children(self);
|
||||
}
|
||||
}
|
||||
self.state.root.clone().visit(&mut V);
|
||||
}
|
||||
|
||||
fn handle_set_title_height(&self, height: i32) -> Result<(), SetTitleHeightError> {
|
||||
if height < 0 {
|
||||
return Err(SetTitleHeightError::Negative(height));
|
||||
|
|
@ -356,10 +392,7 @@ impl ConfigProxyHandler {
|
|||
return Err(SetTitleHeightError::Excessive(height));
|
||||
}
|
||||
self.state.theme.title_height.set(height);
|
||||
self.state
|
||||
.root
|
||||
.clone()
|
||||
.visit(&mut visit_containers(|c| c.on_theme_changed()));
|
||||
self.spaces_change();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -371,15 +404,13 @@ impl ConfigProxyHandler {
|
|||
return Err(SetBorderWidthError::Excessive(width));
|
||||
}
|
||||
self.state.theme.border_width.set(width);
|
||||
self.state
|
||||
.root
|
||||
.clone()
|
||||
.visit(&mut visit_containers(|c| c.on_theme_changed()));
|
||||
self.spaces_change();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_set_title_color(&self, color: i4config::theme::Color) {
|
||||
self.state.theme.title_color.set(color.into());
|
||||
self.colors_change();
|
||||
}
|
||||
|
||||
fn handle_set_border_color(&self, color: i4config::theme::Color) {
|
||||
|
|
@ -450,6 +481,7 @@ impl ConfigProxyHandler {
|
|||
ClientMessage::GetBorderWidth => self.handle_get_border_width(),
|
||||
ClientMessage::CreateSplit { seat, axis } => self.handle_create_split(seat, axis)?,
|
||||
ClientMessage::FocusParent { seat } => self.handle_focus_parent(seat)?,
|
||||
ClientMessage::ToggleFloating { seat } => self.handle_toggle_floating(seat)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -487,6 +519,8 @@ enum CphError {
|
|||
CreateSplitError(#[from] CreateSplitError),
|
||||
#[error("Could not process a `focus_parent` request")]
|
||||
FocusParentError(#[from] FocusParentError),
|
||||
#[error("Could not process a `toggle_floating` request")]
|
||||
ToggleFloatingError(#[from] ToggleFloatingError),
|
||||
#[error("Could not process a `set_title_height` request")]
|
||||
SetTitleHeightError(#[from] SetTitleHeightError),
|
||||
#[error("Could not process a `set_border_width` request")]
|
||||
|
|
@ -625,3 +659,10 @@ enum FocusParentError {
|
|||
CphError(#[from] Box<CphError>),
|
||||
}
|
||||
efrom!(FocusParentError, CphError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum ToggleFloatingError {
|
||||
#[error(transparent)]
|
||||
CphError(#[from] Box<CphError>),
|
||||
}
|
||||
efrom!(ToggleFloatingError, CphError);
|
||||
|
|
|
|||
|
|
@ -203,6 +203,10 @@ impl WlSeatGlobal {
|
|||
self.keyboard_node.get().focus_parent(self);
|
||||
}
|
||||
|
||||
pub fn toggle_floating(self: &Rc<Self>) {
|
||||
self.keyboard_node.get().toggle_floating(self);
|
||||
}
|
||||
|
||||
pub fn get_rate(&self) -> (i32, i32) {
|
||||
self.repeat_rate.get()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -579,12 +579,6 @@ dedicated_add_obj!(WlSurface, WlSurfaceId, surfaces);
|
|||
|
||||
tree_id!(SurfaceNodeId);
|
||||
impl Node for WlSurface {
|
||||
fn focus_parent(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
if let Some(xdg) = self.xdg.get() {
|
||||
xdg.focus_parent(seat);
|
||||
}
|
||||
}
|
||||
|
||||
fn id(&self) -> NodeId {
|
||||
self.node_id.into()
|
||||
}
|
||||
|
|
@ -617,6 +611,19 @@ impl Node for WlSurface {
|
|||
self.seat_state.destroy_node(self);
|
||||
}
|
||||
|
||||
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
|
||||
visitor.visit_surface(&self);
|
||||
}
|
||||
|
||||
fn visit_children(&self, visitor: &mut dyn NodeVisitor) {
|
||||
let children = self.children.borrow_mut();
|
||||
if let Some(c) = children.deref() {
|
||||
for child in c.subsurfaces.values() {
|
||||
visitor.visit_surface(&child.surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_parent_split(&self) -> Option<ContainerSplit> {
|
||||
self.xdg.get().and_then(|x| x.get_split())
|
||||
}
|
||||
|
|
@ -678,6 +685,18 @@ impl Node for WlSurface {
|
|||
seat.focus_surface(&self);
|
||||
}
|
||||
|
||||
fn focus_parent(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
if let Some(xdg) = self.xdg.get() {
|
||||
xdg.focus_parent(seat);
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_floating(self: Rc<Self>, seat: &Rc<WlSeatGlobal>) {
|
||||
if let Some(xdg) = self.xdg.get() {
|
||||
xdg.toggle_floating(seat);
|
||||
}
|
||||
}
|
||||
|
||||
fn unfocus(&self, seat: &WlSeatGlobal) {
|
||||
seat.unfocus_surface(self);
|
||||
}
|
||||
|
|
@ -721,19 +740,6 @@ impl Node for WlSurface {
|
|||
fn dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) {
|
||||
dnd.seat.dnd_surface_motion(self, dnd, x, y);
|
||||
}
|
||||
|
||||
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
|
||||
visitor.visit_surface(&self);
|
||||
}
|
||||
|
||||
fn visit_children(&self, visitor: &mut dyn NodeVisitor) {
|
||||
let children = self.children.borrow_mut();
|
||||
if let Some(c) = children.deref() {
|
||||
for child in c.subsurfaces.values() {
|
||||
visitor.visit_surface(&child.surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@ pub trait XdgSurfaceExt: Debug {
|
|||
let _ = seat;
|
||||
}
|
||||
|
||||
fn toggle_floating(self: Rc<Self>, seat: &Rc<WlSeatGlobal>) {
|
||||
let _ = seat;
|
||||
}
|
||||
|
||||
fn get_split(&self) -> Option<ContainerSplit> {
|
||||
None
|
||||
}
|
||||
|
|
@ -221,6 +225,12 @@ impl XdgSurface {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn toggle_floating(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
if let Some(ext) = self.ext.get() {
|
||||
ext.toggle_floating(seat);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_surface(&self, seat: &WlSeatGlobal) -> Rc<WlSurface> {
|
||||
self.focus_surface
|
||||
.get(&seat.id())
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::rect::Rect;
|
|||
use crate::render::Renderer;
|
||||
use crate::tree::walker::NodeVisitor;
|
||||
use crate::tree::{ContainerNode, ContainerSplit, FindTreeResult};
|
||||
use crate::tree::{FloatNode, FoundNode, Node, NodeId, ToplevelNodeId, WorkspaceNode};
|
||||
use crate::tree::{FoundNode, Node, NodeId, ToplevelNodeId, WorkspaceNode};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
|
|
@ -311,6 +311,20 @@ impl XdgToplevel {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn toggle_floating(self: &Rc<Self>) {
|
||||
let parent = match self.parent_node.get() {
|
||||
Some(p) => p,
|
||||
_ => return,
|
||||
};
|
||||
if parent.is_float() {
|
||||
parent.remove_child(&**self);
|
||||
self.map_tiled();
|
||||
} else if let Some(ws) = self.xdg.workspace.get() {
|
||||
parent.remove_child(&**self);
|
||||
self.map_floating(&ws);
|
||||
}
|
||||
}
|
||||
|
||||
fn notify_parent(&self) {
|
||||
let parent = match self.parent_node.get() {
|
||||
Some(p) => p,
|
||||
|
|
@ -322,90 +336,22 @@ impl XdgToplevel {
|
|||
parent.child_title_changed(self, self.title.borrow_mut().deref());
|
||||
}
|
||||
|
||||
fn map_child(self: &Rc<Self>, parent: &XdgToplevel) {
|
||||
let workspace = match parent.xdg.workspace.get() {
|
||||
Some(w) => w,
|
||||
_ => return self.map_tiled(),
|
||||
};
|
||||
self.xdg.set_workspace(&workspace);
|
||||
let output = workspace.output.get();
|
||||
let output_rect = output.position.get();
|
||||
log::info!("or = {:?}", output_rect);
|
||||
fn map_floating(self: &Rc<Self>, workspace: &Rc<WorkspaceNode>) {
|
||||
let extents = self.xdg.extents.get();
|
||||
let position = {
|
||||
let width = extents.width();
|
||||
let height = extents.height();
|
||||
let mut x1 = output_rect.x1();
|
||||
let mut y1 = output_rect.y1();
|
||||
if width < output_rect.width() {
|
||||
x1 += (output_rect.width() - width) as i32 / 2;
|
||||
}
|
||||
if height < output_rect.height() {
|
||||
y1 += (output_rect.height() - height) as i32 / 2;
|
||||
}
|
||||
Rect::new_sized(x1, y1, width, height).unwrap()
|
||||
};
|
||||
log::info!("pos = {:?}", position);
|
||||
let state = &self.xdg.surface.client.state;
|
||||
let floater = Rc::new(FloatNode {
|
||||
id: state.node_ids.next(),
|
||||
visible: Cell::new(true),
|
||||
position: Cell::new(position),
|
||||
display: output.display.clone(),
|
||||
display_link: Cell::new(None),
|
||||
workspace_link: Cell::new(None),
|
||||
workspace: CloneCell::new(workspace.clone()),
|
||||
child: CloneCell::new(Some(self.clone())),
|
||||
seat_state: Default::default(),
|
||||
});
|
||||
self.parent_node.set(Some(floater.clone()));
|
||||
floater
|
||||
.display_link
|
||||
.set(Some(state.root.stacked.add_last(floater.clone())));
|
||||
floater
|
||||
.workspace_link
|
||||
.set(Some(workspace.stacked.add_last(floater.clone())));
|
||||
self.notify_parent();
|
||||
state.map_floating(self.clone(), extents.width(), extents.height(), workspace);
|
||||
}
|
||||
|
||||
fn map_child(self: &Rc<Self>, parent: &XdgToplevel) {
|
||||
match parent.xdg.workspace.get() {
|
||||
Some(w) => self.map_floating(&w),
|
||||
_ => self.map_tiled(),
|
||||
}
|
||||
}
|
||||
|
||||
fn map_tiled(self: &Rc<Self>) {
|
||||
let state = &self.xdg.surface.client.state;
|
||||
let seat = state.seat_queue.last();
|
||||
if let Some(seat) = seat {
|
||||
if let Some(prev) = seat.last_tiled_keyboard_toplevel() {
|
||||
if let Some(container) = prev.parent_node.get() {
|
||||
if let Some(container) = container.into_container() {
|
||||
container.add_child_after(&*prev, self.clone());
|
||||
self.parent_node.set(Some(container));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let output = {
|
||||
let outputs = state.root.outputs.lock();
|
||||
outputs.values().next().cloned()
|
||||
};
|
||||
if let Some(output) = output {
|
||||
if let Some(workspace) = output.workspace.get() {
|
||||
if let Some(container) = workspace.container.get() {
|
||||
container.append_child(self.clone());
|
||||
self.parent_node.set(Some(container));
|
||||
} else {
|
||||
let container = Rc::new(ContainerNode::new(
|
||||
state,
|
||||
&workspace,
|
||||
workspace.clone(),
|
||||
self.clone(),
|
||||
ContainerSplit::Horizontal,
|
||||
));
|
||||
workspace.set_container(&container);
|
||||
self.parent_node.set(Some(container));
|
||||
};
|
||||
return;
|
||||
}
|
||||
}
|
||||
todo!("map_tiled");
|
||||
state.map_tiled(self.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -526,6 +472,10 @@ impl XdgSurfaceExt for XdgToplevel {
|
|||
self.parent_node.get().map(|p| p.focus_self(seat));
|
||||
}
|
||||
|
||||
fn toggle_floating(self: Rc<Self>, _seat: &Rc<WlSeatGlobal>) {
|
||||
Self::toggle_floating(&self);
|
||||
}
|
||||
|
||||
fn get_split(&self) -> Option<ContainerSplit> {
|
||||
self.parent_node.get().and_then(|p| p.get_split())
|
||||
}
|
||||
|
|
@ -543,14 +493,13 @@ impl XdgSurfaceExt for XdgToplevel {
|
|||
Some(pn) => pn,
|
||||
_ => return,
|
||||
};
|
||||
let cn = Rc::new(ContainerNode::new(
|
||||
let cn = 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
10
src/main.rs
10
src/main.rs
|
|
@ -26,7 +26,7 @@ use crate::ifs::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1Global;
|
|||
use crate::render::RenderError;
|
||||
use crate::sighand::SighandError;
|
||||
use crate::state::State;
|
||||
use crate::tree::{container_layout, render_titles, DisplayNode, NodeIds};
|
||||
use crate::tree::{container_layout, container_titles, DisplayNode, float_layout, float_titles, NodeIds};
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::errorfmt::ErrorFmt;
|
||||
use crate::utils::numcell::NumCell;
|
||||
|
|
@ -158,6 +158,8 @@ fn main_() -> Result<(), MainError> {
|
|||
theme: Default::default(),
|
||||
pending_container_layout: Default::default(),
|
||||
pending_container_titles: Default::default(),
|
||||
pending_float_layout: Default::default(),
|
||||
pending_float_titles: Default::default(),
|
||||
});
|
||||
forker.install(&state);
|
||||
let backend = XorgBackend::new(&state)?;
|
||||
|
|
@ -166,8 +168,10 @@ 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.spawn2(Phase::Layout, container_layout(state.clone()));
|
||||
let _render_titles = engine.spawn2(Phase::PostLayout, render_titles(state.clone()));
|
||||
let _container_do_layout = engine.spawn2(Phase::Layout, container_layout(state.clone()));
|
||||
let _container_render_titles = engine.spawn2(Phase::PostLayout, container_titles(state.clone()));
|
||||
let _float_do_layout = engine.spawn2(Phase::Layout, float_layout(state.clone()));
|
||||
let _float_render_titles = engine.spawn2(Phase::PostLayout, float_titles(state.clone()));
|
||||
let socket_path = Acceptor::install(&state)?;
|
||||
forker.setenv(b"WAYLAND_DISPLAY", socket_path.as_bytes());
|
||||
el.run()?;
|
||||
|
|
|
|||
|
|
@ -20,12 +20,13 @@ use crate::State;
|
|||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
use crate::theme::Color;
|
||||
|
||||
const NON_COLOR: (f32, f32, f32) = (0.2, 0.2, 0.2);
|
||||
const CHILD_COLOR: (f32, f32, f32) = (0.8, 0.8, 0.8);
|
||||
const YES_COLOR: (f32, f32, f32) = (0.0, 0.0, 1.0);
|
||||
const NON_COLOR: Color = Color::from_rgbaf(0.2, 0.2, 0.2, 1.0);
|
||||
const CHILD_COLOR: Color = Color::from_rgbaf(0.8, 0.8, 0.8, 1.0);
|
||||
const YES_COLOR: Color = Color::from_rgbaf(0.0, 0.0, 1.0, 1.0);
|
||||
|
||||
fn focus_color(focus: ContainerFocus) -> (f32, f32, f32) {
|
||||
fn focus_color(focus: ContainerFocus) -> Color {
|
||||
match focus {
|
||||
ContainerFocus::None => NON_COLOR,
|
||||
ContainerFocus::Child => CHILD_COLOR,
|
||||
|
|
@ -64,7 +65,7 @@ impl Renderer<'_> {
|
|||
2.0 * (y as f32 / self.fb.height as f32) - 1.0
|
||||
}
|
||||
|
||||
fn fill_boxes(&self, boxes: &[Rect], r: f32, g: f32, b: f32, a: f32) {
|
||||
fn fill_boxes(&self, boxes: &[Rect], color: &Color) {
|
||||
if boxes.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -87,7 +88,7 @@ impl Renderer<'_> {
|
|||
}
|
||||
unsafe {
|
||||
glUseProgram(self.ctx.fill_prog.prog);
|
||||
glUniform4f(self.ctx.fill_prog_color, r, g, b, a);
|
||||
glUniform4f(self.ctx.fill_prog_color, color.r, color.g, color.b, color.a);
|
||||
glVertexAttribPointer(
|
||||
self.ctx.fill_prog_pos as _,
|
||||
2,
|
||||
|
|
@ -116,13 +117,13 @@ impl Renderer<'_> {
|
|||
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 color = focus_color(ContainerFocus::None);
|
||||
self.fill_boxes(slice::from_ref(&title_rect), &color);
|
||||
let c = self.state.theme.border_color.get();
|
||||
self.fill_boxes(slice::from_ref(&underline_rect), c.r, c.g, c.b, c.a);
|
||||
self.fill_boxes(slice::from_ref(&underline_rect), &c);
|
||||
for child in container.children.iter() {
|
||||
let focus = child.focus.get();
|
||||
let (r, g, b) = focus_color(focus);
|
||||
let color = focus_color(focus);
|
||||
let mut width = space_per_child;
|
||||
if rem > 0 {
|
||||
rem -= 1;
|
||||
|
|
@ -133,7 +134,7 @@ impl Renderer<'_> {
|
|||
}
|
||||
if focus != ContainerFocus::None {
|
||||
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), &color);
|
||||
}
|
||||
pos += width as i32;
|
||||
}
|
||||
|
|
@ -208,13 +209,13 @@ impl Renderer<'_> {
|
|||
}
|
||||
{
|
||||
let c = self.state.theme.title_color.get();
|
||||
self.fill_boxes(&title_rects, c.r, c.g, c.b, c.a);
|
||||
self.fill_boxes(&title_rects, &c);
|
||||
let c = self.state.theme.active_title_color.get();
|
||||
self.fill_boxes(&active_rects, c.r, c.g, c.b, c.a);
|
||||
self.fill_boxes(&active_rects, &c);
|
||||
let c = self.state.theme.underline_color.get();
|
||||
self.fill_boxes(&underline_rects, c.r, c.g, c.b, c.a);
|
||||
self.fill_boxes(&underline_rects, &c);
|
||||
let c = self.state.theme.border_color.get();
|
||||
self.fill_boxes(&border_rects, c.r, c.g, c.b, c.a);
|
||||
self.fill_boxes(&border_rects, &c);
|
||||
for (tx, ty, tex) in titles {
|
||||
self.render_texture(&tex, x + tx, y + ty, ARGB8888);
|
||||
}
|
||||
|
|
@ -349,8 +350,43 @@ impl Renderer<'_> {
|
|||
}
|
||||
|
||||
pub fn render_floating(&mut self, floating: &FloatNode, x: i32, y: i32) {
|
||||
if let Some(child) = floating.child.get() {
|
||||
child.render(self, x, y)
|
||||
let child = match floating.child.get() {
|
||||
Some(c) => c,
|
||||
_ => return,
|
||||
};
|
||||
let pos = floating.position.get();
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.title_height.get();
|
||||
let bw = theme.border_width.get();
|
||||
let bc = theme.border_color.get();
|
||||
let tc = match floating.active.get() {
|
||||
true => theme.active_title_color.get(),
|
||||
false => theme.title_color.get(),
|
||||
};
|
||||
let uc = theme.underline_color.get();
|
||||
let borders = [
|
||||
Rect::new_sized(x, y, pos.width(), bw).unwrap(),
|
||||
Rect::new_sized(x, y, bw, pos.height()).unwrap(),
|
||||
Rect::new_sized(x + pos.width() - bw, y, bw, pos.height()).unwrap(),
|
||||
Rect::new_sized(x, y + pos.height() - bw, pos.width(), bw).unwrap(),
|
||||
];
|
||||
self.fill_boxes(&borders, &bc);
|
||||
let title = [
|
||||
Rect::new_sized(x + bw, y + bw, pos.width() - 2 * bw, th).unwrap(),
|
||||
];
|
||||
self.fill_boxes(&title, &tc);
|
||||
let title_underline = [
|
||||
Rect::new_sized(x + bw, y + bw + th, pos.width() - 2 * bw, 1).unwrap(),
|
||||
];
|
||||
self.fill_boxes(&title_underline, &uc);
|
||||
if let Some(title) = floating.title_texture.get() {
|
||||
self.render_texture(&title, x + bw, y + bw, ARGB8888);
|
||||
}
|
||||
let body = Rect::new_sized(x + bw, y + bw + th + 1, pos.width() - 2 * bw, pos.height() - 2 * bw - th - 1).unwrap();
|
||||
unsafe {
|
||||
with_scissor(&body, || {
|
||||
child.render(self, body.x1(), body.y1());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
73
src/state.rs
73
src/state.rs
|
|
@ -12,9 +12,12 @@ use crate::globals::{Globals, GlobalsError, WaylandGlobal};
|
|||
use crate::ifs::wl_output::WlOutputGlobal;
|
||||
use crate::ifs::wl_seat::{SeatIds, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::NoneSurfaceExt;
|
||||
use crate::rect::Rect;
|
||||
use crate::render::RenderContext;
|
||||
use crate::theme::Theme;
|
||||
use crate::tree::{ContainerNode, DisplayNode, NodeIds};
|
||||
use crate::tree::{
|
||||
ContainerNode, ContainerSplit, DisplayNode, FloatNode, Node, NodeIds, WorkspaceNode,
|
||||
};
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::utils::linkedlist::LinkedList;
|
||||
|
|
@ -58,6 +61,8 @@ pub struct State {
|
|||
pub theme: Theme,
|
||||
pub pending_container_layout: AsyncQueue<Rc<ContainerNode>>,
|
||||
pub pending_container_titles: AsyncQueue<Rc<ContainerNode>>,
|
||||
pub pending_float_layout: AsyncQueue<Rc<FloatNode>>,
|
||||
pub pending_float_titles: AsyncQueue<Rc<FloatNode>>,
|
||||
}
|
||||
|
||||
pub struct MouseData {
|
||||
|
|
@ -107,4 +112,70 @@ impl State {
|
|||
seat.trigger_tree_changed();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_tiled(self: &Rc<Self>, node: Rc<dyn Node>) {
|
||||
let seat = self.seat_queue.last();
|
||||
if let Some(seat) = seat {
|
||||
if let Some(prev) = seat.last_tiled_keyboard_toplevel() {
|
||||
if let Some(container) = prev.parent_node.get() {
|
||||
if let Some(container) = container.into_container() {
|
||||
container.add_child_after(&*prev, node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let output = {
|
||||
let outputs = self.root.outputs.lock();
|
||||
outputs.values().next().cloned()
|
||||
};
|
||||
if let Some(output) = output {
|
||||
if let Some(workspace) = output.workspace.get() {
|
||||
if let Some(container) = workspace.container.get() {
|
||||
container.append_child(node);
|
||||
} else {
|
||||
let container = ContainerNode::new(
|
||||
self,
|
||||
&workspace,
|
||||
workspace.clone(),
|
||||
node,
|
||||
ContainerSplit::Horizontal,
|
||||
);
|
||||
workspace.set_container(&container);
|
||||
};
|
||||
return;
|
||||
}
|
||||
}
|
||||
todo!("map_tiled");
|
||||
}
|
||||
|
||||
pub fn map_floating(
|
||||
self: &Rc<Self>,
|
||||
node: Rc<dyn Node>,
|
||||
mut width: i32,
|
||||
mut height: i32,
|
||||
workspace: &Rc<WorkspaceNode>,
|
||||
) {
|
||||
node.clone().set_workspace(workspace);
|
||||
width += 2 * self.theme.border_width.get();
|
||||
height += 2 * self.theme.border_width.get() + self.theme.title_height.get();
|
||||
let output = workspace.output.get();
|
||||
let output_rect = output.position.get();
|
||||
let position = {
|
||||
let mut x1 = output_rect.x1();
|
||||
let mut y1 = output_rect.y1();
|
||||
if width < output_rect.width() {
|
||||
x1 += (output_rect.width() - width) as i32 / 2;
|
||||
} else {
|
||||
width = output_rect.width();
|
||||
}
|
||||
if height < output_rect.height() {
|
||||
y1 += (output_rect.height() - height) as i32 / 2;
|
||||
} else {
|
||||
height = output_rect.height();
|
||||
}
|
||||
Rect::new_sized(x1, y1, width, height).unwrap()
|
||||
};
|
||||
FloatNode::new(self, workspace, position, node);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
src/theme.rs
16
src/theme.rs
|
|
@ -9,13 +9,6 @@ pub struct Color {
|
|||
}
|
||||
|
||||
impl Color {
|
||||
pub const RED: Self = Self {
|
||||
r: 1.0,
|
||||
g: 0.0,
|
||||
b: 0.0,
|
||||
a: 1.0,
|
||||
};
|
||||
|
||||
pub const GREY: Self = Self {
|
||||
r: 0.8,
|
||||
g: 0.8,
|
||||
|
|
@ -37,6 +30,15 @@ impl Color {
|
|||
a: to_f32(a),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn from_rgbaf(r: f32, g: f32, b: f32, a: f32) -> Self {
|
||||
Self {
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
a,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i4config::theme::Color> for Color {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
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};
|
||||
|
|
@ -19,10 +19,6 @@ use std::mem;
|
|||
use std::ops::{Deref, DerefMut, Sub};
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ContainerSplit {
|
||||
|
|
@ -135,14 +131,14 @@ impl ContainerNode {
|
|||
parent: Rc<dyn Node>,
|
||||
child: Rc<dyn Node>,
|
||||
split: ContainerSplit,
|
||||
) -> Self {
|
||||
) -> Rc<Self> {
|
||||
child.clone().set_workspace(workspace);
|
||||
let children = LinkedList::new();
|
||||
let mut child_nodes = AHashMap::new();
|
||||
child_nodes.insert(
|
||||
child.id(),
|
||||
children.add_last(ContainerChild {
|
||||
node: child,
|
||||
node: child.clone(),
|
||||
active: Cell::new(false),
|
||||
body: Cell::new(Default::default()),
|
||||
content: Cell::new(Default::default()),
|
||||
|
|
@ -152,7 +148,7 @@ impl ContainerNode {
|
|||
title_texture: Default::default(),
|
||||
}),
|
||||
);
|
||||
Self {
|
||||
let slf = Rc::new(Self {
|
||||
id: state.node_ids.next(),
|
||||
parent: CloneCell::new(parent),
|
||||
active: Cell::new(false),
|
||||
|
|
@ -177,7 +173,9 @@ impl ContainerNode {
|
|||
workspace: CloneCell::new(workspace.clone()),
|
||||
seats: RefCell::new(Default::default()),
|
||||
state: state.clone(),
|
||||
}
|
||||
});
|
||||
child.set_parent(slf.clone());
|
||||
slf
|
||||
}
|
||||
|
||||
pub fn num_children(&self) -> usize {
|
||||
|
|
@ -283,11 +281,15 @@ impl ContainerNode {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn on_theme_changed(self: &Rc<Self>) {
|
||||
pub fn on_spaces_changed(self: &Rc<Self>) {
|
||||
self.update_content_size();
|
||||
self.schedule_layout();
|
||||
}
|
||||
|
||||
pub fn on_colors_changed(self: &Rc<Self>) {
|
||||
self.schedule_render_titles();
|
||||
}
|
||||
|
||||
fn schedule_layout(self: &Rc<Self>) {
|
||||
if !self.layout_scheduled.replace(true) {
|
||||
self.state.pending_container_layout.push(self.clone());
|
||||
|
|
@ -500,6 +502,7 @@ impl ContainerNode {
|
|||
}
|
||||
|
||||
fn render_titles(&self) {
|
||||
self.render_titles_scheduled.set(false);
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.title_height.get();
|
||||
let font = theme.font.borrow_mut();
|
||||
|
|
@ -523,7 +526,6 @@ impl ContainerNode {
|
|||
};
|
||||
c.title_texture.set(Some(texture));
|
||||
}
|
||||
self.render_titles_scheduled.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -547,7 +549,7 @@ pub async fn container_layout(state: Rc<State>) {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn render_titles(state: Rc<State>) {
|
||||
pub async fn container_titles(state: Rc<State>) {
|
||||
loop {
|
||||
let container = state.pending_container_titles.pop().await;
|
||||
if container.render_titles_scheduled.get() {
|
||||
|
|
@ -835,6 +837,21 @@ impl Node for ContainerNode {
|
|||
self.parent.get().focus_self(seat);
|
||||
}
|
||||
|
||||
fn toggle_floating(self: Rc<Self>, _seat: &Rc<WlSeatGlobal>) {
|
||||
let parent = self.parent.get();
|
||||
parent.clone().remove_child(&*self);
|
||||
if parent.is_float() {
|
||||
self.state.map_tiled(self.clone());
|
||||
} else {
|
||||
self.state.map_floating(
|
||||
self.clone(),
|
||||
self.width.get(),
|
||||
self.height.get(),
|
||||
&self.workspace.get(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
||||
let mut recurse = |content: Rect, child: NodeRef<ContainerChild>| {
|
||||
if content.contains(x, y) {
|
||||
|
|
|
|||
260
src/tree/float.rs
Normal file
260
src/tree/float.rs
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use i4config::Direction;
|
||||
use crate::{CloneCell, ErrorFmt, State, text};
|
||||
use crate::backend::{KeyState, ScrollAxis};
|
||||
use crate::client::{Client, ClientId};
|
||||
use crate::cursor::KnownCursor;
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_seat::{Dnd, NodeSeatState, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::WlSurface;
|
||||
use crate::rect::Rect;
|
||||
use crate::render::{Renderer, Texture};
|
||||
use crate::theme::Color;
|
||||
use crate::tree::{ContainerNode, ContainerSplit, FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode};
|
||||
use crate::tree::walker::NodeVisitor;
|
||||
use crate::utils::linkedlist::LinkedNode;
|
||||
use crate::xkbcommon::ModifierState;
|
||||
|
||||
tree_id!(FloatNodeId);
|
||||
pub struct FloatNode {
|
||||
pub id: FloatNodeId,
|
||||
pub state: Rc<State>,
|
||||
pub visible: Cell<bool>,
|
||||
pub position: Cell<Rect>,
|
||||
pub display_link: Cell<Option<LinkedNode<Rc<dyn Node>>>>,
|
||||
pub workspace_link: Cell<Option<LinkedNode<Rc<dyn Node>>>>,
|
||||
pub workspace: CloneCell<Rc<WorkspaceNode>>,
|
||||
pub child: CloneCell<Option<Rc<dyn Node>>>,
|
||||
pub active: Cell<bool>,
|
||||
pub seat_state: NodeSeatState,
|
||||
pub layout_scheduled: Cell<bool>,
|
||||
pub render_titles_scheduled: Cell<bool>,
|
||||
pub title: RefCell<String>,
|
||||
pub title_texture: CloneCell<Option<Rc<Texture>>>,
|
||||
}
|
||||
|
||||
pub async fn float_layout(state: Rc<State>) {
|
||||
loop {
|
||||
let node = state.pending_float_layout.pop().await;
|
||||
if node.layout_scheduled.get() {
|
||||
node.perform_layout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn float_titles(state: Rc<State>) {
|
||||
loop {
|
||||
let node = state.pending_float_titles.pop().await;
|
||||
if node.render_titles_scheduled.get() {
|
||||
node.render_title();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatNode {
|
||||
pub fn new(state: &Rc<State>, ws: &Rc<WorkspaceNode>, position: Rect, child: Rc<dyn Node>) -> Rc<Self> {
|
||||
let floater = Rc::new(FloatNode {
|
||||
id: state.node_ids.next(),
|
||||
state: state.clone(),
|
||||
visible: Cell::new(true),
|
||||
position: Cell::new(position),
|
||||
display_link: Cell::new(None),
|
||||
workspace_link: Cell::new(None),
|
||||
workspace: CloneCell::new(ws.clone()),
|
||||
child: CloneCell::new(Some(child.clone())),
|
||||
active: Cell::new(false),
|
||||
seat_state: Default::default(),
|
||||
layout_scheduled: Cell::new(false),
|
||||
render_titles_scheduled: Cell::new(false),
|
||||
title: Default::default(),
|
||||
title_texture: Default::default(),
|
||||
});
|
||||
floater
|
||||
.display_link
|
||||
.set(Some(state.root.stacked.add_last(floater.clone())));
|
||||
floater
|
||||
.workspace_link
|
||||
.set(Some(ws.stacked.add_last(floater.clone())));
|
||||
child.clone().set_workspace(ws);
|
||||
child.clone().set_parent(floater.clone());
|
||||
floater.schedule_layout();
|
||||
floater
|
||||
}
|
||||
|
||||
pub fn on_spaces_changed(self: &Rc<Self>) {
|
||||
self.schedule_layout();
|
||||
}
|
||||
|
||||
pub fn on_colors_changed(self: &Rc<Self>) {
|
||||
self.schedule_render_titles();
|
||||
}
|
||||
|
||||
fn schedule_layout(self: &Rc<Self>) {
|
||||
if !self.layout_scheduled.replace(true) {
|
||||
self.state.pending_float_layout.push(self.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn perform_layout(self: &Rc<Self>) {
|
||||
let child = match self.child.get() {
|
||||
Some(c) => c,
|
||||
_ => return,
|
||||
};
|
||||
let pos = self.position.get();
|
||||
let theme = &self.state.theme;
|
||||
let bw = theme.border_width.get();
|
||||
let th = theme.title_height.get();
|
||||
let cpos = Rect::new_sized(
|
||||
pos.x1() + bw,
|
||||
pos.y1() + bw + th + 1,
|
||||
(pos.width() - 2 * bw).max(0),
|
||||
(pos.height() - 2 * bw - th - 1).max(0),
|
||||
).unwrap();
|
||||
child.clone().change_extents(&cpos);
|
||||
self.layout_scheduled.set(false);
|
||||
self.schedule_render_titles();
|
||||
}
|
||||
|
||||
fn schedule_render_titles(self: &Rc<Self>) {
|
||||
if !self.render_titles_scheduled.replace(true) {
|
||||
self.state.pending_float_titles.push(self.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn render_title(&self) {
|
||||
self.render_titles_scheduled.set(false);
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.title_height.get();
|
||||
let font = theme.font.borrow_mut();
|
||||
let title = self.title.borrow_mut();
|
||||
self.title_texture.set(None);
|
||||
let pos = self.position.get();
|
||||
let ctx = match self.state.render_ctx.get() {
|
||||
Some(c) => c,
|
||||
_ => return,
|
||||
};
|
||||
let texture = match text::render(&ctx, pos.width(), th, &font, &title, Color::GREY) {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
|
||||
return;
|
||||
}
|
||||
};
|
||||
self.title_texture.set(Some(texture));
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FloatNode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("FloatNode").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for FloatNode {
|
||||
fn id(&self) -> NodeId {
|
||||
self.id.into()
|
||||
}
|
||||
|
||||
fn seat_state(&self) -> &NodeSeatState {
|
||||
&self.seat_state
|
||||
}
|
||||
|
||||
fn destroy_node(&self, _detach: bool) {
|
||||
let _v = self.display_link.take();
|
||||
let _v = self.workspace_link.take();
|
||||
if let Some(child) = self.child.get() {
|
||||
child.destroy_node(false);
|
||||
}
|
||||
self.seat_state.destroy_node(self);
|
||||
}
|
||||
|
||||
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
|
||||
visitor.visit_float(&self);
|
||||
}
|
||||
|
||||
fn visit_children(&self, visitor: &mut dyn NodeVisitor) {
|
||||
if let Some(c) = self.child.get() {
|
||||
c.visit(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
fn absolute_position(&self) -> Rect {
|
||||
self.position.get()
|
||||
}
|
||||
|
||||
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.title_height.get();
|
||||
let bw = theme.border_width.get();
|
||||
let pos = self.position.get();
|
||||
if x < bw || x >= pos.width() - bw {
|
||||
return FindTreeResult::AcceptsInput;
|
||||
}
|
||||
if y < bw + th + 1 || x >= pos.height() - bw {
|
||||
return FindTreeResult::AcceptsInput;
|
||||
}
|
||||
let child = match self.child.get() {
|
||||
Some(c) => c,
|
||||
_ => return FindTreeResult::Other,
|
||||
};
|
||||
let x = x - bw;
|
||||
let y = y - bw - th - 1;
|
||||
tree.push(FoundNode {
|
||||
node: child.clone(),
|
||||
x,
|
||||
y,
|
||||
});
|
||||
child.find_tree_at(x, y, tree)
|
||||
}
|
||||
|
||||
fn remove_child(self: Rc<Self>, _child: &dyn Node) {
|
||||
self.child.set(None);
|
||||
self.display_link.set(None);
|
||||
self.workspace_link.set(None);
|
||||
}
|
||||
|
||||
fn pointer_target(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
seat.set_known_cursor(KnownCursor::Default);
|
||||
}
|
||||
|
||||
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
|
||||
renderer.render_floating(self, x, y)
|
||||
}
|
||||
|
||||
fn into_float(self: Rc<Self>) -> Option<Rc<FloatNode>> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn accepts_child(&self, _node: &dyn Node) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn is_float(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn set_workspace(self: Rc<Self>, ws: &Rc<WorkspaceNode>) {
|
||||
if let Some(c) = self.child.get() {
|
||||
c.set_workspace(ws);
|
||||
}
|
||||
self.workspace_link
|
||||
.set(Some(ws.stacked.add_last(self.clone())));
|
||||
self.workspace.set(ws.clone());
|
||||
}
|
||||
|
||||
fn child_active_changed(&self, _child: &dyn Node, active: bool) {
|
||||
self.active.set(active);
|
||||
}
|
||||
|
||||
fn child_title_changed(self: Rc<Self>, child: &dyn Node, title: &str) {
|
||||
let mut t = self.title.borrow_mut();
|
||||
if t.deref() != title {
|
||||
t.clear();
|
||||
t.push_str(title);
|
||||
self.schedule_render_titles();
|
||||
}
|
||||
}
|
||||
}
|
||||
120
src/tree/mod.rs
120
src/tree/mod.rs
|
|
@ -10,7 +10,7 @@ use crate::render::Renderer;
|
|||
use crate::tree::walker::NodeVisitor;
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::utils::linkedlist::{LinkedList, LinkedNode};
|
||||
use crate::utils::linkedlist::{LinkedList};
|
||||
use crate::xkbcommon::ModifierState;
|
||||
use crate::NumCell;
|
||||
pub use container::*;
|
||||
|
|
@ -20,10 +20,12 @@ use std::fmt::{Debug, Display, Formatter};
|
|||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
pub use workspace::*;
|
||||
pub use float::*;
|
||||
|
||||
mod container;
|
||||
pub mod walker;
|
||||
mod workspace;
|
||||
mod float;
|
||||
|
||||
pub struct NodeIds {
|
||||
next: NumCell<u32>,
|
||||
|
|
@ -173,6 +175,10 @@ pub trait Node {
|
|||
let _ = seat;
|
||||
}
|
||||
|
||||
fn toggle_floating(self: Rc<Self>, seat: &Rc<WlSeatGlobal>) {
|
||||
let _ = seat;
|
||||
}
|
||||
|
||||
fn unfocus(&self, seat: &WlSeatGlobal) {
|
||||
let _ = seat;
|
||||
}
|
||||
|
|
@ -495,115 +501,3 @@ impl Node for OutputNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
tree_id!(FloatNodeId);
|
||||
pub struct FloatNode {
|
||||
pub id: FloatNodeId,
|
||||
pub visible: Cell<bool>,
|
||||
pub position: Cell<Rect>,
|
||||
pub display: Rc<DisplayNode>,
|
||||
pub display_link: Cell<Option<LinkedNode<Rc<dyn Node>>>>,
|
||||
pub workspace_link: Cell<Option<LinkedNode<Rc<dyn Node>>>>,
|
||||
pub workspace: CloneCell<Rc<WorkspaceNode>>,
|
||||
pub child: CloneCell<Option<Rc<dyn Node>>>,
|
||||
pub seat_state: NodeSeatState,
|
||||
}
|
||||
|
||||
impl Debug for FloatNode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("FloatNode").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for FloatNode {
|
||||
fn id(&self) -> NodeId {
|
||||
self.id.into()
|
||||
}
|
||||
|
||||
fn seat_state(&self) -> &NodeSeatState {
|
||||
&self.seat_state
|
||||
}
|
||||
|
||||
fn destroy_node(&self, _detach: bool) {
|
||||
let _v = self.display_link.take();
|
||||
let _v = self.workspace_link.take();
|
||||
if let Some(child) = self.child.get() {
|
||||
child.destroy_node(false);
|
||||
}
|
||||
self.seat_state.destroy_node(self);
|
||||
}
|
||||
|
||||
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
|
||||
visitor.visit_float(&self);
|
||||
}
|
||||
|
||||
fn visit_children(&self, visitor: &mut dyn NodeVisitor) {
|
||||
if let Some(c) = self.child.get() {
|
||||
c.visit(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
fn absolute_position(&self) -> Rect {
|
||||
self.position.get()
|
||||
}
|
||||
|
||||
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
||||
let child = match self.child.get() {
|
||||
Some(c) => c,
|
||||
_ => return FindTreeResult::Other,
|
||||
};
|
||||
tree.push(FoundNode {
|
||||
node: child.clone(),
|
||||
x,
|
||||
y,
|
||||
});
|
||||
child.find_tree_at(x, y, tree)
|
||||
}
|
||||
|
||||
fn remove_child(self: Rc<Self>, _child: &dyn Node) {
|
||||
self.child.set(None);
|
||||
self.display_link.set(None);
|
||||
self.workspace_link.set(None);
|
||||
}
|
||||
|
||||
fn child_size_changed(&self, _child: &dyn Node, width: i32, height: i32) {
|
||||
let pos = self.position.get();
|
||||
self.position
|
||||
.set(Rect::new_sized(pos.x1(), pos.y1(), width, height).unwrap());
|
||||
}
|
||||
|
||||
fn pointer_target(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
seat.set_known_cursor(KnownCursor::Default);
|
||||
}
|
||||
|
||||
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
|
||||
renderer.render_floating(self, x, y)
|
||||
}
|
||||
|
||||
fn into_float(self: Rc<Self>) -> Option<Rc<FloatNode>> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn accepts_child(&self, _node: &dyn Node) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn is_float(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn change_extents(self: Rc<Self>, rect: &Rect) {
|
||||
if let Some(child) = self.child.get() {
|
||||
child.change_extents(rect);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_workspace(self: Rc<Self>, ws: &Rc<WorkspaceNode>) {
|
||||
if let Some(c) = self.child.get() {
|
||||
c.set_workspace(ws);
|
||||
}
|
||||
self.workspace_link
|
||||
.set(Some(ws.stacked.add_last(self.clone())));
|
||||
self.workspace.set(ws.clone());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,13 +84,24 @@ impl<T: NodeVisitorBase> NodeVisitor for T {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn visit_containers<F: FnMut(&Rc<ContainerNode>)>(f: F) -> impl NodeVisitor {
|
||||
struct V<F>(F);
|
||||
impl<F: FnMut(&Rc<ContainerNode>)> NodeVisitorBase for V<F> {
|
||||
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
||||
(self.0)(node);
|
||||
node.visit_children(self);
|
||||
}
|
||||
}
|
||||
V(f)
|
||||
}
|
||||
// pub fn visit_containers<F: FnMut(&Rc<ContainerNode>)>(f: F) -> impl NodeVisitor {
|
||||
// struct V<F>(F);
|
||||
// impl<F: FnMut(&Rc<ContainerNode>)> NodeVisitorBase for V<F> {
|
||||
// fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
||||
// (self.0)(node);
|
||||
// node.visit_children(self);
|
||||
// }
|
||||
// }
|
||||
// V(f)
|
||||
// }
|
||||
//
|
||||
// pub fn visit_floats<F: FnMut(&Rc<FloatNode>)>(f: F) -> impl NodeVisitor {
|
||||
// struct V<F>(F);
|
||||
// impl<F: FnMut(&Rc<FloatNode>)> NodeVisitorBase for V<F> {
|
||||
// fn visit_float(&mut self, node: &Rc<FloatNode>) {
|
||||
// (self.0)(node);
|
||||
// node.visit_children(self);
|
||||
// }
|
||||
// }
|
||||
// V(f)
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -10,12 +10,6 @@ use crate::utils::linkedlist::LinkedList;
|
|||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
tree_id!(WorkspaceNodeId);
|
||||
|
||||
pub struct WorkspaceNode {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue