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

Richer input events #164

Merged
merged 1 commit into from
May 7, 2017
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
4 changes: 2 additions & 2 deletions examples/cursor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
extern crate winit;

use winit::{Event, ElementState, MouseCursor, WindowEvent};
use winit::{Event, ElementState, MouseCursor, WindowEvent, KeyboardInput};

fn main() {
let events_loop = winit::EventsLoop::new();
Expand All @@ -13,7 +13,7 @@ fn main() {

events_loop.run_forever(|event| {
match event {
Event::WindowEvent { event: WindowEvent::KeyboardInput(ElementState::Pressed, _, _, _), .. } => {
Event::WindowEvent { event: WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, .. }, .. }, .. } => {
println!("Setting cursor to \"{:?}\"", cursors[cursor_idx]);
window.set_cursor(cursors[cursor_idx]);
if cursor_idx < cursors.len() - 1 {
Expand Down
5 changes: 4 additions & 1 deletion examples/fullscreen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@ fn main() {
winit::Event::WindowEvent { event, .. } => {
match event {
winit::WindowEvent::Closed => events_loop.interrupt(),
winit::WindowEvent::KeyboardInput(_, _, Some(winit::VirtualKeyCode::Escape), _) => events_loop.interrupt(),
winit::WindowEvent::KeyboardInput {
input: winit::KeyboardInput { virtual_keycode: Some(winit::VirtualKeyCode::Escape), .. }, ..
} => events_loop.interrupt(),
_ => ()
}
},
_ => {}
}
});
}
9 changes: 5 additions & 4 deletions examples/grabbing.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
extern crate winit;

use winit::{WindowEvent, ElementState};
use winit::{WindowEvent, ElementState, KeyboardInput};

fn main() {
let events_loop = winit::EventsLoop::new();
Expand All @@ -16,7 +16,7 @@ fn main() {
match event {
winit::Event::WindowEvent { event, .. } => {
match event {
WindowEvent::KeyboardInput(ElementState::Pressed, _, _, _) => {
WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, .. }, .. } => {
if grabbed {
grabbed = false;
window.set_cursor_state(winit::CursorState::Normal)
Expand All @@ -30,13 +30,14 @@ fn main() {

WindowEvent::Closed => events_loop.interrupt(),

a @ WindowEvent::MouseMoved(_, _) => {
a @ WindowEvent::MouseMoved { .. } => {
println!("{:?}", a);
},

_ => (),
}
},
}
_ => {}
}
});
}
3 changes: 3 additions & 0 deletions src/api_transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ macro_rules! gen_api_transition {
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId(usize);

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;

pub struct Window2 {
pub window: ::std::sync::Arc<Window>,
events_loop: ::std::sync::Weak<EventsLoop>,
Expand Down
76 changes: 64 additions & 12 deletions src/events.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use std::path::PathBuf;
use WindowId;
use {WindowId, DeviceId, AxisId, ButtonId};

#[derive(Clone, Debug)]
pub enum Event {
WindowEvent {
window_id: WindowId,
event: WindowEvent,
}
},
DeviceEvent {
device_id: DeviceId,
event: DeviceEvent,
},
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -35,31 +39,36 @@ pub enum WindowEvent {
Focused(bool),

/// An event from the keyboard has been received.
KeyboardInput(ElementState, ScanCode, Option<VirtualKeyCode>, ModifiersState),
KeyboardInput { device_id: DeviceId, input: KeyboardInput },

/// The cursor has moved on the window.
///
/// The parameter are the (x,y) coords in pixels relative to the top-left corner of the window.
MouseMoved(i32, i32),
/// `position` is (x,y) coords in pixels relative to the top-left corner of the window. Because the range of this
/// data is limited by the display area and it may have been transformed by the OS to implement effects such as
/// mouse acceleration, it should not be used to implement non-cursor-like interactions such as 3D camera control.
MouseMoved { device_id: DeviceId, position: (f64, f64) },

/// The cursor has entered the window.
MouseEntered,
MouseEntered { device_id: DeviceId },

/// The cursor has left the window.
MouseLeft,
MouseLeft { device_id: DeviceId },

/// A mouse wheel movement or touchpad scroll occurred.
MouseWheel(MouseScrollDelta, TouchPhase),
MouseWheel { device_id: DeviceId, delta: MouseScrollDelta, phase: TouchPhase },

/// An event from the mouse has been received.
MouseInput(ElementState, MouseButton),
/// An mouse button press has been received.
MouseInput { device_id: DeviceId, state: ElementState, button: MouseButton },

/// Touchpad pressure event.
///
/// At the moment, only supported on Apple forcetouch-capable macbooks.
/// The parameters are: pressure level (value between 0 and 1 representing how hard the touchpad
/// is being pressed) and stage (integer representing the click level).
TouchpadPressure(f32, i64),
TouchpadPressure { device_id: DeviceId, pressure: f32, stage: i64 },

/// Motion on some analog axis not otherwise handled. May overlap with mouse motion.
AxisMotion { device_id: DeviceId, axis: AxisId, value: f64 },

/// The window needs to be redrawn.
Refresh,
Expand All @@ -73,6 +82,48 @@ pub enum WindowEvent {
Touch(Touch)
}

/// Represents raw hardware events that are not associated with any particular window.
///
/// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera or first-person
/// game controls. Many physical actions, such as mouse movement, can produce both device and window events. Because
/// window events typically arise from virtual devices (corresponding to GUI cursors and keyboard focus) the device IDs
/// may not match.
///
/// Note that these events are delivered regardless of input focus.
#[derive(Clone, Debug)]
pub enum DeviceEvent {
Added,
Removed,
Motion { axis: AxisId, value: f64 },
Button { button: ButtonId, state: ElementState },
Key(KeyboardInput),
Text { codepoint: char },
}

#[derive(Debug, Clone, Copy)]
pub struct KeyboardInput {
/// Identifies the physical key pressed
///
/// This should not change if the user adjusts the host's keyboard map. Use when the physical location of the
/// key is more important than the key's host GUI semantics, such as for movement controls in a first-person
/// game.
pub scancode: ScanCode,

pub state: ElementState,

/// Identifies the semantic meaning of the key
///
/// Use when the semantics of the key are more important than the physical location of the key, such as when
/// implementing appropriate behavior for "page up."
pub virtual_keycode: Option<VirtualKeyCode>,

/// Modifier keys active at the time of this input.
///
/// This is tracked internally to avoid tracking errors arising from modifier key state changes when events from
/// this device are not being delivered to the application, e.g. due to keyboard focus being elsewhere.
pub modifiers: ModifiersState
}

#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum TouchPhase {
Started,
Expand All @@ -98,13 +149,14 @@ pub enum TouchPhase {
///
/// Touch may be cancelled if for example window lost focus.
pub struct Touch {
pub device_id: DeviceId,
pub phase: TouchPhase,
pub location: (f64,f64),
/// unique identifier of a finger.
pub id: u64
}

pub type ScanCode = u8;
pub type ScanCode = u32;

#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum ElementState {
Expand Down
16 changes: 16 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,22 @@ pub struct Window {
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId(platform::WindowId);

/// Identifier of an input device.
///
/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which
/// identifies its origin. Note that devices may be virtual (representing an on-screen cursor and keyboard focus) or
/// physical. Virtual devices typically aggregate inputs from multiple physical devices.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId(platform::DeviceId);

/// Identifier for a specific analog axis on some device.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AxisId(u32);

/// Identifier for a specific button on some device.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ButtonId(u32);

/// Provides a way to retreive events from the windows that were registered to it.
// TODO: document usage in multiple threads
pub struct EventsLoop {
Expand Down
4 changes: 4 additions & 0 deletions src/platform/ios/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ impl Window {
let phase: i32 = msg_send![touch, phase];

state.events_queue.push_back(Event::Touch(Touch {
device_id: DEVICE_ID,
id: touch_id,
location: (location.x as f64, location.y as f64),
phase: match phase {
Expand Down Expand Up @@ -495,3 +496,6 @@ impl<'a> Iterator for PollEventsIterator<'a> {
}
}
}

// Constant device ID, to be removed when this backend is updated to report real device IDs.
const DEVICE_ID: ::DeviceId = ::DeviceId(DeviceId);
16 changes: 12 additions & 4 deletions src/platform/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ pub enum WindowId {
Wayland(wayland::WindowId)
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum DeviceId {
#[doc(hidden)]
X(x11::DeviceId),
#[doc(hidden)]
Wayland(wayland::DeviceId)
}

#[derive(Clone)]
pub enum MonitorId {
#[doc(hidden)]
Expand Down Expand Up @@ -137,8 +145,8 @@ impl Window2 {
}
},

UnixBackend::X(ref connec) => {
x11::Window2::new(events_loop, connec, window, pl_attribs).map(Window2::X)
UnixBackend::X(_) => {
x11::Window2::new(events_loop, window, pl_attribs).map(Window2::X)
},
UnixBackend::Error(_) => {
// If the Backend is Error(), it is not possible to instanciate an EventsLoop at all,
Expand Down Expand Up @@ -308,8 +316,8 @@ impl EventsLoop {
EventsLoop::Wayland(wayland::EventsLoop::new(ctxt.clone()))
},

UnixBackend::X(_) => {
EventsLoop::X(x11::EventsLoop::new())
UnixBackend::X(ref ctxt) => {
EventsLoop::X(x11::EventsLoop::new(ctxt.clone()))
},

UnixBackend::Error(_) => {
Expand Down
Loading