tree: make surface visibility tracking more robust
This commit is contained in:
parent
be0935c8dd
commit
ba98103233
26 changed files with 313 additions and 144 deletions
|
|
@ -66,7 +66,7 @@ impl ExtSessionLockV1 {
|
|||
if node.lock_surface.is_some() {
|
||||
return Err(ExtSessionLockV1Error::OutputAlreadyLocked);
|
||||
}
|
||||
node.lock_surface.set(Some(new.clone()));
|
||||
node.set_lock_surface(Some(new.clone()));
|
||||
let pos = output.global.pos.get();
|
||||
new.change_extents(pos);
|
||||
self.client.state.tree_changed();
|
||||
|
|
@ -85,7 +85,7 @@ impl ExtSessionLockV1 {
|
|||
state.lock.locked.set(false);
|
||||
state.lock.lock.take();
|
||||
for output in state.outputs.lock().values() {
|
||||
if let Some(surface) = output.node.lock_surface.take() {
|
||||
if let Some(surface) = output.node.set_lock_surface(None) {
|
||||
surface.destroy_node();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ impl JayCompositor {
|
|||
lock.finish();
|
||||
}
|
||||
for output in state.outputs.lock().values() {
|
||||
if let Some(surface) = output.node.lock_surface.take() {
|
||||
if let Some(surface) = output.node.set_lock_surface(None) {
|
||||
surface.destroy_node();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -981,6 +981,20 @@ impl WlSeatGlobal {
|
|||
pub fn last_input(&self) -> u64 {
|
||||
self.last_input_usec.get()
|
||||
}
|
||||
|
||||
pub fn set_visible(&self, visible: bool) {
|
||||
if let Some(cursor) = self.cursor.get() {
|
||||
cursor.set_visible(visible);
|
||||
}
|
||||
if let Some(icon) = self.dnd_icon() {
|
||||
icon.set_visible(visible);
|
||||
}
|
||||
if let Some(tl_drag) = self.toplevel_drag() {
|
||||
if let Some(tl) = tl_drag.toplevel.get() {
|
||||
tl.tl_set_visible(visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global_base!(WlSeatGlobal, WlSeat, WlSeatError);
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ impl PointerOwner for GrabPointerOwner {
|
|||
return Ok(());
|
||||
}
|
||||
if let Some(icon) = &icon {
|
||||
icon.dnd_icons.insert(seat.id(), seat.clone());
|
||||
icon.set_dnd_icon_seat(seat.id, Some(seat));
|
||||
}
|
||||
if let Some(new) = &src {
|
||||
ipc::attach_seat::<ClipboardIpc>(new, seat, ipc::Role::Dnd)?;
|
||||
|
|
@ -460,7 +460,7 @@ impl PointerOwner for DndPointerOwner {
|
|||
}
|
||||
}
|
||||
if let Some(icon) = self.icon.get() {
|
||||
icon.dnd_icons.remove(&seat.id());
|
||||
icon.set_dnd_icon_seat(seat.id(), None);
|
||||
}
|
||||
seat.pointer_owner.set_default_pointer_owner(seat);
|
||||
seat.tree_changed.trigger();
|
||||
|
|
@ -530,7 +530,7 @@ impl PointerOwner for DndPointerOwner {
|
|||
ipc::detach_seat::<ClipboardIpc>(src, seat);
|
||||
}
|
||||
if let Some(icon) = self.icon.get() {
|
||||
icon.dnd_icons.remove(&seat.id());
|
||||
icon.set_dnd_icon_seat(seat.id(), None);
|
||||
}
|
||||
seat.pointer_owner.set_default_pointer_owner(seat);
|
||||
seat.tree_changed.trigger();
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ pub struct WlSurface {
|
|||
seat_state: NodeSeatState,
|
||||
toplevel: CloneCell<Option<Rc<dyn ToplevelNode>>>,
|
||||
cursors: SmallMap<SeatId, Rc<CursorSurface>, 1>,
|
||||
pub dnd_icons: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
||||
dnd_icons: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
||||
pub tracker: Tracker<Self>,
|
||||
idle_inhibitors: SmallMap<ZwpIdleInhibitorV1Id, Rc<ZwpIdleInhibitorV1>, 1>,
|
||||
viewporter: CloneCell<Option<Rc<WpViewport>>>,
|
||||
|
|
@ -489,7 +489,7 @@ impl WlSurface {
|
|||
id,
|
||||
node_id: client.state.node_ids.next(),
|
||||
client: client.clone(),
|
||||
visible: Default::default(),
|
||||
visible: Cell::new(false),
|
||||
role: Cell::new(SurfaceRole::None),
|
||||
pending: Default::default(),
|
||||
input_region: Default::default(),
|
||||
|
|
@ -1184,7 +1184,9 @@ impl WlSurface {
|
|||
}
|
||||
|
||||
pub fn set_visible(&self, visible: bool) {
|
||||
self.visible.set(visible);
|
||||
if self.visible.replace(visible) == visible {
|
||||
return;
|
||||
}
|
||||
for (_, inhibitor) in &self.idle_inhibitors {
|
||||
if visible {
|
||||
inhibitor.activate();
|
||||
|
|
@ -1204,11 +1206,7 @@ impl WlSurface {
|
|||
self.seat_state.set_visible(self, visible);
|
||||
}
|
||||
|
||||
pub fn detach_node(&self) {
|
||||
self.destroy_node();
|
||||
}
|
||||
|
||||
pub fn destroy_node(&self) {
|
||||
pub fn detach_node(&self, set_invisible: bool) {
|
||||
for (_, constraint) in &self.constraints {
|
||||
constraint.deactivate();
|
||||
}
|
||||
|
|
@ -1218,7 +1216,7 @@ impl WlSurface {
|
|||
let children = self.children.borrow();
|
||||
if let Some(ch) = children.deref() {
|
||||
for ss in ch.subsurfaces.values() {
|
||||
ss.surface.destroy_node();
|
||||
ss.surface.detach_node(set_invisible);
|
||||
}
|
||||
}
|
||||
if let Some(tl) = self.toplevel.get() {
|
||||
|
|
@ -1238,6 +1236,13 @@ impl WlSurface {
|
|||
if self.visible.get() {
|
||||
self.client.state.damage();
|
||||
}
|
||||
if set_invisible {
|
||||
self.visible.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy_node(&self) {
|
||||
self.detach_node(true);
|
||||
}
|
||||
|
||||
pub fn set_content_type(&self, content_type: Option<ContentType>) {
|
||||
|
|
@ -1267,6 +1272,18 @@ impl WlSurface {
|
|||
.get()
|
||||
.consume_pending_child(self, child, &mut consume)
|
||||
}
|
||||
|
||||
pub fn set_dnd_icon_seat(&self, id: SeatId, seat: Option<&Rc<WlSeatGlobal>>) {
|
||||
match seat {
|
||||
None => {
|
||||
self.dnd_icons.remove(&id);
|
||||
}
|
||||
Some(seat) => {
|
||||
self.dnd_icons.insert(id, seat.clone());
|
||||
}
|
||||
}
|
||||
self.set_visible(self.dnd_icons.is_not_empty() && self.client.state.root_visible());
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
|
|
|
|||
|
|
@ -125,9 +125,20 @@ impl Cursor for CursorSurface {
|
|||
|
||||
fn handle_set(self: Rc<Self>) {
|
||||
self.surface.cursors.insert(self.seat.id(), self.clone());
|
||||
if self.surface.cursors.is_not_empty() {
|
||||
self.surface
|
||||
.set_visible(self.surface.client.state.root_visible());
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_unset(&self) {
|
||||
self.surface.cursors.remove(&self.seat.id());
|
||||
if self.surface.cursors.is_empty() {
|
||||
self.surface.set_visible(false);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_visible(&self, visible: bool) {
|
||||
self.surface.set_visible(visible);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ impl ExtSessionLockSurfaceV1 {
|
|||
if let Some(output) = &self.output {
|
||||
if let Some(ls) = output.lock_surface.get() {
|
||||
if ls.node_id == self.node_id {
|
||||
output.lock_surface.take();
|
||||
output.set_lock_surface(None);
|
||||
self.client.state.tree_changed();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ pub struct WlSubsurface {
|
|||
latest_node: CloneCell<Option<NodeRef<StackElement>>>,
|
||||
depth: NumCell<u32>,
|
||||
pub tracker: Tracker<Self>,
|
||||
had_buffer: Cell<bool>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -102,6 +103,7 @@ impl WlSubsurface {
|
|||
latest_node: Default::default(),
|
||||
depth: NumCell::new(0),
|
||||
tracker: Default::default(),
|
||||
had_buffer: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,6 +180,7 @@ impl WlSubsurface {
|
|||
}
|
||||
}
|
||||
self.surface.client.remove_obj(self)?;
|
||||
self.surface.destroy_node();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -344,6 +347,16 @@ impl SurfaceExt for WlSubsurface {
|
|||
self.parent.need_extents_update.set(true);
|
||||
}
|
||||
}
|
||||
let has_buffer = self.surface.buffer.is_some();
|
||||
if self.had_buffer.replace(has_buffer) != has_buffer {
|
||||
if has_buffer {
|
||||
if self.parent.visible.get() {
|
||||
self.surface.set_visible(true);
|
||||
}
|
||||
} else {
|
||||
self.surface.destroy_node();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn subsurface_parent(&self) -> Option<Rc<WlSurface>> {
|
||||
|
|
|
|||
|
|
@ -436,6 +436,10 @@ impl StackedNode for Xwindow {
|
|||
fn stacked_set_visible(&self, visible: bool) {
|
||||
self.tl_set_visible(visible);
|
||||
}
|
||||
|
||||
fn stacked_has_workspace_link(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ impl XdgSurface {
|
|||
|
||||
fn detach_node(&self) {
|
||||
self.workspace.set(None);
|
||||
self.surface.detach_node();
|
||||
self.surface.detach_node(false);
|
||||
let popups = self.popups.lock();
|
||||
for popup in popups.values() {
|
||||
popup.detach_node();
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ pub struct XdgPopup {
|
|||
pos: RefCell<XdgPositioned>,
|
||||
pub tracker: Tracker<Self>,
|
||||
seat_state: NodeSeatState,
|
||||
set_visible_prepared: Cell<bool>,
|
||||
}
|
||||
|
||||
impl Debug for XdgPopup {
|
||||
|
|
@ -77,6 +78,7 @@ impl XdgPopup {
|
|||
pos: RefCell::new(pos),
|
||||
tracker: Default::default(),
|
||||
seat_state: Default::default(),
|
||||
set_visible_prepared: Cell::new(false),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -243,6 +245,7 @@ impl XdgPopup {
|
|||
|
||||
pub fn set_visible(&self, visible: bool) {
|
||||
// log::info!("set visible = {}", visible);
|
||||
self.set_visible_prepared.set(false);
|
||||
self.xdg.set_visible(visible);
|
||||
self.seat_state.set_visible(self, visible);
|
||||
}
|
||||
|
|
@ -340,8 +343,20 @@ impl Node for XdgPopup {
|
|||
impl StackedNode for XdgPopup {
|
||||
stacked_node_impl!();
|
||||
|
||||
fn stacked_prepare_set_visible(&self) {
|
||||
self.set_visible_prepared.set(true);
|
||||
}
|
||||
|
||||
fn stacked_needs_set_visible(&self) -> bool {
|
||||
self.set_visible_prepared.get()
|
||||
}
|
||||
|
||||
fn stacked_set_visible(&self, visible: bool) {
|
||||
self.xdg.set_visible(visible);
|
||||
self.set_visible(visible);
|
||||
}
|
||||
|
||||
fn stacked_has_workspace_link(&self) -> bool {
|
||||
self.workspace_link.borrow().is_some()
|
||||
}
|
||||
|
||||
fn stacked_absolute_position_constrains_input(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -389,6 +389,7 @@ impl XdgToplevel {
|
|||
}
|
||||
self.toplevel_data.detach_node(self);
|
||||
self.xdg.detach_node();
|
||||
self.tl_set_visible(self.state.root_visible());
|
||||
}
|
||||
|
||||
pub fn after_toplevel_drag(self: &Rc<Self>, output: &Rc<OutputNode>, x: i32, y: i32) {
|
||||
|
|
|
|||
|
|
@ -351,6 +351,7 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 {
|
|||
|
||||
fn after_apply_commit(self: Rc<Self>, _pending: &mut PendingState) {
|
||||
let buffer_is_some = self.surface.buffer.is_some();
|
||||
let was_mapped = self.mapped.get();
|
||||
if self.mapped.get() {
|
||||
if !buffer_is_some {
|
||||
self.destroy_node();
|
||||
|
|
@ -367,6 +368,9 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 {
|
|||
self.mapped.set(true);
|
||||
self.compute_position();
|
||||
}
|
||||
if self.mapped.get() != was_mapped {
|
||||
self.output.update_visible();
|
||||
}
|
||||
if self.mapped.get() {
|
||||
match self.keyboard_interactivity.get() {
|
||||
KI_NONE => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue