@@ -5,8 +5,11 @@ use wasm_bindgen::prelude::*;
5
5
use wasm_bindgen:: JsCast ;
6
6
use web_sys:: { window, Gamepad , GamepadButton , KeyboardEvent } ;
7
7
8
- use std:: collections:: hash_map:: { Entry , HashMap } ;
9
- use std:: sync:: { Arc , Mutex } ;
8
+ use std:: {
9
+ cell:: Cell ,
10
+ collections:: hash_map:: { Entry , HashMap } ,
11
+ sync:: { Arc , Mutex } ,
12
+ } ;
10
13
11
14
#[ derive( Debug , snafu:: Snafu ) ]
12
15
pub enum Error {
@@ -20,8 +23,8 @@ pub type Result<T> = std::result::Result<T, Error>;
20
23
pub struct Hook {
21
24
hotkeys : Arc < Mutex < HashMap < KeyCode , Box < dyn FnMut ( ) + Send + ' static > > > > ,
22
25
keyboard_callback : Closure < dyn FnMut ( KeyboardEvent ) > ,
23
- _gamepad_callback : Closure < dyn FnMut ( ) > ,
24
- interval_id : i32 ,
26
+ gamepad_callback : Closure < dyn FnMut ( ) > ,
27
+ interval_id : Cell < Option < i32 > > ,
25
28
}
26
29
27
30
impl Drop for Hook {
@@ -31,11 +34,37 @@ impl Drop for Hook {
31
34
"keypress" ,
32
35
self . keyboard_callback . as_ref ( ) . unchecked_ref ( ) ,
33
36
) ;
34
- window. clear_interval_with_handle ( self . interval_id ) ;
37
+ if let Some ( interval_id) = self . interval_id . get ( ) {
38
+ window. clear_interval_with_handle ( interval_id) ;
39
+ }
35
40
}
36
41
}
37
42
}
38
43
44
+ const TOTAL_BUTTONS : usize = 20 ;
45
+ static GAMEPAD_BUTTONS : [ KeyCode ; TOTAL_BUTTONS ] = [
46
+ KeyCode :: Gamepad0 ,
47
+ KeyCode :: Gamepad1 ,
48
+ KeyCode :: Gamepad2 ,
49
+ KeyCode :: Gamepad3 ,
50
+ KeyCode :: Gamepad4 ,
51
+ KeyCode :: Gamepad5 ,
52
+ KeyCode :: Gamepad6 ,
53
+ KeyCode :: Gamepad7 ,
54
+ KeyCode :: Gamepad8 ,
55
+ KeyCode :: Gamepad9 ,
56
+ KeyCode :: Gamepad10 ,
57
+ KeyCode :: Gamepad11 ,
58
+ KeyCode :: Gamepad12 ,
59
+ KeyCode :: Gamepad13 ,
60
+ KeyCode :: Gamepad14 ,
61
+ KeyCode :: Gamepad15 ,
62
+ KeyCode :: Gamepad16 ,
63
+ KeyCode :: Gamepad17 ,
64
+ KeyCode :: Gamepad18 ,
65
+ KeyCode :: Gamepad19 ,
66
+ ] ;
67
+
39
68
impl Hook {
40
69
pub fn new ( ) -> Result < Self > {
41
70
let hotkeys = Arc :: new ( Mutex :: new ( HashMap :: <
@@ -63,29 +92,6 @@ impl Hook {
63
92
64
93
let hotkey_map = hotkeys. clone ( ) ;
65
94
66
- const TOTAL_BUTTONS : usize = 20 ;
67
- static GAMEPAD_BUTTONS : [ KeyCode ; TOTAL_BUTTONS ] = [
68
- KeyCode :: Gamepad0 ,
69
- KeyCode :: Gamepad1 ,
70
- KeyCode :: Gamepad2 ,
71
- KeyCode :: Gamepad3 ,
72
- KeyCode :: Gamepad4 ,
73
- KeyCode :: Gamepad5 ,
74
- KeyCode :: Gamepad6 ,
75
- KeyCode :: Gamepad7 ,
76
- KeyCode :: Gamepad8 ,
77
- KeyCode :: Gamepad9 ,
78
- KeyCode :: Gamepad10 ,
79
- KeyCode :: Gamepad11 ,
80
- KeyCode :: Gamepad12 ,
81
- KeyCode :: Gamepad13 ,
82
- KeyCode :: Gamepad14 ,
83
- KeyCode :: Gamepad15 ,
84
- KeyCode :: Gamepad16 ,
85
- KeyCode :: Gamepad17 ,
86
- KeyCode :: Gamepad18 ,
87
- KeyCode :: Gamepad19 ,
88
- ] ;
89
95
let mut states = Vec :: new ( ) ;
90
96
let navigator = window. navigator ( ) ;
91
97
@@ -120,18 +126,11 @@ impl Hook {
120
126
}
121
127
} ) as Box < dyn FnMut ( ) > ) ;
122
128
123
- let interval_id = window
124
- . set_interval_with_callback_and_timeout_and_arguments_0 (
125
- gamepad_callback. as_ref ( ) . unchecked_ref ( ) ,
126
- 1000 / 60 ,
127
- )
128
- . map_err ( |_| Error :: FailedToCreateHook ) ?;
129
-
130
129
Ok ( Hook {
131
130
hotkeys,
132
131
keyboard_callback,
133
- _gamepad_callback : gamepad_callback,
134
- interval_id,
132
+ gamepad_callback,
133
+ interval_id : Cell :: new ( None ) ,
135
134
} )
136
135
}
137
136
@@ -140,6 +139,16 @@ impl Hook {
140
139
F : FnMut ( ) + Send + ' static ,
141
140
{
142
141
if let Entry :: Vacant ( vacant) = self . hotkeys . lock ( ) . unwrap ( ) . entry ( hotkey) {
142
+ if GAMEPAD_BUTTONS . contains ( & hotkey) && self . interval_id . get ( ) . is_none ( ) {
143
+ let interval_id = window ( )
144
+ . ok_or ( Error :: FailedToCreateHook ) ?
145
+ . set_interval_with_callback_and_timeout_and_arguments_0 (
146
+ self . gamepad_callback . as_ref ( ) . unchecked_ref ( ) ,
147
+ 1000 / 60 ,
148
+ )
149
+ . map_err ( |_| Error :: FailedToCreateHook ) ?;
150
+ self . interval_id . set ( Some ( interval_id) ) ;
151
+ }
143
152
vacant. insert ( Box :: new ( callback) ) ;
144
153
Ok ( ( ) )
145
154
} else {
0 commit comments