use std::num::NonZeroU32;
use std::task::Waker;
use super::{PendingAction, Platform, WindowSurface};
use kas::config::Options;
use kas::shell::Error;
use kas::theme::Theme;
use kas::util::warn_about_error;
use kas::{draw, AppData, ErasedStack, WindowId};
use std::cell::RefCell;
use std::rc::Rc;
#[cfg(feature = "clipboard")] use arboard::Clipboard;
pub(super) struct ShellShared<Data: AppData, S: kas::draw::DrawSharedImpl, T> {
pub(super) platform: Platform,
#[cfg(feature = "clipboard")]
clipboard: Option<Clipboard>,
pub(super) draw: draw::SharedState<S>,
pub(super) theme: T,
pub(super) pending: Vec<PendingAction<Data>>,
pub(super) waker: Waker,
window_id: u32,
}
pub struct SharedState<Data: AppData, S: WindowSurface, T> {
pub(super) shell: ShellShared<Data, S::Shared, T>,
pub(super) data: Data,
pub(super) config: Rc<RefCell<kas::event::Config>>,
pub(super) scale_factor: f64,
options: Options,
}
impl<Data: AppData, S: WindowSurface, T: Theme<S::Shared>> SharedState<Data, S, T>
where
T::Window: kas::theme::Window,
{
pub(super) fn new(
data: Data,
pw: super::PlatformWrapper,
draw_shared: S::Shared,
mut theme: T,
options: Options,
config: Rc<RefCell<kas::event::Config>>,
) -> Result<Self, Error> {
let platform = pw.platform();
let mut draw = kas::draw::SharedState::new(draw_shared, platform);
theme.init(&mut draw);
#[cfg(feature = "clipboard")]
let clipboard = match Clipboard::new() {
Ok(cb) => Some(cb),
Err(e) => {
warn_about_error("Failed to connect clipboard", &e);
None
}
};
Ok(SharedState {
shell: ShellShared {
platform,
#[cfg(feature = "clipboard")]
clipboard,
draw,
theme,
pending: vec![],
waker: pw.create_waker(),
window_id: 0,
},
data,
config,
scale_factor: pw.guess_scale_factor(),
options,
})
}
#[inline]
pub(crate) fn handle_messages(&mut self, messages: &mut ErasedStack) {
if messages.reset_and_has_any() {
let action = self.data.handle_messages(messages);
self.shell.pending.push(PendingAction::Action(action));
}
}
pub fn on_exit(&self) {
match self
.options
.write_config(&self.config.borrow(), &self.shell.theme)
{
Ok(()) => (),
Err(error) => warn_about_error("Failed to save config", &error),
}
}
}
impl<Data: AppData, S: kas::draw::DrawSharedImpl, T> ShellShared<Data, S, T> {
pub fn next_window_id(&mut self) -> WindowId {
let id = self.window_id + 1;
self.window_id = id;
WindowId::new(NonZeroU32::new(id).unwrap())
}
#[inline]
pub fn get_clipboard(&mut self) -> Option<String> {
#[cfg(feature = "clipboard")]
{
if let Some(cb) = self.clipboard.as_mut() {
match cb.get_text() {
Ok(s) => return Some(s),
Err(e) => warn_about_error("Failed to get clipboard contents", &e),
}
}
}
None
}
#[inline]
pub fn set_clipboard(&mut self, _content: String) {
#[cfg(feature = "clipboard")]
if let Some(cb) = self.clipboard.as_mut() {
match cb.set_text(_content) {
Ok(()) => (),
Err(e) => warn_about_error("Failed to set clipboard contents", &e),
}
}
}
#[inline]
pub fn get_primary(&mut self) -> Option<String> {
#[cfg(all(
unix,
not(any(target_os = "macos", target_os = "android", target_os = "emscripten")),
feature = "clipboard",
))]
{
use arboard::{GetExtLinux, LinuxClipboardKind};
if let Some(cb) = self.clipboard.as_mut() {
match cb.get().clipboard(LinuxClipboardKind::Primary).text() {
Ok(s) => return Some(s),
Err(e) => warn_about_error("Failed to get clipboard contents", &e),
}
}
}
None
}
#[inline]
pub fn set_primary(&mut self, _content: String) {
#[cfg(all(
unix,
not(any(target_os = "macos", target_os = "android", target_os = "emscripten")),
feature = "clipboard",
))]
if let Some(cb) = self.clipboard.as_mut() {
use arboard::{LinuxClipboardKind, SetExtLinux};
match cb
.set()
.clipboard(LinuxClipboardKind::Primary)
.text(_content)
{
Ok(()) => (),
Err(e) => warn_about_error("Failed to set clipboard contents", &e),
}
}
}
}