2019-05-01 17:03:30 -06:00
use std ::{
2019-06-21 11:33:15 -04:00
boxed ::Box ,
collections ::VecDeque ,
os ::raw ::* ,
2022-01-10 21:39:17 +01:00
ptr , slice , str ,
2019-05-01 17:03:30 -06:00
sync ::{ Arc , Mutex , Weak } ,
} ;
use cocoa ::{
appkit ::{ NSApp , NSEvent , NSEventModifierFlags , NSEventPhase , NSView , NSWindow } ,
2019-06-21 11:33:15 -04:00
base ::{ id , nil } ,
2019-12-31 05:32:37 +09:00
foundation ::{ NSInteger , NSPoint , NSRect , NSSize , NSString , NSUInteger } ,
2019-06-21 11:33:15 -04:00
} ;
use objc ::{
declare ::ClassDecl ,
runtime ::{ Class , Object , Protocol , Sel , BOOL , NO , YES } ,
2019-05-01 17:03:30 -06:00
} ;
2019-06-18 02:27:00 +08:00
use crate ::{
2020-01-12 18:50:34 +01:00
dpi ::LogicalPosition ,
2019-05-01 17:03:30 -06:00
event ::{
2019-12-12 22:48:32 +01:00
DeviceEvent , ElementState , Event , KeyboardInput , ModifiersState , MouseButton ,
MouseScrollDelta , TouchPhase , VirtualKeyCode , WindowEvent ,
2019-06-21 11:33:15 -04:00
} ,
platform_impl ::platform ::{
app_state ::AppState ,
event ::{
char_to_keycode , check_function_keys , event_mods , get_scancode , modifier_event ,
2020-01-04 01:32:34 -05:00
scancode_to_keycode , EventWrapper ,
2019-06-21 11:33:15 -04:00
} ,
ffi ::* ,
2022-01-02 22:01:51 +01:00
util ::{ self , IdRef } ,
2019-06-21 11:33:15 -04:00
window ::get_window_id ,
DEVICE_ID ,
2019-05-01 17:03:30 -06:00
} ,
window ::WindowId ,
} ;
2020-01-03 09:34:14 +09:00
pub struct CursorState {
pub visible : bool ,
pub cursor : util ::Cursor ,
}
impl Default for CursorState {
fn default ( ) -> Self {
Self {
visible : true ,
cursor : Default ::default ( ) ,
}
}
}
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
pub ( super ) struct ViewState {
2019-06-11 01:09:38 +02:00
ns_window : id ,
2020-01-03 09:34:14 +09:00
pub cursor_state : Arc < Mutex < CursorState > > ,
2018-06-14 19:42:18 -04:00
ime_spot : Option < ( f64 , f64 ) > ,
2018-05-17 21:28:30 -04:00
raw_characters : Option < String > ,
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
pub ( super ) modifiers : ModifiersState ,
2019-12-31 05:32:37 +09:00
tracking_rect : Option < NSInteger > ,
2018-05-17 21:28:30 -04:00
}
2020-01-12 18:50:34 +01:00
impl ViewState {
fn get_scale_factor ( & self ) -> f64 {
( unsafe { NSWindow ::backingScaleFactor ( self . ns_window ) } ) as f64
}
}
2020-01-03 09:34:14 +09:00
pub fn new_view ( ns_window : id ) -> ( IdRef , Weak < Mutex < CursorState > > ) {
let cursor_state = Default ::default ( ) ;
let cursor_access = Arc ::downgrade ( & cursor_state ) ;
2018-05-22 09:05:33 -04:00
let state = ViewState {
2019-06-11 01:09:38 +02:00
ns_window ,
2020-01-03 09:34:14 +09:00
cursor_state ,
2018-05-22 09:05:33 -04:00
ime_spot : None ,
raw_characters : None ,
2019-05-01 17:03:30 -06:00
modifiers : Default ::default ( ) ,
2019-12-31 05:32:37 +09:00
tracking_rect : None ,
2018-05-22 09:05:33 -04:00
} ;
2018-05-17 21:28:30 -04:00
unsafe {
// This is free'd in `dealloc`
let state_ptr = Box ::into_raw ( Box ::new ( state ) ) as * mut c_void ;
2019-06-11 01:09:38 +02:00
let ns_view : id = msg_send! [ VIEW_CLASS . 0 , alloc ] ;
2019-06-21 11:33:15 -04:00
(
IdRef ::new ( msg_send! [ ns_view , initWithWinit : state_ptr ] ) ,
cursor_access ,
)
2018-05-17 21:28:30 -04:00
}
}
2019-06-11 01:09:38 +02:00
pub unsafe fn set_ime_position ( ns_view : id , input_context : id , x : f64 , y : f64 ) {
let state_ptr : * mut c_void = * ( * ns_view ) . get_mut_ivar ( " winitState " ) ;
2019-05-01 17:03:30 -06:00
let state = & mut * ( state_ptr as * mut ViewState ) ;
2019-06-21 11:33:15 -04:00
let content_rect =
NSWindow ::contentRectForFrameRect_ ( state . ns_window , NSWindow ::frame ( state . ns_window ) ) ;
2019-05-01 17:03:30 -06:00
let base_x = content_rect . origin . x as f64 ;
let base_y = ( content_rect . origin . y + content_rect . size . height ) as f64 ;
state . ime_spot = Some ( ( base_x + x , base_y - y ) ) ;
let _ : ( ) = msg_send! [ input_context , invalidateCharacterCoordinates ] ;
2018-05-17 21:28:30 -04:00
}
struct ViewClass ( * const Class ) ;
unsafe impl Send for ViewClass { }
unsafe impl Sync for ViewClass { }
lazy_static! {
static ref VIEW_CLASS : ViewClass = unsafe {
2018-07-19 10:02:33 -06:00
let superclass = class! ( NSView ) ;
2018-05-17 21:28:30 -04:00
let mut decl = ClassDecl ::new ( " WinitView " , superclass ) . unwrap ( ) ;
2019-06-21 11:33:15 -04:00
decl . add_method ( sel! ( dealloc ) , dealloc as extern " C " fn ( & Object , Sel ) ) ;
2018-05-17 21:28:30 -04:00
decl . add_method (
sel! ( initWithWinit :) ,
2019-06-21 11:33:15 -04:00
init_with_winit as extern " C " fn ( & Object , Sel , * mut c_void ) -> id ,
2018-05-17 21:28:30 -04:00
) ;
2019-05-01 17:03:30 -06:00
decl . add_method (
sel! ( viewDidMoveToWindow ) ,
2019-06-21 11:33:15 -04:00
view_did_move_to_window as extern " C " fn ( & Object , Sel ) ,
2019-05-01 17:03:30 -06:00
) ;
2018-12-27 15:16:58 -05:00
decl . add_method (
sel! ( drawRect :) ,
2019-08-13 21:01:22 -07:00
draw_rect as extern " C " fn ( & Object , Sel , NSRect ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( acceptsFirstResponder ) ,
2019-06-21 11:33:15 -04:00
accepts_first_responder as extern " C " fn ( & Object , Sel ) -> BOOL ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( touchBar ) ,
2019-06-21 11:33:15 -04:00
touch_bar as extern " C " fn ( & Object , Sel ) -> BOOL ,
2018-12-27 15:16:58 -05:00
) ;
2018-12-28 15:29:29 -05:00
decl . add_method (
sel! ( resetCursorRects ) ,
2019-06-21 11:33:15 -04:00
reset_cursor_rects as extern " C " fn ( & Object , Sel ) ,
2018-12-28 15:29:29 -05:00
) ;
2019-05-01 17:03:30 -06:00
decl . add_method (
sel! ( hasMarkedText ) ,
2019-06-21 11:33:15 -04:00
has_marked_text as extern " C " fn ( & Object , Sel ) -> BOOL ,
2019-05-01 17:03:30 -06:00
) ;
2018-05-17 21:28:30 -04:00
decl . add_method (
sel! ( markedRange ) ,
2019-06-21 11:33:15 -04:00
marked_range as extern " C " fn ( & Object , Sel ) -> NSRange ,
2018-05-17 21:28:30 -04:00
) ;
2019-05-01 17:03:30 -06:00
decl . add_method (
sel! ( selectedRange ) ,
2019-06-21 11:33:15 -04:00
selected_range as extern " C " fn ( & Object , Sel ) -> NSRange ,
2019-05-01 17:03:30 -06:00
) ;
2018-05-17 21:28:30 -04:00
decl . add_method (
sel! ( setMarkedText :selectedRange :replacementRange :) ,
2019-06-21 11:33:15 -04:00
set_marked_text as extern " C " fn ( & mut Object , Sel , id , NSRange , NSRange ) ,
2019-05-01 17:03:30 -06:00
) ;
2022-01-02 22:01:51 +01:00
decl . add_method ( sel! ( unmarkText ) , unmark_text as extern " C " fn ( & Object , Sel ) ) ;
2018-05-17 21:28:30 -04:00
decl . add_method (
sel! ( validAttributesForMarkedText ) ,
2019-06-21 11:33:15 -04:00
valid_attributes_for_marked_text as extern " C " fn ( & Object , Sel ) -> id ,
2018-05-17 21:28:30 -04:00
) ;
decl . add_method (
sel! ( attributedSubstringForProposedRange :actualRange :) ,
2019-06-21 11:33:15 -04:00
attributed_substring_for_proposed_range
as extern " C " fn ( & Object , Sel , NSRange , * mut c_void ) -> id ,
2018-05-17 21:28:30 -04:00
) ;
decl . add_method (
sel! ( insertText :replacementRange :) ,
2022-01-02 22:01:51 +01:00
insert_text as extern " C " fn ( & Object , Sel , id , NSRange ) ,
2018-05-17 21:28:30 -04:00
) ;
decl . add_method (
sel! ( characterIndexForPoint :) ,
2019-06-21 11:33:15 -04:00
character_index_for_point as extern " C " fn ( & Object , Sel , NSPoint ) -> NSUInteger ,
2018-05-17 21:28:30 -04:00
) ;
decl . add_method (
sel! ( firstRectForCharacterRange :actualRange :) ,
2019-06-21 11:33:15 -04:00
first_rect_for_character_range
as extern " C " fn ( & Object , Sel , NSRange , * mut c_void ) -> NSRect ,
2018-05-17 21:28:30 -04:00
) ;
decl . add_method (
sel! ( doCommandBySelector :) ,
2019-06-21 11:33:15 -04:00
do_command_by_selector as extern " C " fn ( & Object , Sel , Sel ) ,
2019-05-01 17:03:30 -06:00
) ;
2019-06-21 11:33:15 -04:00
decl . add_method ( sel! ( keyDown :) , key_down as extern " C " fn ( & Object , Sel , id ) ) ;
decl . add_method ( sel! ( keyUp :) , key_up as extern " C " fn ( & Object , Sel , id ) ) ;
2019-05-01 17:03:30 -06:00
decl . add_method (
sel! ( flagsChanged :) ,
2019-06-21 11:33:15 -04:00
flags_changed as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( insertTab :) ,
2019-06-21 11:33:15 -04:00
insert_tab as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( insertBackTab :) ,
2019-06-21 11:33:15 -04:00
insert_back_tab as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( mouseDown :) ,
2019-06-21 11:33:15 -04:00
mouse_down as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
2019-06-21 11:33:15 -04:00
decl . add_method ( sel! ( mouseUp :) , mouse_up as extern " C " fn ( & Object , Sel , id ) ) ;
2019-05-01 17:03:30 -06:00
decl . add_method (
sel! ( rightMouseDown :) ,
2019-06-21 11:33:15 -04:00
right_mouse_down as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( rightMouseUp :) ,
2019-06-21 11:33:15 -04:00
right_mouse_up as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( otherMouseDown :) ,
2019-06-21 11:33:15 -04:00
other_mouse_down as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( otherMouseUp :) ,
2019-06-21 11:33:15 -04:00
other_mouse_up as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( mouseMoved :) ,
2019-06-21 11:33:15 -04:00
mouse_moved as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( mouseDragged :) ,
2019-06-21 11:33:15 -04:00
mouse_dragged as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( rightMouseDragged :) ,
2019-06-21 11:33:15 -04:00
right_mouse_dragged as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( otherMouseDragged :) ,
2019-06-21 11:33:15 -04:00
other_mouse_dragged as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( mouseEntered :) ,
2019-06-21 11:33:15 -04:00
mouse_entered as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( mouseExited :) ,
2019-06-21 11:33:15 -04:00
mouse_exited as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( scrollWheel :) ,
2019-06-21 11:33:15 -04:00
scroll_wheel as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( pressureChangeWithEvent :) ,
2019-06-21 11:33:15 -04:00
pressure_change_with_event as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( _wantsKeyDownForEvent :) ,
2019-06-21 11:33:15 -04:00
wants_key_down_for_event as extern " C " fn ( & Object , Sel , id ) -> BOOL ,
2019-05-01 17:03:30 -06:00
) ;
decl . add_method (
sel! ( cancelOperation :) ,
2019-06-21 11:33:15 -04:00
cancel_operation as extern " C " fn ( & Object , Sel , id ) ,
2019-05-01 17:03:30 -06:00
) ;
2019-12-31 05:32:37 +09:00
decl . add_method (
sel! ( frameDidChange :) ,
frame_did_change as extern " C " fn ( & Object , Sel , id ) ,
) ;
2021-04-30 17:30:09 +08:00
decl . add_method (
sel! ( acceptsFirstMouse :) ,
accepts_first_mouse as extern " C " fn ( & Object , Sel , id ) -> BOOL ,
) ;
2018-05-17 21:28:30 -04:00
decl . add_ivar ::< * mut c_void > ( " winitState " ) ;
2022-01-02 22:01:51 +01:00
decl . add_ivar ::< id > ( " markedText " ) ;
2018-05-17 21:28:30 -04:00
let protocol = Protocol ::get ( " NSTextInputClient " ) . unwrap ( ) ;
2022-01-16 11:14:59 +11:00
decl . add_protocol ( protocol ) ;
2018-05-17 21:28:30 -04:00
ViewClass ( decl . register ( ) )
} ;
}
2019-06-21 11:33:15 -04:00
extern " C " fn dealloc ( this : & Object , _sel : Sel ) {
2018-05-17 21:28:30 -04:00
unsafe {
let state : * mut c_void = * this . get_ivar ( " winitState " ) ;
2022-01-02 22:01:51 +01:00
let marked_text : id = * this . get_ivar ( " markedText " ) ;
let _ : ( ) = msg_send! [ marked_text , release ] ;
Box ::from_raw ( state as * mut ViewState ) ;
2018-05-17 21:28:30 -04:00
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn init_with_winit ( this : & Object , _sel : Sel , state : * mut c_void ) -> id {
2018-05-17 21:28:30 -04:00
unsafe {
let this : id = msg_send! [ this , init ] ;
if this ! = nil {
( * this ) . set_ivar ( " winitState " , state ) ;
2022-01-02 22:01:51 +01:00
let marked_text =
< id as NSMutableAttributedString > ::init ( NSMutableAttributedString ::alloc ( nil ) ) ;
( * this ) . set_ivar ( " markedText " , marked_text ) ;
2019-12-31 05:32:37 +09:00
let _ : ( ) = msg_send! [ this , setPostsFrameChangedNotifications : YES ] ;
let notification_center : & Object =
msg_send! [ class! ( NSNotificationCenter ) , defaultCenter ] ;
let notification_name =
2021-05-27 17:38:41 +02:00
IdRef ::new ( NSString ::alloc ( nil ) . init_str ( " NSViewFrameDidChangeNotification " ) ) ;
2019-12-31 05:32:37 +09:00
let _ : ( ) = msg_send! [
notification_center ,
addObserver : this
selector : sel ! ( frameDidChange :)
name : notification_name
object : this
] ;
2018-05-17 21:28:30 -04:00
}
this
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn view_did_move_to_window ( this : & Object , _sel : Sel ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " viewDidMoveToWindow " ) ;
2019-05-01 17:03:30 -06:00
unsafe {
2019-12-31 05:32:37 +09:00
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
if let Some ( tracking_rect ) = state . tracking_rect . take ( ) {
let _ : ( ) = msg_send! [ this , removeTrackingRect : tracking_rect ] ;
}
2019-05-01 17:03:30 -06:00
let rect : NSRect = msg_send! [ this , visibleRect ] ;
2019-12-31 05:32:37 +09:00
let tracking_rect : NSInteger = msg_send! [ this ,
2019-05-01 17:03:30 -06:00
addTrackingRect :rect
owner :this
2022-01-10 21:39:17 +01:00
userData :ptr ::null_mut ::< c_void > ( )
2019-05-01 17:03:30 -06:00
assumeInside :NO
] ;
2019-12-31 05:32:37 +09:00
state . tracking_rect = Some ( tracking_rect ) ;
2019-05-01 17:03:30 -06:00
}
}
2019-12-31 05:32:37 +09:00
extern " C " fn frame_did_change ( this : & Object , _sel : Sel , _event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " frameDidChange: " ) ;
2019-12-31 05:32:37 +09:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
if let Some ( tracking_rect ) = state . tracking_rect . take ( ) {
let _ : ( ) = msg_send! [ this , removeTrackingRect : tracking_rect ] ;
}
let rect : NSRect = msg_send! [ this , visibleRect ] ;
let tracking_rect : NSInteger = msg_send! [ this ,
addTrackingRect :rect
owner :this
2022-01-10 21:39:17 +01:00
userData :ptr ::null_mut ::< c_void > ( )
2019-12-31 05:32:37 +09:00
assumeInside :NO
] ;
state . tracking_rect = Some ( tracking_rect ) ;
}
}
2019-08-13 21:01:22 -07:00
extern " C " fn draw_rect ( this : & Object , _sel : Sel , rect : NSRect ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " drawRect: " ) ;
2018-12-27 15:16:58 -05:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
2021-04-06 15:22:38 +08:00
AppState ::handle_redraw ( WindowId ( get_window_id ( state . ns_window ) ) ) ;
2018-12-27 15:16:58 -05:00
let superclass = util ::superclass ( this ) ;
2019-06-21 11:33:15 -04:00
let ( ) = msg_send! [ super ( this , superclass ) , drawRect : rect ] ;
2018-12-27 15:16:58 -05:00
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn accepts_first_responder ( _this : & Object , _sel : Sel ) -> BOOL {
2022-01-23 21:35:26 +01:00
trace_scope! ( " acceptsFirstResponder " ) ;
2019-05-01 17:03:30 -06:00
YES
}
// This is necessary to prevent a beefy terminal error on MacBook Pros:
// IMKInputSession [0x7fc573576ff0 presentFunctionRowItemTextInputViewWithEndpoint:completionHandler:] : [self textInputContext]=0x7fc573558e10 *NO* NSRemoteViewController to client, NSError=Error Domain=NSCocoaErrorDomain Code=4099 "The connection from pid 0 was invalidated from this process." UserInfo={NSDebugDescription=The connection from pid 0 was invalidated from this process.}, com.apple.inputmethod.EmojiFunctionRowItem
// TODO: Add an API extension for using `NSTouchBar`
2019-06-21 11:33:15 -04:00
extern " C " fn touch_bar ( _this : & Object , _sel : Sel ) -> BOOL {
2022-01-23 21:35:26 +01:00
trace_scope! ( " touchBar " ) ;
2019-05-01 17:03:30 -06:00
NO
}
2019-06-21 11:33:15 -04:00
extern " C " fn reset_cursor_rects ( this : & Object , _sel : Sel ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " resetCursorRects " ) ;
2018-12-28 15:29:29 -05:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
let bounds : NSRect = msg_send! [ this , bounds ] ;
2020-01-03 09:34:14 +09:00
let cursor_state = state . cursor_state . lock ( ) . unwrap ( ) ;
let cursor = if cursor_state . visible {
cursor_state . cursor . load ( )
} else {
util ::invisible_cursor ( )
} ;
2018-12-28 15:29:29 -05:00
let _ : ( ) = msg_send! [ this ,
addCursorRect :bounds
cursor :cursor
] ;
}
}
2020-03-09 23:57:04 +03:00
extern " C " fn has_marked_text ( this : & Object , _sel : Sel ) -> BOOL {
2022-01-23 21:35:26 +01:00
trace_scope! ( " hasMarkedText " ) ;
2020-03-09 23:57:04 +03:00
unsafe {
2022-01-02 22:01:51 +01:00
let marked_text : id = * this . get_ivar ( " markedText " ) ;
( marked_text . length ( ) > 0 ) as BOOL
2020-03-09 23:57:04 +03:00
}
2018-05-17 21:28:30 -04:00
}
2019-06-21 11:33:15 -04:00
extern " C " fn marked_range ( this : & Object , _sel : Sel ) -> NSRange {
2022-01-23 21:35:26 +01:00
trace_scope! ( " markedRange " ) ;
2018-05-17 21:28:30 -04:00
unsafe {
2022-01-02 22:01:51 +01:00
let marked_text : id = * this . get_ivar ( " markedText " ) ;
let length = marked_text . length ( ) ;
2018-05-17 21:28:30 -04:00
if length > 0 {
NSRange ::new ( 0 , length - 1 )
} else {
util ::EMPTY_RANGE
}
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn selected_range ( _this : & Object , _sel : Sel ) -> NSRange {
2022-01-23 21:35:26 +01:00
trace_scope! ( " selectedRange " ) ;
2018-05-17 21:28:30 -04:00
util ::EMPTY_RANGE
}
2019-06-21 11:33:15 -04:00
extern " C " fn set_marked_text (
2018-05-17 21:28:30 -04:00
this : & mut Object ,
_sel : Sel ,
string : id ,
_selected_range : NSRange ,
_replacement_range : NSRange ,
) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " setMarkedText:selectedRange:replacementRange: " ) ;
2018-05-17 21:28:30 -04:00
unsafe {
2022-01-02 22:01:51 +01:00
let marked_text_ref : & mut id = this . get_mut_ivar ( " markedText " ) ;
let _ : ( ) = msg_send! [ ( * marked_text_ref ) , release ] ;
let marked_text = NSMutableAttributedString ::alloc ( nil ) ;
2022-01-10 21:39:17 +01:00
let has_attr : BOOL = msg_send! [ string , isKindOfClass : class ! ( NSAttributedString ) ] ;
if has_attr ! = NO {
2022-01-02 22:01:51 +01:00
marked_text . initWithAttributedString ( string ) ;
2018-05-17 21:28:30 -04:00
} else {
2022-01-02 22:01:51 +01:00
marked_text . initWithString ( string ) ;
2018-05-17 21:28:30 -04:00
} ;
2022-01-02 22:01:51 +01:00
* marked_text_ref = marked_text ;
2018-05-17 21:28:30 -04:00
}
}
2022-01-02 22:01:51 +01:00
extern " C " fn unmark_text ( this : & Object , _sel : Sel ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " unmarkText " ) ;
2018-05-17 21:28:30 -04:00
unsafe {
2022-01-02 22:01:51 +01:00
let marked_text : id = * this . get_ivar ( " markedText " ) ;
let mutable_string = marked_text . mutableString ( ) ;
2022-01-10 21:39:17 +01:00
let s : id = msg_send! [ class! ( NSString ) , new ] ;
let _ : ( ) = msg_send! [ mutable_string , setString : s ] ;
let _ : ( ) = msg_send! [ s , release ] ;
2022-01-02 22:01:51 +01:00
let input_context : id = msg_send! [ this , inputContext ] ;
let _ : ( ) = msg_send! [ input_context , discardMarkedText ] ;
2018-05-17 21:28:30 -04:00
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn valid_attributes_for_marked_text ( _this : & Object , _sel : Sel ) -> id {
2022-01-23 21:35:26 +01:00
trace_scope! ( " validAttributesForMarkedText " ) ;
2018-07-19 10:02:33 -06:00
unsafe { msg_send! [ class! ( NSArray ) , array ] }
2018-05-17 21:28:30 -04:00
}
2019-06-21 11:33:15 -04:00
extern " C " fn attributed_substring_for_proposed_range (
2018-05-17 21:28:30 -04:00
_this : & Object ,
_sel : Sel ,
_range : NSRange ,
_actual_range : * mut c_void , // *mut NSRange
) -> id {
2022-01-23 21:35:26 +01:00
trace_scope! ( " attributedSubstringForProposedRange:actualRange: " ) ;
2018-05-17 21:28:30 -04:00
nil
}
2019-06-21 11:33:15 -04:00
extern " C " fn character_index_for_point ( _this : & Object , _sel : Sel , _point : NSPoint ) -> NSUInteger {
2022-01-23 21:35:26 +01:00
trace_scope! ( " characterIndexForPoint: " ) ;
2018-05-17 21:28:30 -04:00
0
}
2019-06-21 11:33:15 -04:00
extern " C " fn first_rect_for_character_range (
2018-05-17 21:28:30 -04:00
this : & Object ,
_sel : Sel ,
_range : NSRange ,
_actual_range : * mut c_void , // *mut NSRange
) -> NSRect {
2022-01-23 21:35:26 +01:00
trace_scope! ( " firstRectForCharacterRange:actualRange: " ) ;
2018-05-17 21:28:30 -04:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
let ( x , y ) = state . ime_spot . unwrap_or_else ( | | {
let content_rect = NSWindow ::contentRectForFrameRect_ (
2019-06-11 01:09:38 +02:00
state . ns_window ,
NSWindow ::frame ( state . ns_window ) ,
2018-05-17 21:28:30 -04:00
) ;
let x = content_rect . origin . x ;
let y = util ::bottom_left_to_top_left ( content_rect ) ;
2018-06-14 19:42:18 -04:00
( x , y )
2018-05-17 21:28:30 -04:00
} ) ;
2019-06-21 11:33:15 -04:00
NSRect ::new ( NSPoint ::new ( x as _ , y as _ ) , NSSize ::new ( 0.0 , 0.0 ) )
2018-05-17 21:28:30 -04:00
}
}
2022-01-02 22:01:51 +01:00
extern " C " fn insert_text ( this : & Object , _sel : Sel , string : id , _replacement_range : NSRange ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " insertText:replacementRange: " ) ;
2018-05-17 21:28:30 -04:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
2022-01-10 21:39:17 +01:00
let has_attr : BOOL = msg_send! [ string , isKindOfClass : class ! ( NSAttributedString ) ] ;
let characters = if has_attr ! = NO {
2018-05-17 21:28:30 -04:00
// This is a *mut NSAttributedString
msg_send! [ string , string ]
} else {
// This is already a *mut NSString
string
} ;
2019-06-21 11:33:15 -04:00
let slice =
slice ::from_raw_parts ( characters . UTF8String ( ) as * const c_uchar , characters . len ( ) ) ;
2018-05-17 21:28:30 -04:00
let string = str ::from_utf8_unchecked ( slice ) ;
// We don't need this now, but it's here if that changes.
2019-05-01 17:03:30 -06:00
//let event: id = msg_send![NSApp(), currentEvent];
2018-05-17 21:28:30 -04:00
let mut events = VecDeque ::with_capacity ( characters . len ( ) ) ;
2019-11-27 10:14:36 +01:00
for character in string . chars ( ) . filter ( | c | ! is_corporate_character ( * c ) ) {
2020-01-04 01:32:34 -05:00
events . push_back ( EventWrapper ::StaticEvent ( Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2018-05-17 21:28:30 -04:00
event : WindowEvent ::ReceivedCharacter ( character ) ,
2020-01-04 01:32:34 -05:00
} ) ) ;
2018-05-17 21:28:30 -04:00
}
2019-05-01 17:03:30 -06:00
AppState ::queue_events ( events ) ;
2018-05-17 21:28:30 -04:00
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn do_command_by_selector ( this : & Object , _sel : Sel , command : Sel ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " doCommandBySelector: " ) ;
2018-05-17 21:28:30 -04:00
// Basically, we're sent this message whenever a keyboard event that doesn't generate a "human readable" character
// happens, i.e. newlines, tabs, and Ctrl+C.
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
let mut events = VecDeque ::with_capacity ( 1 ) ;
if command = = sel! ( insertNewline :) {
// The `else` condition would emit the same character, but I'm keeping this here both...
// 1) as a reminder for how `doCommandBySelector` works
2018-05-22 09:05:33 -04:00
// 2) to make our use of carriage return explicit
2020-01-04 01:32:34 -05:00
events . push_back ( EventWrapper ::StaticEvent ( Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2018-05-22 09:05:33 -04:00
event : WindowEvent ::ReceivedCharacter ( '\r' ) ,
2020-01-04 01:32:34 -05:00
} ) ) ;
2018-05-17 21:28:30 -04:00
} else {
let raw_characters = state . raw_characters . take ( ) ;
if let Some ( raw_characters ) = raw_characters {
2019-11-27 10:14:36 +01:00
for character in raw_characters
. chars ( )
. filter ( | c | ! is_corporate_character ( * c ) )
{
2020-01-04 01:32:34 -05:00
events . push_back ( EventWrapper ::StaticEvent ( Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2018-05-17 21:28:30 -04:00
event : WindowEvent ::ReceivedCharacter ( character ) ,
2020-01-04 01:32:34 -05:00
} ) ) ;
2018-05-17 21:28:30 -04:00
}
}
} ;
2019-05-01 17:03:30 -06:00
AppState ::queue_events ( events ) ;
2018-05-17 21:28:30 -04:00
}
}
2019-02-24 06:41:55 +10:00
fn get_characters ( event : id , ignore_modifiers : bool ) -> String {
2018-09-12 20:04:16 +03:00
unsafe {
2019-02-24 06:41:55 +10:00
let characters : id = if ignore_modifiers {
msg_send! [ event , charactersIgnoringModifiers ]
} else {
msg_send! [ event , characters ]
} ;
assert_ne! ( characters , nil ) ;
2019-06-21 11:33:15 -04:00
let slice =
slice ::from_raw_parts ( characters . UTF8String ( ) as * const c_uchar , characters . len ( ) ) ;
2019-02-24 06:41:55 +10:00
2018-09-12 20:04:16 +03:00
let string = str ::from_utf8_unchecked ( slice ) ;
2019-02-24 06:41:55 +10:00
string . to_owned ( )
}
}
2019-11-27 10:14:36 +01:00
// As defined in: https://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT
fn is_corporate_character ( c : char ) -> bool {
2022-01-16 11:14:59 +11:00
matches! ( c ,
2019-11-27 10:14:36 +01:00
'\u{F700}' ..= '\u{F747}'
| '\u{F802}' ..= '\u{F84F}'
| '\u{F850}'
| '\u{F85C}'
| '\u{F85D}'
| '\u{F85F}'
| '\u{F860}' ..= '\u{F86B}'
2022-01-16 11:14:59 +11:00
| '\u{F870}' ..= '\u{F8FF}'
)
2019-11-27 10:14:36 +01:00
}
2019-02-24 06:41:55 +10:00
// Retrieves a layout-independent keycode given an event.
2019-05-01 17:03:30 -06:00
fn retrieve_keycode ( event : id ) -> Option < VirtualKeyCode > {
2019-02-24 06:41:55 +10:00
#[ inline ]
2019-05-01 17:03:30 -06:00
fn get_code ( ev : id , raw : bool ) -> Option < VirtualKeyCode > {
2019-02-24 06:41:55 +10:00
let characters = get_characters ( ev , raw ) ;
2022-01-16 11:14:59 +11:00
characters . chars ( ) . next ( ) . and_then ( char_to_keycode )
2018-09-12 20:04:16 +03:00
}
2019-02-24 06:41:55 +10:00
// Cmd switches Roman letters for Dvorak-QWERTY layout, so we try modified characters first.
// If we don't get a match, then we fall back to unmodified characters.
2019-06-21 11:33:15 -04:00
let code = get_code ( event , false ) . or_else ( | | get_code ( event , true ) ) ;
2019-02-24 06:41:55 +10:00
// We've checked all layout related keys, so fall through to scancode.
// Reaching this code means that the key is layout-independent (e.g. Backspace, Return).
//
// We're additionally checking here for F21-F24 keys, since their keycode
// can vary, but we know that they are encoded
// in characters property.
code . or_else ( | | {
let scancode = get_scancode ( event ) ;
2019-06-21 11:33:15 -04:00
scancode_to_keycode ( scancode ) . or_else ( | | check_function_keys ( & get_characters ( event , true ) ) )
2019-02-24 06:41:55 +10:00
} )
2018-09-12 20:04:16 +03:00
}
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
// Update `state.modifiers` if `event` has something different
fn update_potentially_stale_modifiers ( state : & mut ViewState , event : id ) {
let event_modifiers = event_mods ( event ) ;
if state . modifiers ! = event_modifiers {
state . modifiers = event_modifiers ;
AppState ::queue_event ( EventWrapper ::StaticEvent ( Event ::WindowEvent {
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
event : WindowEvent ::ModifiersChanged ( state . modifiers ) ,
} ) ) ;
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn key_down ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " keyDown: " ) ;
2018-05-17 21:28:30 -04:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
2019-06-11 01:09:38 +02:00
let window_id = WindowId ( get_window_id ( state . ns_window ) ) ;
2019-02-24 06:41:55 +10:00
let characters = get_characters ( event , false ) ;
2018-05-17 21:28:30 -04:00
2019-02-24 06:41:55 +10:00
state . raw_characters = Some ( characters . clone ( ) ) ;
2018-09-12 20:04:16 +03:00
2019-02-24 06:41:55 +10:00
let scancode = get_scancode ( event ) as u32 ;
let virtual_keycode = retrieve_keycode ( event ) ;
2019-05-01 17:03:30 -06:00
2022-01-10 21:39:17 +01:00
let is_repeat : BOOL = msg_send! [ event , isARepeat ] ;
2018-05-17 21:28:30 -04:00
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
update_potentially_stale_modifiers ( state , event ) ;
2020-01-09 22:29:31 -07:00
#[ allow(deprecated) ]
2018-05-17 21:28:30 -04:00
let window_event = Event ::WindowEvent {
2018-05-22 09:05:33 -04:00
window_id ,
2018-05-17 21:28:30 -04:00
event : WindowEvent ::KeyboardInput {
device_id : DEVICE_ID ,
input : KeyboardInput {
state : ElementState ::Pressed ,
scancode ,
virtual_keycode ,
modifiers : event_mods ( event ) ,
} ,
2019-12-07 15:51:37 -07:00
is_synthetic : false ,
2018-05-17 21:28:30 -04:00
} ,
} ;
2019-05-01 17:03:30 -06:00
let pass_along = {
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( window_event ) ) ;
2018-05-22 09:05:33 -04:00
// Emit `ReceivedCharacter` for key repeats
2022-01-10 21:39:17 +01:00
if is_repeat ! = NO {
2019-11-27 10:14:36 +01:00
for character in characters . chars ( ) . filter ( | c | ! is_corporate_character ( * c ) ) {
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( Event ::WindowEvent {
2018-05-22 09:05:33 -04:00
window_id ,
event : WindowEvent ::ReceivedCharacter ( character ) ,
2020-01-04 01:32:34 -05:00
} ) ) ;
2018-05-22 09:05:33 -04:00
}
2019-05-01 17:03:30 -06:00
false
2018-06-17 15:08:26 -04:00
} else {
2019-05-01 17:03:30 -06:00
true
2018-05-22 09:05:33 -04:00
}
2019-05-01 17:03:30 -06:00
} ;
if pass_along {
// Some keys (and only *some*, with no known reason) don't trigger `insertText`, while others do...
// So, we don't give repeats the opportunity to trigger that, since otherwise our hack will cause some
// keys to generate twice as many characters.
2019-06-21 11:33:15 -04:00
let array : id = msg_send! [ class! ( NSArray ) , arrayWithObject : event ] ;
let _ : ( ) = msg_send! [ this , interpretKeyEvents : array ] ;
2018-05-17 21:28:30 -04:00
}
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn key_up ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " keyUp: " ) ;
2018-05-17 21:28:30 -04:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
2019-02-24 06:41:55 +10:00
let scancode = get_scancode ( event ) as u32 ;
let virtual_keycode = retrieve_keycode ( event ) ;
2018-09-12 20:04:16 +03:00
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
update_potentially_stale_modifiers ( state , event ) ;
2020-01-09 22:29:31 -07:00
#[ allow(deprecated) ]
2018-05-17 21:28:30 -04:00
let window_event = Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2018-05-17 21:28:30 -04:00
event : WindowEvent ::KeyboardInput {
device_id : DEVICE_ID ,
input : KeyboardInput {
state : ElementState ::Released ,
scancode ,
virtual_keycode ,
modifiers : event_mods ( event ) ,
} ,
2019-12-07 15:51:37 -07:00
is_synthetic : false ,
2018-05-17 21:28:30 -04:00
} ,
} ;
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( window_event ) ) ;
2019-05-01 17:03:30 -06:00
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn flags_changed ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " flagsChanged: " ) ;
2019-05-01 17:03:30 -06:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
let mut events = VecDeque ::with_capacity ( 4 ) ;
if let Some ( window_event ) = modifier_event (
event ,
NSEventModifierFlags ::NSShiftKeyMask ,
2019-12-28 15:36:06 -05:00
state . modifiers . shift ( ) ,
2019-05-01 17:03:30 -06:00
) {
2019-12-28 15:36:06 -05:00
state . modifiers . toggle ( ModifiersState ::SHIFT ) ;
2019-05-01 17:03:30 -06:00
events . push_back ( window_event ) ;
}
if let Some ( window_event ) = modifier_event (
event ,
NSEventModifierFlags ::NSControlKeyMask ,
2019-12-28 15:36:06 -05:00
state . modifiers . ctrl ( ) ,
2019-05-01 17:03:30 -06:00
) {
2019-12-28 15:36:06 -05:00
state . modifiers . toggle ( ModifiersState ::CTRL ) ;
2019-05-01 17:03:30 -06:00
events . push_back ( window_event ) ;
}
if let Some ( window_event ) = modifier_event (
event ,
NSEventModifierFlags ::NSCommandKeyMask ,
2019-12-28 15:36:06 -05:00
state . modifiers . logo ( ) ,
2019-05-01 17:03:30 -06:00
) {
2019-12-28 15:36:06 -05:00
state . modifiers . toggle ( ModifiersState ::LOGO ) ;
2019-05-01 17:03:30 -06:00
events . push_back ( window_event ) ;
}
if let Some ( window_event ) = modifier_event (
event ,
NSEventModifierFlags ::NSAlternateKeyMask ,
2019-12-28 15:36:06 -05:00
state . modifiers . alt ( ) ,
2019-05-01 17:03:30 -06:00
) {
2019-12-28 15:36:06 -05:00
state . modifiers . toggle ( ModifiersState ::ALT ) ;
2019-05-01 17:03:30 -06:00
events . push_back ( window_event ) ;
}
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
let window_id = WindowId ( get_window_id ( state . ns_window ) ) ;
2019-05-01 17:03:30 -06:00
for event in events {
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( Event ::WindowEvent {
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
window_id ,
2019-05-01 17:03:30 -06:00
event ,
2020-01-04 01:32:34 -05:00
} ) ) ;
2018-05-17 21:28:30 -04:00
}
2019-12-12 22:48:32 +01:00
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( Event ::WindowEvent {
window_id ,
event : WindowEvent ::ModifiersChanged ( state . modifiers ) ,
2020-01-04 01:32:34 -05:00
} ) ) ;
2018-05-17 21:28:30 -04:00
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn insert_tab ( this : & Object , _sel : Sel , _sender : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " insertTab: " ) ;
2018-05-17 21:28:30 -04:00
unsafe {
let window : id = msg_send! [ this , window ] ;
let first_responder : id = msg_send! [ window , firstResponder ] ;
let this_ptr = this as * const _ as * mut _ ;
if first_responder = = this_ptr {
2019-06-21 11:33:15 -04:00
let ( ) : _ = msg_send! [ window , selectNextKeyView : this ] ;
2018-05-17 21:28:30 -04:00
}
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn insert_back_tab ( this : & Object , _sel : Sel , _sender : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " insertBackTab: " ) ;
2018-05-17 21:28:30 -04:00
unsafe {
let window : id = msg_send! [ this , window ] ;
let first_responder : id = msg_send! [ window , firstResponder ] ;
let this_ptr = this as * const _ as * mut _ ;
if first_responder = = this_ptr {
2019-06-21 11:33:15 -04:00
let ( ) : _ = msg_send! [ window , selectPreviousKeyView : this ] ;
2018-05-17 21:28:30 -04:00
}
}
}
2018-06-11 11:16:39 -04:00
2019-05-01 17:03:30 -06:00
// Allows us to receive Cmd-. (the shortcut for closing a dialog)
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=300620#c6
2019-06-21 11:33:15 -04:00
extern " C " fn cancel_operation ( this : & Object , _sel : Sel , _sender : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " cancelOperation: " ) ;
2019-05-01 17:03:30 -06:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
let scancode = 0x2f ;
let virtual_keycode = scancode_to_keycode ( scancode ) ;
debug_assert_eq! ( virtual_keycode , Some ( VirtualKeyCode ::Period ) ) ;
let event : id = msg_send! [ NSApp ( ) , currentEvent ] ;
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
update_potentially_stale_modifiers ( state , event ) ;
2020-01-09 22:29:31 -07:00
#[ allow(deprecated) ]
2019-05-01 17:03:30 -06:00
let window_event = Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2019-05-01 17:03:30 -06:00
event : WindowEvent ::KeyboardInput {
device_id : DEVICE_ID ,
input : KeyboardInput {
state : ElementState ::Pressed ,
scancode : scancode as _ ,
virtual_keycode ,
modifiers : event_mods ( event ) ,
} ,
2019-12-07 15:51:37 -07:00
is_synthetic : false ,
2019-05-01 17:03:30 -06:00
} ,
} ;
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( window_event ) ) ;
2019-05-01 17:03:30 -06:00
}
}
2018-06-11 11:16:39 -04:00
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 ) ;
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
update_potentially_stale_modifiers ( state , event ) ;
2018-06-11 11:16:39 -04:00
let window_event = Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2018-06-11 11:16:39 -04:00
event : WindowEvent ::MouseInput {
device_id : DEVICE_ID ,
state : button_state ,
button ,
modifiers : event_mods ( event ) ,
} ,
} ;
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( window_event ) ) ;
2018-06-11 11:16:39 -04:00
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn mouse_down ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " mouseDown: " ) ;
2020-04-26 20:42:45 +00:00
mouse_motion ( this , event ) ;
2018-06-11 11:16:39 -04:00
mouse_click ( this , event , MouseButton ::Left , ElementState ::Pressed ) ;
}
2019-06-21 11:33:15 -04:00
extern " C " fn mouse_up ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " mouseUp: " ) ;
2020-04-26 20:42:45 +00:00
mouse_motion ( this , event ) ;
2018-06-11 11:16:39 -04:00
mouse_click ( this , event , MouseButton ::Left , ElementState ::Released ) ;
}
2019-06-21 11:33:15 -04:00
extern " C " fn right_mouse_down ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " rightMouseDown: " ) ;
2020-04-26 20:42:45 +00:00
mouse_motion ( this , event ) ;
2018-06-11 11:16:39 -04:00
mouse_click ( this , event , MouseButton ::Right , ElementState ::Pressed ) ;
}
2019-06-21 11:33:15 -04:00
extern " C " fn right_mouse_up ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " rightMouseUp: " ) ;
2020-04-26 20:42:45 +00:00
mouse_motion ( this , event ) ;
2018-06-11 11:16:39 -04:00
mouse_click ( this , event , MouseButton ::Right , ElementState ::Released ) ;
}
2019-06-21 11:33:15 -04:00
extern " C " fn other_mouse_down ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " otherMouseDown: " ) ;
2020-04-26 20:42:45 +00:00
mouse_motion ( this , event ) ;
2018-06-11 11:16:39 -04:00
mouse_click ( this , event , MouseButton ::Middle , ElementState ::Pressed ) ;
}
2019-06-21 11:33:15 -04:00
extern " C " fn other_mouse_up ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " otherMouseUp: " ) ;
2020-04-26 20:42:45 +00:00
mouse_motion ( this , event ) ;
2018-06-11 11:16:39 -04:00
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 ( )
2019-06-21 11:33:15 -04:00
| | view_point . y . is_sign_negative ( )
| | view_point . x > view_rect . size . width
| | view_point . y > view_rect . size . height
{
2022-01-10 21:39:17 +01:00
let mouse_buttons_down : NSUInteger = msg_send! [ class! ( NSEvent ) , pressedMouseButtons ] ;
2020-06-20 03:42:19 +03:00
if mouse_buttons_down = = 0 {
// Point is outside of the client area (view) and no buttons are pressed
return ;
}
2018-06-11 11:16:39 -04:00
}
2018-06-14 19:42:18 -04:00
let x = view_point . x as f64 ;
let y = view_rect . size . height as f64 - view_point . y as f64 ;
2020-01-12 18:50:34 +01:00
let logical_position = LogicalPosition ::new ( x , y ) ;
2018-06-11 11:16:39 -04:00
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
update_potentially_stale_modifiers ( state , event ) ;
2018-06-11 11:16:39 -04:00
let window_event = Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2018-06-11 11:16:39 -04:00
event : WindowEvent ::CursorMoved {
device_id : DEVICE_ID ,
2020-01-12 18:50:34 +01:00
position : logical_position . to_physical ( state . get_scale_factor ( ) ) ,
2018-06-11 11:16:39 -04:00
modifiers : event_mods ( event ) ,
} ,
} ;
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( window_event ) ) ;
2018-06-11 11:16:39 -04:00
}
}
2022-01-23 21:35:26 +01:00
// No tracing on these because that would be overly verbose
2019-06-21 11:33:15 -04:00
extern " C " fn mouse_moved ( this : & Object , _sel : Sel , event : id ) {
2018-06-11 11:16:39 -04:00
mouse_motion ( this , event ) ;
}
2019-06-21 11:33:15 -04:00
extern " C " fn mouse_dragged ( this : & Object , _sel : Sel , event : id ) {
2018-06-11 11:16:39 -04:00
mouse_motion ( this , event ) ;
}
2019-06-21 11:33:15 -04:00
extern " C " fn right_mouse_dragged ( this : & Object , _sel : Sel , event : id ) {
2018-06-11 11:16:39 -04:00
mouse_motion ( this , event ) ;
}
2019-06-21 11:33:15 -04:00
extern " C " fn other_mouse_dragged ( this : & Object , _sel : Sel , event : id ) {
2018-06-11 11:16:39 -04:00
mouse_motion ( this , event ) ;
}
2018-08-15 16:42:57 -07:00
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
extern " C " fn mouse_entered ( this : & Object , _sel : Sel , _event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " mouseEntered: " ) ;
2019-05-01 17:03:30 -06:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
let enter_event = Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2019-06-21 11:33:15 -04:00
event : WindowEvent ::CursorEntered {
device_id : DEVICE_ID ,
} ,
2019-05-01 17:03:30 -06:00
} ;
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( enter_event ) ) ;
2019-05-01 17:03:30 -06:00
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn mouse_exited ( this : & Object , _sel : Sel , _event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " mouseExited: " ) ;
2019-05-01 17:03:30 -06:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
let window_event = Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2019-06-21 11:33:15 -04:00
event : WindowEvent ::CursorLeft {
device_id : DEVICE_ID ,
} ,
2019-05-01 17:03:30 -06:00
} ;
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( window_event ) ) ;
2019-05-01 17:03:30 -06:00
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn scroll_wheel ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " scrollWheel: " ) ;
2020-04-26 20:42:45 +00:00
mouse_motion ( this , event ) ;
2019-05-01 17:03:30 -06:00
unsafe {
2020-07-26 22:16:21 +00:00
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
2019-05-01 17:03:30 -06:00
let delta = {
2020-09-06 07:41:19 -07:00
// macOS horizontal sign convention is the inverse of winit.
let ( x , y ) = ( event . scrollingDeltaX ( ) * - 1.0 , event . scrollingDeltaY ( ) ) ;
2019-05-01 17:03:30 -06:00
if event . hasPreciseScrollingDeltas ( ) = = YES {
2020-07-26 22:16:21 +00:00
let delta = LogicalPosition ::new ( x , y ) . to_physical ( state . get_scale_factor ( ) ) ;
MouseScrollDelta ::PixelDelta ( delta )
2019-05-01 17:03:30 -06:00
} else {
MouseScrollDelta ::LineDelta ( x as f32 , y as f32 )
}
} ;
let phase = match event . phase ( ) {
2019-06-21 11:33:15 -04:00
NSEventPhase ::NSEventPhaseMayBegin | NSEventPhase ::NSEventPhaseBegan = > {
TouchPhase ::Started
2019-06-24 12:14:55 -04:00
}
2019-05-01 17:03:30 -06:00
NSEventPhase ::NSEventPhaseEnded = > TouchPhase ::Ended ,
_ = > TouchPhase ::Moved ,
} ;
let device_event = Event ::DeviceEvent {
device_id : DEVICE_ID ,
event : DeviceEvent ::MouseWheel { delta } ,
} ;
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
Move `ModifiersChanged` variant to `WindowEvent` (#1381)
* Move `ModifiersChanged` variant to `WindowEvent`
* macos: Fix flags_changed for ModifiersChanged variant move
I haven't look too deep at what this does internally, but at least
cargo-check is fully happy now. :)
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Fire a ModifiersChanged event on window_did_resign_key
From debugging, I determined that macOS' emission of a flagsChanged
around window switching is inconsistent. It is fair to assume, I think,
that when the user switches windows, they do not expect their former
modifiers state to remain effective; so I think it's best to clear that
state by sending a ModifiersChanged(ModifiersState::empty()).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Fix build
I don't know enough about the code to implement the fix as it is done on
this branch, but this commit at least fixes the build.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* windows: Send ModifiersChanged(ModifiersState::empty) on KILLFOCUS
Very similar to the changes made in [1], as focus is lost, send an event
to the window indicating that the modifiers have been released.
It's unclear to me (without a Windows device to test this on) whether
this is necessary, but it certainly ensures that unfocused windows will
have at least received this event, which is an improvement.
[1]: f79f21641a31da3e4039d41be89047cdcc6028f7
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* macos: Add a hook to update stale modifiers
Sometimes, `ViewState` and `event` might have different values for their
stored `modifiers` flags. These are internally stored as a bitmask in
the latter and an enum in the former.
We can check to see if they differ, and if they do, automatically
dispatch an event to update consumers of modifier state as well as the
stored `state.modifiers`. That's what the hook does.
This hook is then called in the key_down, mouse_entered, mouse_exited,
mouse_click, scroll_wheel, and pressure_change_with_event callbacks,
which each will contain updated modifiers.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Only call event_mods once when determining whether to update state
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* flags_changed: Memoize window_id collection
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_did_resign_key: Remove synthetic ModifiersChanged event
We no longer need to emit this event, since we are checking the state of
our modifiers before emitting most other events.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Add a call to update_potentially_stale_modifiers
Now, cover all events (that I can think of, at least) where stale
modifiers might affect how user programs behave. Effectively, every
human-interface event (keypress, mouse click, keydown, etc.) will cause
a ModifiersChanged event to be fired if something has changed.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* key_up: Add a call to update_potentially_stale_modifiers
We also want to make sure modifiers state is synchronized here, too.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* mouse_motion: Remove update_potentially_stale_modifiers invocation
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Retry CI
* ViewState: Promote visibility of modifiers to the macos impl
This is so that we can interact with the ViewState directly from the
WindowDelegate.
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* window_delegate: Synthetically set modifiers state to empty on resignKey
This logic is implemented similarly on other platforms, so we wish to
regain parity here. Originally this behavior was implemented to always
fire an event with ModifiersState::empty(), but that was not the best as
it was not necessarily correct and could be a duplicate event.
This solution is perhaps the most elegant possible to implement the
desired behavior of sending a synthetic empty modifiers event when a
window loses focus, trading some safety for interoperation between the
NSWindowDelegate and the NSView (as the objc runtime must now be
consulted in order to acquire access to the ViewState which is "owned"
by the NSView).
Signed-off-by: Kristofer Rye <kristofer.rye@gmail.com>
* Check for modifiers change in window events
* Fix modifier changed on macOS
Since the `mouse_entered` function was generating a mouse motion, which
updates the modifier state, a modifiers changed event was incorrectly
generated.
The updating of the modifier state has also been changed to make sure it
consistently happens before events that have a modifier state attached
to it, without happening on any other event.
This of course means that no `CursorMoved` event is generated anymore
when the user enters the window without it being focused, however I'd
say that is consistent with how winit should behave.
* Fix unused variable warning
* Move changelog entry into `Unreleased` section
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Kristofer Rye <kristofer.rye@gmail.com>
Co-authored-by: Christian Duerr <contact@christianduerr.com>
2020-03-06 15:43:55 -07:00
update_potentially_stale_modifiers ( state , event ) ;
2019-05-01 17:03:30 -06:00
let window_event = Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2019-05-01 17:03:30 -06:00
event : WindowEvent ::MouseWheel {
device_id : DEVICE_ID ,
delta ,
phase ,
modifiers : event_mods ( event ) ,
} ,
} ;
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( device_event ) ) ;
AppState ::queue_event ( EventWrapper ::StaticEvent ( window_event ) ) ;
2019-05-01 17:03:30 -06:00
}
}
2019-06-21 11:33:15 -04:00
extern " C " fn pressure_change_with_event ( this : & Object , _sel : Sel , event : id ) {
2022-01-23 21:35:26 +01:00
trace_scope! ( " pressureChangeWithEvent: " ) ;
2020-04-26 20:42:45 +00:00
mouse_motion ( this , event ) ;
2019-05-01 17:03:30 -06:00
unsafe {
let state_ptr : * mut c_void = * this . get_ivar ( " winitState " ) ;
let state = & mut * ( state_ptr as * mut ViewState ) ;
let pressure = event . pressure ( ) ;
let stage = event . stage ( ) ;
let window_event = Event ::WindowEvent {
2019-06-11 01:09:38 +02:00
window_id : WindowId ( get_window_id ( state . ns_window ) ) ,
2019-05-01 17:03:30 -06:00
event : WindowEvent ::TouchpadPressure {
device_id : DEVICE_ID ,
pressure ,
stage ,
} ,
} ;
2020-01-04 01:32:34 -05:00
AppState ::queue_event ( EventWrapper ::StaticEvent ( window_event ) ) ;
2019-05-01 17:03:30 -06:00
}
}
// Allows us to receive Ctrl-Tab and Ctrl-Esc.
// Note that this *doesn't* help with any missing Cmd inputs.
2018-08-15 16:42:57 -07:00
// https://github.com/chromium/chromium/blob/a86a8a6bcfa438fa3ac2eba6f02b3ad1f8e0756f/ui/views/cocoa/bridged_content_view.mm#L816
2019-06-21 11:33:15 -04:00
extern " C " fn wants_key_down_for_event ( _this : & Object , _sel : Sel , _event : id ) -> BOOL {
2022-01-23 21:35:26 +01:00
trace_scope! ( " _wantsKeyDownForEvent: " ) ;
2018-08-15 16:42:57 -07:00
YES
}
2021-04-30 17:30:09 +08:00
extern " C " fn accepts_first_mouse ( _this : & Object , _sel : Sel , _event : id ) -> BOOL {
2022-01-23 21:35:26 +01:00
trace_scope! ( " acceptsFirstMouse: " ) ;
2021-04-30 17:30:09 +08:00
YES
}