Merge pull request #8958 from mst128256/8730
Area near the top border in frameless window is clickable
This commit is contained in:
commit
dfa4af2210
5 changed files with 176 additions and 19 deletions
|
@ -127,6 +127,7 @@ class NativeWindowMac : public NativeWindow,
|
|||
NORMAL,
|
||||
HIDDEN,
|
||||
HIDDEN_INSET,
|
||||
CUSTOM_BUTTONS_ON_HOVER,
|
||||
};
|
||||
TitleBarStyle title_bar_style() const { return title_bar_style_; }
|
||||
|
||||
|
|
|
@ -46,6 +46,107 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
|
||||
} // namespace
|
||||
|
||||
// This view encapsuates the Quit, Minimize and Full Screen buttons. It is being
|
||||
// used for frameless windows.
|
||||
@interface SemaphoreView : NSView {
|
||||
@private
|
||||
BOOL mouse_inside_;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation SemaphoreView
|
||||
|
||||
- (id)initWithFrame:(NSRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
|
||||
if (self) {
|
||||
mouse_inside_ = NO;
|
||||
|
||||
// create buttons
|
||||
NSButton* closeButton = [NSWindow standardWindowButton:NSWindowCloseButton
|
||||
forStyleMask:NSTitledWindowMask];
|
||||
NSButton* minitButton = [NSWindow standardWindowButton:NSWindowMiniaturizeButton
|
||||
forStyleMask:NSTitledWindowMask];
|
||||
NSButton* fullScreenButton = [NSWindow standardWindowButton:NSWindowZoomButton
|
||||
forStyleMask:NSTitledWindowMask];
|
||||
|
||||
// size view for buttons
|
||||
const int top = 3;
|
||||
const int bottom = 3;
|
||||
const int left = 7;
|
||||
const int between = 6;
|
||||
const int right = 6;
|
||||
|
||||
auto buttonsSize = NSMakeRect(0,
|
||||
0,
|
||||
left + closeButton.frame.size.width + between + minitButton.frame.size.width + between + fullScreenButton.frame.size.width + right,
|
||||
top + closeButton.frame.size.height + bottom);
|
||||
[self setFrame:buttonsSize];
|
||||
|
||||
//set their location
|
||||
[closeButton setFrame:NSMakeRect(left,
|
||||
buttonsSize.size.height - closeButton.frame.size.height - top,
|
||||
closeButton.frame.size.width,
|
||||
closeButton.frame.size.height)];
|
||||
[minitButton setFrame:NSMakeRect(
|
||||
left + closeButton.frame.size.width + between,
|
||||
buttonsSize.size.height - minitButton.frame.size.height - top,
|
||||
minitButton.frame.size.width,
|
||||
minitButton.frame.size.height)];
|
||||
[fullScreenButton setFrame:NSMakeRect(
|
||||
left + closeButton.frame.size.width + between + minitButton.frame.size.width + between,
|
||||
buttonsSize.size.height - fullScreenButton.frame.size.height - top,
|
||||
fullScreenButton.frame.size.width,
|
||||
fullScreenButton.frame.size.height)];
|
||||
|
||||
//add buttons to the window
|
||||
[self addSubview:closeButton];
|
||||
[self addSubview:minitButton];
|
||||
[self addSubview:fullScreenButton];
|
||||
|
||||
// stay in upper left corner
|
||||
[self setAutoresizingMask: NSViewMaxXMargin | NSViewMinYMargin];
|
||||
|
||||
// refresh for initial conditions
|
||||
[self setNeedsDisplayForButtons];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)_mouseInGroup:(NSButton*)button {
|
||||
return mouse_inside_;
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas {
|
||||
auto trackingArea = [[[NSTrackingArea alloc] initWithRect:NSZeroRect
|
||||
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:nil] autorelease];
|
||||
[self addTrackingArea:trackingArea];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent*)event {
|
||||
[super mouseEntered:event];
|
||||
mouse_inside_ = YES;
|
||||
[self setNeedsDisplayForButtons];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent*)event {
|
||||
[super mouseExited:event];
|
||||
mouse_inside_ = NO;
|
||||
[self setNeedsDisplayForButtons];
|
||||
}
|
||||
|
||||
- (void)setNeedsDisplayForButtons {
|
||||
for (NSView* subview in self.subviews) {
|
||||
[subview setHidden:!mouse_inside_];
|
||||
[subview setNeedsDisplay:YES];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// This view always takes the size of its superview. It is intended to be used
|
||||
// as a NSWindow's contentView. It is needed because NSWindow's implementation
|
||||
// explicitly resizes the contentView at inopportune times.
|
||||
|
@ -299,7 +400,7 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
- (BOOL)windowShouldClose:(id)window {
|
||||
// When user tries to close the window by clicking the close button, we do
|
||||
// not close the window immediately, instead we try to close the web page
|
||||
// fisrt, and when the web page is closed the window will also be closed.
|
||||
// first, and when the web page is closed the window will also be closed.
|
||||
shell_->RequestToClosePage();
|
||||
return NO;
|
||||
}
|
||||
|
@ -596,6 +697,22 @@ enum {
|
|||
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
// Custom window button methods
|
||||
|
||||
- (void)performClose:(id)sender {
|
||||
if (shell_->title_bar_style() == atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER)
|
||||
[[self delegate] windowShouldClose:self];
|
||||
else
|
||||
[super performClose:sender];
|
||||
}
|
||||
|
||||
- (void)performMiniaturize:(id)sender {
|
||||
if (shell_->title_bar_style() == atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER)
|
||||
[self miniaturize:self];
|
||||
else
|
||||
[super performMiniaturize:sender];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface ControlRegionView : NSView
|
||||
|
@ -661,9 +778,11 @@ struct Converter<atom::NativeWindowMac::TitleBarStyle> {
|
|||
return false;
|
||||
if (title_bar_style == "hidden") {
|
||||
*out = atom::NativeWindowMac::HIDDEN;
|
||||
} else if (title_bar_style == "hidden-inset" || // Deprecate this after 2.0
|
||||
} else if (title_bar_style == "hidden-inset" || // TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings
|
||||
title_bar_style == "hiddenInset") {
|
||||
*out = atom::NativeWindowMac::HIDDEN_INSET;
|
||||
} else if (title_bar_style == "customButtonsOnHover") {
|
||||
*out = atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -726,6 +845,11 @@ NativeWindowMac::NativeWindowMac(
|
|||
}
|
||||
|
||||
NSUInteger styleMask = NSTitledWindowMask;
|
||||
if (title_bar_style_ == CUSTOM_BUTTONS_ON_HOVER &&
|
||||
base::mac::IsAtLeastOS10_10() &&
|
||||
(!useStandardWindow || transparent() || !has_frame())) {
|
||||
styleMask = NSFullSizeContentViewWindowMask;
|
||||
}
|
||||
if (minimizable) {
|
||||
styleMask |= NSMiniaturizableWindowMask;
|
||||
}
|
||||
|
@ -780,6 +904,9 @@ NativeWindowMac::NativeWindowMac(
|
|||
if (transparent() || !has_frame()) {
|
||||
if (base::mac::IsAtLeastOS10_10()) {
|
||||
// Don't show title bar.
|
||||
if (title_bar_style_ == CUSTOM_BUTTONS_ON_HOVER) {
|
||||
[window_ setTitlebarAppearsTransparent:YES];
|
||||
}
|
||||
[window_ setTitleVisibility:NSWindowTitleHidden];
|
||||
}
|
||||
// Remove non-transparent corners, see http://git.io/vfonD.
|
||||
|
@ -1563,21 +1690,30 @@ void NativeWindowMac::InstallView() {
|
|||
// The fullscreen button should always be hidden for frameless window.
|
||||
[[window_ standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
|
||||
|
||||
if (title_bar_style_ != NORMAL) {
|
||||
if (base::mac::IsOS10_9()) {
|
||||
ShowWindowButton(NSWindowZoomButton);
|
||||
ShowWindowButton(NSWindowMiniaturizeButton);
|
||||
ShowWindowButton(NSWindowCloseButton);
|
||||
if (title_bar_style_ == CUSTOM_BUTTONS_ON_HOVER) {
|
||||
NSView* buttons =
|
||||
[[[SemaphoreView alloc] initWithFrame:NSZeroRect] autorelease];
|
||||
buttons.frame = CGRectMake(0,
|
||||
[content_view_ bounds].size.height - buttons.frame.size.height,
|
||||
buttons.frame.size.width,
|
||||
buttons.frame.size.height);
|
||||
[content_view_ addSubview:buttons];
|
||||
} else {
|
||||
if (title_bar_style_ != NORMAL) {
|
||||
if (base::mac::IsOS10_9()) {
|
||||
ShowWindowButton(NSWindowZoomButton);
|
||||
ShowWindowButton(NSWindowMiniaturizeButton);
|
||||
ShowWindowButton(NSWindowCloseButton);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
// Hide the window buttons.
|
||||
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
||||
[[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
|
||||
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES];
|
||||
}
|
||||
|
||||
// Hide the window buttons.
|
||||
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
||||
[[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
|
||||
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES];
|
||||
|
||||
// Some third-party macOS utilities check the zoom button's enabled state to
|
||||
// determine whether to show custom UI on hover, so we disable it here to
|
||||
// prevent them from doing so in a frameless app window.
|
||||
|
|
|
@ -191,14 +191,21 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
|||
Default is `false`.
|
||||
* `type` String (optional) - The type of window, default is normal window. See more about
|
||||
this below.
|
||||
* `titleBarStyle` String (optional) - The style of window title bar. Default is `default`. Possible values are:
|
||||
* `titleBarStyle` String (optional) - The style of window title bar.
|
||||
Default is `default`. Possible values are:
|
||||
* `default` - Results in the standard gray opaque Mac title
|
||||
bar.
|
||||
* `hidden` - Results in a hidden title bar and a full size content window, yet
|
||||
the title bar still has the standard window controls ("traffic lights") in
|
||||
the top left.
|
||||
* `hidden-inset` - Results in a hidden title bar with an alternative look
|
||||
* `hidden-inset` - Deprecated, use `hiddenInset` instead.
|
||||
* `hiddenInset` - Results in a hidden title bar with an alternative look
|
||||
where the traffic light buttons are slightly more inset from the window edge.
|
||||
* `customButtonsOnHover` Boolean (optional) - Draw custom close, minimize,
|
||||
and full screen buttons on macOS frameless windows. These buttons will not
|
||||
display 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. **Note:** This option is currently experimental.
|
||||
* `thickFrame` Boolean (optional) - Use `WS_THICKFRAME` style for frameless windows on
|
||||
Windows, which adds standard window frame. Setting it to `false` will remove
|
||||
window shadow and window animations. Default is `true`.
|
||||
|
|
|
@ -26,7 +26,7 @@ a chromeless window. Instead of setting `frame` to `false` which disables
|
|||
both the titlebar and window controls, you may want to have the title bar
|
||||
hidden and your content extend to the full window size, yet still preserve
|
||||
the window controls ("traffic lights") for standard window actions.
|
||||
You can do so by specifying the new `titleBarStyle` option:
|
||||
You can do so by specifying the `titleBarStyle` option:
|
||||
|
||||
#### `hidden`
|
||||
|
||||
|
@ -38,13 +38,26 @@ let win = new BrowserWindow({titleBarStyle: 'hidden'})
|
|||
win.show()
|
||||
```
|
||||
|
||||
#### `hidden-inset`
|
||||
#### `hiddenInset`
|
||||
|
||||
Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge.
|
||||
|
||||
```javascript
|
||||
const {BrowserWindow} = require('electron')
|
||||
let win = new BrowserWindow({titleBarStyle: 'hidden-inset'})
|
||||
let win = new BrowserWindow({titleBarStyle: 'hiddenInset'})
|
||||
win.show()
|
||||
```
|
||||
|
||||
#### `customButtonsOnHover`
|
||||
|
||||
Uses custom drawn close, miniaturize, and fullscreen buttons that display
|
||||
when hovering in the top left of the window. These custom buttons prevent issues
|
||||
with mouse events that occur with the standard window toolbar buttons. This
|
||||
option is only applicable for frameless windows.
|
||||
|
||||
```javascript
|
||||
const {BrowserWindow} = require('electron')
|
||||
let win = new BrowserWindow({titleBarStyle: 'customButtonsOnHover', frame: false})
|
||||
win.show()
|
||||
```
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ let window
|
|||
app.once('ready', () => {
|
||||
window = new BrowserWindow({
|
||||
frame: false,
|
||||
titleBarStyle: 'hidden-inset',
|
||||
titleBarStyle: 'hiddenInset',
|
||||
width: 200,
|
||||
height: 200,
|
||||
backgroundColor: '#000'
|
||||
|
|
Loading…
Reference in a new issue