Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions examples/open_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
}

Expand Down
26 changes: 24 additions & 2 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,39 @@ pub enum MouseEvent {
CursorLeft,
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum WindowEvent {
Resized(WindowInfo),
Focused,
Unfocused,
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,
}
202 changes: 91 additions & 111 deletions src/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
);

class.add_method(
sel!(mouseExited:),
mouse_exited as extern "C" fn(&Object, Sel, id),
add_simple_mouse_class_method!(
class,
mouseUp,
ButtonReleased(MouseButton::Left)
);

class.add_method(
sel!(mouseDown:),
left_mouse_down as extern "C" fn(&Object, Sel, id),
add_simple_mouse_class_method!(
class,
rightMouseDown,
ButtonPressed(MouseButton::Right)
);
class.add_method(
sel!(mouseUp:),
left_mouse_up as extern "C" fn(&Object, Sel, id),
add_simple_mouse_class_method!(
class,
rightMouseUp,
ButtonReleased(MouseButton::Right)
);

class.add_method(
sel!(rightMouseDown:),
right_mouse_down as extern "C" fn(&Object, Sel, id),
add_simple_mouse_class_method!(
class,
otherMouseDown,
ButtonPressed(MouseButton::Middle)
);
class.add_method(
sel!(rightMouseUp:),
right_mouse_up as extern "C" fn(&Object, Sel, id),
add_simple_mouse_class_method!(
class,
otherMouseUp,
ButtonReleased(MouseButton::Middle)
);

class.add_method(
sel!(otherMouseDown:),
middle_mouse_down as extern "C" fn(&Object, Sel, id),
add_simple_mouse_class_method!(
class,
mouseEntered,
MouseEvent::CursorEntered
);
class.add_method(
sel!(otherMouseUp:),
middle_mouse_up as extern "C" fn(&Object, Sel, id),
add_simple_mouse_class_method!(
class,
mouseExited,
MouseEvent::CursorLeft
);

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);

Expand Down Expand Up @@ -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);

Expand All @@ -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);
}


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));
}
state.trigger_event(
Event::Mouse(MouseEvent::CursorMoved { position })
);
}


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));
}
}
7 changes: 4 additions & 3 deletions src/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand All @@ -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> {
Expand Down
2 changes: 1 addition & 1 deletion src/x11/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ impl Window {
handler.on_event(
&mut crate::Window::new(self),
Event::Window(WindowEvent::Resized(window_info))
)
);
}
}

Expand Down