tree: add window-management mode
This commit is contained in:
parent
1a73bbd075
commit
70a8f47288
20 changed files with 644 additions and 9 deletions
|
|
@ -338,6 +338,16 @@ impl ConfigProxyHandler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_set_window_management_enabled(
|
||||
&self,
|
||||
seat: Seat,
|
||||
enabled: bool,
|
||||
) -> Result<(), CphError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
seat.set_window_management_enabled(enabled);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_set_input_device_connector(
|
||||
&self,
|
||||
input_device: InputDevice,
|
||||
|
|
@ -1816,6 +1826,9 @@ impl ConfigProxyHandler {
|
|||
ClientMessage::RemoveInputMapping { input_device } => self
|
||||
.handle_remove_input_mapping(input_device)
|
||||
.wrn("remove_input_mapping")?,
|
||||
ClientMessage::SetWindowManagementEnabled { seat, enabled } => self
|
||||
.handle_set_window_management_enabled(seat, enabled)
|
||||
.wrn("set_window_management_enabled")?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -955,6 +955,11 @@ impl WlSeatGlobal {
|
|||
pub fn set_focus_follows_mouse(&self, focus_follows_mouse: bool) {
|
||||
self.focus_follows_mouse.set(focus_follows_mouse);
|
||||
}
|
||||
|
||||
pub fn set_window_management_enabled(self: &Rc<Self>, enabled: bool) {
|
||||
self.pointer_owner
|
||||
.set_window_management_enabled(self, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
impl CursorUserOwner for WlSeatGlobal {
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ impl NodeSeatState {
|
|||
seat.gesture_owner.revert_to_default(&seat);
|
||||
}
|
||||
while let Some((_, seat)) = self.pointer_grabs.pop() {
|
||||
seat.pointer_owner.revert_to_default(&seat);
|
||||
seat.pointer_owner.grab_node_removed(&seat);
|
||||
}
|
||||
let node_id = node.node_id();
|
||||
while let Some((_, seat)) = self.dnd_targets.pop() {
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ use {
|
|||
ipc::wl_data_source::WlDataSource,
|
||||
wl_seat::{
|
||||
wl_pointer::PendingScroll, Dnd, DroppedDnd, WlSeatError, WlSeatGlobal, BTN_LEFT,
|
||||
BTN_RIGHT, CHANGE_CURSOR_MOVED,
|
||||
BTN_RIGHT, CHANGE_CURSOR_MOVED, CHANGE_TREE,
|
||||
},
|
||||
wl_surface::WlSurface,
|
||||
xdg_toplevel_drag_v1::XdgToplevelDragV1,
|
||||
},
|
||||
state::DeviceHandlerData,
|
||||
tree::{FindTreeUsecase, FoundNode, Node, ToplevelNode, WorkspaceNode},
|
||||
tree::{ContainingNode, FindTreeUsecase, FoundNode, Node, ToplevelNode, WorkspaceNode},
|
||||
utils::{clonecell::CloneCell, smallmap::SmallMap},
|
||||
},
|
||||
std::{
|
||||
|
|
@ -136,6 +136,10 @@ impl PointerOwnerHolder {
|
|||
self.owner.get().revert_to_default(seat)
|
||||
}
|
||||
|
||||
pub fn grab_node_removed(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
self.owner.get().grab_node_removed(seat);
|
||||
}
|
||||
|
||||
pub fn dnd_target_removed(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
self.owner.get().dnd_target_removed(seat);
|
||||
}
|
||||
|
|
@ -187,6 +191,15 @@ impl PointerOwnerHolder {
|
|||
});
|
||||
self.select_element(seat, usecase)
|
||||
}
|
||||
|
||||
pub fn set_window_management_enabled(&self, seat: &Rc<WlSeatGlobal>, enabled: bool) {
|
||||
let owner = self.owner.get();
|
||||
if enabled {
|
||||
owner.enable_window_management(seat);
|
||||
} else {
|
||||
owner.disable_window_management(seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait PointerOwner {
|
||||
|
|
@ -213,6 +226,9 @@ trait PointerOwner {
|
|||
seat.dropped_dnd.borrow_mut().take();
|
||||
}
|
||||
fn revert_to_default(&self, seat: &Rc<WlSeatGlobal>);
|
||||
fn grab_node_removed(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
self.revert_to_default(seat);
|
||||
}
|
||||
fn dnd_target_removed(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
self.cancel_dnd(seat);
|
||||
}
|
||||
|
|
@ -225,6 +241,12 @@ trait PointerOwner {
|
|||
fn remove_dnd_icon(&self) {
|
||||
// nothing
|
||||
}
|
||||
fn enable_window_management(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
let _ = seat;
|
||||
}
|
||||
fn disable_window_management(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
let _ = seat;
|
||||
}
|
||||
}
|
||||
|
||||
struct SimplePointerOwner<T> {
|
||||
|
|
@ -262,6 +284,9 @@ struct SelectWorkspaceUsecase<S: ?Sized> {
|
|||
selector: S,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct WindowManagementUsecase;
|
||||
|
||||
impl<T: SimplePointerOwnerUsecase> PointerOwner for SimplePointerOwner<T> {
|
||||
fn button(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, button: u32, state: KeyState) {
|
||||
if state != KeyState::Pressed {
|
||||
|
|
@ -363,6 +388,21 @@ impl<T: SimplePointerOwnerUsecase> PointerOwner for SimplePointerOwner<T> {
|
|||
seat.state.damage();
|
||||
}
|
||||
}
|
||||
|
||||
fn enable_window_management(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
if !T::IS_DEFAULT {
|
||||
return;
|
||||
}
|
||||
seat.pointer_owner.owner.set(Rc::new(SimplePointerOwner {
|
||||
usecase: WindowManagementUsecase,
|
||||
}));
|
||||
seat.changes.or_assign(CHANGE_TREE);
|
||||
seat.apply_changes();
|
||||
}
|
||||
|
||||
fn disable_window_management(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
self.usecase.disable_window_management(seat);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SimplePointerOwnerUsecase> PointerOwner for SimpleGrabPointerOwner<T> {
|
||||
|
|
@ -572,6 +612,10 @@ trait SimplePointerOwnerUsecase: Sized + Clone + 'static {
|
|||
let _ = seat;
|
||||
let _ = node;
|
||||
}
|
||||
|
||||
fn disable_window_management(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
let _ = seat;
|
||||
}
|
||||
}
|
||||
|
||||
impl SimplePointerOwnerUsecase for DefaultPointerUsecase {
|
||||
|
|
@ -795,3 +839,218 @@ impl<S: ?Sized> Drop for SelectWorkspaceUsecase<S> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SimplePointerOwnerUsecase for WindowManagementUsecase {
|
||||
const FIND_TREE_USECASE: FindTreeUsecase = FindTreeUsecase::SelectToplevel;
|
||||
const IS_DEFAULT: bool = false;
|
||||
|
||||
fn default_button(
|
||||
&self,
|
||||
_spo: &SimplePointerOwner<Self>,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
button: u32,
|
||||
pn: &Rc<dyn Node>,
|
||||
) -> bool {
|
||||
let Some(tl) = pn.clone().node_into_toplevel() else {
|
||||
return false;
|
||||
};
|
||||
let pos = tl.node_absolute_position();
|
||||
let (x, y) = seat.pointer_cursor.position();
|
||||
let (x, y) = (x.round_down(), y.round_down());
|
||||
let (mut dx, mut dy) = pos.translate(x, y);
|
||||
let owner: Rc<dyn PointerOwner> = if button == BTN_LEFT {
|
||||
seat.pointer_cursor.set_known(KnownCursor::Move);
|
||||
Rc::new(ToplevelGrabPointerOwner {
|
||||
tl,
|
||||
usecase: MoveToplevelGrabPointerOwner { dx, dy },
|
||||
})
|
||||
} else if button == BTN_RIGHT {
|
||||
let mut top = false;
|
||||
let mut right = false;
|
||||
let mut bottom = false;
|
||||
let mut left = false;
|
||||
if dx <= pos.width() / 2 {
|
||||
left = true;
|
||||
} else {
|
||||
right = true;
|
||||
dx = pos.width() - dx;
|
||||
}
|
||||
if dy <= pos.height() / 2 {
|
||||
top = true;
|
||||
} else {
|
||||
bottom = true;
|
||||
dy = pos.height() - dy;
|
||||
}
|
||||
let cursor = match (top, right, bottom, left) {
|
||||
(true, true, false, false) => KnownCursor::NeResize,
|
||||
(false, true, true, false) => KnownCursor::SeResize,
|
||||
(false, false, true, true) => KnownCursor::SwResize,
|
||||
(true, false, false, true) => KnownCursor::NwResize,
|
||||
_ => KnownCursor::Move,
|
||||
};
|
||||
seat.pointer_cursor.set_known(cursor);
|
||||
Rc::new(ToplevelGrabPointerOwner {
|
||||
tl,
|
||||
usecase: ResizeToplevelGrabPointerOwner {
|
||||
top,
|
||||
right,
|
||||
bottom,
|
||||
left,
|
||||
dx,
|
||||
dy,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
seat.pointer_owner.owner.set(owner);
|
||||
pn.node_seat_state().add_pointer_grab(seat);
|
||||
true
|
||||
}
|
||||
|
||||
fn release_grab(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
seat.pointer_owner
|
||||
.owner
|
||||
.set(Rc::new(SimplePointerOwner { usecase: *self }));
|
||||
seat.changes.or_assign(CHANGE_CURSOR_MOVED);
|
||||
}
|
||||
|
||||
fn disable_window_management(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
seat.pointer_owner.set_default_pointer_owner(seat);
|
||||
seat.apply_changes();
|
||||
}
|
||||
}
|
||||
|
||||
trait WindowManagementGrabUsecase {
|
||||
const BUTTON: u32;
|
||||
|
||||
fn apply_changes(
|
||||
&self,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
parent: Rc<dyn ContainingNode>,
|
||||
tl: &Rc<dyn ToplevelNode>,
|
||||
);
|
||||
}
|
||||
|
||||
struct ToplevelGrabPointerOwner<T> {
|
||||
tl: Rc<dyn ToplevelNode>,
|
||||
usecase: T,
|
||||
}
|
||||
|
||||
impl<T> PointerOwner for ToplevelGrabPointerOwner<T>
|
||||
where
|
||||
T: WindowManagementGrabUsecase,
|
||||
{
|
||||
fn button(&self, seat: &Rc<WlSeatGlobal>, _time_usec: u64, button: u32, state: KeyState) {
|
||||
if button != T::BUTTON || state != KeyState::Released {
|
||||
return;
|
||||
}
|
||||
self.tl.node_seat_state().remove_pointer_grab(seat);
|
||||
self.grab_node_removed(seat);
|
||||
}
|
||||
|
||||
fn axis_node(&self, _seat: &Rc<WlSeatGlobal>) -> Option<Rc<dyn Node>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn apply_changes(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
let Some(parent) = self.tl.tl_data().parent.get() else {
|
||||
return;
|
||||
};
|
||||
self.usecase.apply_changes(seat, parent, &self.tl);
|
||||
}
|
||||
|
||||
fn revert_to_default(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
seat.pointer_owner.set_default_pointer_owner(seat);
|
||||
}
|
||||
|
||||
fn grab_node_removed(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
seat.pointer_cursor.set_known(KnownCursor::Default);
|
||||
seat.pointer_owner.owner.set(Rc::new(SimplePointerOwner {
|
||||
usecase: WindowManagementUsecase,
|
||||
}));
|
||||
seat.changes.or_assign(CHANGE_CURSOR_MOVED);
|
||||
seat.apply_changes();
|
||||
}
|
||||
|
||||
fn disable_window_management(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
seat.pointer_owner.set_default_pointer_owner(seat);
|
||||
seat.apply_changes();
|
||||
}
|
||||
}
|
||||
|
||||
struct MoveToplevelGrabPointerOwner {
|
||||
dx: i32,
|
||||
dy: i32,
|
||||
}
|
||||
|
||||
impl WindowManagementGrabUsecase for MoveToplevelGrabPointerOwner {
|
||||
const BUTTON: u32 = BTN_LEFT;
|
||||
|
||||
fn apply_changes(
|
||||
&self,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
parent: Rc<dyn ContainingNode>,
|
||||
tl: &Rc<dyn ToplevelNode>,
|
||||
) {
|
||||
let (x, y) = seat.pointer_cursor.position();
|
||||
let (x, y) = (x.round_down() - self.dx, y.round_down() - self.dy);
|
||||
parent.cnode_set_child_position(tl.tl_as_node(), x, y);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ResizeToplevelGrabPointerOwner {
|
||||
top: bool,
|
||||
right: bool,
|
||||
bottom: bool,
|
||||
left: bool,
|
||||
dx: i32,
|
||||
dy: i32,
|
||||
}
|
||||
|
||||
impl WindowManagementGrabUsecase for ResizeToplevelGrabPointerOwner {
|
||||
const BUTTON: u32 = BTN_RIGHT;
|
||||
|
||||
fn apply_changes(
|
||||
&self,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
parent: Rc<dyn ContainingNode>,
|
||||
tl: &Rc<dyn ToplevelNode>,
|
||||
) {
|
||||
let (x, y) = seat.pointer_cursor.position();
|
||||
let (x, y) = (x.round_down(), y.round_down());
|
||||
let pos = tl.node_absolute_position();
|
||||
let mut x1 = None;
|
||||
let mut x2 = None;
|
||||
let mut y1 = None;
|
||||
let mut y2 = None;
|
||||
if self.top {
|
||||
let new_v = y - self.dy;
|
||||
if new_v != pos.y1() {
|
||||
y1 = Some(new_v);
|
||||
}
|
||||
}
|
||||
if self.right {
|
||||
let new_v = x + self.dx;
|
||||
if new_v != pos.x2() {
|
||||
x2 = Some(new_v);
|
||||
}
|
||||
}
|
||||
if self.bottom {
|
||||
let new_v = y + self.dy;
|
||||
if new_v != pos.y2() {
|
||||
y2 = Some(new_v);
|
||||
}
|
||||
}
|
||||
if self.left {
|
||||
let new_v = x - self.dx;
|
||||
if new_v != pos.x1() {
|
||||
x1 = Some(new_v);
|
||||
}
|
||||
}
|
||||
if x1.is_some() || x2.is_some() || y1.is_some() || y2.is_some() {
|
||||
parent.cnode_resize_child(tl.tl_as_node(), x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1543,6 +1543,159 @@ impl ContainingNode for ContainerNode {
|
|||
fn cnode_workspace(self: Rc<Self>) -> Rc<WorkspaceNode> {
|
||||
self.workspace.get()
|
||||
}
|
||||
|
||||
fn cnode_set_child_position(self: Rc<Self>, child: &dyn Node, x: i32, y: i32) {
|
||||
let Some(parent) = self.toplevel_data.parent.get() else {
|
||||
return;
|
||||
};
|
||||
let th = self.state.theme.sizes.title_height.get();
|
||||
if self.mono_child.is_some() {
|
||||
parent.cnode_set_child_position(&*self, x, y - th - 1);
|
||||
} else {
|
||||
let children = self.child_nodes.borrow();
|
||||
let Some(child) = children.get(&child.node_id()) else {
|
||||
return;
|
||||
};
|
||||
let pos = child.body.get();
|
||||
let (x, y) = pos.translate(x, y);
|
||||
parent.cnode_set_child_position(&*self, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
fn cnode_resize_child(
|
||||
self: Rc<Self>,
|
||||
child: &dyn Node,
|
||||
new_x1: Option<i32>,
|
||||
new_y1: Option<i32>,
|
||||
new_x2: Option<i32>,
|
||||
new_y2: Option<i32>,
|
||||
) {
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.sizes.title_height.get();
|
||||
let bw = theme.sizes.border_width.get();
|
||||
let mut left_outside = false;
|
||||
let mut right_outside = false;
|
||||
let mut top_outside = false;
|
||||
let mut bottom_outside = false;
|
||||
if self.mono_child.is_some() {
|
||||
top_outside = true;
|
||||
right_outside = true;
|
||||
bottom_outside = true;
|
||||
left_outside = true;
|
||||
} else {
|
||||
let children = self.child_nodes.borrow();
|
||||
let Some(child) = children.get(&child.node_id()) else {
|
||||
return;
|
||||
};
|
||||
let pos = child.body.get();
|
||||
let split = self.split.get();
|
||||
let mut changed_any = false;
|
||||
let (mut i1, mut i2, new_i1, new_i2, mut ci) = match split {
|
||||
ContainerSplit::Horizontal => {
|
||||
top_outside = true;
|
||||
bottom_outside = true;
|
||||
(pos.x1(), pos.x2(), new_x1, new_x2, self.content_width.get())
|
||||
}
|
||||
ContainerSplit::Vertical => {
|
||||
right_outside = true;
|
||||
left_outside = true;
|
||||
(
|
||||
pos.y1(),
|
||||
pos.y2(),
|
||||
new_y1,
|
||||
new_y2,
|
||||
self.content_height.get(),
|
||||
)
|
||||
}
|
||||
};
|
||||
if ci == 0 {
|
||||
ci = 1;
|
||||
}
|
||||
let (new_delta, between) = match split {
|
||||
ContainerSplit::Horizontal => (self.abs_x1.get(), bw),
|
||||
ContainerSplit::Vertical => (self.abs_y1.get(), bw + th + 1),
|
||||
};
|
||||
let new_i1 = new_i1.map(|v| v - new_delta);
|
||||
let new_i2 = new_i2.map(|v| v - new_delta);
|
||||
let (orig_i1, orig_i2) = (i1, i2);
|
||||
let mut sum_factors = self.sum_factors.get();
|
||||
if let Some(new_i1) = new_i1 {
|
||||
if let Some(peer) = child.prev() {
|
||||
let peer_pos = peer.body.get();
|
||||
let peer_i1 = match self.split.get() {
|
||||
ContainerSplit::Horizontal => peer_pos.x1(),
|
||||
ContainerSplit::Vertical => peer_pos.y1(),
|
||||
};
|
||||
i1 = new_i1.max(peer_i1 + between).min(i2);
|
||||
if i1 != orig_i1 {
|
||||
let peer_factor = (i1 - between - peer_i1) as f64 / ci as f64;
|
||||
sum_factors = sum_factors - peer.factor.get() + peer_factor;
|
||||
peer.factor.set(peer_factor);
|
||||
changed_any = true;
|
||||
}
|
||||
} else {
|
||||
match split {
|
||||
ContainerSplit::Horizontal => left_outside = true,
|
||||
ContainerSplit::Vertical => top_outside = true,
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(new_i2) = new_i2 {
|
||||
if let Some(peer) = child.next() {
|
||||
let peer_pos = peer.body.get();
|
||||
let peer_i2 = match self.split.get() {
|
||||
ContainerSplit::Horizontal => peer_pos.x2(),
|
||||
ContainerSplit::Vertical => peer_pos.y2(),
|
||||
};
|
||||
i2 = new_i2.min(peer_i2 - between).max(i1);
|
||||
if i2 != orig_i2 {
|
||||
let peer_factor = (peer_i2 - between - i2) as f64 / ci as f64;
|
||||
sum_factors = sum_factors - peer.factor.get() + peer_factor;
|
||||
peer.factor.set(peer_factor);
|
||||
changed_any = true;
|
||||
}
|
||||
} else {
|
||||
match split {
|
||||
ContainerSplit::Horizontal => right_outside = true,
|
||||
ContainerSplit::Vertical => bottom_outside = true,
|
||||
}
|
||||
}
|
||||
}
|
||||
if changed_any {
|
||||
let factor = (i2 - i1) as f64 / ci as f64;
|
||||
sum_factors = sum_factors - child.factor.get() + factor;
|
||||
child.factor.set(factor);
|
||||
self.sum_factors.set(sum_factors);
|
||||
self.schedule_layout();
|
||||
}
|
||||
}
|
||||
let pos = self.node_absolute_position();
|
||||
let mut x1 = None;
|
||||
let mut x2 = None;
|
||||
let mut y1 = None;
|
||||
let mut y2 = None;
|
||||
if left_outside {
|
||||
x1 = new_x1.map(|v| v.min(pos.x2()));
|
||||
}
|
||||
if right_outside {
|
||||
x2 = new_x2.map(|v| v.max(x1.unwrap_or(pos.x1())));
|
||||
}
|
||||
if top_outside {
|
||||
y1 = new_y1.map(|v| (v - th - 1).min(pos.y2() - th - 1));
|
||||
}
|
||||
if bottom_outside {
|
||||
y2 = new_y2.map(|v| v.max(y1.unwrap_or(pos.y1()) + th + 1));
|
||||
}
|
||||
if (x1.is_some() && x1 != Some(pos.x1()))
|
||||
|| (x2.is_some() && x2 != Some(pos.x2()))
|
||||
|| (y1.is_some() && y1 != Some(pos.y1()))
|
||||
|| (y2.is_some() && y2 != Some(pos.y2()))
|
||||
{
|
||||
if let Some(parent) = self.toplevel_data.parent.get() {
|
||||
parent.cnode_resize_child(&*self, x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToplevelNodeBase for ContainerNode {
|
||||
|
|
|
|||
|
|
@ -12,4 +12,23 @@ pub trait ContainingNode: Node {
|
|||
fn cnode_accepts_child(&self, node: &dyn Node) -> bool;
|
||||
fn cnode_child_attention_request_changed(self: Rc<Self>, child: &dyn Node, set: bool);
|
||||
fn cnode_workspace(self: Rc<Self>) -> Rc<WorkspaceNode>;
|
||||
fn cnode_set_child_position(self: Rc<Self>, child: &dyn Node, x: i32, y: i32) {
|
||||
let _ = child;
|
||||
let _ = x;
|
||||
let _ = y;
|
||||
}
|
||||
fn cnode_resize_child(
|
||||
self: Rc<Self>,
|
||||
child: &dyn Node,
|
||||
new_x1: Option<i32>,
|
||||
new_y1: Option<i32>,
|
||||
new_x2: Option<i32>,
|
||||
new_y2: Option<i32>,
|
||||
) {
|
||||
let _ = child;
|
||||
let _ = new_x1;
|
||||
let _ = new_x2;
|
||||
let _ = new_y1;
|
||||
let _ = new_y2;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -708,6 +708,55 @@ impl ContainingNode for FloatNode {
|
|||
fn cnode_workspace(self: Rc<Self>) -> Rc<WorkspaceNode> {
|
||||
self.workspace.get()
|
||||
}
|
||||
|
||||
fn cnode_set_child_position(self: Rc<Self>, _child: &dyn Node, x: i32, y: i32) {
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.sizes.title_height.get();
|
||||
let bw = theme.sizes.border_width.get();
|
||||
let (x, y) = (x - bw, y - th - bw - 1);
|
||||
let pos = self.position.get();
|
||||
if pos.position() != (x, y) {
|
||||
self.position.set(pos.at_point(x, y));
|
||||
self.state.damage();
|
||||
self.schedule_layout();
|
||||
}
|
||||
}
|
||||
|
||||
fn cnode_resize_child(
|
||||
self: Rc<Self>,
|
||||
_child: &dyn Node,
|
||||
new_x1: Option<i32>,
|
||||
new_y1: Option<i32>,
|
||||
new_x2: Option<i32>,
|
||||
new_y2: Option<i32>,
|
||||
) {
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.sizes.title_height.get();
|
||||
let bw = theme.sizes.border_width.get();
|
||||
let pos = self.position.get();
|
||||
let mut x1 = pos.x1();
|
||||
let mut x2 = pos.x2();
|
||||
let mut y1 = pos.y1();
|
||||
let mut y2 = pos.y2();
|
||||
if let Some(v) = new_x1 {
|
||||
x1 = (v - bw).min(x2 - bw - bw);
|
||||
}
|
||||
if let Some(v) = new_x2 {
|
||||
x2 = (v + bw).max(x1 + bw + bw);
|
||||
}
|
||||
if let Some(v) = new_y1 {
|
||||
y1 = (v - th - bw - 1).min(y2 - bw - th - bw - 1);
|
||||
}
|
||||
if let Some(v) = new_y2 {
|
||||
y2 = (v + bw).max(y1 + bw + th + bw + 1);
|
||||
}
|
||||
let new_pos = Rect::new(x1, y1, x2, y2).unwrap();
|
||||
if new_pos != pos {
|
||||
self.position.set(new_pos);
|
||||
self.state.damage();
|
||||
self.schedule_layout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StackedNode for FloatNode {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue