state: split idle handling
This commit is contained in:
parent
27750a31c4
commit
cd1f049a3e
2 changed files with 144 additions and 120 deletions
126
src/state.rs
126
src/state.rs
|
|
@ -1,9 +1,11 @@
|
||||||
mod animations;
|
mod animations;
|
||||||
mod connectors;
|
mod connectors;
|
||||||
|
mod idle;
|
||||||
mod rendering;
|
mod rendering;
|
||||||
|
|
||||||
pub(crate) use animations::LayoutAnimationCandidate;
|
pub(crate) use animations::LayoutAnimationCandidate;
|
||||||
pub use connectors::{ConnectorData, DrmDevData, OutputData};
|
pub use connectors::{ConnectorData, DrmDevData, OutputData};
|
||||||
|
pub use idle::IdleState;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
|
|
@ -15,7 +17,7 @@ use {
|
||||||
Backend, BackendConnectorStateSerials, BackendEvent, ConnectorId, ConnectorIds,
|
Backend, BackendConnectorStateSerials, BackendEvent, ConnectorId, ConnectorIds,
|
||||||
DrmDeviceId, DrmDeviceIds, HardwareCursorUpdate, InputDevice, InputDeviceGroupIds,
|
DrmDeviceId, DrmDeviceIds, HardwareCursorUpdate, InputDevice, InputDeviceGroupIds,
|
||||||
InputDeviceId, InputDeviceIds, TabletIds, TabletInit, TabletPadIds, TabletPadInit,
|
InputDeviceId, InputDeviceIds, TabletIds, TabletInit, TabletPadIds, TabletPadInit,
|
||||||
TabletToolIds, transaction::{BackendConnectorTransactionError, ConnectorTransaction},
|
TabletToolIds,
|
||||||
},
|
},
|
||||||
backends::dummy::DummyBackend,
|
backends::dummy::DummyBackend,
|
||||||
cli::RunArgs,
|
cli::RunArgs,
|
||||||
|
|
@ -43,7 +45,6 @@ use {
|
||||||
icons::Icons,
|
icons::Icons,
|
||||||
ifs::{
|
ifs::{
|
||||||
ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1,
|
ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1,
|
||||||
ext_idle_notification_v1::ExtIdleNotificationV1,
|
|
||||||
ext_session_lock_v1::ExtSessionLockV1,
|
ext_session_lock_v1::ExtSessionLockV1,
|
||||||
head_management::{
|
head_management::{
|
||||||
HeadNames, jay_head_manager_session_v1::{HeadManagerEvent, JayHeadManagerSessionV1},
|
HeadNames, jay_head_manager_session_v1::{HeadManagerEvent, JayHeadManagerSessionV1},
|
||||||
|
|
@ -67,7 +68,7 @@ use {
|
||||||
wl_subsurface::SubsurfaceIds,
|
wl_subsurface::SubsurfaceIds,
|
||||||
x_surface::xwindow::{Xwindow, XwindowId},
|
x_surface::xwindow::{Xwindow, XwindowId},
|
||||||
xdg_surface::XdgSurfaceConfigureEvent,
|
xdg_surface::XdgSurfaceConfigureEvent,
|
||||||
zwp_idle_inhibitor_v1::{IdleInhibitorId, IdleInhibitorIds, ZwpIdleInhibitorV1},
|
zwp_idle_inhibitor_v1::IdleInhibitorIds,
|
||||||
zwp_input_popup_surface_v2::ZwpInputPopupSurfaceV2,
|
zwp_input_popup_surface_v2::ZwpInputPopupSurfaceV2,
|
||||||
},
|
},
|
||||||
wlr_output_manager::WlrOutputManagerState,
|
wlr_output_manager::WlrOutputManagerState,
|
||||||
|
|
@ -117,7 +118,7 @@ use {
|
||||||
virtual_output::VirtualOutputs,
|
virtual_output::VirtualOutputs,
|
||||||
wheel::Wheel,
|
wheel::Wheel,
|
||||||
wire::{
|
wire::{
|
||||||
ExtForeignToplevelListV1Id, ExtIdleNotificationV1Id, JayHeadManagerSessionV1Id,
|
ExtForeignToplevelListV1Id, JayHeadManagerSessionV1Id,
|
||||||
JayRenderCtxId, JaySeatEventsId, JayWorkspaceWatcherId, ZwlrForeignToplevelManagerV1Id,
|
JayRenderCtxId, JaySeatEventsId, JayWorkspaceWatcherId, ZwlrForeignToplevelManagerV1Id,
|
||||||
ZwpLinuxDmabufFeedbackV1Id,
|
ZwpLinuxDmabufFeedbackV1Id,
|
||||||
},
|
},
|
||||||
|
|
@ -132,7 +133,7 @@ use {
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
rc::{Rc, Weak},
|
rc::{Rc, Weak},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::{Duration, SystemTime},
|
time::SystemTime,
|
||||||
},
|
},
|
||||||
uapi::{OwnedFd, c},
|
uapi::{OwnedFd, c},
|
||||||
};
|
};
|
||||||
|
|
@ -321,74 +322,6 @@ pub struct XWaylandState {
|
||||||
pub display: CloneCell<Option<Rc<String>>>,
|
pub display: CloneCell<Option<Rc<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct InputDeviceData {
|
pub struct InputDeviceData {
|
||||||
pub _handler: SpawnedFuture<()>,
|
pub _handler: SpawnedFuture<()>,
|
||||||
pub id: InputDeviceId,
|
pub id: InputDeviceId,
|
||||||
|
|
@ -839,19 +772,6 @@ 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 start_xwayland(self: &Rc<Self>) {
|
pub fn start_xwayland(self: &Rc<Self>) {
|
||||||
if !self.xwayland.enabled.get() {
|
if !self.xwayland.enabled.get() {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1098,40 +1018,6 @@ impl State {
|
||||||
seat
|
seat
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_closest_output(&self, mut x: i32, mut y: i32) -> (Rc<OutputNode>, i32, i32) {
|
pub fn find_closest_output(&self, mut x: i32, mut y: i32) -> (Rc<OutputNode>, i32, i32) {
|
||||||
let mut optimal_dist = i128::MAX;
|
let mut optimal_dist = i128::MAX;
|
||||||
let mut optimal_output = None;
|
let mut optimal_output = None;
|
||||||
|
|
|
||||||
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