2023-02-28 19:34:12 +01:00
|
|
|
// Copyright 2023 The Chromium Embedded Framework Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be found
|
|
|
|
// in the LICENSE file.
|
|
|
|
|
2024-04-30 17:45:07 +02:00
|
|
|
#include "cef/libcef/browser/views/native_widget_mac.h"
|
2023-02-28 19:34:12 +01:00
|
|
|
|
2024-04-30 17:45:07 +02:00
|
|
|
#include "cef/include/views/cef_window.h"
|
|
|
|
#include "cef/include/views/cef_window_delegate.h"
|
|
|
|
#include "cef/libcef/browser/views/ns_window.h"
|
|
|
|
#include "cef/libcef/browser/views/window_impl.h"
|
2023-04-18 23:20:44 +02:00
|
|
|
#include "chrome/browser/apps/app_shim/app_shim_host_mac.h"
|
|
|
|
#include "chrome/browser/apps/app_shim/app_shim_manager_mac.h"
|
|
|
|
#import "chrome/browser/ui/cocoa/browser_window_command_handler.h"
|
|
|
|
#import "chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.h"
|
|
|
|
#include "chrome/browser/ui/views/frame/browser_frame_mac.h"
|
|
|
|
#include "chrome/browser/ui/views/frame/browser_view.h"
|
|
|
|
#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
|
|
|
|
#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
AppShimHost* GetHostForBrowser(Browser* browser) {
|
|
|
|
auto* const shim_manager = apps::AppShimManager::Get();
|
|
|
|
if (!shim_manager) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return shim_manager->GetHostForRemoteCocoaBrowser(browser);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2023-02-28 19:34:12 +01:00
|
|
|
CefNativeWidgetMac::CefNativeWidgetMac(
|
|
|
|
views::internal::NativeWidgetDelegate* delegate,
|
2023-03-16 18:19:50 +01:00
|
|
|
CefRefPtr<CefWindow> window,
|
|
|
|
CefWindowDelegate* window_delegate)
|
2023-02-28 19:34:12 +01:00
|
|
|
: views::NativeWidgetMac(delegate),
|
2023-03-16 18:19:50 +01:00
|
|
|
window_(window),
|
|
|
|
window_delegate_(window_delegate) {}
|
2023-02-28 19:34:12 +01:00
|
|
|
|
2023-04-18 23:20:44 +02:00
|
|
|
void CefNativeWidgetMac::SetBrowserView(BrowserView* browser_view) {
|
|
|
|
browser_view_ = browser_view;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefNativeWidgetMac::ValidateUserInterfaceItem(
|
|
|
|
int32_t tag,
|
|
|
|
remote_cocoa::mojom::ValidateUserInterfaceItemResult* result) {
|
|
|
|
if (!browser_view_) {
|
|
|
|
result->enable = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return BrowserFrameMac::ValidateUserInterfaceItem(browser_view_->browser(),
|
|
|
|
tag, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CefNativeWidgetMac::WillExecuteCommand(
|
|
|
|
int32_t command,
|
|
|
|
WindowOpenDisposition window_open_disposition,
|
|
|
|
bool is_before_first_responder) {
|
|
|
|
if (!browser_view_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return BrowserFrameMac::WillExecuteCommand(browser_view_->browser(), command,
|
|
|
|
window_open_disposition,
|
|
|
|
is_before_first_responder);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CefNativeWidgetMac::ExecuteCommand(
|
|
|
|
int32_t command,
|
|
|
|
WindowOpenDisposition window_open_disposition,
|
|
|
|
bool is_before_first_responder) {
|
|
|
|
if (!browser_view_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return BrowserFrameMac::ExecuteCommand(browser_view_->browser(), command,
|
|
|
|
window_open_disposition,
|
|
|
|
is_before_first_responder);
|
|
|
|
}
|
|
|
|
|
2023-02-28 19:34:12 +01:00
|
|
|
NativeWidgetMacNSWindow* CefNativeWidgetMac::CreateNSWindow(
|
|
|
|
const remote_cocoa::mojom::CreateWindowParams* params) {
|
|
|
|
NSUInteger style_mask =
|
|
|
|
NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable |
|
2024-08-26 14:44:25 +02:00
|
|
|
NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
|
2023-03-16 18:19:50 +01:00
|
|
|
|
2024-04-12 17:49:31 +02:00
|
|
|
const bool is_frameless = window_delegate_->IsFrameless(window_);
|
|
|
|
const auto accepts_first_mouse = window_delegate_->AcceptsFirstMouse(window_);
|
2023-03-16 18:19:50 +01:00
|
|
|
|
2023-02-28 19:34:12 +01:00
|
|
|
auto window = [[CefNSWindow alloc] initWithStyle:style_mask
|
2024-04-12 17:49:31 +02:00
|
|
|
isFrameless:is_frameless
|
|
|
|
acceptsFirstMouse:accepts_first_mouse];
|
2023-02-28 19:34:12 +01:00
|
|
|
|
2023-03-16 18:19:50 +01:00
|
|
|
if (is_frameless) {
|
2023-02-28 19:34:12 +01:00
|
|
|
[window setTitlebarAppearsTransparent:YES];
|
|
|
|
[window setTitleVisibility:NSWindowTitleHidden];
|
|
|
|
}
|
|
|
|
|
2023-03-16 18:19:50 +01:00
|
|
|
if (!window_delegate_->WithStandardWindowButtons(window_)) {
|
2023-02-28 19:34:12 +01:00
|
|
|
[[window standardWindowButton:NSWindowCloseButton] setHidden:YES];
|
|
|
|
[[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
|
|
|
|
[[window standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefNativeWidgetMac::GetWindowFrameTitlebarHeight(
|
|
|
|
bool* override_titlebar_height,
|
|
|
|
float* titlebar_height) {
|
2023-03-16 18:19:50 +01:00
|
|
|
if (window_delegate_->GetTitlebarHeight(window_, titlebar_height)) {
|
2023-02-28 19:34:12 +01:00
|
|
|
*override_titlebar_height = true;
|
|
|
|
} else {
|
|
|
|
views::NativeWidgetMac::GetWindowFrameTitlebarHeight(
|
|
|
|
override_titlebar_height, titlebar_height);
|
|
|
|
}
|
|
|
|
}
|
2023-04-20 16:59:15 +02:00
|
|
|
|
|
|
|
void CefNativeWidgetMac::OnWindowFullscreenTransitionStart() {
|
|
|
|
views::NativeWidgetMac::OnWindowFullscreenTransitionStart();
|
2023-09-25 21:40:17 +02:00
|
|
|
if (IsCefWindowInitialized()) {
|
|
|
|
window_delegate_->OnWindowFullscreenTransition(window_, false);
|
2023-11-07 22:40:29 +01:00
|
|
|
if (browser_view_) {
|
|
|
|
browser_view_->FullscreenStateChanging();
|
|
|
|
}
|
2023-09-25 21:40:17 +02:00
|
|
|
}
|
2023-04-20 16:59:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CefNativeWidgetMac::OnWindowFullscreenTransitionComplete() {
|
|
|
|
views::NativeWidgetMac::OnWindowFullscreenTransitionComplete();
|
2023-09-25 21:40:17 +02:00
|
|
|
if (IsCefWindowInitialized()) {
|
2023-11-07 22:40:29 +01:00
|
|
|
if (browser_view_) {
|
|
|
|
browser_view_->FullscreenStateChanged();
|
|
|
|
}
|
2023-09-25 21:40:17 +02:00
|
|
|
window_delegate_->OnWindowFullscreenTransition(window_, true);
|
|
|
|
}
|
2023-04-20 16:59:15 +02:00
|
|
|
}
|
2023-04-18 23:20:44 +02:00
|
|
|
|
|
|
|
void CefNativeWidgetMac::OnWindowInitialized() {
|
2024-10-15 19:58:23 +02:00
|
|
|
// This connects the native widget with the command dispatcher so accelerators
|
|
|
|
// work even if a browser_view_ is not created later.
|
|
|
|
// The initialized_ check is necessary because the method can be called twice:
|
|
|
|
// 1. From NativeWidgetMac::InitNativeWidget
|
|
|
|
// 2. From ChromeBrowserFrame::Init
|
|
|
|
if (initialized_) {
|
2023-04-18 23:20:44 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// From BrowserFrameMac::OnWindowInitialized.
|
|
|
|
if (auto* bridge = GetInProcessNSWindowBridge()) {
|
2023-05-05 13:17:14 +02:00
|
|
|
bridge->SetCommandDispatcher([[ChromeCommandDispatcherDelegate alloc] init],
|
|
|
|
[[BrowserWindowCommandHandler alloc] init]);
|
2024-10-15 19:58:23 +02:00
|
|
|
initialized_ = true;
|
|
|
|
} else if (browser_view_) {
|
2023-04-18 23:20:44 +02:00
|
|
|
if (auto* host = GetHostForBrowser(browser_view_->browser())) {
|
|
|
|
host->GetAppShim()->CreateCommandDispatcherForWidget(
|
|
|
|
GetNSWindowHost()->bridged_native_widget_id());
|
2024-10-15 19:58:23 +02:00
|
|
|
initialized_ = true;
|
2023-04-18 23:20:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-09-25 21:40:17 +02:00
|
|
|
|
|
|
|
bool CefNativeWidgetMac::IsCefWindowInitialized() const {
|
|
|
|
return static_cast<CefWindowImpl*>(window_.get())->initialized();
|
|
|
|
}
|