1
0
Fork 0

Support passing back some events to the platform (#90)

* Add mutable event status argument to WindowHandler::on_event

* macOS: simplify method declaration for simple mouse event handlers

* macOS: add macro for adding simple keyboard class methods

* macOS: reorder code in mouse_moved

* Take EventStatus as return value in WindowHandler::on_event

* Add doc comments for EventStatus

* Improve EventStatus documentation

* x11: ignore return value of on_event for now

* EventStatus: improve docs

* Improve EventsStatus docs

* Improve EventStatus docs further

* macOS: ignore EventStatus::Ignored for mouse events

* macOS: minor formatting improvement

* improve EventStatus docs again
This commit is contained in:
Joakim Frostegård 2021-02-09 21:47:31 +01:00 committed by GitHub
parent 663f9d5d4c
commit 72b6a4a2d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 133 additions and 128 deletions

View file

@ -2,7 +2,7 @@ use std::time::Duration;
use rtrb::{RingBuffer, Consumer};
use baseview::{Event, Window, WindowHandler, WindowScalePolicy};
use baseview::{Event, EventStatus, Window, WindowHandler, WindowScalePolicy};
#[derive(Debug, Clone)]
enum Message {
@ -20,12 +20,14 @@ impl WindowHandler for OpenWindowExample {
}
}
fn on_event(&mut self, _window: &mut Window, event: Event) {
fn on_event(&mut self, _window: &mut Window, event: Event) -> EventStatus {
match event {
Event::Mouse(e) => println!("Mouse event: {:?}", e),
Event::Keyboard(e) => println!("Keyboard event: {:?}", e),
Event::Window(e) => println!("Window event: {:?}", e),
}
EventStatus::Captured
}
}

View file

@ -68,7 +68,7 @@ pub enum MouseEvent {
CursorLeft,
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum WindowEvent {
Resized(WindowInfo),
Focused,
@ -76,9 +76,31 @@ pub enum WindowEvent {
WillClose,
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum Event {
Mouse(MouseEvent),
Keyboard(KeyboardEvent),
Window(WindowEvent),
}
/// Return value for [WindowHandler::on_event](`crate::WindowHandler::on_event()`),
/// indicating whether the event was handled by your window or should be passed
/// back to the platform.
///
/// For most event types, this value won't have any effect. This is the case
/// when there is no clear meaning of passing back the event to the platform,
/// or it isn't obviously useful. Currently, only [`Event::Keyboard`] variants
/// are supported.
#[derive(Debug)]
pub enum EventStatus {
/// Event was handled by your window and will not be sent back to the
/// platform for further processing.
Captured,
/// Event was **not** handled by your window, so pass it back to the
/// platform. For parented windows, this usually means that the parent
/// window will receive the event. This is useful for cases such as using
/// DAW functionality for playing piano keys with the keyboard while a
/// plugin window is in focus.
Ignored,
}

View file

@ -13,7 +13,7 @@ use objc::{
};
use uuid::Uuid;
use crate::{Event, MouseButton, MouseEvent, Point, WindowOpenOptions};
use crate::{Event, EventStatus, MouseButton, MouseEvent, Point, WindowOpenOptions};
use crate::MouseEvent::{ButtonPressed, ButtonReleased};
use super::window::WindowState;
@ -23,6 +23,54 @@ use super::window::WindowState;
pub(super) const BASEVIEW_STATE_IVAR: &str = "baseview_state";
macro_rules! add_simple_mouse_class_method {
($class:ident, $sel:ident, $event:expr) => {
#[allow(non_snake_case)]
extern "C" fn $sel(this: &Object, _: Sel, _: id){
let state: &mut WindowState = unsafe {
WindowState::from_field(this)
};
state.trigger_event(Event::Mouse($event));
}
$class.add_method(
sel!($sel:),
$sel as extern "C" fn(&Object, Sel, id),
);
};
}
macro_rules! add_simple_keyboard_class_method {
($class:ident, $sel:ident) => {
#[allow(non_snake_case)]
extern "C" fn $sel(this: &Object, _: Sel, event: id){
let state: &mut WindowState = unsafe {
WindowState::from_field(this)
};
if let Some(key_event) = state.process_native_key_event(event){
let status = state.trigger_event(Event::Keyboard(key_event));
if let EventStatus::Ignored = status {
unsafe {
let superclass = msg_send![this, superclass];
let () = msg_send![super(this, superclass), $sel:event];
}
}
}
}
$class.add_method(
sel!($sel:),
$sel as extern "C" fn(&Object, Sel, id),
);
};
}
pub(super) unsafe fn create_view(
window_options: &WindowOpenOptions,
) -> id {
@ -97,55 +145,50 @@ unsafe fn create_view_class() -> &'static Class {
mouse_moved as extern "C" fn(&Object, Sel, id),
);
class.add_method(
sel!(mouseEntered:),
mouse_entered as extern "C" fn(&Object, Sel, id),
add_simple_mouse_class_method!(
class,
mouseDown,
ButtonPressed(MouseButton::Left)
);
add_simple_mouse_class_method!(
class,
mouseUp,
ButtonReleased(MouseButton::Left)
);
add_simple_mouse_class_method!(
class,
rightMouseDown,
ButtonPressed(MouseButton::Right)
);
add_simple_mouse_class_method!(
class,
rightMouseUp,
ButtonReleased(MouseButton::Right)
);
add_simple_mouse_class_method!(
class,
otherMouseDown,
ButtonPressed(MouseButton::Middle)
);
add_simple_mouse_class_method!(
class,
otherMouseUp,
ButtonReleased(MouseButton::Middle)
);
add_simple_mouse_class_method!(
class,
mouseEntered,
MouseEvent::CursorEntered
);
add_simple_mouse_class_method!(
class,
mouseExited,
MouseEvent::CursorLeft
);
class.add_method(
sel!(mouseExited:),
mouse_exited as extern "C" fn(&Object, Sel, id),
);
class.add_method(
sel!(mouseDown:),
left_mouse_down as extern "C" fn(&Object, Sel, id),
);
class.add_method(
sel!(mouseUp:),
left_mouse_up as extern "C" fn(&Object, Sel, id),
);
class.add_method(
sel!(rightMouseDown:),
right_mouse_down as extern "C" fn(&Object, Sel, id),
);
class.add_method(
sel!(rightMouseUp:),
right_mouse_up as extern "C" fn(&Object, Sel, id),
);
class.add_method(
sel!(otherMouseDown:),
middle_mouse_down as extern "C" fn(&Object, Sel, id),
);
class.add_method(
sel!(otherMouseUp:),
middle_mouse_up as extern "C" fn(&Object, Sel, id),
);
class.add_method(
sel!(keyDown:),
key_down as extern "C" fn(&Object, Sel, id),
);
class.add_method(
sel!(keyUp:),
key_up as extern "C" fn(&Object, Sel, id),
);
class.add_method(
sel!(flagsChanged:),
flags_changed as extern "C" fn(&Object, Sel, id),
);
add_simple_keyboard_class_method!(class, keyDown);
add_simple_keyboard_class_method!(class, keyUp);
add_simple_keyboard_class_method!(class, flagsChanged);
class.add_ivar::<*mut c_void>(BASEVIEW_STATE_IVAR);
@ -310,6 +353,10 @@ extern "C" fn mouse_moved(
_sel: Sel,
event: id
){
let state: &mut WindowState = unsafe {
WindowState::from_field(this)
};
let point: NSPoint = unsafe {
let point = NSEvent::locationInWindow(event);
@ -321,74 +368,7 @@ extern "C" fn mouse_moved(
y: point.y
};
let event = Event::Mouse(MouseEvent::CursorMoved { position });
let state: &mut WindowState = unsafe {
WindowState::from_field(this)
};
state.trigger_event(event);
state.trigger_event(
Event::Mouse(MouseEvent::CursorMoved { position })
);
}
macro_rules! mouse_simple_extern_fn {
($fn:ident, $event:expr) => {
extern "C" fn $fn(
this: &Object,
_sel: Sel,
_event: id,
){
let state: &mut WindowState = unsafe {
WindowState::from_field(this)
};
state.trigger_event(Event::Mouse($event));
}
};
}
mouse_simple_extern_fn!(left_mouse_down, ButtonPressed(MouseButton::Left));
mouse_simple_extern_fn!(left_mouse_up, ButtonReleased(MouseButton::Left));
mouse_simple_extern_fn!(right_mouse_down, ButtonPressed(MouseButton::Right));
mouse_simple_extern_fn!(right_mouse_up, ButtonReleased(MouseButton::Right));
mouse_simple_extern_fn!(middle_mouse_down, ButtonPressed(MouseButton::Middle));
mouse_simple_extern_fn!(middle_mouse_up, ButtonReleased(MouseButton::Middle));
mouse_simple_extern_fn!(mouse_entered, MouseEvent::CursorEntered);
mouse_simple_extern_fn!(mouse_exited, MouseEvent::CursorLeft);
extern "C" fn key_down(this: &Object, _: Sel, event: id){
let state: &mut WindowState = unsafe {
WindowState::from_field(this)
};
if let Some(key_event) = state.process_native_key_event(event){
state.trigger_event(Event::Keyboard(key_event));
}
}
extern "C" fn key_up(this: &Object, _: Sel, event: id){
let state: &mut WindowState = unsafe {
WindowState::from_field(this)
};
if let Some(key_event) = state.process_native_key_event(event){
state.trigger_event(Event::Keyboard(key_event));
}
}
extern "C" fn flags_changed(this: &Object, _: Sel, event: id){
let state: &mut WindowState = unsafe {
WindowState::from_field(this)
};
if let Some(key_event) = state.process_native_key_event(event){
state.trigger_event(Event::Keyboard(key_event));
}
}

View file

@ -17,7 +17,8 @@ use objc::{msg_send, runtime::Object, sel, sel_impl};
use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle};
use crate::{
Event, WindowHandler, WindowOpenOptions, WindowScalePolicy, WindowInfo,
Event, EventStatus, WindowHandler, WindowOpenOptions, WindowScalePolicy,
WindowInfo,
};
use super::view::{create_view, BASEVIEW_STATE_IVAR};
@ -217,9 +218,9 @@ impl WindowState {
&mut *(state_ptr as *mut Self)
}
pub(super) fn trigger_event(&mut self, event: Event) {
pub(super) fn trigger_event(&mut self, event: Event) -> EventStatus {
self.window_handler
.on_event(&mut crate::Window::new(&mut self.window), event);
.on_event(&mut crate::Window::new(&mut self.window), event)
}
pub(super) fn trigger_frame(&mut self) {

View file

@ -2,7 +2,7 @@ use std::marker::PhantomData;
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
use crate::event::Event;
use crate::event::{Event, EventStatus};
use crate::window_open_options::WindowOpenOptions;
#[cfg(target_os = "macos")]
@ -14,7 +14,7 @@ use crate::x11 as platform;
pub trait WindowHandler {
fn on_frame(&mut self, window: &mut Window);
fn on_event(&mut self, window: &mut Window, event: Event);
fn on_event(&mut self, window: &mut Window, event: Event) -> EventStatus;
}
pub struct Window<'a> {

View file

@ -251,7 +251,7 @@ impl Window {
handler.on_event(
&mut crate::Window::new(self),
Event::Window(WindowEvent::Resized(window_info))
)
);
}
}