From 26fab1e3e29fb4caa0ee1edbb12fcf694f526884 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sun, 20 Feb 2022 15:31:54 +0100 Subject: [PATCH] autocommit 2022-02-20 15:31:54 CET --- src/config/handler.rs | 17 ++- src/ifs/wl_seat.rs | 5 + src/ifs/wl_surface.rs | 8 ++ src/ifs/wl_surface/xdg_surface.rs | 18 ++- .../wl_surface/xdg_surface/xdg_toplevel.rs | 20 +++- src/macros.rs | 2 +- src/tree/container.rs | 112 +++++++++++++++++- src/tree/mod.rs | 23 +++- src/tree/workspace.rs | 4 + src/utils/clonecell.rs | 8 ++ 10 files changed, 198 insertions(+), 19 deletions(-) diff --git a/src/config/handler.rs b/src/config/handler.rs index 20710153..89f582ed 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -120,6 +120,12 @@ impl ConfigProxyHandler { Ok(()) } + fn handle_move(&self, seat: Seat, direction: Direction) -> Result<(), MoveError> { + let seat = self.get_seat(seat)?; + seat.move_focused(direction); + Ok(()) + } + fn handle_get_repeat_rate(&self, seat: Seat) -> Result<(), SeatGetRepeatRateError> { let seat = self.get_seat(seat)?; let (rate, delay) = seat.get_rate(); @@ -426,7 +432,7 @@ impl ConfigProxyHandler { self.handle_remove_shortcut(seat, mods, sym)? } ClientMessage::Focus { seat, direction } => self.handle_focus(seat, direction)?, - ClientMessage::Move { seat, direction } => {} + ClientMessage::Move { seat, direction } => self.handle_move(seat, direction)?, ClientMessage::GetInputDevices { seat } => self.handle_get_input_devices(seat), ClientMessage::GetSeats => self.handle_get_seats(), ClientMessage::RemoveSeat { .. } => {} @@ -467,6 +473,8 @@ enum CphError { SeatSetRepeatRateError(#[from] SeatSetRepeatRateError), #[error("Could not process a `focus` request")] FocusError(#[from] FocusError), + #[error("Could not process a `move` request")] + MoveError(#[from] MoveError), #[error("Could not process a `set_split` request")] SetSplitError(#[from] SetSplitError), #[error("Could not process a `get_split` request")] @@ -554,6 +562,13 @@ enum FocusError { } efrom!(FocusError, CphError); +#[derive(Debug, Error)] +enum MoveError { + #[error(transparent)] + CphError(#[from] Box), +} +efrom!(MoveError, CphError); + #[derive(Debug, Error)] enum SetSplitError { #[error(transparent)] diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 4a6d9486..9c3e5ed6 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -227,6 +227,11 @@ impl WlSeatGlobal { kb_node.move_focus(self, direction); } + pub fn move_focused(self: &Rc, direction: Direction) { + let kb_node = self.keyboard_node.get(); + kb_node.move_self(direction); + } + fn set_selection_( self: &Rc, field: &CloneCell>>, diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 233c1ba1..0d1b2f8c 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -637,6 +637,14 @@ impl Node for WlSurface { xdg.move_focus(seat, direction); } + fn move_self(self: Rc, direction: Direction) { + let xdg = match self.xdg.get() { + Some(x) => x, + _ => return, + }; + xdg.move_self(direction); + } + fn absolute_position(&self) -> Rect { self.buffer_abs_pos.get() } diff --git a/src/ifs/wl_surface/xdg_surface.rs b/src/ifs/wl_surface/xdg_surface.rs index 4725c2e8..c213d50e 100644 --- a/src/ifs/wl_surface/xdg_surface.rs +++ b/src/ifs/wl_surface/xdg_surface.rs @@ -96,6 +96,10 @@ pub trait XdgSurfaceExt: Debug { let _ = direction; } + fn move_self(self: Rc, direction: Direction) { + let _ = direction; + } + fn initial_configure(self: Rc) -> Result<(), XdgSurfaceError> { Ok(()) } @@ -171,11 +175,15 @@ impl XdgSurface { } pub fn move_focus(&self, seat: &Rc, direction: Direction) { - let ext = match self.ext.get() { - None => return, - Some(e) => e, - }; - ext.move_focus(seat, direction); + if let Some(ext)= self.ext.get() { + ext.move_focus(seat, direction); + } + } + + pub fn move_self(&self, direction: Direction) { + if let Some(ext)= self.ext.get() { + ext.move_self(direction); + } } pub fn role(&self) -> XdgSurfaceRole { diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index b1e0da07..b4addfc6 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -510,6 +510,11 @@ impl Node for XdgToplevel { self.xdg.set_workspace(ws); } + fn set_parent(self: Rc, parent: Rc) { + self.parent_node.set(Some(parent)); + self.notify_parent(); + } + fn client(&self) -> Option> { Some(self.xdg.surface.client.clone()) } @@ -546,15 +551,18 @@ impl XdgSurfaceExt for XdgToplevel { )); self.parent_node.set(Some(cn.clone())); pn.replace_child(&*self, cn); - self.notify_parent(); } fn move_focus(self: Rc, seat: &Rc, direction: Direction) { - let pn = match self.parent_node.get() { - Some(pn) => pn, - _ => return, - }; - pn.move_focus_from_child(seat, &*self, direction); + if let Some(pn) = self.parent_node.get() { + pn.move_focus_from_child(seat, &*self, direction); + } + } + + fn move_self(self: Rc, direction: Direction) { + if let Some(pn) = self.parent_node.get() { + pn.move_child(self, direction); + } } fn initial_configure(self: Rc) -> Result<(), XdgSurfaceError> { diff --git a/src/macros.rs b/src/macros.rs index 5541bc80..6c7c9dcd 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -31,7 +31,7 @@ macro_rules! object_base { ) -> Result<(), $ename> { match request { $( - $code => slf.$f(parser)?, + $code => $oname::$f(&slf, parser)?, )* _ => unreachable!(), } diff --git a/src/tree/container.rs b/src/tree/container.rs index 0e88803f..c4d89565 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -1,6 +1,6 @@ use crate::cursor::KnownCursor; use crate::fixed::Fixed; -use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT}; +use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT, Dnd}; use crate::rect::Rect; use crate::render::{Renderer, Texture}; use crate::theme::Color; @@ -12,6 +12,7 @@ use crate::{text, ErrorFmt, NumCell, State}; use ahash::AHashMap; use i4config::{Axis, Direction}; use std::cell::{Cell, RefCell}; +use std::collections::hash_map::Entry; use std::fmt::{Debug, Formatter}; use std::mem; use std::ops::{Deref, DerefMut, Sub}; @@ -85,6 +86,7 @@ impl Debug for ContainerNode { } } +#[derive(Clone)] pub struct ContainerChild { pub node: Rc, pub active: Cell, @@ -185,13 +187,23 @@ impl ContainerNode { } pub fn add_child_after(self: &Rc, prev: &dyn Node, new: Rc) { + self.add_child_x(prev, new, |prev, new| self.add_child_after_(prev, new)); + } + + pub fn add_child_before(self: &Rc, prev: &dyn Node, new: Rc) { + self.add_child_x(prev, new, |prev, new| self.add_child_before_(prev, new)); + } + + fn add_child_x(self: &Rc, prev: &dyn Node, new: Rc, f: F) + where F: FnOnce(&NodeRef, Rc), + { let node = self .child_nodes .borrow() .get(&prev.id()) .map(|n| n.to_ref()); if let Some(node) = node { - self.add_child_after_(&node, new); + f(&node, new); return; } log::error!( @@ -200,6 +212,16 @@ impl ContainerNode { } fn add_child_after_(self: &Rc, prev: &NodeRef, new: Rc) { + self.add_child(|cc| prev.append(cc), new); + } + + fn add_child_before_(self: &Rc, prev: &NodeRef, new: Rc) { + self.add_child(|cc| prev.prepend(cc), new); + } + + fn add_child(self: &Rc, f: F, new: Rc) + where F: FnOnce(ContainerChild) -> LinkedNode, + { { let mut links = self.child_nodes.borrow_mut(); if links.contains_key(&new.id()) { @@ -208,7 +230,7 @@ impl ContainerNode { } links.insert( new.id(), - prev.append(ContainerChild { + f(ContainerChild { node: new.clone(), active: Cell::new(false), body: Default::default(), @@ -221,6 +243,7 @@ impl ContainerNode { ); } new.clone().set_workspace(&self.workspace.get()); + new.clone().set_parent(self.clone()); let num_children = self.num_children.fetch_add(1) + 1; self.update_content_size(); let new_child_factor = 1.0 / num_children as f64; @@ -456,6 +479,7 @@ impl ContainerNode { title.push_str("]"); self.parent.get().child_title_changed(&**self, &title); self.schedule_render_titles(); + log::info!("num children: {}", self.num_children.get()); } fn schedule_render_titles(self: &Rc) { @@ -593,6 +617,10 @@ impl Node for ContainerNode { self.parent.get().move_focus_from_child(seat, &*self, direction); } + fn move_self(self: Rc, direction: Direction) { + self.parent.get().move_child(self, direction); + } + fn do_focus(self: Rc, seat: &Rc, direction: Direction) { let node = match direction { Direction::Left => self.children.last(), @@ -646,6 +674,62 @@ impl Node for ContainerNode { }; sibling.node.clone().do_focus(seat, direction); } + // + fn move_child( + self: Rc, + child: Rc, + direction: Direction, + ) { + // CASE 1: This is the only child of the container. Replace the container by the child. + if self.num_children.get() == 1 { + if let Some(parent) = self.parent.get().into_container() { + parent.replace_child(&*self, child.clone()); + } + return; + } + let (split, prev) = direction_to_split(direction); + // CASE 2: We're moving the child within the container. + if split == self.split.get() { + let mut cn = self.child_nodes.borrow_mut(); + let mut child = match cn.entry(child.id()) { + Entry::Occupied(o) => o, + Entry::Vacant(_) => return, + }; + let neighbor = match prev { + true => child.get().prev(), + false => child.get().next(), + }; + if let Some(neighbor) = neighbor { + let cc = child.get().deref().deref().clone(); + let link = match prev { + true => neighbor.prepend(cc), + false => neighbor.append(cc), + }; + child.insert(link); + self.schedule_layout(); + return; + } + } + // CASE 3: We're moving the child out of the container. + let mut neighbor = self.clone(); + let mut parent_opt = self.parent.get().into_container(); + while let Some(parent) = &parent_opt { + if parent.split.get() == split { + break; + } + neighbor = parent.clone(); + parent_opt = parent.parent.get().into_container(); + } + let parent = match parent_opt { + Some(p) => p, + _ => return, + }; + self.clone().remove_child(&*child); + match prev { + true => parent.add_child_before(&*neighbor, child.clone()), + false => parent.add_child_after(&*neighbor, child.clone()), + } + } fn absolute_position(&self) -> Rect { Rect::new_sized( @@ -762,7 +846,7 @@ impl Node for ContainerNode { FindTreeResult::AcceptsInput } - fn replace_child(&self, old: &dyn Node, new: Rc) { + fn replace_child(self: Rc, old: &dyn Node, new: Rc) { let node = match self.child_nodes.borrow_mut().remove(&old.id()) { Some(c) => c, None => return, @@ -777,9 +861,12 @@ impl Node for ContainerNode { title: Default::default(), title_texture: Default::default(), }); + let body = link.body.get(); + drop(node); self.child_nodes.borrow_mut().insert(new.id(), link); + new.clone().set_parent(self.clone()); new.clone().set_workspace(&self.workspace.get()); - let body = node.body.get().move_(self.abs_x1.get(), self.abs_y1.get()); + let body = body.move_(self.abs_x1.get(), self.abs_y1.get()); new.clone().change_extents(&body); } @@ -890,4 +977,19 @@ impl Node for ContainerNode { } self.workspace.set(ws.clone()); } + + fn set_parent(self: Rc, parent: Rc) { + self.parent.set(parent.clone()); + parent.child_size_changed(&*self, self.width.get(), self.height.get()); + parent.clone().child_title_changed(&*self, self.title.borrow_mut().deref()); + } +} + +fn direction_to_split(dir: Direction) -> (ContainerSplit, bool) { + match dir { + Direction::Left => (ContainerSplit::Horizontal, true), + Direction::Down => (ContainerSplit::Vertical, false), + Direction::Up => (ContainerSplit::Vertical, true), + Direction::Right => (ContainerSplit::Horizontal, false), + } } diff --git a/src/tree/mod.rs b/src/tree/mod.rs index e774644c..57aa3793 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -110,6 +110,10 @@ pub trait Node { let _ = direction; } + fn move_self(self: Rc, direction: Direction) { + let _ = direction; + } + fn move_focus_from_child( &self, seat: &Rc, @@ -121,6 +125,15 @@ pub trait Node { let _ = child; } + fn move_child( + self: Rc, + child: Rc, + direction: Direction, + ) { + let _ = direction; + let _ = child; + } + fn absolute_position(&self) -> Rect { Rect::new_empty(0, 0) } @@ -175,7 +188,7 @@ pub trait Node { FindTreeResult::Other } - fn replace_child(&self, old: &dyn Node, new: Rc) { + fn replace_child(self: Rc, old: &dyn Node, new: Rc) { let _ = old; let _ = new; } @@ -234,6 +247,10 @@ pub trait Node { false } + fn is_workspace(&self) -> bool { + false + } + fn change_extents(self: Rc, rect: &Rect) { let _ = rect; } @@ -242,6 +259,10 @@ pub trait Node { let _ = ws; } + fn set_parent(self: Rc, parent: Rc) { + let _ = parent; + } + fn client(&self) -> Option> { None } diff --git a/src/tree/workspace.rs b/src/tree/workspace.rs index d25c56bd..bca48d7f 100644 --- a/src/tree/workspace.rs +++ b/src/tree/workspace.rs @@ -86,6 +86,10 @@ impl Node for WorkspaceNode { renderer.render_workspace(self, x, y); } + fn is_workspace(&self) -> bool { + true + } + fn change_extents(self: Rc, rect: &Rect) { if let Some(c) = self.container.get() { c.change_extents(rect); diff --git a/src/utils/clonecell.rs b/src/utils/clonecell.rs index 9b7f60b4..ffad3ea0 100644 --- a/src/utils/clonecell.rs +++ b/src/utils/clonecell.rs @@ -9,6 +9,14 @@ pub struct CloneCell { data: UnsafeCell, } +impl Clone for CloneCell { + fn clone(&self) -> Self { + Self { + data: UnsafeCell::new(self.get()), + } + } +} + impl Debug for CloneCell { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { unsafe { self.data.get().deref().fmt(f) }