add dbus osk and session support
The D-Bus interfaces used by Phosh are org.gnome.SessionManager for recovering critical services from crashes and sm.puri.OSK0 for manual on-screen keyboard activation. Add support for them.
This commit is contained in:
parent
397323b582
commit
4fd0c82997
6 changed files with 283 additions and 30 deletions
7
src/dbus/mod.rs
Normal file
7
src/dbus/mod.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Copyright (c) 2024, Richard Acayan. All rights reserved.
|
||||
*/
|
||||
|
||||
pub mod osk;
|
||||
pub mod session;
|
||||
99
src/dbus/osk.rs
Normal file
99
src/dbus/osk.rs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Copyright (c) 2024, Richard Acayan. All rights reserved.
|
||||
*/
|
||||
|
||||
use crate::core::Graphics;
|
||||
use crate::wayland::Surface;
|
||||
use crate::wayland::fractional_scale_v1::wp_fractional_scale_v1::WpFractionalScaleV1;
|
||||
use crate::wayland::viewporter::wp_viewport::WpViewport;
|
||||
use crate::wayland::wlr_layer_shell_unstable_v1::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
use wayland_client::Dispatch;
|
||||
use wayland_client::protocol::wl_buffer::WlBuffer;
|
||||
use wayland_client::protocol::wl_shm_pool::WlShmPool;
|
||||
use wayland_client::protocol::wl_surface::WlSurface;
|
||||
use zbus::Connection;
|
||||
use zbus::InterfaceRef;
|
||||
use zbus::Result;
|
||||
use zbus::SignalContext;
|
||||
use zbus::interface;
|
||||
|
||||
pub struct OSK0<T: Dispatch<WlBuffer, u32>
|
||||
+ Dispatch<WlShmPool, u32>
|
||||
+ Dispatch<WlSurface, ()>
|
||||
+ Dispatch<ZwlrLayerSurfaceV1, ()>
|
||||
+ Dispatch<WpFractionalScaleV1, ()>
|
||||
+ Dispatch<WpViewport, ()>
|
||||
+ 'static> {
|
||||
visible: AtomicBool,
|
||||
gfx: Arc<Mutex<Graphics<Surface<T>>>>,
|
||||
sigctx: SignalContext<'static>,
|
||||
conn_wl: Arc<wayland_client::Connection>,
|
||||
}
|
||||
|
||||
#[interface(name = "sm.puri.OSK0")]
|
||||
impl<T: Dispatch<WlBuffer, u32>
|
||||
+ Dispatch<WlShmPool, u32>
|
||||
+ Dispatch<WlSurface, ()>
|
||||
+ Dispatch<ZwlrLayerSurfaceV1, ()>
|
||||
+ Dispatch<WpFractionalScaleV1, ()>
|
||||
+ Dispatch<WpViewport, ()>
|
||||
+ 'static> OSK0<T> {
|
||||
fn get_visible(&self) -> bool
|
||||
{
|
||||
self.visible.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub async fn set_visible(&self, visible: bool)
|
||||
{
|
||||
self.visible.store(visible, Ordering::Relaxed);
|
||||
self.visible_changed(&self.sigctx).await.unwrap();
|
||||
|
||||
let mut gfx = self.gfx.lock().unwrap();
|
||||
let disp = gfx.display_mut();
|
||||
if visible {
|
||||
disp.show();
|
||||
} else {
|
||||
disp.hide();
|
||||
}
|
||||
|
||||
self.conn_wl.flush().unwrap();
|
||||
}
|
||||
|
||||
#[zbus(property)]
|
||||
fn visible(&self) -> bool
|
||||
{
|
||||
self.visible.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Dispatch<WlBuffer, u32>
|
||||
+ Dispatch<WlShmPool, u32>
|
||||
+ Dispatch<WlSurface, ()>
|
||||
+ Dispatch<ZwlrLayerSurfaceV1, ()>
|
||||
+ Dispatch<WpFractionalScaleV1, ()>
|
||||
+ Dispatch<WpViewport, ()>
|
||||
+ 'static> OSK0<T> {
|
||||
pub async fn start(conn: &Connection,
|
||||
gfx: Arc<Mutex<Graphics<Surface<T>>>>,
|
||||
conn_wl: Arc<wayland_client::Connection>)
|
||||
-> Result<InterfaceRef<OSK0<T>>>
|
||||
{
|
||||
let sigctx = SignalContext::new(conn, "/sm/puri/OSK0")?;
|
||||
|
||||
let visible = AtomicBool::new(false);
|
||||
let osk = OSK0 { visible, gfx, sigctx, conn_wl };
|
||||
|
||||
let server = conn.object_server();
|
||||
server.at("/sm/puri/OSK0", osk).await?;
|
||||
conn.request_name("sm.puri.OSK0").await?;
|
||||
|
||||
let osk = server.interface("/sm/puri/OSK0").await?;
|
||||
|
||||
Ok(osk)
|
||||
}
|
||||
}
|
||||
70
src/dbus/session.rs
Normal file
70
src/dbus/session.rs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Copyright (c) 2024, Richard Acayan. All rights reserved.
|
||||
*/
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
use tokio::task;
|
||||
use zbus::Connection;
|
||||
use zbus::Result;
|
||||
use zbus::export::futures_util::stream::StreamExt;
|
||||
use zbus::fdo::DBusProxy;
|
||||
use zbus::names::BusName;
|
||||
use zbus::proxy;
|
||||
use zbus::zvariant::OwnedObjectPath;
|
||||
|
||||
#[proxy(interface = "org.gnome.SessionManager",
|
||||
default_service = "org.gnome.SessionManager",
|
||||
default_path = "/org/gnome/SessionManager")]
|
||||
trait SessionManager {
|
||||
fn register_client(&self, app_id: &str, client_startup_id: &str) -> Result<OwnedObjectPath>;
|
||||
}
|
||||
|
||||
#[proxy(interface = "org.gnome.SessionManager.ClientPrivate")]
|
||||
trait ClientPrivate {
|
||||
fn end_session_response(&self, is_ok: bool, reason: &str) -> Result<()>;
|
||||
|
||||
#[zbus(signal)]
|
||||
fn query_end_session(&self, flags: u32);
|
||||
}
|
||||
|
||||
pub async fn register(conn: &Connection) -> Result<()>
|
||||
{
|
||||
let manager = SessionManagerProxy::new(conn).await?;
|
||||
|
||||
let autostart_id = env::var("DESKTOP_AUTOSTART_ID").unwrap_or(String::new());
|
||||
let path = manager.register_client("sm.puri.OSK0", &autostart_id).await?;
|
||||
|
||||
let dbus = DBusProxy::new(conn).await?;
|
||||
let name = BusName::try_from("org.gnome.SessionManager")?;
|
||||
let id = dbus.get_name_owner(name).await?;
|
||||
|
||||
let client_priv = ClientPrivateProxy::new(conn, id, path).await?;
|
||||
let client_priv = Arc::new(client_priv);
|
||||
|
||||
{
|
||||
let client_priv = client_priv.clone();
|
||||
let mut stream_qes = client_priv.receive_query_end_session().await?;
|
||||
|
||||
task::spawn(async move {
|
||||
while stream_qes.next().await.is_some() {
|
||||
let _ = client_priv.end_session_response(true, "").await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let client_priv = client_priv.clone();
|
||||
let mut stream_es = client_priv.receive_query_end_session().await?;
|
||||
|
||||
task::spawn(async move {
|
||||
while stream_es.next().await.is_some() {
|
||||
let _ = client_priv.end_session_response(true, "").await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue