Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul device events API and add gamepad support on Windows #804

Merged
merged 39 commits into from
Jun 20, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
700e65e
Initial implementation
francesca64 Nov 4, 2018
b552370
Corrected RAWINPUT buffer sizing
francesca64 Nov 4, 2018
8c7f720
Mostly complete XInput implementation
francesca64 Nov 4, 2018
666a391
XInput triggers
francesca64 Nov 4, 2018
da57daa
Add preliminary CHANGELOG entry.
francesca64 Nov 4, 2018
89b6cb7
match unix common API to evl 2.0
elinorbgr Nov 15, 2018
ae6ca46
wayland: eventloop2.0
elinorbgr Nov 15, 2018
e67c500
Merge onto EL2.0 branch
Osspial Feb 15, 2019
7164a69
make EventLoopProxy require T: 'static
elinorbgr Feb 15, 2019
4202b60
Merge branch 'evl2' of https://github.com/vberger/winit into el2-win-joy
Osspial Feb 15, 2019
de20a68
Revamp device event API, as well as several misc. fixes on Windows:
Osspial Feb 24, 2019
8d2826c
Add MouseEvent documentation and Device ID debug passthrough
Osspial Feb 24, 2019
abea210
Improve type safety on get_raw_input_data
Osspial Mar 1, 2019
eb6d43e
Remove button_id field from MouseEvent::Button in favor of utton
Osspial Mar 1, 2019
2f4e18a
Remove regex dependency on Windows
Osspial Mar 1, 2019
e76f47e
Remove axis filtering in XInput
Osspial Mar 1, 2019
7775524
Make gamepads not use lazy_static
Osspial Mar 2, 2019
a3468c3
Publicly expose gamepad rumble
Osspial Mar 3, 2019
437ead3
Unstack DeviceEvent and fix examples/tests
Osspial Mar 3, 2019
36b95e2
Add HANDLE retrieval method to DeviceExtWindows
Osspial Mar 3, 2019
b48bd27
Add distinction between non-joystick axes and joystick axes.
Osspial Mar 4, 2019
0b0066b
Add ability to get gamepad port
Osspial Mar 4, 2019
81eb196
Fix xinput controller hot swapping
Osspial Mar 4, 2019
a44aafa
Add functions for enumerating attached devices
Osspial Mar 4, 2019
8fe2e2c
Clamp input to [0.0, 1.0] on gamepad rumble
Osspial Mar 4, 2019
5334537
Expose gamepad rumble errors
Osspial Mar 4, 2019
af110f9
Add method to check if device is still connected
Osspial Mar 5, 2019
ffbb7b9
Add docs
Osspial Mar 5, 2019
ca6cc12
Rename AxisHint and ButtonHint to GamepadAxis and GamepadButton
Osspial Mar 5, 2019
17a9eae
Merge branch 'eventloop-2.0' into el2-win-joy
Osspial Mar 5, 2019
8fee08a
Add CHANGELOG entry
Osspial Mar 5, 2019
f29b53d
Update CHANGELOG.md
Osspial Mar 6, 2019
d65b9d8
Add HidId and MovedAbsolute
Osspial Mar 7, 2019
1e589d9
Merge branch 'eventloop-2.0' into el2-win-joy
Osspial May 29, 2019
ef5bdd5
Merge branch 'master' into el2-win-joy
Osspial Jun 19, 2019
b3f03c3
Fix xinput deprecation warnings
Osspial Jun 19, 2019
0bc48d6
Add ability to retrieve gamepad battery level
Osspial Jun 20, 2019
592d891
Fix weird imports in gamepad example
Osspial Jun 20, 2019
7bb1118
Update CHANGELOG.md
Osspial Jun 20, 2019
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
Prev Previous commit
Next Next commit
Improve type safety on get_raw_input_data
  • Loading branch information
