Inline some clones to make code more readable, add config, implement dimming -> locking -> sleeping into idle daemon, fix waiting on network thread, implement run menu with application launching and math evaluation,
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
use crate::backend::{BackendThread, Registrator};
|
||||
use crate::config::Config;
|
||||
use crate::{APP_NAME, LOGGER};
|
||||
use crossbeam_channel::{Receiver, Sender};
|
||||
use jmb_logger_rs::*;
|
||||
use nmrs::raw::zbus::interface;
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::process::Command;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::time::Duration;
|
||||
use tokio::sync::watch;
|
||||
use tokio::time::sleep;
|
||||
use wayland_client::globals::registry_queue_init;
|
||||
@@ -17,12 +18,11 @@ use wayland_protocols::ext::idle_notify::v1::client::ext_idle_notification_v1::{
|
||||
Event, ExtIdleNotificationV1,
|
||||
};
|
||||
use wayland_protocols::ext::idle_notify::v1::client::ext_idle_notifier_v1::ExtIdleNotifierV1;
|
||||
use zbus::conn::Builder;
|
||||
use zbus::interface;
|
||||
use zbus::message::Header;
|
||||
|
||||
const SERVICE: &str = "org.freedesktop.ScreenSaver";
|
||||
const OBJECT_PATH: &str = "/org/freedesktop/ScreenSaver";
|
||||
const LEGACY_OBJECT_PATH: &str = "/ScreenSaver";
|
||||
|
||||
struct WlState {
|
||||
idle: Option<bool>,
|
||||
@@ -53,14 +53,8 @@ impl Dispatch<ExtIdleNotificationV1, ()> for WlState {
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
Event::Idled => {
|
||||
println!("Idled: {:?}", Instant::now());
|
||||
state.idle = Some(true);
|
||||
}
|
||||
Event::Resumed => {
|
||||
println!("Resumed: {:?}", Instant::now());
|
||||
state.idle = Some(false);
|
||||
}
|
||||
Event::Idled => state.idle = Some(true),
|
||||
Event::Resumed => state.idle = Some(false),
|
||||
_ => {}
|
||||
}
|
||||
if let Some(idle) = state.idle {
|
||||
@@ -85,15 +79,15 @@ impl Dispatch<ExtIdleNotifierV1, (), WlState> for WlState {
|
||||
struct Inhibitor {
|
||||
owner: String,
|
||||
application: String,
|
||||
_reason: String,
|
||||
reason: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum IdleState {
|
||||
Init(Sender<IdleMessage>),
|
||||
Dimmed,
|
||||
Inhibited,
|
||||
Caffeine,
|
||||
Inhibited(bool),
|
||||
Caffeine(bool),
|
||||
Active,
|
||||
}
|
||||
|
||||
@@ -128,73 +122,92 @@ impl BackendThread<IdleState, Sender<IdleMessage>> for IdleDaemon {
|
||||
}
|
||||
|
||||
fn init(registration_rx: Receiver<Sender<IdleState>>) {
|
||||
let config = Config::load();
|
||||
let (tx, rx) = crossbeam_channel::unbounded::<IdleMessage>();
|
||||
let tx_clone = tx.clone();
|
||||
let instance = Arc::new(Mutex::new(Self {
|
||||
subscribers: Vec::new(),
|
||||
}));
|
||||
let instance_clone = instance.clone();
|
||||
std::thread::spawn(move || {
|
||||
while let Ok(sender) = registration_rx.recv() {
|
||||
if sender.send(IdleState::Init(tx_clone.clone())).is_ok() {
|
||||
trace!(&LOGGER, "Added IdleDaemon Subscriber");
|
||||
instance_clone
|
||||
.lock()
|
||||
.expect("Couldn't get lock")
|
||||
.subscribers
|
||||
.push(sender);
|
||||
std::thread::spawn({
|
||||
let instance = instance.clone();
|
||||
let tx = tx.clone();
|
||||
move || {
|
||||
while let Ok(sender) = registration_rx.recv() {
|
||||
if sender.send(IdleState::Init(tx.clone())).is_ok() {
|
||||
trace!(&LOGGER, "Added IdleDaemon Subscriber");
|
||||
instance
|
||||
.lock()
|
||||
.expect("Couldn't get lock")
|
||||
.subscribers
|
||||
.push(sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
let (wl_tx, wl_rx) = watch::channel(false);
|
||||
let (dbus_tx, dbus_rx) = watch::channel((false, false));
|
||||
std::thread::spawn(move || {
|
||||
if let Err(err) = Self::start_idle_notifier(wl_tx) {
|
||||
error!(&LOGGER, "Idle Daemon unexpectedly quit, reason: {err}");
|
||||
let (dbus_tx, dbus_rx) = watch::channel(false);
|
||||
std::thread::spawn({
|
||||
let config = config.clone();
|
||||
move || {
|
||||
if let Err(err) = Self::start_idle_notifier(wl_tx, &config) {
|
||||
error!(&LOGGER, "Idle Daemon unexpectedly quit, reason: {err}");
|
||||
}
|
||||
}
|
||||
});
|
||||
std::thread::spawn(move || {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("Failed to create Tokio runtime");
|
||||
runtime.block_on(async move {
|
||||
let mut idle_inhibitor = None;
|
||||
while let Ok(msg) = rx.recv() {
|
||||
match msg {
|
||||
IdleMessage::Inhibit => {
|
||||
if idle_inhibitor.is_none()
|
||||
&& let Ok(ii) = IdleInhibitor::inhibit_idle().await
|
||||
{
|
||||
idle_inhibitor = Some(ii);
|
||||
std::thread::spawn({
|
||||
let instance = instance.clone();
|
||||
move || {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("Failed to create Tokio runtime");
|
||||
runtime.block_on(async move {
|
||||
let mut idle_inhibitor = None;
|
||||
while let Ok(msg) = rx.recv() {
|
||||
match msg {
|
||||
IdleMessage::Inhibit => {
|
||||
if idle_inhibitor.is_none()
|
||||
&& let Ok(ii) = IdleInhibitor::inhibit_idle().await
|
||||
{
|
||||
instance.lock().unwrap().publish(IdleState::Caffeine(true));
|
||||
idle_inhibitor = Some(ii);
|
||||
}
|
||||
}
|
||||
}
|
||||
IdleMessage::Release => {
|
||||
if let Some(ii) = idle_inhibitor.take()
|
||||
&& let Err(e) = ii.uninhibit_idle().await
|
||||
{
|
||||
warn!(&LOGGER, "Error uninhibiting {e}");
|
||||
IdleMessage::Release => {
|
||||
if let Some(ii) = idle_inhibitor.take() {
|
||||
match ii.uninhibit_idle().await {
|
||||
Ok(_) => {
|
||||
instance
|
||||
.lock()
|
||||
.unwrap()
|
||||
.publish(IdleState::Caffeine(false));
|
||||
}
|
||||
Err(e) => warn!(&LOGGER, "Error uninhibiting {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
std::thread::spawn(move || {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("Failed to create Tokio runtime");
|
||||
std::thread::spawn({
|
||||
let instance_clone = instance.clone();
|
||||
move || {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("Failed to create Tokio runtime");
|
||||
|
||||
runtime.block_on(async move {
|
||||
let res = IdleDaemon::start_dbus(dbus_tx).await;
|
||||
match res {
|
||||
Ok((_, _)) => {
|
||||
Self::run_idle_timer(instance, wl_rx, dbus_rx).await;
|
||||
runtime.block_on(async move {
|
||||
let res = IdleDaemon::start_dbus(dbus_tx, instance_clone).await;
|
||||
match res {
|
||||
Ok((_, _)) => {
|
||||
Self::run_idle_timer(instance, wl_rx, dbus_rx, &config).await;
|
||||
}
|
||||
Err(err) => error!(&LOGGER, "Error running D-Bus Screensaver: {err}"),
|
||||
}
|
||||
Err(err) => error!(&LOGGER, "Error running D-Bus Screensaver: {err}"),
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -215,20 +228,21 @@ impl IdleStage {
|
||||
}
|
||||
}
|
||||
|
||||
fn timeout(self) -> Duration {
|
||||
fn timeout(self, cfg: &Config) -> Duration {
|
||||
match self {
|
||||
Self::Dim => Duration::from_secs(20),
|
||||
Self::TurnOff => Duration::from_secs(20),
|
||||
Self::Sleep => Duration::from_secs(20),
|
||||
Self::Dim => Duration::from_secs(cfg.dim_timeout_delta()),
|
||||
Self::TurnOff => Duration::from_secs(cfg.lock_timeout_delta()),
|
||||
Self::Sleep => Duration::from_secs(cfg.sleep_timeout_delta()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IdleDaemon {
|
||||
async fn run_idle_timer(
|
||||
_instance: Arc<Mutex<Self>>,
|
||||
instance: Arc<Mutex<Self>>,
|
||||
mut wl_rx: watch::Receiver<bool>,
|
||||
mut dbus_rx: watch::Receiver<(bool, bool)>,
|
||||
mut dbus_rx: watch::Receiver<bool>,
|
||||
config: &Config,
|
||||
) {
|
||||
loop {
|
||||
if let Err(e) = wl_rx.changed().await {
|
||||
@@ -237,22 +251,26 @@ impl IdleDaemon {
|
||||
}
|
||||
let wl_idle = *wl_rx.borrow_and_update();
|
||||
let dbus_state = *dbus_rx.borrow_and_update();
|
||||
println!("Wayland idle state changed {wl_idle} (DBus state: {dbus_state:?})");
|
||||
if wl_idle && !dbus_state.0 {
|
||||
println!("Going into idle cycle");
|
||||
if wl_idle && !dbus_state {
|
||||
let mut stage = IdleStage::Dim;
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = sleep(stage.timeout()) => {
|
||||
_ = sleep(stage.timeout(config)) => {
|
||||
match stage {
|
||||
IdleStage::Dim => instance.lock().unwrap().publish(IdleState::Dimmed),
|
||||
IdleStage::TurnOff => _ = Command::new("hyprlock").spawn(),
|
||||
IdleStage::Sleep => _ = Command::new("systemctl").arg("sleep").spawn(),
|
||||
}
|
||||
stage = stage.next();
|
||||
println!("Reached next stage {stage:?}");
|
||||
}
|
||||
res = wl_rx.changed() => {
|
||||
if let Err(e) = res {
|
||||
warn!(&LOGGER, "Error getting Wayland idle state {e}");
|
||||
return;
|
||||
}
|
||||
println!("WL state change");
|
||||
if !*wl_rx.borrow_and_update() {
|
||||
instance.lock().unwrap().publish(IdleState::Active);
|
||||
}
|
||||
break;
|
||||
}
|
||||
res = dbus_rx.changed() => {
|
||||
@@ -260,7 +278,6 @@ impl IdleDaemon {
|
||||
warn!(&LOGGER, "Error getting D-Bus idle state {e}");
|
||||
return;
|
||||
}
|
||||
println!("D-Bus state change");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -269,7 +286,7 @@ impl IdleDaemon {
|
||||
}
|
||||
}
|
||||
|
||||
fn start_idle_notifier(tx: watch::Sender<bool>) -> Result<(), Box<dyn Error>> {
|
||||
fn start_idle_notifier(tx: watch::Sender<bool>, config: &Config) -> Result<(), Box<dyn Error>> {
|
||||
let conn = Connection::connect_to_env()?;
|
||||
let (globals, mut event_queue) = registry_queue_init::<WlState>(&conn)?;
|
||||
let queue_handle = event_queue.handle();
|
||||
@@ -280,7 +297,12 @@ impl IdleDaemon {
|
||||
|
||||
let mut state = WlState { idle: None, tx };
|
||||
|
||||
let _notification = notifier.get_idle_notification(10_000, &seat, &queue_handle, ());
|
||||
let _notification = notifier.get_idle_notification(
|
||||
(config.idle_timeout() * 1000) as u32,
|
||||
&seat,
|
||||
&queue_handle,
|
||||
(),
|
||||
);
|
||||
|
||||
loop {
|
||||
event_queue.blocking_dispatch(&mut state)?;
|
||||
@@ -288,16 +310,18 @@ impl IdleDaemon {
|
||||
}
|
||||
|
||||
async fn start_dbus(
|
||||
tx: watch::Sender<(bool, bool)>,
|
||||
tx: watch::Sender<bool>,
|
||||
daemon: Arc<Mutex<IdleDaemon>>,
|
||||
) -> zbus::Result<(ScreenSaver, zbus::connection::Connection)> {
|
||||
let service = ScreenSaver::new(tx);
|
||||
let service = ScreenSaver::new(tx, daemon);
|
||||
|
||||
let connection = Builder::session()?
|
||||
.name(SERVICE)?
|
||||
.serve_at(OBJECT_PATH, service.clone())?
|
||||
.serve_at(LEGACY_OBJECT_PATH, service.clone())?
|
||||
.build()
|
||||
let connection = zbus::Connection::session().await?;
|
||||
|
||||
connection
|
||||
.object_server()
|
||||
.at(OBJECT_PATH, service.clone())
|
||||
.await?;
|
||||
connection.request_name(SERVICE).await?;
|
||||
|
||||
info!(&LOGGER, "Providing {SERVICE}");
|
||||
|
||||
@@ -347,22 +371,24 @@ impl IdleInhibitor {
|
||||
#[derive(Clone)]
|
||||
struct ScreenSaver {
|
||||
inner: Arc<Mutex<Inner>>,
|
||||
daemon: Arc<Mutex<IdleDaemon>>,
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
next_cookie: u32,
|
||||
inhibitors: HashMap<u32, Inhibitor>,
|
||||
tx: watch::Sender<(bool, bool)>,
|
||||
tx: watch::Sender<bool>,
|
||||
}
|
||||
|
||||
impl ScreenSaver {
|
||||
fn new(tx: watch::Sender<(bool, bool)>) -> Self {
|
||||
fn new(tx: watch::Sender<bool>, daemon: Arc<Mutex<IdleDaemon>>) -> Self {
|
||||
Self {
|
||||
inner: Arc::new(Mutex::new(Inner {
|
||||
next_cookie: 1,
|
||||
inhibitors: HashMap::new(),
|
||||
tx,
|
||||
})),
|
||||
daemon,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -399,21 +425,26 @@ impl ScreenSaver {
|
||||
}
|
||||
};
|
||||
|
||||
let caffeine_flag = application_name.eq(APP_NAME);
|
||||
|
||||
debug!(&LOGGER, "Inhibitor added: {application_name} {cookie}");
|
||||
debug!(
|
||||
&LOGGER,
|
||||
"Inhibitor added - Name: '{application_name}' Reason: '{reason_for_inhibit}' Value: {cookie}"
|
||||
);
|
||||
inner.inhibitors.insert(
|
||||
cookie,
|
||||
Inhibitor {
|
||||
owner,
|
||||
application: application_name,
|
||||
_reason: reason_for_inhibit,
|
||||
reason: reason_for_inhibit,
|
||||
},
|
||||
);
|
||||
|
||||
self.daemon
|
||||
.lock()
|
||||
.unwrap()
|
||||
.publish(IdleState::Inhibited(true));
|
||||
|
||||
inner.tx.send_modify(|state| {
|
||||
state.0 = !inner.inhibitors.is_empty();
|
||||
state.1 = caffeine_flag;
|
||||
*state = !inner.inhibitors.is_empty();
|
||||
});
|
||||
Ok(cookie)
|
||||
}
|
||||
@@ -432,25 +463,25 @@ impl ScreenSaver {
|
||||
if let Some(removed) = inner.inhibitors.remove(&cookie) {
|
||||
debug!(
|
||||
&LOGGER,
|
||||
"Inhibitor removed: {} {cookie}", removed.application
|
||||
"Inhibitor removed - Name: '{}' Reason: '{}' Value: {cookie}",
|
||||
removed.application,
|
||||
removed.reason
|
||||
);
|
||||
}
|
||||
let mut caffeine_flag = false;
|
||||
for inhibitor in inner.inhibitors.values() {
|
||||
if inhibitor.application.eq(APP_NAME) {
|
||||
caffeine_flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self.daemon
|
||||
.lock()
|
||||
.unwrap()
|
||||
.publish(IdleState::Inhibited(!inner.inhibitors.is_empty()));
|
||||
|
||||
inner.tx.send_modify(|state| {
|
||||
state.0 = !inner.inhibitors.is_empty();
|
||||
state.1 = caffeine_flag;
|
||||
*state = !inner.inhibitors.is_empty();
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
Some(_) => Err(zbus::fdo::Error::AccessDenied(
|
||||
"Cookie belongs to another D-Bus client".into(),
|
||||
)),
|
||||
Some(_) => Err(zbus::fdo::Error::AccessDenied(format!(
|
||||
"Cookie {cookie} belongs to another D-Bus client"
|
||||
))),
|
||||
None => Err(zbus::fdo::Error::Failed("Unknown inhibition cookie".into())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,26 @@ impl BackendThread<NetworkState, UnboundedSender<NetworkCommand>> for NetworkBac
|
||||
}
|
||||
};
|
||||
|
||||
std::thread::spawn({
|
||||
let nm = nm.clone();
|
||||
let mut instance = instance.clone();
|
||||
move || {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("Failed to create Tokio runtime");
|
||||
|
||||
runtime.block_on(async move {
|
||||
while let Ok(tx) = registration_rx.recv() {
|
||||
if tx.send(NetworkState::Init(instance.command_tx.clone())).is_ok() {
|
||||
instance.subscribers.push(tx);
|
||||
let _ = instance.send_all_networks(&nm).await;
|
||||
let _ = instance.send_active_connection(&nm).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
let mut events = match nm.network_events().await {
|
||||
Ok(events) => events,
|
||||
Err(err) => {
|
||||
@@ -169,7 +189,6 @@ impl BackendThread<NetworkState, UnboundedSender<NetworkCommand>> for NetworkBac
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let mut debouncer = EventDebouncer {
|
||||
duration: Duration::from_millis(200),
|
||||
deadline: None,
|
||||
@@ -177,13 +196,6 @@ impl BackendThread<NetworkState, UnboundedSender<NetworkCommand>> for NetworkBac
|
||||
};
|
||||
debouncer.sleep.as_mut().reset(Instant::now() + Duration::from_secs(86400));
|
||||
loop {
|
||||
while let Ok(tx) = registration_rx.try_recv() {
|
||||
if tx.send(NetworkState::Init(instance.command_tx.clone())).is_ok() {
|
||||
instance.subscribers.push(tx);
|
||||
let _ = instance.send_all_networks(&nm).await;
|
||||
let _ = instance.send_active_connection(&nm).await;
|
||||
}
|
||||
}
|
||||
tokio::select! {
|
||||
command = command_rx.recv() => {
|
||||
let Some(command) = command else {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::LOGGER;
|
||||
use crate::backend::{BackendThread, SimpleBackendThread};
|
||||
use crossbeam_channel::{Receiver, Sender};
|
||||
use hyprland::data::{Client, Monitor, Workspaces};
|
||||
use hyprland::data::{Client, CursorPosition, Monitor, Monitors, Workspaces};
|
||||
use hyprland::event_listener::EventListener;
|
||||
use hyprland::prelude::*;
|
||||
use hyprland::shared::{MonitorId, WorkspaceId, WorkspaceType};
|
||||
use hyprland::shared::{MonitorId, WorkspaceId};
|
||||
use jmb_logger_rs::*;
|
||||
use std::io;
|
||||
use std::process::{Command, Output};
|
||||
@@ -24,7 +24,6 @@ pub struct HyprlandComms {
|
||||
}
|
||||
|
||||
impl SimpleBackendThread<WindowManagerEvent> for HyprlandComms {
|
||||
|
||||
fn subscribers(&self) -> &Vec<Sender<WindowManagerEvent>> {
|
||||
&self.subscribers
|
||||
}
|
||||
@@ -38,9 +37,7 @@ impl SimpleBackendThread<WindowManagerEvent> for HyprlandComms {
|
||||
|
||||
let inst_clone = instance.clone();
|
||||
listener.add_workspace_changed_handler(move |workspace| {
|
||||
if let WorkspaceType::Regular(name) = workspace.name
|
||||
&& let Ok(id) = name.parse::<i32>()
|
||||
{
|
||||
if let Ok(id) = workspace.name.parse::<i32>() {
|
||||
inst_clone
|
||||
.lock()
|
||||
.expect("Couldn't get Subscribers")
|
||||
@@ -50,26 +47,24 @@ impl SimpleBackendThread<WindowManagerEvent> for HyprlandComms {
|
||||
|
||||
let inst_clone = instance.clone();
|
||||
listener.add_workspace_added_handler(move |workspace| {
|
||||
if let WorkspaceType::Regular(name) = workspace.name {
|
||||
//unpacks the name of the workspace
|
||||
if let Ok(wss) = Workspaces::get() {
|
||||
//gets all workspaces
|
||||
if let Some(ws) = wss
|
||||
.to_vec()
|
||||
.iter()
|
||||
.find(|ws| ws.id().unwrap() == workspace.id)
|
||||
{
|
||||
//find the current workspace Object from its id
|
||||
if let Ok(id) = name.parse::<i32>() {
|
||||
// parse the id as an int
|
||||
inst_clone
|
||||
.lock()
|
||||
.expect("Couldn't get Subscribers")
|
||||
.publish(WindowManagerEvent::WorkspaceAdded(
|
||||
id,
|
||||
ws.monitor_id.unwrap(),
|
||||
));
|
||||
}
|
||||
//unpacks the name of the workspace
|
||||
if let Ok(wss) = Workspaces::get() {
|
||||
//gets all workspaces
|
||||
if let Some(ws) = wss
|
||||
.to_vec()
|
||||
.iter()
|
||||
.find(|ws| ws.id().unwrap() == workspace.id().unwrap())
|
||||
{
|
||||
//find the current workspace Object from its id
|
||||
if let Ok(id) = workspace.name.parse::<i32>() {
|
||||
// parse the id as an int
|
||||
inst_clone
|
||||
.lock()
|
||||
.expect("Couldn't get Subscribers")
|
||||
.publish(WindowManagerEvent::WorkspaceAdded(
|
||||
id,
|
||||
ws.monitor_id.unwrap(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,9 +72,7 @@ impl SimpleBackendThread<WindowManagerEvent> for HyprlandComms {
|
||||
|
||||
let inst_clone = instance.clone();
|
||||
listener.add_workspace_deleted_handler(move |workspace| {
|
||||
if let WorkspaceType::Regular(name) = workspace.name
|
||||
&& let Ok(id) = name.parse::<i32>()
|
||||
{
|
||||
if let Ok(id) = workspace.name.parse::<i32>() {
|
||||
inst_clone
|
||||
.lock()
|
||||
.expect("Couldn't get Subscribers")
|
||||
@@ -92,7 +85,9 @@ impl SimpleBackendThread<WindowManagerEvent> for HyprlandComms {
|
||||
inst_clone
|
||||
.lock()
|
||||
.expect("Couldn't get Subscribers")
|
||||
.publish(WindowManagerEvent::WorkspaceChanged(evt.workspace_id));
|
||||
.publish(WindowManagerEvent::WorkspaceChanged(
|
||||
evt.workspace.id().unwrap(),
|
||||
));
|
||||
});
|
||||
|
||||
let inst_clone = instance.clone();
|
||||
@@ -106,15 +101,22 @@ impl SimpleBackendThread<WindowManagerEvent> for HyprlandComms {
|
||||
|
||||
let inst_clone = instance.clone();
|
||||
listener.add_workspace_moved_handler(move |event| {
|
||||
if let Some(monitor_id) = Self::monitor_id_from_workspace_id(event.id) {
|
||||
if let Some(monitor_id) =
|
||||
Self::monitor_id_from_workspace_id(event.workspace.id().unwrap())
|
||||
{
|
||||
inst_clone
|
||||
.lock()
|
||||
.expect("Couldn't get Subscribers")
|
||||
.publish(WindowManagerEvent::WorkspaceRemoved(event.id));
|
||||
.publish(WindowManagerEvent::WorkspaceRemoved(
|
||||
event.workspace.id().unwrap(),
|
||||
));
|
||||
inst_clone
|
||||
.lock()
|
||||
.expect("Couldn't get Subscribers")
|
||||
.publish(WindowManagerEvent::WorkspaceAdded(event.id, monitor_id));
|
||||
.publish(WindowManagerEvent::WorkspaceAdded(
|
||||
event.workspace.id().unwrap(),
|
||||
monitor_id,
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -160,7 +162,7 @@ impl HyprlandComms {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn _current_monitor() -> MonitorId {
|
||||
pub fn current_monitor() -> MonitorId {
|
||||
if let Ok(monitor) = Monitor::get_active() {
|
||||
return monitor.id;
|
||||
}
|
||||
@@ -197,4 +199,22 @@ impl HyprlandComms {
|
||||
.arg(format!("hyprctl dispatch \"{dispatcher}\""))
|
||||
.output()
|
||||
}
|
||||
|
||||
pub fn cursor_monitor() -> Option<MonitorId> {
|
||||
if let Ok(pos) = CursorPosition::get()
|
||||
&& let Ok(monitors) = Monitors::get()
|
||||
{
|
||||
for monitor in monitors {
|
||||
if pos.x > monitor.x as i64
|
||||
&& pos.x < (monitor.x as i64 + monitor.width as i64)
|
||||
&& pos.y > monitor.y as i64
|
||||
&& pos.y < (monitor.y as i64 + monitor.height as i64)
|
||||
{
|
||||
return Some(monitor.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user