1
0
Fork 0

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 <micah@photophore.systems>
This commit is contained in:
Dionysis Athinaios 2024-03-25 22:05:16 +00:00 committed by GitHub
parent 085ae2a27e
commit bad50d886a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 52 additions and 2 deletions

View file

@ -7,7 +7,7 @@ use cocoa::appkit::{
NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSBackingStoreBuffered, NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSBackingStoreBuffered,
NSPasteboard, NSView, NSWindow, NSWindowStyleMask, 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 cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString};
use core_foundation::runloop::{ use core_foundation::runloop::{
CFRunLoop, CFRunLoopTimer, CFRunLoopTimerContext, __CFRunLoopTimer, kCFRunLoopDefaultMode, CFRunLoop, CFRunLoopTimer, CFRunLoopTimerContext, __CFRunLoopTimer, kCFRunLoopDefaultMode,
@ -43,6 +43,7 @@ impl WindowHandle {
pub fn is_open(&self) -> bool { pub fn is_open(&self) -> bool {
self.state.window_inner.open.get() self.state.window_inner.open.get()
} }
} }
unsafe impl HasRawWindowHandle for WindowHandle { unsafe impl HasRawWindowHandle for WindowHandle {
@ -284,6 +285,28 @@ impl<'a> Window<'a> {
self.inner.close(); 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) { pub fn resize(&mut self, size: Size) {
if self.inner.open.get() { if self.inner.open.get() {
// NOTE: macOS gives you a personal rave if you pass in fractional pixels here. Even // NOTE: macOS gives you a personal rave if you pass in fractional pixels here. Even

View file

@ -8,7 +8,7 @@ use winapi::um::winuser::{
AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW,
GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW, GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW,
ReleaseCapture, SetCapture, SetProcessDpiAwarenessContext, SetTimer, SetWindowLongPtrW, 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, 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, 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, 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) { pub fn resize(&mut self, size: Size) {
// To avoid reentrant event handler calls we'll defer the actual resizing until after the // To avoid reentrant event handler calls we'll defer the actual resizing until after the
// event has been handled // event has been handled

View file

@ -102,6 +102,14 @@ impl<'a> Window<'a> {
self.window.set_mouse_cursor(cursor); 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 /// 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]. /// access this context through [crate::Window::gl_context].
#[cfg(feature = "opengl")] #[cfg(feature = "opengl")]

View file

@ -359,6 +359,14 @@ impl<'a> Window<'a> {
self.inner.close_requested = true; 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) { pub fn resize(&mut self, size: Size) {
let scaling = self.inner.window_info.scale(); let scaling = self.inner.window_info.scale();
let new_window_info = WindowInfo::from_logical_size(size, scaling); let new_window_info = WindowInfo::from_logical_size(size, scaling);