From ab3c2e44f4c4e67e04f199ae2bfc4bbb32ad4b37 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Wed, 20 Apr 2022 16:11:37 +0200 Subject: [PATCH] autocommit 2022-04-20 16:11:37 CEST --- default-config/src/lib.rs | 10 +- jay-config/src/_private/client.rs | 38 ++++-- jay-config/src/_private/ipc.rs | 10 ++ jay-config/src/input.rs | 13 ++ src/config/handler.rs | 20 +++ src/ifs/wl_seat.rs | 8 ++ src/ifs/wl_surface.rs | 10 ++ .../wl_surface/xdg_surface/xdg_toplevel.rs | 98 ++++++++------ src/ifs/wl_surface/xwindow.rs | 22 ++-- src/state.rs | 92 +------------ src/tree.rs | 25 +++- src/tree/container.rs | 16 ++- src/tree/display.rs | 4 +- src/tree/fullscreen.rs | 122 ++++++++++++++++-- src/tree/output.rs | 6 +- src/tree/placeholder.rs | 55 ++++---- src/tree/toplevel.rs | 60 ++++++++- src/tree/walker.rs | 5 +- src/tree/workspace.rs | 5 +- 19 files changed, 409 insertions(+), 210 deletions(-) diff --git a/default-config/src/lib.rs b/default-config/src/lib.rs index 54211b9f..2c34e9b5 100644 --- a/default-config/src/lib.rs +++ b/default-config/src/lib.rs @@ -13,10 +13,10 @@ use { mods::{Modifiers, ALT, CTRL, SHIFT}, syms::{ SYM_Super_L, SYM_a, SYM_b, SYM_c, SYM_d, SYM_e, SYM_f, SYM_h, SYM_j, SYM_k, SYM_l, - SYM_m, SYM_o, SYM_p, SYM_q, SYM_t, SYM_v, SYM_y, SYM_F1, SYM_F10, SYM_F11, SYM_F12, - SYM_F13, SYM_F14, SYM_F15, SYM_F16, SYM_F17, SYM_F18, SYM_F19, SYM_F2, SYM_F20, - SYM_F21, SYM_F22, SYM_F23, SYM_F24, SYM_F25, SYM_F3, SYM_F4, SYM_F5, SYM_F6, - SYM_F7, SYM_F8, SYM_F9, + SYM_m, SYM_o, SYM_p, SYM_q, SYM_t, SYM_u, SYM_v, SYM_y, SYM_F1, SYM_F10, SYM_F11, + SYM_F12, SYM_F13, SYM_F14, SYM_F15, SYM_F16, SYM_F17, SYM_F18, SYM_F19, SYM_F2, + SYM_F20, SYM_F21, SYM_F22, SYM_F23, SYM_F24, SYM_F25, SYM_F3, SYM_F4, SYM_F5, + SYM_F6, SYM_F7, SYM_F8, SYM_F9, }, }, quit, set_env, @@ -51,6 +51,8 @@ fn configure_seat(s: Seat) { s.bind(MOD | SYM_f, move || s.focus_parent()); + s.bind(MOD | SYM_u, move || s.toggle_fullscreen()); + s.bind(MOD | SHIFT | SYM_c, move || s.close()); s.bind(MOD | SHIFT | SYM_f, move || s.toggle_floating()); diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index c7ea2000..4a8a7054 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -216,19 +216,19 @@ impl Client { } pub fn seats(&self) -> Vec { - let res = self.with_response(|| self.send(&ClientMessage::GetSeats)); + let res = self.send_with_response(&ClientMessage::GetSeats); get_response!(res, vec![], GetSeats, seats); seats } pub fn mono(&self, seat: Seat) -> bool { - let res = self.with_response(|| self.send(&ClientMessage::GetMono { seat })); + let res = self.send_with_response(&ClientMessage::GetMono { seat }); get_response!(res, false, GetMono, mono); mono } pub fn get_timer(&self, name: &str) -> Timer { - let res = self.with_response(|| self.send(&ClientMessage::GetTimer { name })); + let res = self.send_with_response(&ClientMessage::GetTimer { name }); get_response!(res, Timer(0), GetTimer, timer); timer } @@ -255,13 +255,13 @@ impl Client { } pub fn get_workspace(&self, name: &str) -> Workspace { - let res = self.with_response(|| self.send(&ClientMessage::GetWorkspace { name })); + let res = self.send_with_response(&ClientMessage::GetWorkspace { name }); get_response!(res, Workspace(0), GetWorkspace, workspace); workspace } pub fn get_connector(&self, ty: ConnectorType, idx: u32) -> Connector { - let res = self.with_response(|| self.send(&ClientMessage::GetConnector { ty, idx })); + let res = self.send_with_response(&ClientMessage::GetConnector { ty, idx }); get_response!(res, Connector(0), GetConnector, connector); connector } @@ -271,11 +271,21 @@ impl Client { } pub fn split(&self, seat: Seat) -> Axis { - let res = self.with_response(|| self.send(&ClientMessage::GetSplit { seat })); + let res = self.send_with_response(&ClientMessage::GetSplit { seat }); get_response!(res, Axis::Horizontal, GetSplit, axis); axis } + pub fn set_fullscreen(&self, seat: Seat, fullscreen: bool) { + self.send(&ClientMessage::SetFullscreen { seat, fullscreen }); + } + + pub fn get_fullscreen(&self, seat: Seat) -> bool { + let res = self.send_with_response(&ClientMessage::GetFullscreen { seat }); + get_response!(res, false, GetFullscreen, fullscreen); + fullscreen + } + pub fn toggle_floating(&self, seat: Seat) { self.send(&ClientMessage::ToggleFloating { seat }); } @@ -297,13 +307,13 @@ impl Client { } pub fn get_title_height(&self) -> i32 { - let res = self.with_response(|| self.send(&ClientMessage::GetTitleHeight)); + let res = self.send_with_response(&ClientMessage::GetTitleHeight); get_response!(res, 0, GetTitleHeight, height); height } pub fn get_border_width(&self) -> i32 { - let res = self.with_response(|| self.send(&ClientMessage::GetBorderWidth)); + let res = self.send_with_response(&ClientMessage::GetBorderWidth); get_response!(res, 0, GetBorderWidth, width); width } @@ -345,13 +355,13 @@ impl Client { } pub fn create_seat(&self, name: &str) -> Seat { - let res = self.with_response(|| self.send(&ClientMessage::CreateSeat { name })); + let res = self.send_with_response(&ClientMessage::CreateSeat { name }); get_response!(res, Seat(0), CreateSeat, seat); seat } pub fn get_input_devices(&self, seat: Option) -> Vec { - let res = self.with_response(|| self.send(&ClientMessage::GetInputDevices { seat })); + let res = self.send_with_response(&ClientMessage::GetInputDevices { seat }); get_response!(res, vec!(), GetInputDevices, devices); devices } @@ -441,13 +451,13 @@ impl Client { } pub fn device_name(&self, device: InputDevice) -> String { - let res = self.with_response(|| self.send(&ClientMessage::GetDeviceName { device })); + let res = self.send_with_response(&ClientMessage::GetDeviceName { device }); get_response!(res, String::new(), GetDeviceName, name); name } pub fn has_capability(&self, device: InputDevice, cap: Capability) -> bool { - let res = self.with_response(|| self.send(&ClientMessage::HasCapability { device, cap })); + let res = self.send_with_response(&ClientMessage::HasCapability { device, cap }); get_response!(res, false, HasCapability, has); has } @@ -461,13 +471,13 @@ impl Client { } pub fn seat_get_repeat_rate(&self, seat: Seat) -> (i32, i32) { - let res = self.with_response(|| self.send(&ClientMessage::SeatGetRepeatRate { seat })); + let res = self.send_with_response(&ClientMessage::SeatGetRepeatRate { seat }); get_response!(res, (25, 250), GetRepeatRate, rate, delay); (rate, delay) } pub fn parse_keymap(&self, keymap: &str) -> Keymap { - let res = self.with_response(|| self.send(&ClientMessage::ParseKeymap { keymap })); + let res = self.send_with_response(&ClientMessage::ParseKeymap { keymap }); get_response!(res, Keymap(0), ParseKeymap, keymap); keymap } diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index 7a394bc3..ea2378ab 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -226,6 +226,13 @@ pub enum ClientMessage<'a> { key: &'a str, val: &'a str, }, + SetFullscreen { + seat: Seat, + fullscreen: bool, + }, + GetFullscreen { + seat: Seat, + }, } #[derive(Encode, Decode, Debug)] @@ -285,6 +292,9 @@ pub enum Response { height: i32, refresh_millihz: u32, }, + GetFullscreen { + fullscreen: bool, + }, } #[derive(Encode, Decode, Debug)] diff --git a/jay-config/src/input.rs b/jay-config/src/input.rs index 9d9b3218..f8bf725e 100644 --- a/jay-config/src/input.rs +++ b/jay-config/src/input.rs @@ -128,6 +128,19 @@ impl Seat { pub fn show_workspace(self, workspace: Workspace) { get!().show_workspace(self, workspace) } + + pub fn toggle_fullscreen(self) { + let c = get!(); + c.set_fullscreen(self, !c.get_fullscreen(self)); + } + + pub fn fullscreen(self) -> bool { + get!(false).get_fullscreen(self) + } + + pub fn set_fullscreen(self, fullscreen: bool) { + get!().set_fullscreen(self, fullscreen) + } } pub fn get_seats() -> Vec { diff --git a/src/config/handler.rs b/src/config/handler.rs index 8da75ca5..f6edf1cb 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -143,6 +143,20 @@ impl ConfigProxyHandler { res } + fn handle_get_fullscreen(&self, seat: Seat) -> Result<(), CphError> { + let seat = self.get_seat(seat)?; + self.respond(Response::GetFullscreen { + fullscreen: seat.get_fullscreen(), + }); + Ok(()) + } + + fn handle_set_fullscreen(&self, seat: Seat, fullscreen: bool) -> Result<(), CphError> { + let seat = self.get_seat(seat)?; + seat.set_fullscreen(fullscreen); + Ok(()) + } + fn handle_set_keymap(&self, seat: Seat, keymap: Keymap) -> Result<(), CphError> { let seat = self.get_seat(seat)?; let keymap = if keymap.is_invalid() { @@ -881,6 +895,12 @@ impl ConfigProxyHandler { .handle_program_timer(timer, initial, periodic) .wrn("program_timer")?, ClientMessage::SetEnv { key, val } => self.handle_set_env(key, val), + ClientMessage::SetFullscreen { seat, fullscreen } => self + .handle_set_fullscreen(seat, fullscreen) + .wrn("set_fullscreen")?, + ClientMessage::GetFullscreen { seat } => { + self.handle_get_fullscreen(seat).wrn("get_fullscreen")? + } } Ok(()) } diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 64bcbdc8..3295b1bd 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -201,6 +201,14 @@ impl WlSeatGlobal { .set(Some(self.state.seat_queue.add_last(self.clone()))); } + pub fn set_fullscreen(&self, fullscreen: bool) { + self.keyboard_node.get().node_set_fullscreen(fullscreen); + } + + pub fn get_fullscreen(&self) -> bool { + self.keyboard_node.get().node_fullscreen() + } + pub fn set_keymap(&self, keymap: &Rc) { self.kb_map.set(keymap.clone()); let bindings = self.bindings.borrow_mut(); diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 320a89f5..75d0c83e 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -891,6 +891,16 @@ impl SizedNode for WlSurface { fn is_xwayland_surface(&self) -> bool { self.client.is_xwayland } + + fn set_fullscreen(self: &Rc, fullscreen: bool) { + if let Some(tl) = self.toplevel.get() { + tl.set_fullscreen(fullscreen); + } + } + + fn fullscreen(&self) -> bool { + self.toplevel.get().map(|tl| tl.fullscreen()).unwrap_or(false) + } } #[derive(Debug, Error)] diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index c0de76e6..09869e33 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -17,8 +17,9 @@ use { rect::Rect, render::Renderer, tree::{ - FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, SizedNode, ToplevelData, - ToplevelNode, ToplevelNodeId, WorkspaceNode, + FindTreeResult, FoundNode, FullscreenData, Node, NodeId, NodeVisitor, + SizedFullscreenNode, SizedNode, SizedToplevelNode, ToplevelData, ToplevelNodeId, + WorkspaceNode, }, utils::{ buffd::{MsgParser, MsgParserError}, @@ -38,7 +39,7 @@ use { }, thiserror::Error, }; -use crate::tree::{FullscreenData, SizedFullscreenNode}; +use crate::state::State; #[derive(Copy, Clone, Debug, FromPrimitive)] pub enum ResizeEdge { @@ -74,6 +75,7 @@ pub enum Decoration { pub struct XdgToplevel { pub id: XdgToplevelId, + pub state: Rc, pub xdg: Rc, pub node_id: ToplevelNodeId, pub parent_node: CloneCell>>, @@ -107,6 +109,7 @@ impl XdgToplevel { states.insert(STATE_TILED_BOTTOM); Self { id, + state: surface.surface.client.state.clone(), xdg: surface.clone(), node_id: surface.surface.client.state.node_ids.next(), parent_node: Default::default(), @@ -290,7 +293,10 @@ impl XdgToplevel { Ok(()) } - fn set_fullscreen(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), SetFullscreenError> { + fn set_fullscreen( + self: &Rc, + parser: MsgParser<'_, '_>, + ) -> Result<(), SetFullscreenError> { let client = &self.xdg.surface.client; let req: SetFullscreen = client.parse(self.deref(), parser)?; 'set_fullscreen: { @@ -300,23 +306,26 @@ impl XdgToplevel { _ => { log::error!("Output global has no node attached"); break 'set_fullscreen; - }, + } } } else if let Some(ws) = self.xdg.workspace.get() { ws.output.get() } else { break 'set_fullscreen; }; - client.state.set_fullscreen(self.clone(), &output); + self.fullscreen_data.set_fullscreen(&client.state, self.clone(), &output); } self.send_current_configure(); Ok(()) } - fn unset_fullscreen(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), UnsetFullscreenError> { + fn unset_fullscreen( + self: &Rc, + parser: MsgParser<'_, '_>, + ) -> Result<(), UnsetFullscreenError> { let _req: UnsetFullscreen = self.xdg.surface.client.parse(self.deref(), parser)?; self.states.borrow_mut().remove(&STATE_FULLSCREEN); - self.xdg.surface.client.state.unset_fullscreen(self.clone()); + self.fullscreen_data.unset_fullscreen(&self.state, self.clone()); self.send_current_configure(); Ok(()) } @@ -343,8 +352,7 @@ impl XdgToplevel { fn map_floating(self: &Rc, workspace: &Rc) { let (width, height) = self.toplevel_data.float_size(workspace); - let state = &self.xdg.surface.client.state; - state.map_floating(self.clone(), width, height, workspace); + self.state.map_floating(self.clone(), width, height, workspace); } fn map_child(self: &Rc, parent: &XdgToplevel) { @@ -355,8 +363,7 @@ impl XdgToplevel { } fn map_tiled(self: &Rc) { - let state = &self.xdg.surface.client.state; - state.map_tiled(self.clone()); + self.state.map_tiled(self.clone()); } } @@ -403,10 +410,11 @@ impl SizedNode for XdgToplevel { } fn destroy_node(&self, detach: bool) { + self.fullscreen_data.destroy_node(); if let Some(parent) = self.parent_node.take() { if detach { parent.node_remove_child(self); - self.xdg.surface.client.state.tree_changed(); + self.state.tree_changed(); } } self.toplevel_data.clear(); @@ -455,6 +463,20 @@ impl SizedNode for XdgToplevel { self.xdg.absolute_desired_extents.get() } + fn toggle_floating(self: &Rc, _seat: &Rc) { + let parent = match self.parent_node.get() { + Some(p) => p, + _ => return, + }; + if parent.node_is_float() { + parent.node_remove_child2(self.deref(), true); + self.map_tiled(); + } else if let Some(ws) = self.xdg.workspace.get() { + parent.node_remove_child2(self.deref(), true); + self.map_floating(&ws); + } + } + fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { self.xdg.find_tree_at(x, y, tree) } @@ -500,35 +522,13 @@ impl SizedNode for XdgToplevel { fn client(&self) -> Option> { Some(self.xdg.surface.client.clone()) } - - fn toggle_floating(self: &Rc, _seat: &Rc) { - let parent = match self.parent_node.get() { - Some(p) => p, - _ => return, - }; - if parent.node_is_float() { - parent.node_remove_child2(self.deref(), true); - self.map_tiled(); - } else if let Some(ws) = self.xdg.workspace.get() { - parent.node_remove_child2(self.deref(), true); - self.map_floating(&ws); - } - } } -impl ToplevelNode for XdgToplevel { +impl SizedToplevelNode for XdgToplevel { fn data(&self) -> &ToplevelData { &self.toplevel_data } - fn as_node(&self) -> &dyn Node { - self - } - - fn into_node(self: Rc) -> Rc { - self - } - fn accepts_keyboard_focus(&self) -> bool { true } @@ -558,6 +558,22 @@ impl ToplevelNode for XdgToplevel { fn activate(&self) { // nothing } + + fn set_fullscreen(self: &Rc, fullscreen: bool) { + let state = &self.state; + if fullscreen { + if let Some(ws) = self.xdg.workspace.get() { + self.fullscreen_data.set_fullscreen(state, self.clone(), &ws.output.get()); + } + } else { + self.fullscreen_data.unset_fullscreen(state, self.clone()); + } + self.send_current_configure(); + } + + fn fullscreen(&self) -> bool { + self.fullscreen_data.is_fullscreen.get() + } } impl XdgSurfaceExt for XdgToplevel { @@ -578,7 +594,7 @@ impl XdgSurfaceExt for XdgToplevel { child.parent.set(new_parent.clone()); } } - surface.client.state.tree_changed(); + self.state.tree_changed(); } } else if surface.buffer.get().is_some() { if let Some(parent) = self.parent.get() { @@ -602,23 +618,19 @@ impl XdgSurfaceExt for XdgToplevel { // seat.focus_toplevel(self.clone()); // } // } - surface.client.state.tree_changed(); + self.state.tree_changed(); } } fn extents_changed(&self) { self.notify_parent(); if self.parent_node.get().is_some() { - self.xdg.surface.client.state.tree_changed(); + self.state.tree_changed(); } } } impl SizedFullscreenNode for XdgToplevel { - fn data(&self) -> &FullscreenData { - &self.fullscreen_data - } - fn on_set_fullscreen(&self, _workspace: &Rc) { self.states.borrow_mut().insert(STATE_FULLSCREEN); } diff --git a/src/ifs/wl_surface/xwindow.rs b/src/ifs/wl_surface/xwindow.rs index 5503e03c..7027204c 100644 --- a/src/ifs/wl_surface/xwindow.rs +++ b/src/ifs/wl_surface/xwindow.rs @@ -11,8 +11,8 @@ use { render::Renderer, state::State, tree::{ - FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, SizedNode, ToplevelData, - ToplevelNode, WorkspaceNode, + FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, SizedNode, SizedToplevelNode, + ToplevelData, ToplevelNode, WorkspaceNode, }, utils::{ clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode, @@ -474,19 +474,11 @@ impl SizedNode for Xwindow { } } -impl ToplevelNode for Xwindow { +impl SizedToplevelNode for Xwindow { fn data(&self) -> &ToplevelData { &self.toplevel_data } - fn as_node(&self) -> &dyn Node { - self - } - - fn into_node(self: Rc) -> Rc { - self - } - fn accepts_keyboard_focus(&self) -> bool { self.data.info.never_focus.get().not() && self.data.info.input_model.get() != XInputModel::None @@ -509,6 +501,14 @@ impl ToplevelNode for Xwindow { .queue .push(XWaylandEvent::Activate(self.data.clone())); } + + fn set_fullscreen(self: &Rc, _fullscreen: bool) { + // nothing + } + + fn fullscreen(&self) -> bool { + false + } } #[derive(Debug, Error)] diff --git a/src/state.rs b/src/state.rs index cf24da29..22a85125 100644 --- a/src/state.rs +++ b/src/state.rs @@ -25,13 +25,14 @@ use { render::RenderContext, theme::Theme, tree::{ - ContainerNode, ContainerSplit, DisplayNode, FloatNode, Node, NodeIds, NodeVisitorBase, - OutputNode, SizedNode, WorkspaceNode, + ContainerNode, ContainerSplit, DisplayNode, FloatNode, + Node, NodeIds, NodeVisitorBase, OutputNode, + SizedNode, WorkspaceNode, }, utils::{ asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, fdcloser::FdCloser, linkedlist::LinkedList, numcell::NumCell, - queue::AsyncQueue, + queue::AsyncQueue, run_toplevel::RunToplevel, }, wheel::Wheel, xkbcommon::{XkbContext, XkbKeymap}, @@ -48,9 +49,6 @@ use { time::Duration, }, }; -use crate::ifs::wl_seat::collect_kb_foci; -use crate::tree::{PlaceholderNode, FullscreenNode, FullscreenedData, ToplevelNode}; -use crate::utils::run_toplevel::RunToplevel; pub struct State { pub xkb_ctx: XkbContext, @@ -395,86 +393,4 @@ impl State { } serial as _ } - - pub fn set_fullscreen(self: &Rc, node: Rc, output: &Rc) { - let ws = output.ensure_workspace(); - if ws.fullscreen.get().is_some() { - log::info!("Cannot fullscreen a node on a workspace that already has a fullscreen node attached"); - return; - } - let mut data = node.data().data.borrow_mut(); - if data.is_some() { - log::info!("Cannot fullscreen a node that is already fullscreen"); - return; - } - let parent = match node.as_node().node_parent() { - None => { - log::warn!("Cannot fullscreen a node without a parent"); - return; - } - Some(p) => p, - }; - let placeholder = Rc::new(PlaceholderNode::new_for(self, node.clone())); - parent.node_replace_child(node.as_node(), placeholder.clone()); - let mut kb_foci = Default::default(); - if let Some(container) = ws.container.get() { - kb_foci = collect_kb_foci(container.clone()); - container.set_visible(false); - } - *data = Some(FullscreenedData { - placeholder, - workspace: ws.clone(), - }); - node.data().is_fullscreen.set(true); - ws.fullscreen.set(Some(node.clone())); - node.clone().into_node().node_set_parent(ws.clone()); - node.clone().into_node().node_set_workspace(&ws); - node.clone().into_node().node_change_extents(&output.global.pos.get()); - for seat in kb_foci { - node.clone().into_node().node_do_focus(&seat, Direction::Unspecified); - } - node.on_set_fullscreen(&ws); - } - - pub fn unset_fullscreen(self: &Rc, node: Rc) { - if !node.data().is_fullscreen.get() { - log::warn!("Cannot unset fullscreen on a node that is not fullscreen"); - } - let fd = match node.data().data.borrow_mut().take() { - Some(fd) => fd, - _ => { - log::error!("is_fullscreen = true but data is None"); - return; - } - }; - match fd.workspace.fullscreen.get() { - None => { - log::error!("Node is supposed to be fullscreened on a workspace but workspace has not fullscreen node."); - return; - } - Some(f) if f.as_node().node_id() != node.as_node().node_id() => { - log::error!("Node is supposed to be fullscreened on a workspace but the workspace has a different node attached."); - return; - } - _ => { }, - } - fd.workspace.fullscreen.take(); - if let Some(container) = fd.workspace.container.get() { - container.set_visible(true); - } - if fd.placeholder.is_destroyed() { - self.map_tiled(node.into_node()); - return; - } - let parent = fd.placeholder.parent().unwrap(); - parent.node_replace_child(fd.placeholder.deref(), node.clone().into_node()); - if node.as_node().node_visible() { - let kb_foci = collect_kb_foci(fd.placeholder.clone()); - for seat in kb_foci { - node.clone().into_node().node_do_focus(&seat, Direction::Unspecified); - } - } - fd.placeholder.as_node().node_seat_state().destroy_node(fd.placeholder.as_node()); - node.on_unset_fullscreen(); - } } diff --git a/src/tree.rs b/src/tree.rs index 135bb703..fa8189b4 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -18,17 +18,20 @@ use { rc::Rc, }, }; -pub use {container::*, display::*, float::*, output::*, toplevel::*, walker::*, workspace::*, fullscreen::*, placeholder::*}; +pub use { + container::*, display::*, float::*, fullscreen::*, output::*, placeholder::*, toplevel::*, + walker::*, workspace::*, +}; mod container; mod display; mod float; +mod fullscreen; mod output; +mod placeholder; mod toplevel; mod walker; mod workspace; -mod fullscreen; -mod placeholder; pub struct NodeIds { next: NumCell, @@ -370,6 +373,14 @@ pub trait SizedNode: Sized + 'static { fn is_xwayland_surface(&self) -> bool { false } + + fn fullscreen(&self) -> bool { + false + } + + fn set_fullscreen(self: &Rc, fullscreen: bool) { + let _ = fullscreen; + } } pub trait Node { @@ -455,6 +466,8 @@ pub trait Node { fn node_dnd_leave(&self, dnd: &Dnd); fn node_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32); fn node_dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed); + fn node_set_fullscreen(self: Rc, fullscreen: bool); + fn node_fullscreen(&self) -> bool; } impl Node for T { @@ -683,6 +696,12 @@ impl Node for T { fn node_dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) { ::dnd_motion(self, dnd, x, y) } + fn node_set_fullscreen(self: Rc, fullscreen: bool) { + ::set_fullscreen(&self, fullscreen) + } + fn node_fullscreen(&self) -> bool { + ::fullscreen(self) + } } pub struct FoundNode { diff --git a/src/tree/container.rs b/src/tree/container.rs index 72683051..3076e30e 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -983,7 +983,9 @@ impl SizedNode for ContainerNode { } let (split, prev) = direction_to_split(direction); // CASE 2: We're moving the child within the container. - if split == self.split.get() || (split == ContainerSplit::Horizontal && self.mono_child.get().is_some()) { + if split == self.split.get() + || (split == ContainerSplit::Horizontal && self.mono_child.get().is_some()) + { let cc = match self.child_nodes.borrow_mut().get(&child.node_id()) { Some(l) => l.to_ref(), None => return, @@ -1192,8 +1194,8 @@ impl SizedNode for ContainerNode { Some(c) => c, None => { log::error!("Trying to replace a node that isn't a child of this container"); - return - }, + return; + } }; let (have_mc, was_mc) = match self.mono_child.get() { None => (false, false), @@ -1408,6 +1410,14 @@ impl SizedNode for ContainerNode { .clone() .node_child_title_changed(self.deref(), self.title.borrow_mut().deref()); } + + fn set_fullscreen(self: &Rc, _fullscreen: bool) { + // todo + } + + fn fullscreen(&self) -> bool { + false + } } fn direction_to_split(dir: Direction) -> (ContainerSplit, bool) { diff --git a/src/tree/display.rs b/src/tree/display.rs index 0ad87ed2..4d1e07ca 100644 --- a/src/tree/display.rs +++ b/src/tree/display.rs @@ -2,9 +2,7 @@ use { crate::{ backend::ConnectorId, cursor::KnownCursor, - ifs::{ - wl_seat::{NodeSeatState, WlSeatGlobal}, - }, + ifs::wl_seat::{NodeSeatState, WlSeatGlobal}, rect::Rect, render::Renderer, tree::{ diff --git a/src/tree/fullscreen.rs b/src/tree/fullscreen.rs index bfe99e4c..51f77cdb 100644 --- a/src/tree/fullscreen.rs +++ b/src/tree/fullscreen.rs @@ -1,10 +1,17 @@ -use std::cell::{Cell, RefCell}; -use std::ops::Deref; -use std::rc::Rc; -use crate::tree::{PlaceholderNode, Node, WorkspaceNode, SizedNode}; +use { + crate::tree::{Node, PlaceholderNode, SizedNode, WorkspaceNode}, + std::{ + cell::{Cell, RefCell}, + ops::Deref, + rc::Rc, + }, +}; +use jay_config::Direction; +use crate::ifs::wl_seat::collect_kb_foci; +use crate::state::State; +use crate::tree::OutputNode; pub trait SizedFullscreenNode: SizedNode { - fn data(&self) -> &FullscreenData; fn on_set_fullscreen(&self, workspace: &Rc); fn on_unset_fullscreen(&self); fn title(&self) -> String; @@ -19,7 +26,6 @@ pub trait SizedFullscreenNode: SizedNode { } pub trait FullscreenNode { - fn data(&self) -> &FullscreenData; fn on_set_fullscreen(&self, workspace: &Rc); fn on_unset_fullscreen(&self); fn as_node(&self) -> &dyn Node; @@ -28,10 +34,6 @@ pub trait FullscreenNode { } impl FullscreenNode for T { - fn data(&self) -> &FullscreenData { - ::data(self) - } - fn on_set_fullscreen(&self, workspace: &Rc) { ::on_set_fullscreen(self, workspace) } @@ -72,3 +74,103 @@ impl FullscreenData { } } } + +impl FullscreenData { + pub fn set_fullscreen(&self, state: &Rc, node: Rc, output: &Rc) { + let ws = output.ensure_workspace(); + if ws.fullscreen.get().is_some() { + log::info!("Cannot fullscreen a node on a workspace that already has a fullscreen node attached"); + return; + } + let mut data = self.data.borrow_mut(); + if data.is_some() { + log::info!("Cannot fullscreen a node that is already fullscreen"); + return; + } + let parent = match node.as_node().node_parent() { + None => { + log::warn!("Cannot fullscreen a node without a parent"); + return; + } + Some(p) => p, + }; + let placeholder = Rc::new(PlaceholderNode::new_for(state, node.clone())); + parent.node_replace_child(node.as_node(), placeholder.clone()); + let mut kb_foci = Default::default(); + if let Some(container) = ws.container.get() { + kb_foci = collect_kb_foci(container.clone()); + container.set_visible(false); + } + *data = Some(FullscreenedData { + placeholder, + workspace: ws.clone(), + }); + self.is_fullscreen.set(true); + ws.fullscreen.set(Some(node.clone())); + node.clone().into_node().node_set_parent(ws.clone()); + node.clone().into_node().node_set_workspace(&ws); + node.clone() + .into_node() + .node_change_extents(&output.global.pos.get()); + for seat in kb_foci { + node.clone() + .into_node() + .node_do_focus(&seat, Direction::Unspecified); + } + node.on_set_fullscreen(&ws); + } + + pub fn unset_fullscreen(&self, state: &Rc, node: Rc) { + if !self.is_fullscreen.get() { + log::warn!("Cannot unset fullscreen on a node that is not fullscreen"); + return; + } + let fd = match self.data.borrow_mut().take() { + Some(fd) => fd, + _ => { + log::error!("is_fullscreen = true but data is None"); + return; + } + }; + self.is_fullscreen.set(false); + match fd.workspace.fullscreen.get() { + None => { + log::error!("Node is supposed to be fullscreened on a workspace but workspace has not fullscreen node."); + return; + } + Some(f) if f.as_node().node_id() != node.as_node().node_id() => { + log::error!("Node is supposed to be fullscreened on a workspace but the workspace has a different node attached."); + return; + } + _ => {} + } + fd.workspace.fullscreen.take(); + if let Some(container) = fd.workspace.container.get() { + container.set_visible(true); + } + if fd.placeholder.is_destroyed() { + state.map_tiled(node.into_node()); + return; + } + let parent = fd.placeholder.parent().unwrap(); + parent.node_replace_child(fd.placeholder.deref(), node.clone().into_node()); + if node.as_node().node_visible() { + let kb_foci = collect_kb_foci(fd.placeholder.clone()); + for seat in kb_foci { + node.clone() + .into_node() + .node_do_focus(&seat, Direction::Unspecified); + } + } + fd.placeholder + .node_seat_state() + .destroy_node(fd.placeholder.deref()); + node.on_unset_fullscreen(); + } + + pub fn destroy_node(&self) { + if let Some(fd) = self.data.borrow_mut().take() { + fd.placeholder.destroy_node(true); + } + } +} diff --git a/src/tree/output.rs b/src/tree/output.rs index 9b871379..feb6e13d 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -6,7 +6,7 @@ use { wl_output::WlOutputGlobal, wl_seat::{collect_kb_foci2, NodeSeatState, WlSeatGlobal}, wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, - zwlr_layer_shell_v1::{BACKGROUND, BOTTOM}, + zwlr_layer_shell_v1::{BACKGROUND, BOTTOM, OVERLAY, TOP}, }, rect::Rect, render::{Renderer, Texture}, @@ -27,7 +27,6 @@ use { rc::Rc, }, }; -use crate::ifs::zwlr_layer_shell_v1::{OVERLAY, TOP}; tree_id!(OutputNodeId); pub struct OutputNode { @@ -348,7 +347,8 @@ impl SizedNode for OutputNode { { for stacked in self.state.root.stacked.rev_iter() { let ext = stacked.node_absolute_position(); - if stacked.node_absolute_position_constrains_input() && !ext.contains(x_abs, y_abs) { + if stacked.node_absolute_position_constrains_input() && !ext.contains(x_abs, y_abs) + { // TODO: make constrain always true continue; } diff --git a/src/tree/placeholder.rs b/src/tree/placeholder.rs index b30fc001..dad47fd4 100644 --- a/src/tree/placeholder.rs +++ b/src/tree/placeholder.rs @@ -1,16 +1,27 @@ -use std::cell::{Cell, RefCell}; -use std::ops::Deref; -use std::rc::Rc; -use jay_config::Direction; -use crate::client::{Client}; -use crate::cursor::KnownCursor; -use crate::fixed::Fixed; -use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal}; -use crate::ifs::wl_surface::WlSurface; -use crate::rect::Rect; -use crate::state::State; -use crate::tree::{FindTreeResult, FoundNode, FullscreenNode, Node, NodeId, NodeVisitor, SizedNode, ToplevelData, ToplevelNode, WorkspaceNode}; -use crate::utils::clonecell::CloneCell; +use { + crate::{ + client::Client, + cursor::KnownCursor, + fixed::Fixed, + ifs::{ + wl_seat::{NodeSeatState, WlSeatGlobal}, + wl_surface::WlSurface, + }, + rect::Rect, + state::State, + tree::{ + FindTreeResult, FoundNode, FullscreenNode, Node, NodeId, NodeVisitor, SizedNode, + SizedToplevelNode, ToplevelData, WorkspaceNode, + }, + utils::clonecell::CloneCell, + }, + jay_config::Direction, + std::{ + cell::{Cell, RefCell}, + ops::Deref, + rc::Rc, + }, +}; tree_id!(DetachedNodeId); pub struct PlaceholderNode { @@ -152,19 +163,11 @@ impl SizedNode for PlaceholderNode { } } -impl ToplevelNode for PlaceholderNode { +impl SizedToplevelNode for PlaceholderNode { fn data(&self) -> &ToplevelData { &self.toplevel } - fn as_node(&self) -> &dyn Node { - self - } - - fn into_node(self: Rc) -> Rc { - self - } - fn accepts_keyboard_focus(&self) -> bool { true } @@ -180,4 +183,12 @@ impl ToplevelNode for PlaceholderNode { fn activate(&self) { // nothing } + + fn set_fullscreen(self: &Rc, _fullscreen: bool) { + // nothing + } + + fn fullscreen(&self) -> bool { + false + } } diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index 8abbcfbe..7eaaedbe 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -1,12 +1,30 @@ use { crate::{ ifs::{wl_seat::SeatId, wl_surface::WlSurface}, - tree::{Node, WorkspaceNode}, + tree::{Node, SizedNode, WorkspaceNode}, utils::{numcell::NumCell, smallmap::SmallMap}, }, std::{cell::Cell, rc::Rc}, }; +pub trait SizedToplevelNode: SizedNode { + fn data(&self) -> &ToplevelData; + fn accepts_keyboard_focus(&self) -> bool; + fn default_surface(&self) -> Option>; + fn set_active(&self, active: bool); + fn activate(&self); + fn set_fullscreen(self: &Rc, fullscreen: bool); + fn fullscreen(&self) -> bool; + + fn as_node(&self) -> &dyn Node { + self + } + + fn into_node(self: Rc) -> Rc { + self + } +} + tree_id!(ToplevelNodeId); pub trait ToplevelNode { fn data(&self) -> &ToplevelData; @@ -16,6 +34,46 @@ pub trait ToplevelNode { fn default_surface(&self) -> Option>; fn set_active(&self, active: bool); fn activate(&self); + fn set_fullscreen(self: Rc, fullscreen: bool); + fn fullscreen(&self) -> bool; +} + +impl ToplevelNode for T { + fn data(&self) -> &ToplevelData { + ::data(self) + } + + fn as_node(&self) -> &dyn Node { + ::as_node(self) + } + + fn into_node(self: Rc) -> Rc { + ::into_node(self) + } + + fn accepts_keyboard_focus(&self) -> bool { + ::accepts_keyboard_focus(self) + } + + fn default_surface(&self) -> Option> { + ::default_surface(self) + } + + fn set_active(&self, active: bool) { + ::set_active(self, active) + } + + fn activate(&self) { + ::activate(self) + } + + fn set_fullscreen(self: Rc, fullscreen: bool) { + ::set_fullscreen(&self, fullscreen) + } + + fn fullscreen(&self) -> bool { + ::fullscreen(self) + } } #[derive(Default)] diff --git a/src/tree/walker.rs b/src/tree/walker.rs index 042a2de1..40be895b 100644 --- a/src/tree/walker.rs +++ b/src/tree/walker.rs @@ -6,11 +6,12 @@ use { zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, WlSurface, }, - tree::{ContainerNode, DisplayNode, FloatNode, Node, OutputNode, WorkspaceNode}, + tree::{ + ContainerNode, DisplayNode, FloatNode, Node, OutputNode, PlaceholderNode, WorkspaceNode, + }, }, std::rc::Rc, }; -use crate::tree::PlaceholderNode; pub trait NodeVisitorBase: Sized { fn visit_surface(&mut self, node: &Rc) { diff --git a/src/tree/workspace.rs b/src/tree/workspace.rs index 1bcd0364..864657fa 100644 --- a/src/tree/workspace.rs +++ b/src/tree/workspace.rs @@ -5,8 +5,8 @@ use { rect::Rect, render::Renderer, tree::{ - container::ContainerNode, walker::NodeVisitor, FindTreeResult, FoundNode, Node, NodeId, - OutputNode, SizedNode, + container::ContainerNode, walker::NodeVisitor, FindTreeResult, FoundNode, + FullscreenNode, Node, NodeId, OutputNode, SizedNode, }, utils::{ clonecell::CloneCell, @@ -16,7 +16,6 @@ use { jay_config::Direction, std::{cell::Cell, fmt::Debug, rc::Rc}, }; -use crate::tree::FullscreenNode; tree_id!(WorkspaceNodeId);