Osspial committed Mar 1, 2019
commit abea21014b3cc155b531b7f6d91bde7e331fe8ef
112 changes: 55 additions & 57 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use platform_impl::platform::{
drop_handler::FileDropHandler,
event::{self, handle_extended_keys, process_key_params, vkey_to_winit_vkey},
gamepad::GAMEPADS,
raw_input::{self, get_raw_input_data, get_raw_mouse_button_state},
raw_input::{self, get_raw_input_data, get_raw_mouse_button_state, RawInputData},
util,
window::adjust_size,
window_state::{CursorFlags, WindowFlags, WindowState},
Expand Down Expand Up @@ -1547,16 +1547,13 @@ unsafe extern "system" fn thread_event_target_callback<T>(
use event::device::DeviceEvent;
use event::ElementState::{Pressed, Released};

if let Some(mut input) = get_raw_input_data(lparam as _) {
let device_handle = input.header.hDevice;

if input.header.dwType == winuser::RIM_TYPEMOUSE {
let mouse = input.data.mouse();
match get_raw_input_data(lparam as _) {
Some(RawInputData::Mouse{device_handle, raw_mouse}) => {
let mouse_handle = MouseId(device_handle).into();

if util::has_flag(mouse.usFlags, winuser::MOUSE_MOVE_RELATIVE) {
let x = mouse.lLastX as f64;
let y = mouse.lLastY as f64;
if util::has_flag(raw_mouse.usFlags, winuser::MOUSE_MOVE_RELATIVE) {
let x = raw_mouse.lLastX as f64;
let y = raw_mouse.lLastY as f64;

if x != 0.0 || y != 0.0 {
subclass_input.send_event(Event::DeviceEvent(
Expand All @@ -1568,9 +1565,9 @@ unsafe extern "system" fn thread_event_target_callback<T>(
}
}

if util::has_flag(mouse.usButtonFlags, winuser::RI_MOUSE_WHEEL) {
if util::has_flag(raw_mouse.usButtonFlags, winuser::RI_MOUSE_WHEEL) {
// TODO: HOW IS RAW WHEEL DELTA HANDLED ON OTHER PLATFORMS?
let delta = mouse.usButtonData as SHORT / winuser::WHEEL_DELTA;
let delta = raw_mouse.usButtonData as SHORT / winuser::WHEEL_DELTA;
subclass_input.send_event(Event::DeviceEvent(
DeviceEvent::MouseEvent(
mouse_handle,
Expand All @@ -1579,9 +1576,9 @@ unsafe extern "system" fn thread_event_target_callback<T>(
));
}
// Check if there's horizontal wheel movement.
if util::has_flag(mouse.usButtonFlags, 0x0800) {
if util::has_flag(raw_mouse.usButtonFlags, 0x0800) {
// TODO: HOW IS RAW WHEEL DELTA HANDLED ON OTHER PLATFORMS?
let delta = mouse.usButtonData as SHORT / winuser::WHEEL_DELTA;
let delta = raw_mouse.usButtonData as SHORT / winuser::WHEEL_DELTA;
subclass_input.send_event(Event::DeviceEvent(
DeviceEvent::MouseEvent(
mouse_handle,
Expand All @@ -1590,7 +1587,7 @@ unsafe extern "system" fn thread_event_target_callback<T>(
));
}

let button_state = get_raw_mouse_button_state(mouse.usButtonFlags);
let button_state = get_raw_mouse_button_state(raw_mouse.usButtonFlags);
for (index, state) in button_state.iter().cloned().enumerate().filter_map(|(i, state)| state.map(|s| (i, s))) {
// This gives us consistency with X11, since there doesn't
// seem to be anything else reasonable to do for a mouse
Expand All @@ -1612,14 +1609,14 @@ unsafe extern "system" fn thread_event_target_callback<T>(
)
));
}
} else if input.header.dwType == winuser::RIM_TYPEKEYBOARD {
let keyboard = input.data.keyboard();
},
Some(RawInputData::Keyboard{device_handle, raw_keyboard}) => {
let keyboard_id = KeyboardId(device_handle).into();

let pressed = keyboard.Message == winuser::WM_KEYDOWN
|| keyboard.Message == winuser::WM_SYSKEYDOWN;
let released = keyboard.Message == winuser::WM_KEYUP
|| keyboard.Message == winuser::WM_SYSKEYUP;
let pressed = raw_keyboard.Message == winuser::WM_KEYDOWN
|| raw_keyboard.Message == winuser::WM_SYSKEYDOWN;
let released = raw_keyboard.Message == winuser::WM_KEYUP
|| raw_keyboard.Message == winuser::WM_SYSKEYUP;

if pressed || released {
let state = if pressed {
Expand All @@ -1628,11 +1625,11 @@ unsafe extern "system" fn thread_event_target_callback<T>(
Released
};

let scancode = keyboard.MakeCode as _;
let extended = util::has_flag(keyboard.Flags, winuser::RI_KEY_E0 as _)
| util::has_flag(keyboard.Flags, winuser::RI_KEY_E1 as _);
let scancode = raw_keyboard.MakeCode as _;
let extended = util::has_flag(raw_keyboard.Flags, winuser::RI_KEY_E0 as _)
| util::has_flag(raw_keyboard.Flags, winuser::RI_KEY_E1 as _);
if let Some((vkey, scancode)) = handle_extended_keys(
keyboard.VKey as _,
raw_keyboard.VKey as _,
scancode,
extended,
) {
Expand All @@ -1651,45 +1648,46 @@ unsafe extern "system" fn thread_event_target_callback<T>(
));
}
}
} else if input.header.dwType == winuser::RIM_TYPEHID {
},
Some(RawInputData::Hid{device_handle, mut raw_hid}) => {
let gamepad_handle = GamepadHandle(device_handle).into();
let mut gamepad_mutex = GAMEPADS.lock().unwrap();

gamepad_mutex
let gamepad_updated = gamepad_mutex
.get_or_add(device_handle)
.and_then(|gamepad| gamepad
.update_state(&mut input)
.map(|_| gamepad))
.map(|gamepad| {
for (button_id, hint, state) in gamepad.get_changed_buttons() {
subclass_input.send_event(Event::DeviceEvent(
DeviceEvent::GamepadEvent(
gamepad_handle,
GamepadEvent::Button {
button_id,
hint,
state,
},
)
));
}
.update_state(&mut raw_hid.raw_input)
.map(|_| gamepad)
);
if let Some(gamepad) = gamepad_updated {
for (button_id, hint, state) in gamepad.get_changed_buttons() {
subclass_input.send_event(Event::DeviceEvent(
DeviceEvent::GamepadEvent(
gamepad_handle,
GamepadEvent::Button {
button_id,
hint,
state,
},
)
));
}

for (axis, hint, value) in gamepad.get_changed_axes() {
subclass_input.send_event(Event::DeviceEvent(
DeviceEvent::GamepadEvent(
gamepad_handle,
GamepadEvent::Axis {
axis,
hint,
value,
},
)
));
}
});
} else {
unreachable!();
}
for (axis, hint, value) in gamepad.get_changed_axes() {
subclass_input.send_event(Event::DeviceEvent(
DeviceEvent::GamepadEvent(
gamepad_handle,
GamepadEvent::Axis {
axis,
hint,
value,
},
)
));
}
}
},
None => ()
}

commctrl::DefSubclassProc(window, msg, wparam, lparam)
Expand Down
10 changes: 5 additions & 5 deletions src/platform_impl/windows/gamepad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::collections::HashMap;
use std::sync::{Arc, Mutex};

use winapi::um::winnt::HANDLE;
use winapi::um::winuser::RAWINPUT;

use event::{
ElementState,
Expand Down Expand Up @@ -66,17 +65,18 @@ impl Gamepad {
xinput::id_from_name(&name)
.and_then(XInputGamepad::new)
.map(GamepadType::XInput)
.or_else(|| RawGamepad::new(handle)
.map(GamepadType::Raw))
.or_else(||
RawGamepad::new(handle).map(GamepadType::Raw)
)
.map(|backend| Gamepad {
handle,
backend,
})
}

pub unsafe fn update_state(&mut self, input: &mut RAWINPUT) -> Option<()> {
pub unsafe fn update_state(&mut self, raw_input_report: &mut [u8]) -> Option<()> {
match self.backend {
GamepadType::Raw(ref mut gamepad) => gamepad.update_state(input),
GamepadType::Raw(ref mut gamepad) => gamepad.update_state(raw_input_report),
GamepadType::XInput(ref mut gamepad) => gamepad.update_state(),
}
}
Expand Down
Loading