Skip to content

Commit b223fe1

Browse files
authored
fix(webview/macos): frameless windows must become key + route input to WKWebView (#51)
* fix(webview/macos): borderless windows must become key + route input to WKWebView A borderless NSWindow returns NO from -canBecomeKeyWindow by default, so frameless windows never took key focus and their WKWebView never became first responder, killing all keyboard and mouse input. Use a keyable NSWindow subclass for the frameless branch and call makeFirstResponder: on the webview after setContentView and in Show/Focus. * style(webview/macos): clang-format the LaufeyKeyableWindow comment The 4-line comment block above LaufeyKeyableWindow exceeded the 80-col ColumnLimit, failing the CI clang-format check. Reflow it to fit.
1 parent 203427d commit b223fe1

1 file changed

Lines changed: 35 additions & 0 deletions

File tree

webview/src/webview_macos.mm

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,23 @@ static void UnregisterNSWindow(NSWindow* win) {
191191
g_nswindow_to_laufey_id.erase((__bridge void*)win);
192192
}
193193

194+
// A borderless NSWindow returns NO from
195+
// -canBecomeKeyWindow/-canBecomeMainWindow by default, so a frameless window
196+
// never takes key focus and its WKWebView never becomes first responder —
197+
// killing all keyboard and mouse input. This subclass forces both to YES so
198+
// frameless windows behave like normal ones.
199+
@interface LaufeyKeyableWindow : NSWindow
200+
@end
201+
202+
@implementation LaufeyKeyableWindow
203+
- (BOOL)canBecomeKeyWindow {
204+
return YES;
205+
}
206+
- (BOOL)canBecomeMainWindow {
207+
return YES;
208+
}
209+
@end
210+
194211
@interface LaufeyScriptMessageHandler : NSObject <WKScriptMessageHandler>
195212
@property(nonatomic, assign) WKWebViewBackend* backend;
196213
@property(nonatomic, assign) uint32_t windowId;
@@ -886,6 +903,14 @@ int NSButtonToLaufey(NSInteger buttonNumber) {
886903
NSWindowCollectionBehaviorTransient |
887904
NSWindowCollectionBehaviorIgnoresCycle];
888905
window = panel;
906+
} else if (frameless) {
907+
// Borderless windows must be told they can become key/main, otherwise
908+
// they receive no keyboard or mouse input (see LaufeyKeyableWindow).
909+
window = [[LaufeyKeyableWindow alloc]
910+
initWithContentRect:frame
911+
styleMask:style
912+
backing:NSBackingStoreBuffered
913+
defer:NO];
889914
} else {
890915
window = [[NSWindow alloc] initWithContentRect:frame
891916
styleMask:style
@@ -981,6 +1006,8 @@ int NSButtonToLaufey(NSInteger buttonNumber) {
9811006
}
9821007

9831008
[window setContentView:webview];
1009+
// Route input into the web content once the window becomes key.
1010+
[window makeFirstResponder:webview];
9841011

9851012
RegisterNSWindow(window, window_id);
9861013

@@ -1444,16 +1471,20 @@ static CGFloat PrimaryScreenHeight() {
14441471
dispatch_async(dispatch_get_main_queue(), ^{
14451472
@autoreleasepool {
14461473
NSWindow* win = nil;
1474+
WKWebView* web = nil;
14471475
{
14481476
std::lock_guard<std::mutex> lock(windows_mutex_);
14491477
auto* state = GetWindow(window_id);
14501478
if (state) {
14511479
win = state->window;
1480+
web = state->webview;
14521481
}
14531482
}
14541483
if (!win)
14551484
return;
14561485
[win makeKeyAndOrderFront:nil];
1486+
if (web)
1487+
[win makeFirstResponder:web];
14571488
}
14581489
});
14591490
}
@@ -1480,16 +1511,20 @@ static CGFloat PrimaryScreenHeight() {
14801511
dispatch_async(dispatch_get_main_queue(), ^{
14811512
@autoreleasepool {
14821513
NSWindow* win = nil;
1514+
WKWebView* web = nil;
14831515
{
14841516
std::lock_guard<std::mutex> lock(windows_mutex_);
14851517
auto* state = GetWindow(window_id);
14861518
if (state) {
14871519
win = state->window;
1520+
web = state->webview;
14881521
}
14891522
}
14901523
if (win) {
14911524
[NSApp activateIgnoringOtherApps:YES];
14921525
[win makeKeyAndOrderFront:nil];
1526+
if (web)
1527+
[win makeFirstResponder:web];
14931528
}
14941529
}
14951530
});

0 commit comments

Comments
 (0)