1
0
Fork 0

Rename Message to Event. Add AppMessage type and on_app_message method to Receiver trait.

This commit is contained in:
Billy Messenger 2020-09-03 11:38:22 -05:00
parent ab8cb1c223
commit 81e791f06b
6 changed files with 85 additions and 49 deletions

View file

@ -1,4 +1,6 @@
use baseview::Message; use std::sync::mpsc;
use baseview::Event;
fn main() { fn main() {
let window_open_options = baseview::WindowOpenOptions { let window_open_options = baseview::WindowOpenOptions {
@ -10,11 +12,17 @@ fn main() {
let my_program = MyProgram {}; let my_program = MyProgram {};
let _ = baseview::Window::open(window_open_options, my_program); 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 _ = baseview::Window::open(window_open_options, my_program, app_message_rx);
} }
struct MyProgram {} struct MyProgram {}
impl baseview::Receiver for MyProgram { impl baseview::Receiver for MyProgram {
type AppMessage = ();
fn create_context( fn create_context(
&mut self, &mut self,
_window: raw_window_handle::RawWindowHandle, _window: raw_window_handle::RawWindowHandle,
@ -22,45 +30,47 @@ impl baseview::Receiver for MyProgram {
) { ) {
} }
fn on_message(&mut self, message: Message) { fn on_event(&mut self, event: Event) {
match message { match event {
Message::RenderExpose => {} Event::RenderExpose => {}
Message::CursorMotion(x, y) => { Event::CursorMotion(x, y) => {
println!("Cursor moved, x: {}, y: {}", x, y); println!("Cursor moved, x: {}, y: {}", x, y);
} }
Message::MouseDown(button_id) => { Event::MouseDown(button_id) => {
println!("Mouse down, button id: {:?}", button_id); println!("Mouse down, button id: {:?}", button_id);
} }
Message::MouseUp(button_id) => { Event::MouseUp(button_id) => {
println!("Mouse up, button id: {:?}", button_id); println!("Mouse up, button id: {:?}", button_id);
} }
Message::MouseScroll(mouse_scroll) => { Event::MouseScroll(mouse_scroll) => {
println!("Mouse scroll, {:?}", mouse_scroll); println!("Mouse scroll, {:?}", mouse_scroll);
} }
Message::MouseClick(mouse_click) => { Event::MouseClick(mouse_click) => {
println!("Mouse click, {:?}", mouse_click); println!("Mouse click, {:?}", mouse_click);
} }
Message::KeyDown(keycode) => { Event::KeyDown(keycode) => {
println!("Key down, keycode: {}", keycode); println!("Key down, keycode: {}", keycode);
} }
Message::KeyUp(keycode) => { Event::KeyUp(keycode) => {
println!("Key up, keycode: {}", keycode); println!("Key up, keycode: {}", keycode);
} }
Message::CharacterInput(char_code) => { Event::CharacterInput(char_code) => {
println!("Character input, char_code: {}", char_code); println!("Character input, char_code: {}", char_code);
} }
Message::WindowResized(window_info) => { Event::WindowResized(window_info) => {
println!("Window resized, {:?}", window_info); println!("Window resized, {:?}", window_info);
} }
Message::WindowFocus => { Event::WindowFocus => {
println!("Window focused"); println!("Window focused");
} }
Message::WindowUnfocus => { Event::WindowUnfocus => {
println!("Window unfocused"); println!("Window unfocused");
} }
Message::WillClose => { Event::WillClose => {
println!("Window will close"); println!("Window will close");
} }
} }
} }
fn on_app_message(&mut self, _message: Self::AppMessage) {}
} }

View file

@ -37,7 +37,7 @@ pub struct WindowInfo {
} }
#[derive(Debug)] #[derive(Debug)]
pub enum Message { pub enum Event {
RenderExpose, RenderExpose,
CursorMotion(i32, i32), // new (x, y) relative to window CursorMotion(i32, i32), // new (x, y) relative to window
MouseDown(MouseButtonID), MouseDown(MouseButtonID),

View file

@ -15,8 +15,8 @@ mod macos;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub use macos::*; pub use macos::*;
mod message; mod event;
pub use message::*; pub use event::*;
pub enum Parent { pub enum Parent {
None, None,
@ -34,10 +34,13 @@ pub struct WindowOpenOptions<'a> {
} }
pub trait Receiver { pub trait Receiver {
type AppMessage;
fn create_context( fn create_context(
&mut self, &mut self,
window: raw_window_handle::RawWindowHandle, window: raw_window_handle::RawWindowHandle,
window_info: &WindowInfo, window_info: &WindowInfo,
); );
fn on_message(&mut self, message: Message); fn on_event(&mut self, event: Event);
fn on_app_message(&mut self, message: Self::AppMessage);
} }

View file

@ -6,14 +6,19 @@ use cocoa::appkit::{
use cocoa::base::{nil, NO}; use cocoa::base::{nil, NO};
use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString}; use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString};
use crate::{Message, MouseButtonID, MouseScroll, Receiver, WindowOpenOptions}; use crate::{Event, MouseButtonID, MouseScroll, Receiver, WindowOpenOptions};
pub struct Window<R: Receiver> { pub struct Window<R: Receiver> {
receiver: R, receiver: R,
app_message_rx: mpsc::Receiver<R::AppMessage>,
} }
impl<R: Receiver> Window<R> { impl<R: Receiver> Window<R> {
pub fn open(options: WindowOpenOptions, receiver: R) -> Self { pub fn open(
options: WindowOpenOptions,
receiver: R,
app_message_rx: mpsc::Receiver<R::AppMessage>,
) -> Self {
unsafe { unsafe {
let _pool = NSAutoreleasePool::new(nil); let _pool = NSAutoreleasePool::new(nil);
@ -44,7 +49,10 @@ impl<R: Receiver> Window<R> {
current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps); current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps);
app.run(); app.run();
Window { receiver } Window {
receiver,
app_message_rx,
}
} }
} }
} }

View file

@ -2,6 +2,7 @@ extern crate winapi;
use std::ffi::CString; use std::ffi::CString;
use std::ptr::null_mut; use std::ptr::null_mut;
use std::sync::mpsc;
use self::winapi::shared::guiddef::GUID; use self::winapi::shared::guiddef::GUID;
use self::winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM}; use self::winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM};
@ -14,24 +15,24 @@ use self::winapi::um::wingdi::{
PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR, PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR,
}; };
use self::winapi::um::winuser::{ use self::winapi::um::winuser::{
AdjustWindowRectEx, CreateWindowExA, DefWindowProcA, DestroyWindow, DispatchMessageA, GetDC, AdjustWindowRectEx, CreateWindowExA, DefWindowProcA, DestroyWindow, DispatchEventA, EventBoxA,
GetMessageA, GetWindowLongPtrA, MessageBoxA, PeekMessageA, PostMessageA, RegisterClassA, GetDC, GetEventA, GetWindowLongPtrA, PeekEventA, PostEventA, RegisterClassA, ReleaseDC,
ReleaseDC, SetTimer, SetWindowLongPtrA, TranslateMessage, UnregisterClassA, CS_OWNDC, SetTimer, SetWindowLongPtrA, TranslateEvent, UnregisterClassA, CS_OWNDC, GWLP_USERDATA,
GWLP_USERDATA, MB_ICONERROR, MB_OK, MB_TOPMOST, MSG, PM_REMOVE, WM_CREATE, WM_QUIT, MB_ICONERROR, MB_OK, MB_TOPMOST, MSG, PM_REMOVE, WM_CREATE, WM_QUIT, WM_SHOWWINDOW, WM_TIMER,
WM_SHOWWINDOW, WM_TIMER, WNDCLASSA, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WNDCLASSA, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX,
WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE,
}; };
use self::winapi::ctypes::c_void; use self::winapi::ctypes::c_void;
use crate::Parent::WithParent; use crate::Parent::WithParent;
use crate::{handle_message, WindowOpenOptions}; use crate::{handle_message, WindowOpenOptions};
use crate::{Message, MouseButtonID, MouseScroll, Receiver}; use crate::{Event, MouseButtonID, MouseScroll, Receiver};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
unsafe fn message_box(title: &str, msg: &str) { unsafe fn message_box(title: &str, msg: &str) {
let title = (title.to_owned() + "\0").as_ptr() as *const i8; let title = (title.to_owned() + "\0").as_ptr() as *const i8;
let msg = (msg.to_owned() + "\0").as_ptr() as *const i8; let msg = (msg.to_owned() + "\0").as_ptr() as *const i8;
MessageBoxA(null_mut(), msg, title, MB_ICONERROR | MB_OK | MB_TOPMOST); EventBoxA(null_mut(), msg, title, MB_ICONERROR | MB_OK | MB_TOPMOST);
} }
unsafe fn generate_guid() -> String { unsafe fn generate_guid() -> String {
@ -62,7 +63,7 @@ unsafe extern "system" fn wnd_proc(
let win_ptr = GetWindowLongPtrA(hwnd, GWLP_USERDATA) as *const c_void; let win_ptr = GetWindowLongPtrA(hwnd, GWLP_USERDATA) as *const c_void;
match msg { match msg {
WM_CREATE => { WM_CREATE => {
PostMessageA(hwnd, WM_SHOWWINDOW, 0, 0); PostEventA(hwnd, WM_SHOWWINDOW, 0, 0);
0 0
} }
_ => { _ => {
@ -118,6 +119,7 @@ pub struct Window<R: Receiver> {
gl_context: HGLRC, gl_context: HGLRC,
window_class: ATOM, window_class: ATOM,
receiver: R, receiver: R,
app_message_rx: mpsc::Receiver<R::AppMessage>,
scaling: Option<f64>, // DPI scale, 96.0 is "default". scaling: Option<f64>, // DPI scale, 96.0 is "default".
r: f32, r: f32,
g: f32, g: f32,
@ -125,7 +127,11 @@ pub struct Window<R: Receiver> {
} }
impl<R: Receiver> Window<R> { impl<R: Receiver> Window<R> {
pub fn open(options: WindowOpenOptions, receiver: R) { pub fn open(
options: WindowOpenOptions,
receiver: R,
app_message_rx: mpsc::Receiver<R::AppMessage>,
) {
unsafe { unsafe {
let mut window = Window { let mut window = Window {
hwnd: null_mut(), hwnd: null_mut(),
@ -133,6 +139,7 @@ impl<R: Receiver> Window<R> {
gl_context: null_mut(), gl_context: null_mut(),
window_class: 0, window_class: 0,
receiver, receiver,
app_message_rx,
scaling: None, scaling: None,
r: 0.3, r: 0.3,
g: 0.8, g: 0.8,
@ -245,11 +252,11 @@ impl<R: Receiver> Window<R> {
if parent.is_null() { if parent.is_null() {
let mut msg: MSG = std::mem::zeroed(); let mut msg: MSG = std::mem::zeroed();
loop { loop {
let status = GetMessageA(&mut msg, hwnd, 0, 0); let status = GetEventA(&mut msg, hwnd, 0, 0);
if status == -1 { if status == -1 {
break; break;
} }
TranslateMessage(&mut msg); TranslateEvent(&mut msg);
handle_message(Arc::clone(&win_p), msg.message, msg.wParam, msg.lParam); handle_message(Arc::clone(&win_p), msg.message, msg.wParam, msg.lParam);
} }
} }
@ -257,7 +264,7 @@ impl<R: Receiver> Window<R> {
} }
pub fn close(&self) { pub fn close(&self) {
self.receiver.on_message(Message::WillClose); self.receiver.on_event(Event::WillClose);
// todo: see https://github.com/wrl/rutabaga/blob/f30ff67e157375cafdbafe5fb549f1790443a3a8/src/platform/win/window.c#L402 // todo: see https://github.com/wrl/rutabaga/blob/f30ff67e157375cafdbafe5fb549f1790443a3a8/src/platform/win/window.c#L402
unsafe { unsafe {
@ -282,6 +289,6 @@ impl<R: Receiver> Window<R> {
self.r = r; self.r = r;
self.g = g; self.g = g;
self.receiver.on_message(Message::CursorMotion(x, y)); self.receiver.on_message(Event::CursorMotion(x, y));
} }
} }

View file

@ -1,12 +1,12 @@
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw::c_void; use std::os::raw::c_void;
use std::thread; use std::sync::mpsc;
use ::x11::xlib; use ::x11::xlib;
// use xcb::dri2; // needed later // use xcb::dri2; // needed later
use super::XcbConnection; use super::XcbConnection;
use crate::{Message, MouseButtonID, MouseScroll, Parent, Receiver, WindowInfo, WindowOpenOptions}; use crate::{Event, MouseButtonID, MouseScroll, Parent, Receiver, WindowInfo, WindowOpenOptions};
use raw_window_handle::RawWindowHandle; use raw_window_handle::RawWindowHandle;
@ -14,10 +14,15 @@ pub struct Window<R: Receiver> {
scaling: Option<f64>, // DPI scale, 96.0 is "default". scaling: Option<f64>, // DPI scale, 96.0 is "default".
xcb_connection: XcbConnection, xcb_connection: XcbConnection,
receiver: R, receiver: R,
app_message_rx: mpsc::Receiver<R::AppMessage>,
} }
impl<R: Receiver> Window<R> { impl<R: Receiver> Window<R> {
pub fn open(options: WindowOpenOptions, receiver: R) -> Self { pub fn open(
options: WindowOpenOptions,
receiver: R,
app_message_rx: mpsc::Receiver<R::AppMessage>,
) -> Self {
// Convert the parent to a X11 window ID if we're given one // Convert the parent to a X11 window ID if we're given one
let parent = match options.parent { let parent = match options.parent {
Parent::None => None, Parent::None => None,
@ -130,6 +135,7 @@ impl<R: Receiver> Window<R> {
scaling: None, scaling: None,
xcb_connection, xcb_connection,
receiver, receiver,
app_message_rx,
}; };
x11_window.scaling = get_scaling_xft(&x11_window.xcb_connection) x11_window.scaling = get_scaling_xft(&x11_window.xcb_connection)
@ -153,6 +159,8 @@ impl<R: Receiver> Window<R> {
fn run_event_loop(&mut self) { fn run_event_loop(&mut self) {
//let raw_display = self.xcb_connection.conn.get_raw_dpy(); //let raw_display = self.xcb_connection.conn.get_raw_dpy();
loop { loop {
// somehow poll self.app_message_rx for messages at the same time
let ev = self.xcb_connection.conn.wait_for_event(); let ev = self.xcb_connection.conn.wait_for_event();
if let Some(event) = ev { if let Some(event) = ev {
let event_type = event.response_type() & !0x80; let event_type = event.response_type() & !0x80;
@ -179,14 +187,14 @@ impl<R: Receiver> Window<R> {
match event_type { match event_type {
xcb::EXPOSE => { xcb::EXPOSE => {
self.receiver.on_message(Message::RenderExpose); self.receiver.on_event(Event::RenderExpose);
} }
xcb::MOTION_NOTIFY => { xcb::MOTION_NOTIFY => {
let event = unsafe { xcb::cast_event::<xcb::MotionNotifyEvent>(&event) }; let event = unsafe { xcb::cast_event::<xcb::MotionNotifyEvent>(&event) };
let detail = event.detail(); let detail = event.detail();
if detail != 4 && detail != 5 { if detail != 4 && detail != 5 {
self.receiver.on_message(Message::CursorMotion( self.receiver.on_event(Event::CursorMotion(
event.event_x() as i32, event.event_x() as i32,
event.event_y() as i32, event.event_y() as i32,
)); ));
@ -198,20 +206,20 @@ impl<R: Receiver> Window<R> {
match detail { match detail {
4 => { 4 => {
self.receiver.on_message(Message::MouseScroll(MouseScroll { self.receiver.on_event(Event::MouseScroll(MouseScroll {
x_delta: 0.0, x_delta: 0.0,
y_delta: 1.0, y_delta: 1.0,
})); }));
} }
5 => { 5 => {
self.receiver.on_message(Message::MouseScroll(MouseScroll { self.receiver.on_event(Event::MouseScroll(MouseScroll {
x_delta: 0.0, x_delta: 0.0,
y_delta: -1.0, y_delta: -1.0,
})); }));
} }
detail => { detail => {
let button_id = mouse_id(detail); let button_id = mouse_id(detail);
self.receiver.on_message(Message::MouseDown(button_id)); self.receiver.on_event(Event::MouseDown(button_id));
} }
} }
} }
@ -221,20 +229,20 @@ impl<R: Receiver> Window<R> {
if detail != 4 && detail != 5 { if detail != 4 && detail != 5 {
let button_id = mouse_id(detail); let button_id = mouse_id(detail);
self.receiver.on_message(Message::MouseUp(button_id)); self.receiver.on_event(Event::MouseUp(button_id));
} }
} }
xcb::KEY_PRESS => { xcb::KEY_PRESS => {
let event = unsafe { xcb::cast_event::<xcb::KeyPressEvent>(&event) }; let event = unsafe { xcb::cast_event::<xcb::KeyPressEvent>(&event) };
let detail = event.detail(); let detail = event.detail();
self.receiver.on_message(Message::KeyDown(detail)); self.receiver.on_event(Event::KeyDown(detail));
} }
xcb::KEY_RELEASE => { xcb::KEY_RELEASE => {
let event = unsafe { xcb::cast_event::<xcb::KeyReleaseEvent>(&event) }; let event = unsafe { xcb::cast_event::<xcb::KeyReleaseEvent>(&event) };
let detail = event.detail(); let detail = event.detail();
self.receiver.on_message(Message::KeyUp(detail)); self.receiver.on_event(Event::KeyUp(detail));
} }
_ => { _ => {
println!("Unhandled event type: {:?}", event_type); println!("Unhandled event type: {:?}", event_type);