Skip to content

Commit 72b6a4a

Browse files
authored
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
1 parent 663f9d5 commit 72b6a4a

6 files changed

Lines changed: 126 additions & 121 deletions

File tree

examples/open_window.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::time::Duration;
22

33
use rtrb::{RingBuffer, Consumer};
44

5-
use baseview::{Event, Window, WindowHandler, WindowScalePolicy};
5+
use baseview::{Event, EventStatus, Window, WindowHandler, WindowScalePolicy};
66

77
#[derive(Debug, Clone)]
88
enum Message {
@@ -20,12 +20,14 @@ impl WindowHandler for OpenWindowExample {
2020
}
2121
}
2222

23-
fn on_event(&mut self, _window: &mut Window, event: Event) {
23+
fn on_event(&mut self, _window: &mut Window, event: Event) -> EventStatus {
2424
match event {
2525
Event::Mouse(e) => println!("Mouse event: {:?}", e),
2626
Event::Keyboard(e) => println!("Keyboard event: {:?}", e),
2727
Event::Window(e) => println!("Window event: {:?}", e),
2828
}
29+
30+
EventStatus::Captured
2931
}
3032
}
3133

src/event.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,39 @@ pub enum MouseEvent {
6868
CursorLeft,
6969
}
7070

71-
#[derive(Debug)]
71+
#[derive(Debug, Clone)]
7272
pub enum WindowEvent {
7373
Resized(WindowInfo),
7474
Focused,
7575
Unfocused,
7676
WillClose,
7777
}
7878

79-
#[derive(Debug)]
79+
#[derive(Debug, Clone)]
8080
pub enum Event {
8181
Mouse(MouseEvent),
8282
Keyboard(KeyboardEvent),
8383
Window(WindowEvent),
8484
}
85+
86+
87+
/// Return value for [WindowHandler::on_event](`crate::WindowHandler::on_event()`),
88+
/// indicating whether the event was handled by your window or should be passed
89+
/// back to the platform.
90+
///
91+
/// For most event types, this value won't have any effect. This is the case
92+
/// when there is no clear meaning of passing back the event to the platform,
93+
/// or it isn't obviously useful. Currently, only [`Event::Keyboard`] variants
94+
/// are supported.
95+
#[derive(Debug)]
96+
pub enum EventStatus {
97+
/// Event was handled by your window and will not be sent back to the
98+
/// platform for further processing.
99+
Captured,
100+
/// Event was **not** handled by your window, so pass it back to the
101+
/// platform. For parented windows, this usually means that the parent
102+
/// window will receive the event. This is useful for cases such as using
103+
/// DAW functionality for playing piano keys with the keyboard while a
104+
/// plugin window is in focus.
105+
Ignored,
106+
}

src/macos/view.rs

Lines changed: 91 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use objc::{
1313
};
1414
use uuid::Uuid;
1515

16-
use crate::{Event, MouseButton, MouseEvent, Point, WindowOpenOptions};
16+
use crate::{Event, EventStatus, MouseButton, MouseEvent, Point, WindowOpenOptions};
1717
use crate::MouseEvent::{ButtonPressed, ButtonReleased};
1818

1919
use super::window::WindowState;
@@ -23,6 +23,54 @@ use super::window::WindowState;
2323
pub(super) const BASEVIEW_STATE_IVAR: &str = "baseview_state";
2424

2525

26+
macro_rules! add_simple_mouse_class_method {
27+
($class:ident, $sel:ident, $event:expr) => {
28+
#[allow(non_snake_case)]
29+
extern "C" fn $sel(this: &Object, _: Sel, _: id){
30+
let state: &mut WindowState = unsafe {
31+
WindowState::from_field(this)
32+
};
33+
34+
state.trigger_event(Event::Mouse($event));
35+
}
36+
37+
$class.add_method(
38+
sel!($sel:),
39+
$sel as extern "C" fn(&Object, Sel, id),
40+
);
41+
};
42+
}
43+
44+
45+
macro_rules! add_simple_keyboard_class_method {
46+
($class:ident, $sel:ident) => {
47+
#[allow(non_snake_case)]
48+
extern "C" fn $sel(this: &Object, _: Sel, event: id){
49+
let state: &mut WindowState = unsafe {
50+
WindowState::from_field(this)
51+
};
52+
53+
if let Some(key_event) = state.process_native_key_event(event){
54+
let status = state.trigger_event(Event::Keyboard(key_event));
55+
56+
if let EventStatus::Ignored = status {
57+
unsafe {
58+
let superclass = msg_send![this, superclass];
59+
60+
let () = msg_send![super(this, superclass), $sel:event];
61+
}
62+
}
63+
}
64+
}
65+
66+
$class.add_method(
67+
sel!($sel:),
68+
$sel as extern "C" fn(&Object, Sel, id),
69+
);
70+
};
71+
}
72+
73+
2674
pub(super) unsafe fn create_view(
2775
window_options: &WindowOpenOptions,
2876
) -> id {
@@ -97,55 +145,50 @@ unsafe fn create_view_class() -> &'static Class {
97145
mouse_moved as extern "C" fn(&Object, Sel, id),
98146
);
99147

