1
0
Fork 0
forked from wry/wry

Merge pull request #588 from mahkoh/jorth/effective-geometry

xdg-toplevel: center fullscreen surfaces with geometry smaller than o…
This commit is contained in:
mahkoh 2025-09-01 15:38:40 +02:00 committed by GitHub
commit fbef86e928
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 81 additions and 26 deletions

View file

@ -301,6 +301,7 @@ pub struct WlSurface {
pub extents: Cell<Rect>,
pub buffer_abs_pos: Cell<Rect>,
pub need_extents_update: Cell<bool>,
need_extents_propagation: Cell<bool>,
pub buffer: CloneCell<Option<Rc<SurfaceBuffer>>>,
pub shm_staging: CloneCell<Option<Rc<dyn GfxStagingBuffer>>>,
pub shm_textures: DoubleBuffered<SurfaceShmTexture>,
@ -650,6 +651,7 @@ impl WlSurface {
extents: Default::default(),
buffer_abs_pos: Cell::new(Default::default()),
need_extents_update: Default::default(),
need_extents_propagation: Default::default(),
buffer: Default::default(),
shm_staging: Default::default(),
shm_textures: DoubleBuffered::new(DamageQueue::new().map(|damage| SurfaceShmTexture {
@ -904,7 +906,7 @@ impl WlSurface {
self.ext.set(self.client.state.none_surface_ext.clone());
}
fn calculate_extents(&self) {
fn calculate_extents(&self, propagate: bool) {
let old_extents = self.extents.get();
let mut extents = self.buffer_abs_pos.get().at_point(0, 0);
let children = self.children.borrow();
@ -925,7 +927,11 @@ impl WlSurface {
self.extents.set(extents);
self.need_extents_update.set(false);
if old_extents != extents {
self.ext.get().extents_changed()
if propagate {
self.ext.get().extents_changed()
} else {
self.need_extents_propagation.set(true);
}
}
}
@ -1398,7 +1404,7 @@ impl WlSurface {
.push(XWaylandEvent::SurfaceSerialAssigned(self.id));
}
if self.need_extents_update.get() {
self.calculate_extents();
self.calculate_extents(false);
}
if buffer_changed || transform_changed || alpha_changed {
for (_, cursor) in &self.cursors {
@ -1461,6 +1467,9 @@ impl WlSurface {
{
self.output.get().update_presentation_type();
}
if self.need_extents_propagation.take() {
self.ext.get().extents_changed();
}
self.commit_version.fetch_add(1);
Ok(())
}

View file

@ -308,7 +308,7 @@ impl WlSubsurfaceRequestHandler for WlSubsurface {
if !parent.need_extents_update.get() {
break;
}
parent.calculate_extents();
parent.calculate_extents(true);
parent_opt = parent.ext.get().subsurface_parent();
}
}

View file

@ -24,6 +24,7 @@ use {
WorkspaceNode,
},
utils::{
cell_ext::CellExt,
clonecell::CloneCell,
copyhashmap::CopyHashMap,
hash_map_ext::HashMapExt,
@ -90,6 +91,7 @@ pub struct XdgSurface {
acked_serial: Cell<Option<u32>>,
geometry: Cell<Option<Rect>>,
extents: Cell<Rect>,
effective_geometry: Cell<Rect>,
pub absolute_desired_extents: Cell<Rect>,
ext: CloneCell<Option<Rc<dyn XdgSurfaceExt>>>,
popup_display_stack: CloneCell<Rc<LinkedList<Rc<dyn StackedNode>>>>,
@ -231,6 +233,10 @@ pub trait XdgSurfaceExt: Debug {
None
}
fn effective_geometry(&self, geometry: Rect) -> Rect {
geometry
}
fn make_visible(self: Rc<Self>);
fn node_layer(&self) -> NodeLayerLink;
@ -247,6 +253,7 @@ impl XdgSurface {
acked_serial: Cell::new(None),
geometry: Cell::new(None),
extents: Cell::new(surface.extents.get()),
effective_geometry: Default::default(),
absolute_desired_extents: Cell::new(Default::default()),
ext: Default::default(),
popup_display_stack: CloneCell::new(surface.client.state.root.stacked.clone()),
@ -262,10 +269,9 @@ impl XdgSurface {
fn update_surface_position(&self) {
let (mut x1, mut y1) = self.absolute_desired_extents.get().position();
if let Some(geo) = self.geometry.get() {
x1 -= geo.x1();
y1 -= geo.y1();
}
let geo = self.effective_geometry.get();
x1 -= geo.x1();
y1 -= geo.y1();
self.surface.set_absolute_position(x1, y1);
self.update_popup_positions();
}
@ -336,8 +342,8 @@ impl XdgSurface {
self.surface.client.state.damage(extents.move_(x, y));
}
pub fn geometry(&self) -> Option<Rect> {
self.geometry.get()
pub fn geometry(&self) -> Rect {
self.effective_geometry.get()
}
pub fn schedule_configure(self: &Rc<Self>) {
@ -512,6 +518,24 @@ impl XdgSurfaceRequestHandler for XdgSurface {
}
impl XdgSurface {
fn update_effective_geometry(&self) {
let geometry = self
.geometry
.get()
.unwrap_or_else(|| self.surface.extents.get());
let mut effective_geometry = geometry;
let ext = self.ext.get();
if let Some(ext) = &ext {
effective_geometry = ext.effective_geometry(geometry);
}
if self.effective_geometry.replace(effective_geometry) != effective_geometry {
self.update_surface_position();
if let Some(ext) = &ext {
ext.geometry_changed();
}
}
}
fn update_extents(&self) {
let old_extents = self.extents.get();
let mut new_extents = self.surface.extents.get();
@ -519,19 +543,19 @@ impl XdgSurface {
new_extents = new_extents.intersect(geometry);
}
self.extents.set(new_extents);
if old_extents != new_extents
&& let Some(ext) = self.ext.get()
{
ext.extents_changed();
if old_extents != new_extents {
if self.geometry.is_none() {
self.update_effective_geometry();
}
if let Some(ext) = self.ext.get() {
ext.extents_changed();
}
}
}
fn find_tree_at(&self, mut x: i32, mut y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
if let Some(geo) = self.geometry.get() {
let (xt, yt) = geo.translate_inv(x, y);
x = xt;
y = yt;
}
let geo = self.effective_geometry.get();
(x, y) = geo.translate_inv(x, y);
self.surface.find_tree_at_(x, y, tree)
}
@ -604,11 +628,8 @@ impl SurfaceExt for XdgSurface {
{
let prev = self.geometry.replace(Some(geometry));
if prev != Some(geometry) {
self.update_effective_geometry();
self.update_extents();
self.update_surface_position();
if let Some(ext) = self.ext.get() {
ext.geometry_changed();
}
}
}
Ok(())

View file

@ -746,6 +746,10 @@ impl ToplevelNodeBase for XdgToplevel {
) -> Option<TileDragDestination> {
default_tile_drag_destination(self, source, split, abs_bounds, x, y)
}
fn tl_mark_fullscreen_ext(&self) {
self.xdg.update_effective_geometry();
}
}
impl XdgSurfaceExt for XdgToplevel {
@ -776,6 +780,23 @@ impl XdgSurfaceExt for XdgToplevel {
.damage(self.node_absolute_position());
}
fn effective_geometry(&self, geometry: Rect) -> Rect {
if !self.toplevel_data.is_fullscreen.get() {
return geometry;
}
let output = self
.toplevel_data
.output()
.node_absolute_position()
.at_point(0, 0);
let x_overflow = output.width() - geometry.width();
let y_overflow = output.height() - geometry.height();
output.at_point(
geometry.x1() - x_overflow / 2,
geometry.y1() - y_overflow / 2,
)
}
fn make_visible(self: Rc<Self>) {
self.node_make_visible();
}

View file

@ -338,9 +338,8 @@ impl Renderer<'_> {
bounds: Option<&Rect>,
) {
let surface = &xdg.surface;
if let Some(geo) = xdg.geometry() {
(x, y) = geo.translate(x, y);
}
let geo = xdg.geometry();
(x, y) = geo.translate(x, y);
self.render_surface(surface, x, y, bounds);
}

View file

@ -247,6 +247,7 @@ impl<T: ToplevelNodeBase> ToplevelNode for T {
fn tl_mark_fullscreen(&self, fullscreen: bool) {
self.tl_data().is_fullscreen.set(fullscreen);
self.tl_mark_ancestor_fullscreen(fullscreen);
self.tl_mark_fullscreen_ext();
}
}
@ -315,6 +316,10 @@ pub trait ToplevelNodeBase: Node {
fn tl_mark_ancestor_fullscreen_ext(&self, fullscreen: bool) {
let _ = fullscreen;
}
fn tl_mark_fullscreen_ext(&self) {
// nothing
}
}
pub struct FullscreenedData {