diff --git a/BUILD.gn b/BUILD.gn index 2183e07cc..fa93fa624 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1145,6 +1145,10 @@ source_set("libcef_static") { "libcef/browser/native/menu_runner_mac.mm", "libcef/browser/osr/browser_platform_delegate_osr_mac.h", "libcef/browser/osr/browser_platform_delegate_osr_mac.mm", + "libcef/browser/views/native_widget_mac.h", + "libcef/browser/views/native_widget_mac.mm", + "libcef/browser/views/ns_window.h", + "libcef/browser/views/ns_window.mm", "libcef/browser/views/view_util_mac.mm", "libcef/common/util_mac.h", "libcef/common/util_mac.mm", diff --git a/include/capi/views/cef_window_delegate_capi.h b/include/capi/views/cef_window_delegate_capi.h index e23c097cb..ce63b8651 100644 --- a/include/capi/views/cef_window_delegate_capi.h +++ b/include/capi/views/cef_window_delegate_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=019abf16be4e151d31181a6bdcb1ad8dfef03d00$ +// $hash=9f0389a439e6787282880d53375369829adb6a3d$ // #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_WINDOW_DELEGATE_CAPI_H_ @@ -137,6 +137,25 @@ typedef struct _cef_window_delegate_t { int(CEF_CALLBACK* is_frameless)(struct _cef_window_delegate_t* self, struct _cef_window_t* window); + /// + /// Return true (1) if |window| should be created with standard window buttons + /// like close, minimize and zoom. + /// + int(CEF_CALLBACK* with_standard_window_buttons)( + struct _cef_window_delegate_t* self, + struct _cef_window_t* window); + + /// + /// Return whether the titlebar height should be overridden, and sets the + /// height of the titlebar in |titlebar_height|. On macOS, it can also be used + /// to adjust the vertical position of the traffic light buttons in frameless + /// windows. The buttons will be positioned halfway down the titlebar at a + /// height of |titlebar_height| / 2. + /// + int(CEF_CALLBACK* get_titlebar_height)(struct _cef_window_delegate_t* self, + struct _cef_window_t* window, + float* titlebar_height); + /// /// Return true (1) if |window| can be resized. /// diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h index 69bac0e54..92ac91638 100644 --- a/include/cef_api_hash.h +++ b/include/cef_api_hash.h @@ -42,13 +42,13 @@ // way that may cause binary incompatibility with other builds. The universal // hash value will change if any platform is affected whereas the platform hash // values will change only if that particular platform is affected. -#define CEF_API_HASH_UNIVERSAL "17e2f5f1944618780d9d2f445d6f7ca17ad31f2a" +#define CEF_API_HASH_UNIVERSAL "1d8347d8e06dc0dd17f882ca253e1c7bf43d5863" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "43e4bd792e5b0bbe8004dcecca0997803d1effbb" +#define CEF_API_HASH_PLATFORM "b6865f1992a10dcefc0bbc450cf296b648003271" #elif defined(OS_MAC) -#define CEF_API_HASH_PLATFORM "a3e1a9d8eeda6791d3a990d0e94407b4d0569aca" +#define CEF_API_HASH_PLATFORM "d04c2a5ab471493c185eb7c7aa894bc4a79d5a7c" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "63cbcad670b313815a78186a5e029c8b09339e36" +#define CEF_API_HASH_PLATFORM "d7d4cbffa4a798fea97e7b9f3610b5cb803d949e" #endif #ifdef __cplusplus diff --git a/include/views/cef_window_delegate.h b/include/views/cef_window_delegate.h index 22c2aef52..e9a1b528c 100644 --- a/include/views/cef_window_delegate.h +++ b/include/views/cef_window_delegate.h @@ -128,6 +128,29 @@ class CefWindowDelegate : public CefPanelDelegate { /*--cef()--*/ virtual bool IsFrameless(CefRefPtr window) { return false; } + /// + /// Return true if |window| should be created with standard window buttons + /// like close, minimize and zoom. + /// + /*--cef()--*/ + virtual bool WithStandardWindowButtons(CefRefPtr window) { + return false; + } + + /// + /// Return whether the titlebar height should be overridden, + /// and sets the height of the titlebar in |titlebar_height|. + /// On macOS, it can also be used to adjust the vertical position + /// of the traffic light buttons in frameless windows. + /// The buttons will be positioned halfway down the titlebar + /// at a height of |titlebar_height| / 2. + /// + /*--cef()--*/ + virtual bool GetTitlebarHeight(CefRefPtr window, + float* titlebar_height) { + return false; + } + /// /// Return true if |window| can be resized. /// diff --git a/libcef/browser/views/native_widget_mac.h b/libcef/browser/views/native_widget_mac.h new file mode 100644 index 000000000..bbe220688 --- /dev/null +++ b/libcef/browser/views/native_widget_mac.h @@ -0,0 +1,37 @@ +// 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. + +#ifndef CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_ +#define CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_ +#pragma once + +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/views/widget/native_widget_mac.h" + +class CefNativeWidgetMac : public views::NativeWidgetMac { + public: + CefNativeWidgetMac(views::internal::NativeWidgetDelegate* delegate, + bool is_frameless, + bool with_window_buttons, + absl::optional title_bar_height); + ~CefNativeWidgetMac() override = default; + + CefNativeWidgetMac(const CefNativeWidgetMac&) = delete; + CefNativeWidgetMac& operator=(const CefNativeWidgetMac&) = delete; + + protected: + // NativeWidgetMac: + NativeWidgetMacNSWindow* CreateNSWindow( + const remote_cocoa::mojom::CreateWindowParams* params) override; + + void GetWindowFrameTitlebarHeight(bool* override_titlebar_height, + float* titlebar_height) override; + + private: + const bool is_frameless_; + const bool with_window_buttons_; + const absl::optional title_bar_height_; +}; + +#endif // CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_ diff --git a/libcef/browser/views/native_widget_mac.mm b/libcef/browser/views/native_widget_mac.mm new file mode 100644 index 000000000..34ffdb1a0 --- /dev/null +++ b/libcef/browser/views/native_widget_mac.mm @@ -0,0 +1,52 @@ +// 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. + +#include "libcef/browser/views/native_widget_mac.h" + +#include "libcef/browser/views/ns_window.h" + +CefNativeWidgetMac::CefNativeWidgetMac( + views::internal::NativeWidgetDelegate* delegate, + bool is_frameless, + bool with_window_buttons, + absl::optional title_bar_height) + : views::NativeWidgetMac(delegate), + is_frameless_(is_frameless), + with_window_buttons_(with_window_buttons), + title_bar_height_(title_bar_height) {} + +NativeWidgetMacNSWindow* CefNativeWidgetMac::CreateNSWindow( + const remote_cocoa::mojom::CreateWindowParams* params) { + NSUInteger style_mask = + NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | + NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | + NSWindowStyleMaskTexturedBackground; + auto window = [[CefNSWindow alloc] initWithStyle:style_mask + isFrameless:is_frameless_]; + + if (is_frameless_) { + [window setTitlebarAppearsTransparent:YES]; + [window setTitleVisibility:NSWindowTitleHidden]; + } + + if (!with_window_buttons_) { + [[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) { + if (title_bar_height_) { + *override_titlebar_height = true; + *titlebar_height = title_bar_height_.value(); + } else { + views::NativeWidgetMac::GetWindowFrameTitlebarHeight( + override_titlebar_height, titlebar_height); + } +} diff --git a/libcef/browser/views/ns_window.h b/libcef/browser/views/ns_window.h new file mode 100644 index 000000000..2ed159c3e --- /dev/null +++ b/libcef/browser/views/ns_window.h @@ -0,0 +1,20 @@ +// 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. + +#ifndef CEF_LIBCEF_BROWSER_VIEWS_NS_WINDOW_H_ +#define CEF_LIBCEF_BROWSER_VIEWS_NS_WINDOW_H_ +#pragma once + +#include "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" + +@interface CefNSWindow : NativeWidgetMacNSWindow { + @private + bool is_frameless_; +} +- (id)initWithStyle:(NSUInteger)style_mask isFrameless:(bool)is_frameless; + +- (BOOL)shouldCenterTrafficLights; +@end + +#endif // CEF_LIBCEF_BROWSER_VIEWS_NS_WINDOW_H_ diff --git a/libcef/browser/views/ns_window.mm b/libcef/browser/views/ns_window.mm new file mode 100644 index 000000000..b7d42ba0f --- /dev/null +++ b/libcef/browser/views/ns_window.mm @@ -0,0 +1,104 @@ +// 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. + +#include "libcef/browser/views/ns_window.h" + +#include "base/i18n/rtl.h" +#include "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h" +#include "components/remote_cocoa/common/native_widget_ns_window_host.mojom.h" +#include "ui/base/cocoa/window_size_constants.h" + +@interface CefThemeFrame : NativeWidgetMacNSWindowTitledFrame +@end + +// NSThemeFrame (PrivateAPI) definitions. +@interface NSThemeFrame (PrivateAPI) +- (void)setStyleMask:(NSUInteger)styleMask; +- (CGFloat)_titlebarHeight; +- (BOOL)_shouldCenterTrafficLights; +@end + +@implementation CefThemeFrame { + bool in_full_screen_; +} + +// NSThemeFrame (PrivateAPI) overrides. +- (void)setStyleMask:(NSUInteger)styleMask { + in_full_screen_ = (styleMask & NSWindowStyleMaskFullScreen) != 0; + [super setStyleMask:styleMask]; +} + +- (CGFloat)_titlebarHeight { + if (!in_full_screen_) { + bool override_titlebar_height = false; + float titlebar_height = 0; + auto* window = base::mac::ObjCCast([self window]); + if (auto* bridge = [window bridge]) { + bridge->host()->GetWindowFrameTitlebarHeight(&override_titlebar_height, + &titlebar_height); + + if (override_titlebar_height) + return titlebar_height; + } + } + + return [super _titlebarHeight]; +} + +- (BOOL)_shouldCenterTrafficLights { + auto* window = base::mac::ObjCCast([self window]); + return [window shouldCenterTrafficLights]; +} + +- (BOOL)_shouldFlipTrafficLightsForRTL { + return base::i18n::IsRTL() ? YES : NO; +} + +@end + +@interface NSWindow (PrivateAPI) ++ (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle; +@end + +@implementation CefNSWindow + +- (id)initWithStyle:(NSUInteger)style_mask isFrameless:(bool)is_frameless { + if ((self = [super initWithContentRect:ui::kWindowSizeDeterminedLater + styleMask:style_mask + backing:NSBackingStoreBuffered + defer:NO])) { + is_frameless_ = is_frameless; + } + return self; +} + +- (BOOL)shouldCenterTrafficLights { + return is_frameless_ ? YES : NO; +} + +// NSWindow overrides. +- (NSRect)contentRectForFrameRect:(NSRect)frameRect { + if (is_frameless_) { + return frameRect; + } + return [super contentRectForFrameRect:frameRect]; +} + +- (NSRect)frameRectForContentRect:(NSRect)contentRect { + if (is_frameless_) { + return contentRect; + } + return [super frameRectForContentRect:contentRect]; +} + +// NSWindow (PrivateAPI) overrides. ++ (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle { + if (Class custom_frame = [CefThemeFrame class]) { + return custom_frame; + } + + return [super frameViewClassForStyleMask:windowStyle]; +} + +@end diff --git a/libcef/browser/views/view_util.h b/libcef/browser/views/view_util.h index 302eee464..2a9000619 100644 --- a/libcef/browser/views/view_util.h +++ b/libcef/browser/views/view_util.h @@ -9,6 +9,7 @@ #include "include/views/cef_view.h" #include "include/views/cef_window.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/view.h" @@ -21,8 +22,12 @@ class Point; } namespace views { +class NativeWidget; class Widget; +namespace internal { +class NativeWidgetDelegate; } +} // namespace views #define CEF_REQUIRE_VALID_RETURN(ret) \ if (!ParentClass::IsValid()) \ @@ -141,6 +146,12 @@ CefWindowHandle GetWindowHandle(views::Widget* widget); // Returns the platform window handle for |window|. May return nullptr. CefWindowHandle GetWindowHandle(gfx::NativeWindow window); +views::NativeWidget* CreateNativeWidget( + views::internal::NativeWidgetDelegate* delegate, + bool is_frameless, + bool with_window_buttons, + absl::optional title_bar_height); + } // namespace view_util #endif // CEF_LIBCEF_BROWSER_VIEWS_VIEW_UTIL_H_ diff --git a/libcef/browser/views/view_util_aura.cc b/libcef/browser/views/view_util_aura.cc index 5ff60bd7c..f58b9b3f9 100644 --- a/libcef/browser/views/view_util_aura.cc +++ b/libcef/browser/views/view_util_aura.cc @@ -6,6 +6,8 @@ #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" +#include "ui/views/widget/native_widget.h" +#include "ui/views/widget/native_widget_delegate.h" #include "ui/views/widget/widget.h" namespace view_util { @@ -40,4 +42,12 @@ CefWindowHandle GetWindowHandle(gfx::NativeWindow window) { return kNullWindowHandle; } +views::NativeWidget* CreateNativeWidget( + views::internal::NativeWidgetDelegate* delegate, + bool is_frameless, + bool with_window_buttons, + absl::optional title_bar_height) { + return nullptr; +} + } // namespace view_util diff --git a/libcef/browser/views/view_util_mac.mm b/libcef/browser/views/view_util_mac.mm index 8320b477d..f69bf8323 100644 --- a/libcef/browser/views/view_util_mac.mm +++ b/libcef/browser/views/view_util_mac.mm @@ -7,6 +7,7 @@ #import #include "include/internal/cef_types_mac.h" +#include "libcef/browser/views/native_widget_mac.h" #include "ui/views/widget/widget.h" @@ -44,4 +45,12 @@ CefWindowHandle GetWindowHandle(gfx::NativeWindow window) { return kNullWindowHandle; } +views::NativeWidget* CreateNativeWidget( + views::internal::NativeWidgetDelegate* delegate, + bool is_frameless, + bool with_window_buttons, + absl::optional title_bar_height) { + return new CefNativeWidgetMac(delegate, is_frameless, with_window_buttons, + title_bar_height); +} } // namespace view_util diff --git a/libcef/browser/views/window_view.cc b/libcef/browser/views/window_view.cc index 93b98275b..4bf06c66e 100644 --- a/libcef/browser/views/window_view.cc +++ b/libcef/browser/views/window_view.cc @@ -312,6 +312,15 @@ void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget) { DCHECK(!params.bounds.IsEmpty()); } else { is_frameless_ = cef_delegate()->IsFrameless(cef_window); + + const bool with_standard_buttons = + cef_delegate()->WithStandardWindowButtons(cef_window); + + const auto title_bar_height = GetTitlebarHeight(cef_window); + + params.native_widget = view_util::CreateNativeWidget( + widget, is_frameless_, with_standard_buttons, title_bar_height); + can_resize = cef_delegate()->CanResize(cef_window); const auto show_state = cef_delegate()->GetInitialShowState(cef_window); @@ -657,3 +666,14 @@ views::NonClientFrameView* CefWindowView::GetNonClientFrameView() const { } return widget->non_client_view()->frame_view(); } + +absl::optional CefWindowView::GetTitlebarHeight( + const CefRefPtr& window) const { + float title_bar_height = 0; + const bool has_title_bar_height = + cef_delegate()->GetTitlebarHeight(window, &title_bar_height); + if (has_title_bar_height) { + return title_bar_height; + } + return absl::nullopt; +} \ No newline at end of file diff --git a/libcef/browser/views/window_view.h b/libcef/browser/views/window_view.h index 6789636b8..5b52a3f3f 100644 --- a/libcef/browser/views/window_view.h +++ b/libcef/browser/views/window_view.h @@ -14,6 +14,7 @@ #include "libcef/browser/views/overlay_view_host.h" #include "libcef/browser/views/panel_view.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/skia/include/core/SkRegion.h" #include "ui/display/display.h" #include "ui/views/widget/widget_delegate.h" @@ -119,6 +120,9 @@ class CefWindowView void MoveOverlaysIfNecessary(); + absl::optional GetTitlebarHeight( + const CefRefPtr& window) const; + // Not owned by this object. Delegate* window_delegate_; diff --git a/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc b/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc index 30b849439..64c799e33 100644 --- a/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc +++ b/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=af80a36cdcb47a18eb1ac8bc3315dfd322f4e96e$ +// $hash=18f715de465689a4e8484bbced8ad92d9434438a$ // #include "libcef_dll/cpptoc/views/window_delegate_cpptoc.h" @@ -270,6 +270,62 @@ window_delegate_is_frameless(struct _cef_window_delegate_t* self, return _retval; } +int CEF_CALLBACK window_delegate_with_standard_window_buttons( + struct _cef_window_delegate_t* self, + cef_window_t* window) { + shutdown_checker::AssertNotShutdown(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) { + return 0; + } + // Verify param: window; type: refptr_diff + DCHECK(window); + if (!window) { + return 0; + } + + // Execute + bool _retval = CefWindowDelegateCppToC::Get(self)->WithStandardWindowButtons( + CefWindowCToCpp::Wrap(window)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK +window_delegate_get_titlebar_height(struct _cef_window_delegate_t* self, + cef_window_t* window, + float* titlebar_height) { + shutdown_checker::AssertNotShutdown(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) { + return 0; + } + // Verify param: window; type: refptr_diff + DCHECK(window); + if (!window) { + return 0; + } + // Verify param: titlebar_height; type: simple_byaddr + DCHECK(titlebar_height); + if (!titlebar_height) { + return 0; + } + + // Execute + bool _retval = CefWindowDelegateCppToC::Get(self)->GetTitlebarHeight( + CefWindowCToCpp::Wrap(window), titlebar_height); + + // Return type: bool + return _retval; +} + int CEF_CALLBACK window_delegate_can_resize(struct _cef_window_delegate_t* self, cef_window_t* window) { shutdown_checker::AssertNotShutdown(); @@ -705,6 +761,9 @@ CefWindowDelegateCppToC::CefWindowDelegateCppToC() { GetStruct()->get_initial_bounds = window_delegate_get_initial_bounds; GetStruct()->get_initial_show_state = window_delegate_get_initial_show_state; GetStruct()->is_frameless = window_delegate_is_frameless; + GetStruct()->with_standard_window_buttons = + window_delegate_with_standard_window_buttons; + GetStruct()->get_titlebar_height = window_delegate_get_titlebar_height; GetStruct()->can_resize = window_delegate_can_resize; GetStruct()->can_maximize = window_delegate_can_maximize; GetStruct()->can_minimize = window_delegate_can_minimize; diff --git a/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc b/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc index 70dda25ef..206d9532a 100644 --- a/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc +++ b/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=18f601c8e152c39928595e1f02c9274f0dc6ce8a$ +// $hash=40aea12873a3c8803c9d2d6c06a0270197ead58e$ // #include "libcef_dll/ctocpp/views/window_delegate_ctocpp.h" @@ -257,6 +257,63 @@ bool CefWindowDelegateCToCpp::IsFrameless(CefRefPtr window) { return _retval ? true : false; } +NO_SANITIZE("cfi-icall") +bool CefWindowDelegateCToCpp::WithStandardWindowButtons( + CefRefPtr window) { + shutdown_checker::AssertNotShutdown(); + + cef_window_delegate_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, with_standard_window_buttons)) { + return false; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: window; type: refptr_diff + DCHECK(window.get()); + if (!window.get()) { + return false; + } + + // Execute + int _retval = _struct->with_standard_window_buttons( + _struct, CefWindowCppToC::Wrap(window)); + + // Return type: bool + return _retval ? true : false; +} + +NO_SANITIZE("cfi-icall") +bool CefWindowDelegateCToCpp::GetTitlebarHeight(CefRefPtr window, + float* titlebar_height) { + shutdown_checker::AssertNotShutdown(); + + cef_window_delegate_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_titlebar_height)) { + return false; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: window; type: refptr_diff + DCHECK(window.get()); + if (!window.get()) { + return false; + } + // Verify param: titlebar_height; type: simple_byaddr + DCHECK(titlebar_height); + if (!titlebar_height) { + return false; + } + + // Execute + int _retval = _struct->get_titlebar_height( + _struct, CefWindowCppToC::Wrap(window), titlebar_height); + + // Return type: bool + return _retval ? true : false; +} + NO_SANITIZE("cfi-icall") bool CefWindowDelegateCToCpp::CanResize(CefRefPtr window) { shutdown_checker::AssertNotShutdown(); diff --git a/libcef_dll/ctocpp/views/window_delegate_ctocpp.h b/libcef_dll/ctocpp/views/window_delegate_ctocpp.h index 6f1f42026..def8dd49c 100644 --- a/libcef_dll/ctocpp/views/window_delegate_ctocpp.h +++ b/libcef_dll/ctocpp/views/window_delegate_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=1a923e68b1e07234f97d3c219cc70cc91c118a77$ +// $hash=d100d8866a7eab2a163d4ddb3cacd00141f65757$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_WINDOW_DELEGATE_CTOCPP_H_ @@ -50,6 +50,9 @@ class CefWindowDelegateCToCpp CefRect GetInitialBounds(CefRefPtr window) override; cef_show_state_t GetInitialShowState(CefRefPtr window) override; bool IsFrameless(CefRefPtr window) override; + bool WithStandardWindowButtons(CefRefPtr window) override; + bool GetTitlebarHeight(CefRefPtr window, + float* titlebar_height) override; bool CanResize(CefRefPtr window) override; bool CanMaximize(CefRefPtr window) override; bool CanMinimize(CefRefPtr window) override; diff --git a/tests/cefclient/browser/views_overlay_controls.cc b/tests/cefclient/browser/views_overlay_controls.cc index 38ebba0bf..d84b19cdf 100644 --- a/tests/cefclient/browser/views_overlay_controls.cc +++ b/tests/cefclient/browser/views_overlay_controls.cc @@ -5,6 +5,7 @@ #include "tests/cefclient/browser/views_overlay_controls.h" #include +#include #include #include "include/views/cef_box_layout.h" @@ -34,9 +35,37 @@ std::string GetLabel(ViewsOverlayControls::Command command, bool maximized) { return std::string(); } +std::array GetButtons() { +#if defined(OS_MAC) + return {ViewsOverlayControls::Command::kClose, + ViewsOverlayControls::Command::kMaximize, + ViewsOverlayControls::Command::kMinimize}; +#else + return {ViewsOverlayControls::Command::kMinimize, + ViewsOverlayControls::Command::kMaximize, + ViewsOverlayControls::Command::kClose}; +#endif +} + +cef_docking_mode_t GetPanelDockingMode() { +#if defined(OS_MAC) + return CEF_DOCKING_MODE_TOP_LEFT; +#else + return CEF_DOCKING_MODE_TOP_RIGHT; +#endif +} +cef_docking_mode_t GetMenuDockingMode() { +#if defined(OS_MAC) + return CEF_DOCKING_MODE_TOP_RIGHT; +#else + return CEF_DOCKING_MODE_TOP_LEFT; +#endif +} + } // namespace -ViewsOverlayControls::ViewsOverlayControls() = default; +ViewsOverlayControls::ViewsOverlayControls(bool with_window_buttons) + : with_window_buttons_(with_window_buttons) {} void ViewsOverlayControls::Initialize(CefRefPtr window, CefRefPtr menu_button, @@ -49,30 +78,31 @@ void ViewsOverlayControls::Initialize(CefRefPtr window, window_ = window; window_maximized_ = window_->IsMaximized(); - // Window control buttons. These controls are currently text which means that - // we can't use a transparent background because subpixel text rendering will - // break. See comments on the related DCHECK in Label::PaintText. - panel_ = CefPanel::CreatePanel(nullptr); - views_style::ApplyTo(panel_); + if (with_window_buttons_) { + // Window control buttons. These controls are currently text which means + // that we can't use a transparent background because subpixel text + // rendering will break. + // See comments on the related DCHECK in Label::PaintText. + panel_ = CefPanel::CreatePanel(nullptr); + views_style::ApplyTo(panel_); - // Use a horizontal box layout. - CefBoxLayoutSettings panel_layout_settings; - panel_layout_settings.horizontal = true; - panel_->SetToBoxLayout(panel_layout_settings); + // Use a horizontal box layout. + CefBoxLayoutSettings panel_layout_settings; + panel_layout_settings.horizontal = true; + panel_->SetToBoxLayout(panel_layout_settings); - panel_->AddChildView(CreateButton(ViewsOverlayControls::Command::kMinimize)); - panel_->AddChildView(CreateButton(ViewsOverlayControls::Command::kMaximize)); - panel_->AddChildView(CreateButton(ViewsOverlayControls::Command::kClose)); - - panel_controller_ = - window->AddOverlayView(panel_, CEF_DOCKING_MODE_TOP_RIGHT); - panel_controller_->SetVisible(true); + for (auto button : GetButtons()) { + panel_->AddChildView(CreateButton(button)); + } + panel_controller_ = window->AddOverlayView(panel_, GetPanelDockingMode()); + panel_controller_->SetInsets(CefInsets(kInsets, kInsets, 0, kInsets)); + panel_controller_->SetVisible(true); + } // Menu button. menu_button->SetBackgroundColor(kBackgroundColor); - menu_controller_ = - window_->AddOverlayView(menu_button, CEF_DOCKING_MODE_TOP_LEFT); - menu_controller_->SetInsets(CefInsets(kInsets, kInsets, 0, 0)); + menu_controller_ = window_->AddOverlayView(menu_button, GetMenuDockingMode()); + menu_controller_->SetInsets(CefInsets(kInsets, kInsets, 0, kInsets)); menu_controller_->SetVisible(true); // Location bar. Will be made visible in UpdateControls(). @@ -87,8 +117,10 @@ void ViewsOverlayControls::Initialize(CefRefPtr window, void ViewsOverlayControls::Destroy() { window_ = nullptr; panel_ = nullptr; - panel_controller_->Destroy(); - panel_controller_ = nullptr; + if (panel_controller_) { + panel_controller_->Destroy(); + panel_controller_ = nullptr; + } menu_controller_->Destroy(); menu_controller_ = nullptr; location_bar_ = nullptr; @@ -180,7 +212,7 @@ CefRefPtr ViewsOverlayControls::CreateButton(Command command) { } void ViewsOverlayControls::MaybeUpdateMaximizeButton() { - if (window_->IsMaximized() == window_maximized_) { + if (!with_window_buttons_ || window_->IsMaximized() == window_maximized_) { return; } window_maximized_ = !window_maximized_; diff --git a/tests/cefclient/browser/views_overlay_controls.h b/tests/cefclient/browser/views_overlay_controls.h index c33ab9eb5..475fd90cd 100644 --- a/tests/cefclient/browser/views_overlay_controls.h +++ b/tests/cefclient/browser/views_overlay_controls.h @@ -25,7 +25,7 @@ class ViewsOverlayControls : public CefButtonDelegate { kClose, }; - ViewsOverlayControls(); + explicit ViewsOverlayControls(bool with_window_buttons); void Initialize(CefRefPtr window, CefRefPtr menu_button, @@ -53,6 +53,7 @@ class ViewsOverlayControls : public CefButtonDelegate { // Window control buttons. CefRefPtr panel_; CefRefPtr panel_controller_; + const bool with_window_buttons_; // Location bar. CefRefPtr location_bar_; diff --git a/tests/cefclient/browser/views_window.cc b/tests/cefclient/browser/views_window.cc index 59092d7b6..fc6f09c0d 100644 --- a/tests/cefclient/browser/views_window.cc +++ b/tests/cefclient/browser/views_window.cc @@ -34,6 +34,11 @@ const char kDefaultExtensionIcon[] = "window_icon"; constexpr int kDefaultWidth = 800; constexpr int kDefaultHeight = 600; +#if defined(OS_MAC) +constexpr int kTitleBarHeight = 35; +constexpr int kWindowButtonsWidth = 80; +#endif + // Control IDs for Views in the top-level Window. enum ControlIds { ID_WINDOW = 1, @@ -106,6 +111,22 @@ void AddFileMenuItems(CefRefPtr file_menu) { true); } +CefBrowserViewDelegate::ChromeToolbarType CalculateChromeToolbarType( + const std::string& toolbar_type, + bool hide_toolbar, + bool with_overlay_controls) { + if (!MainContext::Get()->UseChromeRuntime() || toolbar_type == "none" || + hide_toolbar) { + return CEF_CTT_NONE; + } + + if (toolbar_type == "location") { + return CEF_CTT_LOCATION; + } + + return with_overlay_controls ? CEF_CTT_LOCATION : CEF_CTT_NORMAL; +} + } // namespace // static @@ -278,17 +299,13 @@ void ViewsWindow::SetDraggableRegions( return; } - std::vector window_regions; - // Convert the regions from BrowserView to Window coordinates. - std::vector::const_iterator it = regions.begin(); - for (; it != regions.end(); ++it) { - CefDraggableRegion region = *it; + std::vector window_regions = regions; + for (auto& region : window_regions) { CefPoint origin = CefPoint(region.bounds.x, region.bounds.y); browser_view_->ConvertPointToWindow(origin); region.bounds.x = origin.x; region.bounds.y = origin.y; - window_regions.push_back(region); } if (overlay_controls_) { @@ -653,6 +670,14 @@ void ViewsWindow::OnWindowBoundsChanged(CefRefPtr window, // Track the last visible bounds for window restore purposes. last_visible_bounds_ = new_bounds; } + +#if defined(OS_MAC) + if (frameless_ && with_standard_buttons_ && top_toolbar_) { + auto insets = top_toolbar_->GetInsets(); + insets.left = window->IsFullscreen() ? 0 : kWindowButtonsWidth; + top_toolbar_->SetInsets(insets); + } +#endif } bool ViewsWindow::CanClose(CefRefPtr window) { @@ -701,6 +726,24 @@ bool ViewsWindow::IsFrameless(CefRefPtr window) { return frameless_; } +bool ViewsWindow::WithStandardWindowButtons(CefRefPtr window) { + CEF_REQUIRE_UI_THREAD(); + return with_standard_buttons_; +} + +bool ViewsWindow::GetTitlebarHeight(CefRefPtr window, + float* titlebar_height) { + CEF_REQUIRE_UI_THREAD(); +#if defined(OS_MAC) + if (frameless_ && with_standard_buttons_) { + *titlebar_height = kTitleBarHeight; + return true; + } +#endif + + return false; +} + bool ViewsWindow::CanResize(CefRefPtr window) { CEF_REQUIRE_UI_THREAD(); // Don't allow windows hosting extensions to resize. @@ -815,7 +858,9 @@ void ViewsWindow::OnWindowChanged(CefRefPtr view, bool added) { } if (with_overlay_controls_) { - overlay_controls_ = new ViewsOverlayControls(); + // Add window buttons if we don't have standard ones + const bool with_window_buttons = !with_standard_buttons_; + overlay_controls_ = new ViewsOverlayControls(with_window_buttons); overlay_controls_->Initialize(window_, CreateMenuButton(), CreateLocationBar(), chrome_toolbar_type_ != CEF_CTT_NONE); @@ -865,6 +910,10 @@ ViewsWindow::ViewsWindow(Delegate* delegate, const bool hide_frame = command_line->HasSwitch(switches::kHideFrame); const bool hide_overlays = command_line->HasSwitch(switches::kHideOverlays); + const bool hide_toolbar = + hide_frame && hide_overlays && !delegate_->WithControls(); + const bool show_window_buttons = + command_line->HasSwitch(switches::kShowWindowButtons); // Without a window frame. frameless_ = hide_frame || delegate_->WithExtension(); @@ -873,20 +922,13 @@ ViewsWindow::ViewsWindow(Delegate* delegate, with_overlay_controls_ = hide_frame && !hide_overlays && !delegate_->WithControls(); - if (MainContext::Get()->UseChromeRuntime()) { - const std::string& toolbar_type = - command_line->GetSwitchValue(switches::kShowChromeToolbar); - if (toolbar_type == "none") { - chrome_toolbar_type_ = CEF_CTT_NONE; - } else if (toolbar_type == "location") { - chrome_toolbar_type_ = CEF_CTT_LOCATION; - } else { - chrome_toolbar_type_ = - with_overlay_controls_ ? CEF_CTT_LOCATION : CEF_CTT_NORMAL; - } - } else { - chrome_toolbar_type_ = CEF_CTT_NONE; - } + // If window has frame or flag passed explicitly + with_standard_buttons_ = !frameless_ || show_window_buttons; + + const std::string& toolbar_type = + command_line->GetSwitchValue(switches::kShowChromeToolbar); + chrome_toolbar_type_ = CalculateChromeToolbarType(toolbar_type, hide_toolbar, + with_overlay_controls_); #if !defined(OS_MAC) // On Mac we don't show a top menu on the window. The options are available in @@ -1025,9 +1067,8 @@ void ViewsWindow::AddControls() { top_panel->SetToBoxLayout(top_panel_layout_settings); // Add the buttons and URL textfield to |top_panel|. - for (size_t i = 0U; i < browse_buttons.size(); ++i) { - top_panel->AddChildView(browse_buttons[i]); - } + for (auto& browse_button : browse_buttons) + top_panel->AddChildView(browse_button); top_panel->AddChildView(location_bar_); UpdateExtensionControls(); @@ -1043,6 +1084,14 @@ void ViewsWindow::AddControls() { top_toolbar_ = top_panel; } +#if defined(OS_MAC) + if (frameless_ && with_standard_buttons_) { + auto insets = top_toolbar_->GetInsets(); + insets.left = kWindowButtonsWidth; + top_toolbar_->SetInsets(insets); + } +#endif + // Add the top panel and browser view to |window|. int top_index = 0; if (top_menu_panel) { @@ -1061,8 +1110,10 @@ void ViewsWindow::AddControls() { // Lay out |window| again with the new button sizes. window_->Layout(); + const int buttons_number = static_cast(browse_buttons.size()); + // Minimum window width is the size of all buttons plus some extra. - min_width = browse_buttons[0]->GetBounds().width * 4 + + min_width = browse_buttons[0]->GetBounds().width * buttons_number + menu_button_->GetBounds().width + 100; } diff --git a/tests/cefclient/browser/views_window.h b/tests/cefclient/browser/views_window.h index b49dd43f7..14c974469 100644 --- a/tests/cefclient/browser/views_window.h +++ b/tests/cefclient/browser/views_window.h @@ -174,6 +174,9 @@ class ViewsWindow : public CefBrowserViewDelegate, CefRect GetInitialBounds(CefRefPtr window) override; cef_show_state_t GetInitialShowState(CefRefPtr window) override; bool IsFrameless(CefRefPtr window) override; + bool WithStandardWindowButtons(CefRefPtr window) override; + bool GetTitlebarHeight(CefRefPtr window, + float* titlebar_height) override; bool CanResize(CefRefPtr window) override; bool CanClose(CefRefPtr window) override; bool OnAccelerator(CefRefPtr window, int command_id) override; @@ -238,6 +241,7 @@ class ViewsWindow : public CefBrowserViewDelegate, bool frameless_; bool with_controls_; bool with_overlay_controls_; + bool with_standard_buttons_; ChromeToolbarType chrome_toolbar_type_; CefRefPtr window_; diff --git a/tests/shared/common/client_switches.cc b/tests/shared/common/client_switches.cc index 322451455..8cd9f85ca 100644 --- a/tests/shared/common/client_switches.cc +++ b/tests/shared/common/client_switches.cc @@ -52,6 +52,7 @@ const char kHideChromeStatusBubble[] = "hide-chrome-status-bubble"; const char kUseDefaultPopup[] = "use-default-popup"; const char kUseClientDialogs[] = "use-client-dialogs"; const char kUseTestHttpServer[] = "use-test-http-server"; +const char kShowWindowButtons[] = "show-window-buttons"; } // namespace switches } // namespace client diff --git a/tests/shared/common/client_switches.h b/tests/shared/common/client_switches.h index 8d9d92b62..6cc3fb4a7 100644 --- a/tests/shared/common/client_switches.h +++ b/tests/shared/common/client_switches.h @@ -46,6 +46,7 @@ extern const char kHideChromeStatusBubble[]; extern const char kUseDefaultPopup[]; extern const char kUseClientDialogs[]; extern const char kUseTestHttpServer[]; +extern const char kShowWindowButtons[]; } // namespace switches } // namespace client