100-
class.add_method(
101-
sel!(mouseEntered:),
102-
mouse_entered as extern "C" fn(&Object, Sel, id),
148+
add_simple_mouse_class_method!(
149+
class,
150+
mouseDown,
151+
ButtonPressed(MouseButton::Left)
103152
);
104-
105-
class.add_method(
106-
sel!(mouseExited:),
107-
mouse_exited as extern "C" fn(&Object, Sel, id),
153+
add_simple_mouse_class_method!(
154+
class,
155+
mouseUp,
156+
ButtonReleased(MouseButton::Left)
108157
);
109-
110-
class.add_method(
111-
sel!(mouseDown:),
112-
left_mouse_down as extern "C" fn(&Object, Sel, id),
158+
add_simple_mouse_class_method!(
159+
class,
160+
rightMouseDown,
161+
ButtonPressed(MouseButton::Right)
113162
);
114-
class.add_method(
115-
sel!(mouseUp:),
116-
left_mouse_up as extern "C" fn(&Object, Sel, id),
163+
add_simple_mouse_class_method!(
164+
class,
165+
rightMouseUp,
166+
ButtonReleased(MouseButton::Right)
117167
);
118-
119-
class.add_method(
120-
sel!(rightMouseDown:),
121-
right_mouse_down as extern "C" fn(&Object, Sel, id),
168+
add_simple_mouse_class_method!(
169+
class,
170+
otherMouseDown,
171+
ButtonPressed(MouseButton::Middle)
122172
);
123-
class.add_method(
124-
sel!(rightMouseUp:),
125-
right_mouse_up as extern "C" fn(&Object, Sel, id),
173+
add_simple_mouse_class_method!(
174+
class,
175+
otherMouseUp,
176+
ButtonReleased(MouseButton::Middle)
126177
);
127-
128-
class.add_method(
129-
sel!(otherMouseDown:),
130-
middle_mouse_down as extern "C" fn(&Object, Sel, id),
178+
add_simple_mouse_class_method!(
179+
class,
180+
mouseEntered,
181+
MouseEvent::CursorEntered
131182
);
132-
class.add_method(
133-
sel!(otherMouseUp:),
134-
middle_mouse_up as extern "C" fn(&Object, Sel, id),
183+
add_simple_mouse_class_method!(
184+
class,
185+
mouseExited,
186+
MouseEvent::CursorLeft
135187
);
136188

137-
class.add_method(
138-
sel!(keyDown:),
139-
key_down as extern "C" fn(&Object, Sel, id),
140-
);
141-
class.add_method(
142-
sel!(keyUp:),
143-
key_up as extern "C" fn(&Object, Sel, id),
144-
);
145-
class.add_method(
146-
sel!(flagsChanged:),
147-
flags_changed as extern "C" fn(&Object, Sel, id),
148-
);
189+
add_simple_keyboard_class_method!(class, keyDown);
190+
add_simple_keyboard_class_method!(class, keyUp);
191+
add_simple_keyboard_class_method!(class, flagsChanged);
149192

150193
class.add_ivar::<*mut c_void>(BASEVIEW_STATE_IVAR);
151194

@@ -310,6 +353,10 @@ extern "C" fn mouse_moved(
310353
_sel: Sel,
311354
event: id
312355
){
356+
let state: &mut WindowState = unsafe {
357+
WindowState::from_field(this)
358+
};
359+
313360
let point: NSPoint = unsafe {
314361
let point = NSEvent::locationInWindow(event);
315362

@@ -321,74 +368,7 @@ extern "C" fn mouse_moved(
321368
y: point.y
322369
};
323370

324-
let event = Event::Mouse(MouseEvent::CursorMoved { position });
325-
326-
let state: &mut WindowState = unsafe {
327-
WindowState::from_field(this)
328-
};
329-
330-
state.trigger_event(event);
331-
}
332-
333-
334-
macro_rules! mouse_simple_extern_fn {
335-
($fn:ident, $event:expr) => {
336-
extern "C" fn $fn(
337-
this: &Object,
338-
_sel: Sel,
339-
_event: id,
340-
){
341-
let state: &mut WindowState = unsafe {
342-
WindowState::from_field(this)
343-
};
344-
345-
state.trigger_event(Event::Mouse($event));
346-
}
347-
};
348-
}
349-
350-
351-
mouse_simple_extern_fn!(left_mouse_down, ButtonPressed(MouseButton::Left));
352-
mouse_simple_extern_fn!(left_mouse_up, ButtonReleased(MouseButton::Left));
353-
354-
mouse_simple_extern_fn!(right_mouse_down, ButtonPressed(MouseButton::Right));
355-
mouse_simple_extern_fn!(right_mouse_up, ButtonReleased(MouseButton::Right));
356-
357-
mouse_simple_extern_fn!(middle_mouse_down, ButtonPressed(MouseButton::Middle));
358-
mouse_simple_extern_fn!(middle_mouse_up, ButtonReleased(MouseButton::Middle));
359-
360-
mouse_simple_extern_fn!(mouse_entered, MouseEvent::CursorEntered);
361-
mouse_simple_extern_fn!(mouse_exited, MouseEvent::CursorLeft);
362-
363-
364-
extern "C" fn key_down(this: &Object, _: Sel, event: id){
365-
let state: &mut WindowState = unsafe {
366-
WindowState::from_field(this)
367-
};
368-
369-
if let Some(key_event) = state.process_native_key_event(event){
370-
state.trigger_event(Event::Keyboard(key_event));
371-
}
372-
}
373-
374-
375-
extern "C" fn key_up(this: &Object, _: Sel, event: id){
376-
let state: &mut WindowState = unsafe {
377-
WindowState::from_field(this)
378-
};
379-
380-
if let Some(key_event) = state.process_native_key_event(event){
381-
state.trigger_event(Event::Keyboard(key_event));
382-
}
371+
state.trigger_event(
372+
Event::Mouse(MouseEvent::CursorMoved { position })
373+
);
383374
}
384-
385-
386-
extern "C" fn flags_changed(this: &Object, _: Sel, event: id){
387-
let state: &mut WindowState = unsafe {
388-
WindowState::from_field(this)
389-
};
390-
391-
if let Some(key_event) = state.process_native_key_event(event){
392-
state.trigger_event(Event::Keyboard(key_event));
393-
}
394-
}

src/macos/window.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use objc::{msg_send, runtime::Object, sel, sel_impl};
1717
use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle};
1818

1919
use crate::{
20-
Event, WindowHandler, WindowOpenOptions, WindowScalePolicy, WindowInfo,
20+
Event, EventStatus, WindowHandler, WindowOpenOptions, WindowScalePolicy,
21+
WindowInfo,
2122
};
2223

2324
use super::view::{create_view, BASEVIEW_STATE_IVAR};
@@ -217,9 +218,9 @@ impl WindowState {
217218
&mut *(state_ptr as *mut Self)
218219
}
219220

220-
pub(super) fn trigger_event(&mut self, event: Event) {
221+
pub(super) fn trigger_event(&mut self, event: Event) -> EventStatus {
221222
self.window_handler
222-
.on_event(&mut crate::Window::new(&mut self.window), event);
223+
.on_event(&mut crate::Window::new(&mut self.window), event)
223224
}
224225

225226
pub(super) fn trigger_frame(&mut self) {

src/window.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::marker::PhantomData;
22

33
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
44

5-
use crate::event::Event;
5+
use crate::event::{Event, EventStatus};
66
use crate::window_open_options::WindowOpenOptions;
77

88
#[cfg(target_os = "macos")]
@@ -14,7 +14,7 @@ use crate::x11 as platform;
1414

1515
pub trait WindowHandler {
1616
fn on_frame(&mut self, window: &mut Window);
17-
fn on_event(&mut self, window: &mut Window, event: Event);
17+
fn on_event(&mut self, window: &mut Window, event: Event) -> EventStatus;
1818
}
1919

2020
pub struct Window<'a> {

src/x11/window.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ impl Window {
251251
handler.on_event(
252252
&mut crate::Window::new(self),
253253
Event::Window(WindowEvent::Resized(window_info))
254-
)
254+
);
255255
}
256256
}
257257

0 commit comments

Comments
 (0)