refactor(wayland): many things
This commit is contained in:
@@ -71,6 +71,13 @@ impl Default for SurfaceState {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl SurfaceState {
|
||||
pub fn has_valid_buffer(&self) -> bool {
|
||||
self.buffer
|
||||
.as_ref()
|
||||
.is_some_and(|b| b.buffer.size().x > 0 && b.buffer.size().y > 0)
|
||||
}
|
||||
}
|
||||
|
||||
// if returning false, don't run this callback again... just remove it
|
||||
pub type OnCommitCallback = Box<dyn Fn(&Surface, &SurfaceState) -> bool + Send + Sync>;
|
||||
|
||||
@@ -3,10 +3,16 @@ use crate::{
|
||||
core::error::Result,
|
||||
nodes::{
|
||||
drawable::model::ModelPart,
|
||||
items::panel::{Backend, Geometry, PanelItemInitData, SurfaceId, ToplevelInfo},
|
||||
items::panel::{
|
||||
Backend, ChildInfo, Geometry, PanelItem, PanelItemInitData, SurfaceId, ToplevelInfo,
|
||||
},
|
||||
},
|
||||
wayland::{
|
||||
Message,
|
||||
core::{seat::SeatMessage, surface::Surface},
|
||||
},
|
||||
wayland::{Message, core::surface::Surface},
|
||||
};
|
||||
use dashmap::DashMap;
|
||||
use mint::Vector2;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Weak;
|
||||
@@ -15,12 +21,14 @@ use tracing;
|
||||
#[derive(Debug)]
|
||||
pub struct XdgBackend {
|
||||
toplevel: Weak<Toplevel>,
|
||||
children: DashMap<u64, (Weak<Surface>, ChildInfo)>,
|
||||
}
|
||||
|
||||
impl XdgBackend {
|
||||
pub fn new(toplevel: Arc<Toplevel>) -> Self {
|
||||
Self {
|
||||
toplevel: Arc::downgrade(&toplevel),
|
||||
children: DashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,14 +40,59 @@ impl XdgBackend {
|
||||
.expect("Toplevel should always be valid while XdgBackend exists")
|
||||
}
|
||||
|
||||
fn surface_from_id(&self, id: SurfaceId) -> Option<Arc<Surface>> {
|
||||
pub fn panel_item(&self) -> Option<Arc<PanelItem<XdgBackend>>> {
|
||||
self.toplevel().wl_surface().panel_item.lock().upgrade()
|
||||
}
|
||||
|
||||
fn surface_from_id(&self, id: &SurfaceId) -> Option<Arc<Surface>> {
|
||||
match id {
|
||||
SurfaceId::Toplevel(_) => Some(self.toplevel().wl_surface().clone()),
|
||||
SurfaceId::Child(_) => None,
|
||||
SurfaceId::Child(id) => self.children.get(id).as_deref().and_then(|c| c.0.upgrade()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_child(&self, surface: &Arc<Surface>, info: ChildInfo) {
|
||||
let Some(SurfaceId::Child(id)) = surface.surface_id.get().cloned() else {
|
||||
return;
|
||||
};
|
||||
self.children
|
||||
.insert(id, (Arc::downgrade(surface), info.clone()));
|
||||
|
||||
let Some(panel_item) = self.panel_item() else {
|
||||
tracing::error!("Couldn't find panel item in add_child");
|
||||
return;
|
||||
};
|
||||
panel_item.create_child(id, &info);
|
||||
}
|
||||
|
||||
pub fn reposition_child(&self, surface: &Arc<Surface>, geometry: Geometry) {
|
||||
let Some(SurfaceId::Child(id)) = surface.surface_id.get() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(mut child) = self.children.get_mut(&id) {
|
||||
child.1.geometry = geometry;
|
||||
}
|
||||
let Some(panel_item) = self.panel_item() else {
|
||||
tracing::error!("Couldn't find panel item in reposition_child");
|
||||
return;
|
||||
};
|
||||
panel_item.reposition_child(*id, &geometry);
|
||||
}
|
||||
|
||||
pub fn remove_child(&self, surface: &Surface) {
|
||||
let Some(SurfaceId::Child(id)) = surface.surface_id.get() else {
|
||||
return;
|
||||
};
|
||||
self.children.remove(id);
|
||||
|
||||
let Some(panel_item) = self.panel_item() else {
|
||||
tracing::error!("Couldn't find panel item in remove_child");
|
||||
return;
|
||||
};
|
||||
panel_item.destroy_child(*id);
|
||||
}
|
||||
}
|
||||
impl Backend for XdgBackend {
|
||||
fn start_data(&self) -> Result<PanelItemInitData> {
|
||||
let surface_state = self.toplevel().wl_surface().current_state();
|
||||
@@ -76,7 +129,7 @@ impl Backend for XdgBackend {
|
||||
|
||||
fn apply_cursor_material(&self, _model_part: &Arc<ModelPart>) {}
|
||||
fn apply_surface_material(&self, surface: SurfaceId, model_part: &Arc<ModelPart>) {
|
||||
if let Some(surface) = self.surface_from_id(surface) {
|
||||
if let Some(surface) = self.surface_from_id(&surface) {
|
||||
surface.apply_material(model_part);
|
||||
}
|
||||
}
|
||||
@@ -123,30 +176,29 @@ impl Backend for XdgBackend {
|
||||
}
|
||||
|
||||
fn pointer_motion(&self, surface: &SurfaceId, position: Vector2<f32>) {
|
||||
if let Some(surface) = self.surface_from_id(surface.clone()) {
|
||||
if let Some(surface) = self.surface_from_id(surface) {
|
||||
let _ = self
|
||||
.toplevel()
|
||||
.wl_surface()
|
||||
.message_sink
|
||||
.send(Message::Seat(
|
||||
crate::wayland::core::seat::SeatMessage::PointerMotion { surface, position },
|
||||
));
|
||||
.send(Message::Seat(SeatMessage::PointerMotion {
|
||||
surface,
|
||||
position,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
fn pointer_button(&self, surface: &SurfaceId, button: u32, pressed: bool) {
|
||||
if let Some(surface) = self.surface_from_id(surface.clone()) {
|
||||
if let Some(surface) = self.surface_from_id(surface) {
|
||||
let _ = self
|
||||
.toplevel()
|
||||
.wl_surface()
|
||||
.message_sink
|
||||
.send(Message::Seat(
|
||||
crate::wayland::core::seat::SeatMessage::PointerButton {
|
||||
surface,
|
||||
button,
|
||||
pressed,
|
||||
},
|
||||
));
|
||||
.send(Message::Seat(SeatMessage::PointerButton {
|
||||
surface,
|
||||
button,
|
||||
pressed,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,18 +208,16 @@ impl Backend for XdgBackend {
|
||||
scroll_distance: Option<Vector2<f32>>,
|
||||
scroll_steps: Option<Vector2<f32>>,
|
||||
) {
|
||||
if let Some(surface) = self.surface_from_id(surface.clone()) {
|
||||
if let Some(surface) = self.surface_from_id(surface) {
|
||||
let _ = self
|
||||
.toplevel()
|
||||
.wl_surface()
|
||||
.message_sink
|
||||
.send(Message::Seat(
|
||||
crate::wayland::core::seat::SeatMessage::PointerScroll {
|
||||
surface,
|
||||
scroll_distance,
|
||||
scroll_steps,
|
||||
},
|
||||
));
|
||||
.send(Message::Seat(SeatMessage::PointerScroll {
|
||||
surface,
|
||||
scroll_distance,
|
||||
scroll_steps,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,19 +227,17 @@ impl Backend for XdgBackend {
|
||||
key,
|
||||
if pressed { "pressed" } else { "released" }
|
||||
);
|
||||
if let Some(surface) = self.surface_from_id(surface.clone()) {
|
||||
if let Some(surface) = self.surface_from_id(surface) {
|
||||
let _ = self
|
||||
.toplevel()
|
||||
.wl_surface()
|
||||
.message_sink
|
||||
.send(Message::Seat(
|
||||
crate::wayland::core::seat::SeatMessage::KeyboardKey {
|
||||
surface,
|
||||
keymap_id,
|
||||
key,
|
||||
pressed,
|
||||
},
|
||||
));
|
||||
.send(Message::Seat(SeatMessage::KeyboardKey {
|
||||
surface,
|
||||
keymap_id,
|
||||
key,
|
||||
pressed,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,18 +248,16 @@ impl Backend for XdgBackend {
|
||||
position.x,
|
||||
position.y
|
||||
);
|
||||
if let Some(surface) = self.surface_from_id(surface.clone()) {
|
||||
if let Some(surface) = self.surface_from_id(surface) {
|
||||
let _ = self
|
||||
.toplevel()
|
||||
.wl_surface()
|
||||
.message_sink
|
||||
.send(Message::Seat(
|
||||
crate::wayland::core::seat::SeatMessage::TouchDown {
|
||||
surface,
|
||||
id,
|
||||
position,
|
||||
},
|
||||
));
|
||||
.send(Message::Seat(SeatMessage::TouchDown {
|
||||
surface,
|
||||
id,
|
||||
position,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,24 +269,27 @@ impl Backend for XdgBackend {
|
||||
position.y
|
||||
);
|
||||
let toplevel = self.toplevel();
|
||||
let _ = toplevel.wl_surface().message_sink.send(Message::Seat(
|
||||
crate::wayland::core::seat::SeatMessage::TouchMove { id, position },
|
||||
));
|
||||
let _ = toplevel
|
||||
.wl_surface()
|
||||
.message_sink
|
||||
.send(Message::Seat(SeatMessage::TouchMove { id, position }));
|
||||
}
|
||||
|
||||
fn touch_up(&self, id: u32) {
|
||||
tracing::debug!("Backend: Touch up {}", id);
|
||||
let toplevel = self.toplevel();
|
||||
let _ = toplevel.wl_surface().message_sink.send(Message::Seat(
|
||||
crate::wayland::core::seat::SeatMessage::TouchUp { id },
|
||||
));
|
||||
let _ = toplevel
|
||||
.wl_surface()
|
||||
.message_sink
|
||||
.send(Message::Seat(SeatMessage::TouchUp { id }));
|
||||
}
|
||||
|
||||
fn reset_input(&self) {
|
||||
tracing::debug!("Backend: Reset input");
|
||||
let toplevel = self.toplevel();
|
||||
let _ = toplevel.wl_surface().message_sink.send(Message::Seat(
|
||||
crate::wayland::core::seat::SeatMessage::Reset,
|
||||
));
|
||||
let _ = toplevel
|
||||
.wl_surface()
|
||||
.message_sink
|
||||
.send(Message::Seat(SeatMessage::Reset));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
use super::{
|
||||
backend::XdgBackend,
|
||||
positioner::{Positioner, PositionerData},
|
||||
surface::Surface,
|
||||
};
|
||||
use crate::{
|
||||
nodes::items::panel::{Geometry, PanelItem, SurfaceId},
|
||||
nodes::items::panel::{Geometry, SurfaceId},
|
||||
wayland::util::DoubleBuffer,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use rand::Rng;
|
||||
use std::sync::{Arc, Weak, atomic::AtomicBool};
|
||||
use std::sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
use waynest::{
|
||||
server::{Client, Dispatcher, Result, protocol::stable::xdg_shell::xdg_popup::XdgPopup},
|
||||
wire::ObjectId,
|
||||
@@ -20,8 +22,7 @@ pub struct Popup {
|
||||
id: ObjectId,
|
||||
version: u32,
|
||||
parent: Arc<Surface>,
|
||||
surface: Arc<Surface>,
|
||||
pub panel_item: Weak<PanelItem<XdgBackend>>,
|
||||
pub surface: Arc<Surface>,
|
||||
positioner_data: Mutex<PositionerData>,
|
||||
geometry: DoubleBuffer<Geometry>,
|
||||
mapped: AtomicBool,
|
||||
@@ -31,7 +32,6 @@ impl Popup {
|
||||
id: ObjectId,
|
||||
version: u32,
|
||||
parent: Arc<Surface>,
|
||||
panel_item: &Arc<PanelItem<XdgBackend>>,
|
||||
surface: Arc<Surface>,
|
||||
positioner: &Positioner,
|
||||
) -> Self {
|
||||
@@ -46,7 +46,6 @@ impl Popup {
|
||||
version,
|
||||
parent,
|
||||
surface,
|
||||
panel_item: Arc::downgrade(panel_item),
|
||||
positioner_data: Mutex::new(positioner_data),
|
||||
geometry: DoubleBuffer::new(positioner_data.infinite_geometry()),
|
||||
mapped: AtomicBool::new(false),
|
||||
@@ -90,6 +89,13 @@ impl XdgPopup for Popup {
|
||||
)
|
||||
.await?;
|
||||
self.surface.reconfigure(client).await?;
|
||||
|
||||
let Some(panel_item) = self.surface.wl_surface.panel_item.lock().upgrade() else {
|
||||
return Ok(());
|
||||
};
|
||||
panel_item
|
||||
.backend
|
||||
.reposition_child(&self.surface.wl_surface, geometry);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -98,3 +104,14 @@ impl XdgPopup for Popup {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl Drop for Popup {
|
||||
fn drop(&mut self) {
|
||||
if !self.mapped.load(Ordering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
let Some(panel_item) = self.surface.wl_surface.panel_item.lock().upgrade() else {
|
||||
return;
|
||||
};
|
||||
panel_item.backend.remove_child(&self.surface.wl_surface);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use super::{popup::Popup, positioner::Positioner, toplevel::MappedInner};
|
||||
use crate::nodes::items::panel::{ChildInfo, SurfaceId};
|
||||
use crate::wayland::util::ClientExt;
|
||||
use crate::wayland::{core::surface::SurfaceRole, display::Display, xdg::toplevel::Toplevel};
|
||||
use std::sync::Arc;
|
||||
use waynest::server;
|
||||
pub use waynest::server::protocol::stable::xdg_shell::xdg_surface::*;
|
||||
use waynest::{
|
||||
server::{Client, Dispatcher, Result},
|
||||
@@ -81,23 +81,19 @@ impl XdgSurface for Surface {
|
||||
let toplevel_weak = Arc::downgrade(&toplevel);
|
||||
let pid = client.get::<Display>(ObjectId::DISPLAY).unwrap().pid;
|
||||
let configured = self.configured.clone();
|
||||
self.wl_surface.add_commit_handler(move |_surface, state| {
|
||||
self.wl_surface.add_commit_handler(move |surface, state| {
|
||||
let Some(toplevel) = toplevel_weak.upgrade() else {
|
||||
return true;
|
||||
};
|
||||
|
||||
// Only proceed if configured and has valid buffer
|
||||
let has_valid_buffer = state
|
||||
.buffer
|
||||
.as_ref()
|
||||
.is_some_and(|b| b.buffer.size().x > 0 && b.buffer.size().y > 0);
|
||||
|
||||
let mut mapped_lock = toplevel.mapped.lock();
|
||||
if mapped_lock.is_none()
|
||||
&& configured.load(std::sync::atomic::Ordering::SeqCst)
|
||||
&& has_valid_buffer
|
||||
&& state.has_valid_buffer()
|
||||
{
|
||||
mapped_lock.replace(MappedInner::create(toplevel.clone(), pid));
|
||||
let mapped_inner = MappedInner::create(toplevel.clone(), pid);
|
||||
*surface.panel_item.lock() = Arc::downgrade(&mapped_inner.panel_item);
|
||||
mapped_lock.replace(mapped_inner);
|
||||
return false;
|
||||
}
|
||||
true
|
||||
@@ -152,53 +148,52 @@ impl XdgSurface for Surface {
|
||||
)
|
||||
.await;
|
||||
};
|
||||
let Some(panel_item) = parent.wl_surface.panel_item.lock().upgrade() else {
|
||||
return Err(server::Error::Custom(
|
||||
"Parent surface does not have a panel item".to_string(),
|
||||
));
|
||||
};
|
||||
*self.wl_surface.panel_item.lock() = parent.wl_surface.panel_item.lock().clone();
|
||||
let positioner = client.get::<Positioner>(positioner).unwrap();
|
||||
|
||||
let surface = client.get::<Surface>(self.id).unwrap();
|
||||
|
||||
let popup = client.insert(
|
||||
popup_id,
|
||||
Popup::new(
|
||||
popup_id,
|
||||
self.version,
|
||||
parent,
|
||||
&panel_item,
|
||||
surface,
|
||||
&positioner,
|
||||
),
|
||||
Popup::new(popup_id, self.version, parent.clone(), surface, &positioner),
|
||||
);
|
||||
|
||||
let serial = client.next_event_serial();
|
||||
self.configure(client, sender_id, serial).await?;
|
||||
|
||||
// let pid = client.get::<Display>(ObjectId::DISPLAY).unwrap().pid;
|
||||
// let configured = self.configured.clone();
|
||||
// surface.add_commit_handler(move |surface, state| {
|
||||
// let Some(SurfaceRole::XDGPopup(popup)) = &mut *surface.role.lock() else {
|
||||
// return true;
|
||||
// };
|
||||
let Some(SurfaceId::Child(id)) = self.wl_surface.surface_id.get() else {
|
||||
return Ok(());
|
||||
};
|
||||
let Some(parent_id) = parent.wl_surface.surface_id.get() else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
// // Only proceed if configured and has valid buffer
|
||||
// let has_valid_buffer = state
|
||||
// .buffer
|
||||
// .as_ref()
|
||||
// .is_some_and(|b| b.buffer.size().x > 0 && b.buffer.size().y > 0);
|
||||
let child_info = ChildInfo {
|
||||
id: *id,
|
||||
parent: parent_id.clone(),
|
||||
geometry: positioner.data().infinite_geometry(),
|
||||
z_order: 1,
|
||||
receives_input: true,
|
||||
};
|
||||
|
||||
// let mut mapped_lock = popup.mapped.lock();
|
||||
// if mapped_lock.is_none()
|
||||
// && configured.load(std::sync::atomic::Ordering::SeqCst)
|
||||
// && has_valid_buffer
|
||||
// {
|
||||
// mapped_lock.replace(Mapped::create(popup.clone(), pid));
|
||||
// return false;
|
||||
// }
|
||||
// true
|
||||
// });
|
||||
let popup_weak = Arc::downgrade(&popup);
|
||||
let configured = self.configured.clone();
|
||||
self.wl_surface.add_commit_handler(move |surface, state| {
|
||||
let Some(popup) = popup_weak.upgrade() else {
|
||||
return true;
|
||||
};
|
||||
let Some(panel_item) = surface.panel_item.lock().upgrade() else {
|
||||
return true;
|
||||
};
|
||||
|
||||
if configured.load(std::sync::atomic::Ordering::SeqCst) && state.has_valid_buffer() {
|
||||
panel_item
|
||||
.backend
|
||||
.add_child(&popup.surface.wl_surface, child_info.clone());
|
||||
return false;
|
||||
}
|
||||
true
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -18,16 +18,16 @@ use waynest::{
|
||||
#[derive(Debug)]
|
||||
pub struct MappedInner {
|
||||
pub panel_item_node: Arc<Node>,
|
||||
pub _panel_item: Arc<PanelItem<XdgBackend>>,
|
||||
pub panel_item: Arc<PanelItem<XdgBackend>>,
|
||||
}
|
||||
impl MappedInner {
|
||||
pub fn create(toplevel: Arc<Toplevel>, pid: Option<i32>) -> Self {
|
||||
let (panel_item_node, _panel_item) =
|
||||
let (panel_item_node, panel_item) =
|
||||
PanelItem::create(Box::new(XdgBackend::new(toplevel)), pid);
|
||||
|
||||
Self {
|
||||
panel_item_node,
|
||||
_panel_item,
|
||||
panel_item,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user