refactor(wayland): less crashy
This commit is contained in:
19
src/main.rs
19
src/main.rs
@@ -192,13 +192,13 @@ fn main() {
|
|||||||
let mut wayland = wayland::Wayland::new().unwrap();
|
let mut wayland = wayland::Wayland::new().unwrap();
|
||||||
info!("Stardust ready!");
|
info!("Stardust ready!");
|
||||||
|
|
||||||
if let Some(project_dirs) = project_dirs.as_ref() {
|
let startup_child = if let Some(project_dirs) = project_dirs.as_ref() {
|
||||||
let startup_script_path = cli_args
|
let startup_script_path = cli_args
|
||||||
.startup_script
|
.startup_script
|
||||||
.clone()
|
.clone()
|
||||||
.and_then(|p| p.canonicalize().ok())
|
.and_then(|p| p.canonicalize().ok())
|
||||||
.unwrap_or_else(|| project_dirs.config_dir().join("startup"));
|
.unwrap_or_else(|| project_dirs.config_dir().join("startup"));
|
||||||
let _startup = Command::new(startup_script_path)
|
Command::new(startup_script_path)
|
||||||
.stdin(Stdio::null())
|
.stdin(Stdio::null())
|
||||||
.env(
|
.env(
|
||||||
"FLAT_WAYLAND_DISPLAY",
|
"FLAT_WAYLAND_DISPLAY",
|
||||||
@@ -218,8 +218,11 @@ fn main() {
|
|||||||
.env("MOZ_ENABLE_WAYLAND", "1")
|
.env("MOZ_ENABLE_WAYLAND", "1")
|
||||||
.env("CLUTTER_BACKEND", "wayland")
|
.env("CLUTTER_BACKEND", "wayland")
|
||||||
.env("SDL_VIDEODRIVER", "wayland")
|
.env("SDL_VIDEODRIVER", "wayland")
|
||||||
.spawn();
|
.spawn()
|
||||||
}
|
.ok()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let mut last_frame_delta = Duration::ZERO;
|
let mut last_frame_delta = Duration::ZERO;
|
||||||
let mut sleep_duration = Duration::ZERO;
|
let mut sleep_duration = Duration::ZERO;
|
||||||
@@ -273,14 +276,18 @@ fn main() {
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(feature = "wayland")]
|
if let Some(mut startup_child) = startup_child {
|
||||||
let _wayland = ManuallyDrop::new(wayland);
|
let _ = startup_child.kill();
|
||||||
|
}
|
||||||
|
|
||||||
let _ = event_stop_tx.send(());
|
let _ = event_stop_tx.send(());
|
||||||
event_thread
|
event_thread
|
||||||
.join()
|
.join()
|
||||||
.expect("Failed to cleanly shut down event loop")
|
.expect("Failed to cleanly shut down event loop")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
|
let _wayland = ManuallyDrop::new(wayland);
|
||||||
|
|
||||||
info!("Cleanly shut down Stardust");
|
info!("Cleanly shut down Stardust");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ impl EnvironmentItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ItemSpecialization for EnvironmentItem {
|
impl ItemSpecialization for EnvironmentItem {
|
||||||
fn serialize_start_data(&self, id: &str) -> Vec<u8> {
|
fn serialize_start_data(&self, id: &str) -> Option<Vec<u8>> {
|
||||||
serialize((id, self.path.as_str())).unwrap()
|
serialize((id, self.path.as_str())).ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ impl Drop for Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait ItemSpecialization {
|
pub trait ItemSpecialization {
|
||||||
fn serialize_start_data(&self, id: &str) -> Vec<u8>;
|
fn serialize_start_data(&self, id: &str) -> Option<Vec<u8>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ItemType {
|
pub enum ItemType {
|
||||||
@@ -240,10 +240,8 @@ impl ItemUI {
|
|||||||
self.item_aliases.add(item.uid.clone(), &alias_node);
|
self.item_aliases.add(item.uid.clone(), &alias_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = node.send_remote_signal(
|
let Some(serialized_data) = item.specialization.serialize_start_data(&item.uid) else {return};
|
||||||
"create_item",
|
let _ = node.send_remote_signal("create_item", &serialized_data);
|
||||||
&item.specialization.serialize_start_data(&item.uid),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
fn handle_destroy_item(&self, item: &Item) {
|
fn handle_destroy_item(&self, item: &Item) {
|
||||||
self.item_aliases.remove(&item.uid);
|
self.item_aliases.remove(&item.uid);
|
||||||
@@ -360,10 +358,9 @@ impl ItemAcceptor {
|
|||||||
if let Ok(alias_node) = item.make_alias(&client, &node.path) {
|
if let Ok(alias_node) = item.make_alias(&client, &node.path) {
|
||||||
self.accepted_aliases.add(item.uid.clone(), &alias_node);
|
self.accepted_aliases.add(item.uid.clone(), &alias_node);
|
||||||
}
|
}
|
||||||
let _ = node.send_remote_signal(
|
|
||||||
"capture",
|
let Some(serialized_data) = item.specialization.serialize_start_data(&item.uid) else {return};
|
||||||
&item.specialization.serialize_start_data(&item.uid),
|
let _ = node.send_remote_signal("capture", &serialized_data);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
fn handle_release(&self, item: &Item) {
|
fn handle_release(&self, item: &Item) {
|
||||||
let Some(node) = self.node.upgrade() else { return };
|
let Some(node) = self.node.upgrade() else { return };
|
||||||
|
|||||||
@@ -156,50 +156,58 @@ pub enum RecommendedState {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct WaylandBackend {
|
pub struct WaylandBackend {
|
||||||
toplevel: WlWeak<XdgToplevel>,
|
toplevel: WlWeak<XdgToplevel>,
|
||||||
|
toplevel_wl_surface: WlWeak<WlSurface>,
|
||||||
popups: Mutex<FxHashMap<String, WlWeak<XdgPopup>>>,
|
popups: Mutex<FxHashMap<String, WlWeak<XdgPopup>>>,
|
||||||
cursor: Mutex<Option<WlWeak<WlSurface>>>,
|
cursor: Mutex<Option<WlWeak<WlSurface>>>,
|
||||||
}
|
}
|
||||||
impl WaylandBackend {
|
impl WaylandBackend {
|
||||||
pub fn create(toplevel: XdgToplevel) -> Self {
|
pub fn create(toplevel: XdgToplevel) -> Option<Self> {
|
||||||
WaylandBackend {
|
let toplevel_wl_surface =
|
||||||
|
XdgSurfaceData::get(&ToplevelData::get(&toplevel).lock().xdg_surface()?)?
|
||||||
|
.lock()
|
||||||
|
.wl_surface()?
|
||||||
|
.downgrade();
|
||||||
|
Some(WaylandBackend {
|
||||||
toplevel: toplevel.downgrade(),
|
toplevel: toplevel.downgrade(),
|
||||||
|
toplevel_wl_surface,
|
||||||
popups: Mutex::new(FxHashMap::default()),
|
popups: Mutex::new(FxHashMap::default()),
|
||||||
cursor: Mutex::new(None),
|
cursor: Mutex::new(None),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
fn toplevel(&self) -> XdgToplevel {
|
fn toplevel(&self) -> Option<XdgToplevel> {
|
||||||
self.toplevel.upgrade().unwrap()
|
self.toplevel.upgrade().ok()
|
||||||
}
|
}
|
||||||
fn toplevel_xdg_surface(&self) -> XdgSurface {
|
fn toplevel_xdg_surface(&self) -> Option<XdgSurface> {
|
||||||
let toplevel = self.toplevel();
|
let toplevel = self.toplevel()?;
|
||||||
let data = ToplevelData::get(&toplevel).lock();
|
let data = ToplevelData::get(&toplevel).lock();
|
||||||
data.xdg_surface()
|
data.xdg_surface()
|
||||||
}
|
}
|
||||||
fn toplevel_wl_surface(&self) -> WlSurface {
|
fn toplevel_wl_surface(&self) -> Option<WlSurface> {
|
||||||
XdgSurfaceData::get(&self.toplevel_xdg_surface())
|
self.toplevel_wl_surface.upgrade().ok()
|
||||||
.lock()
|
|
||||||
.wl_surface()
|
|
||||||
}
|
}
|
||||||
fn wl_surface_from_id(&self, id: &SurfaceID) -> Option<WlSurface> {
|
fn wl_surface_from_id(&self, id: &SurfaceID) -> Option<WlSurface> {
|
||||||
match id {
|
match id {
|
||||||
SurfaceID::Cursor => self.cursor.lock().clone()?.upgrade().ok(),
|
SurfaceID::Cursor => self.cursor.lock().clone()?.upgrade().ok(),
|
||||||
SurfaceID::Toplevel => Some(self.toplevel_wl_surface()),
|
SurfaceID::Toplevel => self.toplevel_wl_surface(),
|
||||||
SurfaceID::Popup(popup) => {
|
SurfaceID::Popup(popup) => {
|
||||||
let popups = self.popups.lock();
|
let popups = self.popups.lock();
|
||||||
let popup = popups.get(popup)?.upgrade().ok()?;
|
let popup = popups.get(popup)?.upgrade().ok()?;
|
||||||
let surf = PopupData::get(&popup).lock().wl_surface();
|
let wl_surface = PopupData::get(&popup)?.lock().wl_surface();
|
||||||
Some(surf)
|
wl_surface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn input_surfaces(&self) -> Vec<WlSurface> {
|
fn input_surfaces(&self) -> Vec<WlSurface> {
|
||||||
let mut surfaces = vec![self.toplevel_wl_surface()];
|
let mut surfaces = self
|
||||||
|
.toplevel_wl_surface()
|
||||||
|
.map(|s| vec![s])
|
||||||
|
.unwrap_or_default();
|
||||||
surfaces.extend(self.popups.lock().values().filter_map(|p| {
|
surfaces.extend(self.popups.lock().values().filter_map(|p| {
|
||||||
let popup = p.upgrade().ok()?;
|
let popup = p.upgrade().ok()?;
|
||||||
let popup_data = PopupData::get(&popup).lock();
|
let popup_data = PopupData::get(&popup)?.lock();
|
||||||
let xdg_surface = popup_data.xdg_surface();
|
let xdg_surface = popup_data.xdg_surface()?;
|
||||||
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface).lock();
|
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface)?.lock();
|
||||||
Some(xdg_surface_data.wl_surface())
|
xdg_surface_data.wl_surface()
|
||||||
}));
|
}));
|
||||||
surfaces
|
surfaces
|
||||||
}
|
}
|
||||||
@@ -211,7 +219,7 @@ impl WaylandBackend {
|
|||||||
bounds: Option<Vector2<u32>>,
|
bounds: Option<Vector2<u32>>,
|
||||||
) {
|
) {
|
||||||
let Ok(xdg_toplevel) = self.toplevel.upgrade() else {return};
|
let Ok(xdg_toplevel) = self.toplevel.upgrade() else {return};
|
||||||
let xdg_surface = self.toplevel_xdg_surface();
|
let Some(xdg_surface) = self.toplevel_xdg_surface() else {return};
|
||||||
debug!(?size, ?states, ?bounds, "Configure toplevel info");
|
debug!(?size, ?states, ?bounds, "Configure toplevel info");
|
||||||
if let Some(bounds) = bounds {
|
if let Some(bounds) = bounds {
|
||||||
if xdg_toplevel.version() > EVT_CONFIGURE_BOUNDS_SINCE {
|
if xdg_toplevel.version() > EVT_CONFIGURE_BOUNDS_SINCE {
|
||||||
@@ -231,15 +239,19 @@ impl WaylandBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_toplevel(&self) -> Result<Vec<u8>> {
|
fn serialize_toplevel(&self) -> Result<Vec<u8>> {
|
||||||
let toplevel = self.toplevel();
|
let toplevel = self
|
||||||
|
.toplevel()
|
||||||
|
.ok_or_else(|| eyre!("Toplevel does not exist"))?;
|
||||||
let state = ToplevelData::get(&toplevel);
|
let state = ToplevelData::get(&toplevel);
|
||||||
let data = serialize(&state.lock().clone())?;
|
let data = serialize(&state.lock().clone())?;
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_toplevel_capabilities(&self, capabilities: Vec<u8>) {
|
fn set_toplevel_capabilities(&self, capabilities: Vec<u8>) {
|
||||||
self.toplevel().wm_capabilities(capabilities);
|
let Ok(xdg_toplevel) = self.toplevel.upgrade() else {return};
|
||||||
self.toplevel_xdg_surface().configure(SERIAL_COUNTER.inc());
|
xdg_toplevel.wm_capabilities(capabilities);
|
||||||
|
let Some(xdg_surface) = self.toplevel_xdg_surface() else {return};
|
||||||
|
xdg_surface.configure(SERIAL_COUNTER.inc());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_popup(&self, panel_item: &PanelItem, popup: &XdgPopup, data: &PopupData) {
|
pub fn new_popup(&self, panel_item: &PanelItem, popup: &XdgPopup, data: &PopupData) {
|
||||||
@@ -259,13 +271,15 @@ impl WaylandBackend {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
pub fn drop_popup(&self, panel_item: &PanelItem, uid: &str) {
|
pub fn drop_popup(&self, panel_item: &PanelItem, uid: &str) {
|
||||||
if let Some(popup) = self
|
'seat_drop: {
|
||||||
.popups
|
let Some(popup) = self
|
||||||
.lock()
|
.popups
|
||||||
.remove(uid)
|
.lock()
|
||||||
.and_then(|popup| popup.upgrade().ok()?.data::<Arc<PopupData>>().cloned())
|
.remove(uid) else {break 'seat_drop};
|
||||||
{
|
let Some(popup) = popup.upgrade().ok() else {break 'seat_drop};
|
||||||
panel_item.seat_data.drop_surface(&popup.wl_surface());
|
let Some(popup) = popup.data::<Arc<PopupData>>().cloned() else {break 'seat_drop};
|
||||||
|
let Some(wl_surface) = popup.wl_surface() else {break 'seat_drop};
|
||||||
|
panel_item.seat_data.drop_surface(&wl_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(node) = panel_item.node.upgrade() else { return };
|
let Some(node) = panel_item.node.upgrade() else { return };
|
||||||
@@ -457,14 +471,14 @@ impl PanelItem {
|
|||||||
Some(panel_item.clone())
|
Some(panel_item.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toplevel_wl_surface(&self) -> WlSurface {
|
fn toplevel_wl_surface(&self) -> Option<WlSurface> {
|
||||||
match &self.backend {
|
match &self.backend {
|
||||||
Backend::Wayland(w) => w.toplevel_wl_surface(),
|
Backend::Wayland(w) => w.toplevel_wl_surface(),
|
||||||
Backend::X11(x) => x.toplevel.wl_surface().unwrap(),
|
Backend::X11(x) => x.toplevel.wl_surface(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn core_surface(&self) -> Option<Arc<CoreSurface>> {
|
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()
|
data.data_map.get::<Arc<CoreSurface>>().cloned()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -616,7 +630,10 @@ impl PanelItem {
|
|||||||
keymap,
|
keymap,
|
||||||
match &panel_item.backend {
|
match &panel_item.backend {
|
||||||
Backend::Wayland(w) => w.input_surfaces(),
|
Backend::Wayland(w) => w.input_surfaces(),
|
||||||
Backend::X11(_) => vec![panel_item.toplevel_wl_surface()],
|
Backend::X11(_) => panel_item
|
||||||
|
.toplevel_wl_surface()
|
||||||
|
.map(|s| vec![s])
|
||||||
|
.unwrap_or_default(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -666,7 +683,8 @@ impl PanelItem {
|
|||||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||||
if let Backend::Wayland(w) = &panel_item.backend {
|
if let Backend::Wayland(w) = &panel_item.backend {
|
||||||
if w.toplevel().version() < EVT_WM_CAPABILITIES_SINCE {
|
let Some(toplevel) = w.toplevel() else {return Ok(())};
|
||||||
|
if toplevel.version() < EVT_WM_CAPABILITIES_SINCE {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -707,17 +725,17 @@ impl PanelItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_drop(&self) {
|
pub fn on_drop(&self) {
|
||||||
let toplevel = self.toplevel_wl_surface();
|
let Some(toplevel) = self.toplevel_wl_surface() else {return};
|
||||||
self.seat_data.drop_surface(&toplevel);
|
self.seat_data.drop_surface(&toplevel);
|
||||||
|
|
||||||
debug!("Drop panel item");
|
debug!("Dropped panel item gracefully");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ItemSpecialization for PanelItem {
|
impl ItemSpecialization for PanelItem {
|
||||||
fn serialize_start_data(&self, id: &str) -> Vec<u8> {
|
fn serialize_start_data(&self, id: &str) -> Option<Vec<u8>> {
|
||||||
match &self.backend {
|
match &self.backend {
|
||||||
Backend::Wayland(w) => {
|
Backend::Wayland(w) => {
|
||||||
let toplevel = w.toplevel();
|
let toplevel = w.toplevel()?;
|
||||||
let toplevel_state = ToplevelData::get(&toplevel);
|
let toplevel_state = ToplevelData::get(&toplevel);
|
||||||
let toplevel_state = toplevel_state.lock().clone();
|
let toplevel_state = toplevel_state.lock().clone();
|
||||||
|
|
||||||
@@ -734,7 +752,7 @@ impl ItemSpecialization for PanelItem {
|
|||||||
keyboard_grab,
|
keyboard_grab,
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
.unwrap()
|
.ok()
|
||||||
}
|
}
|
||||||
Backend::X11(x) => {
|
Backend::X11(x) => {
|
||||||
let size = (
|
let size = (
|
||||||
@@ -761,7 +779,7 @@ impl ItemSpecialization for PanelItem {
|
|||||||
None::<SurfaceID>,
|
None::<SurfaceID>,
|
||||||
None::<SurfaceID>,
|
None::<SurfaceID>,
|
||||||
);
|
);
|
||||||
serialize((id, info)).unwrap()
|
serialize((id, info)).ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ impl WaylandState {
|
|||||||
);
|
);
|
||||||
let _output_global = output.create_global::<Self>(&display_handle);
|
let _output_global = output.create_global::<Self>(&display_handle);
|
||||||
let mode = Mode {
|
let mode = Mode {
|
||||||
size: (4096, 4096).into(),
|
size: (2048, 2048).into(),
|
||||||
refresh: 60000,
|
refresh: 60000,
|
||||||
};
|
};
|
||||||
output.change_current_state(
|
output.change_current_state(
|
||||||
|
|||||||
@@ -220,11 +220,11 @@ impl XdgSurfaceData {
|
|||||||
geometry: None,
|
geometry: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get(xdg_surface: &XdgSurface) -> &Mutex<Self> {
|
pub fn get(xdg_surface: &XdgSurface) -> Option<&Mutex<Self>> {
|
||||||
xdg_surface.data::<Mutex<Self>>().unwrap()
|
xdg_surface.data::<Mutex<Self>>()
|
||||||
}
|
}
|
||||||
pub fn wl_surface(&self) -> WlSurface {
|
pub fn wl_surface(&self) -> Option<WlSurface> {
|
||||||
self.wl_surface.upgrade().unwrap()
|
self.wl_surface.upgrade().ok()
|
||||||
}
|
}
|
||||||
pub fn panel_item(&self) -> Option<Arc<PanelItem>> {
|
pub fn panel_item(&self) -> Option<Arc<PanelItem>> {
|
||||||
self.panel_item.upgrade()
|
self.panel_item.upgrade()
|
||||||
@@ -274,23 +274,25 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
|
|||||||
|
|
||||||
let client_credentials = client.get_credentials(&state.display_handle).ok();
|
let client_credentials = client.get_credentials(&state.display_handle).ok();
|
||||||
let seat_data = state.seats.get(&client.id()).unwrap().clone();
|
let seat_data = state.seats.get(&client.id()).unwrap().clone();
|
||||||
|
let Some(wl_surface) = xdg_surface_data.lock().wl_surface() else {return};
|
||||||
CoreSurface::add_to(
|
CoreSurface::add_to(
|
||||||
&state.display,
|
&state.display,
|
||||||
state.display_handle.clone(),
|
state.display_handle.clone(),
|
||||||
&xdg_surface_data.lock().wl_surface(),
|
&wl_surface,
|
||||||
{
|
{
|
||||||
let toplevel = toplevel.downgrade();
|
let toplevel = toplevel.downgrade();
|
||||||
move || {
|
move || {
|
||||||
let toplevel = toplevel.upgrade().unwrap();
|
let toplevel = toplevel.upgrade().unwrap();
|
||||||
let toplevel_data = ToplevelData::get(&toplevel);
|
let toplevel_data = ToplevelData::get(&toplevel);
|
||||||
let xdg_surface = toplevel_data.lock().xdg_surface();
|
let Some(xdg_surface) = toplevel_data.lock().xdg_surface() else {return};
|
||||||
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface);
|
let Some(xdg_surface_data) = XdgSurfaceData::get(&xdg_surface) else {return};
|
||||||
let wl_surface = xdg_surface_data.lock().wl_surface();
|
let Some(wl_surface) = xdg_surface_data.lock().wl_surface() else {return};
|
||||||
|
|
||||||
xdg_surface_data.lock().surface_id = SurfaceID::Toplevel;
|
xdg_surface_data.lock().surface_id = SurfaceID::Toplevel;
|
||||||
|
let Some(backend) = WaylandBackend::create(toplevel.clone()) else {return};
|
||||||
let (node, panel_item) = PanelItem::create(
|
let (node, panel_item) = PanelItem::create(
|
||||||
wl_surface.clone(),
|
wl_surface.clone(),
|
||||||
Backend::Wayland(WaylandBackend::create(toplevel.clone())),
|
Backend::Wayland(backend),
|
||||||
client_credentials,
|
client_credentials,
|
||||||
seat_data.clone(),
|
seat_data.clone(),
|
||||||
);
|
);
|
||||||
@@ -304,6 +306,7 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
|
|||||||
let toplevel = toplevel.upgrade().unwrap();
|
let toplevel = toplevel.upgrade().unwrap();
|
||||||
let toplevel_data = ToplevelData::get(&toplevel);
|
let toplevel_data = ToplevelData::get(&toplevel);
|
||||||
let Some(panel_item) = toplevel_data.lock().panel_item() else {
|
let Some(panel_item) = toplevel_data.lock().panel_item() else {
|
||||||
|
let Some(xdg_surface) = toplevel_data.lock().xdg_surface() else {return};
|
||||||
// if the wayland toplevel isn't mapped, hammer it again with a configure until it cooperates
|
// if the wayland toplevel isn't mapped, hammer it again with a configure until it cooperates
|
||||||
toplevel.configure(
|
toplevel.configure(
|
||||||
0,
|
0,
|
||||||
@@ -314,7 +317,6 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
|
|||||||
vec![]
|
vec![]
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let xdg_surface = toplevel_data.lock().xdg_surface();
|
|
||||||
xdg_surface.configure(SERIAL_COUNTER.inc());
|
xdg_surface.configure(SERIAL_COUNTER.inc());
|
||||||
return
|
return
|
||||||
};
|
};
|
||||||
@@ -353,11 +355,10 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
|
|||||||
xdg_surface_data.lock().surface_id = SurfaceID::Popup(uid);
|
xdg_surface_data.lock().surface_id = SurfaceID::Popup(uid);
|
||||||
let panel_item = parent_data.panel_item().unwrap();
|
let panel_item = parent_data.panel_item().unwrap();
|
||||||
xdg_surface_data.lock().panel_item = Arc::downgrade(&panel_item);
|
xdg_surface_data.lock().panel_item = Arc::downgrade(&panel_item);
|
||||||
|
let Some(wl_surface) = xdg_surface_data.lock().wl_surface() else {return};
|
||||||
panel_item.seat_data.new_surface(
|
panel_item
|
||||||
&xdg_surface_data.lock().wl_surface(),
|
.seat_data
|
||||||
Arc::downgrade(&panel_item),
|
.new_surface(&wl_surface, Arc::downgrade(&panel_item));
|
||||||
);
|
|
||||||
debug!(?xdg_popup, ?xdg_surface, "Create XDG popup");
|
debug!(?xdg_popup, ?xdg_surface, "Create XDG popup");
|
||||||
|
|
||||||
let xdg_surface = xdg_surface.downgrade();
|
let xdg_surface = xdg_surface.downgrade();
|
||||||
@@ -368,7 +369,7 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
|
|||||||
&xdg_surface_data.lock().wl_surface.upgrade().unwrap(),
|
&xdg_surface_data.lock().wl_surface.upgrade().unwrap(),
|
||||||
move || {
|
move || {
|
||||||
let xdg_popup = xdg_popup.upgrade().unwrap();
|
let xdg_popup = xdg_popup.upgrade().unwrap();
|
||||||
let popup_data = PopupData::get(&xdg_popup);
|
let Some(popup_data) = PopupData::get(&xdg_popup) else {return};
|
||||||
let popup_data = popup_data.lock();
|
let popup_data = popup_data.lock();
|
||||||
// panel_item.commit_popup(popup_data);
|
// panel_item.commit_popup(popup_data);
|
||||||
let Backend::Wayland(wayland_backend) = &panel_item.backend else {return};
|
let Backend::Wayland(wayland_backend) = &panel_item.backend else {return};
|
||||||
@@ -444,21 +445,22 @@ impl ToplevelData {
|
|||||||
toplevel.data::<Mutex<ToplevelData>>().unwrap()
|
toplevel.data::<Mutex<ToplevelData>>().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn xdg_surface(&self) -> XdgSurface {
|
pub fn xdg_surface(&self) -> Option<XdgSurface> {
|
||||||
self.xdg_surface.upgrade().unwrap()
|
self.xdg_surface.upgrade().ok()
|
||||||
}
|
}
|
||||||
fn panel_item(&self) -> Option<Arc<PanelItem>> {
|
fn panel_item(&self) -> Option<Arc<PanelItem>> {
|
||||||
let xdg_surface = self.xdg_surface();
|
let xdg_surface = self.xdg_surface()?;
|
||||||
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface).lock();
|
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface)?.lock();
|
||||||
xdg_surface_data.panel_item()
|
xdg_surface_data.panel_item()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Serialize for ToplevelData {
|
impl Serialize for ToplevelData {
|
||||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
let xdg_surface = self.xdg_surface();
|
let Some(xdg_surface) = self.xdg_surface() else {return serializer.serialize_none()};
|
||||||
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface).lock();
|
let Some(xdg_surface_data) = XdgSurfaceData::get(&xdg_surface) else {return serializer.serialize_none()};
|
||||||
|
let xdg_surface_data = xdg_surface_data.lock();
|
||||||
let geometry = xdg_surface_data.geometry.clone();
|
let geometry = xdg_surface_data.geometry.clone();
|
||||||
let wl_surface = xdg_surface_data.wl_surface();
|
let Some(wl_surface) = xdg_surface_data.wl_surface() else {return serde_error::<S>("Wayland surface not found")};
|
||||||
let Some(core_surface) = CoreSurface::from_wl_surface(&wl_surface) else {return serde_error::<S>("Core surface not found")};
|
let Some(core_surface) = CoreSurface::from_wl_surface(&wl_surface) else {return serde_error::<S>("Core surface not found")};
|
||||||
let Some(size) = core_surface.size() else {return serializer.serialize_none()};
|
let Some(size) = core_surface.size() else {return serializer.serialize_none()};
|
||||||
let geometry = geometry.unwrap_or_else(|| Geometry {
|
let geometry = geometry.unwrap_or_else(|| Geometry {
|
||||||
@@ -604,21 +606,25 @@ impl PopupData {
|
|||||||
xdg_surface: xdg_surface.downgrade(),
|
xdg_surface: xdg_surface.downgrade(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get(popup: &XdgPopup) -> &Mutex<Self> {
|
pub fn get(popup: &XdgPopup) -> Option<&Mutex<Self>> {
|
||||||
popup.data::<Mutex<Self>>().unwrap()
|
popup.data::<Mutex<Self>>()
|
||||||
}
|
}
|
||||||
pub fn xdg_surface(&self) -> XdgSurface {
|
pub fn xdg_surface(&self) -> Option<XdgSurface> {
|
||||||
self.xdg_surface.upgrade().unwrap()
|
self.xdg_surface.upgrade().ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn panel_item(&self) -> Option<Arc<PanelItem>> {
|
fn panel_item(&self) -> Option<Arc<PanelItem>> {
|
||||||
XdgSurfaceData::get(&self.xdg_surface()).lock().panel_item()
|
XdgSurfaceData::get(&self.xdg_surface()?)?
|
||||||
|
.lock()
|
||||||
|
.panel_item()
|
||||||
}
|
}
|
||||||
// fn get_parent(&self) -> Option<XdgSurface> {
|
// fn get_parent(&self) -> Option<XdgSurface> {
|
||||||
// self.parent.as_ref()?.upgrade().ok()
|
// self.parent.as_ref()?.upgrade().ok()
|
||||||
// }
|
// }
|
||||||
pub fn wl_surface(&self) -> WlSurface {
|
pub fn wl_surface(&self) -> Option<WlSurface> {
|
||||||
XdgSurfaceData::get(&self.xdg_surface()).lock().wl_surface()
|
XdgSurfaceData::get(&self.xdg_surface()?)?
|
||||||
|
.lock()
|
||||||
|
.wl_surface()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn positioner_data(&self) -> Option<PositionerData> {
|
pub fn positioner_data(&self) -> Option<PositionerData> {
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ pub static DISPLAY: OnceCell<String> = OnceCell::new();
|
|||||||
|
|
||||||
pub struct XWaylandState {
|
pub struct XWaylandState {
|
||||||
pub display: u32,
|
pub display: u32,
|
||||||
xwayland: XWayland,
|
_xwayland: XWayland,
|
||||||
event_loop_signal: LoopSignal,
|
_event_loop_signal: LoopSignal,
|
||||||
event_loop_join: Option<JoinHandle<Result<(), calloop::Error>>>,
|
event_loop_join: Option<JoinHandle<Result<(), calloop::Error>>>,
|
||||||
}
|
}
|
||||||
impl XWaylandState {
|
impl XWaylandState {
|
||||||
@@ -71,8 +71,8 @@ impl XWaylandState {
|
|||||||
)?;
|
)?;
|
||||||
let _ = tx.send(XWaylandState {
|
let _ = tx.send(XWaylandState {
|
||||||
display,
|
display,
|
||||||
xwayland,
|
_xwayland: xwayland,
|
||||||
event_loop_signal: event_loop.get_signal(),
|
_event_loop_signal: event_loop.get_signal(),
|
||||||
event_loop_join: None,
|
event_loop_join: None,
|
||||||
});
|
});
|
||||||
let wayland_display_handle = wayland_display.lock().handle();
|
let wayland_display_handle = wayland_display.lock().handle();
|
||||||
@@ -82,7 +82,7 @@ impl XWaylandState {
|
|||||||
wm: None,
|
wm: None,
|
||||||
seat: None,
|
seat: None,
|
||||||
};
|
};
|
||||||
event_loop.run(Duration::from_secs(60 * 60), &mut handler, |_| ())
|
event_loop.run(Duration::from_millis(100), &mut handler, |_| ())
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut state = rx.blocking_recv()?;
|
let mut state = rx.blocking_recv()?;
|
||||||
@@ -92,12 +92,12 @@ impl XWaylandState {
|
|||||||
Ok(state)
|
Ok(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Drop for XWaylandState {
|
// impl Drop for XWaylandState {
|
||||||
fn drop(&mut self) {
|
// fn drop(&mut self) {
|
||||||
self.xwayland.shutdown();
|
// self.xwayland.shutdown();
|
||||||
self.event_loop_signal.stop();
|
// self.event_loop_signal.stop();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
struct XWaylandHandler {
|
struct XWaylandHandler {
|
||||||
wayland_display: Arc<Mutex<Display<WaylandState>>>,
|
wayland_display: Arc<Mutex<Display<WaylandState>>>,
|
||||||
|
|||||||
Reference in New Issue
Block a user