Skip to content

Commit

Permalink
views: mac: Support dynamic resize of title bar height (see chromiume…
Browse files Browse the repository at this point in the history
…mbedded#3189)

This is intended for usage with frameless windows that show the standard window
buttons, where resizing the title bar height changes the button offset. Returning a
different value from CefWindowDelegate::GetTitlebarHeight and forcing a resize of
the NSWindow's theme frame (see ViewsWindow::NudgeWindow) will update the
title bar height.

To test:
1. Run `cefclient --use-views --hide-frame --show-window-buttons --url=http://tests/window`
2. Enter a new value for title bar height and click the "Set Titlebar Height" button
  • Loading branch information
nik-sp authored and magreenblatt committed Mar 16, 2023
1 parent 0a2c7a1 commit c83b3cd
Show file tree
Hide file tree
Showing 19 changed files with 155 additions and 61 deletions.
1 change: 1 addition & 0 deletions cef_paths2.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@
'tests/cefclient/browser/temp_window_mac.mm',
'tests/cefclient/browser/text_input_client_osr_mac.h',
'tests/cefclient/browser/text_input_client_osr_mac.mm',
'tests/cefclient/browser/views_window_mac.mm',
'tests/cefclient/browser/window_test_runner_mac.h',
'tests/cefclient/browser/window_test_runner_mac.mm',
'tests/cefclient/cefclient_mac.mm',
Expand Down
16 changes: 9 additions & 7 deletions libcef/browser/views/native_widget_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@
#define CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_
#pragma once

#include "third_party/abseil-cpp/absl/types/optional.h"
#include "include/internal/cef_ptr.h"

#include "ui/views/widget/native_widget_mac.h"

class CefWindow;
class CefWindowDelegate;

class CefNativeWidgetMac : public views::NativeWidgetMac {
public:
CefNativeWidgetMac(views::internal::NativeWidgetDelegate* delegate,
bool is_frameless,
bool with_window_buttons,
absl::optional<float> title_bar_height);
CefRefPtr<CefWindow> window,
CefWindowDelegate* window_delegate);
~CefNativeWidgetMac() override = default;

CefNativeWidgetMac(const CefNativeWidgetMac&) = delete;
Expand All @@ -29,9 +32,8 @@ class CefNativeWidgetMac : public views::NativeWidgetMac {
float* titlebar_height) override;

private:
const bool is_frameless_;
const bool with_window_buttons_;
const absl::optional<float> title_bar_height_;
const CefRefPtr<CefWindow> window_;
CefWindowDelegate* const window_delegate_;
};

#endif // CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_
24 changes: 13 additions & 11 deletions libcef/browser/views/native_widget_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,36 @@

#include "libcef/browser/views/native_widget_mac.h"

#include "include/views/cef_window.h"
#include "include/views/cef_window_delegate.h"
#include "libcef/browser/views/ns_window.h"

CefNativeWidgetMac::CefNativeWidgetMac(
views::internal::NativeWidgetDelegate* delegate,
bool is_frameless,
bool with_window_buttons,
absl::optional<float> title_bar_height)
CefRefPtr<CefWindow> window,
CefWindowDelegate* window_delegate)
: views::NativeWidgetMac(delegate),
is_frameless_(is_frameless),
with_window_buttons_(with_window_buttons),
title_bar_height_(title_bar_height) {}
window_(window),
window_delegate_(window_delegate) {}

NativeWidgetMacNSWindow* CefNativeWidgetMac::CreateNSWindow(
const remote_cocoa::mojom::CreateWindowParams* params) {
NSUInteger style_mask =
NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable |
NSWindowStyleMaskClosable | NSWindowStyleMaskResizable |
NSWindowStyleMaskTexturedBackground;

bool is_frameless = window_delegate_->IsFrameless(window_);

auto window = [[CefNSWindow alloc] initWithStyle:style_mask
isFrameless:is_frameless_];
isFrameless:is_frameless];

