From 58ed00eb11fc44508f3278f98661f0d3d547f8e8 Mon Sep 17 00:00:00 2001 From: Micah Johnston Date: Mon, 7 Sep 2020 02:37:16 -0500 Subject: [PATCH 1/7] api change: AppWindow methods receive an &mut Window, which implements HasRawWindowHandle --- examples/open_window.rs | 14 +++++++------- src/lib.rs | 20 ++++---------------- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/examples/open_window.rs b/examples/open_window.rs index 8b344b5..49cff6f 100644 --- a/examples/open_window.rs +++ b/examples/open_window.rs @@ -1,6 +1,6 @@ use std::sync::mpsc; -use baseview::Event; +use baseview::{Event, Window}; fn main() { let window_open_options = baseview::WindowOpenOptions { @@ -14,21 +14,21 @@ fn main() { // Send _app_message_tx to a separate thread, then send messages to the GUI thread. - let _ = baseview::Window::::open(window_open_options, app_message_rx); + let _ = Window::open::(window_open_options, app_message_rx); } + struct MyProgram {} impl baseview::AppWindow for MyProgram { type AppMessage = (); - fn build(_window_handle: baseview::RawWindow, window_info: &baseview::WindowInfo) -> Self { - println!("Window info: {:?}", window_info); + fn build(window: &mut Window) -> Self { Self {} } - fn draw(&mut self) {} + fn draw(&mut self, window: &mut Window) {} - fn on_event(&mut self, event: Event) { + fn on_event(&mut self, window: &mut Window, event: Event) { match event { Event::CursorMotion(x, y) => { println!("Cursor moved, x: {}, y: {}", x, y); @@ -69,5 +69,5 @@ impl baseview::AppWindow for MyProgram { } } - fn on_app_message(&mut self, _message: Self::AppMessage) {} + fn on_app_message(&mut self, window: &mut Window, _message: Self::AppMessage) {} } diff --git a/src/lib.rs b/src/lib.rs index 406bb91..a962ba4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,21 +36,9 @@ pub struct WindowOpenOptions<'a> { pub trait AppWindow { type AppMessage; - fn build(window_handle: RawWindow, window_info: &WindowInfo) -> Self; + fn build(window: &mut Window) -> Self; - fn draw(&mut self); - fn on_event(&mut self, event: Event); - fn on_app_message(&mut self, message: Self::AppMessage); -} - -/// A wrapper for a `RawWindowHandle`. Some context creators expect an `&impl HasRawWindowHandle`. -#[derive(Debug, Copy, Clone)] -pub struct RawWindow { - pub raw_window_handle: raw_window_handle::RawWindowHandle, -} - -unsafe impl raw_window_handle::HasRawWindowHandle for RawWindow { - fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle { - self.raw_window_handle - } + fn draw(&mut self, window: &mut Window); + fn on_event(&mut self, window: &mut Window, event: Event); + fn on_app_message(&mut self, window: &mut Window, message: Self::AppMessage); } From e78598954f579b1fda951c2ce7489e5254c0c7c4 Mon Sep 17 00:00:00 2001 From: Micah Johnston Date: Mon, 7 Sep 2020 02:37:52 -0500 Subject: [PATCH 2/7] adapt windows backend to new api --- src/win/window.rs | 92 +++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/win/window.rs b/src/win/window.rs index 0489760..89ad38b 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -6,18 +6,20 @@ use winapi::um::winuser::{ AdjustWindowRectEx, CreateWindowExA, DefWindowProcA, DestroyWindow, DispatchMessageA, GetMessageA, GetWindowLongPtrA, MessageBoxA, PostMessageA, RegisterClassA, SetTimer, SetWindowLongPtrA, TranslateMessage, UnregisterClassA, CS_OWNDC, GWLP_USERDATA, MB_ICONERROR, - MB_OK, MB_TOPMOST, MSG, WM_CREATE, WM_MOUSEMOVE, WM_PAINT, WM_SHOWWINDOW, WM_TIMER, WNDCLASSA, - WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, - WS_SIZEBOX, WS_VISIBLE, + MB_OK, MB_TOPMOST, MSG, WM_CLOSE, WM_CREATE, WM_MOUSEMOVE, WM_PAINT, WM_SHOWWINDOW, WM_TIMER, + WNDCLASSA, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, + WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, }; +use std::cell::RefCell; use std::ffi::c_void; use std::ptr::null_mut; -use std::sync::mpsc; use std::rc::Rc; -use std::cell::RefCell; +use std::sync::mpsc; -use crate::{AppWindow, Event, Parent::WithParent, RawWindow, WindowInfo, WindowOpenOptions}; +use raw_window_handle::{windows::WindowsHandle, HasRawWindowHandle, RawWindowHandle}; + +use crate::{AppWindow, Event, Parent::WithParent, WindowInfo, WindowOpenOptions}; unsafe fn message_box(title: &str, msg: &str) { let title = (title.to_owned() + "\0").as_ptr() as *const i8; @@ -46,7 +48,7 @@ unsafe fn generate_guid() -> String { const WIN_FRAME_TIMER: usize = 4242; -unsafe fn handle_timer(win: &RefCell>, timer_id: usize) { +unsafe fn handle_timer(window_state: &RefCell>, timer_id: usize) { match timer_id { WIN_FRAME_TIMER => {} _ => (), @@ -66,22 +68,33 @@ unsafe extern "system" fn wnd_proc( let win_ptr = GetWindowLongPtrA(hwnd, GWLP_USERDATA) as *const c_void; if !win_ptr.is_null() { - let win = &*(win_ptr as *const RefCell>); + let window_state = &*(win_ptr as *const RefCell>); + let mut window = Window { hwnd }; match msg { WM_MOUSEMOVE => { let x = (lparam & 0xFFFF) as i32; let y = ((lparam >> 16) & 0xFFFF) as i32; - win.borrow_mut().handle_mouse_motion(x, y); + window_state + .borrow_mut() + .app_window + .on_event(&mut window, Event::CursorMotion(x, y)); return 0; } WM_TIMER => { - handle_timer(&win, wparam); + handle_timer(&window_state, wparam); return 0; } WM_PAINT => { return 0; } + WM_CLOSE => { + window_state + .borrow_mut() + .app_window + .on_event(&mut window, Event::WillClose); + return DefWindowProcA(hwnd, msg, wparam, lparam); + } _ => {} } } @@ -113,16 +126,21 @@ unsafe fn unregister_wnd_class(wnd_class: ATOM) { UnregisterClassA(wnd_class as _, null_mut()); } -pub struct Window { - pub(crate) hwnd: HWND, +struct WindowState { window_class: ATOM, - app_window: A, - app_message_rx: mpsc::Receiver, scaling: Option, // DPI scale, 96.0 is "default". + app_window: A, } -impl Window { - pub fn open(options: WindowOpenOptions, app_message_rx: mpsc::Receiver) { +pub struct Window { + hwnd: HWND, +} + +impl Window { + pub fn open( + options: WindowOpenOptions, + app_message_rx: mpsc::Receiver, + ) { unsafe { let title = (options.title.to_owned() + "\0").as_ptr() as *const i8; @@ -170,28 +188,15 @@ impl Window { ); // todo: manage error ^ - let mut windows_handle = raw_window_handle::windows::WindowsHandle::empty(); - windows_handle.hwnd = hwnd as *mut std::ffi::c_void; + let mut window = Window { hwnd }; - let raw_window = RawWindow { - raw_window_handle: raw_window_handle::RawWindowHandle::Windows(windows_handle), - }; + let app_window = A::build(&mut window); - let window_info = WindowInfo { - width: options.width as u32, - height: options.height as u32, - scale: 1.0, - }; - - let app_window = A::build(raw_window, &window_info); - - let window = Window { - hwnd, + let window_state = Rc::new(RefCell::new(WindowState { window_class, - app_window, - app_message_rx, scaling: None, - }; + app_window, + })); let win = Rc::new(RefCell::new(window)); @@ -213,18 +218,13 @@ impl Window { } } } +} - pub fn close(&mut self) { - self.app_window.on_event(Event::WillClose); - - // todo: see https://github.com/wrl/rutabaga/blob/f30ff67e157375cafdbafe5fb549f1790443a3a8/src/platform/win/window.c#L402 - unsafe { - DestroyWindow(self.hwnd); - unregister_wnd_class(self.window_class); - } - } - - pub(crate) fn handle_mouse_motion(&mut self, x: i32, y: i32) { - self.app_window.on_event(Event::CursorMotion(x, y)); +unsafe impl HasRawWindowHandle for Window { + fn raw_window_handle(&self) -> RawWindowHandle { + RawWindowHandle::Windows(WindowsHandle { + hwnd: self.hwnd as *mut std::ffi::c_void, + ..WindowsHandle::empty() + }) } } From bb6a5eeeac671a9cbdd0ebebbe7db90dabdf7c38 Mon Sep 17 00:00:00 2001 From: Micah Johnston Date: Mon, 7 Sep 2020 02:43:06 -0500 Subject: [PATCH 3/7] adapt macos backend to new api --- src/macos/window.rs | 63 +++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/src/macos/window.rs b/src/macos/window.rs index ebc67d1..2213f3e 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -6,22 +6,23 @@ use cocoa::appkit::{ NSApplicationActivationPolicyRegular, NSBackingStoreBuffered, NSRunningApplication, NSView, NSWindow, NSWindowStyleMask, }; -use cocoa::base::{nil, NO}; +use cocoa::base::{id, nil, NO}; use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString}; use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle}; -use crate::{ - AppWindow, Event, MouseButtonID, MouseScroll, RawWindow, WindowInfo, WindowOpenOptions, -}; +use crate::{AppWindow, MouseScroll, WindowOpenOptions}; -pub struct Window { - app_window: A, - app_message_rx: mpsc::Receiver, +pub struct Window { + ns_window: id, + ns_view: id, } -impl Window { - pub fn open(options: WindowOpenOptions, app_message_rx: mpsc::Receiver) -> Self { +impl Window { + pub fn open( + options: WindowOpenOptions, + app_message_rx: mpsc::Receiver, + ) { unsafe { let _pool = NSAutoreleasePool::new(nil); @@ -33,7 +34,7 @@ impl Window { NSSize::new(options.width as f64, options.height as f64), ); - let window = NSWindow::alloc(nil) + let ns_window = NSWindow::alloc(nil) .initWithContentRect_styleMask_backing_defer_( rect, NSWindowStyleMask::NSTitledWindowMask, @@ -41,37 +42,33 @@ impl Window { NO, ) .autorelease(); - window.center(); - window.setTitle_(NSString::alloc(nil).init_str(options.title)); - window.makeKeyAndOrderFront_(nil); + ns_window.center(); + ns_window.setTitle_(NSString::alloc(nil).init_str(options.title)); + ns_window.makeKeyAndOrderFront_(nil); - let view = NSView::alloc(nil).init(); - window.setContentView_(view); + let ns_view = NSView::alloc(nil).init(); + ns_window.setContentView_(ns_view); - let raw_window = RawWindow { - raw_window_handle: RawWindowHandle::MacOS(MacOSHandle { - ns_window: window as *mut c_void, - ns_view: app as *mut c_void, - ..raw_window_handle::macos::MacOSHandle::empty() - }), + let mut window = Window { + ns_window, + ns_view, }; - let window_info = WindowInfo { - width: options.width as u32, - height: options.height as u32, - scale: 1.0, - }; - - let app_window = A::build(raw_window, &window_info); + let app_window = A::build(&mut window); let current_app = NSRunningApplication::currentApplication(nil); current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps); app.run(); - - Window { - app_window, - app_message_rx, - } } } } + +unsafe impl HasRawWindowHandle for Window { + fn raw_window_handle(&self) -> RawWindowHandle { + RawWindowHandle::MacOS(MacOSHandle { + ns_window: self.ns_window as *mut c_void, + ns_view: self.ns_view as *mut c_void, + ..MacOSHandle::empty() + }) + } +} From 057324e688779f3355cdedddd79f7ee0b6f90436 Mon Sep 17 00:00:00 2001 From: micah Date: Mon, 7 Sep 2020 14:16:48 -0400 Subject: [PATCH 4/7] adapt x11 backend to new api --- src/x11/window.rs | 210 ++++++++++++++++++++++------------------------ 1 file changed, 100 insertions(+), 110 deletions(-) diff --git a/src/x11/window.rs b/src/x11/window.rs index 3f23726..5d3a896 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -4,20 +4,19 @@ use std::sync::mpsc; use super::XcbConnection; use crate::{ - AppWindow, Event, MouseButtonID, MouseScroll, Parent, RawWindow, WindowInfo, WindowOpenOptions, + AppWindow, Event, MouseButtonID, MouseScroll, Parent, WindowOpenOptions, }; -use raw_window_handle::RawWindowHandle; +use raw_window_handle::{unix::XlibHandle, HasRawWindowHandle, RawWindowHandle}; -pub struct Window { - scaling: f64, +pub struct Window { xcb_connection: XcbConnection, - app_window: A, - app_message_rx: mpsc::Receiver, + window_id: u32, + scaling: f64, } -impl Window { - pub fn open(options: WindowOpenOptions, app_message_rx: mpsc::Receiver) -> Self { +impl Window { + pub fn open(options: WindowOpenOptions, app_message_rx: mpsc::Receiver) { // Convert the parent to a X11 window ID if we're given one let parent = match options.parent { Parent::None => None, @@ -93,131 +92,122 @@ impl Window { xcb_connection.conn.flush(); - let raw_handle = RawWindowHandle::Xlib(raw_window_handle::unix::XlibHandle { - window: window_id as c_ulong, - display: xcb_connection.conn.get_raw_dpy() as *mut c_void, - ..raw_window_handle::unix::XlibHandle::empty() - }); - - let raw_window = RawWindow { - raw_window_handle: raw_handle, - }; - let scaling = get_scaling_xft(&xcb_connection) .or(get_scaling_screen_dimensions(&xcb_connection)) .unwrap_or(1.0); - let window_info = WindowInfo { - width: options.width as u32, - height: options.height as u32, - scale: scaling, - }; - - let app_window = A::build(raw_window, &window_info); - - let mut x11_window = Self { - scaling, + let mut window = Self { xcb_connection, - app_window, - app_message_rx, + window_id, + scaling, }; - x11_window.run_event_loop(); + let mut app_window = A::build(&mut window); - x11_window + run_event_loop(&mut window, &mut app_window); } +} - // Event loop - fn run_event_loop(&mut self) { - loop { - // somehow poll self.app_message_rx for messages at the same time +unsafe impl HasRawWindowHandle for Window { + fn raw_window_handle(&self) -> RawWindowHandle { + RawWindowHandle::Xlib(XlibHandle { + window: self.window_id as c_ulong, + display: self.xcb_connection.conn.get_raw_dpy() as *mut c_void, + ..raw_window_handle::unix::XlibHandle::empty() + }) + } +} - let ev = self.xcb_connection.conn.wait_for_event(); - if let Some(event) = ev { - let event_type = event.response_type() & !0x80; +// Event loop +fn run_event_loop(window: &mut Window, app_window: &mut A) { + loop { + // somehow poll app_message_rx for messages at the same time - // For all of the keyboard and mouse events, you can fetch - // `x`, `y`, `detail`, and `state`. - // - `x` and `y` are the position inside the window where the cursor currently is - // when the event happened. - // - `detail` will tell you which keycode was pressed/released (for keyboard events) - // or which mouse button was pressed/released (for mouse events). - // For mouse events, here's what the value means (at least on my current mouse): - // 1 = left mouse button - // 2 = middle mouse button (scroll wheel) - // 3 = right mouse button - // 4 = scroll wheel up - // 5 = scroll wheel down - // 8 = lower side button ("back" button) - // 9 = upper side button ("forward" button) - // Note that you *will* get a "button released" event for even the scroll wheel - // events, which you can probably ignore. - // - `state` will tell you the state of the main three mouse buttons and some of - // the keyboard modifier keys at the time of the event. - // http://rtbo.github.io/rust-xcb/src/xcb/ffi/xproto.rs.html#445 + let ev = window.xcb_connection.conn.wait_for_event(); + if let Some(event) = ev { + let event_type = event.response_type() & !0x80; - match event_type { - xcb::EXPOSE => { - self.app_window.draw(); + // For all of the keyboard and mouse events, you can fetch + // `x`, `y`, `detail`, and `state`. + // - `x` and `y` are the position inside the window where the cursor currently is + // when the event happened. + // - `detail` will tell you which keycode was pressed/released (for keyboard events) + // or which mouse button was pressed/released (for mouse events). + // For mouse events, here's what the value means (at least on my current mouse): + // 1 = left mouse button + // 2 = middle mouse button (scroll wheel) + // 3 = right mouse button + // 4 = scroll wheel up + // 5 = scroll wheel down + // 8 = lower side button ("back" button) + // 9 = upper side button ("forward" button) + // Note that you *will* get a "button released" event for even the scroll wheel + // events, which you can probably ignore. + // - `state` will tell you the state of the main three mouse buttons and some of + // the keyboard modifier keys at the time of the event. + // http://rtbo.github.io/rust-xcb/src/xcb/ffi/xproto.rs.html#445 + + match event_type { + xcb::EXPOSE => { + app_window.draw(window); + } + xcb::MOTION_NOTIFY => { + let event = unsafe { xcb::cast_event::(&event) }; + let detail = event.detail(); + + if detail != 4 && detail != 5 { + app_window.on_event(window, Event::CursorMotion( + event.event_x() as i32, + event.event_y() as i32, + )); } - xcb::MOTION_NOTIFY => { - let event = unsafe { xcb::cast_event::(&event) }; - let detail = event.detail(); + } + xcb::BUTTON_PRESS => { + let event = unsafe { xcb::cast_event::(&event) }; + let detail = event.detail(); - if detail != 4 && detail != 5 { - self.app_window.on_event(Event::CursorMotion( - event.event_x() as i32, - event.event_y() as i32, - )); + match detail { + 4 => { + app_window.on_event(window, Event::MouseScroll(MouseScroll { + x_delta: 0.0, + y_delta: 1.0, + })); } - } - xcb::BUTTON_PRESS => { - let event = unsafe { xcb::cast_event::(&event) }; - let detail = event.detail(); - - match detail { - 4 => { - self.app_window.on_event(Event::MouseScroll(MouseScroll { - x_delta: 0.0, - y_delta: 1.0, - })); - } - 5 => { - self.app_window.on_event(Event::MouseScroll(MouseScroll { - x_delta: 0.0, - y_delta: -1.0, - })); - } - detail => { - let button_id = mouse_id(detail); - self.app_window.on_event(Event::MouseDown(button_id)); - } + 5 => { + app_window.on_event(window, Event::MouseScroll(MouseScroll { + x_delta: 0.0, + y_delta: -1.0, + })); } - } - xcb::BUTTON_RELEASE => { - let event = unsafe { xcb::cast_event::(&event) }; - let detail = event.detail(); - - if detail != 4 && detail != 5 { + detail => { let button_id = mouse_id(detail); - self.app_window.on_event(Event::MouseUp(button_id)); + app_window.on_event(window, Event::MouseDown(button_id)); } } - xcb::KEY_PRESS => { - let event = unsafe { xcb::cast_event::(&event) }; - let detail = event.detail(); + } + xcb::BUTTON_RELEASE => { + let event = unsafe { xcb::cast_event::(&event) }; + let detail = event.detail(); - self.app_window.on_event(Event::KeyDown(detail)); + if detail != 4 && detail != 5 { + let button_id = mouse_id(detail); + app_window.on_event(window, Event::MouseUp(button_id)); } - xcb::KEY_RELEASE => { - let event = unsafe { xcb::cast_event::(&event) }; - let detail = event.detail(); + } + xcb::KEY_PRESS => { + let event = unsafe { xcb::cast_event::(&event) }; + let detail = event.detail(); - self.app_window.on_event(Event::KeyUp(detail)); - } - _ => { - println!("Unhandled event type: {:?}", event_type); - } + app_window.on_event(window, Event::KeyDown(detail)); + } + xcb::KEY_RELEASE => { + let event = unsafe { xcb::cast_event::(&event) }; + let detail = event.detail(); + + app_window.on_event(window, Event::KeyUp(detail)); + } + _ => { + println!("Unhandled event type: {:?}", event_type); } } } From c51aea5c128349590615d156f57b1c92e76a03e0 Mon Sep 17 00:00:00 2001 From: Micah Johnston Date: Mon, 7 Sep 2020 21:36:54 -0500 Subject: [PATCH 5/7] rename AppWindow -> WindowHandler --- examples/open_window.rs | 8 +++--- src/lib.rs | 6 ++--- src/macos/window.rs | 13 ++++------ src/win/window.rs | 30 +++++++++++----------- src/x11/window.rs | 55 +++++++++++++++++++++++------------------ 5 files changed, 58 insertions(+), 54 deletions(-) diff --git a/examples/open_window.rs b/examples/open_window.rs index 49cff6f..4a6f546 100644 --- a/examples/open_window.rs +++ b/examples/open_window.rs @@ -1,6 +1,6 @@ use std::sync::mpsc; -use baseview::{Event, Window}; +use baseview::{Event, Window, WindowHandler}; fn main() { let window_open_options = baseview::WindowOpenOptions { @@ -19,8 +19,8 @@ fn main() { struct MyProgram {} -impl baseview::AppWindow for MyProgram { - type AppMessage = (); +impl WindowHandler for MyProgram { + type Message = (); fn build(window: &mut Window) -> Self { Self {} @@ -69,5 +69,5 @@ impl baseview::AppWindow for MyProgram { } } - fn on_app_message(&mut self, window: &mut Window, _message: Self::AppMessage) {} + fn on_message(&mut self, window: &mut Window, _message: Self::Message) {} } diff --git a/src/lib.rs b/src/lib.rs index a962ba4..c4ed84f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,12 +33,12 @@ pub struct WindowOpenOptions<'a> { pub parent: Parent, } -pub trait AppWindow { - type AppMessage; +pub trait WindowHandler { + type Message; fn build(window: &mut Window) -> Self; fn draw(&mut self, window: &mut Window); fn on_event(&mut self, window: &mut Window, event: Event); - fn on_app_message(&mut self, window: &mut Window, message: Self::AppMessage); + fn on_message(&mut self, window: &mut Window, message: Self::Message); } diff --git a/src/macos/window.rs b/src/macos/window.rs index 2213f3e..d142884 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -11,7 +11,7 @@ use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString}; use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle}; -use crate::{AppWindow, MouseScroll, WindowOpenOptions}; +use crate::{MouseScroll, WindowHandler, WindowOpenOptions}; pub struct Window { ns_window: id, @@ -19,9 +19,9 @@ pub struct Window { } impl Window { - pub fn open( + pub fn open( options: WindowOpenOptions, - app_message_rx: mpsc::Receiver, + app_message_rx: mpsc::Receiver, ) { unsafe { let _pool = NSAutoreleasePool::new(nil); @@ -49,12 +49,9 @@ impl Window { let ns_view = NSView::alloc(nil).init(); ns_window.setContentView_(ns_view); - let mut window = Window { - ns_window, - ns_view, - }; + let mut window = Window { ns_window, ns_view }; - let app_window = A::build(&mut window); + let handler = H::build(&mut window); let current_app = NSRunningApplication::currentApplication(nil); current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps); diff --git a/src/win/window.rs b/src/win/window.rs index 89ad38b..b735daf 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -19,7 +19,7 @@ use std::sync::mpsc; use raw_window_handle::{windows::WindowsHandle, HasRawWindowHandle, RawWindowHandle}; -use crate::{AppWindow, Event, Parent::WithParent, WindowInfo, WindowOpenOptions}; +use crate::{Event, Parent::WithParent, WindowHandler, WindowInfo, WindowOpenOptions}; unsafe fn message_box(title: &str, msg: &str) { let title = (title.to_owned() + "\0").as_ptr() as *const i8; @@ -48,14 +48,14 @@ unsafe fn generate_guid() -> String { const WIN_FRAME_TIMER: usize = 4242; -unsafe fn handle_timer(window_state: &RefCell>, timer_id: usize) { +unsafe fn handle_timer(window_state: &RefCell>, timer_id: usize) { match timer_id { WIN_FRAME_TIMER => {} _ => (), } } -unsafe extern "system" fn wnd_proc( +unsafe extern "system" fn wnd_proc( hwnd: HWND, msg: UINT, wparam: WPARAM, @@ -68,7 +68,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 window_state = &*(win_ptr as *const RefCell>); let mut window = Window { hwnd }; match msg { @@ -77,7 +77,7 @@ unsafe extern "system" fn wnd_proc( let y = ((lparam >> 16) & 0xFFFF) as i32; window_state .borrow_mut() - .app_window + .handler .on_event(&mut window, Event::CursorMotion(x, y)); return 0; } @@ -91,7 +91,7 @@ unsafe extern "system" fn wnd_proc( WM_CLOSE => { window_state .borrow_mut() - .app_window + .handler .on_event(&mut window, Event::WillClose); return DefWindowProcA(hwnd, msg, wparam, lparam); } @@ -102,13 +102,13 @@ unsafe extern "system" fn wnd_proc( return DefWindowProcA(hwnd, msg, wparam, lparam); } -unsafe fn register_wnd_class() -> ATOM { +unsafe fn register_wnd_class() -> ATOM { // We generate a unique name for the new window class to prevent name collisions let class_name = format!("Baseview-{}", generate_guid()).as_ptr() as *const i8; let wnd_class = WNDCLASSA { style: CS_OWNDC, - lpfnWndProc: Some(wnd_proc::), + lpfnWndProc: Some(wnd_proc::), hInstance: null_mut(), lpszClassName: class_name, cbClsExtra: 0, @@ -126,10 +126,10 @@ unsafe fn unregister_wnd_class(wnd_class: ATOM) { UnregisterClassA(wnd_class as _, null_mut()); } -struct WindowState { +struct WindowState { window_class: ATOM, scaling: Option, // DPI scale, 96.0 is "default". - app_window: A, + handler: H, } pub struct Window { @@ -137,14 +137,14 @@ pub struct Window { } impl Window { - pub fn open( + pub fn open( options: WindowOpenOptions, - app_message_rx: mpsc::Receiver, + app_message_rx: mpsc::Receiver, ) { unsafe { let title = (options.title.to_owned() + "\0").as_ptr() as *const i8; - let window_class = register_wnd_class::(); + let window_class = register_wnd_class::(); // todo: manage error ^ let mut flags = WS_POPUPWINDOW @@ -190,12 +190,12 @@ impl Window { let mut window = Window { hwnd }; - let app_window = A::build(&mut window); + let handler = H::build(&mut window); let window_state = Rc::new(RefCell::new(WindowState { window_class, scaling: None, - app_window, + handler, })); let win = Rc::new(RefCell::new(window)); diff --git a/src/x11/window.rs b/src/x11/window.rs index 5d3a896..4b7694b 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -3,9 +3,7 @@ use std::os::raw::{c_ulong, c_void}; use std::sync::mpsc; use super::XcbConnection; -use crate::{ - AppWindow, Event, MouseButtonID, MouseScroll, Parent, WindowOpenOptions, -}; +use crate::{Event, MouseButtonID, MouseScroll, Parent, WindowHandler, WindowOpenOptions}; use raw_window_handle::{unix::XlibHandle, HasRawWindowHandle, RawWindowHandle}; @@ -16,7 +14,10 @@ pub struct Window { } impl Window { - pub fn open(options: WindowOpenOptions, app_message_rx: mpsc::Receiver) { + pub fn open( + options: WindowOpenOptions, + app_message_rx: mpsc::Receiver, + ) { // Convert the parent to a X11 window ID if we're given one let parent = match options.parent { Parent::None => None, @@ -102,9 +103,9 @@ impl Window { scaling, }; - let mut app_window = A::build(&mut window); + let mut handler = H::build(&mut window); - run_event_loop(&mut window, &mut app_window); + run_event_loop(&mut window, &mut handler); } } @@ -119,7 +120,7 @@ unsafe impl HasRawWindowHandle for Window { } // Event loop -fn run_event_loop(window: &mut Window, app_window: &mut A) { +fn run_event_loop(window: &mut Window, handler: &mut H) { loop { // somehow poll app_message_rx for messages at the same time @@ -149,17 +150,17 @@ fn run_event_loop(window: &mut Window, app_window: &mut A) { match event_type { xcb::EXPOSE => { - app_window.draw(window); + handler.draw(window); } xcb::MOTION_NOTIFY => { let event = unsafe { xcb::cast_event::(&event) }; let detail = event.detail(); if detail != 4 && detail != 5 { - app_window.on_event(window, Event::CursorMotion( - event.event_x() as i32, - event.event_y() as i32, - )); + handler.on_event( + window, + Event::CursorMotion(event.event_x() as i32, event.event_y() as i32), + ); } } xcb::BUTTON_PRESS => { @@ -168,20 +169,26 @@ fn run_event_loop(window: &mut Window, app_window: &mut A) { match detail { 4 => { - app_window.on_event(window, Event::MouseScroll(MouseScroll { - x_delta: 0.0, - y_delta: 1.0, - })); + handler.on_event( + window, + Event::MouseScroll(MouseScroll { + x_delta: 0.0, + y_delta: 1.0, + }), + ); } 5 => { - app_window.on_event(window, Event::MouseScroll(MouseScroll { - x_delta: 0.0, - y_delta: -1.0, - })); + handler.on_event( + window, + Event::MouseScroll(MouseScroll { + x_delta: 0.0, + y_delta: -1.0, + }), + ); } detail => { let button_id = mouse_id(detail); - app_window.on_event(window, Event::MouseDown(button_id)); + handler.on_event(window, Event::MouseDown(button_id)); } } } @@ -191,20 +198,20 @@ fn run_event_loop(window: &mut Window, app_window: &mut A) { if detail != 4 && detail != 5 { let button_id = mouse_id(detail); - app_window.on_event(window, Event::MouseUp(button_id)); + handler.on_event(window, Event::MouseUp(button_id)); } } xcb::KEY_PRESS => { let event = unsafe { xcb::cast_event::(&event) }; let detail = event.detail(); - app_window.on_event(window, Event::KeyDown(detail)); + handler.on_event(window, Event::KeyDown(detail)); } xcb::KEY_RELEASE => { let event = unsafe { xcb::cast_event::(&event) }; let detail = event.detail(); - app_window.on_event(window, Event::KeyUp(detail)); + handler.on_event(window, Event::KeyUp(detail)); } _ => { println!("Unhandled event type: {:?}", event_type); From 601a5d62a4557be679965c2c64a2f707a9c5e024 Mon Sep 17 00:00:00 2001 From: Micah Johnston Date: Mon, 7 Sep 2020 21:39:21 -0500 Subject: [PATCH 6/7] remove mspc channel (to be replaced by baseview-specific WindowHandle --- examples/open_window.rs | 8 +------- src/macos/window.rs | 6 +----- src/win/window.rs | 6 +----- src/x11/window.rs | 8 +------- 4 files changed, 4 insertions(+), 24 deletions(-) diff --git a/examples/open_window.rs b/examples/open_window.rs index 4a6f546..861c95b 100644 --- a/examples/open_window.rs +++ b/examples/open_window.rs @@ -1,5 +1,3 @@ -use std::sync::mpsc; - use baseview::{Event, Window, WindowHandler}; fn main() { @@ -10,11 +8,7 @@ fn main() { parent: baseview::Parent::None, }; - let (_app_message_tx, app_message_rx) = mpsc::channel::<()>(); - - // Send _app_message_tx to a separate thread, then send messages to the GUI thread. - - let _ = Window::open::(window_open_options, app_message_rx); + Window::open::(window_open_options); } struct MyProgram {} diff --git a/src/macos/window.rs b/src/macos/window.rs index d142884..ee4c0d9 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -1,5 +1,4 @@ use std::ffi::c_void; -use std::sync::mpsc; use cocoa::appkit::{ NSApp, NSApplication, NSApplicationActivateIgnoringOtherApps, @@ -19,10 +18,7 @@ pub struct Window { } impl Window { - pub fn open( - options: WindowOpenOptions, - app_message_rx: mpsc::Receiver, - ) { + pub fn open(options: WindowOpenOptions) { unsafe { let _pool = NSAutoreleasePool::new(nil); diff --git a/src/win/window.rs b/src/win/window.rs index b735daf..bcc53f9 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -15,7 +15,6 @@ use std::cell::RefCell; use std::ffi::c_void; use std::ptr::null_mut; use std::rc::Rc; -use std::sync::mpsc; use raw_window_handle::{windows::WindowsHandle, HasRawWindowHandle, RawWindowHandle}; @@ -137,10 +136,7 @@ pub struct Window { } impl Window { - pub fn open( - options: WindowOpenOptions, - app_message_rx: mpsc::Receiver, - ) { + pub fn open(options: WindowOpenOptions) { unsafe { let title = (options.title.to_owned() + "\0").as_ptr() as *const i8; diff --git a/src/x11/window.rs b/src/x11/window.rs index 4b7694b..c5c5a30 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -1,6 +1,5 @@ use std::ffi::CStr; use std::os::raw::{c_ulong, c_void}; -use std::sync::mpsc; use super::XcbConnection; use crate::{Event, MouseButtonID, MouseScroll, Parent, WindowHandler, WindowOpenOptions}; @@ -14,10 +13,7 @@ pub struct Window { } impl Window { - pub fn open( - options: WindowOpenOptions, - app_message_rx: mpsc::Receiver, - ) { + pub fn open(options: WindowOpenOptions) { // Convert the parent to a X11 window ID if we're given one let parent = match options.parent { Parent::None => None, @@ -122,8 +118,6 @@ unsafe impl HasRawWindowHandle for Window { // Event loop fn run_event_loop(window: &mut Window, handler: &mut H) { loop { - // somehow poll app_message_rx for messages at the same time - let ev = window.xcb_connection.conn.wait_for_event(); if let Some(event) = ev { let event_type = event.response_type() & !0x80; From 5ecce5d28ddb6bd46e4c9db19883be495092c9bf Mon Sep 17 00:00:00 2001 From: Micah Johnston Date: Mon, 7 Sep 2020 21:45:08 -0500 Subject: [PATCH 7/7] Window::open() returns WindowHandle struct --- examples/open_window.rs | 2 +- src/macos/window.rs | 6 +++++- src/win/window.rs | 6 +++++- src/x11/window.rs | 6 +++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/examples/open_window.rs b/examples/open_window.rs index 861c95b..1371354 100644 --- a/examples/open_window.rs +++ b/examples/open_window.rs @@ -8,7 +8,7 @@ fn main() { parent: baseview::Parent::None, }; - Window::open::(window_open_options); + let _handle = Window::open::(window_open_options); } struct MyProgram {} diff --git a/src/macos/window.rs b/src/macos/window.rs index ee4c0d9..40c54b4 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -18,7 +18,7 @@ pub struct Window { } impl Window { - pub fn open(options: WindowOpenOptions) { + pub fn open(options: WindowOpenOptions) -> WindowHandle { unsafe { let _pool = NSAutoreleasePool::new(nil); @@ -52,6 +52,8 @@ impl Window { let current_app = NSRunningApplication::currentApplication(nil); current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps); app.run(); + + WindowHandle } } } @@ -65,3 +67,5 @@ unsafe impl HasRawWindowHandle for Window { }) } } + +pub struct WindowHandle; diff --git a/src/win/window.rs b/src/win/window.rs index bcc53f9..e3b4cfa 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -136,7 +136,7 @@ pub struct Window { } impl Window { - pub fn open(options: WindowOpenOptions) { + pub fn open(options: WindowOpenOptions) -> WindowHandle { unsafe { let title = (options.title.to_owned() + "\0").as_ptr() as *const i8; @@ -213,6 +213,8 @@ impl Window { } } } + + WindowHandle } } @@ -224,3 +226,5 @@ unsafe impl HasRawWindowHandle for Window { }) } } + +pub struct WindowHandle; diff --git a/src/x11/window.rs b/src/x11/window.rs index c5c5a30..2974de6 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -13,7 +13,7 @@ pub struct Window { } impl Window { - pub fn open(options: WindowOpenOptions) { + pub fn open(options: WindowOpenOptions) -> WindowHandle { // Convert the parent to a X11 window ID if we're given one let parent = match options.parent { Parent::None => None, @@ -102,6 +102,8 @@ impl Window { let mut handler = H::build(&mut window); run_event_loop(&mut window, &mut handler); + + WindowHandle } } @@ -115,6 +117,8 @@ unsafe impl HasRawWindowHandle for Window { } } +pub struct WindowHandle; + // Event loop fn run_event_loop(window: &mut Window, handler: &mut H) { loop {