feat: make trafficLightPosition work for customButtonOnHover (#26789)
This commit is contained in:
parent
1e2a2004e9
commit
e01b1831d9
6 changed files with 76 additions and 45 deletions
|
@ -227,7 +227,9 @@ 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`
|
* `trafficLightPosition` [Point](structures/point.md) (optional) - Set a
|
||||||
|
custom position for the traffic light buttons. Can only be used with
|
||||||
|
`titleBarStyle` set to `hidden` or `customButtonsOnHover`.
|
||||||
* `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`.
|
||||||
|
@ -1737,12 +1739,13 @@ deprecated and will be removed in an upcoming version of macOS.
|
||||||
|
|
||||||
* `position` [Point](structures/point.md)
|
* `position` [Point](structures/point.md)
|
||||||
|
|
||||||
Set a custom position for the traffic light buttons. Can only be used with `titleBarStyle` set to `hidden`.
|
Set a custom position for the traffic light buttons. Can only be used with
|
||||||
|
`titleBarStyle` set to `hidden` or `customButtonsOnHover`.
|
||||||
|
|
||||||
#### `win.getTrafficLightPosition()` _macOS_
|
#### `win.getTrafficLightPosition()` _macOS_
|
||||||
|
|
||||||
Returns `Point` - The current position for the traffic light buttons. Can only be used with `titleBarStyle`
|
Returns `Point` - The current position for the traffic light buttons. Can only
|
||||||
set to `hidden`.
|
be used with `titleBarStyle` set to `hidden` or `customButtonsOnHover`.
|
||||||
|
|
||||||
#### `win.setTouchBar(touchBar)` _macOS_
|
#### `win.setTouchBar(touchBar)` _macOS_
|
||||||
|
|
||||||
|
|
|
@ -842,11 +842,16 @@ void BaseWindow::SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value) {
|
||||||
|
|
||||||
#if defined(OS_MAC)
|
#if defined(OS_MAC)
|
||||||
void BaseWindow::SetTrafficLightPosition(const gfx::Point& position) {
|
void BaseWindow::SetTrafficLightPosition(const gfx::Point& position) {
|
||||||
window_->SetTrafficLightPosition(position);
|
// For backward compatibility we treat (0, 0) as reseting to default.
|
||||||
|
if (position.IsOrigin())
|
||||||
|
window_->SetTrafficLightPosition(base::nullopt);
|
||||||
|
else
|
||||||
|
window_->SetTrafficLightPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Point BaseWindow::GetTrafficLightPosition() const {
|
gfx::Point BaseWindow::GetTrafficLightPosition() const {
|
||||||
return window_->GetTrafficLightPosition();
|
// For backward compatibility we treat default value as (0, 0).
|
||||||
|
return window_->GetTrafficLightPosition().value_or(gfx::Point());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "base/memory/weak_ptr.h"
|
#include "base/memory/weak_ptr.h"
|
||||||
#include "base/observer_list.h"
|
#include "base/observer_list.h"
|
||||||
|
#include "base/optional.h"
|
||||||
#include "base/strings/string16.h"
|
#include "base/strings/string16.h"
|
||||||
#include "base/supports_user_data.h"
|
#include "base/supports_user_data.h"
|
||||||
#include "base/values.h"
|
#include "base/values.h"
|
||||||
|
@ -198,8 +199,8 @@ class NativeWindow : public base::SupportsUserData,
|
||||||
|
|
||||||
// Traffic Light API
|
// Traffic Light API
|
||||||
#if defined(OS_MAC)
|
#if defined(OS_MAC)
|
||||||
virtual void SetTrafficLightPosition(const gfx::Point& position) = 0;
|
virtual void SetTrafficLightPosition(base::Optional<gfx::Point> position) = 0;
|
||||||
virtual gfx::Point GetTrafficLightPosition() const = 0;
|
virtual base::Optional<gfx::Point> GetTrafficLightPosition() const = 0;
|
||||||
virtual void RedrawTrafficLights() = 0;
|
virtual void RedrawTrafficLights() = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -159,8 +159,8 @@ class NativeWindowMac : public NativeWindow, public ui::NativeThemeObserver {
|
||||||
// Custom traffic light positioning
|
// Custom traffic light positioning
|
||||||
void RedrawTrafficLights() override;
|
void RedrawTrafficLights() override;
|
||||||
void SetExitingFullScreen(bool flag);
|
void SetExitingFullScreen(bool flag);
|
||||||
void SetTrafficLightPosition(const gfx::Point& position) override;
|
void SetTrafficLightPosition(base::Optional<gfx::Point> position) override;
|
||||||
gfx::Point GetTrafficLightPosition() const override;
|
base::Optional<gfx::Point> GetTrafficLightPosition() const override;
|
||||||
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;
|
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;
|
||||||
|
|
||||||
enum class VisualEffectState {
|
enum class VisualEffectState {
|
||||||
|
@ -220,7 +220,7 @@ class NativeWindowMac : public NativeWindow, public ui::NativeThemeObserver {
|
||||||
bool fullscreen_window_title_ = false;
|
bool fullscreen_window_title_ = false;
|
||||||
bool resizable_ = true;
|
bool resizable_ = true;
|
||||||
bool exiting_fullscreen_ = false;
|
bool exiting_fullscreen_ = false;
|
||||||
gfx::Point traffic_light_position_;
|
base::Optional<gfx::Point> traffic_light_position_;
|
||||||
|
|
||||||
NSInteger attention_request_id_ = 0; // identifier from requestUserAttention
|
NSInteger attention_request_id_ = 0; // identifier from requestUserAttention
|
||||||
|
|
||||||
|
|
|
@ -124,13 +124,18 @@
|
||||||
@interface CustomWindowButtonView : NSView {
|
@interface CustomWindowButtonView : NSView {
|
||||||
@private
|
@private
|
||||||
BOOL mouse_inside_;
|
BOOL mouse_inside_;
|
||||||
|
gfx::Point margin_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id)initWithMargin:(const base::Optional<gfx::Point>&)margin;
|
||||||
|
- (void)setMargin:(const base::Optional<gfx::Point>&)margin;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation CustomWindowButtonView
|
@implementation CustomWindowButtonView
|
||||||
|
|
||||||
- (id)initWithFrame:(NSRect)frame {
|
- (id)initWithMargin:(const base::Optional<gfx::Point>&)margin {
|
||||||
self = [super initWithFrame:frame];
|
self = [super initWithFrame:NSZeroRect];
|
||||||
|
[self setMargin:margin];
|
||||||
|
|
||||||
NSButton* close_button =
|
NSButton* close_button =
|
||||||
[NSWindow standardWindowButton:NSWindowCloseButton
|
[NSWindow standardWindowButton:NSWindowCloseButton
|
||||||
|
@ -163,18 +168,20 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setMargin:(const base::Optional<gfx::Point>&)margin {
|
||||||
|
margin_ = margin.value_or(gfx::Point(7, 3));
|
||||||
|
}
|
||||||
|
|
||||||
- (void)viewDidMoveToWindow {
|
- (void)viewDidMoveToWindow {
|
||||||
if (!self.window) {
|
if (!self.window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stay in upper left corner.
|
// Stay in upper left corner.
|
||||||
const CGFloat top_margin = 3;
|
|
||||||
const CGFloat left_margin = 7;
|
|
||||||
[self setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
|
[self setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
|
||||||
[self setFrameOrigin:NSMakePoint(left_margin, self.window.frame.size.height -
|
[self setFrameOrigin:NSMakePoint(margin_.x(), self.window.frame.size.height -
|
||||||
self.frame.size.height -
|
self.frame.size.height -
|
||||||
top_margin)];
|
margin_.y())];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)_mouseInGroup:(NSButton*)button {
|
- (BOOL)_mouseInGroup:(NSButton*)button {
|
||||||
|
@ -365,7 +372,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_);
|
options.GetOptional(options::kTrafficLightPosition, &traffic_light_position_);
|
||||||
options.Get(options::kVisualEffectState, &visual_effect_state_);
|
options.Get(options::kVisualEffectState, &visual_effect_state_);
|
||||||
|
|
||||||
bool minimizable = true;
|
bool minimizable = true;
|
||||||
|
@ -543,9 +550,10 @@ void NativeWindowMac::RedrawTrafficLights() {
|
||||||
// Ensure maximizable options retain pre-existing state.
|
// Ensure maximizable options retain pre-existing state.
|
||||||
SetMaximizable(maximizable_);
|
SetMaximizable(maximizable_);
|
||||||
|
|
||||||
if (!traffic_light_position_.x() && !traffic_light_position_.y()) {
|
// Changing system titlebar is only allowed for "hidden" titleBarStyle.
|
||||||
|
if (!traffic_light_position_ || title_bar_style_ != TitleBarStyle::kHidden)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if (IsFullscreen())
|
if (IsFullscreen())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -571,7 +579,7 @@ void NativeWindowMac::RedrawTrafficLights() {
|
||||||
|
|
||||||
[titleBarContainerView setHidden:NO];
|
[titleBarContainerView setHidden:NO];
|
||||||
CGFloat buttonHeight = [close frame].size.height;
|
CGFloat buttonHeight = [close frame].size.height;
|
||||||
CGFloat titleBarFrameHeight = buttonHeight + traffic_light_position_.y();
|
CGFloat titleBarFrameHeight = buttonHeight + traffic_light_position_->y();
|
||||||
CGRect titleBarRect = titleBarContainerView.frame;
|
CGRect titleBarRect = titleBarContainerView.frame;
|
||||||
CGFloat titleBarWidth = NSWidth(titleBarRect);
|
CGFloat titleBarWidth = NSWidth(titleBarRect);
|
||||||
titleBarRect.size.height = titleBarFrameHeight;
|
titleBarRect.size.height = titleBarFrameHeight;
|
||||||
|
@ -589,10 +597,10 @@ void NativeWindowMac::RedrawTrafficLights() {
|
||||||
if (isRTL) {
|
if (isRTL) {
|
||||||
CGFloat buttonWidth = NSWidth(rect);
|
CGFloat buttonWidth = NSWidth(rect);
|
||||||
// origin is always top-left, even in RTL
|
// origin is always top-left, even in RTL
|
||||||
rect.origin.x = titleBarWidth - traffic_light_position_.x() +
|
rect.origin.x = titleBarWidth - traffic_light_position_->x() +
|
||||||
(i * space_between) - buttonWidth;
|
(i * space_between) - buttonWidth;
|
||||||
} else {
|
} else {
|
||||||
rect.origin.x = traffic_light_position_.x() + (i * space_between);
|
rect.origin.x = traffic_light_position_->x() + (i * space_between);
|
||||||
}
|
}
|
||||||
rect.origin.y = (titleBarFrameHeight - rect.size.height) / 2;
|
rect.origin.y = (titleBarFrameHeight - rect.size.height) / 2;
|
||||||
[view setFrameOrigin:rect.origin];
|
[view setFrameOrigin:rect.origin];
|
||||||
|
@ -1588,12 +1596,18 @@ void NativeWindowMac::SetVibrancy(const std::string& type) {
|
||||||
[effect_view setMaterial:vibrancyType];
|
[effect_view setMaterial:vibrancyType];
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowMac::SetTrafficLightPosition(const gfx::Point& position) {
|
void NativeWindowMac::SetTrafficLightPosition(
|
||||||
traffic_light_position_ = position;
|
base::Optional<gfx::Point> position) {
|
||||||
RedrawTrafficLights();
|
traffic_light_position_ = std::move(position);
|
||||||
|
if (title_bar_style_ == TitleBarStyle::kHidden) {
|
||||||
|
RedrawTrafficLights();
|
||||||
|
} else if (title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover) {
|
||||||
|
[buttons_view_ setMargin:position];
|
||||||
|
[buttons_view_ viewDidMoveToWindow];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Point NativeWindowMac::GetTrafficLightPosition() const {
|
base::Optional<gfx::Point> NativeWindowMac::GetTrafficLightPosition() const {
|
||||||
return traffic_light_position_;
|
return traffic_light_position_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1695,8 +1709,8 @@ void NativeWindowMac::AddContentViewLayers(bool minimizable, bool closable) {
|
||||||
|
|
||||||
// Create a custom window buttons view for kCustomButtonsOnHover.
|
// Create a custom window buttons view for kCustomButtonsOnHover.
|
||||||
if (title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover) {
|
if (title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover) {
|
||||||
buttons_view_.reset(
|
buttons_view_.reset([[CustomWindowButtonView alloc]
|
||||||
[[CustomWindowButtonView alloc] initWithFrame:NSZeroRect]);
|
initWithMargin:traffic_light_position_]);
|
||||||
|
|
||||||
if (!minimizable)
|
if (!minimizable)
|
||||||
[[buttons_view_ viewWithTag:2] removeFromSuperview];
|
[[buttons_view_ viewWithTag:2] removeFromSuperview];
|
||||||
|
|
|
@ -1536,28 +1536,36 @@ describe('BrowserWindow module', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ifdescribe(process.platform === 'darwin')('BrowserWindow.getTrafficLightPosition(pos)', () => {
|
ifdescribe(process.platform === 'darwin')('trafficLightPosition', () => {
|
||||||
|
const pos = { x: 10, y: 10 };
|
||||||
afterEach(closeAllWindows);
|
afterEach(closeAllWindows);
|
||||||
|
|
||||||
it('gets the set traffic light position property', () => {
|
describe('BrowserWindow.getTrafficLightPosition(pos)', () => {
|
||||||
const pos = { x: 10, y: 10 };
|
it('gets position property for "hidden" titleBarStyle', () => {
|
||||||
const w = new BrowserWindow({ show: false, titleBarStyle: 'hidden', trafficLightPosition: pos });
|
const w = new BrowserWindow({ show: false, titleBarStyle: 'hidden', trafficLightPosition: pos });
|
||||||
const currentPosition = w.getTrafficLightPosition();
|
expect(w.getTrafficLightPosition()).to.deep.equal(pos);
|
||||||
|
});
|
||||||
|
|
||||||
expect(currentPosition).to.deep.equal(pos);
|
it('gets position property for "customButtonsOnHover" titleBarStyle', () => {
|
||||||
|
const w = new BrowserWindow({ show: false, titleBarStyle: 'customButtonsOnHover', trafficLightPosition: pos });
|
||||||
|
expect(w.getTrafficLightPosition()).to.deep.equal(pos);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
ifdescribe(process.platform === 'darwin')('BrowserWindow.setTrafficLightPosition(pos)', () => {
|
describe('BrowserWindow.setTrafficLightPosition(pos)', () => {
|
||||||
afterEach(closeAllWindows);
|
it('sets position property for "hidden" titleBarStyle', () => {
|
||||||
|
const w = new BrowserWindow({ show: false, titleBarStyle: 'hidden', trafficLightPosition: pos });
|
||||||
|
const newPos = { x: 20, y: 20 };
|
||||||
|
w.setTrafficLightPosition(newPos);
|
||||||
|
expect(w.getTrafficLightPosition()).to.deep.equal(newPos);
|
||||||
|
});
|
||||||
|
|
||||||
it('can set the traffic light position property', () => {
|
it('sets position property for "customButtonsOnHover" titleBarStyle', () => {
|
||||||
const pos = { x: 10, y: 10 };
|
const w = new BrowserWindow({ show: false, titleBarStyle: 'customButtonsOnHover', trafficLightPosition: pos });
|
||||||
const w = new BrowserWindow({ show: false, titleBarStyle: 'hidden', trafficLightPosition: pos });
|
const newPos = { x: 20, y: 20 };
|
||||||
w.setTrafficLightPosition(pos);
|
w.setTrafficLightPosition(newPos);
|
||||||
const currentPosition = w.getTrafficLightPosition();
|
expect(w.getTrafficLightPosition()).to.deep.equal(newPos);
|
||||||
|
});
|
||||||
expect(currentPosition).to.deep.equal(pos);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue