From db45e5839011aaa07ae7df15c4deec7311463795 Mon Sep 17 00:00:00 2001 From: Andy Barron Date: Thu, 3 Nov 2016 01:31:16 -0700 Subject: [PATCH] Add MouseEntered/MouseLeft for Windows, X11, Wayland, & Cocoa --- src/api/wayland/context.rs | 17 ++++++++++++----- src/api/x11/input.rs | 6 +++--- src/events.rs | 6 ++++++ src/platform/macos/mod.rs | 2 ++ src/platform/windows/callback.rs | 13 ++++++++++--- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/api/wayland/context.rs b/src/api/wayland/context.rs index f98b1e88..b3bd437a 100644 --- a/src/api/wayland/context.rs +++ b/src/api/wayland/context.rs @@ -397,9 +397,9 @@ impl wl_pointer::Handler for WaylandEnv { if window.equals(surface) { self.mouse_focus = Some(eviter.clone()); let (w, h) = self.mouse_location; - eviter.lock().unwrap().push_back( - Event::MouseMoved(w, h) - ); + let mut event_queue = eviter.lock().unwrap(); + event_queue.push_back(Event::MouseEntered); + event_queue.push_back(Event::MouseMoved(w, h)); break; } } @@ -409,9 +409,16 @@ impl wl_pointer::Handler for WaylandEnv { _evqh: &mut EventQueueHandle, _proxy: &wl_pointer::WlPointer, _serial: u32, - _surface: &wl_surface::WlSurface) + surface: &wl_surface::WlSurface) { - self.mouse_focus = None + self.mouse_focus = None; + for &(ref window, ref eviter) in &self.windows { + if window.equals(surface) { + let mut event_queue = eviter.lock().unwrap(); + event_queue.push_back(Event::MouseLeft); + break; + } + } } fn motion(&mut self, diff --git a/src/api/x11/input.rs b/src/api/x11/input.rs index 310f1bcb..86ce8577 100644 --- a/src/api/x11/input.rs +++ b/src/api/x11/input.rs @@ -170,7 +170,7 @@ impl XInputEventHandler { } pub fn translate_event(&mut self, cookie: &ffi::XGenericEventCookie) -> Option { - use events::Event::{Focused, MouseInput, MouseMoved, MouseWheel}; + use events::Event::{Focused, MouseEntered, MouseInput, MouseLeft, MouseMoved, MouseWheel}; use events::ElementState::{Pressed, Released}; use events::MouseButton::{Left, Right, Middle}; use events::MouseScrollDelta::LineDelta; @@ -254,9 +254,9 @@ impl XInputEventHandler { // our window however, so clear the previous axis state whenever // the cursor re-enters the window self.current_state.axis_values.clear(); - None + Some(MouseEntered) }, - ffi::XI_Leave => None, + ffi::XI_Leave => Some(MouseLeft), ffi::XI_FocusIn => Some(Focused(true)), ffi::XI_FocusOut => Some(Focused(false)), ffi::XI_TouchBegin | ffi::XI_TouchUpdate | ffi::XI_TouchEnd => { diff --git a/src/events.rs b/src/events.rs index 7186256c..b6fd7732 100644 --- a/src/events.rs +++ b/src/events.rs @@ -30,6 +30,12 @@ pub enum Event { /// The parameter are the (x,y) coords in pixels relative to the top-left corner of the window. MouseMoved(i32, i32), + /// The cursor has entered the window. + MouseEntered, + + /// The cursor has left the window. + MouseLeft, + /// A mouse wheel movement or touchpad scroll occurred. MouseWheel(MouseScrollDelta, TouchPhase), diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index 0a8a0e42..2ed0e895 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -683,6 +683,8 @@ unsafe fn NSEventToEvent(window: &Window, nsevent: id) -> Option { appkit::NSLeftMouseUp => { Some(Event::MouseInput(ElementState::Released, MouseButton::Left)) }, appkit::NSRightMouseDown => { Some(Event::MouseInput(ElementState::Pressed, MouseButton::Right)) }, appkit::NSRightMouseUp => { Some(Event::MouseInput(ElementState::Released, MouseButton::Right)) }, + appkit::NSMouseEntered => { Some(Event::MouseEntered) }, + appkit::NSMouseExited => { Some(Event::MouseLeft) }, appkit::NSMouseMoved | appkit::NSLeftMouseDragged | appkit::NSOtherMouseDragged | diff --git a/src/platform/windows/callback.rs b/src/platform/windows/callback.rs index 6f6bd2cb..26e1e95e 100644 --- a/src/platform/windows/callback.rs +++ b/src/platform/windows/callback.rs @@ -125,11 +125,14 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, } winapi::WM_MOUSEMOVE => { - use events::Event::MouseMoved; + use events::Event::{MouseEntered, MouseMoved}; CONTEXT_STASH.with(|context_stash| { let mut context_stash = context_stash.borrow_mut(); if let Some(context_stash) = context_stash.as_mut() { - context_stash.mouse_in_window = true; + if !context_stash.mouse_in_window { + send_event(window, MouseEntered); + context_stash.mouse_in_window = true; + } } }); @@ -142,10 +145,14 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_MOUSELEAVE => { + use events::Event::MouseLeft; CONTEXT_STASH.with(|context_stash| { let mut context_stash = context_stash.borrow_mut(); if let Some(context_stash) = context_stash.as_mut() { - context_stash.mouse_in_window = false; + if context_stash.mouse_in_window { + send_event(window, MouseLeft); + context_stash.mouse_in_window = false; + } } });