screen notification popups
This commit is contained in:
@@ -2,6 +2,9 @@ pub mod common;
|
|||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod notifications;
|
pub mod notifications;
|
||||||
|
|
||||||
|
#[allow(clippy::all)]
|
||||||
|
mod notifications_dbus;
|
||||||
|
|
||||||
#[cfg(feature = "openvr")]
|
#[cfg(feature = "openvr")]
|
||||||
pub mod openvr;
|
pub mod openvr;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
use dbus::{blocking::Connection, channel::MatchingReceiver, message::MatchRule};
|
use dbus::{
|
||||||
|
arg::{PropMap, Variant},
|
||||||
|
blocking::Connection,
|
||||||
|
channel::MatchingReceiver,
|
||||||
|
message::MatchRule,
|
||||||
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
sync::{
|
sync::{
|
||||||
@@ -9,6 +14,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
backend::notifications_dbus::OrgFreedesktopNotifications,
|
||||||
overlays::toast::{Toast, ToastTopic},
|
overlays::toast::{Toast, ToastTopic},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
};
|
};
|
||||||
@@ -196,6 +202,60 @@ impl Drop for NotificationManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct DbusNotificationSender {
|
||||||
|
connection: Connection,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DbusNotificationSender {
|
||||||
|
pub fn new() -> anyhow::Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
connection: Connection::new_session()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn notify_send(
|
||||||
|
&self,
|
||||||
|
summary: &str,
|
||||||
|
body: &str,
|
||||||
|
urgency: u8,
|
||||||
|
timeout: i32,
|
||||||
|
replaces_id: u32,
|
||||||
|
transient: bool,
|
||||||
|
) -> anyhow::Result<u32> {
|
||||||
|
let proxy = self.connection.with_proxy(
|
||||||
|
"org.freedesktop.Notifications",
|
||||||
|
"/org/freedesktop/Notifications",
|
||||||
|
Duration::from_millis(1000),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut hints = PropMap::new();
|
||||||
|
hints.insert("urgency".to_string(), Variant(Box::new(urgency)));
|
||||||
|
hints.insert("transient".to_string(), Variant(Box::new(transient)));
|
||||||
|
|
||||||
|
Ok(proxy.notify(
|
||||||
|
"WlxOverlay-S",
|
||||||
|
replaces_id,
|
||||||
|
"",
|
||||||
|
summary,
|
||||||
|
body,
|
||||||
|
vec![],
|
||||||
|
hints,
|
||||||
|
timeout,
|
||||||
|
)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn notify_close(&self, id: u32) -> anyhow::Result<()> {
|
||||||
|
let proxy = self.connection.with_proxy(
|
||||||
|
"org.freedesktop.Notifications",
|
||||||
|
"/org/freedesktop/Notifications",
|
||||||
|
Duration::from_millis(1000),
|
||||||
|
);
|
||||||
|
|
||||||
|
proxy.close_notification(id)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_dbus(msg: &dbus::Message) -> anyhow::Result<Toast> {
|
fn parse_dbus(msg: &dbus::Message) -> anyhow::Result<Toast> {
|
||||||
let mut args = msg.iter_init();
|
let mut args = msg.iter_init();
|
||||||
let app_name: String = args.read()?;
|
let app_name: String = args.read()?;
|
||||||
|
|||||||
267
src/backend/notifications_dbus.rs
Normal file
267
src/backend/notifications_dbus.rs
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
// This code was autogenerated with `dbus-codegen-rust -g -m None -d org.freedesktop.Notifications -p /org/freedesktop/Notifications`, see https://github.com/diwic/dbus-rs
|
||||||
|
use dbus as dbus;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use dbus::arg;
|
||||||
|
use dbus::blocking;
|
||||||
|
|
||||||
|
pub trait OrgFreedesktopDBusProperties {
|
||||||
|
fn get<R0: for<'b> arg::Get<'b> + 'static>(&self, interface_name: &str, property_name: &str) -> Result<R0, dbus::Error>;
|
||||||
|
fn get_all(&self, interface_name: &str) -> Result<arg::PropMap, dbus::Error>;
|
||||||
|
fn set<I2: arg::Arg + arg::Append>(&self, interface_name: &str, property_name: &str, value: I2) -> Result<(), dbus::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct OrgFreedesktopDBusPropertiesPropertiesChanged {
|
||||||
|
pub interface_name: String,
|
||||||
|
pub changed_properties: arg::PropMap,
|
||||||
|
pub invalidated_properties: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl arg::AppendAll for OrgFreedesktopDBusPropertiesPropertiesChanged {
|
||||||
|
fn append(&self, i: &mut arg::IterAppend) {
|
||||||
|
arg::RefArg::append(&self.interface_name, i);
|
||||||
|
arg::RefArg::append(&self.changed_properties, i);
|
||||||
|
arg::RefArg::append(&self.invalidated_properties, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl arg::ReadAll for OrgFreedesktopDBusPropertiesPropertiesChanged {
|
||||||
|
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||||
|
Ok(OrgFreedesktopDBusPropertiesPropertiesChanged {
|
||||||
|
interface_name: i.read()?,
|
||||||
|
changed_properties: i.read()?,
|
||||||
|
invalidated_properties: i.read()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl dbus::message::SignalArgs for OrgFreedesktopDBusPropertiesPropertiesChanged {
|
||||||
|
const NAME: &'static str = "PropertiesChanged";
|
||||||
|
const INTERFACE: &'static str = "org.freedesktop.DBus.Properties";
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target=T>> OrgFreedesktopDBusProperties for blocking::Proxy<'a, C> {
|
||||||
|
|
||||||
|
fn get<R0: for<'b> arg::Get<'b> + 'static>(&self, interface_name: &str, property_name: &str) -> Result<R0, dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.DBus.Properties", "Get", (interface_name, property_name, ))
|
||||||
|
.and_then(|r: (arg::Variant<R0>, )| Ok((r.0).0, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_all(&self, interface_name: &str) -> Result<arg::PropMap, dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.DBus.Properties", "GetAll", (interface_name, ))
|
||||||
|
.and_then(|r: (arg::PropMap, )| Ok(r.0, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set<I2: arg::Arg + arg::Append>(&self, interface_name: &str, property_name: &str, value: I2) -> Result<(), dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.DBus.Properties", "Set", (interface_name, property_name, arg::Variant(value), ))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait OrgFreedesktopDBusIntrospectable {
|
||||||
|
fn introspect(&self) -> Result<String, dbus::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target=T>> OrgFreedesktopDBusIntrospectable for blocking::Proxy<'a, C> {
|
||||||
|
|
||||||
|
fn introspect(&self) -> Result<String, dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.DBus.Introspectable", "Introspect", ())
|
||||||
|
.and_then(|r: (String, )| Ok(r.0, ))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait OrgFreedesktopDBusPeer {
|
||||||
|
fn ping(&self) -> Result<(), dbus::Error>;
|
||||||
|
fn get_machine_id(&self) -> Result<String, dbus::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target=T>> OrgFreedesktopDBusPeer for blocking::Proxy<'a, C> {
|
||||||
|
|
||||||
|
fn ping(&self) -> Result<(), dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.DBus.Peer", "Ping", ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_machine_id(&self) -> Result<String, dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.DBus.Peer", "GetMachineId", ())
|
||||||
|
.and_then(|r: (String, )| Ok(r.0, ))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait OrgFreedesktopNotifications {
|
||||||
|
fn set_noti_window_visibility(&self, value: bool) -> Result<(), dbus::Error>;
|
||||||
|
fn toggle_dnd(&self) -> Result<bool, dbus::Error>;
|
||||||
|
fn set_dnd(&self, state: bool) -> Result<(), dbus::Error>;
|
||||||
|
fn get_dnd(&self) -> Result<bool, dbus::Error>;
|
||||||
|
fn manually_close_notification(&self, id: u32, timeout: bool) -> Result<(), dbus::Error>;
|
||||||
|
fn close_all_notifications(&self) -> Result<(), dbus::Error>;
|
||||||
|
fn hide_latest_notification(&self, close: bool) -> Result<(), dbus::Error>;
|
||||||
|
fn get_capabilities(&self) -> Result<Vec<String>, dbus::Error>;
|
||||||
|
fn notify(&self, app_name: &str, replaces_id: u32, app_icon: &str, summary: &str, body: &str, actions: Vec<&str>, hints: arg::PropMap, expire_timeout: i32) -> Result<u32, dbus::Error>;
|
||||||
|
fn close_notification(&self, id: u32) -> Result<(), dbus::Error>;
|
||||||
|
fn get_server_information(&self) -> Result<(String, String, String, String), dbus::Error>;
|
||||||
|
fn dnd(&self) -> Result<bool, dbus::Error>;
|
||||||
|
fn set_dnd_(&self, value: bool) -> Result<(), dbus::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct OrgFreedesktopNotificationsOnDndToggle {
|
||||||
|
pub dnd: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl arg::AppendAll for OrgFreedesktopNotificationsOnDndToggle {
|
||||||
|
fn append(&self, i: &mut arg::IterAppend) {
|
||||||
|
arg::RefArg::append(&self.dnd, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl arg::ReadAll for OrgFreedesktopNotificationsOnDndToggle {
|
||||||
|
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||||
|
Ok(OrgFreedesktopNotificationsOnDndToggle {
|
||||||
|
dnd: i.read()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl dbus::message::SignalArgs for OrgFreedesktopNotificationsOnDndToggle {
|
||||||
|
const NAME: &'static str = "OnDndToggle";
|
||||||
|
const INTERFACE: &'static str = "org.freedesktop.Notifications";
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct OrgFreedesktopNotificationsNotificationClosed {
|
||||||
|
pub id: u32,
|
||||||
|
pub reason: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl arg::AppendAll for OrgFreedesktopNotificationsNotificationClosed {
|
||||||
|
fn append(&self, i: &mut arg::IterAppend) {
|
||||||
|
arg::RefArg::append(&self.id, i);
|
||||||
|
arg::RefArg::append(&self.reason, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl arg::ReadAll for OrgFreedesktopNotificationsNotificationClosed {
|
||||||
|
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||||
|
Ok(OrgFreedesktopNotificationsNotificationClosed {
|
||||||
|
id: i.read()?,
|
||||||
|
reason: i.read()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl dbus::message::SignalArgs for OrgFreedesktopNotificationsNotificationClosed {
|
||||||
|
const NAME: &'static str = "NotificationClosed";
|
||||||
|
const INTERFACE: &'static str = "org.freedesktop.Notifications";
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct OrgFreedesktopNotificationsActionInvoked {
|
||||||
|
pub id: u32,
|
||||||
|
pub action_key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl arg::AppendAll for OrgFreedesktopNotificationsActionInvoked {
|
||||||
|
fn append(&self, i: &mut arg::IterAppend) {
|
||||||
|
arg::RefArg::append(&self.id, i);
|
||||||
|
arg::RefArg::append(&self.action_key, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl arg::ReadAll for OrgFreedesktopNotificationsActionInvoked {
|
||||||
|
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||||
|
Ok(OrgFreedesktopNotificationsActionInvoked {
|
||||||
|
id: i.read()?,
|
||||||
|
action_key: i.read()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl dbus::message::SignalArgs for OrgFreedesktopNotificationsActionInvoked {
|
||||||
|
const NAME: &'static str = "ActionInvoked";
|
||||||
|
const INTERFACE: &'static str = "org.freedesktop.Notifications";
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct OrgFreedesktopNotificationsNotificationReplied {
|
||||||
|
pub id: u32,
|
||||||
|
pub text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl arg::AppendAll for OrgFreedesktopNotificationsNotificationReplied {
|
||||||
|
fn append(&self, i: &mut arg::IterAppend) {
|
||||||
|
arg::RefArg::append(&self.id, i);
|
||||||
|
arg::RefArg::append(&self.text, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl arg::ReadAll for OrgFreedesktopNotificationsNotificationReplied {
|
||||||
|
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||||
|
Ok(OrgFreedesktopNotificationsNotificationReplied {
|
||||||
|
id: i.read()?,
|
||||||
|
text: i.read()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl dbus::message::SignalArgs for OrgFreedesktopNotificationsNotificationReplied {
|
||||||
|
const NAME: &'static str = "NotificationReplied";
|
||||||
|
const INTERFACE: &'static str = "org.freedesktop.Notifications";
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target=T>> OrgFreedesktopNotifications for blocking::Proxy<'a, C> {
|
||||||
|
|
||||||
|
fn set_noti_window_visibility(&self, value: bool) -> Result<(), dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "SetNotiWindowVisibility", (value, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toggle_dnd(&self) -> Result<bool, dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "ToggleDnd", ())
|
||||||
|
.and_then(|r: (bool, )| Ok(r.0, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dnd(&self, state: bool) -> Result<(), dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "SetDnd", (state, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_dnd(&self) -> Result<bool, dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "GetDnd", ())
|
||||||
|
.and_then(|r: (bool, )| Ok(r.0, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn manually_close_notification(&self, id: u32, timeout: bool) -> Result<(), dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "ManuallyCloseNotification", (id, timeout, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close_all_notifications(&self) -> Result<(), dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "CloseAllNotifications", ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hide_latest_notification(&self, close: bool) -> Result<(), dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "HideLatestNotification", (close, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_capabilities(&self) -> Result<Vec<String>, dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "GetCapabilities", ())
|
||||||
|
.and_then(|r: (Vec<String>, )| Ok(r.0, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn notify(&self, app_name: &str, replaces_id: u32, app_icon: &str, summary: &str, body: &str, actions: Vec<&str>, hints: arg::PropMap, expire_timeout: i32) -> Result<u32, dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "Notify", (app_name, replaces_id, app_icon, summary, body, actions, hints, expire_timeout, ))
|
||||||
|
.and_then(|r: (u32, )| Ok(r.0, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close_notification(&self, id: u32) -> Result<(), dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "CloseNotification", (id, ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_server_information(&self) -> Result<(String, String, String, String), dbus::Error> {
|
||||||
|
self.method_call("org.freedesktop.Notifications", "GetServerInformation", ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dnd(&self) -> Result<bool, dbus::Error> {
|
||||||
|
<Self as blocking::stdintf::org_freedesktop_dbus::Properties>::get(self, "org.freedesktop.Notifications", "Dnd")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dnd_(&self, value: bool) -> Result<(), dbus::Error> {
|
||||||
|
<Self as blocking::stdintf::org_freedesktop_dbus::Properties>::set(self, "org.freedesktop.Notifications", "Dnd", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ use wlx_capture::{
|
|||||||
DrmFormat, FrameFormat, MouseMeta, WlxFrame, DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR8888,
|
DrmFormat, FrameFormat, MouseMeta, WlxFrame, DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR8888,
|
||||||
DRM_FORMAT_ARGB8888, DRM_FORMAT_XBGR2101010, DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888,
|
DRM_FORMAT_ARGB8888, DRM_FORMAT_XBGR2101010, DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888,
|
||||||
},
|
},
|
||||||
|
pipewire::PipewireSelectScreenResult,
|
||||||
WlxCapture,
|
WlxCapture,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,8 +26,8 @@ use wlx_capture::{
|
|||||||
use {
|
use {
|
||||||
crate::config_io,
|
crate::config_io,
|
||||||
std::error::Error,
|
std::error::Error,
|
||||||
std::{ops::Deref, path::PathBuf},
|
std::{ops::Deref, path::PathBuf, task},
|
||||||
wlx_capture::pipewire::{pipewire_select_screen, PipewireCapture},
|
wlx_capture::pipewire::PipewireCapture,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(all(feature = "x11", feature = "pipewire"))]
|
#[cfg(all(feature = "x11", feature = "pipewire"))]
|
||||||
@@ -337,21 +338,22 @@ impl ScreenRenderer {
|
|||||||
)> {
|
)> {
|
||||||
let name = output.name.clone();
|
let name = output.name.clone();
|
||||||
let embed_mouse = !session.config.double_cursor_fix;
|
let embed_mouse = !session.config.double_cursor_fix;
|
||||||
log::info!(
|
|
||||||
"On screen share prompt, pick: {} {} {} (pos {}, {})",
|
let select_screen_result = select_pw_screen(
|
||||||
&output.name,
|
&format!(
|
||||||
&output.make,
|
"Now select: {} {} {} @ {},{}",
|
||||||
&output.model,
|
&output.name,
|
||||||
&output.logical_pos.0,
|
&output.make,
|
||||||
&output.logical_pos.1,
|
&output.model,
|
||||||
);
|
&output.logical_pos.0,
|
||||||
let select_screen_result = futures::executor::block_on(pipewire_select_screen(
|
&output.logical_pos.1
|
||||||
|
),
|
||||||
token,
|
token,
|
||||||
embed_mouse,
|
embed_mouse,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
))?;
|
)?;
|
||||||
|
|
||||||
let node_id = select_screen_result.streams.first().unwrap().node_id; // streams guaranteed to have at least one element
|
let node_id = select_screen_result.streams.first().unwrap().node_id; // streams guaranteed to have at least one element
|
||||||
|
|
||||||
@@ -866,8 +868,16 @@ pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateDa
|
|||||||
let pw_tokens_copy = pw_tokens.clone();
|
let pw_tokens_copy = pw_tokens.clone();
|
||||||
let token = pw_tokens.arc_get("x11").map(|s| s.as_str());
|
let token = pw_tokens.arc_get("x11").map(|s| s.as_str());
|
||||||
let embed_mouse = !app.session.config.double_cursor_fix;
|
let embed_mouse = !app.session.config.double_cursor_fix;
|
||||||
let select_screen_result =
|
|
||||||
futures::executor::block_on(pipewire_select_screen(token, embed_mouse, true, true, true))?;
|
let select_screen_result = select_pw_screen(
|
||||||
|
"Select ALL screens on the screencast pop-up!",
|
||||||
|
token,
|
||||||
|
embed_mouse,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
)?;
|
||||||
|
|
||||||
if let Some(restore_token) = select_screen_result.restore_token {
|
if let Some(restore_token) = select_screen_result.restore_token {
|
||||||
if pw_tokens.arc_set("x11".into(), restore_token.clone()) {
|
if pw_tokens.arc_set("x11".into(), restore_token.clone()) {
|
||||||
log::info!("Adding Pipewire token {}", restore_token);
|
log::info!("Adding Pipewire token {}", restore_token);
|
||||||
@@ -1066,3 +1076,54 @@ fn best_match<'a>(
|
|||||||
log::debug!("best: {:?}", best.map(|b| &b.monitor));
|
log::debug!("best: {:?}", best.map(|b| &b.monitor));
|
||||||
best
|
best
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "pipewire")]
|
||||||
|
fn select_pw_screen(
|
||||||
|
instructions: &str,
|
||||||
|
token: Option<&str>,
|
||||||
|
embed_mouse: bool,
|
||||||
|
screens_only: bool,
|
||||||
|
persist: bool,
|
||||||
|
multiple: bool,
|
||||||
|
) -> Result<PipewireSelectScreenResult, wlx_capture::pipewire::AshpdError> {
|
||||||
|
use crate::backend::notifications::DbusNotificationSender;
|
||||||
|
use wlx_capture::pipewire::pipewire_select_screen;
|
||||||
|
|
||||||
|
let future = async move {
|
||||||
|
let print_at = Instant::now() + Duration::from_millis(250);
|
||||||
|
let mut notify = None;
|
||||||
|
|
||||||
|
let f = pipewire_select_screen(token, embed_mouse, screens_only, persist, multiple);
|
||||||
|
futures::pin_mut!(f);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match futures::poll!(&mut f) {
|
||||||
|
task::Poll::Ready(result) => return result,
|
||||||
|
task::Poll::Pending => {
|
||||||
|
if Instant::now() >= print_at {
|
||||||
|
log::info!("{}", instructions);
|
||||||
|
if let Ok(sender) = DbusNotificationSender::new() {
|
||||||
|
if let Ok(id) = sender.notify_send(instructions, "", 2, 0, 0, true) {
|
||||||
|
notify = Some((sender, id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
futures::future::lazy(|_| {
|
||||||
|
std::thread::sleep(Duration::from_millis(10));
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = f.await;
|
||||||
|
if let Some((sender, id)) = notify {
|
||||||
|
let _ = sender.notify_close(id);
|
||||||
|
}
|
||||||
|
result
|
||||||
|
};
|
||||||
|
|
||||||
|
futures::executor::block_on(future)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user