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) {
|
if let Err(err) = draw_surface_tree(renderer, frame, &wl_surface, initial_place, log) {
|
||||||
result = Err(err);
|
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::{
|
shell::{
|
||||||
legacy::{wl_shell_init, ShellRequest, ShellState as WlShellState, ShellSurfaceKind},
|
legacy::{wl_shell_init, ShellRequest, ShellState as WlShellState, ShellSurfaceKind},
|
||||||
xdg::{
|
xdg::{
|
||||||
xdg_shell_init, Configure, ShellState as XdgShellState, SurfaceCachedState, XdgRequest,
|
xdg_shell_init, Configure, ShellState as XdgShellState, SurfaceCachedState,
|
||||||
XdgToplevelSurfaceRoleAttributes,
|
XdgPopupSurfaceRoleAttributes, XdgRequest, XdgToplevelSurfaceRoleAttributes,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Serial,
|
Serial,
|
||||||
|
@ -859,4 +859,22 @@ fn surface_commit(surface: &wl_surface::WlSurface, window_map: &RefCell<WindowMa
|
||||||
window_map.set_location(&toplevel, location);
|
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::cell::RefCell;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
reexports::{wayland_protocols::xdg_shell::server::xdg_toplevel, wayland_server::protocol::wl_surface},
|
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},
|
compositor::{with_states, with_surface_tree_downward, SubsurfaceCachedState, TraversalAction},
|
||||||
shell::{
|
shell::{
|
||||||
legacy::ShellSurface,
|
legacy::ShellSurface,
|
||||||
xdg::{PopupSurface, SurfaceCachedState, ToplevelSurface},
|
xdg::{PopupSurface, SurfaceCachedState, ToplevelSurface, XdgPopupSurfaceRoleAttributes},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -77,7 +78,7 @@ pub enum PopupKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PopupKind {
|
impl PopupKind {
|
||||||
pub fn alive(&self) -> bool {
|
fn alive(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
PopupKind::Xdg(ref t) => t.alive(),
|
PopupKind::Xdg(ref t) => t.alive(),
|
||||||
}
|
}
|
||||||
|
@ -88,6 +89,44 @@ impl PopupKind {
|
||||||
PopupKind::Xdg(ref t) => t.get_surface(),
|
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 {
|
struct Window {
|
||||||
|
@ -294,6 +333,19 @@ impl WindowMap {
|
||||||
f(&w.toplevel, w.location, &w.bbox)
|
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) {
|
pub fn refresh(&mut self) {
|
||||||
self.windows.retain(|w| w.toplevel.alive());
|
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> {
|
pub fn find_popup(&self, surface: &wl_surface::WlSurface) -> Option<PopupKind> {
|
||||||
self.popups.iter().find_map(|p| {
|
self.popups.iter().find_map(|p| {
|
||||||
if p.popup
|
if p.popup
|
||||||
|
|
|
@ -11,6 +11,7 @@ use smithay::{
|
||||||
calloop::EventLoop,
|
calloop::EventLoop,
|
||||||
wayland_server::{protocol::wl_output, Display},
|
wayland_server::{protocol::wl_output, Display},
|
||||||
},
|
},
|
||||||
|
utils::Rectangle,
|
||||||
wayland::{
|
wayland::{
|
||||||
output::{Mode, Output, PhysicalProperties},
|
output::{Mode, Output, PhysicalProperties},
|
||||||
seat::CursorImageStatus,
|
seat::CursorImageStatus,
|
||||||
|
@ -120,12 +121,28 @@ pub fn run_winit(
|
||||||
{
|
{
|
||||||
let mut renderer = renderer.borrow_mut();
|
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
|
let result = renderer
|
||||||
.render(|renderer, frame| {
|
.render(|renderer, frame| {
|
||||||
frame.clear([0.8, 0.8, 0.9, 1.0])?;
|
frame.clear([0.8, 0.8, 0.9, 1.0])?;
|
||||||
|
|
||||||
// draw the windows
|
// 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;
|
let (x, y) = state.pointer_location;
|
||||||
// draw the dnd icon if any
|
// draw the dnd icon if any
|
||||||
|
|
|
@ -1368,7 +1368,7 @@ impl PopupSurface {
|
||||||
|
|
||||||
/// Access the underlying `wl_surface` of this toplevel surface
|
/// 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> {
|
pub fn get_surface(&self) -> Option<&wl_surface::WlSurface> {
|
||||||
if self.alive() {
|
if self.alive() {
|
||||||
Some(&self.wl_surface)
|
Some(&self.wl_surface)
|
||||||
|
|
|
@ -18,7 +18,7 @@ use super::{
|
||||||
};
|
};
|
||||||
|
|
||||||
static XDG_TOPLEVEL_ROLE: &str = "xdg_toplevel";
|
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(
|
pub(crate) fn implement_wm_base(
|
||||||
shell: Main<xdg_wm_base::XdgWmBase>,
|
shell: Main<xdg_wm_base::XdgWmBase>,
|
||||||
|
|
Loading…
Reference in New Issue