Merge pull request #524 from mahkoh/jorth/focus-layer
Add focus-below, focus-above, and focus-tiles actions
This commit is contained in:
commit
e70be28e22
31 changed files with 633 additions and 59 deletions
|
|
@ -15,7 +15,7 @@ use {
|
||||||
client::{Client, ClientCriterion, ClientMatcher, MatchedClient},
|
client::{Client, ClientCriterion, ClientMatcher, MatchedClient},
|
||||||
exec::Command,
|
exec::Command,
|
||||||
input::{
|
input::{
|
||||||
FocusFollowsMouseMode, InputDevice, Seat, SwitchEvent, Timeline,
|
FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, SwitchEvent, Timeline,
|
||||||
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
|
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
|
||||||
},
|
},
|
||||||
keyboard::{
|
keyboard::{
|
||||||
|
|
@ -379,6 +379,14 @@ impl ConfigClient {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn seat_focus_layer_rel(&self, seat: Seat, direction: LayerDirection) {
|
||||||
|
self.send(&ClientMessage::SeatFocusLayerRel { seat, direction });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn seat_focus_tiles(&self, seat: Seat) {
|
||||||
|
self.send(&ClientMessage::SeatFocusTiles { seat });
|
||||||
|
}
|
||||||
|
|
||||||
pub fn seat_focus(&self, seat: Seat, direction: Direction) {
|
pub fn seat_focus(&self, seat: Seat, direction: Direction) {
|
||||||
self.send(&ClientMessage::SeatFocus { seat, direction });
|
self.send(&ClientMessage::SeatFocus { seat, direction });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use {
|
||||||
Axis, Direction, PciId, Workspace,
|
Axis, Direction, PciId, Workspace,
|
||||||
client::{Client, ClientMatcher},
|
client::{Client, ClientMatcher},
|
||||||
input::{
|
input::{
|
||||||
FocusFollowsMouseMode, InputDevice, Seat, SwitchEvent, Timeline,
|
FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, SwitchEvent, Timeline,
|
||||||
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
|
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
|
||||||
},
|
},
|
||||||
keyboard::{Keymap, mods::Modifiers, syms::KeySym},
|
keyboard::{Keymap, mods::Modifiers, syms::KeySym},
|
||||||
|
|
@ -737,6 +737,13 @@ pub enum ClientMessage<'a> {
|
||||||
seat: Seat,
|
seat: Seat,
|
||||||
same_workspace: bool,
|
same_workspace: bool,
|
||||||
},
|
},
|
||||||
|
SeatFocusLayerRel {
|
||||||
|
seat: Seat,
|
||||||
|
direction: LayerDirection,
|
||||||
|
},
|
||||||
|
SeatFocusTiles {
|
||||||
|
seat: Seat,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,13 @@ pub enum Timeline {
|
||||||
Newer,
|
Newer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A direction for layer traversal.
|
||||||
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
|
pub enum LayerDirection {
|
||||||
|
Below,
|
||||||
|
Above,
|
||||||
|
}
|
||||||
|
|
||||||
/// A seat.
|
/// A seat.
|
||||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
pub struct Seat(pub u64);
|
pub struct Seat(pub u64);
|
||||||
|
|
@ -303,6 +310,17 @@ impl Seat {
|
||||||
get!().seat_focus_history_set_same_workspace(self, same_workspace)
|
get!().seat_focus_history_set_same_workspace(self, same_workspace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Moves the keyboard focus of the seat to the layer above or below the current
|
||||||
|
/// layer.
|
||||||
|
pub fn focus_layer_rel(self, direction: LayerDirection) {
|
||||||
|
get!().seat_focus_layer_rel(self, direction)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Moves the keyboard focus to the tile layer.
|
||||||
|
pub fn focus_tiles(self) {
|
||||||
|
get!().seat_focus_tiles(self)
|
||||||
|
}
|
||||||
|
|
||||||
/// Moves the keyboard focus of the seat in the specified direction.
|
/// Moves the keyboard focus of the seat in the specified direction.
|
||||||
pub fn focus(self, direction: Direction) {
|
pub fn focus(self, direction: Direction) {
|
||||||
get!().seat_focus(self, direction)
|
get!().seat_focus(self, direction)
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ use {
|
||||||
Axis, Direction, Workspace,
|
Axis, Direction, Workspace,
|
||||||
client::{Client as ConfigClient, ClientMatcher},
|
client::{Client as ConfigClient, ClientMatcher},
|
||||||
input::{
|
input::{
|
||||||
FocusFollowsMouseMode, InputDevice, Seat, Timeline,
|
FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, Timeline,
|
||||||
acceleration::{ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT, AccelProfile},
|
acceleration::{ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT, AccelProfile},
|
||||||
capability::{
|
capability::{
|
||||||
CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD,
|
CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD,
|
||||||
|
|
@ -2185,6 +2185,25 @@ impl ConfigProxyHandler {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_seat_focus_layer_rel(
|
||||||
|
&self,
|
||||||
|
seat: Seat,
|
||||||
|
direction: LayerDirection,
|
||||||
|
) -> Result<(), CphError> {
|
||||||
|
let seat = self.get_seat(seat)?;
|
||||||
|
match direction {
|
||||||
|
LayerDirection::Below => seat.focus_layer_below(),
|
||||||
|
LayerDirection::Above => seat.focus_layer_above(),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_seat_focus_tiles(&self, seat: Seat) -> Result<(), CphError> {
|
||||||
|
let seat = self.get_seat(seat)?;
|
||||||
|
seat.focus_tiles();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn spaces_change(&self) {
|
fn spaces_change(&self) {
|
||||||
struct V;
|
struct V;
|
||||||
impl NodeVisitorBase for V {
|
impl NodeVisitorBase for V {
|
||||||
|
|
@ -3039,6 +3058,12 @@ impl ConfigProxyHandler {
|
||||||
} => self
|
} => self
|
||||||
.handle_seat_focus_history_set_same_workspace(seat, same_workspace)
|
.handle_seat_focus_history_set_same_workspace(seat, same_workspace)
|
||||||
.wrn("seat_focus_history_set_same_workspace")?,
|
.wrn("seat_focus_history_set_same_workspace")?,
|
||||||
|
ClientMessage::SeatFocusLayerRel { seat, direction } => self
|
||||||
|
.handle_seat_focus_layer_rel(seat, direction)
|
||||||
|
.wrn("seat_focus_layer_rel")?,
|
||||||
|
ClientMessage::SeatFocusTiles { seat } => {
|
||||||
|
self.handle_seat_focus_tiles(seat).wrn("seat_focus_tiles")?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ use {
|
||||||
dnd_icon::DndIcon,
|
dnd_icon::DndIcon,
|
||||||
tray::{DynTrayItem, TrayItemId},
|
tray::{DynTrayItem, TrayItemId},
|
||||||
xdg_surface::xdg_popup::XdgPopup,
|
xdg_surface::xdg_popup::XdgPopup,
|
||||||
|
zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
||||||
},
|
},
|
||||||
xdg_toplevel_drag_v1::XdgToplevelDragV1,
|
xdg_toplevel_drag_v1::XdgToplevelDragV1,
|
||||||
},
|
},
|
||||||
|
|
@ -80,9 +81,10 @@ use {
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
state::{DeviceHandlerData, State},
|
state::{DeviceHandlerData, State},
|
||||||
tree::{
|
tree::{
|
||||||
ContainerNode, ContainerSplit, Direction, FoundNode, Node, NodeId, NodeLocation,
|
ContainerNode, ContainerSplit, Direction, FoundNode, Node, NodeId, NodeLayer,
|
||||||
OutputNode, ToplevelNode, WorkspaceNode, generic_node_visitor, toplevel_create_split,
|
NodeLayerLink, NodeLocation, OutputNode, StackedNode, ToplevelNode, WorkspaceNode,
|
||||||
toplevel_parent_container, toplevel_set_floating, toplevel_set_workspace,
|
generic_node_visitor, toplevel_create_split, toplevel_parent_container,
|
||||||
|
toplevel_set_floating, toplevel_set_workspace,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
asyncevent::AsyncEvent,
|
asyncevent::AsyncEvent,
|
||||||
|
|
@ -801,6 +803,165 @@ impl WlSeatGlobal {
|
||||||
self.focus_history_same_workspace.set(same_workspace);
|
self.focus_history_same_workspace.set(same_workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn focus_layer_rel<LI, SI>(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
next_layer: impl Fn(NodeLayer) -> NodeLayer,
|
||||||
|
layer_node_next: impl Fn(
|
||||||
|
&NodeRef<Rc<ZwlrLayerSurfaceV1>>,
|
||||||
|
) -> Option<NodeRef<Rc<ZwlrLayerSurfaceV1>>>,
|
||||||
|
stacked_node_next: impl Fn(
|
||||||
|
&NodeRef<Rc<dyn StackedNode>>,
|
||||||
|
) -> Option<NodeRef<Rc<dyn StackedNode>>>,
|
||||||
|
layer_list_iter: impl Fn(&LinkedList<Rc<ZwlrLayerSurfaceV1>>) -> LI,
|
||||||
|
stacked_list_iter: impl Fn(&LinkedList<Rc<dyn StackedNode>>) -> SI,
|
||||||
|
) where
|
||||||
|
LI: Iterator<Item = NodeRef<Rc<ZwlrLayerSurfaceV1>>>,
|
||||||
|
SI: Iterator<Item = NodeRef<Rc<dyn StackedNode>>>,
|
||||||
|
{
|
||||||
|
fn node_viable(n: &(impl Node + ?Sized)) -> bool {
|
||||||
|
n.node_visible() && n.node_accepts_focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
let current = self.keyboard_node.get();
|
||||||
|
let Some(output) = current.node_output() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let current_layer = current.node_layer();
|
||||||
|
match ¤t_layer {
|
||||||
|
NodeLayerLink::Layer0(l)
|
||||||
|
| NodeLayerLink::Layer1(l)
|
||||||
|
| NodeLayerLink::Layer2(l)
|
||||||
|
| NodeLayerLink::Layer3(l) => {
|
||||||
|
if let Some(n) = layer_node_next(l)
|
||||||
|
&& node_viable(&**n)
|
||||||
|
{
|
||||||
|
n.deref()
|
||||||
|
.clone()
|
||||||
|
.node_do_focus(self, Direction::Unspecified);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NodeLayerLink::Stacked(l) | NodeLayerLink::StackedAboveLayers(l) => {
|
||||||
|
if let Some(n) = stacked_node_next(l)
|
||||||
|
&& node_viable(&**n)
|
||||||
|
&& n.node_output().map(|o| o.id) == Some(output.id)
|
||||||
|
{
|
||||||
|
n.deref()
|
||||||
|
.clone()
|
||||||
|
.node_do_focus(self, Direction::Unspecified);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NodeLayerLink::Display => {}
|
||||||
|
NodeLayerLink::Output => {}
|
||||||
|
NodeLayerLink::Workspace => {}
|
||||||
|
NodeLayerLink::Tiled => {}
|
||||||
|
NodeLayerLink::Fullscreen => {}
|
||||||
|
NodeLayerLink::Lock => {}
|
||||||
|
NodeLayerLink::InputMethod => {}
|
||||||
|
}
|
||||||
|
let handle_layer_shell = |l: &LinkedList<Rc<ZwlrLayerSurfaceV1>>| {
|
||||||
|
for n in layer_list_iter(l) {
|
||||||
|
if node_viable(&**n) {
|
||||||
|
return Some(n.deref().clone() as Rc<dyn Node>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let handle_stacked = |l: &LinkedList<Rc<dyn StackedNode>>| {
|
||||||
|
for n in stacked_list_iter(l) {
|
||||||
|
if node_viable(&**n) && n.node_output().map(|o| o.id) == Some(output.id) {
|
||||||
|
return Some(n.deref().clone() as Rc<dyn Node>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let ws = output.workspace.get();
|
||||||
|
let first = next_layer(current_layer.layer());
|
||||||
|
let mut layer = first;
|
||||||
|
loop {
|
||||||
|
let node = match layer {
|
||||||
|
NodeLayer::Display => None,
|
||||||
|
NodeLayer::Layer0 => handle_layer_shell(&output.layers[0]),
|
||||||
|
NodeLayer::Layer1 => handle_layer_shell(&output.layers[1]),
|
||||||
|
NodeLayer::Output => None,
|
||||||
|
NodeLayer::Workspace => None,
|
||||||
|
NodeLayer::Tiled => ws
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|w| w.container.get())
|
||||||
|
.map(|n| n as Rc<dyn Node>),
|
||||||
|
NodeLayer::Fullscreen => ws
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|w| w.fullscreen.get())
|
||||||
|
.map(|n| n as Rc<dyn Node>),
|
||||||
|
NodeLayer::Stacked => handle_stacked(&self.state.root.stacked),
|
||||||
|
NodeLayer::Layer2 => handle_layer_shell(&output.layers[2]),
|
||||||
|
NodeLayer::Layer3 => handle_layer_shell(&output.layers[3]),
|
||||||
|
NodeLayer::StackedAboveLayers => {
|
||||||
|
handle_stacked(&self.state.root.stacked_above_layers)
|
||||||
|
}
|
||||||
|
NodeLayer::Lock => None,
|
||||||
|
NodeLayer::InputMethod => None,
|
||||||
|
};
|
||||||
|
if let Some(n) = node {
|
||||||
|
if node_viable(&*n) {
|
||||||
|
n.node_do_focus(self, Direction::Unspecified);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layer = next_layer(layer);
|
||||||
|
if layer == first {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn focus_layer_below(self: &Rc<Self>) {
|
||||||
|
self.focus_layer_rel(
|
||||||
|
|l| l.prev(),
|
||||||
|
|n| n.prev(),
|
||||||
|
|n| n.prev(),
|
||||||
|
|l| l.rev_iter(),
|
||||||
|
|l| l.rev_iter(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn focus_layer_above(self: &Rc<Self>) {
|
||||||
|
self.focus_layer_rel(
|
||||||
|
|l| l.next(),
|
||||||
|
|n| n.next(),
|
||||||
|
|n| n.next(),
|
||||||
|
|l| l.iter(),
|
||||||
|
|l| l.iter(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn focus_tiles(self: &Rc<Self>) {
|
||||||
|
let current = self.keyboard_node.get();
|
||||||
|
if matches!(
|
||||||
|
current.node_layer().layer(),
|
||||||
|
NodeLayer::Tiled | NodeLayer::Fullscreen,
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Some(output) = current.node_output() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(ws) = output.workspace.get() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let node = match ws.fullscreen.get() {
|
||||||
|
Some(fs) => fs as Rc<dyn Node>,
|
||||||
|
_ => match ws.container.get() {
|
||||||
|
Some(c) => c,
|
||||||
|
_ => return,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if node.node_visible() && node.node_accepts_focus() {
|
||||||
|
node.node_do_focus(self, Direction::Unspecified);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_selection_<T, X, S>(
|
fn set_selection_<T, X, S>(
|
||||||
self: &Rc<Self>,
|
self: &Rc<Self>,
|
||||||
field: &CloneCell<Option<Rc<dyn DynDataSource>>>,
|
field: &CloneCell<Option<Rc<dyn DynDataSource>>>,
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,8 @@ use {
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
tree::{
|
tree::{
|
||||||
BeforeLatchListener, BeforeLatchResult, ContainerNode, FindTreeResult, FoundNode,
|
BeforeLatchListener, BeforeLatchResult, ContainerNode, FindTreeResult, FoundNode,
|
||||||
LatchListener, Node, NodeId, NodeLocation, NodeVisitor, NodeVisitorBase, OutputNode,
|
LatchListener, Node, NodeId, NodeLayerLink, NodeLocation, NodeVisitor, NodeVisitorBase,
|
||||||
PlaceholderNode, PresentationListener, ToplevelNode, VblankListener,
|
OutputNode, PlaceholderNode, PresentationListener, ToplevelNode, VblankListener,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap,
|
cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap,
|
||||||
|
|
@ -372,6 +372,8 @@ enum CommitAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SurfaceExt {
|
trait SurfaceExt {
|
||||||
|
fn node_layer(&self) -> NodeLayerLink;
|
||||||
|
|
||||||
fn commit_requested(self: Rc<Self>, pending: &mut Box<PendingState>) -> CommitAction {
|
fn commit_requested(self: Rc<Self>, pending: &mut Box<PendingState>) -> CommitAction {
|
||||||
let _ = pending;
|
let _ = pending;
|
||||||
CommitAction::ContinueCommit
|
CommitAction::ContinueCommit
|
||||||
|
|
@ -444,6 +446,10 @@ trait SurfaceExt {
|
||||||
pub struct NoneSurfaceExt;
|
pub struct NoneSurfaceExt;
|
||||||
|
|
||||||
impl SurfaceExt for NoneSurfaceExt {
|
impl SurfaceExt for NoneSurfaceExt {
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
NodeLayerLink::Display
|
||||||
|
}
|
||||||
|
|
||||||
fn is_some(&self) -> bool {
|
fn is_some(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
@ -1796,6 +1802,10 @@ impl Node for WlSurface {
|
||||||
Some(self.location.get())
|
Some(self.location.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
self.ext.get().node_layer()
|
||||||
|
}
|
||||||
|
|
||||||
fn node_active_changed(&self, active: bool) {
|
fn node_active_changed(&self, active: bool) {
|
||||||
if let Some(tl) = self.toplevel.get() {
|
if let Some(tl) = self.toplevel.get() {
|
||||||
tl.tl_surface_active_changed(active);
|
tl.tl_surface_active_changed(active);
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ use {
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
tree::{
|
tree::{
|
||||||
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, NodeVisitor,
|
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation,
|
||||||
OutputNode,
|
NodeVisitor, OutputNode,
|
||||||
},
|
},
|
||||||
utils::numcell::NumCell,
|
utils::numcell::NumCell,
|
||||||
wire::{ExtSessionLockSurfaceV1Id, WlSurfaceId, ext_session_lock_surface_v1::*},
|
wire::{ExtSessionLockSurfaceV1Id, WlSurfaceId, ext_session_lock_surface_v1::*},
|
||||||
|
|
@ -95,6 +95,10 @@ impl ExtSessionLockSurfaceV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SurfaceExt for ExtSessionLockSurfaceV1 {
|
impl SurfaceExt for ExtSessionLockSurfaceV1 {
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
NodeLayerLink::Lock
|
||||||
|
}
|
||||||
|
|
||||||
fn extents_changed(&self) {
|
fn extents_changed(&self) {
|
||||||
self.client.state.tree_changed();
|
self.client.state.tree_changed();
|
||||||
}
|
}
|
||||||
|
|
@ -138,6 +142,10 @@ impl Node for ExtSessionLockSurfaceV1 {
|
||||||
self.surface.node_location()
|
self.surface.node_location()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
NodeLayerLink::Lock
|
||||||
|
}
|
||||||
|
|
||||||
fn node_find_tree_at(
|
fn node_find_tree_at(
|
||||||
&self,
|
&self,
|
||||||
x: i32,
|
x: i32,
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ use {
|
||||||
},
|
},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
tree::{
|
tree::{
|
||||||
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, NodeVisitor,
|
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation,
|
||||||
OutputNode, StackedNode,
|
NodeVisitor, OutputNode, StackedNode,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
copyhashmap::CopyHashMap,
|
copyhashmap::CopyHashMap,
|
||||||
|
|
@ -216,6 +216,13 @@ impl<T: TrayItem> XdgPopupParent for Popup<T> {
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
let Some(link) = self.stack_link.borrow().as_ref().map(|w| w.to_ref()) else {
|
||||||
|
return NodeLayerLink::Display;
|
||||||
|
};
|
||||||
|
NodeLayerLink::Stacked(link)
|
||||||
|
}
|
||||||
|
|
||||||
fn tray_item(&self) -> Option<TrayItemId> {
|
fn tray_item(&self) -> Option<TrayItemId> {
|
||||||
Some(self.parent.data().tray_item_id)
|
Some(self.parent.data().tray_item_id)
|
||||||
}
|
}
|
||||||
|
|
@ -230,6 +237,10 @@ impl<T: TrayItem> XdgPopupParent for Popup<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: TrayItem> SurfaceExt for T {
|
impl<T: TrayItem> SurfaceExt for T {
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
NodeLayerLink::Output
|
||||||
|
}
|
||||||
|
|
||||||
fn before_apply_commit(
|
fn before_apply_commit(
|
||||||
self: Rc<Self>,
|
self: Rc<Self>,
|
||||||
pending: &mut PendingState,
|
pending: &mut PendingState,
|
||||||
|
|
@ -308,6 +319,10 @@ impl<T: TrayItem> Node for T {
|
||||||
self.data().surface.node_location()
|
self.data().surface.node_location()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
NodeLayerLink::Output
|
||||||
|
}
|
||||||
|
|
||||||
fn node_find_tree_at(
|
fn node_find_tree_at(
|
||||||
&self,
|
&self,
|
||||||
x: i32,
|
x: i32,
|
||||||
|
|
@ -384,7 +399,7 @@ fn get_popup<T: TrayItem>(
|
||||||
};
|
};
|
||||||
seat.add_tray_item_popup(item, &popup);
|
seat.add_tray_item_popup(item, &popup);
|
||||||
let stack = data.client.state.root.stacked.clone();
|
let stack = data.client.state.root.stacked.clone();
|
||||||
popup.xdg.set_popup_stack(&stack);
|
popup.xdg.set_popup_stack(&stack, false);
|
||||||
popup.xdg.set_output(&node);
|
popup.xdg.set_output(&node);
|
||||||
let user = Rc::new(Popup {
|
let user = Rc::new(Popup {
|
||||||
parent: item.clone(),
|
parent: item.clone(),
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use {
|
||||||
},
|
},
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
tree::Node,
|
tree::{Node, NodeLayerLink},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
linkedlist::{LinkedNode, NodeRef},
|
linkedlist::{LinkedNode, NodeRef},
|
||||||
|
|
@ -361,6 +361,10 @@ impl Object for WlSubsurface {
|
||||||
simple_add_obj!(WlSubsurface);
|
simple_add_obj!(WlSubsurface);
|
||||||
|
|
||||||
impl SurfaceExt for WlSubsurface {
|
impl SurfaceExt for WlSubsurface {
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
self.parent.node_layer()
|
||||||
|
}
|
||||||
|
|
||||||
fn commit_requested(self: Rc<Self>, pending: &mut Box<PendingState>) -> CommitAction {
|
fn commit_requested(self: Rc<Self>, pending: &mut Box<PendingState>) -> CommitAction {
|
||||||
if self.sync() {
|
if self.sync() {
|
||||||
let mut parent_pending = self.pending();
|
let mut parent_pending = self.pending();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use {
|
||||||
x_surface::{xwayland_surface_v1::XwaylandSurfaceV1, xwindow::Xwindow},
|
x_surface::{xwayland_surface_v1::XwaylandSurfaceV1, xwindow::Xwindow},
|
||||||
},
|
},
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
tree::{Node, ToplevelNode, ToplevelNodeBase},
|
tree::{Node, NodeLayerLink, ToplevelNode, ToplevelNodeBase},
|
||||||
utils::clonecell::CloneCell,
|
utils::clonecell::CloneCell,
|
||||||
xwayland::XWaylandEvent,
|
xwayland::XWaylandEvent,
|
||||||
},
|
},
|
||||||
|
|
@ -23,6 +23,13 @@ pub struct XSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SurfaceExt for XSurface {
|
impl SurfaceExt for XSurface {
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
let Some(win) = self.xwindow.get() else {
|
||||||
|
return NodeLayerLink::Display;
|
||||||
|
};
|
||||||
|
win.node_layer()
|
||||||
|
}
|
||||||
|
|
||||||
fn after_apply_commit(self: Rc<Self>) {
|
fn after_apply_commit(self: Rc<Self>) {
|
||||||
if let Some(xwindow) = self.xwindow.get() {
|
if let Some(xwindow) = self.xwindow.get() {
|
||||||
xwindow.map_status_changed();
|
xwindow.map_status_changed();
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ use {
|
||||||
state::State,
|
state::State,
|
||||||
tree::{
|
tree::{
|
||||||
ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId,
|
ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId,
|
||||||
NodeLocation, NodeVisitor, OutputNode, StackedNode, TileDragDestination, ToplevelData,
|
NodeLayerLink, NodeLocation, NodeVisitor, OutputNode, StackedNode, TileDragDestination,
|
||||||
ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode,
|
ToplevelData, ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode,
|
||||||
default_tile_drag_destination,
|
default_tile_drag_destination,
|
||||||
},
|
},
|
||||||
utils::{clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode},
|
utils::{clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode},
|
||||||
|
|
@ -375,6 +375,17 @@ impl Node for Xwindow {
|
||||||
self.x.surface.node_location()
|
self.x.surface.node_location()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
if let Some(link) = self.display_link.borrow().as_ref() {
|
||||||
|
return NodeLayerLink::Stacked(link.to_ref());
|
||||||
|
}
|
||||||
|
self.toplevel_data.node_layer()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_accepts_focus(&self) -> bool {
|
||||||
|
self.tl_accepts_keyboard_focus()
|
||||||
|
}
|
||||||
|
|
||||||
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _direction: Direction) {
|
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _direction: Direction) {
|
||||||
seat.focus_toplevel(self.clone());
|
seat.focus_toplevel(self.clone());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ use {
|
||||||
object::Object,
|
object::Object,
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
tree::{
|
tree::{
|
||||||
FindTreeResult, FoundNode, Node, NodeLocation, OutputNode, StackedNode, WorkspaceNode,
|
FindTreeResult, FoundNode, Node, NodeLayerLink, NodeLocation, OutputNode, StackedNode,
|
||||||
|
WorkspaceNode,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
|
|
@ -75,6 +76,7 @@ pub struct XdgSurface {
|
||||||
pub absolute_desired_extents: Cell<Rect>,
|
pub absolute_desired_extents: Cell<Rect>,
|
||||||
ext: CloneCell<Option<Rc<dyn XdgSurfaceExt>>>,
|
ext: CloneCell<Option<Rc<dyn XdgSurfaceExt>>>,
|
||||||
popup_display_stack: CloneCell<Rc<LinkedList<Rc<dyn StackedNode>>>>,
|
popup_display_stack: CloneCell<Rc<LinkedList<Rc<dyn StackedNode>>>>,
|
||||||
|
is_above_layers: Cell<bool>,
|
||||||
popups: CopyHashMap<XdgPopupId, Rc<Popup>>,
|
popups: CopyHashMap<XdgPopupId, Rc<Popup>>,
|
||||||
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
||||||
pub tracker: Tracker<Self>,
|
pub tracker: Tracker<Self>,
|
||||||
|
|
@ -152,6 +154,16 @@ impl XdgPopupParent for Popup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
let Some(link) = self.display_link.borrow().as_ref().map(|w| w.to_ref()) else {
|
||||||
|
return NodeLayerLink::Display;
|
||||||
|
};
|
||||||
|
match self.popup.xdg.is_above_layers.get() {
|
||||||
|
true => NodeLayerLink::StackedAboveLayers(link),
|
||||||
|
false => NodeLayerLink::Stacked(link),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn tray_item(&self) -> Option<TrayItemId> {
|
fn tray_item(&self) -> Option<TrayItemId> {
|
||||||
self.parent.clone().tray_item()
|
self.parent.clone().tray_item()
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +213,8 @@ pub trait XdgSurfaceExt: Debug {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_visible(self: Rc<Self>);
|
fn make_visible(self: Rc<Self>);
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XdgSurface {
|
impl XdgSurface {
|
||||||
|
|
@ -217,6 +231,7 @@ impl XdgSurface {
|
||||||
absolute_desired_extents: Cell::new(Default::default()),
|
absolute_desired_extents: Cell::new(Default::default()),
|
||||||
ext: Default::default(),
|
ext: Default::default(),
|
||||||
popup_display_stack: CloneCell::new(surface.client.state.root.stacked.clone()),
|
popup_display_stack: CloneCell::new(surface.client.state.root.stacked.clone()),
|
||||||
|
is_above_layers: Cell::new(false),
|
||||||
popups: Default::default(),
|
popups: Default::default(),
|
||||||
workspace: Default::default(),
|
workspace: Default::default(),
|
||||||
tracker: Default::default(),
|
tracker: Default::default(),
|
||||||
|
|
@ -331,7 +346,12 @@ impl XdgSurface {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_popup_stack(&self, stack: &Rc<LinkedList<Rc<dyn StackedNode>>>) {
|
pub fn set_popup_stack(
|
||||||
|
&self,
|
||||||
|
stack: &Rc<LinkedList<Rc<dyn StackedNode>>>,
|
||||||
|
is_above_layers: bool,
|
||||||
|
) {
|
||||||
|
self.is_above_layers.set(is_above_layers);
|
||||||
let prev = self.popup_display_stack.set(stack.clone());
|
let prev = self.popup_display_stack.set(stack.clone());
|
||||||
if rc_eq(&prev, stack) {
|
if rc_eq(&prev, stack) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -340,7 +360,7 @@ impl XdgSurface {
|
||||||
if let Some(dl) = &*popup.display_link.borrow() {
|
if let Some(dl) = &*popup.display_link.borrow() {
|
||||||
stack.add_last_existing(dl);
|
stack.add_last_existing(dl);
|
||||||
}
|
}
|
||||||
popup.popup.xdg.set_popup_stack(stack);
|
popup.popup.xdg.set_popup_stack(stack, is_above_layers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -423,7 +443,10 @@ impl XdgSurfaceRequestHandler for XdgSurface {
|
||||||
workspace_link: Default::default(),
|
workspace_link: Default::default(),
|
||||||
});
|
});
|
||||||
popup.parent.set(Some(user.clone()));
|
popup.parent.set(Some(user.clone()));
|
||||||
popup.xdg.set_popup_stack(&parent.popup_display_stack.get());
|
popup.xdg.set_popup_stack(
|
||||||
|
&parent.popup_display_stack.get(),
|
||||||
|
parent.is_above_layers.get(),
|
||||||
|
);
|
||||||
popup.xdg.set_output(&parent.surface.output.get());
|
popup.xdg.set_output(&parent.surface.output.get());
|
||||||
parent.popups.set(req.id, user);
|
parent.popups.set(req.id, user);
|
||||||
}
|
}
|
||||||
|
|
@ -526,6 +549,13 @@ impl Object for XdgSurface {
|
||||||
dedicated_add_obj!(XdgSurface, XdgSurfaceId, xdg_surfaces);
|
dedicated_add_obj!(XdgSurface, XdgSurfaceId, xdg_surfaces);
|
||||||
|
|
||||||
impl SurfaceExt for XdgSurface {
|
impl SurfaceExt for XdgSurface {
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
let Some(ext) = self.ext.get() else {
|
||||||
|
return NodeLayerLink::Display;
|
||||||
|
};
|
||||||
|
ext.node_layer()
|
||||||
|
}
|
||||||
|
|
||||||
fn before_apply_commit(
|
fn before_apply_commit(
|
||||||
self: Rc<Self>,
|
self: Rc<Self>,
|
||||||
pending: &mut PendingState,
|
pending: &mut PendingState,
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ use {
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
tree::{
|
tree::{
|
||||||
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, NodeVisitor,
|
Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink,
|
||||||
OutputNode, StackedNode,
|
NodeLocation, NodeVisitor, OutputNode, StackedNode,
|
||||||
},
|
},
|
||||||
utils::clonecell::CloneCell,
|
utils::clonecell::CloneCell,
|
||||||
wire::{XdgPopupId, xdg_popup::*},
|
wire::{XdgPopupId, xdg_popup::*},
|
||||||
|
|
@ -46,6 +46,7 @@ pub trait XdgPopupParent {
|
||||||
fn post_commit(&self);
|
fn post_commit(&self);
|
||||||
fn visible(&self) -> bool;
|
fn visible(&self) -> bool;
|
||||||
fn make_visible(self: Rc<Self>);
|
fn make_visible(self: Rc<Self>);
|
||||||
|
fn node_layer(&self) -> NodeLayerLink;
|
||||||
fn tray_item(&self) -> Option<TrayItemId> {
|
fn tray_item(&self) -> Option<TrayItemId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -317,13 +318,21 @@ impl Node for XdgPopup {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_output(&self) -> Option<Rc<OutputNode>> {
|
fn node_output(&self) -> Option<Rc<OutputNode>> {
|
||||||
self.xdg.workspace.get().map(|w| w.output.get())
|
Some(self.xdg.surface.output.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_location(&self) -> Option<NodeLocation> {
|
fn node_location(&self) -> Option<NodeLocation> {
|
||||||
self.xdg.surface.node_location()
|
self.xdg.surface.node_location()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
XdgSurfaceExt::node_layer(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _direction: Direction) {
|
||||||
|
seat.focus_node(self.xdg.surface.clone());
|
||||||
|
}
|
||||||
|
|
||||||
fn node_find_tree_at(
|
fn node_find_tree_at(
|
||||||
&self,
|
&self,
|
||||||
x: i32,
|
x: i32,
|
||||||
|
|
@ -441,6 +450,13 @@ impl XdgSurfaceExt for XdgPopup {
|
||||||
fn make_visible(self: Rc<Self>) {
|
fn make_visible(self: Rc<Self>) {
|
||||||
self.node_make_visible();
|
self.node_make_visible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
let Some(parent) = self.parent.get() else {
|
||||||
|
return NodeLayerLink::Display;
|
||||||
|
};
|
||||||
|
parent.node_layer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ use {
|
||||||
state::State,
|
state::State,
|
||||||
tree::{
|
tree::{
|
||||||
ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId,
|
ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId,
|
||||||
NodeLocation, NodeVisitor, OutputNode, TileDragDestination, ToplevelData, ToplevelNode,
|
NodeLayerLink, NodeLocation, NodeVisitor, OutputNode, TileDragDestination,
|
||||||
ToplevelNodeBase, ToplevelNodeId, ToplevelType, WorkspaceNode,
|
ToplevelData, ToplevelNode, ToplevelNodeBase, ToplevelNodeId, ToplevelType,
|
||||||
default_tile_drag_destination,
|
WorkspaceNode, default_tile_drag_destination,
|
||||||
},
|
},
|
||||||
utils::{clonecell::CloneCell, hash_map_ext::HashMapExt},
|
utils::{clonecell::CloneCell, hash_map_ext::HashMapExt},
|
||||||
wire::{XdgToplevelId, xdg_toplevel::*},
|
wire::{XdgToplevelId, xdg_toplevel::*},
|
||||||
|
|
@ -577,6 +577,10 @@ impl Node for XdgToplevel {
|
||||||
self.xdg.surface.node_location()
|
self.xdg.surface.node_location()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
self.toplevel_data.node_layer()
|
||||||
|
}
|
||||||
|
|
||||||
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _direction: Direction) {
|
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _direction: Direction) {
|
||||||
seat.focus_toplevel(self.clone());
|
seat.focus_toplevel(self.clone());
|
||||||
}
|
}
|
||||||
|
|
@ -788,6 +792,10 @@ impl XdgSurfaceExt for XdgToplevel {
|
||||||
fn make_visible(self: Rc<Self>) {
|
fn make_visible(self: Rc<Self>) {
|
||||||
self.node_make_visible();
|
self.node_make_visible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
self.toplevel_data.node_layer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use {
|
||||||
client::{Client, ClientError},
|
client::{Client, ClientError},
|
||||||
ifs::{
|
ifs::{
|
||||||
wl_output::OutputGlobalOpt,
|
wl_output::OutputGlobalOpt,
|
||||||
wl_seat::NodeSeatState,
|
wl_seat::{NodeSeatState, WlSeatGlobal},
|
||||||
wl_surface::{
|
wl_surface::{
|
||||||
PendingState, SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError,
|
PendingState, SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError,
|
||||||
xdg_surface::xdg_popup::{XdgPopup, XdgPopupParent},
|
xdg_surface::xdg_popup::{XdgPopup, XdgPopupParent},
|
||||||
|
|
@ -15,8 +15,8 @@ use {
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
tree::{
|
tree::{
|
||||||
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, NodeVisitor,
|
Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink,
|
||||||
OutputNode, StackedNode,
|
NodeLocation, NodeVisitor, OutputNode, StackedNode,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
bitflags::BitflagsExt,
|
bitflags::BitflagsExt,
|
||||||
|
|
@ -65,7 +65,7 @@ pub struct ZwlrLayerSurfaceV1 {
|
||||||
exclusive_zone: Cell<ExclusiveZone>,
|
exclusive_zone: Cell<ExclusiveZone>,
|
||||||
margin: Cell<(i32, i32, i32, i32)>,
|
margin: Cell<(i32, i32, i32, i32)>,
|
||||||
keyboard_interactivity: Cell<u32>,
|
keyboard_interactivity: Cell<u32>,
|
||||||
link: Cell<Option<LinkedNode<Rc<Self>>>>,
|
link: RefCell<Option<LinkedNode<Rc<Self>>>>,
|
||||||
seat_state: NodeSeatState,
|
seat_state: NodeSeatState,
|
||||||
last_configure: Cell<(i32, i32)>,
|
last_configure: Cell<(i32, i32)>,
|
||||||
exclusive_edge: Cell<Option<u32>>,
|
exclusive_edge: Cell<Option<u32>>,
|
||||||
|
|
@ -171,7 +171,7 @@ impl ZwlrLayerSurfaceV1 {
|
||||||
exclusive_zone: Cell::new(ExclusiveZone::MoveSelf),
|
exclusive_zone: Cell::new(ExclusiveZone::MoveSelf),
|
||||||
margin: Cell::new((0, 0, 0, 0)),
|
margin: Cell::new((0, 0, 0, 0)),
|
||||||
keyboard_interactivity: Cell::new(0),
|
keyboard_interactivity: Cell::new(0),
|
||||||
link: Cell::new(None),
|
link: Default::default(),
|
||||||
seat_state: Default::default(),
|
seat_state: Default::default(),
|
||||||
last_configure: Default::default(),
|
last_configure: Default::default(),
|
||||||
exclusive_edge: Default::default(),
|
exclusive_edge: Default::default(),
|
||||||
|
|
@ -291,7 +291,7 @@ impl ZwlrLayerSurfaceV1RequestHandler for ZwlrLayerSurfaceV1 {
|
||||||
return Err(ZwlrLayerSurfaceV1Error::PopupHasParent);
|
return Err(ZwlrLayerSurfaceV1Error::PopupHasParent);
|
||||||
}
|
}
|
||||||
let stack = self.client.state.root.stacked_above_layers.clone();
|
let stack = self.client.state.root.stacked_above_layers.clone();
|
||||||
popup.xdg.set_popup_stack(&stack);
|
popup.xdg.set_popup_stack(&stack, true);
|
||||||
let user = Rc::new(Popup {
|
let user = Rc::new(Popup {
|
||||||
parent: slf.clone(),
|
parent: slf.clone(),
|
||||||
popup: popup.clone(),
|
popup: popup.clone(),
|
||||||
|
|
@ -534,7 +534,7 @@ impl ZwlrLayerSurfaceV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy_node(&self) {
|
pub fn destroy_node(&self) {
|
||||||
self.link.set(None);
|
self.link.borrow_mut().take();
|
||||||
self.mapped.set(false);
|
self.mapped.set(false);
|
||||||
self.surface.destroy_node();
|
self.surface.destroy_node();
|
||||||
self.seat_state.destroy_node(self);
|
self.seat_state.destroy_node(self);
|
||||||
|
|
@ -562,6 +562,18 @@ impl ZwlrLayerSurfaceV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SurfaceExt for ZwlrLayerSurfaceV1 {
|
impl SurfaceExt for ZwlrLayerSurfaceV1 {
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
let Some(link) = self.link.borrow().as_ref().map(|l| l.to_ref()) else {
|
||||||
|
return NodeLayerLink::Display;
|
||||||
|
};
|
||||||
|
match self.layer.get() {
|
||||||
|
0 => NodeLayerLink::Layer0(link),
|
||||||
|
1 => NodeLayerLink::Layer1(link),
|
||||||
|
2 => NodeLayerLink::Layer2(link),
|
||||||
|
_ => NodeLayerLink::Layer3(link),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn before_apply_commit(
|
fn before_apply_commit(
|
||||||
self: Rc<Self>,
|
self: Rc<Self>,
|
||||||
pending: &mut PendingState,
|
pending: &mut PendingState,
|
||||||
|
|
@ -587,7 +599,7 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 {
|
||||||
}
|
}
|
||||||
} else if buffer_is_some {
|
} else if buffer_is_some {
|
||||||
let layer = &output.layers[self.layer.get() as usize];
|
let layer = &output.layers[self.layer.get() as usize];
|
||||||
self.link.set(Some(layer.add_last(self.clone())));
|
*self.link.borrow_mut() = Some(layer.add_last(self.clone()));
|
||||||
self.mapped.set(true);
|
self.mapped.set(true);
|
||||||
self.compute_position();
|
self.compute_position();
|
||||||
self.update_exclusive_size();
|
self.update_exclusive_size();
|
||||||
|
|
@ -663,6 +675,18 @@ impl Node for ZwlrLayerSurfaceV1 {
|
||||||
self.surface.node_location()
|
self.surface.node_location()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
SurfaceExt::node_layer(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_accepts_focus(&self) -> bool {
|
||||||
|
self.keyboard_interactivity.get() != KI_NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _direction: Direction) {
|
||||||
|
seat.focus_node(self.surface.clone())
|
||||||
|
}
|
||||||
|
|
||||||
fn node_find_tree_at(
|
fn node_find_tree_at(
|
||||||
&self,
|
&self,
|
||||||
x: i32,
|
x: i32,
|
||||||
|
|
@ -728,6 +752,13 @@ impl XdgPopupParent for Popup {
|
||||||
fn make_visible(self: Rc<Self>) {
|
fn make_visible(self: Rc<Self>) {
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
let Some(link) = self.stack_link.borrow().as_ref().map(|w| w.to_ref()) else {
|
||||||
|
return NodeLayerLink::Display;
|
||||||
|
};
|
||||||
|
NodeLayerLink::StackedAboveLayers(link)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object_base! {
|
object_base! {
|
||||||
|
|
@ -738,7 +769,7 @@ object_base! {
|
||||||
impl Object for ZwlrLayerSurfaceV1 {
|
impl Object for ZwlrLayerSurfaceV1 {
|
||||||
fn break_loops(&self) {
|
fn break_loops(&self) {
|
||||||
self.destroy_node();
|
self.destroy_node();
|
||||||
self.link.set(None);
|
self.link.borrow_mut().take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use {
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
state::State,
|
state::State,
|
||||||
|
tree::NodeLayerLink,
|
||||||
wire::{WlSurfaceId, ZwpInputPopupSurfaceV2Id, zwp_input_popup_surface_v2::*},
|
wire::{WlSurfaceId, ZwpInputPopupSurfaceV2Id, zwp_input_popup_surface_v2::*},
|
||||||
},
|
},
|
||||||
std::{cell::Cell, rc::Rc},
|
std::{cell::Cell, rc::Rc},
|
||||||
|
|
@ -27,6 +28,10 @@ pub struct ZwpInputPopupSurfaceV2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SurfaceExt for ZwpInputPopupSurfaceV2 {
|
impl SurfaceExt for ZwpInputPopupSurfaceV2 {
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
NodeLayerLink::InputMethod
|
||||||
|
}
|
||||||
|
|
||||||
fn after_apply_commit(self: Rc<Self>) {
|
fn after_apply_commit(self: Rc<Self>) {
|
||||||
self.update_visible();
|
self.update_visible();
|
||||||
if self.surface.visible.get() {
|
if self.surface.visible.get() {
|
||||||
|
|
|
||||||
85
src/tree.rs
85
src/tree.rs
|
|
@ -13,14 +13,15 @@ use {
|
||||||
},
|
},
|
||||||
wl_pointer::PendingScroll,
|
wl_pointer::PendingScroll,
|
||||||
},
|
},
|
||||||
wl_surface::{WlSurface, tray::TrayItemId},
|
wl_surface::{WlSurface, tray::TrayItemId, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1},
|
||||||
},
|
},
|
||||||
keyboard::KeyboardState,
|
keyboard::KeyboardState,
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
utils::numcell::NumCell,
|
utils::{linkedlist::NodeRef, numcell::NumCell},
|
||||||
},
|
},
|
||||||
jay_config::Direction as JayDirection,
|
jay_config::Direction as JayDirection,
|
||||||
|
linearize::{Linearize, LinearizeExt},
|
||||||
std::{
|
std::{
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
|
@ -121,6 +122,81 @@ pub enum NodeLocation {
|
||||||
Output(OutputNodeId),
|
Output(OutputNodeId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Linearize, Eq, PartialEq, Debug)]
|
||||||
|
pub enum NodeLayer {
|
||||||
|
Display,
|
||||||
|
Layer0,
|
||||||
|
Layer1,
|
||||||
|
Output,
|
||||||
|
Workspace,
|
||||||
|
Tiled,
|
||||||
|
Fullscreen,
|
||||||
|
Stacked,
|
||||||
|
Layer2,
|
||||||
|
Layer3,
|
||||||
|
StackedAboveLayers,
|
||||||
|
Lock,
|
||||||
|
InputMethod,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum NodeLayerLink {
|
||||||
|
Display,
|
||||||
|
Layer0(NodeRef<Rc<ZwlrLayerSurfaceV1>>),
|
||||||
|
Layer1(NodeRef<Rc<ZwlrLayerSurfaceV1>>),
|
||||||
|
Output,
|
||||||
|
Workspace,
|
||||||
|
Tiled,
|
||||||
|
Fullscreen,
|
||||||
|
Stacked(NodeRef<Rc<dyn StackedNode>>),
|
||||||
|
Layer2(NodeRef<Rc<ZwlrLayerSurfaceV1>>),
|
||||||
|
Layer3(NodeRef<Rc<ZwlrLayerSurfaceV1>>),
|
||||||
|
StackedAboveLayers(NodeRef<Rc<dyn StackedNode>>),
|
||||||
|
Lock,
|
||||||
|
InputMethod,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeLayerLink {
|
||||||
|
pub fn layer(&self) -> NodeLayer {
|
||||||
|
macro_rules! map {
|
||||||
|
($($id:ident,)*) => {
|
||||||
|
match self {
|
||||||
|
$(
|
||||||
|
Self::$id { .. } => NodeLayer::$id,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
map! {
|
||||||
|
Display,
|
||||||
|
Layer0,
|
||||||
|
Layer1,
|
||||||
|
Output,
|
||||||
|
Workspace,
|
||||||
|
Tiled,
|
||||||
|
Fullscreen,
|
||||||
|
Stacked,
|
||||||
|
Layer2,
|
||||||
|
Layer3,
|
||||||
|
StackedAboveLayers,
|
||||||
|
Lock,
|
||||||
|
InputMethod,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeLayer {
|
||||||
|
pub fn prev(self) -> Self {
|
||||||
|
if self == NodeLayer::Display {
|
||||||
|
return NodeLayer::InputMethod;
|
||||||
|
}
|
||||||
|
Self::from_linear(self.linearize() - 1).unwrap_or(NodeLayer::InputMethod)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(self) -> Self {
|
||||||
|
Self::from_linear(self.linearize() + 1).unwrap_or(NodeLayer::Display)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Node: 'static {
|
pub trait Node: 'static {
|
||||||
fn node_id(&self) -> NodeId;
|
fn node_id(&self) -> NodeId;
|
||||||
fn node_seat_state(&self) -> &NodeSeatState;
|
fn node_seat_state(&self) -> &NodeSeatState;
|
||||||
|
|
@ -130,12 +206,17 @@ pub trait Node: 'static {
|
||||||
fn node_absolute_position(&self) -> Rect;
|
fn node_absolute_position(&self) -> Rect;
|
||||||
fn node_output(&self) -> Option<Rc<OutputNode>>;
|
fn node_output(&self) -> Option<Rc<OutputNode>>;
|
||||||
fn node_location(&self) -> Option<NodeLocation>;
|
fn node_location(&self) -> Option<NodeLocation>;
|
||||||
|
fn node_layer(&self) -> NodeLayerLink;
|
||||||
|
|
||||||
fn node_child_title_changed(self: Rc<Self>, child: &dyn Node, title: &str) {
|
fn node_child_title_changed(self: Rc<Self>, child: &dyn Node, title: &str) {
|
||||||
let _ = child;
|
let _ = child;
|
||||||
let _ = title;
|
let _ = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_accepts_focus(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||||
let _ = seat;
|
let _ = seat;
|
||||||
let _ = direction;
|
let _ = direction;
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ use {
|
||||||
text::TextTexture,
|
text::TextTexture,
|
||||||
tree::{
|
tree::{
|
||||||
ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node,
|
ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node,
|
||||||
NodeId, NodeLocation, OutputNode, TddType, TileDragDestination, ToplevelData,
|
NodeId, NodeLayerLink, NodeLocation, OutputNode, TddType, TileDragDestination,
|
||||||
ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode, default_tile_drag_bounds,
|
ToplevelData, ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode,
|
||||||
toplevel_set_floating, walker::NodeVisitor,
|
default_tile_drag_bounds, toplevel_set_floating, walker::NodeVisitor,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
asyncevent::AsyncEvent,
|
asyncevent::AsyncEvent,
|
||||||
|
|
@ -1553,6 +1553,10 @@ impl Node for ContainerNode {
|
||||||
Some(self.location.get())
|
Some(self.location.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
self.toplevel_data.node_layer()
|
||||||
|
}
|
||||||
|
|
||||||
fn node_child_title_changed(self: Rc<Self>, child: &dyn Node, title: &str) {
|
fn node_child_title_changed(self: Rc<Self>, child: &dyn Node, title: &str) {
|
||||||
if let Some(child) = self.child_nodes.borrow().get(&child.node_id()) {
|
if let Some(child) = self.child_nodes.borrow().get(&child.node_id()) {
|
||||||
self.update_child_title(child, title);
|
self.update_child_title(child, title);
|
||||||
|
|
@ -2108,6 +2112,10 @@ impl ContainingNode for ContainerNode {
|
||||||
fn cnode_get_float(self: Rc<Self>) -> Option<Rc<FloatNode>> {
|
fn cnode_get_float(self: Rc<Self>) -> Option<Rc<FloatNode>> {
|
||||||
self.tl_data().float.get()
|
self.tl_data().float.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cnode_self_or_ancestor_fullscreen(&self) -> bool {
|
||||||
|
self.tl_data().self_or_ancestor_is_fullscreen.get()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToplevelNodeBase for ContainerNode {
|
impl ToplevelNodeBase for ContainerNode {
|
||||||
|
|
@ -2229,6 +2237,12 @@ impl ToplevelNodeBase for ContainerNode {
|
||||||
child.node.tl_set_float(float);
|
child.node.tl_set_float(float);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tl_mark_ancestor_fullscreen_ext(&self, fullscreen: bool) {
|
||||||
|
for child in self.children.iter() {
|
||||||
|
child.node.tl_mark_ancestor_fullscreen(fullscreen);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn direction_to_split(dir: Direction) -> (ContainerSplit, bool) {
|
fn direction_to_split(dir: Direction) -> (ContainerSplit, bool) {
|
||||||
|
|
|
||||||
|
|
@ -41,4 +41,7 @@ pub trait ContainingNode: Node {
|
||||||
fn cnode_get_float(self: Rc<Self>) -> Option<Rc<FloatNode>> {
|
fn cnode_get_float(self: Rc<Self>) -> Option<Rc<FloatNode>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
fn cnode_self_or_ancestor_fullscreen(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ use {
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
state::State,
|
state::State,
|
||||||
tree::{
|
tree::{
|
||||||
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, OutputNode,
|
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation,
|
||||||
StackedNode, TileDragDestination, WorkspaceDragDestination, WorkspaceNodeId,
|
OutputNode, StackedNode, TileDragDestination, WorkspaceDragDestination,
|
||||||
walker::NodeVisitor,
|
WorkspaceNodeId, walker::NodeVisitor,
|
||||||
},
|
},
|
||||||
utils::{copyhashmap::CopyHashMap, linkedlist::LinkedList},
|
utils::{copyhashmap::CopyHashMap, linkedlist::LinkedList},
|
||||||
},
|
},
|
||||||
|
|
@ -157,6 +157,10 @@ impl Node for DisplayNode {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
NodeLayerLink::Display
|
||||||
|
}
|
||||||
|
|
||||||
fn node_find_tree_at(
|
fn node_find_tree_at(
|
||||||
&self,
|
&self,
|
||||||
x: i32,
|
x: i32,
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ use {
|
||||||
text::TextTexture,
|
text::TextTexture,
|
||||||
tree::{
|
tree::{
|
||||||
ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId,
|
ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId,
|
||||||
NodeLocation, OutputNode, PinnedNode, StackedNode, TileDragDestination, ToplevelNode,
|
NodeLayerLink, NodeLocation, OutputNode, PinnedNode, StackedNode, TileDragDestination,
|
||||||
WorkspaceNode, toplevel_set_floating, walker::NodeVisitor,
|
ToplevelNode, WorkspaceNode, toplevel_set_floating, walker::NodeVisitor,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
asyncevent::AsyncEvent, clonecell::CloneCell, double_click_state::DoubleClickState,
|
asyncevent::AsyncEvent, clonecell::CloneCell, double_click_state::DoubleClickState,
|
||||||
|
|
@ -709,10 +709,30 @@ impl Node for FloatNode {
|
||||||
Some(self.location.get())
|
Some(self.location.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
let Some(l) = self.display_link.borrow().as_ref().map(|l| l.to_ref()) else {
|
||||||
|
return NodeLayerLink::Display;
|
||||||
|
};
|
||||||
|
NodeLayerLink::Stacked(l)
|
||||||
|
}
|
||||||
|
|
||||||
fn node_child_title_changed(self: Rc<Self>, _child: &dyn Node, title: &str) {
|
fn node_child_title_changed(self: Rc<Self>, _child: &dyn Node, title: &str) {
|
||||||
self.update_child_title(title);
|
self.update_child_title(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_accepts_focus(&self) -> bool {
|
||||||
|
if let Some(c) = self.child.get() {
|
||||||
|
return c.tl_accepts_keyboard_focus();
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||||
|
if let Some(c) = self.child.get() {
|
||||||
|
c.node_do_focus(seat, direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn node_find_tree_at(
|
fn node_find_tree_at(
|
||||||
&self,
|
&self,
|
||||||
x: i32,
|
x: i32,
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,9 @@ use {
|
||||||
state::State,
|
state::State,
|
||||||
text::TextTexture,
|
text::TextTexture,
|
||||||
tree::{
|
tree::{
|
||||||
Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation,
|
Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink,
|
||||||
PinnedNode, StackedNode, TddType, TileDragDestination, WorkspaceDragDestination,
|
NodeLocation, PinnedNode, StackedNode, TddType, TileDragDestination,
|
||||||
WorkspaceNode, WorkspaceNodeId, walker::NodeVisitor,
|
WorkspaceDragDestination, WorkspaceNode, WorkspaceNodeId, walker::NodeVisitor,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
asyncevent::AsyncEvent, bitflags::BitflagsExt, clonecell::CloneCell,
|
asyncevent::AsyncEvent, bitflags::BitflagsExt, clonecell::CloneCell,
|
||||||
|
|
@ -1478,6 +1478,10 @@ impl Node for OutputNode {
|
||||||
Some(NodeLocation::Output(self.id))
|
Some(NodeLocation::Output(self.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
NodeLayerLink::Output
|
||||||
|
}
|
||||||
|
|
||||||
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||||
if self.state.lock.locked.get() {
|
if self.state.lock.locked.get() {
|
||||||
if let Some(lock) = self.lock_surface.get() {
|
if let Some(lock) = self.lock_surface.get() {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,9 @@ use {
|
||||||
text::TextTexture,
|
text::TextTexture,
|
||||||
tree::{
|
tree::{
|
||||||
ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId,
|
ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId,
|
||||||
NodeLocation, NodeVisitor, OutputNode, TileDragDestination, ToplevelData, ToplevelNode,
|
NodeLayerLink, NodeLocation, NodeVisitor, OutputNode, TileDragDestination,
|
||||||
ToplevelNodeBase, ToplevelType, WorkspaceNode, default_tile_drag_destination,
|
ToplevelData, ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode,
|
||||||
|
default_tile_drag_destination,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
asyncevent::AsyncEvent, errorfmt::ErrorFmt, on_drop_event::OnDropEvent,
|
asyncevent::AsyncEvent, errorfmt::ErrorFmt, on_drop_event::OnDropEvent,
|
||||||
|
|
@ -181,6 +182,10 @@ impl Node for PlaceholderNode {
|
||||||
self.location.get()
|
self.location.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
self.toplevel.node_layer()
|
||||||
|
}
|
||||||
|
|
||||||
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _direction: Direction) {
|
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _direction: Direction) {
|
||||||
seat.focus_toplevel(self.clone());
|
seat.focus_toplevel(self.clone());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ use {
|
||||||
state::State,
|
state::State,
|
||||||
tree::{
|
tree::{
|
||||||
ContainerNode, ContainerSplit, ContainingNode, Direction, FloatNode, Node, NodeId,
|
ContainerNode, ContainerSplit, ContainingNode, Direction, FloatNode, Node, NodeId,
|
||||||
OutputNode, PlaceholderNode, WorkspaceNode,
|
NodeLayerLink, OutputNode, PlaceholderNode, WorkspaceNode,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
array_to_tuple::ArrayToTuple,
|
array_to_tuple::ArrayToTuple,
|
||||||
|
|
@ -70,6 +70,8 @@ pub trait ToplevelNode: ToplevelNodeBase {
|
||||||
fn tl_pinned(&self) -> bool;
|
fn tl_pinned(&self) -> bool;
|
||||||
fn tl_set_pinned(&self, self_pinned: bool, pinned: bool);
|
fn tl_set_pinned(&self, self_pinned: bool, pinned: bool);
|
||||||
fn tl_set_float(&self, float: Option<&Rc<FloatNode>>);
|
fn tl_set_float(&self, float: Option<&Rc<FloatNode>>);
|
||||||
|
fn tl_mark_ancestor_fullscreen(&self, fullscreen: bool);
|
||||||
|
fn tl_mark_fullscreen(&self, fullscreen: bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ToplevelNodeBase> ToplevelNode for T {
|
impl<T: ToplevelNodeBase> ToplevelNode for T {
|
||||||
|
|
@ -110,6 +112,9 @@ impl<T: ToplevelNodeBase> ToplevelNode for T {
|
||||||
|
|
||||||
fn tl_set_parent(&self, parent: Rc<dyn ContainingNode>) {
|
fn tl_set_parent(&self, parent: Rc<dyn ContainingNode>) {
|
||||||
let data = self.tl_data();
|
let data = self.tl_data();
|
||||||
|
if !data.is_fullscreen.get() {
|
||||||
|
self.tl_mark_ancestor_fullscreen(parent.cnode_self_or_ancestor_fullscreen());
|
||||||
|
}
|
||||||
let parent_was_none = data.parent.set(Some(parent.clone())).is_none();
|
let parent_was_none = data.parent.set(Some(parent.clone())).is_none();
|
||||||
if parent_was_none {
|
if parent_was_none {
|
||||||
data.mapped_during_iteration.set(data.state.eng.iteration());
|
data.mapped_during_iteration.set(data.state.eng.iteration());
|
||||||
|
|
@ -227,6 +232,22 @@ impl<T: ToplevelNodeBase> ToplevelNode for T {
|
||||||
self.tl_data().float.set(float.cloned());
|
self.tl_data().float.set(float.cloned());
|
||||||
self.tl_push_float(float);
|
self.tl_push_float(float);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tl_mark_ancestor_fullscreen(&self, fullscreen: bool) {
|
||||||
|
let old = self
|
||||||
|
.tl_data()
|
||||||
|
.self_or_ancestor_is_fullscreen
|
||||||
|
.replace(fullscreen);
|
||||||
|
if old == fullscreen {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.tl_mark_ancestor_fullscreen_ext(fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tl_mark_fullscreen(&self, fullscreen: bool) {
|
||||||
|
self.tl_data().is_fullscreen.set(fullscreen);
|
||||||
|
self.tl_mark_ancestor_fullscreen(fullscreen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToplevelNodeBase: Node {
|
pub trait ToplevelNodeBase: Node {
|
||||||
|
|
@ -290,6 +311,10 @@ pub trait ToplevelNodeBase: Node {
|
||||||
fn tl_push_float(&self, float: Option<&Rc<FloatNode>>) {
|
fn tl_push_float(&self, float: Option<&Rc<FloatNode>>) {
|
||||||
let _ = float;
|
let _ = float;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tl_mark_ancestor_fullscreen_ext(&self, fullscreen: bool) {
|
||||||
|
let _ = fullscreen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FullscreenedData {
|
pub struct FullscreenedData {
|
||||||
|
|
@ -346,6 +371,7 @@ pub struct ToplevelData {
|
||||||
pub float_height: Cell<i32>,
|
pub float_height: Cell<i32>,
|
||||||
pub pinned: Cell<bool>,
|
pub pinned: Cell<bool>,
|
||||||
pub is_fullscreen: Cell<bool>,
|
pub is_fullscreen: Cell<bool>,
|
||||||
|
pub self_or_ancestor_is_fullscreen: Cell<bool>,
|
||||||
pub fullscrceen_data: RefCell<Option<FullscreenedData>>,
|
pub fullscrceen_data: RefCell<Option<FullscreenedData>>,
|
||||||
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
||||||
pub title: RefCell<String>,
|
pub title: RefCell<String>,
|
||||||
|
|
@ -401,6 +427,7 @@ impl ToplevelData {
|
||||||
float_height: Default::default(),
|
float_height: Default::default(),
|
||||||
pinned: Cell::new(false),
|
pinned: Cell::new(false),
|
||||||
is_fullscreen: Default::default(),
|
is_fullscreen: Default::default(),
|
||||||
|
self_or_ancestor_is_fullscreen: Default::default(),
|
||||||
fullscrceen_data: Default::default(),
|
fullscrceen_data: Default::default(),
|
||||||
workspace: Default::default(),
|
workspace: Default::default(),
|
||||||
title: RefCell::new(title),
|
title: RefCell::new(title),
|
||||||
|
|
@ -731,7 +758,7 @@ impl ToplevelData {
|
||||||
workspace: ws.clone(),
|
workspace: ws.clone(),
|
||||||
});
|
});
|
||||||
drop(data);
|
drop(data);
|
||||||
self.is_fullscreen.set(true);
|
node.tl_mark_fullscreen(true);
|
||||||
self.property_changed(TL_CHANGED_FULLSCREEN);
|
self.property_changed(TL_CHANGED_FULLSCREEN);
|
||||||
node.tl_set_parent(ws.clone());
|
node.tl_set_parent(ws.clone());
|
||||||
ws.set_fullscreen_node(&node);
|
ws.set_fullscreen_node(&node);
|
||||||
|
|
@ -758,7 +785,7 @@ impl ToplevelData {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.is_fullscreen.set(false);
|
node.tl_mark_fullscreen(false);
|
||||||
self.property_changed(TL_CHANGED_FULLSCREEN);
|
self.property_changed(TL_CHANGED_FULLSCREEN);
|
||||||
match fd.workspace.fullscreen.get() {
|
match fd.workspace.fullscreen.get() {
|
||||||
None => {
|
None => {
|
||||||
|
|
@ -875,6 +902,16 @@ impl ToplevelData {
|
||||||
parent.cnode_make_visible(slf);
|
parent.cnode_make_visible(slf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
if self.self_or_ancestor_is_fullscreen.get() {
|
||||||
|
return NodeLayerLink::Fullscreen;
|
||||||
|
}
|
||||||
|
if let Some(float) = self.float.get() {
|
||||||
|
return float.node_layer();
|
||||||
|
}
|
||||||
|
NodeLayerLink::Tiled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for ToplevelData {
|
impl Drop for ToplevelData {
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,9 @@ use {
|
||||||
text::TextTexture,
|
text::TextTexture,
|
||||||
tree::{
|
tree::{
|
||||||
ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node,
|
ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node,
|
||||||
NodeId, NodeLocation, NodeVisitorBase, OutputNode, OutputNodeId, PlaceholderNode,
|
NodeId, NodeLayerLink, NodeLocation, NodeVisitorBase, OutputNode, OutputNodeId,
|
||||||
StackedNode, ToplevelNode, container::ContainerNode, walker::NodeVisitor,
|
PlaceholderNode, StackedNode, ToplevelNode, container::ContainerNode,
|
||||||
|
walker::NodeVisitor,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
|
|
@ -321,6 +322,10 @@ impl Node for WorkspaceNode {
|
||||||
Some(self.location())
|
Some(self.location())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_layer(&self) -> NodeLayerLink {
|
||||||
|
NodeLayerLink::Workspace
|
||||||
|
}
|
||||||
|
|
||||||
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
fn node_do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||||
if let Some(fs) = self.fullscreen.get() {
|
if let Some(fs) = self.fullscreen.get() {
|
||||||
fs.node_do_focus(seat, direction);
|
fs.node_do_focus(seat, direction);
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,10 @@ use {
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
jay_config::{
|
jay_config::{
|
||||||
Axis, Direction, Workspace,
|
Axis, Direction, Workspace,
|
||||||
input::{SwitchEvent, Timeline, acceleration::AccelProfile, clickmethod::ClickMethod},
|
input::{
|
||||||
|
LayerDirection, SwitchEvent, Timeline, acceleration::AccelProfile,
|
||||||
|
clickmethod::ClickMethod,
|
||||||
|
},
|
||||||
keyboard::{Keymap, ModifiedKeySym, mods::Modifiers, syms::KeySym},
|
keyboard::{Keymap, ModifiedKeySym, mods::Modifiers, syms::KeySym},
|
||||||
logging::LogLevel,
|
logging::LogLevel,
|
||||||
status::MessageFormat,
|
status::MessageFormat,
|
||||||
|
|
@ -72,6 +75,8 @@ pub enum SimpleCommand {
|
||||||
ShowBar(bool),
|
ShowBar(bool),
|
||||||
ToggleBar,
|
ToggleBar,
|
||||||
FocusHistory(Timeline),
|
FocusHistory(Timeline),
|
||||||
|
FocusLayerRel(LayerDirection),
|
||||||
|
FocusTiles,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ use {
|
||||||
jay_config::{
|
jay_config::{
|
||||||
Axis::{Horizontal, Vertical},
|
Axis::{Horizontal, Vertical},
|
||||||
get_workspace,
|
get_workspace,
|
||||||
input::Timeline,
|
input::{LayerDirection, Timeline},
|
||||||
},
|
},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
};
|
};
|
||||||
|
|
@ -139,6 +139,9 @@ impl ActionParser<'_> {
|
||||||
"toggle-bar" => ToggleBar,
|
"toggle-bar" => ToggleBar,
|
||||||
"focus-prev" => FocusHistory(Timeline::Older),
|
"focus-prev" => FocusHistory(Timeline::Older),
|
||||||
"focus-next" => FocusHistory(Timeline::Newer),
|
"focus-next" => FocusHistory(Timeline::Newer),
|
||||||
|
"focus-below" => FocusLayerRel(LayerDirection::Below),
|
||||||
|
"focus-above" => FocusLayerRel(LayerDirection::Above),
|
||||||
|
"focus-tiles" => FocusTiles,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(
|
return Err(
|
||||||
ActionParserError::UnknownSimpleAction(string.to_string()).spanned(span)
|
ActionParserError::UnknownSimpleAction(string.to_string()).spanned(span)
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,14 @@ impl Action {
|
||||||
let persistent = state.persistent.clone();
|
let persistent = state.persistent.clone();
|
||||||
B::new(move || persistent.seat.focus_history(timeline))
|
B::new(move || persistent.seat.focus_history(timeline))
|
||||||
}
|
}
|
||||||
|
SimpleCommand::FocusLayerRel(direction) => {
|
||||||
|
let persistent = state.persistent.clone();
|
||||||
|
B::new(move || persistent.seat.focus_layer_rel(direction))
|
||||||
|
}
|
||||||
|
SimpleCommand::FocusTiles => {
|
||||||
|
let persistent = state.persistent.clone();
|
||||||
|
B::new(move || persistent.seat.focus_tiles())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Action::Multi { actions } => {
|
Action::Multi { actions } => {
|
||||||
let actions: Vec<_> = actions.into_iter().map(|a| a.into_fn(state)).collect();
|
let actions: Vec<_> = actions.into_iter().map(|a| a.into_fn(state)).collect();
|
||||||
|
|
|
||||||
|
|
@ -1614,7 +1614,10 @@
|
||||||
"hide-bar",
|
"hide-bar",
|
||||||
"toggle-bar",
|
"toggle-bar",
|
||||||
"focus-prev",
|
"focus-prev",
|
||||||
"focus-next"
|
"focus-next",
|
||||||
|
"focus-below",
|
||||||
|
"focus-above",
|
||||||
|
"focus-tiles"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Status": {
|
"Status": {
|
||||||
|
|
|
||||||
|
|
@ -3675,6 +3675,18 @@ The string should have one of the following values:
|
||||||
|
|
||||||
Focuses the next window in the focus history.
|
Focuses the next window in the focus history.
|
||||||
|
|
||||||
|
- `focus-below`:
|
||||||
|
|
||||||
|
Focuses the layer below the currently focused layer.
|
||||||
|
|
||||||
|
- `focus-above`:
|
||||||
|
|
||||||
|
Focuses the layer above the currently focused layer.
|
||||||
|
|
||||||
|
- `focus-tiles`:
|
||||||
|
|
||||||
|
Focuses the tile layer.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="types-Status"></a>
|
<a name="types-Status"></a>
|
||||||
|
|
|
||||||
|
|
@ -864,6 +864,12 @@ SimpleActionName:
|
||||||
description: Focuses the previous window in the focus history.
|
description: Focuses the previous window in the focus history.
|
||||||
- value: focus-next
|
- value: focus-next
|
||||||
description: Focuses the next window in the focus history.
|
description: Focuses the next window in the focus history.
|
||||||
|
- value: focus-below
|
||||||
|
description: Focuses the layer below the currently focused layer.
|
||||||
|
- value: focus-above
|
||||||
|
description: Focuses the layer above the currently focused layer.
|
||||||
|
- value: focus-tiles
|
||||||
|
description: Focuses the tile layer.
|
||||||
|
|
||||||
|
|
||||||
Color:
|
Color:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue