use core::cell::RefCell;
use std::sync::{Arc, Mutex, PoisonError};
use accesskit::{ActionHandler, ActionRequest, ActivationHandler, TreeUpdate};
use accesskit_windows::{Adapter, HWND, LPARAM, LRESULT, WPARAM};
use super::ffi::{Handle, Lparam, Lresult, Wparam};
use super::proc::key;
use crate::ShellWaker;
#[derive(Clone, Debug, Default)]
struct Actions(Arc<Mutex<Vec<(isize, ActionRequest)>>>);
impl Actions {
fn push(&self, hwnd: isize, request: ActionRequest) {
self.0
.lock()
.unwrap_or_else(PoisonError::into_inner)
.push((hwnd, request));
}
fn take(&self) -> Vec<(isize, ActionRequest)> {
core::mem::take(&mut *self.0.lock().unwrap_or_else(PoisonError::into_inner))
}
fn forget(&self, hwnd: isize) {
self.0
.lock()
.unwrap_or_else(PoisonError::into_inner)
.retain(|&(known, _)| known != hwnd);
}
}
struct Handler {
hwnd: isize,
actions: Actions,
waker: Option<ShellWaker>,
}
impl ActionHandler for Handler {
fn do_action(&mut self, request: ActionRequest) {
self.actions.push(self.hwnd, request);
if let Some(waker) = &self.waker {
waker.wake();
}
}
}
#[derive(Default)]
struct Activation {
asked: bool,
}
impl ActivationHandler for Activation {
fn request_initial_tree(&mut self) -> Option<TreeUpdate> {
self.asked = true;
None
}
}
pub(super) struct GetObject {
pub lresult: Option<Lresult>,
pub activated: bool,
}
#[derive(Debug, Default)]
pub(super) struct Adapters {
adapters: RefCell<Vec<(isize, Adapter)>>,
actions: Actions,
}
impl Adapters {
pub(super) fn open(&self, hwnd: Handle, focused: bool, waker: Option<ShellWaker>) {
let window = key(hwnd);
let handler = Handler {
hwnd: window,
actions: self.actions.clone(),
waker,
};
let adapter = Adapter::new(HWND(hwnd), focused, handler);
self.adapters.borrow_mut().push((window, adapter));
}
pub(super) fn take_actions(&self) -> Vec<(isize, ActionRequest)> {
self.actions.take()
}
pub(super) fn close(&self, hwnd: isize) {
self.actions.forget(hwnd);
let removed = {
let mut adapters = self.adapters.borrow_mut();
adapters
.iter()
.position(|&(known, _)| known == hwnd)
.map(|index| adapters.remove(index))
};
drop(removed);
}
pub(super) fn get_object(&self, hwnd: isize, w_param: Wparam, l_param: Lparam) -> GetObject {
let mut activation = Activation::default();
let provider = {
let mut adapters = self.adapters.borrow_mut();
adapters
.iter_mut()
.find(|(known, _)| *known == hwnd)
.and_then(|(_, adapter)| {
adapter.handle_wm_getobject(WPARAM(w_param), LPARAM(l_param), &mut activation)
})
};
let lresult = provider.map(|provider| {
let LRESULT(lresult) = provider.into();
lresult
});
GetObject {
lresult,
activated: activation.asked,
}
}
pub(super) fn focus(&self, hwnd: isize, focused: bool) {
let events = {
let mut adapters = self.adapters.borrow_mut();
adapters
.iter_mut()
.find(|(known, _)| *known == hwnd)
.and_then(|(_, adapter)| adapter.update_window_focus_state(focused))
};
if let Some(events) = events {
events.raise();
}
}
pub(super) fn update(&self, hwnd: isize, update: TreeUpdate) {
let events = {
let mut adapters = self.adapters.borrow_mut();
adapters
.iter_mut()
.find(|(known, _)| *known == hwnd)
.and_then(|(_, adapter)| adapter.update_if_active(|| update))
};
if let Some(events) = events {
events.raise();
}
}
}