Change ModifiersState to a bitflags struct (#1306)

* Change ModifiersState to a bitflags struct

* Make examples work

* Add modifier state methods

* all things considered, only erroring out in one file throughout all of these changes is kinda impressive

* Make expansion plans more clear

* Move changelog entry

* Try to fix macos build

* Revert modifiers println in cursor_grab

* Make serde serialization less bug-prone
This commit is contained in:
Osspial 2019-12-28 15:36:06 -05:00 committed by GitHub
parent 027c52171d
commit 20e81695ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 190 additions and 93 deletions

View file

@ -15,6 +15,7 @@
- `RedrawRequested` is now issued only after `MainEventsCleared`.
- `RedrawEventsCleared` is issued after each set of `RedrawRequested` events.
- Implement synthetic window focus key events on Windows.
- **Breaking**: Change `ModifiersState` to a `bitflags` struct.
# 0.20.0 Alpha 5 (2019-12-09)

View file

@ -25,6 +25,7 @@ libc = "0.2.64"
log = "0.4"
serde = { version = "1", optional = true, features = ["serde_derive"] }
raw-window-handle = "0.3"
bitflags = "1"
[dev-dependencies]
image = "0.21"
@ -48,9 +49,6 @@ version = "0.1.3"
default_features = false
features = ["display_link"]
[target.'cfg(any(target_os = "ios", target_os = "windows"))'.dependencies]
bitflags = "1"
[target.'cfg(target_os = "windows")'.dependencies.winapi]
version = "0.3.6"
features = [

View file

@ -30,8 +30,8 @@ fn main() {
use winit::event::VirtualKeyCode::*;
match key {
Escape => *control_flow = ControlFlow::Exit,
G => window.set_cursor_grab(!modifiers.shift).unwrap(),
H => window.set_cursor_visible(modifiers.shift),
G => window.set_cursor_grab(!modifiers.shift()).unwrap(),
H => window.set_cursor_visible(modifiers.shift()),
_ => (),
}
}

View file

@ -60,7 +60,7 @@ fn main() {
..
} => {
window.set_title(&format!("{:?}", key));
let state = !modifiers.shift;
let state = !modifiers.shift();
use VirtualKeyCode::*;
match key {
A => window.set_always_on_top(state),
@ -81,7 +81,7 @@ fn main() {
video_modes.iter().nth(video_mode_id).unwrap()
);
}
F => window.set_fullscreen(match (state, modifiers.alt) {
F => window.set_fullscreen(match (state, modifiers.alt()) {
(true, false) => {
Some(Fullscreen::Borderless(window.current_monitor()))
}

View file

@ -675,21 +675,99 @@ pub enum VirtualKeyCode {
Cut,
}
impl ModifiersState {
/// Returns `true` if the shift key is pressed.
pub fn shift(&self) -> bool {
self.intersects(Self::SHIFT)
}
/// Returns `true` if the control key is pressed.
pub fn ctrl(&self) -> bool {
self.intersects(Self::CTRL)
}
/// Returns `true` if the alt key is pressed.
pub fn alt(&self) -> bool {
self.intersects(Self::ALT)
}
/// Returns `true` if the logo key is pressed.
pub fn logo(&self) -> bool {
self.intersects(Self::LOGO)
}
}
bitflags! {
/// Represents the current state of the keyboard modifiers
///
/// Each field of this struct represents a modifier and is `true` if this modifier is active.
#[derive(Default, Debug, Hash, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct ModifiersState {
/// The "shift" key
pub shift: bool,
/// The "control" key
pub ctrl: bool,
/// The "alt" key
pub alt: bool,
/// The "logo" key
///
/// Each flag represents a modifier and is set if this modifier is active.
#[derive(Default)]
pub struct ModifiersState: u32 {
// left and right modifiers are currently commented out, but we should be able to support
// them in a future release
/// The "shift" key.
const SHIFT = 0b100 << 0;
// const LSHIFT = 0b010 << 0;
// const RSHIFT = 0b001 << 0;
/// The "control" key.
const CTRL = 0b100 << 3;
// const LCTRL = 0b010 << 3;
// const RCTRL = 0b001 << 3;
/// The "alt" key.
const ALT = 0b100 << 6;
// const LALT = 0b010 << 6;
// const RALT = 0b001 << 6;
/// This is the "windows" key on PC and "command" key on Mac.
const LOGO = 0b100 << 9;
// const LLOGO = 0b010 << 9;
// const RLOGO = 0b001 << 9;
}
}
#[cfg(feature = "serde")]
mod modifiers_serde {
use super::ModifiersState;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Default, Serialize, Deserialize)]
#[serde(default)]
#[serde(rename = "ModifiersState")]
pub struct ModifiersStateSerialize {
pub shift: bool,
pub ctrl: bool,
pub alt: bool,
pub logo: bool,
}
impl Serialize for ModifiersState {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = ModifiersStateSerialize {
shift: self.shift(),
ctrl: self.ctrl(),
alt: self.alt(),
logo: self.logo(),
};
s.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for ModifiersState {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let ModifiersStateSerialize {
shift,
ctrl,
alt,
logo,
} = ModifiersStateSerialize::deserialize(deserializer)?;
let mut m = ModifiersState::empty();
m.set(ModifiersState::SHIFT, shift);
m.set(ModifiersState::CTRL, ctrl);
m.set(ModifiersState::ALT, alt);
m.set(ModifiersState::LOGO, logo);
Ok(m)
}
}
}

View file

@ -119,7 +119,6 @@ extern crate log;
#[macro_use]
extern crate serde;
#[macro_use]
#[cfg(any(target_os = "ios", target_os = "windows"))]
extern crate bitflags;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[macro_use]

View file

@ -404,12 +404,12 @@ fn keysym_to_vkey(keysym: u32) -> Option<VirtualKeyCode> {
impl ModifiersState {
pub(crate) fn from_wayland(mods: keyboard::ModifiersState) -> ModifiersState {
ModifiersState {
shift: mods.shift,
ctrl: mods.ctrl,
alt: mods.alt,
logo: mods.logo,
}
let mut m = ModifiersState::empty();
m.set(ModifiersState::SHIFT, mods.shift);
m.set(ModifiersState::CTRL, mods.ctrl);
m.set(ModifiersState::ALT, mods.alt);
m.set(ModifiersState::LOGO, mods.logo);
m
}
}

View file

@ -17,12 +17,12 @@ impl ModifiersState {
}
pub(crate) fn from_x11_mask(mask: c_uint) -> Self {
ModifiersState {
alt: mask & ffi::Mod1Mask != 0,
shift: mask & ffi::ShiftMask != 0,
ctrl: mask & ffi::ControlMask != 0,
logo: mask & ffi::Mod4Mask != 0,
}
let mut m = ModifiersState::empty();
m.set(ModifiersState::SHIFT, mask & ffi::Mod1Mask != 0);
m.set(ModifiersState::CTRL, mask & ffi::ShiftMask != 0);
m.set(ModifiersState::ALT, mask & ffi::ControlMask != 0);
m.set(ModifiersState::LOGO, mask & ffi::Mod4Mask != 0);
m
}
}

View file

@ -116,10 +116,10 @@ impl ModifierKeyState {
let mut new_state = *state;
match except {
Some(Modifier::Alt) => new_state.alt = self.state.alt,
Some(Modifier::Ctrl) => new_state.ctrl = self.state.ctrl,
Some(Modifier::Shift) => new_state.shift = self.state.shift,
Some(Modifier::Logo) => new_state.logo = self.state.logo,
Some(Modifier::Alt) => new_state.set(ModifiersState::ALT, self.state.alt()),
Some(Modifier::Ctrl) => new_state.set(ModifiersState::CTRL, self.state.ctrl()),
Some(Modifier::Shift) => new_state.set(ModifiersState::SHIFT, self.state.shift()),
Some(Modifier::Logo) => new_state.set(ModifiersState::LOGO, self.state.logo()),
None => (),
}
@ -170,18 +170,18 @@ impl ModifierKeyState {
fn get_modifier(state: &ModifiersState, modifier: Modifier) -> bool {
match modifier {
Modifier::Alt => state.alt,
Modifier::Ctrl => state.ctrl,
Modifier::Shift => state.shift,
Modifier::Logo => state.logo,
Modifier::Alt => state.alt(),
Modifier::Ctrl => state.ctrl(),
Modifier::Shift => state.shift(),
Modifier::Logo => state.logo(),
}
}
fn set_modifier(state: &mut ModifiersState, modifier: Modifier, value: bool) {
match modifier {
Modifier::Alt => state.alt = value,
Modifier::Ctrl => state.ctrl = value,
Modifier::Shift => state.shift = value,
Modifier::Logo => state.logo = value,
Modifier::Alt => state.set(ModifiersState::ALT, value),
Modifier::Ctrl => state.set(ModifiersState::CTRL, value),
Modifier::Shift => state.set(ModifiersState::SHIFT, value),
Modifier::Logo => state.set(ModifiersState::LOGO, value),
}
}

View file

@ -14,7 +14,7 @@ use std::{
use cocoa::{appkit::NSApp, base::nil, foundation::NSString};
use crate::{
event::{Event, StartCause, WindowEvent},
event::{Event, StartCause},
event_loop::{ControlFlow, EventLoopWindowTarget as RootWindowTarget},
platform_impl::platform::{observer::EventLoopWaker, util::Never},
window::WindowId,

View file

@ -224,12 +224,24 @@ pub fn check_function_keys(string: &str) -> Option<VirtualKeyCode> {
pub fn event_mods(event: id) -> ModifiersState {
let flags = unsafe { NSEvent::modifierFlags(event) };
ModifiersState {
shift: flags.contains(NSEventModifierFlags::NSShiftKeyMask),
ctrl: flags.contains(NSEventModifierFlags::NSControlKeyMask),
alt: flags.contains(NSEventModifierFlags::NSAlternateKeyMask),
logo: flags.contains(NSEventModifierFlags::NSCommandKeyMask),
}
let mut m = ModifiersState::empty();
m.set(
ModifiersState::SHIFT,
flags.contains(NSEventModifierFlags::NSShiftKeyMask),
);
m.set(
ModifiersState::CTRL,
flags.contains(NSEventModifierFlags::NSControlKeyMask),
);
m.set(
ModifiersState::ALT,
flags.contains(NSEventModifierFlags::NSAlternateKeyMask),
);
m.set(
ModifiersState::LOGO,
flags.contains(NSEventModifierFlags::NSCommandKeyMask),
);
m
}
pub fn get_scancode(event: cocoa::base::id) -> c_ushort {

View file

@ -646,36 +646,36 @@ extern "C" fn flags_changed(this: &Object, _sel: Sel, event: id) {
if let Some(window_event) = modifier_event(
event,
NSEventModifierFlags::NSShiftKeyMask,
state.modifiers.shift,
state.modifiers.shift(),
) {
state.modifiers.shift = !state.modifiers.shift;
state.modifiers.toggle(ModifiersState::SHIFT);
events.push_back(window_event);
}
if let Some(window_event) = modifier_event(
event,
NSEventModifierFlags::NSControlKeyMask,
state.modifiers.ctrl,
state.modifiers.ctrl(),
) {
state.modifiers.ctrl = !state.modifiers.ctrl;
state.modifiers.toggle(ModifiersState::CTRL);
events.push_back(window_event);
}
if let Some(window_event) = modifier_event(
event,
NSEventModifierFlags::NSCommandKeyMask,
state.modifiers.logo,
state.modifiers.logo(),
) {
state.modifiers.logo = !state.modifiers.logo;
state.modifiers.toggle(ModifiersState::LOGO);
events.push_back(window_event);
}
if let Some(window_event) = modifier_event(
event,
NSEventModifierFlags::NSAlternateKeyMask,
state.modifiers.alt,
state.modifiers.alt(),
) {
state.modifiers.alt = !state.modifiers.alt;
state.modifiers.toggle(ModifiersState::ALT);
events.push_back(window_event);
}

View file

@ -15,12 +15,12 @@ pub fn mouse_button(event: &impl IMouseEvent) -> MouseButton {
}
pub fn mouse_modifiers(event: &impl IMouseEvent) -> ModifiersState {
ModifiersState {
shift: event.shift_key(),
ctrl: event.ctrl_key(),
alt: event.alt_key(),
logo: event.meta_key(),
}
let mut m = ModifiersState::empty();
m.set(ModifiersState::SHIFT, event.shift_key());
m.set(ModifiersState::CTRL, event.ctrl_key());
m.set(ModifiersState::ALT, event.alt_key());
m.set(ModifiersState::LOGO, event.meta_key());
m
}
pub fn mouse_position(event: &impl IMouseEvent) -> LogicalPosition {
@ -213,12 +213,12 @@ pub fn virtual_key_code(event: &impl IKeyboardEvent) -> Option<VirtualKeyCode> {
}
pub fn keyboard_modifiers(event: &impl IKeyboardEvent) -> ModifiersState {
ModifiersState {
shift: event.shift_key(),
ctrl: event.ctrl_key(),
alt: event.alt_key(),
logo: event.meta_key(),
}
let mut m = ModifiersState::empty();
m.set(ModifiersState::SHIFT, event.shift_key());
m.set(ModifiersState::CTRL, event.ctrl_key());
m.set(ModifiersState::ALT, event.alt_key());
m.set(ModifiersState::LOGO, event.meta_key());
m
}
pub fn codepoint(event: &impl IKeyboardEvent) -> char {

View file

@ -14,12 +14,12 @@ pub fn mouse_button(event: &MouseEvent) -> MouseButton {
}
pub fn mouse_modifiers(event: &MouseEvent) -> ModifiersState {
ModifiersState {
shift: event.shift_key(),
ctrl: event.ctrl_key(),
alt: event.alt_key(),
logo: event.meta_key(),
}
let mut m = ModifiersState::empty();
m.set(ModifiersState::SHIFT, event.shift_key());
m.set(ModifiersState::CTRL, event.ctrl_key());
m.set(ModifiersState::ALT, event.alt_key());
m.set(ModifiersState::LOGO, event.meta_key());
m
}
pub fn mouse_position(event: &MouseEvent) -> LogicalPosition {
@ -211,12 +211,12 @@ pub fn virtual_key_code(event: &KeyboardEvent) -> Option<VirtualKeyCode> {
}
pub fn keyboard_modifiers(event: &KeyboardEvent) -> ModifiersState {
ModifiersState {
shift: event.shift_key(),
ctrl: event.ctrl_key(),
alt: event.alt_key(),
logo: event.meta_key(),
}
let mut m = ModifiersState::empty();
m.set(ModifiersState::SHIFT, event.shift_key());
m.set(ModifiersState::CTRL, event.ctrl_key());
m.set(ModifiersState::ALT, event.alt_key());
m.set(ModifiersState::LOGO, event.meta_key());
m
}
pub fn codepoint(event: &KeyboardEvent) -> char {

View file

@ -17,13 +17,22 @@ fn key_pressed(vkey: c_int) -> bool {
}
pub fn get_key_mods() -> ModifiersState {
let mut mods = ModifiersState::default();
let filter_out_altgr = layout_uses_altgr() && key_pressed(winuser::VK_RMENU);
mods.shift = key_pressed(winuser::VK_SHIFT);
mods.ctrl = key_pressed(winuser::VK_CONTROL) && !filter_out_altgr;
mods.alt = key_pressed(winuser::VK_MENU) && !filter_out_altgr;
mods.logo = key_pressed(winuser::VK_LWIN) || key_pressed(winuser::VK_RWIN);
let mut mods = ModifiersState::empty();
mods.set(ModifiersState::SHIFT, key_pressed(winuser::VK_SHIFT));
mods.set(
ModifiersState::CTRL,
key_pressed(winuser::VK_CONTROL) && !filter_out_altgr,
);
mods.set(
ModifiersState::ALT,
key_pressed(winuser::VK_MENU) && !filter_out_altgr,
);
mods.set(
ModifiersState::LOGO,
key_pressed(winuser::VK_LWIN) || key_pressed(winuser::VK_RWIN),
);
mods
}