Skip to content

Commit

Permalink
Merge pull request #5 from ShadowBlip/feature/window-created
Browse files Browse the repository at this point in the history
Implement method to listen for window created events
  • Loading branch information
Ericky14 authored Feb 9, 2024
2 parents 14eeaca + d3149eb commit ccfba1a
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 8 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ zbus = { version = "3.14.1", default-features = false, features = ["tokio"] }
zbus_macros = "3.14.1"
inotify = "0.10.2"
gamescope-wayland-client = { git = "https://github.com/ShadowBlip/gamescope-wayland-client.git", version = "0.1.0" }
gamescope-x11-client = { git = "https://github.com/ShadowBlip/gamescope-x11-client.git", rev = "4b293ed350636c7ef2e96dd5125db7b1ca1d8187" }
gamescope-x11-client = { git = "https://github.com/ShadowBlip/gamescope-x11-client.git", rev = "3a0cbe64ba60dffb5ad85f156101c056f764e659" }
15 changes: 13 additions & 2 deletions src/gamescope/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,19 +198,30 @@ impl Manager {
// also attach the dbus interface with extra methods
if instance.primary().await? {
log::debug!("Discovered XWayland {} is primary", name);

// Property changes events
let primary = xwayland::DBusInterfacePrimary::new(
name.clone(),
path.clone(),
self.dbus.clone(),
)?;
let changes_rx = primary.listen_for_property_changes()?;
let property_changes_rx = primary.listen_for_property_changes()?;
let window_created_rx = primary.listen_for_window_created()?;
self.dbus.object_server().at(path.clone(), primary).await?;

// Propagate gamescope changes to DBus signals
xwayland::dispatch_primary_property_changes(
self.dbus.clone(),
path.clone(),
changes_rx,
property_changes_rx,
)
.await?;

// Propagate gamescope changes to DBus signals
xwayland::dispatch_primary_window_created(
self.dbus.clone(),
path.clone(),
window_created_rx,
)
.await?;
}
Expand Down
61 changes: 58 additions & 3 deletions src/gamescope/xwayland.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,14 @@ impl DBusInterfacePrimary {
Ok(rx)
}

/// Starts a new thread listening for window created events. Returns
/// a receiver channel where changes will be sent to. This is usually used
/// to process DBus property changes outside of the dispatched handler
pub fn listen_for_window_created(&self) -> Result<Receiver<u32>, Box<dyn Error>> {
let (_, rx) = self.xwayland.listen_for_window_created()?;
Ok(rx)
}

/// Returns a reference to the dbus interface
async fn get_interface(&self) -> Result<zbus::InterfaceRef<DBusInterfacePrimary>, zbus::Error> {
self.dbus
Expand Down Expand Up @@ -535,6 +543,10 @@ impl DBusInterfacePrimary {
#[dbus_interface(signal)]
async fn baselayer_window_updated(ctxt: &SignalContext<'_>) -> zbus::Result<()>;

/// Fires when a new window is created
#[dbus_interface(signal)]
async fn window_created(ctxt: &SignalContext<'_>, window_id: u32) -> zbus::Result<()>;

/// Sets the given window as the main launcher app. This will set an X window
/// property called STEAM_GAME to 769 (Steam), which will make Gamescope
/// treat the window as the main overlay.
Expand Down Expand Up @@ -646,16 +658,38 @@ pub async fn dispatch_primary_property_changes(
// Wait for events from the channel and dispatch them to the DBus interface
while let Ok(event) = rx.recv() {
log::debug!("Got property change event: {:?}", event);
dispatch_primary_to_dbus(conn.clone(), path.clone(), event);
dispatch_property_change_to_dbus(conn.clone(), path.clone(), event);
}
log::warn!("Stopped listening for property changes");
});

Ok(())
}

/// Listen for windows created and emit the appropriate DBus signals. This is
/// split into two methods to bridge the gap between the sync world and the async
/// world.
pub async fn dispatch_primary_window_created(
conn: zbus::Connection,
path: String,
rx: Receiver<u32>,
) -> Result<(), Box<dyn Error>> {
tokio::task::spawn_blocking(move || {
log::debug!("Started listening for windows created");

// Wait for events from the channel and dispatch them to the DBus interface
while let Ok(event) = rx.recv() {
log::debug!("Got window created event: {:?}", event);
dispatch_window_created_to_dbus(conn.clone(), path.clone(), event);
}
log::warn!("Stopped listening for windows created");
});

Ok(())
}

/// Dispatch the given event to DBus using async
fn dispatch_primary_to_dbus(conn: zbus::Connection, path: String, event: String) {
fn dispatch_property_change_to_dbus(conn: zbus::Connection, path: String, event: String) {
tokio::task::spawn(async move {
// Get the object instance at the given path so we can send DBus signal
// updates
Expand All @@ -665,8 +699,8 @@ fn dispatch_primary_to_dbus(conn: zbus::Connection, path: String, event: String)
.await
.expect("Unable to get reference to DBus interface");

log::debug!("Got property change event: {:?}", event);
let iface = iface_ref.get_mut().await;
log::debug!("Got property change event: {:?}", event);

// Match on the type of property that was changed to send the appropriate
// DBus signal.
Expand Down Expand Up @@ -704,3 +738,24 @@ fn dispatch_primary_to_dbus(conn: zbus::Connection, path: String, event: String)
}
});
}

/// Dispatch the given event to DBus using async
fn dispatch_window_created_to_dbus(conn: zbus::Connection, path: String, value: u32) {
tokio::task::spawn(async move {
// Get the object instance at the given path so we can send DBus signal
// updates
let iface_ref = conn
.object_server()
.interface::<_, DBusInterfacePrimary>(path)
.await
.expect("Unable to get reference to DBus interface");

log::debug!("Got window created for window_id: {:?}", value);

DBusInterfacePrimary::window_created(iface_ref.signal_context(), value)
.await
.unwrap_or_else(|error| {
log::warn!("Unable to signal window created event: {:?}", error);
});
});
}

0 comments on commit ccfba1a

Please sign in to comment.