1
0
Fork 0
forked from wry/wry

autocommit 2022-02-20 21:53:46 CET

This commit is contained in:
Julian Orth 2022-02-20 21:53:46 +01:00
parent fbb389b5e9
commit 292fa50fe7
18 changed files with 594 additions and 280 deletions

View file

@ -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
View 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();
}
}
}

View file

@ -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());
}
}

View file

@ -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)
// }

View file

@ -10,12 +10,6 @@ use crate::utils::linkedlist::LinkedList;
use std::fmt::Debug;
use std::rc::Rc;
tree_id!(WorkspaceNodeId);
pub struct WorkspaceNode {