mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
views: mac: Fix frameless window behavior (fixes issue #3189)
Frameless windows now display as expected. Default traffic light buttons can optionally be shown at configurable vertical position. Layout respects text direction.
This commit is contained in:
committed by
Marshall Greenblatt
parent
6926287894
commit
f6de0344cb
37
libcef/browser/views/native_widget_mac.h
Normal file
37
libcef/browser/views/native_widget_mac.h
Normal file
@@ -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<float> 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<float> title_bar_height_;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_
|
52
libcef/browser/views/native_widget_mac.mm
Normal file
52
libcef/browser/views/native_widget_mac.mm
Normal file
@@ -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<float> 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);
|
||||
}
|
||||
}
|
20
libcef/browser/views/ns_window.h
Normal file
20
libcef/browser/views/ns_window.h
Normal file
@@ -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_
|
104
libcef/browser/views/ns_window.mm
Normal file
104
libcef/browser/views/ns_window.mm
Normal file
@@ -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<CefNSWindow>([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<CefNSWindow>([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
|
@@ -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<float> title_bar_height);
|
||||
|
||||
} // namespace view_util
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_VIEWS_VIEW_UTIL_H_
|
||||
|
@@ -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<float> title_bar_height) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace view_util
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#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<float> title_bar_height) {
|
||||
return new CefNativeWidgetMac(delegate, is_frameless, with_window_buttons,
|
||||
title_bar_height);
|
||||
}
|
||||
} // namespace view_util
|
||||
|
@@ -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<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;
|
||||
}
|
@@ -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<float> GetTitlebarHeight(
|
||||
const CefRefPtr<CefWindow>& window) const;
|
||||
|
||||
// Not owned by this object.
|
||||
Delegate* window_delegate_;
|
||||
|
||||
|
Reference in New Issue
Block a user