feat: custom positioning for traffic light buttons (#21781)

* feat: custom positioning for traffic light buttons

* remove NSLog and unnecessary call-site in IsVisible()

* no longer need to check if entering fullscreen

* change API to take a point object

Co-authored-by: tonyfwoo <55114329+tonyfwoo@users.noreply.github.com>
This commit is contained in:
Tony 2020-01-23 10:13:08 -08:00 committed by Samuel Attard
parent dd95a6f034
commit 5781850706
6 changed files with 69 additions and 0 deletions

View file

@ -229,6 +229,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
unless hovered over in the top left of the window. These custom buttons prevent unless hovered over in the top left of the window. These custom buttons prevent
issues with mouse events that occur with the standard window toolbar buttons. issues with mouse events that occur with the standard window toolbar buttons.
**Note:** This option is currently experimental. **Note:** This option is currently experimental.
* `trafficLightPosition` [Point](structures/point.md) (optional) - Set a custom position for the traffic light buttons. Can only be used with `titleBarStyle` set to `hidden`
* `fullscreenWindowTitle` Boolean (optional) - Shows the title in the * `fullscreenWindowTitle` Boolean (optional) - Shows the title in the
title bar in full screen mode on macOS for all `titleBarStyle` options. title bar in full screen mode on macOS for all `titleBarStyle` options.
Default is `false`. Default is `false`.

View file

@ -149,6 +149,10 @@ class NativeWindowMac : public NativeWindow {
void SetCollectionBehavior(bool on, NSUInteger flag); void SetCollectionBehavior(bool on, NSUInteger flag);
void SetWindowLevel(int level); void SetWindowLevel(int level);
// Custom traffic light positioning
void RepositionTrafficLights();
void SetExitingFullScreen(bool flag);
enum class TitleBarStyle { enum class TitleBarStyle {
NORMAL, NORMAL,
HIDDEN, HIDDEN,
@ -162,6 +166,7 @@ class NativeWindowMac : public NativeWindow {
bool zoom_to_page_width() const { return zoom_to_page_width_; } bool zoom_to_page_width() const { return zoom_to_page_width_; }
bool fullscreen_window_title() const { return fullscreen_window_title_; } bool fullscreen_window_title() const { return fullscreen_window_title_; }
bool always_simple_fullscreen() const { return always_simple_fullscreen_; } bool always_simple_fullscreen() const { return always_simple_fullscreen_; }
bool exiting_fullscreen() const { return exiting_fullscreen_; }
protected: protected:
// views::WidgetDelegate: // views::WidgetDelegate:
@ -198,6 +203,8 @@ class NativeWindowMac : public NativeWindow {
bool zoom_to_page_width_ = false; bool zoom_to_page_width_ = false;
bool fullscreen_window_title_ = false; bool fullscreen_window_title_ = false;
bool resizable_ = true; bool resizable_ = true;
bool exiting_fullscreen_ = false;
gfx::Point traffic_light_position_;
NSInteger attention_request_id_ = 0; // identifier from requestUserAttention NSInteger attention_request_id_ = 0; // identifier from requestUserAttention

View file

@ -28,6 +28,7 @@
#include "shell/browser/ui/inspectable_web_contents_view.h" #include "shell/browser/ui/inspectable_web_contents_view.h"
#include "shell/browser/window_list.h" #include "shell/browser/window_list.h"
#include "shell/common/deprecate_util.h" #include "shell/common/deprecate_util.h"
#include "shell/common/gin_converters/gfx_converter.h"
#include "shell/common/gin_helper/dictionary.h" #include "shell/common/gin_helper/dictionary.h"
#include "shell/common/options_switches.h" #include "shell/common/options_switches.h"
#include "skia/ext/skia_utils_mac.h" #include "skia/ext/skia_utils_mac.h"
@ -335,6 +336,7 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
options.Get(options::kZoomToPageWidth, &zoom_to_page_width_); options.Get(options::kZoomToPageWidth, &zoom_to_page_width_);
options.Get(options::kFullscreenWindowTitle, &fullscreen_window_title_); options.Get(options::kFullscreenWindowTitle, &fullscreen_window_title_);
options.Get(options::kSimpleFullScreen, &always_simple_fullscreen_); options.Get(options::kSimpleFullScreen, &always_simple_fullscreen_);
options.Get(options::kTrafficLightPosition, &traffic_light_position_);
bool minimizable = true; bool minimizable = true;
options.Get(options::kMinimizable, &minimizable); options.Get(options::kMinimizable, &minimizable);
@ -509,6 +511,45 @@ NativeWindowMac::~NativeWindowMac() {
[NSEvent removeMonitor:wheel_event_monitor_]; [NSEvent removeMonitor:wheel_event_monitor_];
} }
void NativeWindowMac::RepositionTrafficLights() {
if (!traffic_light_position_.x() && !traffic_light_position_.y()) {
return;
}
NSWindow* window = window_;
NSButton* close = [window standardWindowButton:NSWindowCloseButton];
NSButton* miniaturize =
[window standardWindowButton:NSWindowMiniaturizeButton];
NSButton* zoom = [window standardWindowButton:NSWindowZoomButton];
NSView* titleBarContainerView = close.superview.superview;
// Hide the container when exiting fullscreen, otherwise traffic light buttons
// jump
if (exiting_fullscreen_) {
[titleBarContainerView setHidden:YES];
return;
}
[titleBarContainerView setHidden:NO];
CGFloat buttonHeight = [close frame].size.height;
CGFloat titleBarFrameHeight = buttonHeight + traffic_light_position_.y();
CGRect titleBarRect = titleBarContainerView.frame;
titleBarRect.size.height = titleBarFrameHeight;
titleBarRect.origin.y = window.frame.size.height - titleBarFrameHeight;
[titleBarContainerView setFrame:titleBarRect];
NSArray* windowButtons = @[ close, miniaturize, zoom ];
const CGFloat space_between =
[miniaturize frame].origin.x - [close frame].origin.x;
for (NSUInteger i = 0; i < windowButtons.count; i++) {
NSView* view = [windowButtons objectAtIndex:i];
CGRect rect = [view frame];
rect.origin.x = traffic_light_position_.x() + (i * space_between);
rect.origin.y = (titleBarFrameHeight - rect.size.height) / 2;
[view setFrameOrigin:rect.origin];
}
}
void NativeWindowMac::SetContentView(views::View* view) { void NativeWindowMac::SetContentView(views::View* view) {
views::View* root_view = GetContentsView(); views::View* root_view = GetContentsView();
if (content_view()) if (content_view())
@ -628,6 +669,10 @@ bool NativeWindowMac::IsVisible() {
return [window_ isVisible] && !occluded && !IsMinimized(); return [window_ isVisible] && !occluded && !IsMinimized();
} }
void NativeWindowMac::SetExitingFullScreen(bool flag) {
exiting_fullscreen_ = flag;
}
bool NativeWindowMac::IsEnabled() { bool NativeWindowMac::IsEnabled() {
return [window_ attachedSheet] == nil; return [window_ attachedSheet] == nil;
} }
@ -949,6 +994,9 @@ void NativeWindowMac::Invalidate() {
void NativeWindowMac::SetTitle(const std::string& title) { void NativeWindowMac::SetTitle(const std::string& title) {
[window_ setTitle:base::SysUTF8ToNSString(title)]; [window_ setTitle:base::SysUTF8ToNSString(title)];
if (title_bar_style_ == TitleBarStyle::HIDDEN) {
RepositionTrafficLights();
}
} }
std::string NativeWindowMac::GetTitle() { std::string NativeWindowMac::GetTitle() {

View file

@ -136,6 +136,9 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
- (void)windowDidResize:(NSNotification*)notification { - (void)windowDidResize:(NSNotification*)notification {
[super windowDidResize:notification]; [super windowDidResize:notification];
shell_->NotifyWindowResize(); shell_->NotifyWindowResize();
if (shell_->title_bar_style() == TitleBarStyle::HIDDEN) {
shell_->RepositionTrafficLights();
}
} }
- (void)windowWillMove:(NSNotification*)notification { - (void)windowWillMove:(NSNotification*)notification {
@ -249,11 +252,19 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
shell_->SetStyleMask(false, NSWindowStyleMaskFullSizeContentView); shell_->SetStyleMask(false, NSWindowStyleMaskFullSizeContentView);
[window setTitlebarAppearsTransparent:YES]; [window setTitlebarAppearsTransparent:YES];
} }
shell_->SetExitingFullScreen(true);
if (shell_->title_bar_style() == TitleBarStyle::HIDDEN) {
shell_->RepositionTrafficLights();
}
} }
- (void)windowDidExitFullScreen:(NSNotification*)notification { - (void)windowDidExitFullScreen:(NSNotification*)notification {
shell_->SetResizable(is_resizable_); shell_->SetResizable(is_resizable_);
shell_->NotifyWindowLeaveFullScreen(); shell_->NotifyWindowLeaveFullScreen();
shell_->SetExitingFullScreen(false);
if (shell_->title_bar_style() == TitleBarStyle::HIDDEN) {
shell_->RepositionTrafficLights();
}
} }
- (void)windowWillClose:(NSNotification*)notification { - (void)windowWillClose:(NSNotification*)notification {

View file

@ -28,6 +28,7 @@ const char kMaximizable[] = "maximizable";
const char kFullScreenable[] = "fullscreenable"; const char kFullScreenable[] = "fullscreenable";
const char kClosable[] = "closable"; const char kClosable[] = "closable";
const char kFullscreen[] = "fullscreen"; const char kFullscreen[] = "fullscreen";
const char kTrafficLightPosition[] = "trafficLightPosition";
// Whether the window should show in taskbar. // Whether the window should show in taskbar.
const char kSkipTaskbar[] = "skipTaskbar"; const char kSkipTaskbar[] = "skipTaskbar";

View file

@ -54,6 +54,7 @@ extern const char kOpacity[];
extern const char kFocusable[]; extern const char kFocusable[];
extern const char kWebPreferences[]; extern const char kWebPreferences[];
extern const char kVibrancyType[]; extern const char kVibrancyType[];
extern const char kTrafficLightPosition[];
// WebPreferences. // WebPreferences.
extern const char kZoomFactor[]; extern const char kZoomFactor[];