if (is_frameless_) {
if (is_frameless) {
[window setTitlebarAppearsTransparent:YES];
[window setTitleVisibility:NSWindowTitleHidden];
}

if (!with_window_buttons_) {
if (!window_delegate_->WithStandardWindowButtons(window_)) {
[[window standardWindowButton:NSWindowCloseButton] setHidden:YES];
[[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
[[window standardWindowButton:NSWindowZoomButton] setHidden:YES];
Expand All @@ -42,9 +45,8 @@
void CefNativeWidgetMac::GetWindowFrameTitlebarHeight(
bool* override_titlebar_height,
float* titlebar_height) {
if (title_bar_height_) {
if (window_delegate_->GetTitlebarHeight(window_, titlebar_height)) {
*override_titlebar_height = true;
*titlebar_height = title_bar_height_.value();
} else {
views::NativeWidgetMac::GetWindowFrameTitlebarHeight(
override_titlebar_height, titlebar_height);
Expand Down
8 changes: 4 additions & 4 deletions libcef/browser/views/view_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#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"

Expand All @@ -29,6 +28,8 @@ class NativeWidgetDelegate;
}
} // namespace views

class CefWindowDelegate;

#define CEF_REQUIRE_VALID_RETURN(ret) \
if (!ParentClass::IsValid()) \
return ret;
Expand Down Expand Up @@ -148,9 +149,8 @@ CefWindowHandle GetWindowHandle(gfx::NativeWindow window);

views::NativeWidget* CreateNativeWidget(
views::internal::NativeWidgetDelegate* delegate,
bool is_frameless,
bool with_window_buttons,
absl::optional<float> title_bar_height);
CefRefPtr<CefWindow> window,
CefWindowDelegate* window_delegate);

} // namespace view_util

Expand Down
5 changes: 2 additions & 3 deletions libcef/browser/views/view_util_aura.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ CefWindowHandle GetWindowHandle(gfx::NativeWindow window) {

views::NativeWidget* CreateNativeWidget(
views::internal::NativeWidgetDelegate* delegate,
bool is_frameless,
bool with_window_buttons,
absl::optional<float> title_bar_height) {
CefRefPtr<CefWindow> window,
CefWindowDelegate* window_delegate) {
return nullptr;
}

Expand Down
8 changes: 3 additions & 5 deletions libcef/browser/views/view_util_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,8 @@ CefWindowHandle GetWindowHandle(gfx::NativeWindow window) {

views::NativeWidget* CreateNativeWidget(
views::internal::NativeWidgetDelegate* delegate,
bool is_frameless,
bool with_window_buttons,
absl::optional<float> title_bar_height) {
return new CefNativeWidgetMac(delegate, is_frameless, with_window_buttons,
title_bar_height);
CefRefPtr<CefWindow> window,
CefWindowDelegate* window_delegate) {
return new CefNativeWidgetMac(delegate, window, window_delegate);
}
} // namespace view_util
20 changes: 2 additions & 18 deletions libcef/browser/views/window_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,8 @@ void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget) {
} 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);
params.native_widget =
view_util::CreateNativeWidget(widget, cef_window, cef_delegate());

can_resize = cef_delegate()->CanResize(cef_window);

Expand Down Expand Up @@ -666,14 +661,3 @@ views::NonClientFrameView* CefWindowView::GetNonClientFrameView() const {
}
return widget->non_client_view()->frame_view();
}

absl::optional<float> CefWindowView::GetTitlebarHeight(
const CefRefPtr<CefWindow>& 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;
}
4 changes: 0 additions & 4 deletions libcef/browser/views/window_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#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"
Expand Down Expand Up @@ -120,9 +119,6 @@ class CefWindowView

void MoveOverlaysIfNecessary();

absl::optional<float> GetTitlebarHeight(
const CefRefPtr<CefWindow>& window) const;

// Not owned by this object.
Delegate* window_delegate_;

Expand Down
6 changes: 6 additions & 0 deletions tests/cefclient/browser/root_window_views.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ RootWindowViews::~RootWindowViews() {
REQUIRE_MAIN_THREAD();
}

void RootWindowViews::SetTitlebarHeight(const std::optional<float>& height) {
if (window_) {
window_->SetTitlebarHeight(height);
}
}

void RootWindowViews::Init(RootWindow::Delegate* delegate,
std::unique_ptr<RootWindowConfig> config,
const CefBrowserSettings& settings) {
Expand Down
2 changes: 2 additions & 0 deletions tests/cefclient/browser/root_window_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class RootWindowViews : public RootWindow,
RootWindowViews();
~RootWindowViews();

void SetTitlebarHeight(const std::optional<float>& height);

// RootWindow methods:
void Init(RootWindow::Delegate* delegate,
std::unique_ptr<RootWindowConfig> config,
Expand Down
27 changes: 25 additions & 2 deletions tests/cefclient/browser/views_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,16 @@ bool ViewsWindow::GetWindowRestorePreferences(
return true;
}

void ViewsWindow::SetTitlebarHeight(const std::optional<float>& height) {
CEF_REQUIRE_UI_THREAD();
if (height.has_value()) {
override_titlebar_height_ = height;
} else {
override_titlebar_height_ = default_titlebar_height_;
}
NudgeWindow();
}

CefRefPtr<CefBrowserViewDelegate> ViewsWindow::GetDelegateForPopupBrowserView(
CefRefPtr<CefBrowserView> browser_view,
const CefBrowserSettings& settings,
Expand Down Expand Up @@ -735,8 +745,8 @@ bool ViewsWindow::GetTitlebarHeight(CefRefPtr<CefWindow> window,
float* titlebar_height) {
CEF_REQUIRE_UI_THREAD();
#if defined(OS_MAC)
if (frameless_ && with_standard_buttons_) {
*titlebar_height = kTitleBarHeight;
if (override_titlebar_height_.has_value()) {
*titlebar_height = override_titlebar_height_.value();
return true;
}
#endif
Expand Down Expand Up @@ -925,6 +935,13 @@ ViewsWindow::ViewsWindow(Delegate* delegate,
// If window has frame or flag passed explicitly
with_standard_buttons_ = !frameless_ || show_window_buttons;

#if defined(OS_MAC)
if (frameless_ && with_standard_buttons_) {
default_titlebar_height_ = kTitleBarHeight;
override_titlebar_height_ = kTitleBarHeight;
}
#endif

const std::string& toolbar_type =
command_line->GetSwitchValue(switches::kShowChromeToolbar);
chrome_toolbar_type_ = CalculateChromeToolbarType(toolbar_type, hide_toolbar,
Expand Down Expand Up @@ -1262,4 +1279,10 @@ void ViewsWindow::OnExtensionWindowClosed() {
extension_button_pressed_lock_ = nullptr;
}

#if !defined(OS_MAC)
void ViewsWindow::NudgeWindow() {
NOTIMPLEMENTED();
}
#endif

} // namespace client
6 changes: 6 additions & 0 deletions tests/cefclient/browser/views_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class ViewsWindow : public CefBrowserViewDelegate,

bool GetWindowRestorePreferences(cef_show_state_t& show_state,
std::optional<CefRect>& dip_bounds);
void SetTitlebarHeight(const std::optional<float>& height);

// CefBrowserViewDelegate methods:
CefRefPtr<CefBrowserViewDelegate> GetDelegateForPopupBrowserView(
Expand Down Expand Up @@ -236,6 +237,8 @@ class ViewsWindow : public CefBrowserViewDelegate,
const ImageCache::ImageSet& images);
void OnExtensionWindowClosed();

void NudgeWindow();

Delegate* delegate_; // Not owned by this object.
CefRefPtr<CefBrowserView> browser_view_;
bool frameless_;
Expand All @@ -258,6 +261,9 @@ class ViewsWindow : public CefBrowserViewDelegate,

CefRefPtr<ViewsOverlayControls> overlay_controls_;

std::optional<float> default_titlebar_height_;
std::optional<float> override_titlebar_height_;

// Structure representing an extension.
struct ExtensionInfo {
ExtensionInfo(CefRefPtr<CefExtension> extension, CefRefPtr<CefImage> image)
Expand Down
24 changes: 24 additions & 0 deletions tests/cefclient/browser/views_window_mac.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 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 "tests/cefclient/browser/views_window.h"

#include <Cocoa/Cocoa.h>

namespace client {

void ViewsWindow::NudgeWindow() {
if (window_) {
auto view = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_->GetWindowHandle());
NSWindow* main_window = view.window;

auto theme_frame = main_window.contentView.superview;
// Nudge view frame a little to force an update.
NSSize size = theme_frame.frame.size;
[theme_frame setFrameSize:NSMakeSize(size.width - 1, size.height)];
[theme_frame setFrameSize:size];
}
}

}
17 changes: 13 additions & 4 deletions tests/cefclient/browser/window_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const char kMessagePositionName[] = "WindowTest.Position";
const char kMessageMinimizeName[] = "WindowTest.Minimize";
const char kMessageMaximizeName[] = "WindowTest.Maximize";
const char kMessageRestoreName[] = "WindowTest.Restore";
const char kMessageTitlebarHeightName[] = "WindowTest.TitlebarHeight";

// Create the appropriate platform test runner object.
std::unique_ptr<WindowTestRunner> CreateWindowTestRunner() {
Expand Down Expand Up @@ -69,6 +70,15 @@ std::vector<int> ParsePosition(const std::string& message_name) {
return vec;
}

std::optional<float> ParseHeight(const std::string& message) {
if (message.size() > sizeof(kMessageTitlebarHeightName)) {
const std::string& val = message.substr(sizeof(kMessageTitlebarHeightName));
return std::stof(val);
} else {
return std::nullopt;
}
}

// Handle messages in the browser process.
class Handler : public CefMessageRouterBrowserSide::Handler {
public:
Expand All @@ -91,18 +101,17 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
if (message_name.find(kMessagePositionName) == 0) {
const auto vec = ParsePosition(message_name);
if (vec.size() == 4) {
// Execute SetPos() on the main thread.
runner_->SetPos(browser, vec[0], vec[1], vec[2], vec[3]);
}
} else if (message_name == kMessageMinimizeName) {
// Execute Minimize() on the main thread.
runner_->Minimize(browser);
} else if (message_name == kMessageMaximizeName) {
// Execute Maximize() on the main thread.
runner_->Maximize(browser);
} else if (message_name == kMessageRestoreName) {
// Execute Restore() on the main thread.
runner_->Restore(browser);
} else if (message_name.find(kMessageTitlebarHeightName) == 0) {
const auto height = ParseHeight(message_name);
runner_->SetTitleBarHeight(browser, height);
} else {
NOTREACHED();
}
Expand Down
5 changes: 5 additions & 0 deletions tests/cefclient/browser/window_test_runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,10 @@ void WindowTestRunner::ModifyBounds(const CefRect& display, CefRect& window) {
}
}

void WindowTestRunner::SetTitleBarHeight(CefRefPtr<CefBrowser> browser,
const std::optional<float>& height) {
NOTIMPLEMENTED();
}

} // namespace window_test
} // namespace client
Loading

0 comments on commit c83b3cd

Please sign in to comment.