Rudimentary xdg_popup support
This commit is contained in:
parent
47bc37c67b
commit
3a0c631edd
|
@ -210,6 +210,16 @@ where
|
|||
if let Err(err) = draw_surface_tree(renderer, frame, &wl_surface, initial_place, log) {
|
||||
result = Err(err);
|
||||
}
|
||||
// furthermore, draw its popups
|
||||
window_map.with_child_popups(&wl_surface, |popup| {
|
||||
let location = popup.location();
|
||||
let draw_location = (initial_place.0 + location.0, initial_place.1 + location.1);
|
||||
if let Some(wl_surface) = popup.get_surface() {
|
||||
if let Err(err) = draw_surface_tree(renderer, frame, &wl_surface, draw_location, log) {
|
||||
result = Err(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ use smithay::{
|
|||
shell::{
|
||||
legacy::{wl_shell_init, ShellRequest, ShellState as WlShellState, ShellSurfaceKind},
|
||||
xdg::{
|
||||
xdg_shell_init, Configure, ShellState as XdgShellState, SurfaceCachedState, XdgRequest,
|
||||
XdgToplevelSurfaceRoleAttributes,
|
||||
xdg_shell_init, Configure, ShellState as XdgShellState, SurfaceCachedState,
|
||||
XdgPopupSurfaceRoleAttributes, XdgRequest, XdgToplevelSurfaceRoleAttributes,
|
||||
},
|
||||
},
|
||||
Serial,
|
||||
|
@ -859,4 +859,22 @@ fn surface_commit(surface: &wl_surface::WlSurface, window_map: &RefCell<WindowMa
|
|||
window_map.set_location(&toplevel, location);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(popup) = window_map.find_popup(surface) {
|
||||
let PopupKind::Xdg(ref popup) = popup;
|
||||
let initial_configure_sent = with_states(surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
})
|
||||
.unwrap();
|
||||
if !initial_configure_sent {
|
||||
// TODO: properly recompute the geometry with the whole of positioner state
|
||||
popup.send_configure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::cell::RefCell;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use smithay::{
|
||||
reexports::{wayland_protocols::xdg_shell::server::xdg_toplevel, wayland_server::protocol::wl_surface},
|
||||
|
@ -7,7 +8,7 @@ use smithay::{
|
|||
compositor::{with_states, with_surface_tree_downward, SubsurfaceCachedState, TraversalAction},
|
||||
shell::{
|
||||
legacy::ShellSurface,
|
||||
xdg::{PopupSurface, SurfaceCachedState, ToplevelSurface},
|
||||
xdg::{PopupSurface, SurfaceCachedState, ToplevelSurface, XdgPopupSurfaceRoleAttributes},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -77,7 +78,7 @@ pub enum PopupKind {
|
|||
}
|
||||
|
||||
impl PopupKind {
|
||||
pub fn alive(&self) -> bool {
|
||||
fn alive(&self) -> bool {
|
||||
match *self {
|
||||
PopupKind::Xdg(ref t) => t.alive(),
|
||||
}
|
||||
|
@ -88,6 +89,44 @@ impl PopupKind {
|
|||
PopupKind::Xdg(ref t) => t.get_surface(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<wl_surface::WlSurface> {
|
||||
let wl_surface = match self.get_surface() {
|
||||
Some(s) => s,
|
||||
None => return None,
|
||||
};
|
||||
with_states(wl_surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.parent
|
||||
.clone()
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub fn location(&self) -> (i32, i32) {
|
||||
let wl_surface = match self.get_surface() {
|
||||
Some(s) => s,
|
||||
None => return (0, 0),
|
||||
};
|
||||
let geometry = with_states(wl_surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.current
|
||||
.geometry
|
||||
})
|
||||
.unwrap_or_default();
|
||||
(geometry.x, geometry.y)
|
||||
}
|
||||
}
|
||||
|
||||
struct Window {
|
||||
|
@ -294,6 +333,19 @@ impl WindowMap {
|
|||
f(&w.toplevel, w.location, &w.bbox)
|
||||
}
|
||||
}
|
||||
pub fn with_child_popups<Func>(&self, base: &wl_surface::WlSurface, mut f: Func)
|
||||
where
|
||||
Func: FnMut(&PopupKind),
|
||||
{
|
||||
for w in self
|
||||
.popups
|
||||
.iter()
|
||||
.rev()
|
||||
.filter(move |w| w.popup.parent().as_ref() == Some(base))
|
||||
{
|
||||
f(&w.popup)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refresh(&mut self) {
|
||||
self.windows.retain(|w| w.toplevel.alive());
|
||||
|
@ -329,6 +381,7 @@ impl WindowMap {
|
|||
})
|
||||
}
|
||||
|
||||
/// Finds the popup corresponding to the given `WlSurface`.
|
||||
pub fn find_popup(&self, surface: &wl_surface::WlSurface) -> Option<PopupKind> {
|
||||
self.popups.iter().find_map(|p| {
|
||||
if p.popup
|
||||
|
|
|
@ -11,6 +11,7 @@ use smithay::{
|
|||
calloop::EventLoop,
|
||||
wayland_server::{protocol::wl_output, Display},
|
||||
},
|
||||
utils::Rectangle,
|
||||
wayland::{
|
||||
output::{Mode, Output, PhysicalProperties},
|
||||
seat::CursorImageStatus,
|
||||
|
@ -120,12 +121,28 @@ pub fn run_winit(
|
|||
{
|
||||
let mut renderer = renderer.borrow_mut();
|
||||
|
||||
let output_rect = {
|
||||
let (width, height) = renderer.window_size().physical_size.into();
|
||||
Rectangle {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width,
|
||||
height,
|
||||
}
|
||||
};
|
||||
|
||||
let result = renderer
|
||||
.render(|renderer, frame| {
|
||||
frame.clear([0.8, 0.8, 0.9, 1.0])?;
|
||||
|
||||
// draw the windows
|
||||
draw_windows(renderer, frame, &*state.window_map.borrow(), None, &log)?;
|
||||
draw_windows(
|
||||
renderer,
|
||||
frame,
|
||||
&*state.window_map.borrow(),
|
||||
Some(output_rect),
|
||||
&log,
|
||||
)?;
|
||||
|
||||
let (x, y) = state.pointer_location;
|
||||
// draw the dnd icon if any
|
||||
|
|
|
@ -1368,7 +1368,7 @@ impl PopupSurface {
|
|||
|
||||
/// Access the underlying `wl_surface` of this toplevel surface
|
||||
///
|
||||
/// Returns `None` if the toplevel surface actually no longer exists.
|
||||
/// Returns `None` if the popup surface actually no longer exists.
|
||||
pub fn get_surface(&self) -> Option<&wl_surface::WlSurface> {
|
||||
if self.alive() {
|
||||
Some(&self.wl_surface)
|
||||
|
|
|
@ -18,7 +18,7 @@ use super::{
|
|||
};
|
||||
|
||||
static XDG_TOPLEVEL_ROLE: &str = "xdg_toplevel";
|
||||
static XDG_POPUP_ROLE: &str = "xdg_toplevel";
|
||||
static XDG_POPUP_ROLE: &str = "xdg_popup";
|
||||
|
||||
pub(crate) fn implement_wm_base(
|
||||
shell: Main<xdg_wm_base::XdgWmBase>,
|
||||
|
|
Loading…
Reference in New Issue