From b8bc006fc1a15e36e71dad377743be90d0161986 Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Fri, 11 Sep 2020 10:21:05 -0500 Subject: [PATCH 1/5] Add and refactor events --- examples/open_window.rs | 41 ++------------- src/event.rs | 107 ++++++++++++++++++++++++++++++++-------- src/keyboard.rs | 26 ++++++++++ src/lib.rs | 4 ++ src/macos/window.rs | 5 +- src/mouse_cursor.rs | 18 +++++++ src/win/window.rs | 5 +- src/x11/window.rs | 58 ++++++++++++++-------- 8 files changed, 184 insertions(+), 80 deletions(-) create mode 100644 src/keyboard.rs create mode 100644 src/mouse_cursor.rs diff --git a/examples/open_window.rs b/examples/open_window.rs index 1371354..77f39ef 100644 --- a/examples/open_window.rs +++ b/examples/open_window.rs @@ -24,42 +24,11 @@ impl WindowHandler for MyProgram { fn on_event(&mut self, window: &mut Window, event: Event) { match event { - Event::CursorMotion(x, y) => { - println!("Cursor moved, x: {}, y: {}", x, y); - } - Event::MouseDown(button_id) => { - println!("Mouse down, button id: {:?}", button_id); - } - Event::MouseUp(button_id) => { - println!("Mouse up, button id: {:?}", button_id); - } - Event::MouseScroll(mouse_scroll) => { - println!("Mouse scroll, {:?}", mouse_scroll); - } - Event::MouseClick(mouse_click) => { - println!("Mouse click, {:?}", mouse_click); - } - Event::KeyDown(keycode) => { - println!("Key down, keycode: {}", keycode); - } - Event::KeyUp(keycode) => { - println!("Key up, keycode: {}", keycode); - } - Event::CharacterInput(char_code) => { - println!("Character input, char_code: {}", char_code); - } - Event::WindowResized(window_info) => { - println!("Window resized, {:?}", window_info); - } - Event::WindowFocus => { - println!("Window focused"); - } - Event::WindowUnfocus => { - println!("Window unfocused"); - } - Event::WillClose => { - println!("Window will close"); - } + Event::Interval(delta_time) => println!("Update interval, delta time: {}", delta_time), + Event::Mouse(e) => println!("Mouse event: {:?}", e), + Event::Keyboard(e) => println!("Keyboard event: {:?}", e), + Event::Window(e) => println!("Window event: {:?}", e), + Event::FileDrop(e) => println!("File drop event: {:?}", e), } } diff --git a/src/event.rs b/src/event.rs index 95875c4..25296ce 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,5 +1,14 @@ +use std::path::PathBuf; + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum KeyboardEvent { + KeyPressed(u32), + KeyReleased(u32), + CharacterInput(char), +} + #[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum MouseButtonID { +pub enum MouseButton { Left, Middle, Right, @@ -8,39 +17,95 @@ pub enum MouseButtonID { Other(u8), } -#[derive(Debug, Copy, Clone)] -pub struct MouseScroll { - pub x_delta: f64, - pub y_delta: f64, +/// A scroll movement. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ScrollDelta { + /// A line-based scroll movement + Lines { + /// The number of horizontal lines scrolled + x: f32, + + /// The number of vertical lines scrolled + y: f32, + }, + /// A pixel-based scroll movement + Pixels { + /// The number of horizontal pixels scrolled + x: f32, + /// The number of vertical pixels scrolled + y: f32, + }, } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq)] pub struct MouseClick { - pub id: MouseButtonID, + pub button: MouseButton, pub click_count: usize, pub x: i32, pub y: i32, } -#[derive(Debug)] +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum MouseEvent { + /// The mouse cursor was moved + CursorMoved { + /// The X coordinate of the mouse position + x: i32, + /// The Y coordinate of the mouse position + y: i32, + }, + + /// A mouse button was pressed. + ButtonPressed(MouseButton), + + /// A mouse button was released. + ButtonReleased(MouseButton), + + /// A mouse button was clicked. + Click(MouseClick), + + /// The mouse wheel was scrolled. + WheelScrolled(ScrollDelta), + + /// The mouse cursor entered the window. + CursorEntered, + + /// The mouse cursor left the window. + CursorLeft, +} + +#[derive(Debug, Copy, Clone, PartialEq)] pub struct WindowInfo { pub width: u32, pub height: u32, - pub scale: f64, + pub scale_factor: f64, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum WindowEvent { + Resized(WindowInfo), + Focused, + Unfocused, + WillClose, +} + +#[derive(PartialEq, Clone, Debug)] +pub enum FileDropEvent { + /// A file is being hovered over the window. + FileHovered(PathBuf), + + /// A file has beend dropped into the window. + FileDropped(PathBuf), + + /// A file was hovered, but has exited the window. + FilesHoveredLeft, } #[derive(Debug)] pub enum Event { - CursorMotion(i32, i32), // new (x, y) relative to window - MouseDown(MouseButtonID), - MouseUp(MouseButtonID), - MouseScroll(MouseScroll), - MouseClick(MouseClick), - KeyDown(u8), // keycode - KeyUp(u8), // keycode - CharacterInput(u32), // character code - WindowResized(WindowInfo), // new (width, height) - WindowFocus, - WindowUnfocus, - WillClose, + Interval(f64), // delta time passed + Mouse(MouseEvent), + Keyboard(KeyboardEvent), + Window(WindowEvent), + FileDrop(FileDropEvent), } diff --git a/src/keyboard.rs b/src/keyboard.rs new file mode 100644 index 0000000..796bf7e --- /dev/null +++ b/src/keyboard.rs @@ -0,0 +1,26 @@ +// TODO: Add a method to the Window that returns the +// current modifier state. + +/// The current state of the keyboard modifiers. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub struct ModifiersState { + pub shift: bool, + pub control: bool, + pub alt: bool, + pub logo: bool, +} + +impl ModifiersState { + /// Returns true if the current [`ModifiersState`] has at least the same + /// modifiers enabled as the given value, and false otherwise. + /// + /// [`ModifiersState`]: struct.ModifiersState.html + pub fn matches_atleast(&self, modifiers: ModifiersState) -> bool { + let shift = !modifiers.shift || self.shift; + let control = !modifiers.control || self.control; + let alt = !modifiers.alt || self.alt; + let logo = !modifiers.logo || self.logo; + + shift && control && alt && logo + } +} diff --git a/src/lib.rs b/src/lib.rs index c4ed84f..d391d88 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,11 @@ mod macos; pub use macos::*; mod event; +mod keyboard; +mod mouse_cursor; pub use event::*; +pub use keyboard::*; +pub use mouse_cursor::MouseCursor; pub enum Parent { None, diff --git a/src/macos/window.rs b/src/macos/window.rs index 40c54b4..6ae0ae6 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -10,7 +10,10 @@ use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString}; use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle}; -use crate::{MouseScroll, WindowHandler, WindowOpenOptions}; +use crate::{ + Event, FileDropEvent, KeyboardEvent, MouseButton, MouseEvent, ScrollDelta, WindowEvent, + WindowHandler, WindowOpenOptions, +}; pub struct Window { ns_window: id, diff --git a/src/mouse_cursor.rs b/src/mouse_cursor.rs new file mode 100644 index 0000000..0fdcf78 --- /dev/null +++ b/src/mouse_cursor.rs @@ -0,0 +1,18 @@ +#[derive(Debug, Eq, PartialEq, Clone, Copy, PartialOrd, Ord)] +pub enum MouseCursor { + Idle, + Pointer, + Grab, + Text, + Crosshair, + Working, + Grabbing, + ResizingHorizontally, + ResizingVertically, +} + +impl Default for MouseCursor { + fn default() -> Self { + Self::Idle + } +} diff --git a/src/win/window.rs b/src/win/window.rs index e3b4cfa..04607df 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -18,7 +18,10 @@ use std::rc::Rc; use raw_window_handle::{windows::WindowsHandle, HasRawWindowHandle, RawWindowHandle}; -use crate::{Event, Parent::WithParent, WindowHandler, WindowInfo, WindowOpenOptions}; +use crate::{ + Event, FileDropEvent, KeyboardEvent, MouseButton, MouseEvent, Parent::WithParent, ScrollDelta, + WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, +}; unsafe fn message_box(title: &str, msg: &str) { let title = (title.to_owned() + "\0").as_ptr() as *const i8; diff --git a/src/x11/window.rs b/src/x11/window.rs index 2974de6..a5048ab 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -2,7 +2,10 @@ use std::ffi::CStr; use std::os::raw::{c_ulong, c_void}; use super::XcbConnection; -use crate::{Event, MouseButtonID, MouseScroll, Parent, WindowHandler, WindowOpenOptions}; +use crate::{ + Event, FileDropEvent, KeyboardEvent, MouseButton, MouseEvent, Parent, ScrollDelta, WindowEvent, + WindowHandler, WindowOpenOptions, +}; use raw_window_handle::{unix::XlibHandle, HasRawWindowHandle, RawWindowHandle}; @@ -157,7 +160,10 @@ fn run_event_loop(window: &mut Window, handler: &mut H) { if detail != 4 && detail != 5 { handler.on_event( window, - Event::CursorMotion(event.event_x() as i32, event.event_y() as i32), + Event::Mouse(MouseEvent::CursorMoved { + x: event.event_x() as i32, + y: event.event_y() as i32, + }), ); } } @@ -169,24 +175,27 @@ fn run_event_loop(window: &mut Window, handler: &mut H) { 4 => { handler.on_event( window, - Event::MouseScroll(MouseScroll { - x_delta: 0.0, - y_delta: 1.0, - }), + Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines { + x: 0.0, + y: 1.0, + })), ); } 5 => { handler.on_event( window, - Event::MouseScroll(MouseScroll { - x_delta: 0.0, - y_delta: -1.0, - }), + Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines { + x: 0.0, + y: -1.0, + })), ); } detail => { let button_id = mouse_id(detail); - handler.on_event(window, Event::MouseDown(button_id)); + handler.on_event( + window, + Event::Mouse(MouseEvent::ButtonPressed(button_id)), + ); } } } @@ -196,20 +205,27 @@ fn run_event_loop(window: &mut Window, handler: &mut H) { if detail != 4 && detail != 5 { let button_id = mouse_id(detail); - handler.on_event(window, Event::MouseUp(button_id)); + handler + .on_event(window, Event::Mouse(MouseEvent::ButtonReleased(button_id))); } } xcb::KEY_PRESS => { let event = unsafe { xcb::cast_event::(&event) }; let detail = event.detail(); - handler.on_event(window, Event::KeyDown(detail)); + handler.on_event( + window, + Event::Keyboard(KeyboardEvent::KeyPressed(detail as u32)), + ); } xcb::KEY_RELEASE => { let event = unsafe { xcb::cast_event::(&event) }; let detail = event.detail(); - handler.on_event(window, Event::KeyUp(detail)); + handler.on_event( + window, + Event::Keyboard(KeyboardEvent::KeyReleased(detail as u32)), + ); } _ => { println!("Unhandled event type: {:?}", event_type); @@ -300,13 +316,13 @@ fn get_scaling_screen_dimensions(xcb_connection: &XcbConnection) -> Option Some(yscale) } -fn mouse_id(id: u8) -> MouseButtonID { +fn mouse_id(id: u8) -> MouseButton { match id { - 1 => MouseButtonID::Left, - 2 => MouseButtonID::Middle, - 3 => MouseButtonID::Right, - 6 => MouseButtonID::Back, - 7 => MouseButtonID::Forward, - id => MouseButtonID::Other(id), + 1 => MouseButton::Left, + 2 => MouseButton::Middle, + 3 => MouseButton::Right, + 6 => MouseButton::Back, + 7 => MouseButton::Forward, + id => MouseButton::Other(id), } } From 83f2ffd27a64454e0032a3caf768550b1c78d2bb Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Fri, 11 Sep 2020 10:23:19 -0500 Subject: [PATCH 2/5] Rename scale_factor to scale --- src/event.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/event.rs b/src/event.rs index 25296ce..0e34836 100644 --- a/src/event.rs +++ b/src/event.rs @@ -78,7 +78,7 @@ pub enum MouseEvent { pub struct WindowInfo { pub width: u32, pub height: u32, - pub scale_factor: f64, + pub scale: f64, } #[derive(Debug, Clone, Copy, PartialEq)] From 9efade9a18d803e9c4f35517aed8a94df10c053b Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Fri, 11 Sep 2020 10:44:05 -0500 Subject: [PATCH 3/5] Fix Windows build --- src/win/window.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/win/window.rs b/src/win/window.rs index 04607df..944a012 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -77,10 +77,13 @@ unsafe extern "system" fn wnd_proc( WM_MOUSEMOVE => { let x = (lparam & 0xFFFF) as i32; let y = ((lparam >> 16) & 0xFFFF) as i32; - window_state - .borrow_mut() - .handler - .on_event(&mut window, Event::CursorMotion(x, y)); + window_state.borrow_mut().handler.on_event( + &mut window, + Event::Mouse(MouseEvent::CursorMoved { + x: x as i32, + y: y as i32, + }), + ); return 0; } WM_TIMER => { @@ -94,7 +97,7 @@ unsafe extern "system" fn wnd_proc( window_state .borrow_mut() .handler - .on_event(&mut window, Event::WillClose); + .on_event(&mut window, Event::Window(WindowEvent::WillClose)); return DefWindowProcA(hwnd, msg, wparam, lparam); } _ => {} From 52580cc2a90fac727ebdc38a635d082500c8ac85 Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Fri, 11 Sep 2020 11:43:46 -0500 Subject: [PATCH 4/5] rebase --- src/x11/window.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/x11/window.rs b/src/x11/window.rs index 3e1b3d2..dc28bc0 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -219,7 +219,7 @@ impl Window { let wm_delete_window = self.xcb_connection.atoms.wm_delete_window.unwrap_or(xcb::NONE); if wm_delete_window == data32[0] { - handler.on_event(self, Event::WillClose); + handler.on_event(self, Event::Window(WindowEvent::WillClose)); // FIXME: handler should decide whether window stays open or not self.event_loop_running = false; @@ -237,7 +237,7 @@ impl Window { if detail != 4 && detail != 5 { handler.on_event( self, - Event::CursorMotion(event.event_x() as i32, event.event_y() as i32), + Event::Mouse(MouseEvent::CursorMoved { x: event.event_x() as i32, y: event.event_y() as i32 }), ); } } @@ -250,24 +250,24 @@ impl Window { 4 => { handler.on_event( self, - Event::MouseScroll(MouseScroll { - x_delta: 0.0, - y_delta: 1.0, - }), + Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines { + x: 0.0, + y: 1.0, + })), ); } 5 => { handler.on_event( self, - Event::MouseScroll(MouseScroll { - x_delta: 0.0, - y_delta: -1.0, - }), + Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines { + x: 0.0, + y: -1.0, + })), ); } detail => { let button_id = mouse_id(detail); - handler.on_event(self, Event::MouseDown(button_id)); + handler.on_event(self, Event::Mouse(MouseEvent::ButtonPressed(button_id))); } } } @@ -278,7 +278,7 @@ impl Window { if detail != 4 && detail != 5 { let button_id = mouse_id(detail); - handler.on_event(self, Event::MouseUp(button_id)); + handler.on_event(self, Event::Mouse(MouseEvent::ButtonReleased(button_id))); } } @@ -290,14 +290,14 @@ impl Window { let event = unsafe { xcb::cast_event::(&event) }; let detail = event.detail(); - handler.on_event(self, Event::KeyDown(detail)); + handler.on_event(self, Event::Keyboard(KeyboardEvent::KeyPressed(detail as u32))); } xcb::KEY_RELEASE => { let event = unsafe { xcb::cast_event::(&event) }; let detail = event.detail(); - handler.on_event(self, Event::KeyUp(detail)); + handler.on_event(self, Event::Keyboard(KeyboardEvent::KeyReleased(detail as u32))); } _ => { From e67887d92f153f47c8a99442a6d0656bbc656014 Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Fri, 11 Sep 2020 11:49:56 -0500 Subject: [PATCH 5/5] Remove Interval event --- examples/open_window.rs | 1 - src/event.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/examples/open_window.rs b/examples/open_window.rs index 8b1197c..04e2b73 100644 --- a/examples/open_window.rs +++ b/examples/open_window.rs @@ -24,7 +24,6 @@ impl WindowHandler for MyProgram { fn on_event(&mut self, window: &mut Window, event: Event) { match event { - Event::Interval(delta_time) => println!("Update interval, delta time: {}", delta_time), Event::Mouse(e) => println!("Mouse event: {:?}", e), Event::Keyboard(e) => println!("Keyboard event: {:?}", e), Event::Window(e) => println!("Window event: {:?}", e), diff --git a/src/event.rs b/src/event.rs index 0e34836..d03cedf 100644 --- a/src/event.rs +++ b/src/event.rs @@ -103,7 +103,6 @@ pub enum FileDropEvent { #[derive(Debug)] pub enum Event { - Interval(f64), // delta time passed Mouse(MouseEvent), Keyboard(KeyboardEvent), Window(WindowEvent),