xdg-toplevel: center fullscreen surfaces with geometry smaller than output
This commit is contained in:
parent
642eaffcff
commit
197b069c50
6 changed files with 81 additions and 26 deletions
|
|
@ -301,6 +301,7 @@ pub struct WlSurface {
|
||||||
pub extents: Cell<Rect>,
|
pub extents: Cell<Rect>,
|
||||||
pub buffer_abs_pos: Cell<Rect>,
|
pub buffer_abs_pos: Cell<Rect>,
|
||||||
pub need_extents_update: Cell<bool>,
|
pub need_extents_update: Cell<bool>,
|
||||||
|
need_extents_propagation: Cell<bool>,
|
||||||
pub buffer: CloneCell<Option<Rc<SurfaceBuffer>>>,
|
pub buffer: CloneCell<Option<Rc<SurfaceBuffer>>>,
|
||||||
pub shm_staging: CloneCell<Option<Rc<dyn GfxStagingBuffer>>>,
|
pub shm_staging: CloneCell<Option<Rc<dyn GfxStagingBuffer>>>,
|
||||||
pub shm_textures: DoubleBuffered<SurfaceShmTexture>,
|
pub shm_textures: DoubleBuffered<SurfaceShmTexture>,
|
||||||
|
|
@ -650,6 +651,7 @@ impl WlSurface {
|
||||||
extents: Default::default(),
|
extents: Default::default(),
|
||||||
buffer_abs_pos: Cell::new(Default::default()),
|
buffer_abs_pos: Cell::new(Default::default()),
|
||||||
need_extents_update: Default::default(),
|
need_extents_update: Default::default(),
|
||||||
|
need_extents_propagation: Default::default(),
|
||||||
buffer: Default::default(),
|
buffer: Default::default(),
|
||||||
shm_staging: Default::default(),
|
shm_staging: Default::default(),
|
||||||
shm_textures: DoubleBuffered::new(DamageQueue::new().map(|damage| SurfaceShmTexture {
|
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());
|
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 old_extents = self.extents.get();
|
||||||
let mut extents = self.buffer_abs_pos.get().at_point(0, 0);
|
let mut extents = self.buffer_abs_pos.get().at_point(0, 0);
|
||||||
let children = self.children.borrow();
|
let children = self.children.borrow();
|
||||||
|
|
@ -925,7 +927,11 @@ impl WlSurface {
|
||||||
self.extents.set(extents);
|
self.extents.set(extents);
|
||||||
self.need_extents_update.set(false);
|
self.need_extents_update.set(false);
|
||||||
if old_extents != extents {
|
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));
|
.push(XWaylandEvent::SurfaceSerialAssigned(self.id));
|
||||||
}
|
}
|
||||||
if self.need_extents_update.get() {
|
if self.need_extents_update.get() {
|
||||||
self.calculate_extents();
|
self.calculate_extents(false);
|
||||||
}
|
}
|
||||||
if buffer_changed || transform_changed || alpha_changed {
|
if buffer_changed || transform_changed || alpha_changed {
|
||||||
for (_, cursor) in &self.cursors {
|
for (_, cursor) in &self.cursors {
|
||||||
|
|
@ -1461,6 +1467,9 @@ impl WlSurface {
|
||||||
{
|
{
|
||||||
self.output.get().update_presentation_type();
|
self.output.get().update_presentation_type();
|
||||||
}
|
}
|
||||||
|
if self.need_extents_propagation.take() {
|
||||||
|
self.ext.get().extents_changed();
|
||||||
|
}
|
||||||
self.commit_version.fetch_add(1);
|
self.commit_version.fetch_add(1);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,7 @@ impl WlSubsurfaceRequestHandler for WlSubsurface {
|
||||||
if !parent.need_extents_update.get() {
|
if !parent.need_extents_update.get() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
parent.calculate_extents();
|
parent.calculate_extents(true);
|
||||||
parent_opt = parent.ext.get().subsurface_parent();
|
parent_opt = parent.ext.get().subsurface_parent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ use {
|
||||||
WorkspaceNode,
|
WorkspaceNode,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
|
cell_ext::CellExt,
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
copyhashmap::CopyHashMap,
|
copyhashmap::CopyHashMap,
|
||||||
hash_map_ext::HashMapExt,
|
hash_map_ext::HashMapExt,
|
||||||
|
|
@ -90,6 +91,7 @@ pub struct XdgSurface {
|
||||||
acked_serial: Cell<Option<u32>>,
|
acked_serial: Cell<Option<u32>>,
|
||||||
geometry: Cell<Option<Rect>>,
|
geometry: Cell<Option<Rect>>,
|
||||||
extents: Cell<Rect>,
|
extents: Cell<Rect>,
|
||||||
|
effective_geometry: Cell<Rect>,
|
||||||
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>>>>,
|
||||||
|
|
@ -231,6 +233,10 @@ pub trait XdgSurfaceExt: Debug {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn effective_geometry(&self, geometry: Rect) -> Rect {
|
||||||
|
geometry
|
||||||
|
}
|
||||||
|
|
||||||
fn make_visible(self: Rc<Self>);
|
fn make_visible(self: Rc<Self>);
|
||||||
|
|
||||||
fn node_layer(&self) -> NodeLayerLink;
|
fn node_layer(&self) -> NodeLayerLink;
|
||||||
|
|
@ -247,6 +253,7 @@ impl XdgSurface {
|
||||||
acked_serial: Cell::new(None),
|
acked_serial: Cell::new(None),
|
||||||
geometry: Cell::new(None),
|
geometry: Cell::new(None),
|
||||||
extents: Cell::new(surface.extents.get()),
|
extents: Cell::new(surface.extents.get()),
|
||||||
|
effective_geometry: Default::default(),
|
||||||
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()),
|
||||||
|
|
@ -262,10 +269,9 @@ impl XdgSurface {
|
||||||
|
|
||||||
fn update_surface_position(&self) {
|
fn update_surface_position(&self) {
|
||||||
let (mut x1, mut y1) = self.absolute_desired_extents.get().position();
|
let (mut x1, mut y1) = self.absolute_desired_extents.get().position();
|
||||||
if let Some(geo) = self.geometry.get() {
|
let geo = self.effective_geometry.get();
|
||||||
x1 -= geo.x1();
|
x1 -= geo.x1();
|
||||||
y1 -= geo.y1();
|
y1 -= geo.y1();
|
||||||
}
|
|
||||||
self.surface.set_absolute_position(x1, y1);
|
self.surface.set_absolute_position(x1, y1);
|
||||||
self.update_popup_positions();
|
self.update_popup_positions();
|
||||||
}
|
}
|
||||||
|
|
@ -336,8 +342,8 @@ impl XdgSurface {
|
||||||
self.surface.client.state.damage(extents.move_(x, y));
|
self.surface.client.state.damage(extents.move_(x, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn geometry(&self) -> Option<Rect> {
|
pub fn geometry(&self) -> Rect {
|
||||||
self.geometry.get()
|
self.effective_geometry.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn schedule_configure(self: &Rc<Self>) {
|
pub fn schedule_configure(self: &Rc<Self>) {
|
||||||
|
|
@ -512,6 +518,24 @@ impl XdgSurfaceRequestHandler for XdgSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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) {
|
fn update_extents(&self) {
|
||||||
let old_extents = self.extents.get();
|
let old_extents = self.extents.get();
|
||||||
let mut new_extents = self.surface.extents.get();
|
let mut new_extents = self.surface.extents.get();
|
||||||
|
|
@ -519,19 +543,19 @@ impl XdgSurface {
|
||||||
new_extents = new_extents.intersect(geometry);
|
new_extents = new_extents.intersect(geometry);
|
||||||
}
|
}
|
||||||
self.extents.set(new_extents);
|
self.extents.set(new_extents);
|
||||||
if old_extents != new_extents
|
if old_extents != new_extents {
|
||||||
&& let Some(ext) = self.ext.get()
|
if self.geometry.is_none() {
|
||||||
{
|
self.update_effective_geometry();
|
||||||
ext.extents_changed();
|
}
|
||||||
|
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 {
|
fn find_tree_at(&self, mut x: i32, mut y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
||||||
if let Some(geo) = self.geometry.get() {
|
let geo = self.effective_geometry.get();
|
||||||
let (xt, yt) = geo.translate_inv(x, y);
|
(x, y) = geo.translate_inv(x, y);
|
||||||
x = xt;
|
|
||||||
y = yt;
|
|
||||||
}
|
|
||||||
self.surface.find_tree_at_(x, y, tree)
|
self.surface.find_tree_at_(x, y, tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -604,11 +628,8 @@ impl SurfaceExt for XdgSurface {
|
||||||
{
|
{
|
||||||
let prev = self.geometry.replace(Some(geometry));
|
let prev = self.geometry.replace(Some(geometry));
|
||||||
if prev != Some(geometry) {
|
if prev != Some(geometry) {
|
||||||
|
self.update_effective_geometry();
|
||||||
self.update_extents();
|
self.update_extents();
|
||||||
self.update_surface_position();
|
|
||||||
if let Some(ext) = self.ext.get() {
|
|
||||||
ext.geometry_changed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -746,6 +746,10 @@ impl ToplevelNodeBase for XdgToplevel {
|
||||||
) -> Option<TileDragDestination> {
|
) -> Option<TileDragDestination> {
|
||||||
default_tile_drag_destination(self, source, split, abs_bounds, x, y)
|
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 {
|
impl XdgSurfaceExt for XdgToplevel {
|
||||||
|
|
@ -776,6 +780,23 @@ impl XdgSurfaceExt for XdgToplevel {
|
||||||
.damage(self.node_absolute_position());
|
.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>) {
|
fn make_visible(self: Rc<Self>) {
|
||||||
self.node_make_visible();
|
self.node_make_visible();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -338,9 +338,8 @@ impl Renderer<'_> {
|
||||||
bounds: Option<&Rect>,
|
bounds: Option<&Rect>,
|
||||||
) {
|
) {
|
||||||
let surface = &xdg.surface;
|
let surface = &xdg.surface;
|
||||||
if let Some(geo) = xdg.geometry() {
|
let geo = xdg.geometry();
|
||||||
(x, y) = geo.translate(x, y);
|
(x, y) = geo.translate(x, y);
|
||||||
}
|
|
||||||
self.render_surface(surface, x, y, bounds);
|
self.render_surface(surface, x, y, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,7 @@ impl<T: ToplevelNodeBase> ToplevelNode for T {
|
||||||
fn tl_mark_fullscreen(&self, fullscreen: bool) {
|
fn tl_mark_fullscreen(&self, fullscreen: bool) {
|
||||||
self.tl_data().is_fullscreen.set(fullscreen);
|
self.tl_data().is_fullscreen.set(fullscreen);
|
||||||
self.tl_mark_ancestor_fullscreen(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) {
|
fn tl_mark_ancestor_fullscreen_ext(&self, fullscreen: bool) {
|
||||||
let _ = fullscreen;
|
let _ = fullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tl_mark_fullscreen_ext(&self) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FullscreenedData {
|
pub struct FullscreenedData {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue