//! Modifier key data. //! //! Modifier keys like Shift and Control alter the character value //! and are used in keyboard shortcuts. //! //! Use the constants to match for combinations of the modifier keys. /// Pressed modifier keys. /// /// Specification: /// #[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Metas(u32); impl Metas { /// Return `true` if a shift key is pressed. pub fn shift(&self) -> bool { self.contains(Metas::SHIFT) } /// Return `true` if a control key is pressed. pub fn ctrl(&self) -> bool { self.contains(Metas::CONTROL) } /// Return `true` if an alt key is pressed. pub fn alt(&self) -> bool { self.contains(Metas::ALT) } /// Return `true` if a meta key is pressed. pub fn meta(&self) -> bool { self.contains(Metas::META) } } // remove bitflags dep impl Metas { pub const EMPTY: Self = Self::from_bits_retain(0); pub const ALL: Self = Self::all(); pub const ALT: Self = Self::from_bits_retain(0x01); pub const ALT_GRAPH: Self = Self::from_bits_retain(0x2); pub const CAPS_LOCK: Self = Self::from_bits_retain(0x4); pub const CONTROL: Self = Self::from_bits_retain(0x8); pub const FN: Self = Self::from_bits_retain(0x10); pub const FN_LOCK: Self = Self::from_bits_retain(0x20); pub const META: Self = Self::from_bits_retain(0x40); pub const NUM_LOCK: Self = Self::from_bits_retain(0x80); pub const SCROLL_LOCK: Self = Self::from_bits_retain(0x100); pub const SHIFT: Self = Self::from_bits_retain(0x200); pub const SYMBOL: Self = Self::from_bits_retain(0x400); pub const SYMBOL_LOCK: Self = Self::from_bits_retain(0x800); pub const HYPER: Self = Self::from_bits_retain(0x1000); pub const SUPER: Self = Self::from_bits_retain(0x2000); } impl Metas { #[inline] pub const fn is_empty(&self) -> bool { self.0 == 0 } #[inline] pub const fn bits(&self) -> u32 { self.0 } #[inline] pub const fn all() -> Self { Self::from_bits_retain( Self::ALT.0 | Self::ALT_GRAPH.0 | Self::CAPS_LOCK.0 | Self::CONTROL.0 | Self::FN.0 | Self::FN_LOCK.0 | Self::META.0 | Self::NUM_LOCK.0 | Self::SCROLL_LOCK.0 | Self::SHIFT.0 | Self::SYMBOL.0 | Self::SYMBOL_LOCK.0 | Self::HYPER.0 | Self::SUPER.0, ) } #[inline] pub const fn from_bits_retain(bits: u32) -> Self { Self(bits) } #[inline] pub const fn from_bits_truncate(bits: u32) -> Self { let bits = bits; { Self(bits & Self::all().bits()) } } #[inline] pub const fn contains(&self, other: Self) -> bool { let f = self; let other = other; { f.bits() & other.bits() == other.bits() } } #[inline] pub fn insert(&mut self, other: Self) { *self = Self::from_bits_retain(self.bits()).union(other); } #[inline] pub fn remove(&mut self, other: Self) { *self = Self::from_bits_retain(self.bits()).difference(other); } #[inline] pub fn toggle(&mut self, other: Self) { *self = Self::from_bits_retain(self.bits()).symmetric_difference(other); } #[inline] pub fn set(&mut self, other: Self, value: bool) { if value { self.insert(other); } else { self.remove(other); } } #[inline] #[must_use] pub const fn intersection(self, other: Self) -> Self { Self::from_bits_retain(self.bits() & other.bits()) } #[inline] #[must_use] pub const fn union(self, other: Self) -> Self { Self::from_bits_retain(self.bits() | other.bits()) } #[inline] #[must_use] pub const fn difference(self, other: Self) -> Self { Self::from_bits_retain(self.bits() & !other.bits()) } #[inline] #[must_use] pub const fn symmetric_difference(self, other: Self) -> Self { Self::from_bits_retain(self.bits() ^ other.bits()) } #[inline] #[must_use] pub const fn complement(self) -> Self { Self::from_bits_truncate(!self.bits()) } #[inline] pub fn from_name(name: &str) -> Option { if name == "ALT" { return Self::ALT.into(); } if name == "ALT_GRAPH" { return Self::ALT_GRAPH.into(); } if name == "CAPS_LOCK" { return Self::CAPS_LOCK.into(); } if name == "CONTROL" { return Self::CONTROL.into(); } if name == "FN" { return Self::FN.into(); } if name == "FN_LOCK" { return Self::FN_LOCK.into(); } if name == "META" { return Self::META.into(); } if name == "NUM_LOCK" { return Self::NUM_LOCK.into(); } if name == "SCROLL_LOCK" { return Self::SCROLL_LOCK.into(); } if name == "SHIFT" { return Self::SHIFT.into(); } if name == "SYMBOL" { return Self::SYMBOL.into(); } if name == "SYMBOL_LOCK" { return Self::SYMBOL_LOCK.into(); } if name == "HYPER" { return Self::HYPER.into(); } if name == "SUPER" { return Self::SUPER.into(); } None } } impl std::fmt::Debug for Metas { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut f = f.debug_tuple(""); if self.contains(Metas::ALT) { f.field(&"ALT"); } if self.contains(Metas::ALT_GRAPH) { f.field(&"ALT_GRAPH"); } if self.contains(Metas::CAPS_LOCK) { f.field(&"CAPS_LOCK"); } if self.contains(Metas::CONTROL) { f.field(&"CONTROL"); } if self.contains(Metas::FN) { f.field(&"FN"); } if self.contains(Metas::FN_LOCK) { f.field(&"FN_LOCK"); } if self.contains(Metas::META) { f.field(&"META"); } if self.contains(Metas::NUM_LOCK) { f.field(&"NUM_LOCK"); } if self.contains(Metas::SCROLL_LOCK) { f.field(&"SCROLL_LOCK"); } if self.contains(Metas::SHIFT) { f.field(&"SHIFT"); } if self.contains(Metas::SYMBOL) { f.field(&"SYMBOL"); } if self.contains(Metas::SYMBOL_LOCK) { f.field(&"SYMBOL_LOCK"); } if self.contains(Metas::HYPER) { f.field(&"HYPER"); } if self.contains(Metas::SUPER) { f.field(&"SUPER"); } f.finish() } } impl core::ops::BitOr for Metas { type Output = Self; #[inline] fn bitor(self, other: Metas) -> Self { self.union(other) } } impl core::ops::BitOrAssign for Metas { #[inline] fn bitor_assign(&mut self, other: Self) { self.insert(other); } } impl core::ops::BitXor for Metas { type Output = Self; #[inline] fn bitxor(self, other: Self) -> Self { self.symmetric_difference(other) } } impl core::ops::BitXorAssign for Metas { #[inline] fn bitxor_assign(&mut self, other: Self) { self.toggle(other); } } impl core::ops::BitAnd for Metas { type Output = Self; #[inline] fn bitand(self, other: Self) -> Self { self.intersection(other) } } impl core::ops::BitAndAssign for Metas { #[inline] fn bitand_assign(&mut self, other: Self) { *self = Self::from_bits_retain(self.bits()).intersection(other); } } impl core::ops::Sub for Metas { type Output = Self; #[inline] fn sub(self, other: Self) -> Self { self.difference(other) } } impl core::ops::SubAssign for Metas { #[inline] fn sub_assign(&mut self, other: Self) { self.remove(other); } } impl core::ops::Not for Metas { type Output = Self; #[inline] fn not(self) -> Self { self.complement() } }