Skip to content

Commit

Permalink
Add support for no button in a mouse event.
Browse files Browse the repository at this point in the history
  • Loading branch information
xStrom committed Apr 14, 2020
1 parent cbc705f commit 3b3b656
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 55 deletions.
2 changes: 1 addition & 1 deletion druid-shell/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub use hotkey::{HotKey, KeyCompare, RawMods, SysMods};
pub use keyboard::{KeyEvent, KeyModifiers};
pub use keycodes::KeyCode;
pub use menu::Menu;
pub use mouse::{Cursor, MouseButton, MouseEvent};
pub use mouse::{Cursor, MouseButton, MouseButtonExt, MouseEvent};
pub use window::{
IdleHandle, IdleToken, Text, TimerToken, WinHandler, WindowBuilder, WindowHandle,
};
35 changes: 30 additions & 5 deletions druid-shell/src/mouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub struct MouseEvent {
pub count: u32,
/// The currently pressed button in the case of a move or click event,
/// or the released button in the case of a mouse-up event.
pub button: MouseButton,
pub button: Option<MouseButton>,
}

/// An indicator of which mouse button was pressed.
Expand All @@ -52,20 +52,45 @@ pub enum MouseButton {
Unknown,
}

impl MouseButton {
/// Adds convenience methods to `MouseButton` and `Option<MouseButton>`.
pub trait MouseButtonExt {
/// Returns `true` if this is the left mouse button.
fn is_left(self) -> bool;

/// Returns `true` if this is the right mouse button.
fn is_right(self) -> bool;
}

impl MouseButtonExt for MouseButton {
#[inline(always)]
pub fn is_left(self) -> bool {
fn is_left(self) -> bool {
self == MouseButton::Left
}

/// Returns `true` if this is the right mouse button.
#[inline(always)]
pub fn is_right(self) -> bool {
fn is_right(self) -> bool {
self == MouseButton::Right
}
}

impl MouseButtonExt for Option<MouseButton> {
#[inline(always)]
fn is_left(self) -> bool {
match self {
Some(MouseButton::Left) => true,
_ => false,
}
}

#[inline(always)]
fn is_right(self) -> bool {
match self {
Some(MouseButton::Right) => true,
_ => false,
}
}
}

//NOTE: this currently only contains cursors that are included by default on
//both Windows and macOS. We may want to provide polyfills for various additional cursors,
//and we will also want to add some mechanism for adding custom cursors.
Expand Down
22 changes: 10 additions & 12 deletions druid-shell/src/platform/gtk/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,28 +713,26 @@ fn make_gdk_cursor(cursor: &Cursor, gdk_window: &gdk::Window) -> Option<gdk::Cur
)
}

fn get_mouse_button(button: u32) -> MouseButton {
fn get_mouse_button(button: u32) -> Option<MouseButton> {
match button {
1 => MouseButton::Left,
2 => MouseButton::Middle,
3 => MouseButton::Right,
4 => MouseButton::X1,
5 => MouseButton::X2,
_ => MouseButton::Unknown,
0 => None
1 => Some(MouseButton::Left),
2 => Some(MouseButton::Middle),
3 => Some(MouseButton::Right),
4 => Some(MouseButton::X1),
5 => Some(MouseButton::X2),
_ => Some(MouseButton::Unknown),
}
}

fn get_mouse_button_from_modifiers(modifiers: gdk::ModifierType) -> MouseButton {
fn get_mouse_button_from_modifiers(modifiers: gdk::ModifierType) -> Option<MouseButton> {
match modifiers {
modifiers if modifiers.contains(ModifierType::BUTTON1_MASK) => MouseButton::Left,
modifiers if modifiers.contains(ModifierType::BUTTON2_MASK) => MouseButton::Middle,
modifiers if modifiers.contains(ModifierType::BUTTON3_MASK) => MouseButton::Right,
modifiers if modifiers.contains(ModifierType::BUTTON4_MASK) => MouseButton::X1,
modifiers if modifiers.contains(ModifierType::BUTTON5_MASK) => MouseButton::X2,
_ => {
//FIXME: what about when no modifiers match?
MouseButton::Unknown
}
_ => None,
}
}

Expand Down
21 changes: 9 additions & 12 deletions druid-shell/src/platform/mac/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ extern "C" fn set_frame_size(this: &mut Object, _: Sel, size: NSSize) {
// otherwise we get it from the event itself.
fn mouse_event(nsevent: id, view: id, button: Option<MouseButton>) -> MouseEvent {
unsafe {
let button = button.unwrap_or_else(|| {
let button = button.or_else(|| {
let button = NSEvent::pressedMouseButtons(nsevent);
get_mouse_button(button as usize)
});
Expand All @@ -380,19 +380,16 @@ fn mouse_event(nsevent: id, view: id, button: Option<MouseButton>) -> MouseEvent
}
}

fn get_mouse_button(mask: usize) -> MouseButton {
fn get_mouse_button(mask: usize) -> Option<MouseButton> {
//TODO: this doesn't correctly handle multiple buttons being pressed.
match mask {
mask if mask & 1 > 0 => MouseButton::Left,
mask if mask & 1 << 1 > 0 => MouseButton::Right,
mask if mask & 1 << 2 > 0 => MouseButton::Middle,
mask if mask & 1 << 3 > 0 => MouseButton::X1,
mask if mask & 1 << 4 > 0 => MouseButton::X2,
_ => {
//FIXME: this gets called when the mouse moves, where there
//may be no buttons down. This is mostly a problem with our API?
MouseButton::Unknown
}
mask if mask == 0 => None,
mask if mask & 1 > 0 => Some(MouseButton::Left),
mask if mask & 1 << 1 > 0 => Some(MouseButton::Right),
mask if mask & 1 << 2 > 0 => Some(MouseButton::Middle),
mask if mask & 1 << 3 > 0 => Some(MouseButton::X1),
mask if mask & 1 << 4 > 0 => Some(MouseButton::X2),
_ => Some(MouseButton::Unknown),
}
}

Expand Down
22 changes: 9 additions & 13 deletions druid-shell/src/platform/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,14 +633,13 @@ impl WndProc for MyWndProc {
let pos = Point::new(px as f64, py as f64);
let mods = get_mod_state();
let button = match wparam {
w if (w & 1) > 0 => MouseButton::Left,
w if (w & 1 << 1) > 0 => MouseButton::Right,
w if (w & 1 << 5) > 0 => MouseButton::Middle,
w if (w & 1 << 6) > 0 => MouseButton::X1,
w if (w & 1 << 7) > 0 => MouseButton::X2,
//FIXME: I guess we probably do want `MouseButton::None`?
//this feels bad, but also this gets discarded in druid anyway.
_ => MouseButton::Unknown,
w if w == 0 => None,
w if (w & 1) > 0 => Some(MouseButton::Left),
w if (w & 1 << 1) > 0 => Some(MouseButton::Right),
w if (w & 1 << 5) > 0 => Some(MouseButton::Middle),
w if (w & 1 << 6) > 0 => Some(MouseButton::X1),
w if (w & 1 << 7) > 0 => Some(MouseButton::X2),
_ => Some(MouseButton::Unknown),
};
let event = MouseEvent {
pos,
Expand Down Expand Up @@ -680,10 +679,7 @@ impl WndProc for MyWndProc {
match HIWORD(wparam as u32) {
1 => MouseButton::X1,
2 => MouseButton::X2,
_ => {
warn!("unexpected X button event");
return None;
}
_ => MouseButton::Unknown,
}
}
_ => unreachable!(),
Expand All @@ -703,8 +699,8 @@ impl WndProc for MyWndProc {
let event = MouseEvent {
pos,
mods,
button,
count,
button: Some(button),
};
if count > 0 {
s.enter_mouse_capture(hwnd, button);
Expand Down
6 changes: 3 additions & 3 deletions druid-shell/src/platform/x11/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl Application {
meta: false,
},
count: 0,
button: MouseButton::Left,
button: Some(MouseButton::Left),
};
WINDOW_MAP.with(|map| {
let mut windows = map.borrow_mut();
Expand All @@ -137,7 +137,7 @@ impl Application {
meta: false,
},
count: 0,
button: MouseButton::Left,
button: Some(MouseButton::Left),
};
WINDOW_MAP.with(|map| {
let mut windows = map.borrow_mut();
Expand All @@ -161,7 +161,7 @@ impl Application {
meta: false,
},
count: 0,
button: MouseButton::Left,
button: Some(MouseButton::Left),
};
WINDOW_MAP.with(|map| {
let mut windows = map.borrow_mut();
Expand Down
4 changes: 2 additions & 2 deletions druid/examples/game_of_life.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ impl Widget<AppData> for GameOfLifeWidget {
}
}
Event::MouseDown(e) => {
if e.button == MouseButton::Left {
if e.button == Some(MouseButton::Left) {
data.drawing = true;
let grid_pos_opt = self.grid_pos(e.pos);
grid_pos_opt
Expand All @@ -258,7 +258,7 @@ impl Widget<AppData> for GameOfLifeWidget {
}
}
Event::MouseUp(e) => {
if e.button == MouseButton::Left {
if e.button == Some(MouseButton::Left) {
data.drawing = false;
}
}
Expand Down
4 changes: 2 additions & 2 deletions druid/examples/multiwin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
use druid::widget::{Align, Button, Flex, Label, Padding};
use druid::{
commands as sys_cmds, AppDelegate, AppLauncher, Command, ContextMenu, Data, DelegateCtx, Env,
Event, EventCtx, LocalizedString, MenuDesc, MenuItem, Selector, Target, Widget, WindowDesc,
WindowId,
Event, EventCtx, LocalizedString, MenuDesc, MenuItem, MouseButtonExt, Selector, Target, Widget,
WindowDesc, WindowId,
};

use log::info;
Expand Down
4 changes: 2 additions & 2 deletions druid/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ pub use piet::{Color, LinearGradient, RadialGradient, RenderContext, UnitPoint};
// these are the types from shell that we expose; others we only use internally.
pub use shell::{
Application, Clipboard, ClipboardFormat, Cursor, Error as PlatformError, FileDialogOptions,
FileInfo, FileSpec, FormatId, HotKey, KeyCode, KeyEvent, KeyModifiers, MouseButton, RawMods,
SysMods, Text, TimerToken, WindowHandle,
FileInfo, FileSpec, FormatId, HotKey, KeyCode, KeyEvent, KeyModifiers, MouseButton,
MouseButtonExt, RawMods, SysMods, Text, TimerToken, WindowHandle,
};

pub use crate::core::WidgetPod;
Expand Down
2 changes: 1 addition & 1 deletion druid/src/mouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct MouseEvent {
pub count: u32,
/// The currently pressed button in the case of a move or click event,
/// or the released button in the case of a mouse-up event.
pub button: MouseButton,
pub button: Option<MouseButton>,
}

impl From<druid_shell::MouseEvent> for MouseEvent {
Expand Down
2 changes: 1 addition & 1 deletion druid/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn propogate_hot() {
window_pos: pos,
mods: KeyModifiers::default(),
count: 0,
button: MouseButton::Left,
button: Some(MouseButton::Left),
}
}
Harness::create((), widget, |harness| {
Expand Down
2 changes: 1 addition & 1 deletion druid/src/widget/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::kurbo::{Line, Point, Rect, Size};
use crate::widget::flex::Axis;
use crate::{
theme, BoxConstraints, Color, Cursor, Data, Env, Event, EventCtx, LayoutCtx, LifeCycle,
LifeCycleCtx, PaintCtx, RenderContext, UpdateCtx, Widget, WidgetPod,
LifeCycleCtx, MouseButtonExt, PaintCtx, RenderContext, UpdateCtx, Widget, WidgetPod,
};

/// A container containing two other widgets, splitting the area either horizontally or vertically.
Expand Down

0 comments on commit 3b3b656

Please sign in to comment.