state: split idle handling
This commit is contained in:
parent
27750a31c4
commit
cd1f049a3e
2 changed files with 144 additions and 120 deletions
138
src/state/idle.rs
Normal file
138
src/state/idle.rs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
use {
|
||||
crate::{
|
||||
backend::transaction::{BackendConnectorTransactionError, ConnectorTransaction},
|
||||
client::ClientId,
|
||||
ifs::{
|
||||
ext_idle_notification_v1::ExtIdleNotificationV1,
|
||||
wl_surface::zwp_idle_inhibitor_v1::{
|
||||
IdleInhibitorId, ZwpIdleInhibitorV1,
|
||||
},
|
||||
},
|
||||
utils::{
|
||||
asyncevent::AsyncEvent, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
||||
hash_map_ext::HashMapExt,
|
||||
},
|
||||
wire::ExtIdleNotificationV1Id,
|
||||
},
|
||||
std::{cell::Cell, rc::Rc, time::Duration},
|
||||
};
|
||||
|
||||
use super::State;
|
||||
|
||||
pub struct IdleState {
|
||||
pub input: Cell<bool>,
|
||||
pub change: AsyncEvent,
|
||||
pub timeout: Cell<Duration>,
|
||||
pub grace_period: Cell<Duration>,
|
||||
pub key_press_enables_dpms: Cell<bool>,
|
||||
pub mouse_move_enables_dpms: Cell<bool>,
|
||||
pub timeout_changed: Cell<bool>,
|
||||
pub inhibitors: CopyHashMap<IdleInhibitorId, Rc<ZwpIdleInhibitorV1>>,
|
||||
pub inhibitors_changed: Cell<bool>,
|
||||
pub backend_idle: Cell<bool>,
|
||||
pub dpms_off_by_command: Cell<bool>,
|
||||
pub inhibited_idle_notifications:
|
||||
CopyHashMap<(ClientId, ExtIdleNotificationV1Id), Rc<ExtIdleNotificationV1>>,
|
||||
pub in_grace_period: Cell<bool>,
|
||||
}
|
||||
|
||||
impl IdleState {
|
||||
pub fn set_timeout(&self, state: &State, timeout: Duration) {
|
||||
self.timeout.set(timeout);
|
||||
self.timeout_changed(state);
|
||||
}
|
||||
|
||||
pub fn set_grace_period(&self, state: &State, grace_period: Duration) {
|
||||
self.grace_period.set(grace_period);
|
||||
self.timeout_changed(state);
|
||||
}
|
||||
|
||||
fn timeout_changed(&self, _state: &State) {
|
||||
self.timeout_changed.set(true);
|
||||
self.change.trigger();
|
||||
}
|
||||
|
||||
pub fn add_inhibitor(&self, state: &State, inhibitor: &Rc<ZwpIdleInhibitorV1>) {
|
||||
self.inhibitors.set(inhibitor.inhibit_id, inhibitor.clone());
|
||||
self.inhibitors_changed(state);
|
||||
}
|
||||
|
||||
pub fn remove_inhibitor(&self, state: &State, inhibitor: &ZwpIdleInhibitorV1) {
|
||||
self.inhibitors.remove(&inhibitor.inhibit_id);
|
||||
self.inhibitors_changed(state);
|
||||
if self.inhibitors.is_empty() {
|
||||
self.resume_inhibited_notifications();
|
||||
}
|
||||
}
|
||||
|
||||
fn inhibitors_changed(&self, _state: &State) {
|
||||
self.inhibitors_changed.set(true);
|
||||
self.change.trigger();
|
||||
}
|
||||
|
||||
fn resume_inhibited_notifications(&self) {
|
||||
for notification in self.inhibited_idle_notifications.lock().drain_values() {
|
||||
notification.resume.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_inhibited_notification(&self, n: &Rc<ExtIdleNotificationV1>) {
|
||||
self.inhibited_idle_notifications
|
||||
.set((n.client.id, n.id), n.clone());
|
||||
}
|
||||
|
||||
pub fn remove_inhibited_notification(&self, n: &ExtIdleNotificationV1) {
|
||||
self.inhibited_idle_notifications
|
||||
.remove(&(n.client.id, n.id));
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn input_occurred(self: &Rc<Self>, key_press: bool, mouse_move: bool) {
|
||||
if self.idle.dpms_off_by_command.get() {
|
||||
let enable_dpms = key_press && self.idle.key_press_enables_dpms.get()
|
||||
|| mouse_move && self.idle.mouse_move_enables_dpms.get();
|
||||
if enable_dpms && let Err(e) = self.set_dpms_active(true) {
|
||||
log::error!("Could not enable DPMS after input: {}", ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
if !self.idle.input.replace(true) {
|
||||
self.idle.change.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_backend_idle(&self, idle: bool) {
|
||||
if self.idle.backend_idle.replace(idle) != idle {
|
||||
self.root.update_visible(self);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_connectors_active(
|
||||
self: &Rc<Self>,
|
||||
active: bool,
|
||||
) -> Result<(), BackendConnectorTransactionError> {
|
||||
let mut tran = ConnectorTransaction::new(self);
|
||||
for connector in self.connectors.lock().values() {
|
||||
let mut state = connector.state.borrow().clone();
|
||||
state.active = active;
|
||||
tran.add(&connector.connector, state)?;
|
||||
}
|
||||
tran.prepare()?.apply()?.commit();
|
||||
self.set_backend_idle(!active);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_dpms_active(
|
||||
self: &Rc<Self>,
|
||||
active: bool,
|
||||
) -> Result<(), BackendConnectorTransactionError> {
|
||||
self.set_connectors_active(active)?;
|
||||
self.idle.dpms_off_by_command.set(!active);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn root_visible(&self) -> bool {
|
||||
!self.idle.backend_idle.get()
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue