1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-27 12:23:46 +03:00

add apply function to safely access inner data

This commit is contained in:
Wez Furlong 2019-08-13 22:53:35 -07:00
parent d69938701c
commit e98b29aec6
4 changed files with 59 additions and 3 deletions

View File

@ -1,19 +1,20 @@
use crate::config::Config; use crate::config::Config;
use crate::font::FontConfiguration; use crate::font::FontConfiguration;
use crate::frontend::guicommon::host::{HostHelper, HostImpl, TabHost}; use crate::frontend::guicommon::host::{HostHelper, HostImpl, TabHost};
use crate::frontend::guicommon::window::TerminalWindow;
use crate::mux::tab::Tab; use crate::mux::tab::Tab;
use crate::mux::window::WindowId as MuxWindowId; use crate::mux::window::WindowId as MuxWindowId;
use crate::mux::Mux; use crate::mux::Mux;
use ::window::*; use ::window::*;
use failure::Fallible; use failure::Fallible;
use promise::Future; use promise::Future;
use std::any::Any;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
pub struct TermWindow { pub struct TermWindow {
config: Arc<Config>, window: Option<Window>,
fonts: Rc<FontConfiguration>, fonts: Rc<FontConfiguration>,
config: Arc<Config>,
width: usize, width: usize,
height: usize, height: usize,
cell_height: usize, cell_height: usize,
@ -22,6 +23,10 @@ pub struct TermWindow {
} }
impl WindowCallbacks for TermWindow { impl WindowCallbacks for TermWindow {
fn created(&mut self, window: &Window) {
self.window.replace(window.clone());
}
fn can_close(&mut self) -> bool { fn can_close(&mut self) -> bool {
// self.host.close_current_tab(); // self.host.close_current_tab();
true true
@ -38,6 +43,13 @@ impl WindowCallbacks for TermWindow {
*/ */
Connection::get().unwrap().terminate_message_loop(); Connection::get().unwrap().terminate_message_loop();
} }
fn as_any(&mut self) -> &mut dyn Any {
self
}
fn paint(&mut self, ctx: &mut dyn PaintContext) {
}
} }
impl Drop for TermWindow { impl Drop for TermWindow {
@ -72,6 +84,7 @@ impl TermWindow {
width, width,
height, height,
Box::new(Self { Box::new(Self {
window: None,
width, width,
height, height,
cell_height, cell_height,

View File

@ -1,5 +1,6 @@
use ::window::*; use ::window::*;
use failure::Fallible; use failure::Fallible;
use std::any::Any;
struct MyWindow { struct MyWindow {
allow_close: bool, allow_close: bool,
@ -75,6 +76,10 @@ impl WindowCallbacks for MyWindow {
spawn_window().unwrap(); spawn_window().unwrap();
} }
} }
fn as_any(&mut self) -> &mut dyn Any {
self
}
} }
fn spawn_window() -> Fallible<()> { fn spawn_window() -> Fallible<()> {
@ -90,6 +95,14 @@ fn spawn_window() -> Fallible<()> {
)?; )?;
win.show(); win.show();
win.apply(|myself, win| {
if let Some(myself) = myself.downcast_ref::<MyWindow>() {
eprintln!(
"got myself; allow_close={}, cursor_pos:{:?}",
myself.allow_close, myself.cursor_pos
);
}
});
Ok(()) Ok(())
} }

View File

@ -1,3 +1,4 @@
use std::any::Any;
pub mod bitmaps; pub mod bitmaps;
pub mod color; pub mod color;
pub mod input; pub mod input;
@ -100,7 +101,7 @@ pub enum MouseCursor {
} }
#[allow(unused_variables)] #[allow(unused_variables)]
pub trait WindowCallbacks { pub trait WindowCallbacks: Any {
/// Called when the window close button is clicked. /// Called when the window close button is clicked.
/// Return true to allow the close to continue, false to /// Return true to allow the close to continue, false to
/// prevent it from closing. /// prevent it from closing.
@ -134,6 +135,13 @@ pub trait WindowCallbacks {
/// Called when the window is created and allows the embedding /// Called when the window is created and allows the embedding
/// app to reference the window and operate upon it. /// app to reference the window and operate upon it.
fn created(&mut self, window: &Window) {} fn created(&mut self, window: &Window) {}
/// An unfortunate bit of boilerplate; you need to provie an impl
/// of this method that returns `self` in order for the downcast_ref
/// method of the Any trait to be usable on WindowCallbacks.
/// https://stackoverflow.com/q/46045298/149111 and others have
/// some rationale on why Rust works this way.
fn as_any(&mut self) -> &mut dyn Any;
} }
pub trait WindowOps { pub trait WindowOps {
@ -152,6 +160,14 @@ pub trait WindowOps {
/// Change the titlebar text for the window /// Change the titlebar text for the window
fn set_title(&self, title: &str); fn set_title(&self, title: &str);
/// Schedule a callback on the data associated with the window.
/// The `Any` that is passed in corresponds to the WindowCallbacks
/// impl you passed to `new_window`, pre-converted to Any so that
/// you can `downcast_ref` or `downcast_mut` it and operate on it.
fn apply<F: Send + 'static + Fn(&mut dyn Any, &dyn WindowOps)>(&self, func: F)
where
Self: Sized;
} }
pub trait WindowOpsMut { pub trait WindowOpsMut {

View File

@ -19,6 +19,7 @@ use objc::declare::ClassDecl;
use objc::rc::{StrongPtr, WeakPtr}; use objc::rc::{StrongPtr, WeakPtr};
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::*; use objc::*;
use std::any::Any;
use std::cell::RefCell; use std::cell::RefCell;
use std::ffi::c_void; use std::ffi::c_void;
use std::rc::Rc; use std::rc::Rc;
@ -119,6 +120,19 @@ impl WindowOps for Window {
let title = title.to_owned(); let title = title.to_owned();
Connection::with_window_inner(self.0, move |inner| inner.set_title(&title)); Connection::with_window_inner(self.0, move |inner| inner.set_title(&title));
} }
fn apply<F: Send + 'static + Fn(&mut dyn Any, &dyn WindowOps)>(&self, func: F)
where
Self: Sized,
{
Connection::with_window_inner(self.0, move |inner| {
let window = Window(inner.window_id);
if let Some(window_view) = WindowView::get_this(unsafe { &**inner.view }) {
func(window_view.inner.borrow_mut().callbacks.as_any(), &window);
}
});
}
} }
impl WindowOpsMut for WindowInner { impl WindowOpsMut for WindowInner {