feat: add nested Phase 0 compositor
This commit is contained in:
1 parent
aab447ef25
commit
475d433ec4
8 files changed
+2710
-2
No files matched your search
@@ -0,0 +1,129 @@
|
||||
use smithay::{
|
||||
desktop::{
|
||||
PopupKind, PopupManager, Space, Window, find_popup_root_surface, get_popup_toplevel_coords,
|
||||
},
|
||||
reexports::wayland_server::protocol::{wl_seat, wl_surface::WlSurface},
|
||||
utils::Serial,
|
||||
wayland::{
|
||||
compositor::with_states,
|
||||
shell::xdg::{
|
||||
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
|
||||
XdgToplevelSurfaceData,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::Ferese;
|
||||
|
||||
impl XdgShellHandler for Ferese {
|
||||
fn xdg_shell_state(&mut self) -> &mut XdgShellState {
|
||||
&mut self.xdg_shell_state
|
||||
}
|
||||
|
||||
fn new_toplevel(&mut self, surface: ToplevelSurface) {
|
||||
self.space
|
||||
.map_element(Window::new_wayland_window(surface), (0, 0), true);
|
||||
}
|
||||
|
||||
fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) {
|
||||
self.unconstrain_popup(&surface);
|
||||
if let Err(error) = self.popups.track_popup(PopupKind::Xdg(surface)) {
|
||||
tracing::warn!(?error, "failed to track xdg popup");
|
||||
}
|
||||
}
|
||||
|
||||
fn reposition_request(
|
||||
&mut self,
|
||||
surface: PopupSurface,
|
||||
positioner: PositionerState,
|
||||
token: u32,
|
||||
) {
|
||||
surface.with_pending_state(|state| {
|
||||
state.geometry = positioner.get_geometry();
|
||||
state.positioner = positioner;
|
||||
});
|
||||
self.unconstrain_popup(&surface);
|
||||
surface.send_repositioned(token);
|
||||
}
|
||||
|
||||
fn move_request(&mut self, _: ToplevelSurface, _: wl_seat::WlSeat, _: Serial) {}
|
||||
|
||||
fn resize_request(
|
||||
&mut self,
|
||||
_: ToplevelSurface,
|
||||
_: wl_seat::WlSeat,
|
||||
_: Serial,
|
||||
_: smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::ResizeEdge,
|
||||
) {
|
||||
}
|
||||
|
||||
fn grab(&mut self, _: PopupSurface, _: wl_seat::WlSeat, _: Serial) {}
|
||||
}
|
||||
|
||||
pub fn handle_commit(popups: &mut PopupManager, space: &Space<Window>, surface: &WlSurface) {
|
||||
if let Some(window) = space
|
||||
.elements()
|
||||
.find(|window| {
|
||||
window
|
||||
.toplevel()
|
||||
.is_some_and(|toplevel| toplevel.wl_surface() == surface)
|
||||
})
|
||||
.cloned()
|
||||
{
|
||||
let configured = with_states(surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.expect("xdg toplevel state exists")
|
||||
.lock()
|
||||
.expect("xdg toplevel state is not poisoned")
|
||||
.initial_configure_sent
|
||||
});
|
||||
if !configured {
|
||||
window
|
||||
.toplevel()
|
||||
.expect("mapped window has a toplevel")
|
||||
.send_configure();
|
||||
}
|
||||
}
|
||||
|
||||
popups.commit(surface);
|
||||
if let Some(PopupKind::Xdg(popup)) = popups.find_popup(surface)
|
||||
&& !popup.is_initial_configure_sent()
|
||||
{
|
||||
popup
|
||||
.send_configure()
|
||||
.expect("initial popup configure is valid");
|
||||
}
|
||||
}
|
||||
|
||||
impl Ferese {
|
||||
fn unconstrain_popup(&self, popup: &PopupSurface) {
|
||||
let Ok(root) = find_popup_root_surface(&PopupKind::Xdg(popup.clone())) else {
|
||||
return;
|
||||
};
|
||||
let Some(window) = self.space.elements().find(|window| {
|
||||
window
|
||||
.toplevel()
|
||||
.is_some_and(|toplevel| toplevel.wl_surface() == &root)
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
let Some(output) = self.space.outputs().next() else {
|
||||
return;
|
||||
};
|
||||
let Some(output_geometry) = self.space.output_geometry(output) else {
|
||||
return;
|
||||
};
|
||||
let Some(window_geometry) = self.space.element_geometry(window) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let mut target = output_geometry;
|
||||
target.loc -= get_popup_toplevel_coords(&PopupKind::Xdg(popup.clone()));
|
||||
target.loc -= window_geometry.loc;
|
||||
popup.with_pending_state(|state| {
|
||||
state.geometry = state.positioner.get_unconstrained_geometry(target);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user