feat(wayland): popups, more compatibility, more stability
get_parent grab popups fix head thingy popup list feat: remove set_active feat(wayland): commit_popup feat(wayland): cleanup moar changess actually fix the problem with everything oh my god proper popup state fix: multi thread event loop fix: match popup surface ID make wayland input system go over surfaces instead of toplevels feat: massive refactor of all wayland things
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use super::{
|
||||
seat::{Cursor, SeatData},
|
||||
surface::CoreSurface,
|
||||
xdg_shell::{XdgSurfaceData, XdgToplevelData},
|
||||
xdg_shell::{PopupData, ToplevelData, XdgSurfaceData},
|
||||
SERIAL_COUNTER,
|
||||
};
|
||||
use crate::{
|
||||
@@ -23,11 +23,18 @@ use lazy_static::lazy_static;
|
||||
use mint::Vector2;
|
||||
use nanoid::nanoid;
|
||||
use parking_lot::Mutex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::{
|
||||
de::{Deserializer, Error, SeqAccess, Visitor},
|
||||
ser::Serializer,
|
||||
Deserialize, Serialize,
|
||||
};
|
||||
use smithay::{
|
||||
reexports::{
|
||||
wayland_protocols::xdg::shell::server::xdg_toplevel::{
|
||||
XdgToplevel, EVT_CONFIGURE_BOUNDS_SINCE, EVT_WM_CAPABILITIES_SINCE,
|
||||
wayland_protocols::xdg::shell::server::{
|
||||
xdg_popup::XdgPopup,
|
||||
xdg_surface::XdgSurface,
|
||||
xdg_toplevel::{XdgToplevel, EVT_CONFIGURE_BOUNDS_SINCE, EVT_WM_CAPABILITIES_SINCE},
|
||||
},
|
||||
wayland_server::{
|
||||
backend::Credentials, protocol::wl_surface::WlSurface, Resource, Weak as WlWeak,
|
||||
@@ -44,55 +51,92 @@ lazy_static! {
|
||||
pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo {
|
||||
type_name: "panel",
|
||||
aliased_local_signals: vec![
|
||||
"apply_cursor_material",
|
||||
"apply_toplevel_material",
|
||||
"apply_surface_material",
|
||||
"configure_toplevel",
|
||||
"set_toplevel_capabilities",
|
||||
"pointer_set_active",
|
||||
"pointer_scroll",
|
||||
"pointer_button",
|
||||
"pointer_motion",
|
||||
"keyboard_set_active",
|
||||
"keyboard_key",
|
||||
"keyboard_set_keymap_names",
|
||||
"keyboard_set_keymap_string",
|
||||
"close",
|
||||
],
|
||||
aliased_local_methods: vec![],
|
||||
aliased_remote_signals: vec!["commit_toplevel", "recommend_toplevel_state", "set_cursor"],
|
||||
aliased_remote_signals: vec![
|
||||
"commit_toplevel",
|
||||
"recommend_toplevel_state",
|
||||
"set_cursor",
|
||||
"new_popup",
|
||||
"reposition_popup",
|
||||
"drop_popup",
|
||||
],
|
||||
ui: Default::default(),
|
||||
items: Registry::new(),
|
||||
acceptors: Registry::new(),
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct ToplevelState {
|
||||
#[serde(skip_serializing)]
|
||||
pub mapped: bool,
|
||||
#[serde(skip_serializing)]
|
||||
pub parent: Option<WlWeak<XdgToplevel>>,
|
||||
pub title: Option<String>,
|
||||
pub app_id: Option<String>,
|
||||
pub size: Vector2<u32>,
|
||||
pub max_size: Option<Vector2<u32>>,
|
||||
pub min_size: Option<Vector2<u32>>,
|
||||
pub states: Vec<u32>,
|
||||
#[serde(skip_serializing)]
|
||||
pub queued_state: Option<Box<ToplevelState>>,
|
||||
/// An ID for a surface inside this panel item
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub enum SurfaceID {
|
||||
Cursor,
|
||||
Toplevel,
|
||||
Popup(String),
|
||||
}
|
||||
impl Default for ToplevelState {
|
||||
impl Default for SurfaceID {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mapped: false,
|
||||
parent: None,
|
||||
title: None,
|
||||
app_id: None,
|
||||
size: Vector2::from([0; 2]),
|
||||
max_size: None,
|
||||
min_size: None,
|
||||
states: Vec::new(),
|
||||
queued_state: None,
|
||||
Self::Toplevel
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for SurfaceID {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
deserializer.deserialize_seq(SurfaceIDVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct SurfaceIDVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for SurfaceIDVisitor {
|
||||
type Value = SurfaceID;
|
||||
|
||||
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.write_str("idk")
|
||||
}
|
||||
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let Some(discrim) = seq.next_element()? else {
|
||||
return Err(A::Error::missing_field("discrim"));
|
||||
};
|
||||
|
||||
// idk if you wanna check for extraneous elements
|
||||
// I didn't bother
|
||||
|
||||
match discrim {
|
||||
"Cursor" => Ok(SurfaceID::Cursor),
|
||||
"Toplevel" => Ok(SurfaceID::Toplevel),
|
||||
"Popup" => {
|
||||
let Some(text) = seq.next_element()? else {
|
||||
return Err(A::Error::missing_field("popup_text"));
|
||||
};
|
||||
Ok(SurfaceID::Popup(text))
|
||||
}
|
||||
_ => Err(A::Error::unknown_variant(
|
||||
discrim,
|
||||
&["Cursor", "Toplevel", "Popup"],
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::Serialize for SurfaceID {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
match self {
|
||||
Self::Cursor => ["Cursor"].serialize(serializer),
|
||||
Self::Toplevel => ["Toplevel"].serialize(serializer),
|
||||
Self::Popup(text) => ["Popup", text].serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,11 +152,15 @@ pub enum RecommendedState {
|
||||
}
|
||||
|
||||
pub struct PanelItem {
|
||||
pub uid: String,
|
||||
node: Weak<Node>,
|
||||
client_credentials: Option<Credentials>,
|
||||
cursor: Mutex<Option<WlWeak<WlSurface>>>,
|
||||
pub seat_data: Arc<SeatData>,
|
||||
toplevel: WlWeak<XdgToplevel>,
|
||||
pub cursor: Mutex<Option<WlWeak<WlSurface>>>,
|
||||
seat_data: Arc<SeatData>,
|
||||
popups: Mutex<FxHashMap<String, WlWeak<XdgPopup>>>,
|
||||
pointer_grab: Mutex<Option<SurfaceID>>,
|
||||
keyboard_grab: Mutex<Option<SurfaceID>>,
|
||||
}
|
||||
impl PanelItem {
|
||||
pub fn create(
|
||||
@@ -122,51 +170,49 @@ impl PanelItem {
|
||||
seat_data: Arc<SeatData>,
|
||||
) -> (Arc<Node>, Arc<PanelItem>) {
|
||||
debug!(?toplevel, ?client_credentials, "Create panel item");
|
||||
let uid = nanoid!();
|
||||
let node = Arc::new(Node::create(
|
||||
&INTERNAL_CLIENT,
|
||||
"/item/panel/item",
|
||||
&nanoid!(),
|
||||
&uid,
|
||||
true,
|
||||
));
|
||||
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap();
|
||||
let panel_item = Arc::new(PanelItem {
|
||||
uid: uid.clone(),
|
||||
node: Arc::downgrade(&node),
|
||||
client_credentials,
|
||||
toplevel: toplevel.downgrade(),
|
||||
cursor: Mutex::new(None),
|
||||
seat_data,
|
||||
toplevel: toplevel.downgrade(),
|
||||
popups: Mutex::new(FxHashMap::default()),
|
||||
pointer_grab: Mutex::new(None),
|
||||
keyboard_grab: Mutex::new(None),
|
||||
});
|
||||
|
||||
panel_item
|
||||
.seat_data
|
||||
.new_panel_item(&panel_item, &toplevel, &wl_surface);
|
||||
.new_surface(&wl_surface, Arc::downgrade(&panel_item));
|
||||
|
||||
let item = Item::add_to(
|
||||
&node,
|
||||
uid,
|
||||
&ITEM_TYPE_INFO_PANEL,
|
||||
ItemType::Panel(panel_item.clone()),
|
||||
);
|
||||
node.add_local_signal(
|
||||
"apply_toplevel_material",
|
||||
PanelItem::apply_toplevel_material_flex,
|
||||
"apply_surface_material",
|
||||
PanelItem::apply_surface_material_flex,
|
||||
);
|
||||
node.add_local_signal("configure_toplevel", PanelItem::configure_toplevel_flex);
|
||||
if toplevel.version() >= EVT_WM_CAPABILITIES_SINCE {
|
||||
node.add_local_signal(
|
||||
"set_toplevel_capabilities",
|
||||
PanelItem::set_toplevel_capabilities_flex,
|
||||
);
|
||||
}
|
||||
node.add_local_signal(
|
||||
"apply_cursor_material",
|
||||
PanelItem::apply_cursor_material_flex,
|
||||
"set_toplevel_capabilities",
|
||||
PanelItem::set_toplevel_capabilities_flex,
|
||||
);
|
||||
node.add_local_signal("pointer_set_active", PanelItem::pointer_set_active_flex);
|
||||
node.add_local_signal("pointer_scroll", PanelItem::pointer_scroll_flex);
|
||||
node.add_local_signal("pointer_button", PanelItem::pointer_button_flex);
|
||||
node.add_local_signal("pointer_motion", PanelItem::pointer_motion_flex);
|
||||
|
||||
node.add_local_signal("keyboard_set_active", PanelItem::keyboard_set_active_flex);
|
||||
node.add_local_signal(
|
||||
"keyboard_set_keymap_string",
|
||||
PanelItem::keyboard_set_keymap_string_flex,
|
||||
@@ -195,38 +241,26 @@ impl PanelItem {
|
||||
(node, panel_item)
|
||||
}
|
||||
|
||||
pub fn from_node(node: &Node) -> Option<&PanelItem> {
|
||||
node.item.get().and_then(|item| match &item.specialization {
|
||||
ItemType::Panel(panel_item) => Some(&**panel_item),
|
||||
_ => None,
|
||||
})
|
||||
pub fn from_node(node: &Node) -> Option<Arc<PanelItem>> {
|
||||
let ItemType::Panel(panel_item) = &node.item.get()?.specialization else {return None};
|
||||
Some(panel_item.clone())
|
||||
}
|
||||
|
||||
fn toplevel_surface_data(&self) -> Option<XdgSurfaceData> {
|
||||
Some(
|
||||
self.toplevel
|
||||
.upgrade()
|
||||
.ok()?
|
||||
.data::<XdgToplevelData>()?
|
||||
.xdg_surface_data
|
||||
.clone(),
|
||||
)
|
||||
fn toplevel(&self) -> XdgToplevel {
|
||||
self.toplevel.upgrade().unwrap()
|
||||
}
|
||||
fn toplevel_state(&self) -> Option<Arc<Mutex<ToplevelState>>> {
|
||||
Some(
|
||||
self.toplevel
|
||||
.upgrade()
|
||||
.ok()?
|
||||
.data::<XdgToplevelData>()?
|
||||
.state
|
||||
.clone(),
|
||||
)
|
||||
fn toplevel_xdg_surface(&self) -> XdgSurface {
|
||||
let toplevel = self.toplevel();
|
||||
let data = ToplevelData::get(&toplevel).lock();
|
||||
data.xdg_surface()
|
||||
}
|
||||
pub fn toplevel_wl_surface(&self) -> Option<WlSurface> {
|
||||
self.toplevel_surface_data()?.wl_surface.upgrade().ok()
|
||||
fn toplevel_wl_surface(&self) -> WlSurface {
|
||||
XdgSurfaceData::get(&self.toplevel_xdg_surface())
|
||||
.lock()
|
||||
.wl_surface()
|
||||
}
|
||||
fn core_surface(&self) -> Option<Arc<CoreSurface>> {
|
||||
compositor::with_states(&self.toplevel_wl_surface()?, |data| {
|
||||
compositor::with_states(&self.toplevel_wl_surface(), |data| {
|
||||
data.data_map.get::<Arc<CoreSurface>>().cloned()
|
||||
})
|
||||
}
|
||||
@@ -235,55 +269,49 @@ impl PanelItem {
|
||||
core_surface.flush_clients();
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_toplevel_material_flex(
|
||||
node: &Node,
|
||||
calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct SurfaceMaterialInfo<'a> {
|
||||
model_path: &'a str,
|
||||
idx: u32,
|
||||
}
|
||||
let info: SurfaceMaterialInfo = deserialize(data)?;
|
||||
let model_node = calling_client
|
||||
.scenegraph
|
||||
.get_node(info.model_path)
|
||||
.ok_or_else(|| eyre!("Model node not found"))?;
|
||||
let Some(Drawable::Model(model)) = model_node.drawable.get() else {bail!("Node is not a model")};
|
||||
debug!(?info, "Apply toplevel material");
|
||||
|
||||
if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization {
|
||||
if let Some(core_surface) = panel_item.core_surface() {
|
||||
core_surface.apply_material(model.clone(), info.idx);
|
||||
fn wl_surface_from_id(&self, id: &SurfaceID) -> Option<WlSurface> {
|
||||
match id {
|
||||
SurfaceID::Cursor => self.cursor.lock().clone()?.upgrade().ok(),
|
||||
SurfaceID::Toplevel => Some(self.toplevel_wl_surface()),
|
||||
SurfaceID::Popup(popup) => {
|
||||
let popups = self.popups.lock();
|
||||
let popup = popups.get(popup)?.upgrade().ok()?;
|
||||
let surf = PopupData::get(&popup).lock().wl_surface();
|
||||
Some(surf)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn wl_surface_from_id_result(&self, id: &SurfaceID) -> Result<WlSurface> {
|
||||
self.wl_surface_from_id(id)
|
||||
.ok_or(eyre!("Surface with ID not found"))
|
||||
}
|
||||
|
||||
fn apply_cursor_material_flex(
|
||||
fn apply_surface_material_flex(
|
||||
node: &Node,
|
||||
calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(cursor) = panel_item.cursor.lock().as_ref().and_then(|c| c.upgrade().ok()) else { return Ok(())};
|
||||
let Some(core_surface) = CoreSurface::from_wl_surface(&cursor) else { return Ok(()) };
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct SurfaceMaterialInfo<'a> {
|
||||
surface: SurfaceID,
|
||||
model_path: &'a str,
|
||||
idx: u32,
|
||||
}
|
||||
|
||||
let info: SurfaceMaterialInfo = deserialize(data)?;
|
||||
debug!(?cursor, ?info, "Apply cursor material");
|
||||
|
||||
let Some(wl_surface) = panel_item.wl_surface_from_id(&info.surface) else { return Ok(()) };
|
||||
let Some(core_surface) = CoreSurface::from_wl_surface(&wl_surface) else { return Ok(()) };
|
||||
|
||||
let model_node = calling_client
|
||||
.scenegraph
|
||||
.get_node(info.model_path)
|
||||
.ok_or_else(|| eyre!("Model node not found"))?;
|
||||
let Some(Drawable::Model(model)) = model_node.drawable.get() else {bail!("Node is not a model")};
|
||||
debug!(?info, "Apply surface material");
|
||||
|
||||
core_surface.apply_material(model.clone(), info.idx);
|
||||
|
||||
Ok(())
|
||||
@@ -291,69 +319,57 @@ impl PanelItem {
|
||||
|
||||
fn pointer_motion_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
debug!(?toplevel, "Pointer deactivate");
|
||||
|
||||
let (surface_id, position): (SurfaceID, Vector2<f64>) = deserialize(data)?;
|
||||
let wl_surface = panel_item.wl_surface_from_id_result(&surface_id)?;
|
||||
debug!(?surface_id, ?position, "Pointer deactivate");
|
||||
|
||||
panel_item
|
||||
.seat_data
|
||||
.pointer_event(&toplevel, PointerEvent::Motion(deserialize(data)?));
|
||||
.pointer_event(&wl_surface, PointerEvent::Motion(position));
|
||||
panel_item.flush_clients();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn pointer_button_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
|
||||
let (button, state): (u32, u32) = deserialize(data)?;
|
||||
debug!(button, state, "Pointer button");
|
||||
let (surface_id, button, state): (SurfaceID, u32, u32) = deserialize(data)?;
|
||||
let wl_surface = panel_item.wl_surface_from_id_result(&surface_id)?;
|
||||
debug!(?surface_id, button, state, "Pointer button");
|
||||
|
||||
panel_item
|
||||
.seat_data
|
||||
.pointer_event(&toplevel, PointerEvent::Button { button, state });
|
||||
.pointer_event(&wl_surface, PointerEvent::Button { button, state });
|
||||
panel_item.flush_clients();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn pointer_scroll_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PointerScrollArgs {
|
||||
struct PointerScrollInfo {
|
||||
surface_id: SurfaceID,
|
||||
axis_continuous: Option<Vector2<f32>>,
|
||||
axis_discrete: Option<Vector2<f32>>,
|
||||
}
|
||||
let args: PointerScrollArgs = deserialize(data)?;
|
||||
let info: PointerScrollInfo = deserialize(data)?;
|
||||
let wl_surface = panel_item.wl_surface_from_id_result(&info.surface_id)?;
|
||||
|
||||
debug!(?args, "Pointer scroll");
|
||||
debug!(?info, "Pointer scroll");
|
||||
|
||||
panel_item.seat_data.pointer_event(
|
||||
&toplevel,
|
||||
&wl_surface,
|
||||
PointerEvent::Scroll {
|
||||
axis_continuous: args.axis_continuous,
|
||||
axis_discrete: args.axis_discrete,
|
||||
axis_continuous: info.axis_continuous,
|
||||
axis_discrete: info.axis_discrete,
|
||||
},
|
||||
);
|
||||
panel_item.flush_clients();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn pointer_set_active_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
let active: bool = deserialize(data)?;
|
||||
debug!(?toplevel, active, "Pointer set active");
|
||||
|
||||
panel_item.seat_data.set_pointer_active(&toplevel, active);
|
||||
panel_item.flush_clients();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keyboard_set_keymap_string_flex(
|
||||
node: &Node,
|
||||
@@ -397,38 +413,32 @@ impl PanelItem {
|
||||
}
|
||||
fn keyboard_set_keymap_flex(node: &Node, keymap: &Keymap) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
let toplevel = panel_item.toplevel_wl_surface();
|
||||
debug!(?toplevel, "Keyboard set keymap");
|
||||
|
||||
panel_item.seat_data.set_keymap(&toplevel, keymap);
|
||||
let mut surfaces = vec![toplevel];
|
||||
surfaces.extend(panel_item.popups.lock().values().filter_map(|p| {
|
||||
let popup = p.upgrade().ok()?;
|
||||
let popup_data = PopupData::get(&popup).lock();
|
||||
let xdg_surface = popup_data.xdg_surface();
|
||||
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface).lock();
|
||||
Some(xdg_surface_data.wl_surface())
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keyboard_set_active_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
let active: bool = deserialize(data)?;
|
||||
debug!(?toplevel, active, "Keyboard set active");
|
||||
|
||||
panel_item.seat_data.set_keyboard_active(&toplevel, active);
|
||||
panel_item.seat_data.set_keymap(keymap, surfaces);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keyboard_key_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
let (key, state): (u32, u32) = deserialize(data)?;
|
||||
let (surface_id, key, state): (SurfaceID, u32, u32) = deserialize(data)?;
|
||||
let wl_surface = panel_item.wl_surface_from_id_result(&surface_id)?;
|
||||
debug!(key, state, "Set keyboard key state");
|
||||
|
||||
panel_item
|
||||
.seat_data
|
||||
.keyboard_event(&toplevel, KeyboardEvent::Key { key, state });
|
||||
.keyboard_event(&wl_surface, KeyboardEvent::Key { key, state });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -441,7 +451,7 @@ impl PanelItem {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Ok(xdg_toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
let Some(xdg_surface) = panel_item.toplevel_surface_data().and_then(|d| d.xdg_surface.upgrade().ok()) else { return Ok(()) };
|
||||
let xdg_surface = panel_item.toplevel_xdg_surface();
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct ConfigureToplevelInfo {
|
||||
@@ -452,9 +462,6 @@ impl PanelItem {
|
||||
|
||||
let info: ConfigureToplevelInfo = deserialize(data)?;
|
||||
debug!(info = ?&info, "Configure toplevel info");
|
||||
if let Some(xdg_state) = panel_item.toplevel_state() {
|
||||
xdg_state.lock().queued_state.as_mut().unwrap().states = info.states.clone();
|
||||
}
|
||||
if let Some(bounds) = info.bounds {
|
||||
if xdg_toplevel.version() > EVT_CONFIGURE_BOUNDS_SINCE {
|
||||
xdg_toplevel.configure_bounds(bounds.x as i32, bounds.y as i32);
|
||||
@@ -483,7 +490,10 @@ impl PanelItem {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Ok(xdg_toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
let Some(xdg_surface) = panel_item.toplevel_surface_data().and_then(|d| d.xdg_surface.upgrade().ok()) else { return Ok(()) };
|
||||
if xdg_toplevel.version() < EVT_WM_CAPABILITIES_SINCE {
|
||||
return Ok(());
|
||||
}
|
||||
let xdg_surface = panel_item.toplevel_xdg_surface();
|
||||
|
||||
let capabilities: Vec<u8> = deserialize(data)?;
|
||||
debug!("Set toplevel capabilities");
|
||||
@@ -495,23 +505,22 @@ impl PanelItem {
|
||||
}
|
||||
|
||||
pub fn commit_toplevel(&self) {
|
||||
let mapped_size = self.core_surface().and_then(|c| c.size());
|
||||
let Some(state) = self.toplevel_state() else { return };
|
||||
let mut state = state.lock();
|
||||
let mut queued_state = state.queued_state.take().unwrap();
|
||||
queued_state.mapped = mapped_size.is_some();
|
||||
if let Some(size) = mapped_size {
|
||||
queued_state.size = size;
|
||||
}
|
||||
*state = (*queued_state).clone();
|
||||
state.queued_state = Some(queued_state);
|
||||
// let mapped_size = self.core_surface().and_then(|c| c.size());
|
||||
let toplevel = self.toplevel();
|
||||
let state = ToplevelData::get(&toplevel);
|
||||
let state = state.lock();
|
||||
// let mut queued_state = state.queued_state.take().unwrap();
|
||||
// queued_state.mapped = mapped_size.is_some();
|
||||
// if let Some(size) = mapped_size {
|
||||
// queued_state.size = size;
|
||||
// queued_state.geometry.update_to_surface_size(size);
|
||||
// }
|
||||
// *state = (*queued_state).clone();
|
||||
// state.queued_state = Some(queued_state);
|
||||
|
||||
debug!(state = ?&state.mapped.then_some(&*state), "Commit toplevel");
|
||||
debug!(state = ?&*state, "Commit toplevel");
|
||||
let Some(node) = self.node.upgrade() else { return };
|
||||
let _ = node.send_remote_signal(
|
||||
"commit_toplevel",
|
||||
&serialize(&state.mapped.then_some(&*state)).unwrap(),
|
||||
);
|
||||
let _ = node.send_remote_signal("commit_toplevel", &serialize(&*state).unwrap());
|
||||
}
|
||||
|
||||
pub fn recommend_toplevel_state(&self, state: RecommendedState) {
|
||||
@@ -522,6 +531,56 @@ impl PanelItem {
|
||||
let _ = node.send_remote_signal("recommend_toplevel_state", &data);
|
||||
}
|
||||
|
||||
pub fn new_popup(&self, popup: &XdgPopup, data: &PopupData) {
|
||||
let uid = data.uid.clone();
|
||||
|
||||
self.popups.lock().insert(uid.clone(), popup.downgrade());
|
||||
|
||||
let Some(node) = self.node.upgrade() else { return };
|
||||
let _ = node.send_remote_signal("new_popup", &serialize(&(&uid, data)).unwrap());
|
||||
}
|
||||
// pub fn commit_popup(&self, data: &PopupData) {
|
||||
// let xdg_surf = data.xdg_surface.upgrade().unwrap();
|
||||
// let surf = xdg_surf
|
||||
// .data::<XdgSurfaceData>()
|
||||
// .unwrap()
|
||||
// .wl_surface
|
||||
// .upgrade()
|
||||
// .unwrap();
|
||||
|
||||
// let core_surface =
|
||||
// compositor::with_states(&surf, |s| s.data_map.get::<Arc<CoreSurface>>().cloned())
|
||||
// .unwrap();
|
||||
// let mut popup_state = data.state.lock();
|
||||
// popup_state.mapped = core_surface.size().is_some();
|
||||
// }
|
||||
pub fn reposition_popup(&self, popup_state: &PopupData) {
|
||||
let Some(node) = self.node.upgrade() else { return };
|
||||
|
||||
let _ = node.send_remote_signal(
|
||||
"reposition_popup",
|
||||
&serialize(popup_state.positioner_data().unwrap()).unwrap(),
|
||||
);
|
||||
}
|
||||
pub fn drop_popup(&self, uid: &str) {
|
||||
if let Some(popup) = self
|
||||
.popups
|
||||
.lock()
|
||||
.remove(uid)
|
||||
.and_then(|popup| popup.upgrade().ok()?.data::<Arc<PopupData>>().cloned())
|
||||
{
|
||||
self.seat_data.drop_surface(&popup.wl_surface());
|
||||
}
|
||||
|
||||
let Some(node) = self.node.upgrade() else { return };
|
||||
let _ = node.send_remote_signal("drop_popup", &serialize(uid).unwrap());
|
||||
}
|
||||
|
||||
pub fn grab_keyboard(&self, sid: Option<SurfaceID>) {
|
||||
let Some(node) = self.node.upgrade() else { return };
|
||||
|
||||
let _ = node.send_remote_signal("grab_keyboard", &serialize(sid).unwrap());
|
||||
}
|
||||
pub fn set_cursor(&self, surface: Option<&WlSurface>, hotspot_x: i32, hotspot_y: i32) {
|
||||
let Some(node) = self.node.upgrade() else { return };
|
||||
debug!(?surface, hotspot_x, hotspot_y, "Set cursor size");
|
||||
@@ -540,8 +599,8 @@ impl PanelItem {
|
||||
}
|
||||
|
||||
pub fn on_drop(&self) {
|
||||
let Ok(toplevel) = self.toplevel.upgrade() else { return; };
|
||||
self.seat_data.drop_panel_item(&toplevel);
|
||||
let toplevel = self.toplevel_wl_surface();
|
||||
self.seat_data.drop_surface(&toplevel);
|
||||
|
||||
debug!("Drop panel item");
|
||||
}
|
||||
@@ -559,12 +618,35 @@ impl ItemSpecialization for PanelItem {
|
||||
})
|
||||
.map(|cursor| cursor.hotspot);
|
||||
|
||||
let toplevel_state = self.toplevel_state();
|
||||
let toplevel_state = toplevel_state.as_ref().map(|state| state.lock());
|
||||
let toplevel_state = toplevel_state
|
||||
.as_ref()
|
||||
.and_then(|state| state.mapped.then_some(&**state));
|
||||
let toplevel = self.toplevel();
|
||||
let toplevel_state = ToplevelData::get(&toplevel);
|
||||
let toplevel_state = toplevel_state.lock().clone();
|
||||
|
||||
serialize((id, (toplevel_state, cursor_size.zip(cursor_hotspot)))).unwrap()
|
||||
let popups = self
|
||||
.popups
|
||||
.lock()
|
||||
.values()
|
||||
.filter_map(|v| Some(v.upgrade().ok()?.data::<Mutex<PopupData>>()?.lock().clone()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let pointer_grab = self.pointer_grab.lock().clone();
|
||||
let keyboard_grab = self.keyboard_grab.lock().clone();
|
||||
|
||||
serialize((
|
||||
id,
|
||||
(
|
||||
cursor_size.zip(cursor_hotspot),
|
||||
toplevel_state,
|
||||
popups,
|
||||
pointer_grab,
|
||||
keyboard_grab,
|
||||
),
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
impl Drop for PanelItem {
|
||||
fn drop(&mut self) {
|
||||
// Dropped panel item, basically just a debug breakpoint place
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user