accepts_input_at rejects buffer-less surfaces
This commit is contained in:
parent
bb43c238e3
commit
12adb678bb
1 changed files with 48 additions and 2 deletions
|
|
@ -318,7 +318,7 @@ pub struct WlSurface {
|
|||
pub content_type: Cell<Option<ContentType>>,
|
||||
pub drm_feedback: CopyHashMap<ZwpLinuxDmabufFeedbackV1Id, Rc<ZwpLinuxDmabufFeedbackV1>>,
|
||||
syncobj_surface: CloneCell<Option<Rc<WpLinuxDrmSyncobjSurfaceV1>>>,
|
||||
destroyed: Cell<bool>,
|
||||
pub destroyed: Cell<bool>,
|
||||
commit_timeline: CommitTimeline,
|
||||
alpha_modifier: CloneCell<Option<Rc<WpAlphaModifierSurfaceV1>>>,
|
||||
alpha: Cell<Option<f32>>,
|
||||
|
|
@ -1019,6 +1019,7 @@ impl WlSurfaceRequestHandler for WlSurface {
|
|||
self.unset_dnd_icons();
|
||||
self.unset_cursors();
|
||||
self.ext.get().on_surface_destroy()?;
|
||||
self.destroyed.set(true);
|
||||
self.destroy_node();
|
||||
{
|
||||
let mut children = self.children.borrow_mut();
|
||||
|
|
@ -1029,6 +1030,19 @@ impl WlSurfaceRequestHandler for WlSurface {
|
|||
}
|
||||
*children = None;
|
||||
}
|
||||
// Capture a close-animation snapshot if the client is destroying the
|
||||
// surface while it still has a buffer (i.e. without a clean null-attach
|
||||
// commit first — typical for crash/disconnect paths).
|
||||
if self.buffer.is_some()
|
||||
&& let Some(tl) = self.toplevel.get()
|
||||
&& let Some(snap) = crate::animation::capture_snapshot(&self.client.state, &tl)
|
||||
{
|
||||
self.client
|
||||
.state
|
||||
.close_snapshots
|
||||
.borrow_mut()
|
||||
.push(Rc::new(snap));
|
||||
}
|
||||
self.buffer.set(None);
|
||||
self.reset_shm_textures();
|
||||
if let Some(xwayland_serial) = self.xwayland_serial.get() {
|
||||
|
|
@ -1041,7 +1055,6 @@ impl WlSurfaceRequestHandler for WlSurface {
|
|||
self.client.remove_obj(self)?;
|
||||
self.idle_inhibitors.clear();
|
||||
self.constraints.take();
|
||||
self.destroyed.set(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -1238,8 +1251,24 @@ impl WlSurface {
|
|||
let mut buffer_changed = false;
|
||||
let mut old_raw_size = None;
|
||||
let (mut dx, mut dy) = mem::take(&mut pending.offset);
|
||||
let mut buffer_presence_changed = false;
|
||||
if let Some(buffer_change) = pending.buffer.take() {
|
||||
buffer_changed = true;
|
||||
buffer_presence_changed = buffer_change.is_some() != self.buffer.is_some();
|
||||
// If the client just attached a null buffer to the main surface of
|
||||
// a mapped toplevel, capture a snapshot before we drop the buffer
|
||||
// so the close animation has something to render after teardown.
|
||||
if buffer_change.is_none()
|
||||
&& self.buffer.is_some()
|
||||
&& let Some(tl) = self.toplevel.get()
|
||||
&& let Some(snap) = crate::animation::capture_snapshot(&self.client.state, &tl)
|
||||
{
|
||||
self.client
|
||||
.state
|
||||
.close_snapshots
|
||||
.borrow_mut()
|
||||
.push(Rc::new(snap));
|
||||
}
|
||||
if let Some(buffer) = self.buffer.take() {
|
||||
old_raw_size = Some(buffer.buffer.buf.rect);
|
||||
}
|
||||
|
|
@ -1408,6 +1437,16 @@ impl WlSurface {
|
|||
};
|
||||
self.is_opaque.set(is_opaque);
|
||||
}
|
||||
if buffer_abs_pos_size_changed || buffer_presence_changed {
|
||||
// Pointer focus depends on whether this surface accepts input.
|
||||
// It just changed (size shrank/grew, or buffer went from null to
|
||||
// non-null or vice versa — the latter happens when a client
|
||||
// dismisses a subsurface by null-attaching while keeping its
|
||||
// wp_viewport destination). Force a re-evaluation so the pointer
|
||||
// stack doesn't keep a now-invisible surface focused until the
|
||||
// next motion event.
|
||||
self.client.state.tree_changed();
|
||||
}
|
||||
let mut tearing_changed = false;
|
||||
if let Some(tearing) = pending.tearing.take()
|
||||
&& self.tearing.replace(tearing) != tearing
|
||||
|
|
@ -1597,6 +1636,13 @@ impl WlSurface {
|
|||
}
|
||||
|
||||
fn accepts_input_at(&self, mut x: i32, mut y: i32) -> bool {
|
||||
// Per the wayland spec, a surface without a buffer is invisible and
|
||||
// cannot receive input. Without this check, a client that null-buffers
|
||||
// but keeps a wp_viewport destination set (as foot does for its
|
||||
// fractional-scaling subsurfaces) would keep an invisible hit-rect.
|
||||
if self.buffer.is_none() {
|
||||
return false;
|
||||
}
|
||||
let rect = self.buffer_abs_pos.get().at_point(0, 0);
|
||||
if !rect.contains(x, y) {
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue