electron/atom/browser/ui/cocoa/atom_ns_window.mm
Cheng Zhao 5547df6073 report correct content size in AtomNSWindow
The views framework relies on NSWindow to return content size of window,
since we don't use the borderless window, the original result would
include titlebar. We have to override the function to return correct
result for frameless window.
2018-05-04 09:55:09 +09:00

237 lines
7.2 KiB
Text

// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/ui/cocoa/atom_ns_window.h"
#include "atom/browser/native_window_mac.h"
#include "atom/browser/ui/cocoa/atom_preview_item.h"
#include "atom/browser/ui/cocoa/atom_touch_bar.h"
#include "ui/base/cocoa/window_size_constants.h"
namespace atom {
bool ScopedDisableResize::disable_resize_ = false;
} // namespace atom
@implementation AtomNSWindow
@synthesize acceptsFirstMouse;
@synthesize enableLargerThanScreen;
@synthesize disableAutoHideCursor;
@synthesize disableKeyOrMainWindow;
@synthesize windowButtonsOffset;
@synthesize vibrantView;
- (id)initWithShell:(atom::NativeWindowMac*)shell
styleMask:(NSUInteger)styleMask {
if ((self = [super initWithContentRect:ui::kWindowSizeDeterminedLater
styleMask:styleMask
backing:NSBackingStoreBuffered
defer:YES])) {
shell_ = shell;
}
return self;
}
- (atom::NativeWindowMac*)shell {
return shell_;
}
- (NSRect)originalContentRectForFrameRect:(NSRect)frameRect {
return [super contentRectForFrameRect:frameRect];
}
- (NSTouchBar*)makeTouchBar API_AVAILABLE(macosx(10.12.2)) {
if (shell_->touch_bar())
return [shell_->touch_bar() makeTouchBar];
else
return nil;
}
// NSWindow overrides.
- (void)swipeWithEvent:(NSEvent*)event {
if (event.deltaY == 1.0) {
shell_->NotifyWindowSwipe("up");
} else if (event.deltaX == -1.0) {
shell_->NotifyWindowSwipe("right");
} else if (event.deltaY == -1.0) {
shell_->NotifyWindowSwipe("down");
} else if (event.deltaX == 1.0) {
shell_->NotifyWindowSwipe("left");
}
}
- (NSRect)contentRectForFrameRect:(NSRect)frameRect {
if (shell_->has_frame())
return [super contentRectForFrameRect:frameRect];
else
return frameRect;
}
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen {
// Resizing is disabled.
if (atom::ScopedDisableResize::IsResizeDisabled())
return [self frame];
// Enable the window to be larger than screen.
if ([self enableLargerThanScreen])
return frameRect;
else
return [super constrainFrameRect:frameRect toScreen:screen];
}
- (void)setFrame:(NSRect)windowFrame display:(BOOL)displayViews {
// constrainFrameRect is not called on hidden windows so disable adjusting
// the frame directly when resize is disabled
if (!atom::ScopedDisableResize::IsResizeDisabled())
[super setFrame:windowFrame display:displayViews];
}
- (id)accessibilityAttributeValue:(NSString*)attribute {
if (![attribute isEqualToString:@"AXChildren"])
return [super accessibilityAttributeValue:attribute];
// Filter out objects that aren't the title bar buttons. This has the effect
// of removing the window title, which VoiceOver already sees.
// * when VoiceOver is disabled, this causes Cmd+C to be used for TTS but
// still leaves the buttons available in the accessibility tree.
// * when VoiceOver is enabled, the full accessibility tree is used.
// Without removing the title and with VO disabled, the TTS would always read
// the window title instead of using Cmd+C to get the selected text.
NSPredicate* predicate = [NSPredicate
predicateWithFormat:@"(self isKindOfClass: %@) OR (self.className == %@)",
[NSButtonCell class], @"RenderWidgetHostViewCocoa"];
NSArray* children = [super accessibilityAttributeValue:attribute];
return [children filteredArrayUsingPredicate:predicate];
}
- (BOOL)canBecomeMainWindow {
return !self.disableKeyOrMainWindow;
}
- (BOOL)canBecomeKeyWindow {
return !self.disableKeyOrMainWindow;
}
- (void)enableWindowButtonsOffset {
auto closeButton = [self standardWindowButton:NSWindowCloseButton];
auto miniaturizeButton =
[self standardWindowButton:NSWindowMiniaturizeButton];
auto zoomButton = [self standardWindowButton:NSWindowZoomButton];
[closeButton setPostsFrameChangedNotifications:YES];
[miniaturizeButton setPostsFrameChangedNotifications:YES];
[zoomButton setPostsFrameChangedNotifications:YES];
windowButtonsInterButtonSpacing_ =
NSMinX([miniaturizeButton frame]) - NSMaxX([closeButton frame]);
auto center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(adjustCloseButton:)
name:NSViewFrameDidChangeNotification
object:closeButton];
[center addObserver:self
selector:@selector(adjustMiniaturizeButton:)
name:NSViewFrameDidChangeNotification
object:miniaturizeButton];
[center addObserver:self
selector:@selector(adjustZoomButton:)
name:NSViewFrameDidChangeNotification
object:zoomButton];
}
- (void)adjustCloseButton:(NSNotification*)notification {
[self adjustButton:[notification object] ofKind:NSWindowCloseButton];
}
- (void)adjustMiniaturizeButton:(NSNotification*)notification {
[self adjustButton:[notification object] ofKind:NSWindowMiniaturizeButton];
}
- (void)adjustZoomButton:(NSNotification*)notification {
[self adjustButton:[notification object] ofKind:NSWindowZoomButton];
}
- (void)adjustButton:(NSButton*)button ofKind:(NSWindowButton)kind {
NSRect buttonFrame = [button frame];
NSRect frameViewBounds = [[self frameView] bounds];
NSPoint offset = self.windowButtonsOffset;
buttonFrame.origin = NSMakePoint(
offset.x, (NSHeight(frameViewBounds) - NSHeight(buttonFrame) - offset.y));
switch (kind) {
case NSWindowZoomButton:
buttonFrame.origin.x += NSWidth(
[[self standardWindowButton:NSWindowMiniaturizeButton] frame]);
buttonFrame.origin.x += windowButtonsInterButtonSpacing_;
// fallthrough
case NSWindowMiniaturizeButton:
buttonFrame.origin.x +=
NSWidth([[self standardWindowButton:NSWindowCloseButton] frame]);
buttonFrame.origin.x += windowButtonsInterButtonSpacing_;
// fallthrough
default:
break;
}
BOOL didPost = [button postsBoundsChangedNotifications];
[button setPostsFrameChangedNotifications:NO];
[button setFrame:buttonFrame];
[button setPostsFrameChangedNotifications:didPost];
}
- (NSView*)frameView {
return [[self contentView] superview];
}
// Quicklook methods
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel*)panel {
return YES;
}
- (void)beginPreviewPanelControl:(QLPreviewPanel*)panel {
panel.delegate = [self delegate];
panel.dataSource = static_cast<id<QLPreviewPanelDataSource>>([self delegate]);
}
- (void)endPreviewPanelControl:(QLPreviewPanel*)panel {
panel.delegate = nil;
panel.dataSource = 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)toggleFullScreenMode:(id)sender {
if (shell_->simple_fullscreen())
shell_->SetSimpleFullScreen(!shell_->IsSimpleFullScreen());
else
[super toggleFullScreen:sender];
}
- (void)performMiniaturize:(id)sender {
if (shell_->title_bar_style() ==
atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER)
[self miniaturize:self];
else
[super performMiniaturize:sender];
}
@end