Skip to content

Commit

Permalink
tree: make surface visibility tracking more robust
Browse files Browse the repository at this point in the history
  • Loading branch information
mahkoh committed Mar 29, 2024
1 parent be0935c commit ba98103
Show file tree
Hide file tree
Showing 26 changed files with 310 additions and 141 deletions.
4 changes: 3 additions & 1 deletion src/backends/metal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,9 @@ impl Backend for MetalBackend {
return;
}
}
if !idle {
if idle {
self.state.set_backend_idle(true);
} else {
for device in devices.values() {
for connector in device.connectors.lock().values() {
connector.schedule_present();
Expand Down
7 changes: 5 additions & 2 deletions src/backends/metal/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,11 @@ impl MetalConnector {
async fn present_loop(self: Rc<Self>) {
loop {
self.present_trigger.triggered().await;
if let Err(e) = self.present(true) {
log::error!("Could not present: {}", ErrorFmt(e));
match self.present(true) {
Ok(_) => self.state.set_backend_idle(false),
Err(e) => {
log::error!("Could not present: {}", ErrorFmt(e));
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/backends/x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,8 @@ impl XBackend {
log::error!("Could not present image: {:?}", e);
return;
}

self.state.set_backend_idle(false);
}

async fn handle_input_event(self: &Rc<Self>, event: &Event) -> Result<(), XBackendError> {
Expand Down
1 change: 1 addition & 0 deletions src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ fn start_compositor2(
timeout_changed: Default::default(),
inhibitors: Default::default(),
inhibitors_changed: Default::default(),
backend_idle: Cell::new(true),
},
run_args,
xwayland: XWaylandState {
Expand Down
4 changes: 4 additions & 0 deletions src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ pub trait Cursor {
fn time_until_tick(&self) -> Duration {
Duration::new(0, 0)
}

fn set_visible(&self, visible: bool) {
let _ = visible;
}
}

pub struct ServerCursors {
Expand Down
4 changes: 2 additions & 2 deletions src/ifs/ext_session_lock_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/ifs/jay_compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/ifs/wl_seat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions src/ifs/wl_seat/pointer_owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
35 changes: 26 additions & 9 deletions src/ifs/wl_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>>,
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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();
Expand All @@ -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();
}
Expand All @@ -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() {
Expand All @@ -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>) {
Expand Down Expand Up @@ -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! {
Expand Down
11 changes: 11 additions & 0 deletions src/ifs/wl_surface/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
2 changes: 1 addition & 1 deletion src/ifs/wl_surface/ext_session_lock_surface_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/ifs/wl_surface/wl_subsurface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -102,6 +103,7 @@ impl WlSubsurface {
latest_node: Default::default(),
depth: NumCell::new(0),
tracker: Default::default(),
had_buffer: Cell::new(false),
}
}

Expand Down Expand Up @@ -178,6 +180,7 @@ impl WlSubsurface {
}
}
self.surface.client.remove_obj(self)?;
self.surface.destroy_node();
Ok(())
}

Expand Down Expand Up @@ -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>> {
Expand Down
4 changes: 4 additions & 0 deletions src/ifs/wl_surface/x_surface/xwindow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
2 changes: 1 addition & 1 deletion src/ifs/wl_surface/xdg_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
17 changes: 16 additions & 1 deletion src/ifs/wl_surface/xdg_surface/xdg_popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -77,6 +78,7 @@ impl XdgPopup {
pos: RefCell::new(pos),
tracker: Default::default(),
seat_state: Default::default(),
set_visible_prepared: Cell::new(false),
})
}

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions src/ifs/wl_surface/zwlr_layer_surface_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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 => {
Expand Down
1 change: 1 addition & 0 deletions src/it/test_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub struct TestBackend {

impl TestBackend {
pub fn new(state: &Rc<State>, future: TestFuture) -> Self {
state.set_backend_idle(false);
let default_connector = Rc::new(TestConnector {
id: state.connector_ids.next(),
kernel_id: ConnectorKernelId {
Expand Down
Loading

0 comments on commit ba98103

Please sign in to comment.