Merge pull request #689 from mahkoh/jorth/xdg-initial-commit-state
xdg-shell: make acked serial part of the pending state
This commit is contained in:
commit
3a4ca4defe
7 changed files with 85 additions and 36 deletions
|
|
@ -486,6 +486,7 @@ struct PendingState {
|
||||||
commit_time: Option<u64>,
|
commit_time: Option<u64>,
|
||||||
tray_item_ack_serial: Option<u32>,
|
tray_item_ack_serial: Option<u32>,
|
||||||
color_description: Option<Option<Rc<ColorDescription>>>,
|
color_description: Option<Option<Rc<ColorDescription>>>,
|
||||||
|
serial: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AttachedSubsurfaceState {
|
struct AttachedSubsurfaceState {
|
||||||
|
|
@ -539,6 +540,7 @@ impl PendingState {
|
||||||
opt!(commit_time);
|
opt!(commit_time);
|
||||||
opt!(tray_item_ack_serial);
|
opt!(tray_item_ack_serial);
|
||||||
opt!(color_description);
|
opt!(color_description);
|
||||||
|
opt!(serial);
|
||||||
{
|
{
|
||||||
let (dx1, dy1) = self.offset;
|
let (dx1, dy1) = self.offset;
|
||||||
let (dx2, dy2) = mem::take(&mut next.offset);
|
let (dx2, dy2) = mem::take(&mut next.offset);
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,9 @@ pub struct XdgSurface {
|
||||||
base: Rc<XdgWmBase>,
|
base: Rc<XdgWmBase>,
|
||||||
role: Cell<XdgSurfaceRole>,
|
role: Cell<XdgSurfaceRole>,
|
||||||
pub surface: Rc<WlSurface>,
|
pub surface: Rc<WlSurface>,
|
||||||
requested_serial: NumCell<u32>,
|
requested_serial: NumCell<u64>,
|
||||||
acked_serial: Cell<Option<u32>>,
|
acked_serial: Cell<u64>,
|
||||||
|
applied_serial: Cell<u64>,
|
||||||
geometry: Cell<Option<Rect>>,
|
geometry: Cell<Option<Rect>>,
|
||||||
extents: Cell<Rect>,
|
extents: Cell<Rect>,
|
||||||
effective_geometry: Cell<Rect>,
|
effective_geometry: Cell<Rect>,
|
||||||
|
|
@ -99,11 +100,19 @@ pub struct XdgSurface {
|
||||||
popups: CopyHashMap<XdgPopupId, Rc<Popup>>,
|
popups: CopyHashMap<XdgPopupId, Rc<Popup>>,
|
||||||
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
||||||
pub tracker: Tracker<Self>,
|
pub tracker: Tracker<Self>,
|
||||||
have_initial_commit: Cell<bool>,
|
initial_commit_state: Cell<InitialCommitState>,
|
||||||
configure_scheduled: Cell<bool>,
|
configure_scheduled: Cell<bool>,
|
||||||
destroyed: Cell<bool>,
|
destroyed: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
|
||||||
|
enum InitialCommitState {
|
||||||
|
#[default]
|
||||||
|
Unmapped,
|
||||||
|
Sent,
|
||||||
|
Mapped,
|
||||||
|
}
|
||||||
|
|
||||||
struct Popup {
|
struct Popup {
|
||||||
parent: Rc<XdgSurface>,
|
parent: Rc<XdgSurface>,
|
||||||
popup: Rc<XdgPopup>,
|
popup: Rc<XdgPopup>,
|
||||||
|
|
@ -209,8 +218,8 @@ impl PendingXdgSurfaceData {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait XdgSurfaceExt: Debug {
|
pub trait XdgSurfaceExt: Debug {
|
||||||
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
|
fn initial_configure(self: Rc<Self>) {
|
||||||
Ok(())
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_commit(self: Rc<Self>) {
|
fn post_commit(self: Rc<Self>) {
|
||||||
|
|
@ -250,7 +259,8 @@ impl XdgSurface {
|
||||||
role: Cell::new(XdgSurfaceRole::None),
|
role: Cell::new(XdgSurfaceRole::None),
|
||||||
surface: surface.clone(),
|
surface: surface.clone(),
|
||||||
requested_serial: NumCell::new(1),
|
requested_serial: NumCell::new(1),
|
||||||
acked_serial: Cell::new(None),
|
acked_serial: Cell::new(0),
|
||||||
|
applied_serial: Cell::new(0),
|
||||||
geometry: Cell::new(None),
|
geometry: Cell::new(None),
|
||||||
extents: Cell::new(surface.extents.get()),
|
extents: Cell::new(surface.extents.get()),
|
||||||
effective_geometry: Default::default(),
|
effective_geometry: Default::default(),
|
||||||
|
|
@ -261,7 +271,7 @@ impl XdgSurface {
|
||||||
popups: Default::default(),
|
popups: Default::default(),
|
||||||
workspace: Default::default(),
|
workspace: Default::default(),
|
||||||
tracker: Default::default(),
|
tracker: Default::default(),
|
||||||
have_initial_commit: Default::default(),
|
initial_commit_state: Default::default(),
|
||||||
configure_scheduled: Default::default(),
|
configure_scheduled: Default::default(),
|
||||||
destroyed: Default::default(),
|
destroyed: Default::default(),
|
||||||
}
|
}
|
||||||
|
|
@ -350,17 +360,34 @@ impl XdgSurface {
|
||||||
if self.configure_scheduled.replace(true) {
|
if self.configure_scheduled.replace(true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let serial = self.requested_serial.add_fetch(1);
|
|
||||||
self.surface
|
self.surface
|
||||||
.client
|
.client
|
||||||
.state
|
.state
|
||||||
.xdg_surface_configure_events
|
.xdg_surface_configure_events
|
||||||
.push(XdgSurfaceConfigureEvent {
|
.push(XdgSurfaceConfigureEvent {
|
||||||
xdg: self.clone(),
|
xdg: self.clone(),
|
||||||
serial,
|
serial: self.next_serial() as _,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn next_serial(&self) -> u64 {
|
||||||
|
let mut serial = self.requested_serial.add_fetch(1);
|
||||||
|
if serial as u32 == 0 {
|
||||||
|
serial = self.requested_serial.add_fetch(1);
|
||||||
|
}
|
||||||
|
serial
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_serial(&self, serial: u32) -> u64 {
|
||||||
|
let max = self.requested_serial.get();
|
||||||
|
let mask = u32::MAX as u64;
|
||||||
|
let mut serial = max & !mask | (serial as u64);
|
||||||
|
if serial > max {
|
||||||
|
serial = serial.saturating_sub(mask + 1);
|
||||||
|
}
|
||||||
|
serial
|
||||||
|
}
|
||||||
|
|
||||||
pub fn send_configure(&self, serial: u32) {
|
pub fn send_configure(&self, serial: u32) {
|
||||||
self.surface.client.event(Configure {
|
self.surface.client.event(Configure {
|
||||||
self_id: self.id,
|
self_id: self.id,
|
||||||
|
|
@ -510,9 +537,13 @@ impl XdgSurfaceRequestHandler for XdgSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ack_configure(&self, req: AckConfigure, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
fn ack_configure(&self, req: AckConfigure, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
if self.requested_serial.get() == req.serial {
|
let serial = self.map_serial(req.serial);
|
||||||
self.acked_serial.set(Some(req.serial));
|
let last = self.acked_serial.get();
|
||||||
|
if serial <= last {
|
||||||
|
return Err(XdgSurfaceError::InvalidSerial(serial, last));
|
||||||
}
|
}
|
||||||
|
self.acked_serial.set(serial);
|
||||||
|
self.surface.pending.borrow_mut().serial = Some(serial);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -616,26 +647,41 @@ impl SurfaceExt for XdgSurface {
|
||||||
self: Rc<Self>,
|
self: Rc<Self>,
|
||||||
pending: &mut PendingState,
|
pending: &mut PendingState,
|
||||||
) -> Result<(), WlSurfaceError> {
|
) -> Result<(), WlSurfaceError> {
|
||||||
if !self.have_initial_commit.get()
|
if let Some(pending) = &mut pending.xdg_surface {
|
||||||
&& let Some(ext) = self.ext.get()
|
if let Some(geometry) = pending.geometry.take() {
|
||||||
{
|
let prev = self.geometry.replace(Some(geometry));
|
||||||
ext.initial_configure()?;
|
if prev != Some(geometry) {
|
||||||
self.schedule_configure();
|
self.update_effective_geometry();
|
||||||
self.have_initial_commit.set(true);
|
self.update_extents();
|
||||||
}
|
}
|
||||||
if let Some(pending) = &mut pending.xdg_surface
|
|
||||||
&& let Some(geometry) = pending.geometry.take()
|
|
||||||
{
|
|
||||||
let prev = self.geometry.replace(Some(geometry));
|
|
||||||
if prev != Some(geometry) {
|
|
||||||
self.update_effective_geometry();
|
|
||||||
self.update_extents();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(serial) = pending.serial.take() {
|
||||||
|
self.applied_serial.set(serial);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after_apply_commit(self: Rc<Self>) {
|
fn after_apply_commit(self: Rc<Self>) {
|
||||||
|
match self.initial_commit_state.get() {
|
||||||
|
InitialCommitState::Unmapped => {
|
||||||
|
if let Some(ext) = self.ext.get() {
|
||||||
|
ext.initial_configure();
|
||||||
|
self.schedule_configure();
|
||||||
|
self.initial_commit_state.set(InitialCommitState::Sent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InitialCommitState::Sent => {
|
||||||
|
if self.surface.buffer.is_some() {
|
||||||
|
self.initial_commit_state.set(InitialCommitState::Mapped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InitialCommitState::Mapped => {
|
||||||
|
if self.surface.buffer.is_none() {
|
||||||
|
self.initial_commit_state.set(InitialCommitState::Unmapped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(ext) = self.ext.get() {
|
if let Some(ext) = self.ext.get() {
|
||||||
ext.post_commit();
|
ext.post_commit();
|
||||||
}
|
}
|
||||||
|
|
@ -682,6 +728,8 @@ pub enum XdgSurfaceError {
|
||||||
AlreadyConstructed,
|
AlreadyConstructed,
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
WlSurfaceError(Box<WlSurfaceError>),
|
WlSurfaceError(Box<WlSurfaceError>),
|
||||||
|
#[error("The serial {0} is not larger than the previously acked serial {1}")]
|
||||||
|
InvalidSerial(u64, u64),
|
||||||
}
|
}
|
||||||
efrom!(XdgSurfaceError, WlSurfaceError);
|
efrom!(XdgSurfaceError, WlSurfaceError);
|
||||||
efrom!(XdgSurfaceError, ClientError);
|
efrom!(XdgSurfaceError, ClientError);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use {
|
||||||
wl_seat::{NodeSeatState, WlSeatGlobal, tablet::TabletTool},
|
wl_seat::{NodeSeatState, WlSeatGlobal, tablet::TabletTool},
|
||||||
wl_surface::{
|
wl_surface::{
|
||||||
tray::TrayItemId,
|
tray::TrayItemId,
|
||||||
xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt},
|
xdg_surface::{XdgSurface, XdgSurfaceExt},
|
||||||
},
|
},
|
||||||
xdg_positioner::{
|
xdg_positioner::{
|
||||||
CA_FLIP_X, CA_FLIP_Y, CA_RESIZE_X, CA_RESIZE_Y, CA_SLIDE_X, CA_SLIDE_Y,
|
CA_FLIP_X, CA_FLIP_Y, CA_RESIZE_X, CA_RESIZE_Y, CA_SLIDE_X, CA_SLIDE_Y,
|
||||||
|
|
@ -417,13 +417,12 @@ impl StackedNode for XdgPopup {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XdgSurfaceExt for XdgPopup {
|
impl XdgSurfaceExt for XdgPopup {
|
||||||
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
|
fn initial_configure(self: Rc<Self>) {
|
||||||
if let Some(parent) = self.parent.get() {
|
if let Some(parent) = self.parent.get() {
|
||||||
self.update_position(&*parent);
|
self.update_position(&*parent);
|
||||||
let rel = self.relative_position.get();
|
let rel = self.relative_position.get();
|
||||||
self.send_configure(rel.x1(), rel.y1(), rel.width(), rel.height());
|
self.send_configure(rel.x1(), rel.y1(), rel.width(), rel.height());
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_commit(self: Rc<Self>) {
|
fn post_commit(self: Rc<Self>) {
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,7 @@ use {
|
||||||
wl_surface::{
|
wl_surface::{
|
||||||
WlSurface,
|
WlSurface,
|
||||||
xdg_surface::{
|
xdg_surface::{
|
||||||
XdgSurface, XdgSurfaceError, XdgSurfaceExt,
|
XdgSurface, XdgSurfaceExt, xdg_toplevel::xdg_dialog_v1::XdgDialogV1,
|
||||||
xdg_toplevel::xdg_dialog_v1::XdgDialogV1,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
xdg_toplevel_drag_v1::XdgToplevelDragV1,
|
xdg_toplevel_drag_v1::XdgToplevelDragV1,
|
||||||
|
|
@ -753,14 +752,13 @@ impl ToplevelNodeBase for XdgToplevel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XdgSurfaceExt for XdgToplevel {
|
impl XdgSurfaceExt for XdgToplevel {
|
||||||
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
|
fn initial_configure(self: Rc<Self>) {
|
||||||
let rect = self.xdg.absolute_desired_extents.get();
|
let rect = self.xdg.absolute_desired_extents.get();
|
||||||
if rect.is_empty() {
|
if rect.is_empty() {
|
||||||
self.send_configure(0, 0);
|
self.send_configure(0, 0);
|
||||||
} else {
|
} else {
|
||||||
self.send_configure_checked(rect.width(), rect.height());
|
self.send_configure_checked(rect.width(), rect.height());
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_commit(self: Rc<Self>) {
|
fn post_commit(self: Rc<Self>) {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ impl TestXdgWmBase {
|
||||||
tran: self.tran.clone(),
|
tran: self.tran.clone(),
|
||||||
_server: server,
|
_server: server,
|
||||||
destroyed: Cell::new(false),
|
destroyed: Cell::new(false),
|
||||||
last_serial: Cell::new(0),
|
last_serial: Default::default(),
|
||||||
});
|
});
|
||||||
self.tran.add_obj(xdg.clone())?;
|
self.tran.add_obj(xdg.clone())?;
|
||||||
Ok(xdg)
|
Ok(xdg)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ pub struct TestXdgSurface {
|
||||||
pub tran: Rc<TestTransport>,
|
pub tran: Rc<TestTransport>,
|
||||||
pub _server: Rc<XdgSurface>,
|
pub _server: Rc<XdgSurface>,
|
||||||
pub destroyed: Cell<bool>,
|
pub destroyed: Cell<bool>,
|
||||||
pub last_serial: Cell<u32>,
|
pub last_serial: Cell<Option<u32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestXdgSurface {
|
impl TestXdgSurface {
|
||||||
|
|
@ -63,7 +63,7 @@ impl TestXdgSurface {
|
||||||
|
|
||||||
fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||||
let ev = Configure::parse_full(parser)?;
|
let ev = Configure::parse_full(parser)?;
|
||||||
self.last_serial.set(ev.serial);
|
self.last_serial.set(Some(ev.serial));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@ pub struct TestWindow {
|
||||||
|
|
||||||
impl TestWindow {
|
impl TestWindow {
|
||||||
pub async fn map(&self) -> Result<(), TestError> {
|
pub async fn map(&self) -> Result<(), TestError> {
|
||||||
self.xdg.ack_configure(self.xdg.last_serial.get())?;
|
if let Some(serial) = self.xdg.last_serial.take() {
|
||||||
|
self.xdg.ack_configure(serial)?;
|
||||||
|
}
|
||||||
self.surface
|
self.surface
|
||||||
.map(self.tl.core.width.get(), self.tl.core.height.get())
|
.map(self.tl.core.width.get(), self.tl.core.height.get())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue