separate Window::open() into three functions (parented, as_if_parented, and blocking)
This commit is contained in:
parent
86bf222601
commit
36e4474c8a
|
@ -34,16 +34,10 @@ fn main() {
|
|||
title: "baseview".into(),
|
||||
size: baseview::Size::new(512.0, 512.0),
|
||||
scale: WindowScalePolicy::SystemScaleFactor,
|
||||
parent: baseview::Parent::None,
|
||||
};
|
||||
|
||||
let (mut tx, rx) = RingBuffer::new(128).split();
|
||||
|
||||
let opt_app_runner = Window::open(
|
||||
window_open_options,
|
||||
|_| OpenWindowExample { rx }
|
||||
);
|
||||
|
||||
::std::thread::spawn(move || {
|
||||
loop {
|
||||
::std::thread::sleep(Duration::from_secs(5));
|
||||
|
@ -54,5 +48,8 @@ fn main() {
|
|||
}
|
||||
});
|
||||
|
||||
opt_app_runner.unwrap().app_run_blocking();
|
||||
Window::open_blocking(
|
||||
window_open_options,
|
||||
|_| OpenWindowExample { rx }
|
||||
);
|
||||
}
|
||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -1,5 +1,3 @@
|
|||
use raw_window_handle::RawWindowHandle;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
mod win;
|
||||
#[cfg(target_os = "linux")]
|
||||
|
@ -19,17 +17,3 @@ pub use mouse_cursor::MouseCursor;
|
|||
pub use window::*;
|
||||
pub use window_info::*;
|
||||
pub use window_open_options::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Parent {
|
||||
None,
|
||||
AsIfParented,
|
||||
WithParent(RawWindowHandle),
|
||||
}
|
||||
|
||||
unsafe impl Send for Parent {}
|
||||
|
||||
pub trait WindowHandler {
|
||||
fn on_frame(&mut self);
|
||||
fn on_event(&mut self, window: &mut Window, event: Event);
|
||||
}
|
||||
|
|
|
@ -17,27 +17,13 @@ use objc::{msg_send, runtime::Object, sel, sel_impl};
|
|||
use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle};
|
||||
|
||||
use crate::{
|
||||
Event, Parent, WindowHandler, WindowOpenOptions,
|
||||
WindowScalePolicy, WindowInfo
|
||||
Event, WindowHandler, WindowOpenOptions, WindowScalePolicy, WindowInfo,
|
||||
};
|
||||
|
||||
use super::view::{create_view, BASEVIEW_STATE_IVAR};
|
||||
use super::keyboard::KeyboardState;
|
||||
|
||||
|
||||
pub struct AppRunner;
|
||||
|
||||
impl AppRunner {
|
||||
pub fn app_run_blocking(self) {
|
||||
unsafe {
|
||||
// Get reference to already created shared NSApplication object
|
||||
// and run the main loop
|
||||
NSApp().run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct Window {
|
||||
/// Only set if we created the parent window, i.e. we are running in
|
||||
/// parentless mode
|
||||
|
@ -47,104 +33,149 @@ pub struct Window {
|
|||
}
|
||||
|
||||
impl Window {
|
||||
pub fn open<H, B>(
|
||||
options: WindowOpenOptions,
|
||||
build: B
|
||||
) -> Option<crate::AppRunner>
|
||||
where H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static
|
||||
pub fn open_parented<P, H, B>(parent: &P, options: WindowOpenOptions, build: B)
|
||||
where
|
||||
P: HasRawWindowHandle,
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
let _pool = unsafe { NSAutoreleasePool::new(nil) };
|
||||
|
||||
let mut window = unsafe {
|
||||
Window {
|
||||
ns_window: None,
|
||||
ns_view: create_view(&options),
|
||||
}
|
||||
let handle = if let RawWindowHandle::MacOS(handle) = parent.raw_window_handle() {
|
||||
handle
|
||||
} else {
|
||||
panic!("Not a macOS window");
|
||||
};
|
||||
|
||||
let ns_view = unsafe { create_view(&options) };
|
||||
|
||||
let window = Window {
|
||||
ns_window: None,
|
||||
ns_view,
|
||||
};
|
||||
|
||||
Self::init(window, build);
|
||||
|
||||
unsafe {
|
||||
let _: id = msg_send![handle.ns_view as *mut Object, addSubview: ns_view];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_as_if_parented<H, B>(options: WindowOpenOptions, build: B) -> RawWindowHandle
|
||||
where
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
let _pool = unsafe { NSAutoreleasePool::new(nil) };
|
||||
|
||||
let ns_view = unsafe { create_view(&options) };
|
||||
|
||||
let window = Window {
|
||||
ns_window: None,
|
||||
ns_view,
|
||||
};
|
||||
|
||||
let raw_window_handle = window.raw_window_handle();
|
||||
|
||||
Self::init(window, build);
|
||||
|
||||
raw_window_handle
|
||||
}
|
||||
|
||||
pub fn open_blocking<H, B>(options: WindowOpenOptions, build: B)
|
||||
where
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
let _pool = unsafe { NSAutoreleasePool::new(nil) };
|
||||
|
||||
// It seems prudent to run NSApp() here before doing other
|
||||
// work. It runs [NSApplication sharedApplication], which is
|
||||
// what is run at the very start of the Xcode-generated main
|
||||
// function of a cocoa app according to:
|
||||
// https://developer.apple.com/documentation/appkit/nsapplication
|
||||
let app = unsafe { NSApp() };
|
||||
|
||||
unsafe {
|
||||
app.setActivationPolicy_(
|
||||
NSApplicationActivationPolicyRegular
|
||||
);
|
||||
}
|
||||
|
||||
let scaling = match options.scale {
|
||||
WindowScalePolicy::ScaleFactor(scale) => scale,
|
||||
WindowScalePolicy::SystemScaleFactor => 1.0,
|
||||
};
|
||||
|
||||
let window_info = WindowInfo::from_logical_size(
|
||||
options.size,
|
||||
scaling
|
||||
);
|
||||
|
||||
let rect = NSRect::new(
|
||||
NSPoint::new(0.0, 0.0),
|
||||
NSSize::new(
|
||||
window_info.logical_size().width as f64,
|
||||
window_info.logical_size().height as f64
|
||||
),
|
||||
);
|
||||
|
||||
let ns_window = unsafe {
|
||||
let ns_window = NSWindow::alloc(nil)
|
||||
.initWithContentRect_styleMask_backing_defer_(
|
||||
rect,
|
||||
NSWindowStyleMask::NSTitledWindowMask,
|
||||
NSBackingStoreBuffered,
|
||||
NO,
|
||||
)
|
||||
.autorelease();
|
||||
ns_window.center();
|
||||
|
||||
let title = NSString::alloc(nil)
|
||||
.init_str(&options.title)
|
||||
.autorelease();
|
||||
ns_window.setTitle_(title);
|
||||
|
||||
ns_window.makeKeyAndOrderFront_(nil);
|
||||
|
||||
ns_window
|
||||
};
|
||||
|
||||
let ns_view = unsafe { create_view(&options) };
|
||||
|
||||
let window = Window {
|
||||
ns_window: Some(ns_window),
|
||||
ns_view,
|
||||
};
|
||||
|
||||
Self::init(window, build);
|
||||
|
||||
unsafe {
|
||||
ns_window.setContentView_(ns_view);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
app.run();
|
||||
}
|
||||
}
|
||||
|
||||
fn init<H, B>(
|
||||
mut window: Window,
|
||||
build: B
|
||||
)
|
||||
where H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
let window_handler = Box::new(build(&mut crate::Window::new(&mut window)));
|
||||
|
||||
let retain_count_after_build: usize = unsafe {
|
||||
msg_send![window.ns_view, retainCount]
|
||||
};
|
||||
|
||||
let opt_app_runner = match options.parent {
|
||||
Parent::WithParent(RawWindowHandle::MacOS(handle)) => {
|
||||
unsafe {
|
||||
let () = msg_send![
|
||||
handle.ns_view as *mut Object,
|
||||
addSubview: window.ns_view
|
||||
];
|
||||
}
|
||||
|
||||
None
|
||||
},
|
||||
Parent::WithParent(_) => {
|
||||
panic!("Not a macOS window");
|
||||
},
|
||||
Parent::AsIfParented => {
|
||||
None
|
||||
},
|
||||
Parent::None => {
|
||||
// It seems prudent to run NSApp() here before doing other
|
||||
// work. It runs [NSApplication sharedApplication], which is
|
||||
// what is run at the very start of the Xcode-generated main
|
||||
// function of a cocoa app according to:
|
||||
// https://developer.apple.com/documentation/appkit/nsapplication
|
||||
unsafe {
|
||||
let app = NSApp();
|
||||
app.setActivationPolicy_(
|
||||
NSApplicationActivationPolicyRegular
|
||||
);
|
||||
}
|
||||
|
||||
let scaling = match options.scale {
|
||||
WindowScalePolicy::ScaleFactor(scale) => scale,
|
||||
WindowScalePolicy::SystemScaleFactor => 1.0,
|
||||
};
|
||||
|
||||
let window_info = WindowInfo::from_logical_size(
|
||||
options.size,
|
||||
scaling
|
||||
);
|
||||
|
||||
let rect = NSRect::new(
|
||||
NSPoint::new(0.0, 0.0),
|
||||
NSSize::new(
|
||||
window_info.logical_size().width as f64,
|
||||
window_info.logical_size().height as f64
|
||||
),
|
||||
);
|
||||
|
||||
unsafe {
|
||||
let ns_window = NSWindow::alloc(nil)
|
||||
.initWithContentRect_styleMask_backing_defer_(
|
||||
rect,
|
||||
NSWindowStyleMask::NSTitledWindowMask,
|
||||
NSBackingStoreBuffered,
|
||||
NO,
|
||||
)
|
||||
.autorelease();
|
||||
ns_window.center();
|
||||
|
||||
let title = NSString::alloc(nil)
|
||||
.init_str(&options.title)
|
||||
.autorelease();
|
||||
ns_window.setTitle_(title);
|
||||
|
||||
ns_window.makeKeyAndOrderFront_(nil);
|
||||
|
||||
ns_window.setContentView_(window.ns_view);
|
||||
|
||||
window.ns_window = Some(ns_window);
|
||||
|
||||
Some(crate::AppRunner(AppRunner))
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let window_state_ptr = Box::into_raw(Box::new(WindowState {
|
||||
window,
|
||||
window_handler,
|
||||
|
@ -161,8 +192,6 @@ impl Window {
|
|||
|
||||
WindowState::setup_timer(window_state_ptr);
|
||||
}
|
||||
|
||||
opt_app_runner
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ use raw_window_handle::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
Event, MouseButton, MouseEvent, Parent::WithParent, WindowEvent,
|
||||
Event, MouseButton, MouseEvent, WindowEvent,
|
||||
WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy, PhyPoint,
|
||||
};
|
||||
|
||||
|
@ -225,17 +225,49 @@ pub struct Window {
|
|||
hwnd: HWND,
|
||||
}
|
||||
|
||||
pub struct AppRunner {
|
||||
hwnd: HWND,
|
||||
}
|
||||
impl Window {
|
||||
pub fn open_parented<P, H, B>(parent: &P, options: WindowOpenOptions, build: B)
|
||||
where
|
||||
P: HasRawWindowHandle,
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
let parent = match parent.raw_window_handle() {
|
||||
RawWindowHandle::Windows(h) => h.hwnd as HWND,
|
||||
h => panic!("unsupported parent handle {:?}", h),
|
||||
};
|
||||
|
||||
Self::open(true, parent, options, build);
|
||||
}
|
||||
|
||||
pub fn open_as_if_parented<H, B>(options: WindowOpenOptions, build: B) -> RawWindowHandle
|
||||
where
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
let hwnd = Self::open(true, null_mut(), options, build);
|
||||
|
||||
RawWindowHandle::Windows(WindowsHandle {
|
||||
hwnd: hwnd as *mut std::ffi::c_void,
|
||||
..WindowsHandle::empty()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn open_blocking<H, B>(options: WindowOpenOptions, build: B)
|
||||
where
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
let hwnd = Self::open(false, null_mut(), options, build);
|
||||
|
||||
impl AppRunner {
|
||||
pub fn app_run_blocking(self) {
|
||||
unsafe {
|
||||
let mut msg: MSG = std::mem::zeroed();
|
||||
|
||||
loop {
|
||||
let status = GetMessageW(&mut msg, self.hwnd, 0, 0);
|
||||
let status = GetMessageW(&mut msg, hwnd, 0, 0);
|
||||
|
||||
if status == -1 {
|
||||
break;
|
||||
|
@ -246,16 +278,16 @@ impl AppRunner {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn open<H, B>(
|
||||
fn open<H, B>(
|
||||
parented: bool,
|
||||
parent: HWND,
|
||||
options: WindowOpenOptions,
|
||||
build: B
|
||||
) -> Option<crate::AppRunner>
|
||||
where H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static
|
||||
) -> HWND
|
||||
where H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
unsafe {
|
||||
let mut title: Vec<u16> = OsStr::new(&options.title[..])
|
||||
|
@ -265,14 +297,6 @@ impl Window {
|
|||
|
||||
let window_class = register_wnd_class();
|
||||
// todo: manage error ^
|
||||
|
||||
let mut flags = WS_POPUPWINDOW
|
||||
| WS_CAPTION
|
||||
| WS_VISIBLE
|
||||
| WS_SIZEBOX
|
||||
| WS_MINIMIZEBOX
|
||||
| WS_MAXIMIZEBOX
|
||||
| WS_CLIPSIBLINGS;
|
||||
|
||||
let scaling = match options.scale {
|
||||
WindowScalePolicy::SystemScaleFactor => get_scaling().unwrap_or(1.0),
|
||||
|
@ -289,21 +313,22 @@ impl Window {
|
|||
bottom: window_info.physical_size().height as i32,
|
||||
};
|
||||
|
||||
// todo: add check flags https://github.com/wrl/rutabaga/blob/f30ff67e157375cafdbafe5fb549f1790443a3a8/src/platform/win/window.c#L351
|
||||
let parent = match options.parent {
|
||||
WithParent(RawWindowHandle::Windows(h)) => {
|
||||
flags = WS_CHILD | WS_VISIBLE;
|
||||
h.hwnd
|
||||
}
|
||||
|
||||
WithParent(h) => panic!("unsupported parent handle {:?}", h),
|
||||
|
||||
_ => {
|
||||
AdjustWindowRectEx(&mut rect, flags, FALSE, 0);
|
||||
null_mut()
|
||||
}
|
||||
let flags = if parented {
|
||||
WS_CHILD | WS_VISIBLE
|
||||
} else {
|
||||
WS_POPUPWINDOW
|
||||
| WS_CAPTION
|
||||
| WS_VISIBLE
|
||||
| WS_SIZEBOX
|
||||
| WS_MINIMIZEBOX
|
||||
| WS_MAXIMIZEBOX
|
||||
| WS_CLIPSIBLINGS
|
||||
};
|
||||
|
||||
if !parented {
|
||||
AdjustWindowRectEx(&mut rect, flags, FALSE, 0);
|
||||
}
|
||||
|
||||
let hwnd = CreateWindowExW(
|
||||
0,
|
||||
window_class as _,
|
||||
|
@ -333,11 +358,7 @@ impl Window {
|
|||
SetWindowLongPtrW(hwnd, GWLP_USERDATA, Box::into_raw(window_state) as *const _ as _);
|
||||
SetTimer(hwnd, WIN_FRAME_TIMER, 15, None);
|
||||
|
||||
if let crate::Parent::None = options.parent {
|
||||
Some(crate::AppRunner(AppRunner { hwnd }))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
hwnd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,22 +2,19 @@ use std::marker::PhantomData;
|
|||
|
||||
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
|
||||
|
||||
use crate::WindowHandler;
|
||||
use crate::event::Event;
|
||||
use crate::window_open_options::WindowOpenOptions;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use crate::macos as platform;
|
||||
#[cfg(target_os = "windows")]
|
||||
use crate::win as platform;
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::x11 as platform;
|
||||
#[cfg(target_os = "macos")]
|
||||
use crate::macos as platform;
|
||||
|
||||
pub struct AppRunner(pub(crate) platform::AppRunner);
|
||||
|
||||
impl AppRunner {
|
||||
pub fn app_run_blocking(self){
|
||||
self.0.app_run_blocking();
|
||||
}
|
||||
pub trait WindowHandler {
|
||||
fn on_frame(&mut self);
|
||||
fn on_event(&mut self, window: &mut Window, event: Event);
|
||||
}
|
||||
|
||||
pub struct Window<'a> {
|
||||
|
@ -34,15 +31,32 @@ impl<'a> Window<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn open<H, B>(
|
||||
options: WindowOpenOptions,
|
||||
build: B
|
||||
) -> Option<AppRunner>
|
||||
where H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut Window) -> H,
|
||||
B: Send + 'static
|
||||
pub fn open_parented<P, H, B>(parent: &P, options: WindowOpenOptions, build: B)
|
||||
where
|
||||
P: HasRawWindowHandle,
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
platform::Window::open::<H, B>(options, build)
|
||||
platform::Window::open_parented::<P, H, B>(parent, options, build)
|
||||
}
|
||||
|
||||
pub fn open_as_if_parented<H, B>(options: WindowOpenOptions, build: B) -> RawWindowHandle
|
||||
where
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
platform::Window::open_as_if_parented::<H, B>(options, build)
|
||||
}
|
||||
|
||||
pub fn open_blocking<H, B>(options: WindowOpenOptions, build: B)
|
||||
where
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
platform::Window::open_blocking::<H, B>(options, build)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{Parent, Size};
|
||||
use crate::Size;
|
||||
|
||||
/// The dpi scaling policy of the window
|
||||
#[derive(Debug)]
|
||||
|
@ -10,7 +10,6 @@ pub enum WindowScalePolicy {
|
|||
}
|
||||
|
||||
/// The options for opening a new window
|
||||
#[derive(Debug)]
|
||||
pub struct WindowOpenOptions {
|
||||
pub title: String,
|
||||
|
||||
|
@ -22,6 +21,4 @@ pub struct WindowOpenOptions {
|
|||
|
||||
/// The dpi scaling policy
|
||||
pub scale: WindowScalePolicy,
|
||||
|
||||
pub parent: Parent,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use raw_window_handle::{
|
|||
|
||||
use super::XcbConnection;
|
||||
use crate::{
|
||||
Event, MouseButton, MouseCursor, MouseEvent, Parent, ScrollDelta,
|
||||
Event, MouseButton, MouseCursor, MouseEvent, ScrollDelta,
|
||||
WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions,
|
||||
WindowScalePolicy, PhyPoint, PhySize,
|
||||
};
|
||||
|
@ -30,57 +30,77 @@ pub struct Window {
|
|||
new_physical_size: Option<PhySize>,
|
||||
}
|
||||
|
||||
pub struct WindowHandle;
|
||||
// Hack to allow sending a RawWindowHandle between threads. Do not make public
|
||||
struct SendableRwh(RawWindowHandle);
|
||||
|
||||
unsafe impl Send for SendableRwh {}
|
||||
|
||||
pub struct AppRunner {
|
||||
thread: std::thread::JoinHandle<()>,
|
||||
}
|
||||
|
||||
impl AppRunner {
|
||||
pub fn app_run_blocking(self) {
|
||||
let _ = self.thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
type WindowOpenResult = Result<(), ()>;
|
||||
type WindowOpenResult = Result<SendableRwh, ()>;
|
||||
|
||||
impl Window {
|
||||
pub fn open<H, B>(
|
||||
options: WindowOpenOptions,
|
||||
build: B
|
||||
) -> Option<crate::AppRunner>
|
||||
where H: WindowHandler,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static
|
||||
pub fn open_parented<P, H, B>(parent: &P, options: WindowOpenOptions, build: B)
|
||||
where
|
||||
P: HasRawWindowHandle,
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
let is_not_parented = matches!(options.parent, Parent::None);
|
||||
// Convert parent into something that X understands
|
||||
let parent_id = match parent.raw_window_handle() {
|
||||
RawWindowHandle::Xlib(h) => h.window as u32,
|
||||
RawWindowHandle::Xcb(h) => h.window,
|
||||
h => panic!("unsupported parent handle type {:?}", h),
|
||||
};
|
||||
|
||||
let (tx, rx) = mpsc::sync_channel::<WindowOpenResult>(1);
|
||||
|
||||
let thread = thread::spawn(move || {
|
||||
if let Err(e) = Self::window_thread::<H, B>(options, build, tx.clone()) {
|
||||
let _ = tx.send(Err(e));
|
||||
}
|
||||
Self::window_thread(Some(parent_id), options, build, tx.clone());
|
||||
});
|
||||
|
||||
// FIXME: placeholder types for returning errors in the future
|
||||
let _ = rx.recv();
|
||||
let _ = rx.recv().unwrap().unwrap();
|
||||
}
|
||||
|
||||
if is_not_parented {
|
||||
Some(crate::AppRunner(AppRunner { thread }))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
pub fn open_as_if_parented<H, B>(options: WindowOpenOptions, build: B) -> RawWindowHandle
|
||||
where
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
let (tx, rx) = mpsc::sync_channel::<WindowOpenResult>(1);
|
||||
|
||||
let thread = thread::spawn(move || {
|
||||
Self::window_thread(None, options, build, tx.clone());
|
||||
});
|
||||
|
||||
rx.recv().unwrap().unwrap().0
|
||||
}
|
||||
|
||||
pub fn open_blocking<H, B>(options: WindowOpenOptions, build: B)
|
||||
where
|
||||
H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
let (tx, rx) = mpsc::sync_channel::<WindowOpenResult>(1);
|
||||
|
||||
let thread = thread::spawn(move || {
|
||||
Self::window_thread(None, options, build, tx.clone());
|
||||
});
|
||||
|
||||
let _ = rx.recv().unwrap().unwrap();
|
||||
|
||||
thread.join();
|
||||
}
|
||||
|
||||
fn window_thread<H, B>(
|
||||
parent: Option<u32>,
|
||||
options: WindowOpenOptions, build: B,
|
||||
tx: mpsc::SyncSender<WindowOpenResult>,
|
||||
) -> WindowOpenResult
|
||||
where H: WindowHandler,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static
|
||||
)
|
||||
where H: WindowHandler + 'static,
|
||||
B: FnOnce(&mut crate::Window) -> H,
|
||||
B: Send + 'static,
|
||||
{
|
||||
// Connect to the X server
|
||||
// FIXME: baseview error type instead of unwrap()
|
||||
|
@ -95,15 +115,7 @@ impl Window {
|
|||
|
||||
let foreground = xcb_connection.conn.generate_id();
|
||||
|
||||
// Convert parent into something that X understands
|
||||
let parent_id = match options.parent {
|
||||
Parent::WithParent(RawWindowHandle::Xlib(h)) => h.window as u32,
|
||||
Parent::WithParent(RawWindowHandle::Xcb(h)) => h.window,
|
||||
Parent::WithParent(h) =>
|
||||
panic!("unsupported parent handle type {:?}", h),
|
||||
|
||||
Parent::None | Parent::AsIfParented => screen.root(),
|
||||
};
|
||||
let parent_id = parent.unwrap_or_else(|| screen.root());
|
||||
|
||||
xcb::create_gc(
|
||||
&xcb_connection.conn,
|
||||
|
@ -188,10 +200,9 @@ impl Window {
|
|||
|
||||
let mut handler = build(&mut crate::Window::new(&mut window));
|
||||
|
||||
let _ = tx.send(Ok(()));
|
||||
let _ = tx.send(Ok(SendableRwh(window.raw_window_handle())));
|
||||
|
||||
window.run_event_loop(&mut handler);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn window_info(&self) -> &WindowInfo {
|
||||
|
|
Loading…
Reference in a new issue