mirror of
https://github.com/wez/wezterm.git
synced 2024-11-10 15:04:32 +03:00
plumb WindowOps for macos
This commit is contained in:
parent
0f25545014
commit
d8b143776d
@ -42,4 +42,5 @@ libc = "0.2"
|
||||
[target.'cfg(target_os="macos")'.dependencies]
|
||||
cocoa = "0.19"
|
||||
objc = "0.2"
|
||||
core-foundation = "0.6"
|
||||
core-graphics = "0.17"
|
||||
|
@ -1,17 +1,80 @@
|
||||
use super::window::WindowInner;
|
||||
use cocoa::appkit::{NSApp, NSApplication, NSApplicationActivationPolicyRegular};
|
||||
use cocoa::base::{id, nil};
|
||||
use core_foundation::runloop::*;
|
||||
use failure::Fallible;
|
||||
use objc::*;
|
||||
use promise::{BasicExecutor, SpawnFunc};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub struct Connection {
|
||||
ns_app: id,
|
||||
pub(crate) windows: RefCell<HashMap<usize, Rc<RefCell<WindowInner>>>>,
|
||||
pub(crate) next_window_id: AtomicUsize,
|
||||
}
|
||||
|
||||
struct SpawnQueue {
|
||||
spawned_funcs: Mutex<VecDeque<SpawnFunc>>,
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static CONN: RefCell<Option<Rc<Connection>>> = RefCell::new(None);
|
||||
}
|
||||
lazy_static::lazy_static! {
|
||||
static ref SPAWN_QUEUE: Arc<SpawnQueue> = Arc::new(SpawnQueue::new().expect("failed to create SpawnQueue"));
|
||||
}
|
||||
|
||||
impl Drop for SpawnQueue {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl SpawnQueue {
|
||||
fn new() -> Fallible<Self> {
|
||||
let spawned_funcs = Mutex::new(VecDeque::new());
|
||||
|
||||
let observer = unsafe {
|
||||
CFRunLoopObserverCreate(
|
||||
std::ptr::null(),
|
||||
kCFRunLoopAllActivities,
|
||||
1,
|
||||
0,
|
||||
SpawnQueue::trigger,
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
unsafe {
|
||||
CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes);
|
||||
}
|
||||
|
||||
Ok(Self { spawned_funcs })
|
||||
}
|
||||
|
||||
extern "C" fn trigger(_observer: *mut __CFRunLoopObserver, _: u32, _: *mut std::ffi::c_void) {
|
||||
SPAWN_QUEUE.run();
|
||||
}
|
||||
|
||||
fn spawn(&self, f: SpawnFunc) {
|
||||
self.spawned_funcs.lock().unwrap().push_back(f);
|
||||
unsafe {
|
||||
CFRunLoopWakeUp(CFRunLoopGetMain());
|
||||
}
|
||||
}
|
||||
|
||||
fn run(&self) {
|
||||
loop {
|
||||
if let Some(func) = self.spawned_funcs.lock().unwrap().pop_front() {
|
||||
func();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
pub fn get() -> Option<Rc<Self>> {
|
||||
@ -25,10 +88,18 @@ impl Connection {
|
||||
}
|
||||
|
||||
pub fn init() -> Fallible<Rc<Self>> {
|
||||
// Ensure that the SPAWN_QUEUE is created; it will have nothing
|
||||
// to run right now.
|
||||
SPAWN_QUEUE.run();
|
||||
|
||||
unsafe {
|
||||
let ns_app = NSApp();
|
||||
ns_app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
|
||||
let conn = Rc::new(Self { ns_app });
|
||||
let conn = Rc::new(Self {
|
||||
ns_app,
|
||||
windows: RefCell::new(HashMap::new()),
|
||||
next_window_id: AtomicUsize::new(1),
|
||||
});
|
||||
CONN.with(|m| *m.borrow_mut() = Some(Rc::clone(&conn)));
|
||||
Ok(conn)
|
||||
}
|
||||
@ -46,4 +117,36 @@ impl Connection {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn executor() -> impl BasicExecutor {
|
||||
SpawnQueueExecutor {}
|
||||
}
|
||||
|
||||
pub(crate) fn next_window_id(&self) -> usize {
|
||||
self.next_window_id
|
||||
.fetch_add(1, ::std::sync::atomic::Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn window_by_id(&self, window_id: usize) -> Option<Rc<RefCell<WindowInner>>> {
|
||||
self.windows.borrow().get(&window_id).map(Rc::clone)
|
||||
}
|
||||
|
||||
pub(crate) fn with_window_inner<F: FnMut(&mut WindowInner) + Send + 'static>(
|
||||
window_id: usize,
|
||||
mut f: F,
|
||||
) {
|
||||
SpawnQueueExecutor {}.execute(Box::new(move || {
|
||||
if let Some(handle) = Connection::get().unwrap().window_by_id(window_id) {
|
||||
let mut inner = handle.borrow_mut();
|
||||
f(&mut inner);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
struct SpawnQueueExecutor;
|
||||
impl BasicExecutor for SpawnQueueExecutor {
|
||||
fn execute(&self, f: SpawnFunc) {
|
||||
SPAWN_QUEUE.spawn(f)
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,9 @@ use super::{nsstring, nsstring_to_str};
|
||||
use crate::bitmaps::Image;
|
||||
use crate::os::macos::bitmap::BitmapRef;
|
||||
use crate::{
|
||||
BitmapImage, Color, Dimensions, KeyCode, KeyEvent, Modifiers, MouseButtons, MouseEvent,
|
||||
MouseEventKind, MousePress, Operator, PaintContext, WindowCallbacks,
|
||||
BitmapImage, Color, Connection, Dimensions, KeyCode, KeyEvent, Modifiers, MouseButtons,
|
||||
MouseCursor, MouseEvent, MouseEventKind, MousePress, Operator, PaintContext, WindowCallbacks,
|
||||
WindowOps, WindowOpsMut,
|
||||
};
|
||||
use cocoa::appkit::{
|
||||
NSApplicationActivateIgnoringOtherApps, NSBackingStoreBuffered, NSEvent, NSEventModifierFlags,
|
||||
@ -22,16 +23,14 @@ use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Window {
|
||||
pub(crate) struct WindowInner {
|
||||
window_id: usize,
|
||||
window: StrongPtr,
|
||||
view: StrongPtr,
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
eprintln!("drop Window");
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Window(usize);
|
||||
|
||||
impl Window {
|
||||
pub fn new_window(
|
||||
@ -51,9 +50,14 @@ impl Window {
|
||||
NSSize::new(width as f64, height as f64),
|
||||
);
|
||||
|
||||
let conn = Connection::get().expect("Connection::init has not been called");
|
||||
|
||||
let window_id = conn.next_window_id();
|
||||
|
||||
let inner = Rc::new(RefCell::new(Inner {
|
||||
callbacks,
|
||||
view_id: None,
|
||||
window_id,
|
||||
}));
|
||||
|
||||
let window = StrongPtr::new(
|
||||
@ -76,22 +80,70 @@ impl Window {
|
||||
window.setContentView_(*view);
|
||||
window.setDelegate_(*view);
|
||||
|
||||
Ok(Self { window, view })
|
||||
let window_inner = Rc::new(RefCell::new(WindowInner {
|
||||
window_id,
|
||||
window,
|
||||
view,
|
||||
}));
|
||||
conn.windows
|
||||
.borrow_mut()
|
||||
.insert(window_id, Rc::clone(&window_inner));
|
||||
|
||||
let window = Window(window_id);
|
||||
|
||||
inner.borrow_mut().callbacks.created(&window);
|
||||
|
||||
Ok(window)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show(&self) {
|
||||
impl WindowOps for Window {
|
||||
fn hide(&self) {
|
||||
Connection::with_window_inner(self.0, |inner| inner.hide());
|
||||
}
|
||||
fn show(&self) {
|
||||
eprintln!("schedule show");
|
||||
Connection::with_window_inner(self.0, |inner| inner.show());
|
||||
}
|
||||
fn set_cursor(&self, cursor: Option<MouseCursor>) {
|
||||
Connection::with_window_inner(self.0, move |inner| {
|
||||
let _ = inner.set_cursor(cursor);
|
||||
});
|
||||
}
|
||||
fn invalidate(&self) {
|
||||
Connection::with_window_inner(self.0, |inner| inner.invalidate());
|
||||
}
|
||||
fn set_title(&self, title: &str) {
|
||||
let title = title.to_owned();
|
||||
Connection::with_window_inner(self.0, move |inner| inner.set_title(&title));
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowOpsMut for WindowInner {
|
||||
fn show(&mut self) {
|
||||
eprintln!("do show");
|
||||
unsafe {
|
||||
let current_app = NSRunningApplication::currentApplication(nil);
|
||||
current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps);
|
||||
self.window.makeKeyAndOrderFront_(nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn hide(&mut self) {}
|
||||
fn set_cursor(&mut self, cursor: Option<MouseCursor>) {}
|
||||
fn invalidate(&mut self) {
|
||||
unsafe {
|
||||
let () = msg_send![*self.view, setNeedsDisplay: YES];
|
||||
}
|
||||
}
|
||||
fn set_title(&mut self, title: &str) {}
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
callbacks: Box<WindowCallbacks>,
|
||||
view_id: Option<WeakPtr>,
|
||||
window_id: usize,
|
||||
}
|
||||
|
||||
impl Drop for Inner {
|
||||
@ -314,8 +366,9 @@ impl WindowView {
|
||||
};
|
||||
|
||||
if let Some(myself) = Self::get_this(this) {
|
||||
eprintln!("{:?}", event);
|
||||
// myself.inner.borrow_mut().callbacks.mouse_event(&event, &window);
|
||||
let mut inner = myself.inner.borrow_mut();
|
||||
let window = Window(inner.window_id);
|
||||
inner.callbacks.mouse_event(&event, &window);
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,8 +417,9 @@ impl WindowView {
|
||||
};
|
||||
|
||||
if let Some(myself) = Self::get_this(this) {
|
||||
eprintln!("{:?}", event);
|
||||
// myself.inner.borrow_mut().callbacks.key_event(&event, &window);
|
||||
let mut inner = myself.inner.borrow_mut();
|
||||
let window = Window(inner.window_id);
|
||||
inner.callbacks.key_event(&event, &window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user