From 80bc5a0d1ba141966bb35856533c397600f382ea Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Wed, 17 Feb 2021 23:31:49 +0900 Subject: [PATCH 1/8] Add wrapper for event watch --- src/sdl2/event.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index 09ddb782bcd..9cddd982022 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -28,6 +28,7 @@ use crate::mouse; use crate::mouse::{MouseButton, MouseState, MouseWheelDirection}; use crate::sys; +use crate::sys::SDL_EventFilter; use crate::sys::SDL_EventType; struct CustomEventTypeMaps { @@ -231,6 +232,13 @@ impl crate::EventSubsystem { pub fn event_sender(&self) -> EventSender { EventSender { _priv: () } } + + pub fn add_event_watch<'a, F: FnMut(Event) -> () + 'a>( + &self, + callback: F, + ) -> EventWatch<'a, F> { + EventWatch::add(callback) + } } /// Types of events that can be delivered. @@ -2894,3 +2902,40 @@ impl EventSender { Ok(()) } } + +pub struct EventWatch<'a, F: FnMut(Event) -> () + 'a>(Box, PhantomData<&'a F>); + +impl<'a, F: FnMut(Event) -> () + 'a> EventWatch<'a, F> { + pub fn add(f: F) -> EventWatch<'a, F> { + let f = Box::new(f); + let mut watch = EventWatch(f, PhantomData); + unsafe { sys::SDL_AddEventWatch(watch.filter(), watch.callback()) }; + println!("Added"); + watch + } + + fn filter(&self) -> SDL_EventFilter { + Some(event_callback_marshall:: as _) + } + + fn callback(&mut self) -> *mut c_void { + &mut *self.0 as *mut _ as *mut c_void + } +} + +impl<'a, F: FnMut(Event) -> () + 'a> Drop for EventWatch<'a, F> { + fn drop(&mut self) { + unsafe { sys::SDL_DelEventWatch(self.filter(), self.callback()) }; + println!("Deleted"); + } +} + +extern "C" fn event_callback_marshall ()>( + user_data: *mut c_void, + event: *mut sdl2_sys::SDL_Event, +) -> i32 { + let f: &mut F = unsafe { &mut *(user_data as *mut _) }; + let event = Event::from_ll(unsafe { *event }); + f(event); + 0 +} From 13fac9a2f9a3eced007dd8d9ddbed210f27298ce Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Wed, 17 Feb 2021 23:40:32 +0900 Subject: [PATCH 2/8] Add documentation for add_event_watch --- src/sdl2/event.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index 9cddd982022..939cfd46ccd 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -233,6 +233,19 @@ impl crate::EventSubsystem { EventSender { _priv: () } } + /// Create an event watcher which is called every time an event is added to event queue. + /// + /// The watcher is disabled when the return value is dropped. + /// Just calling this function without binding to a variable immediately disables the watcher. + /// In order to make it persistent, you have to bind in a variable and keep it until it's no + /// longer needed. + /// + /// # Example: dump every event to stderr + /// ``` + /// let _event_watch = event_subsystem.add_event_watch(|event| { + /// dbg!(event); + /// }); + /// ``` pub fn add_event_watch<'a, F: FnMut(Event) -> () + 'a>( &self, callback: F, From 328f334edcda34cc1404b173868071a889bada4e Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Thu, 18 Feb 2021 00:11:03 +0900 Subject: [PATCH 3/8] Remove unnecessary comment --- src/sdl2/event.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index 939cfd46ccd..3cdead58915 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -2923,7 +2923,6 @@ impl<'a, F: FnMut(Event) -> () + 'a> EventWatch<'a, F> { let f = Box::new(f); let mut watch = EventWatch(f, PhantomData); unsafe { sys::SDL_AddEventWatch(watch.filter(), watch.callback()) }; - println!("Added"); watch } @@ -2939,7 +2938,6 @@ impl<'a, F: FnMut(Event) -> () + 'a> EventWatch<'a, F> { impl<'a, F: FnMut(Event) -> () + 'a> Drop for EventWatch<'a, F> { fn drop(&mut self) { unsafe { sys::SDL_DelEventWatch(self.filter(), self.callback()) }; - println!("Deleted"); } } From 911fea4d3bba4ead3ffc6d7e61c290856a19aa24 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Thu, 18 Feb 2021 00:11:22 +0900 Subject: [PATCH 4/8] Make sample code complete --- src/sdl2/event.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index 3cdead58915..e0a594b7e99 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -242,7 +242,11 @@ impl crate::EventSubsystem { /// /// # Example: dump every event to stderr /// ``` - /// let _event_watch = event_subsystem.add_event_watch(|event| { + /// let sdl = sdl2::init().unwrap(); + /// let ev = sdl.event().unwrap(); + /// + /// // `let _ = ...` is insufficient, as it is dropped immediately. + /// let _event_watch = ev.add_event_watch(|event| { /// dbg!(event); /// }); /// ``` From a3de1d1791f33a3a9d7d79183a67a76d2813f50f Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Thu, 18 Feb 2021 00:39:34 +0900 Subject: [PATCH 5/8] Add document & correct visibility for EventWatch --- src/sdl2/event.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index e0a594b7e99..d73545dfce2 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -2920,10 +2920,12 @@ impl EventSender { } } +/// An handler for the event watch callback. +/// One must bind this struct in a variable as long as you want to keep the callback active. pub struct EventWatch<'a, F: FnMut(Event) -> () + 'a>(Box, PhantomData<&'a F>); impl<'a, F: FnMut(Event) -> () + 'a> EventWatch<'a, F> { - pub fn add(f: F) -> EventWatch<'a, F> { + fn add(f: F) -> EventWatch<'a, F> { let f = Box::new(f); let mut watch = EventWatch(f, PhantomData); unsafe { sys::SDL_AddEventWatch(watch.filter(), watch.callback()) }; From 5182dc9de0c41b9664da06929b9b64c632cd9fde Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Thu, 18 Feb 2021 22:08:09 +0900 Subject: [PATCH 6/8] Enable event watch (de)activation. --- src/sdl2/event.rs | 51 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index d73545dfce2..64b09049ccc 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -2922,28 +2922,69 @@ impl EventSender { /// An handler for the event watch callback. /// One must bind this struct in a variable as long as you want to keep the callback active. -pub struct EventWatch<'a, F: FnMut(Event) -> () + 'a>(Box, PhantomData<&'a F>); +/// For further information, see [`EventSubsystem::add_event_watch`]. +pub struct EventWatch<'a, F: FnMut(Event) -> () + 'a> { + activated: bool, + callback: Box, + _phantom: PhantomData<&'a F>, +} impl<'a, F: FnMut(Event) -> () + 'a> EventWatch<'a, F> { fn add(f: F) -> EventWatch<'a, F> { let f = Box::new(f); - let mut watch = EventWatch(f, PhantomData); - unsafe { sys::SDL_AddEventWatch(watch.filter(), watch.callback()) }; + let mut watch = EventWatch { + activated: false, + callback: f, + _phantom: PhantomData, + }; + watch.activate(); watch } + /// Activates the event watch. + /// Does nothing if it is already activated. + pub fn activate(&mut self) { + if !self.activated { + self.activated = true; + unsafe { sys::SDL_AddEventWatch(self.filter(), self.callback()) }; + } + } + + /// Deactivates the event watch. + /// Does nothing if it is already activated. + pub fn deactivate(&mut self) { + if self.activated { + self.activated = false; + unsafe { sys::SDL_DelEventWatch(self.filter(), self.callback()) }; + } + } + + /// Returns if the event watch is activated. + pub fn activated(&self) -> bool { + self.activated + } + + /// Set the activation state of the event watch. + pub fn set_activated(&mut self, activate: bool) { + if activate { + self.activate(); + } else { + self.deactivate(); + } + } + fn filter(&self) -> SDL_EventFilter { Some(event_callback_marshall:: as _) } fn callback(&mut self) -> *mut c_void { - &mut *self.0 as *mut _ as *mut c_void + &mut *self.callback as *mut _ as *mut c_void } } impl<'a, F: FnMut(Event) -> () + 'a> Drop for EventWatch<'a, F> { fn drop(&mut self) { - unsafe { sys::SDL_DelEventWatch(self.filter(), self.callback()) }; + self.deactivate(); } } From 97c611ce050ac81fe085931d8316825edf405ffc Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Fri, 19 Feb 2021 10:56:54 +0900 Subject: [PATCH 7/8] Change closure -> trait --- src/sdl2/event.rs | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index 64b09049ccc..e2b5684081b 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -242,18 +242,24 @@ impl crate::EventSubsystem { /// /// # Example: dump every event to stderr /// ``` + /// use sdl2::event::{Event, EventWatchCallback}; /// let sdl = sdl2::init().unwrap(); /// let ev = sdl.event().unwrap(); /// + /// struct Callback; + /// impl EventWatchCallback for Callback { + /// fn callback(&mut self, event: Event) { + /// dbg!(event); + /// } + /// } + /// /// // `let _ = ...` is insufficient, as it is dropped immediately. - /// let _event_watch = ev.add_event_watch(|event| { - /// dbg!(event); - /// }); + /// let _event_watch = ev.add_event_watch(Callback); /// ``` - pub fn add_event_watch<'a, F: FnMut(Event) -> () + 'a>( + pub fn add_event_watch<'a, CB: EventWatchCallback + 'a>( &self, - callback: F, - ) -> EventWatch<'a, F> { + callback: CB, + ) -> EventWatch<'a, CB> { EventWatch::add(callback) } } @@ -2920,18 +2926,23 @@ impl EventSender { } } +/// A callback trait for [`EventSubsystem::add_event_watch`]. +pub trait EventWatchCallback { + fn callback(&mut self, event: Event) -> (); +} + /// An handler for the event watch callback. /// One must bind this struct in a variable as long as you want to keep the callback active. /// For further information, see [`EventSubsystem::add_event_watch`]. -pub struct EventWatch<'a, F: FnMut(Event) -> () + 'a> { +pub struct EventWatch<'a, CB: EventWatchCallback + 'a> { activated: bool, - callback: Box, - _phantom: PhantomData<&'a F>, + callback: Box, + _phantom: PhantomData<&'a CB>, } -impl<'a, F: FnMut(Event) -> () + 'a> EventWatch<'a, F> { - fn add(f: F) -> EventWatch<'a, F> { - let f = Box::new(f); +impl<'a, CB: EventWatchCallback + 'a> EventWatch<'a, CB> { + fn add(callback: CB) -> EventWatch<'a, CB> { + let f = Box::new(callback); let mut watch = EventWatch { activated: false, callback: f, @@ -2974,7 +2985,7 @@ impl<'a, F: FnMut(Event) -> () + 'a> EventWatch<'a, F> { } fn filter(&self) -> SDL_EventFilter { - Some(event_callback_marshall:: as _) + Some(event_callback_marshall:: as _) } fn callback(&mut self) -> *mut c_void { @@ -2982,18 +2993,18 @@ impl<'a, F: FnMut(Event) -> () + 'a> EventWatch<'a, F> { } } -impl<'a, F: FnMut(Event) -> () + 'a> Drop for EventWatch<'a, F> { +impl<'a, CB: EventWatchCallback + 'a> Drop for EventWatch<'a, CB> { fn drop(&mut self) { self.deactivate(); } } -extern "C" fn event_callback_marshall ()>( +extern "C" fn event_callback_marshall( user_data: *mut c_void, event: *mut sdl2_sys::SDL_Event, ) -> i32 { - let f: &mut F = unsafe { &mut *(user_data as *mut _) }; + let f: &mut CB = unsafe { &mut *(user_data as *mut _) }; let event = Event::from_ll(unsafe { *event }); - f(event); + f.callback(event); 0 } From c47d8f5cd98dc0f2a37cf5b433afee5d72445d4a Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 20 Feb 2021 00:29:22 +0900 Subject: [PATCH 8/8] Implement EventWatchCallback for closure type --- src/sdl2/event.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index e2b5684081b..bf03c97b908 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -242,19 +242,13 @@ impl crate::EventSubsystem { /// /// # Example: dump every event to stderr /// ``` - /// use sdl2::event::{Event, EventWatchCallback}; /// let sdl = sdl2::init().unwrap(); /// let ev = sdl.event().unwrap(); /// - /// struct Callback; - /// impl EventWatchCallback for Callback { - /// fn callback(&mut self, event: Event) { - /// dbg!(event); - /// } - /// } - /// /// // `let _ = ...` is insufficient, as it is dropped immediately. - /// let _event_watch = ev.add_event_watch(Callback); + /// let _event_watch = ev.add_event_watch(|event| { + /// dbg!(event); + /// }); /// ``` pub fn add_event_watch<'a, CB: EventWatchCallback + 'a>( &self, @@ -3008,3 +3002,9 @@ extern "C" fn event_callback_marshall( f.callback(event); 0 } + +impl ()> EventWatchCallback for F { + fn callback(&mut self, event: Event) -> () { + self(event) + } +}