aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-08-11 08:22:34 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-08-11 08:22:34 +0400
commit3959d1eaa10f97f2377f8174b711c8c30a2f3949 (patch)
tree3a314d442a5a535a5047f2f9ac9511ef3ef829d1
parent91c7763aabf47217c6ec5587b0aae23fdaa6ecaa (diff)
downloadniri-3959d1eaa10f97f2377f8174b711c8c30a2f3949.tar.gz
niri-3959d1eaa10f97f2377f8174b711c8c30a2f3949.tar.bz2
niri-3959d1eaa10f97f2377f8174b711c8c30a2f3949.zip
Add draft popup implementation
Missing grabs and positioning but gets the job sufficiently done for now.
-rw-r--r--src/handlers/compositor.rs3
-rw-r--r--src/handlers/xdg_shell.rs101
-rw-r--r--src/niri.rs5
3 files changed, 80 insertions, 29 deletions
diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs
index 1cd781f6..f5a955e1 100644
--- a/src/handlers/compositor.rs
+++ b/src/handlers/compositor.rs
@@ -9,7 +9,6 @@ use smithay::wayland::compositor::{
use smithay::wayland::shm::{ShmHandler, ShmState};
use smithay::{delegate_compositor, delegate_shm};
-use super::xdg_shell;
use crate::grabs::resize_grab;
use crate::niri::ClientState;
use crate::Niri;
@@ -43,7 +42,7 @@ impl CompositorHandler for Niri {
}
};
- xdg_shell::handle_commit(&self.space, surface);
+ self.xdg_handle_commit(surface);
resize_grab::handle_commit(&mut self.space, surface);
self.queue_redraw();
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs
index 686c5525..6a12d4e9 100644
--- a/src/handlers/xdg_shell.rs
+++ b/src/handlers/xdg_shell.rs
@@ -1,5 +1,5 @@
use smithay::delegate_xdg_shell;
-use smithay::desktop::{Space, Window};
+use smithay::desktop::{PopupKind, Window};
use smithay::input::pointer::{Focus, GrabStartData as PointerGrabStartData};
use smithay::input::Seat;
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
@@ -9,8 +9,8 @@ use smithay::reexports::wayland_server::Resource;
use smithay::utils::{Rectangle, Serial};
use smithay::wayland::compositor::with_states;
use smithay::wayland::shell::xdg::{
- PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
- XdgToplevelSurfaceData,
+ PopupSurface, PositionerState, ToplevelSurface, XdgPopupSurfaceData, XdgShellHandler,
+ XdgShellState, XdgToplevelSurfaceData,
};
use crate::grabs::{MoveSurfaceGrab, ResizeSurfaceGrab};
@@ -26,8 +26,17 @@ impl XdgShellHandler for Niri {
self.space.map_element(window, (0, 0), false);
}
- fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) {
- // TODO: Popup handling using PopupManager
+ fn new_popup(&mut self, surface: PopupSurface, positioner: PositionerState) {
+ surface.with_pending_state(|state| {
+ // NOTE: This is not really necessary as the default geometry
+ // is already set the same way, but for demonstrating how
+ // to set the initial popup geometry this code is left as
+ // an example
+ state.geometry = positioner.get_geometry();
+ });
+ if let Err(err) = self.popups.track_popup(PopupKind::Xdg(surface)) {
+ warn!("error tracking popup: {err:?}");
+ }
}
fn move_request(&mut self, surface: ToplevelSurface, seat: wl_seat::WlSeat, serial: Serial) {
@@ -96,6 +105,24 @@ impl XdgShellHandler for Niri {
}
}
+ fn reposition_request(
+ &mut self,
+ surface: PopupSurface,
+ positioner: PositionerState,
+ token: u32,
+ ) {
+ surface.with_pending_state(|state| {
+ // NOTE: This is again a simplification, a proper compositor would
+ // calculate the geometry of the popup here. For simplicity we just
+ // use the default implementation here that does not take the
+ // window position and output constraints into account.
+ let geometry = positioner.get_geometry();
+ state.geometry = geometry;
+ state.positioner = positioner;
+ });
+ surface.send_repositioned(token);
+ }
+
fn grab(&mut self, _surface: PopupSurface, _seat: wl_seat::WlSeat, _serial: Serial) {
// TODO popup grabs
}
@@ -181,26 +208,48 @@ fn check_grab(
Some(start_data)
}
-/// Should be called on `WlSurface::commit`
-pub fn handle_commit(space: &Space<Window>, surface: &WlSurface) -> Option<()> {
- let window = space
- .elements()
- .find(|w| w.toplevel().wl_surface() == surface)
- .cloned()?;
-
- let initial_configure_sent = with_states(surface, |states| {
- states
- .data_map
- .get::<XdgToplevelSurfaceData>()
- .unwrap()
- .lock()
- .unwrap()
- .initial_configure_sent
- });
-
- if !initial_configure_sent {
- window.toplevel().send_configure();
- }
+impl Niri {
+ /// Should be called on `WlSurface::commit`
+ pub fn xdg_handle_commit(&mut self, surface: &WlSurface) {
+ self.popups.commit(surface);
- Some(())
+ if let Some(window) = self
+ .space
+ .elements()
+ .find(|w| w.toplevel().wl_surface() == surface)
+ .cloned()
+ {
+ let initial_configure_sent = with_states(surface, |states| {
+ states
+ .data_map
+ .get::<XdgToplevelSurfaceData>()
+ .unwrap()
+ .lock()
+ .unwrap()
+ .initial_configure_sent
+ });
+
+ if !initial_configure_sent {
+ window.toplevel().send_configure();
+ }
+ }
+
+ if let Some(popup) = self.popups.find_popup(surface) {
+ let PopupKind::Xdg(ref popup) = popup;
+ let initial_configure_sent = with_states(surface, |states| {
+ states
+ .data_map
+ .get::<XdgPopupSurfaceData>()
+ .unwrap()
+ .lock()
+ .unwrap()
+ .initial_configure_sent
+ });
+ if !initial_configure_sent {
+ // NOTE: This should never fail as the initial configure is always
+ // allowed.
+ popup.send_configure().expect("initial configure failed");
+ }
+ }
+ }
}
diff --git a/src/niri.rs b/src/niri.rs
index ac5cba43..0fbd49f5 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -6,7 +6,7 @@ use smithay::backend::renderer::element::render_elements;
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
use smithay::backend::renderer::ImportAll;
use smithay::desktop::space::{space_render_elements, SpaceRenderElements};
-use smithay::desktop::{Space, Window, WindowSurfaceType};
+use smithay::desktop::{PopupManager, Space, Window, WindowSurfaceType};
use smithay::input::keyboard::XkbConfig;
use smithay::input::{Seat, SeatState};
use smithay::output::Output;
@@ -42,6 +42,7 @@ pub struct Niri {
pub output_manager_state: OutputManagerState,
pub seat_state: SeatState<Self>,
pub data_device_state: DataDeviceState,
+ pub popups: PopupManager,
pub seat: Seat<Self>,
pub output: Option<Output>,
@@ -137,6 +138,7 @@ impl Niri {
output_manager_state,
seat_state,
data_device_state,
+ popups: PopupManager::default(),
seat,
output: None,
@@ -225,6 +227,7 @@ impl Niri {
});
self.space.refresh();
+ self.popups.cleanup();
}
}