implement popup protocol checks
This commit is contained in:
parent
477f737b95
commit
6d3d5f7933
|
@ -1109,7 +1109,9 @@ fn surface_commit(
|
|||
.unwrap();
|
||||
if !initial_configure_sent {
|
||||
// TODO: properly recompute the geometry with the whole of positioner state
|
||||
popup.send_configure();
|
||||
// NOTE: This should never fail as the initial configure is always
|
||||
// allowed.
|
||||
popup.send_configure().expect("initial configure failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1247,6 +1247,21 @@ impl ToplevelSurface {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents the possible errors that
|
||||
/// can be returned from [`PopupSurface::send_configure`]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum PopupConfigureError {
|
||||
/// The popup has already been configured and the
|
||||
/// protocol version forbids the popup to
|
||||
/// be re-configured
|
||||
#[error("The popup has already been configured")]
|
||||
AlreadyConfigured,
|
||||
/// The popup is not allowed to be re-configured,
|
||||
/// the positioner is not reactive
|
||||
#[error("The popup positioner is not reactive")]
|
||||
NotReactive,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum PopupKind {
|
||||
Xdg(xdg_popup::XdgPopup),
|
||||
|
@ -1329,6 +1344,14 @@ impl PopupSurface {
|
|||
Some(ShellClient { kind: shell })
|
||||
}
|
||||
|
||||
/// Get the version of the popup resource
|
||||
fn version(&self) -> u32 {
|
||||
match self.shell_surface {
|
||||
PopupKind::Xdg(ref xdg) => xdg.as_ref().version(),
|
||||
PopupKind::ZxdgV6(ref zxdg) => zxdg.as_ref().version(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Internal configure function to re-use the configure
|
||||
/// logic for both [`XdgRequest::send_configure`] and [`XdgRequest::send_repositioned`]
|
||||
fn send_configure_internal(&self, reposition_token: Option<u32>) {
|
||||
|
@ -1340,6 +1363,7 @@ impl PopupSurface {
|
|||
.unwrap()
|
||||
.lock()
|
||||
.unwrap();
|
||||
|
||||
if !attributes.initial_configure_sent
|
||||
|| attributes.server_pending.is_some()
|
||||
|| reposition_token.is_some()
|
||||
|
@ -1380,8 +1404,42 @@ impl PopupSurface {
|
|||
///
|
||||
/// You can manipulate the state that will be sent to the client with the [`with_pending_state`](#method.with_pending_state)
|
||||
/// method.
|
||||
pub fn send_configure(&self) {
|
||||
self.send_configure_internal(None)
|
||||
///
|
||||
/// Returns [`Err(PopupConfigureError)`] if the initial configure has already been sent and
|
||||
/// the client protocol version disallows a re-configure or the current [`PositionerState`]
|
||||
/// is not reactive
|
||||
pub fn send_configure(&self) -> Result<(), PopupConfigureError> {
|
||||
if let Some(surface) = self.get_surface() {
|
||||
// Check if we are allowed to send a configure
|
||||
compositor::with_states(surface, |states| {
|
||||
let attributes = states
|
||||
.data_map
|
||||
.get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap();
|
||||
|
||||
if attributes.initial_configure_sent && self.version() < xdg_popup::EVT_REPOSITIONED_SINCE {
|
||||
// Return error, initial configure already sent and client
|
||||
// does not support re-configure
|
||||
return Err(PopupConfigureError::AlreadyConfigured);
|
||||
}
|
||||
|
||||
let is_reactive = attributes.current.positioner.reactive;
|
||||
|
||||
if attributes.initial_configure_sent && !is_reactive {
|
||||
// Return error, the positioner does not allow re-configure
|
||||
return Err(PopupConfigureError::NotReactive);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.unwrap_or(Ok(()))?;
|
||||
|
||||
self.send_configure_internal(None);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Send a configure event, including the `repositioned` event to the client
|
||||
|
|
Loading…
Reference in New Issue