mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 13:31:29 +11:00
macOS: Only detect clicks+motion within client area (#561)
* macOS: Only detect clicks within client area * macOS: Only track mouse motion within client area * Add CHANGELOG entry about #463 fix
This commit is contained in:
parent
262490d074
commit
2b4b64f499
|
@ -11,6 +11,8 @@
|
||||||
- On macOS, `VirtualKeyCode::RWin` and `VirtualKeyCode::LWin` are no longer switched.
|
- On macOS, `VirtualKeyCode::RWin` and `VirtualKeyCode::LWin` are no longer switched.
|
||||||
- On macOS, windows without decorations can once again be resized.
|
- On macOS, windows without decorations can once again be resized.
|
||||||
- Fixed race conditions when creating an `EventsLoop` on X11, most commonly manifesting as "[xcb] Unknown sequence number while processing queue".
|
- Fixed race conditions when creating an `EventsLoop` on X11, most commonly manifesting as "[xcb] Unknown sequence number while processing queue".
|
||||||
|
- On macOS, `CursorMoved` and `MouseInput` events are only generated if they occurs within the window's client area.
|
||||||
|
- On macOS, resizing the window no longer generates a spurious `MouseInput` event.
|
||||||
|
|
||||||
# Version 0.15.0 (2018-05-22)
|
# Version 0.15.0 (2018-05-22)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use {ControlFlow, EventsLoopClosed};
|
use {ControlFlow, EventsLoopClosed};
|
||||||
use cocoa::{self, appkit, foundation};
|
use cocoa::{self, appkit, foundation};
|
||||||
use cocoa::appkit::{NSApplication, NSEvent, NSEventMask, NSEventModifierFlags, NSEventPhase, NSView, NSWindow};
|
use cocoa::appkit::{NSApplication, NSEvent, NSEventMask, NSEventModifierFlags, NSEventPhase, NSView, NSWindow};
|
||||||
use events::{self, ElementState, Event, MouseButton, TouchPhase, WindowEvent, DeviceEvent, ModifiersState, KeyboardInput};
|
use events::{self, ElementState, Event, TouchPhase, WindowEvent, DeviceEvent, ModifiersState, KeyboardInput};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::sync::{Arc, Mutex, Weak};
|
use std::sync::{Arc, Mutex, Weak};
|
||||||
use super::window::Window2;
|
use super::window::Window2;
|
||||||
|
@ -9,7 +9,6 @@ use std;
|
||||||
use std::os::raw::*;
|
use std::os::raw::*;
|
||||||
use super::DeviceId;
|
use super::DeviceId;
|
||||||
|
|
||||||
|
|
||||||
pub struct EventsLoop {
|
pub struct EventsLoop {
|
||||||
modifiers: Modifiers,
|
modifiers: Modifiers,
|
||||||
pub shared: Arc<Shared>,
|
pub shared: Arc<Shared>,
|
||||||
|
@ -363,13 +362,6 @@ impl EventsLoop {
|
||||||
event
|
event
|
||||||
},
|
},
|
||||||
|
|
||||||
appkit::NSLeftMouseDown => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Pressed, button: MouseButton::Left, modifiers: event_mods(ns_event) })) },
|
|
||||||
appkit::NSLeftMouseUp => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Released, button: MouseButton::Left, modifiers: event_mods(ns_event) })) },
|
|
||||||
appkit::NSRightMouseDown => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Pressed, button: MouseButton::Right, modifiers: event_mods(ns_event) })) },
|
|
||||||
appkit::NSRightMouseUp => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Released, button: MouseButton::Right, modifiers: event_mods(ns_event) })) },
|
|
||||||
appkit::NSOtherMouseDown => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Pressed, button: MouseButton::Middle, modifiers: event_mods(ns_event) })) },
|
|
||||||
appkit::NSOtherMouseUp => { Some(into_event(WindowEvent::MouseInput { device_id: DEVICE_ID, state: ElementState::Released, button: MouseButton::Middle, modifiers: event_mods(ns_event) })) },
|
|
||||||
|
|
||||||
appkit::NSMouseEntered => {
|
appkit::NSMouseEntered => {
|
||||||
let window = match maybe_window.or_else(maybe_key_window) {
|
let window = match maybe_window.or_else(maybe_key_window) {
|
||||||
Some(window) => window,
|
Some(window) => window,
|
||||||
|
@ -410,27 +402,9 @@ impl EventsLoop {
|
||||||
None => return None,
|
None => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let window_point = ns_event.locationInWindow();
|
|
||||||
let view_point = if ns_window == cocoa::base::nil {
|
|
||||||
let ns_size = foundation::NSSize::new(0.0, 0.0);
|
|
||||||
let ns_rect = foundation::NSRect::new(window_point, ns_size);
|
|
||||||
let window_rect = window.window.convertRectFromScreen_(ns_rect);
|
|
||||||
window.view.convertPoint_fromView_(window_rect.origin, cocoa::base::nil)
|
|
||||||
} else {
|
|
||||||
window.view.convertPoint_fromView_(window_point, cocoa::base::nil)
|
|
||||||
};
|
|
||||||
let view_rect = NSView::frame(*window.view);
|
|
||||||
let scale_factor = window.hidpi_factor();
|
let scale_factor = window.hidpi_factor();
|
||||||
|
|
||||||
let mut events = std::collections::VecDeque::new();
|
let mut events = std::collections::VecDeque::with_capacity(3);
|
||||||
|
|
||||||
{
|
|
||||||
let x = (scale_factor * view_point.x as f32) as f64;
|
|
||||||
let y = (scale_factor * (view_rect.size.height - view_point.y) as f32) as f64;
|
|
||||||
let window_event = WindowEvent::CursorMoved { device_id: DEVICE_ID, position: (x, y), modifiers: event_mods(ns_event) };
|
|
||||||
let event = Event::WindowEvent { window_id: ::WindowId(window.id()), event: window_event };
|
|
||||||
events.push_back(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
let delta_x = (scale_factor * ns_event.deltaX() as f32) as f64;
|
let delta_x = (scale_factor * ns_event.deltaX() as f32) as f64;
|
||||||
if delta_x != 0.0 {
|
if delta_x != 0.0 {
|
||||||
|
|
|
@ -8,12 +8,12 @@ use std::os::raw::*;
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
|
|
||||||
use cocoa::base::{class, id, nil};
|
use cocoa::base::{class, id, nil};
|
||||||
use cocoa::appkit::NSWindow;
|
use cocoa::appkit::{NSEvent, NSView, NSWindow};
|
||||||
use cocoa::foundation::{NSPoint, NSRect, NSSize, NSString, NSUInteger};
|
use cocoa::foundation::{NSPoint, NSRect, NSSize, NSString, NSUInteger};
|
||||||
use objc::declare::ClassDecl;
|
use objc::declare::ClassDecl;
|
||||||
use objc::runtime::{Class, Object, Protocol, Sel, BOOL};
|
use objc::runtime::{Class, Object, Protocol, Sel, BOOL};
|
||||||
|
|
||||||
use {ElementState, Event, KeyboardInput, WindowEvent, WindowId};
|
use {ElementState, Event, KeyboardInput, MouseButton, WindowEvent, WindowId};
|
||||||
use platform::platform::events_loop::{DEVICE_ID, event_mods, Shared, to_virtual_key_code};
|
use platform::platform::events_loop::{DEVICE_ID, event_mods, Shared, to_virtual_key_code};
|
||||||
use platform::platform::util;
|
use platform::platform::util;
|
||||||
use platform::platform::ffi::*;
|
use platform::platform::ffi::*;
|
||||||
|
@ -112,6 +112,16 @@ lazy_static! {
|
||||||
decl.add_method(sel!(keyUp:), key_up as extern fn(&Object, Sel, id));
|
decl.add_method(sel!(keyUp:), key_up as extern fn(&Object, Sel, id));
|
||||||
decl.add_method(sel!(insertTab:), insert_tab as extern fn(&Object, Sel, id));
|
decl.add_method(sel!(insertTab:), insert_tab as extern fn(&Object, Sel, id));
|
||||||
decl.add_method(sel!(insertBackTab:), insert_back_tab as extern fn(&Object, Sel, id));
|
decl.add_method(sel!(insertBackTab:), insert_back_tab as extern fn(&Object, Sel, id));
|
||||||
|
decl.add_method(sel!(mouseDown:), mouse_down as extern fn(&Object, Sel, id));
|
||||||
|
decl.add_method(sel!(mouseUp:), mouse_up as extern fn(&Object, Sel, id));
|
||||||
|
decl.add_method(sel!(rightMouseDown:), right_mouse_down as extern fn(&Object, Sel, id));
|
||||||
|
decl.add_method(sel!(rightMouseUp:), right_mouse_up as extern fn(&Object, Sel, id));
|
||||||
|
decl.add_method(sel!(otherMouseDown:), other_mouse_down as extern fn(&Object, Sel, id));
|
||||||
|
decl.add_method(sel!(otherMouseUp:), other_mouse_up as extern fn(&Object, Sel, id));
|
||||||
|
decl.add_method(sel!(mouseMoved:), mouse_moved as extern fn(&Object, Sel, id));
|
||||||
|
decl.add_method(sel!(mouseDragged:), mouse_dragged as extern fn(&Object, Sel, id));
|
||||||
|
decl.add_method(sel!(rightMouseDragged:), right_mouse_dragged as extern fn(&Object, Sel, id));
|
||||||
|
decl.add_method(sel!(otherMouseDragged:), other_mouse_dragged as extern fn(&Object, Sel, id));
|
||||||
decl.add_ivar::<*mut c_void>("winitState");
|
decl.add_ivar::<*mut c_void>("winitState");
|
||||||
decl.add_ivar::<id>("markedText");
|
decl.add_ivar::<id>("markedText");
|
||||||
let protocol = Protocol::get("NSTextInputClient").unwrap();
|
let protocol = Protocol::get("NSTextInputClient").unwrap();
|
||||||
|
@ -448,3 +458,109 @@ extern fn insert_back_tab(this: &Object, _sel: Sel, _sender: id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mouse_click(this: &Object, event: id, button: MouseButton, button_state: ElementState) {
|
||||||
|
unsafe {
|
||||||
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
|
let state = &mut *(state_ptr as *mut ViewState);
|
||||||
|
|
||||||
|
let window_event = Event::WindowEvent {
|
||||||
|
window_id: WindowId(get_window_id(state.window)),
|
||||||
|
event: WindowEvent::MouseInput {
|
||||||
|
device_id: DEVICE_ID,
|
||||||
|
state: button_state,
|
||||||
|
button,
|
||||||
|
modifiers: event_mods(event),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(shared) = state.shared.upgrade() {
|
||||||
|
shared.pending_events
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.push_back(window_event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||||
|
mouse_click(this, event, MouseButton::Left, ElementState::Pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||||
|
mouse_click(this, event, MouseButton::Left, ElementState::Released);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn right_mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||||
|
mouse_click(this, event, MouseButton::Right, ElementState::Pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn right_mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||||
|
mouse_click(this, event, MouseButton::Right, ElementState::Released);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn other_mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||||
|
mouse_click(this, event, MouseButton::Middle, ElementState::Pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn other_mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||||
|
mouse_click(this, event, MouseButton::Middle, ElementState::Released);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mouse_motion(this: &Object, event: id) {
|
||||||
|
unsafe {
|
||||||
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
|
let state = &mut *(state_ptr as *mut ViewState);
|
||||||
|
|
||||||
|
// We have to do this to have access to the `NSView` trait...
|
||||||
|
let view: id = this as *const _ as *mut _;
|
||||||
|
|
||||||
|
let window_point = event.locationInWindow();
|
||||||
|
let view_point = view.convertPoint_fromView_(window_point, nil);
|
||||||
|
let view_rect = NSView::frame(view);
|
||||||
|
|
||||||
|
if view_point.x.is_sign_negative()
|
||||||
|
|| view_point.y.is_sign_negative()
|
||||||
|
|| view_point.x > view_rect.size.width
|
||||||
|
|| view_point.y > view_rect.size.height {
|
||||||
|
// Point is outside of the client area (view)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let scale_factor = NSWindow::backingScaleFactor(state.window) as f64;
|
||||||
|
let x = scale_factor * view_point.x as f64;
|
||||||
|
let y = scale_factor * (view_rect.size.height as f64 - view_point.y as f64);
|
||||||
|
|
||||||
|
let window_event = Event::WindowEvent {
|
||||||
|
window_id: WindowId(get_window_id(state.window)),
|
||||||
|
event: WindowEvent::CursorMoved {
|
||||||
|
device_id: DEVICE_ID,
|
||||||
|
position: (x, y),
|
||||||
|
modifiers: event_mods(event),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(shared) = state.shared.upgrade() {
|
||||||
|
shared.pending_events
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.push_back(window_event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn mouse_moved(this: &Object, _sel: Sel, event: id) {
|
||||||
|
mouse_motion(this, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn mouse_dragged(this: &Object, _sel: Sel, event: id) {
|
||||||
|
mouse_motion(this, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn right_mouse_dragged(this: &Object, _sel: Sel, event: id) {
|
||||||
|
mouse_motion(this, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn other_mouse_dragged(this: &Object, _sel: Sel, event: id) {
|
||||||
|
mouse_motion(this, event);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue