From bad50d886a36699bcb19078256cb1063f1166ed6 Mon Sep 17 00:00:00 2001 From: Dionysis Athinaios Date: Mon, 25 Mar 2024 22:05:16 +0000 Subject: [PATCH] Implement input focus for Mac & Windows (#170) * Implement input focus for Mac * Add stubs for Windows and Linux * Remove unnecessary call to window * Implement input focus for Windows * Add check for key window status * Rename to `has_focus` & `focus` * Use GetFocus * Fix incorrectly named var --------- Co-authored-by: Micah Johnston --- src/macos/window.rs | 25 ++++++++++++++++++++++++- src/win/window.rs | 13 ++++++++++++- src/window.rs | 8 ++++++++ src/x11/window.rs | 8 ++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/macos/window.rs b/src/macos/window.rs index ea8b78f..15b9469 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -7,7 +7,7 @@ use cocoa::appkit::{ NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSBackingStoreBuffered, NSPasteboard, NSView, NSWindow, NSWindowStyleMask, }; -use cocoa::base::{id, nil, NO, YES}; +use cocoa::base::{id, nil, BOOL, NO, YES}; use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString}; use core_foundation::runloop::{ CFRunLoop, CFRunLoopTimer, CFRunLoopTimerContext, __CFRunLoopTimer, kCFRunLoopDefaultMode, @@ -43,6 +43,7 @@ impl WindowHandle { pub fn is_open(&self) -> bool { self.state.window_inner.open.get() } + } unsafe impl HasRawWindowHandle for WindowHandle { @@ -284,6 +285,28 @@ impl<'a> Window<'a> { self.inner.close(); } + pub fn has_focus(&mut self) -> bool { + unsafe { + let view = self.inner.ns_view.as_mut().unwrap(); + let window: id = msg_send![view, window]; + if window == nil { return false; }; + let first_responder: id = msg_send![window, firstResponder]; + let is_key_window: BOOL = msg_send![window, isKeyWindow]; + let is_focused: BOOL = msg_send![view, isEqual: first_responder]; + is_key_window == YES && is_focused == YES + } + } + + pub fn focus(&mut self) { + unsafe { + let view = self.inner.ns_view.as_mut().unwrap(); + let window: id = msg_send![view, window]; + if window != nil { + msg_send![window, makeFirstResponder:view] + } + } + } + pub fn resize(&mut self, size: Size) { if self.inner.open.get() { // NOTE: macOS gives you a personal rave if you pass in fractional pixels here. Even diff --git a/src/win/window.rs b/src/win/window.rs index ca8ec4c..b0b72cb 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -8,7 +8,7 @@ use winapi::um::winuser::{ AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW, ReleaseCapture, SetCapture, SetProcessDpiAwarenessContext, SetTimer, SetWindowLongPtrW, - SetWindowPos, TrackMouseEvent, TranslateMessage, UnregisterClassW, CS_OWNDC, + SetWindowPos, SetFocus, GetFocus, TrackMouseEvent, TranslateMessage, UnregisterClassW, CS_OWNDC, GET_XBUTTON_WPARAM, GWLP_USERDATA, IDC_ARROW, MSG, SWP_NOMOVE, SWP_NOZORDER, TRACKMOUSEEVENT, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE, WM_DPICHANGED, WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEHWHEEL, @@ -770,6 +770,17 @@ impl Window<'_> { } } + pub fn has_focus(&mut self) -> bool { + let focused_window = unsafe { GetFocus() }; + focused_window == self.state.hwnd + } + + pub fn focus(&mut self) { + unsafe { + SetFocus(self.state.hwnd); + } + } + pub fn resize(&mut self, size: Size) { // To avoid reentrant event handler calls we'll defer the actual resizing until after the // event has been handled diff --git a/src/window.rs b/src/window.rs index 63e3f49..0008b7c 100644 --- a/src/window.rs +++ b/src/window.rs @@ -102,6 +102,14 @@ impl<'a> Window<'a> { self.window.set_mouse_cursor(cursor); } + pub fn has_focus(&mut self) -> bool { + self.window.has_focus() + } + + pub fn focus(&mut self) { + self.window.focus() + } + /// If provided, then an OpenGL context will be created for this window. You'll be able to /// access this context through [crate::Window::gl_context]. #[cfg(feature = "opengl")] diff --git a/src/x11/window.rs b/src/x11/window.rs index fae1f69..6c5d5b6 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -359,6 +359,14 @@ impl<'a> Window<'a> { self.inner.close_requested = true; } + pub fn has_focus(&mut self) -> bool { + unimplemented!() + } + + pub fn focus(&mut self) { + unimplemented!() + } + pub fn resize(&mut self, size: Size) { let scaling = self.inner.window_info.scale(); let new_window_info = WindowInfo::from_logical_size(size, scaling);