From 4ba64d8f86f2c68cd91a5ccb8118eba754852bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 23 Nov 2020 19:52:50 +0100 Subject: [PATCH 1/7] Add cross-platform Window wrapper, currently only macOS support --- src/lib.rs | 11 +++-------- src/macos/window.rs | 16 +++++++++------- src/window.rs | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 src/window.rs diff --git a/src/lib.rs b/src/lib.rs index 67ac9dd..47a95a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,26 +2,21 @@ use raw_window_handle::RawWindowHandle; #[cfg(target_os = "windows")] mod win; -#[cfg(target_os = "windows")] -pub use win::*; - #[cfg(target_os = "linux")] mod x11; -#[cfg(target_os = "linux")] -pub use crate::x11::*; - #[cfg(target_os = "macos")] mod macos; -#[cfg(target_os = "macos")] -pub use macos::*; mod event; mod keyboard; mod mouse_cursor; +mod window; mod window_info; mod window_open_options; + pub use event::*; pub use mouse_cursor::MouseCursor; +pub use window::*; pub use window_info::*; pub use window_open_options::*; diff --git a/src/macos/window.rs b/src/macos/window.rs index 7194eb8..755a390 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -58,12 +58,12 @@ impl WindowHandle { impl Window { pub fn open(options: WindowOpenOptions, build: B) -> WindowHandle where H: WindowHandler, - B: FnOnce(&mut Window) -> H, + B: FnOnce(&mut crate::window::Window) -> H, B: Send + 'static { let _pool = unsafe { NSAutoreleasePool::new(nil) }; - let mut window = match options.parent { + let window = match options.parent { Parent::WithParent(parent) => { if let RawWindowHandle::MacOS(handle) = parent { let ns_view = handle.ns_view as *mut objc::runtime::Object; @@ -155,10 +155,12 @@ impl Window { }, }; + let mut window = crate::window::Window(window); + let window_handler = build(&mut window); let window_state_arc = Arc::new(WindowState { - window, + window: window, window_handler, keyboard_state: KeyboardState::new(), }); @@ -168,7 +170,7 @@ impl Window { ) as *mut c_void; unsafe { - (*window_state_arc.window.ns_view).set_ivar( + (*window_state_arc.window.0.ns_view).set_ivar( WINDOW_STATE_IVAR_NAME, window_state_pointer ); @@ -183,13 +185,13 @@ impl Window { let timer: id = msg_send![ ::objc::class!(NSTimer), scheduledTimerWithTimeInterval:timer_interval - target:window_state_arc.window.ns_view + target:window_state_arc.window.0.ns_view selector:selector userInfo:nil repeats:YES ]; - (*window_state_arc.window.ns_view).set_ivar( + (*window_state_arc.window.0.ns_view).set_ivar( FRAME_TIMER_IVAR_NAME, timer as *mut c_void, ) @@ -201,7 +203,7 @@ impl Window { pub(super) struct WindowState { - window: Window, + window: crate::window::Window, window_handler: H, keyboard_state: KeyboardState, } diff --git a/src/window.rs b/src/window.rs new file mode 100644 index 0000000..3d67573 --- /dev/null +++ b/src/window.rs @@ -0,0 +1,36 @@ +use crate::WindowHandler; +use crate::window_open_options::WindowOpenOptions; + +#[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 WindowHandle(platform::WindowHandle); + + +impl WindowHandle { + pub fn app_run_blocking(self){ + self.0.app_run_blocking(); + } +} + + +pub struct Window(pub(crate) platform::Window); + + +impl Window { + pub fn open( + options: WindowOpenOptions, + build: B + ) -> WindowHandle + where H: WindowHandler, + B: FnOnce(&mut Window) -> H, + B: Send + 'static + { + WindowHandle(platform::Window::open::(options, build)) + } +} \ No newline at end of file From f9226c366eeae61dab0055781d8d26397f87444b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 23 Nov 2020 20:22:24 +0100 Subject: [PATCH 2/7] platform api unification: support Windows --- src/win/window.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/win/window.rs b/src/win/window.rs index ae952be..1c89bb9 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -72,7 +72,7 @@ unsafe extern "system" fn wnd_proc( let win_ptr = GetWindowLongPtrA(hwnd, GWLP_USERDATA) as *const c_void; if !win_ptr.is_null() { let window_state = &*(win_ptr as *const RefCell>); - let mut window = Window { hwnd }; + let mut window = crate::window::Window(Window { hwnd }); match msg { WM_MOUSEMOVE => { @@ -177,7 +177,7 @@ impl WindowHandle { impl Window { pub fn open(options: WindowOpenOptions, build: B) -> WindowHandle where H: WindowHandler, - B: FnOnce(&mut Window) -> H, + B: FnOnce(&mut crate::window::Window) -> H, B: Send + 'static { unsafe { @@ -240,7 +240,7 @@ impl Window { ); // todo: manage error ^ - let mut window = Window { hwnd }; + let mut window = crate::window::Window(Window { hwnd }); let handler = build(&mut window); From 185bd624473370e63eaf26f8f8c05e87ca750a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 23 Nov 2020 21:59:17 +0100 Subject: [PATCH 3/7] api unification: make cross-platform Window hold a reference --- src/macos/window.rs | 21 +++++++++++---------- src/win/window.rs | 7 +++---- src/window.rs | 4 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/macos/window.rs b/src/macos/window.rs index 755a390..8b993ab 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -63,7 +63,7 @@ impl Window { { let _pool = unsafe { NSAutoreleasePool::new(nil) }; - let window = match options.parent { + let mut window = match options.parent { Parent::WithParent(parent) => { if let RawWindowHandle::MacOS(handle) = parent { let ns_view = handle.ns_view as *mut objc::runtime::Object; @@ -155,12 +155,10 @@ impl Window { }, }; - let mut window = crate::window::Window(window); - - let window_handler = build(&mut window); + let window_handler = build(&mut crate::window::Window(&mut window)); let window_state_arc = Arc::new(WindowState { - window: window, + window, window_handler, keyboard_state: KeyboardState::new(), }); @@ -170,7 +168,7 @@ impl Window { ) as *mut c_void; unsafe { - (*window_state_arc.window.0.ns_view).set_ivar( + (*window_state_arc.window.ns_view).set_ivar( WINDOW_STATE_IVAR_NAME, window_state_pointer ); @@ -185,13 +183,13 @@ impl Window { let timer: id = msg_send![ ::objc::class!(NSTimer), scheduledTimerWithTimeInterval:timer_interval - target:window_state_arc.window.0.ns_view + target:window_state_arc.window.ns_view selector:selector userInfo:nil repeats:YES ]; - (*window_state_arc.window.0.ns_view).set_ivar( + (*window_state_arc.window.ns_view).set_ivar( FRAME_TIMER_IVAR_NAME, timer as *mut c_void, ) @@ -203,7 +201,7 @@ impl Window { pub(super) struct WindowState { - window: crate::window::Window, + window: Window, window_handler: H, keyboard_state: KeyboardState, } @@ -222,7 +220,10 @@ impl WindowState { } pub(super) fn trigger_event(&mut self, event: Event){ - self.window_handler.on_event(&mut self.window, event); + self.window_handler.on_event( + &mut crate::window::Window(&mut self.window), + event + ); } pub(super) fn trigger_frame(&mut self){ diff --git a/src/win/window.rs b/src/win/window.rs index 1c89bb9..60a8523 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -72,7 +72,8 @@ unsafe extern "system" fn wnd_proc( let win_ptr = GetWindowLongPtrA(hwnd, GWLP_USERDATA) as *const c_void; if !win_ptr.is_null() { let window_state = &*(win_ptr as *const RefCell>); - let mut window = crate::window::Window(Window { hwnd }); + let mut window = Window { hwnd }; + let mut window = crate::window::Window(&mut window); match msg { WM_MOUSEMOVE => { @@ -240,9 +241,7 @@ impl Window { ); // todo: manage error ^ - let mut window = crate::window::Window(Window { hwnd }); - - let handler = build(&mut window); + let handler = build(&mut crate::window::Window(&mut Window { hwnd })); let window_state = Box::new(RefCell::new(WindowState { window_class, diff --git a/src/window.rs b/src/window.rs index 3d67573..9d4c365 100644 --- a/src/window.rs +++ b/src/window.rs @@ -19,10 +19,10 @@ impl WindowHandle { } -pub struct Window(pub(crate) platform::Window); +pub struct Window<'a>(pub(crate) &'a mut platform::Window); -impl Window { +impl <'a>Window<'a> { pub fn open( options: WindowOpenOptions, build: B From 6450bff3685aaee39e8c28267bc55b0ee79a6db4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 23 Nov 2020 22:18:36 +0100 Subject: [PATCH 4/7] api unification: add Linux support --- src/x11/window.rs | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/x11/window.rs b/src/x11/window.rs index 9d3a5e5..2de1043 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -46,7 +46,7 @@ type WindowOpenResult = Result<(), ()>; impl Window { pub fn open(options: WindowOpenOptions, build: B) -> WindowHandle where H: WindowHandler, - B: FnOnce(&mut Window) -> H, + B: FnOnce(&mut crate::Window) -> H, B: Send + 'static { let (tx, rx) = mpsc::sync_channel::(1); @@ -66,7 +66,7 @@ impl Window { fn window_thread(options: WindowOpenOptions, build: B, tx: mpsc::SyncSender) -> WindowOpenResult where H: WindowHandler, - B: FnOnce(&mut Window) -> H, + B: FnOnce(&mut crate::Window) -> H, B: Send + 'static { // Connect to the X server @@ -173,7 +173,7 @@ impl Window { new_physical_size: None, }; - let mut handler = build(&mut window); + let mut handler = build(&mut crate::Window(&mut window)); let _ = tx.send(Ok(())); @@ -222,9 +222,12 @@ impl Window { self.window_info.scale() ); - handler.on_event(self, Event::Window( - WindowEvent::Resized(self.window_info) - )) + let window_info = self.window_info; + + handler.on_event( + &mut crate::Window(self), + Event::Window(WindowEvent::Resized(window_info)) + ) } } @@ -313,7 +316,10 @@ impl Window { .unwrap_or(xcb::NONE); if wm_delete_window == data32[0] { - handler.on_event(self, Event::Window(WindowEvent::WillClose)); + handler.on_event( + &mut crate::Window(self), + Event::Window(WindowEvent::WillClose) + ); // FIXME: handler should decide whether window stays open or not self.event_loop_running = false; @@ -342,7 +348,7 @@ impl Window { let logical_pos = physical_pos.to_logical(&self.window_info); handler.on_event( - self, + &mut crate::Window(self), Event::Mouse(MouseEvent::CursorMoved { position: logical_pos, }), @@ -357,7 +363,7 @@ impl Window { match detail { 4 => { handler.on_event( - self, + &mut crate::Window(self), Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines { x: 0.0, y: 1.0, @@ -366,7 +372,7 @@ impl Window { } 5 => { handler.on_event( - self, + &mut crate::Window(self), Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines { x: 0.0, y: -1.0, @@ -375,7 +381,10 @@ impl Window { } detail => { let button_id = mouse_id(detail); - handler.on_event(self, Event::Mouse(MouseEvent::ButtonPressed(button_id))); + handler.on_event( + &mut crate::Window(self), + Event::Mouse(MouseEvent::ButtonPressed(button_id)) + ); } } } @@ -386,7 +395,10 @@ impl Window { if detail != 4 && detail != 5 { let button_id = mouse_id(detail); - handler.on_event(self, Event::Mouse(MouseEvent::ButtonReleased(button_id))); + handler.on_event( + &mut crate::Window(self), + Event::Mouse(MouseEvent::ButtonReleased(button_id)) + ); } } @@ -397,7 +409,7 @@ impl Window { let event = unsafe { xcb::cast_event::(&event) }; handler.on_event( - self, + &mut crate::Window(self), Event::Keyboard(convert_key_press_event(&event)) ); } @@ -406,7 +418,7 @@ impl Window { let event = unsafe { xcb::cast_event::(&event) }; handler.on_event( - self, + &mut crate::Window(self), Event::Keyboard(convert_key_release_event(&event)) ); } From a8c7c707d274b6e8defb96f57b39d2f7f49b7a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 23 Nov 2020 22:26:27 +0100 Subject: [PATCH 5/7] unify platforms: simplify imports --- src/macos/window.rs | 6 +++--- src/win/window.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/macos/window.rs b/src/macos/window.rs index 8b993ab..aa3cc48 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -58,7 +58,7 @@ impl WindowHandle { impl Window { pub fn open(options: WindowOpenOptions, build: B) -> WindowHandle where H: WindowHandler, - B: FnOnce(&mut crate::window::Window) -> H, + B: FnOnce(&mut crate::Window) -> H, B: Send + 'static { let _pool = unsafe { NSAutoreleasePool::new(nil) }; @@ -155,7 +155,7 @@ impl Window { }, }; - let window_handler = build(&mut crate::window::Window(&mut window)); + let window_handler = build(&mut crate::Window(&mut window)); let window_state_arc = Arc::new(WindowState { window, @@ -221,7 +221,7 @@ impl WindowState { pub(super) fn trigger_event(&mut self, event: Event){ self.window_handler.on_event( - &mut crate::window::Window(&mut self.window), + &mut crate::Window(&mut self.window), event ); } diff --git a/src/win/window.rs b/src/win/window.rs index 60a8523..b5e22ca 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -73,7 +73,7 @@ unsafe extern "system" fn wnd_proc( if !win_ptr.is_null() { let window_state = &*(win_ptr as *const RefCell>); let mut window = Window { hwnd }; - let mut window = crate::window::Window(&mut window); + let mut window = crate::Window(&mut window); match msg { WM_MOUSEMOVE => { @@ -178,7 +178,7 @@ impl WindowHandle { impl Window { pub fn open(options: WindowOpenOptions, build: B) -> WindowHandle where H: WindowHandler, - B: FnOnce(&mut crate::window::Window) -> H, + B: FnOnce(&mut crate::Window) -> H, B: Send + 'static { unsafe { @@ -241,7 +241,7 @@ impl Window { ); // todo: manage error ^ - let handler = build(&mut crate::window::Window(&mut Window { hwnd })); + let handler = build(&mut crate::Window(&mut Window { hwnd })); let window_state = Box::new(RefCell::new(WindowState { window_class, From 1ddd6fa47e1332ada4c4a79274150c3a8d5e2901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Tue, 24 Nov 2020 20:41:55 +0100 Subject: [PATCH 6/7] api unification: return shared WindowHandle in platform code --- src/macos/window.rs | 7 +++++-- src/win/window.rs | 7 +++++-- src/window.rs | 6 +++--- src/x11/window.rs | 7 +++++-- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/macos/window.rs b/src/macos/window.rs index aa3cc48..78295fd 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -56,7 +56,10 @@ impl WindowHandle { } impl Window { - pub fn open(options: WindowOpenOptions, build: B) -> WindowHandle + pub fn open( + options: WindowOpenOptions, + build: B + ) -> crate::WindowHandle where H: WindowHandler, B: FnOnce(&mut crate::Window) -> H, B: Send + 'static @@ -195,7 +198,7 @@ impl Window { ) } - WindowHandle + crate::WindowHandle(WindowHandle) } } diff --git a/src/win/window.rs b/src/win/window.rs index b5e22ca..75d84ec 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -176,7 +176,10 @@ impl WindowHandle { } impl Window { - pub fn open(options: WindowOpenOptions, build: B) -> WindowHandle + pub fn open( + options: WindowOpenOptions, + build: B + ) -> crate::WindowHandle where H: WindowHandler, B: FnOnce(&mut crate::Window) -> H, B: Send + 'static @@ -252,7 +255,7 @@ impl Window { SetWindowLongPtrA(hwnd, GWLP_USERDATA, Box::into_raw(window_state) as *const _ as _); SetTimer(hwnd, 4242, 13, None); - WindowHandle { hwnd } + crate::WindowHandle(WindowHandle { hwnd }) } } } diff --git a/src/window.rs b/src/window.rs index 9d4c365..0327e16 100644 --- a/src/window.rs +++ b/src/window.rs @@ -9,7 +9,7 @@ use crate::x11 as platform; use crate::macos as platform; -pub struct WindowHandle(platform::WindowHandle); +pub struct WindowHandle(pub(crate) platform::WindowHandle); impl WindowHandle { @@ -31,6 +31,6 @@ impl <'a>Window<'a> { B: FnOnce(&mut Window) -> H, B: Send + 'static { - WindowHandle(platform::Window::open::(options, build)) + platform::Window::open::(options, build) } -} \ No newline at end of file +} diff --git a/src/x11/window.rs b/src/x11/window.rs index 2de1043..946f240 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -44,7 +44,10 @@ impl WindowHandle { type WindowOpenResult = Result<(), ()>; impl Window { - pub fn open(options: WindowOpenOptions, build: B) -> WindowHandle + pub fn open( + options: WindowOpenOptions, + build: B + ) -> crate::WindowHandle where H: WindowHandler, B: FnOnce(&mut crate::Window) -> H, B: Send + 'static @@ -60,7 +63,7 @@ impl Window { // FIXME: placeholder types for returning errors in the future let _ = rx.recv(); - WindowHandle { thread } + crate::WindowHandle(WindowHandle { thread }) } fn window_thread(options: WindowOpenOptions, build: B, From dd87afefd943368b1bb5f04b78c75b578c2055df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Fri, 27 Nov 2020 00:34:09 +0100 Subject: [PATCH 7/7] api unification: impl HasRawWindowHandle on wrapper Window --- src/window.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/window.rs b/src/window.rs index 0327e16..93f3aa2 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,3 +1,5 @@ +use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; + use crate::WindowHandler; use crate::window_open_options::WindowOpenOptions; @@ -34,3 +36,10 @@ impl <'a>Window<'a> { platform::Window::open::(options, build) } } + + +unsafe impl <'a>HasRawWindowHandle for Window<'a> { + fn raw_window_handle(&self) -> RawWindowHandle { + self.0.raw_window_handle() + } +} \ No newline at end of file