From 37a7df49d6d42db0c572021bea9a763aac31a598 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Apr 2018 15:26:34 +0900 Subject: [PATCH 1/9] mac: Provide ViewsDelegate --- atom/browser/atom_browser_main_parts.cc | 15 +++++++++- atom/browser/atom_browser_main_parts.h | 9 ++++++ atom/browser/native_window_mac.h | 4 +++ atom/browser/native_window_mac.mm | 1 + atom/browser/ui/cocoa/views_delegate_mac.h | 30 +++++++++++++++++++ atom/browser/ui/cocoa/views_delegate_mac.mm | 33 +++++++++++++++++++++ filenames.gypi | 2 ++ 7 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 atom/browser/ui/cocoa/views_delegate_mac.h create mode 100644 atom/browser/ui/cocoa/views_delegate_mac.mm diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 0afb4348bc22..24c4c7b31c27 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -16,7 +16,6 @@ #include "atom/common/api/atom_bindings.h" #include "atom/common/asar/asar_util.h" #include "atom/common/node_bindings.h" -#include "atom/common/node_includes.h" #include "base/command_line.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/browser_process.h" @@ -36,6 +35,13 @@ #include "atom/browser/atom_web_ui_controller_factory.h" #endif // defined(ENABLE_PDF_VIEWER) +#if defined(OS_MACOSX) +#include "atom/browser/ui/cocoa/views_delegate_mac.h" +#endif + +// Must be included after all other headers. +#include "atom/common/node_includes.h" + namespace atom { namespace { @@ -171,6 +177,13 @@ int AtomBrowserMainParts::PreCreateThreads() { return result; } +void AtomBrowserMainParts::ToolkitInitialized() { + brightray::BrowserMainParts::ToolkitInitialized(); +#if defined(OS_MACOSX) + views_delegate_.reset(new ViewsDelegateMac); +#endif +} + void AtomBrowserMainParts::PreMainMessageLoopRun() { js_env_->OnMessageLoopCreated(); diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index 58f9821c020d..ff81a7c3b5cd 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -25,6 +25,10 @@ class NodeDebugger; class NodeEnvironment; class BridgeTaskRunner; +#if defined(OS_MACOSX) +class ViewsDelegateMac; +#endif + class AtomBrowserMainParts : public brightray::BrowserMainParts { public: AtomBrowserMainParts(); @@ -50,6 +54,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { void PreEarlyInitialization() override; void PostEarlyInitialization() override; int PreCreateThreads() override; + void ToolkitInitialized() override; void PreMainMessageLoopRun() override; bool MainMessageLoopRun(int* result_code) override; void PostMainMessageLoopStart() override; @@ -69,6 +74,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { void FreeAppDelegate(); #endif +#if defined(OS_MACOSX) + std::unique_ptr views_delegate_; +#endif + // A fake BrowserProcess object that used to feed the source code from chrome. std::unique_ptr fake_browser_process_; diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 62ddc9784441..b74f1b623827 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -12,6 +12,8 @@ #include "atom/browser/native_window.h" #include "base/mac/scoped_nsobject.h" +#include "ui/views/widget/widget_delegate.h" +#include "ui/views/widget/widget_observer.h" @class AtomNSWindow; @class AtomNSWindowDelegate; @@ -147,6 +149,8 @@ class NativeWindowMac : public NativeWindow { base::scoped_nsobject window_; base::scoped_nsobject window_delegate_; + std::unique_ptr widget_; + // Event monitor for scroll wheel event. id wheel_event_monitor_; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 046a349eecf8..95f0a2d96fa7 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -24,6 +24,7 @@ #include "skia/ext/skia_utils_mac.h" #include "ui/gfx/skia_util.h" #include "ui/gl/gpu_switching_manager.h" +#include "ui/views/widget/widget.h" namespace { diff --git a/atom/browser/ui/cocoa/views_delegate_mac.h b/atom/browser/ui/cocoa/views_delegate_mac.h new file mode 100644 index 000000000000..455fb6171e38 --- /dev/null +++ b/atom/browser/ui/cocoa/views_delegate_mac.h @@ -0,0 +1,30 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_COCOA_VIEWS_DELEGATE_MAC_H_ +#define ATOM_BROWSER_UI_COCOA_VIEWS_DELEGATE_MAC_H_ + +#include "ui/views/views_delegate.h" + +namespace atom { + +class ViewsDelegateMac : public views::ViewsDelegate { + public: + ViewsDelegateMac(); + ~ViewsDelegateMac() override; + + // ViewsDelegate: + void OnBeforeWidgetInit( + views::Widget::InitParams* params, + views::internal::NativeWidgetDelegate* delegate) override; + ui::ContextFactory* GetContextFactory() override; + ui::ContextFactoryPrivate* GetContextFactoryPrivate() override; + + private: + DISALLOW_COPY_AND_ASSIGN(ViewsDelegateMac); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_UI_COCOA_VIEWS_DELEGATE_MAC_H_ diff --git a/atom/browser/ui/cocoa/views_delegate_mac.mm b/atom/browser/ui/cocoa/views_delegate_mac.mm new file mode 100644 index 000000000000..0d26b7d19d35 --- /dev/null +++ b/atom/browser/ui/cocoa/views_delegate_mac.mm @@ -0,0 +1,33 @@ +// 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/views_delegate_mac.h" + +#include "content/public/browser/context_factory.h" +#include "ui/views/widget/native_widget_mac.h" + +namespace atom { + +ViewsDelegateMac::ViewsDelegateMac() { +} + +ViewsDelegateMac::~ViewsDelegateMac() { +} + +void ViewsDelegateMac::OnBeforeWidgetInit( + views::Widget::InitParams* params, + views::internal::NativeWidgetDelegate* delegate) { + if (!params->native_widget) + params->native_widget = new views::NativeWidgetMac(delegate); +} + +ui::ContextFactory* ViewsDelegateMac::GetContextFactory() { + return content::GetContextFactory(); +} + +ui::ContextFactoryPrivate* ViewsDelegateMac::GetContextFactoryPrivate() { + return content::GetContextFactoryPrivate(); +} + +} // namespace atom diff --git a/filenames.gypi b/filenames.gypi index 3e0cb381fb6e..d607717e2780 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -318,6 +318,8 @@ 'atom/browser/ui/cocoa/atom_menu_controller.mm', 'atom/browser/ui/cocoa/atom_touch_bar.h', 'atom/browser/ui/cocoa/atom_touch_bar.mm', + 'atom/browser/ui/cocoa/views_delegate_mac.h', + 'atom/browser/ui/cocoa/views_delegate_mac.mm', 'atom/browser/ui/cocoa/touch_bar_forward_declarations.h', 'atom/browser/ui/drag_util_mac.mm', 'atom/browser/ui/drag_util_views.cc', From 9bc79f840e0d960b3fa487531da1793f74310ef4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Apr 2018 15:36:14 +0900 Subject: [PATCH 2/9] mac: Override NativeWidgetMac --- .../browser/ui/cocoa/atom_native_widget_mac.h | 28 +++++++++++++++++++ .../ui/cocoa/atom_native_widget_mac.mm | 22 +++++++++++++++ filenames.gypi | 2 ++ 3 files changed, 52 insertions(+) create mode 100644 atom/browser/ui/cocoa/atom_native_widget_mac.h create mode 100644 atom/browser/ui/cocoa/atom_native_widget_mac.mm diff --git a/atom/browser/ui/cocoa/atom_native_widget_mac.h b/atom/browser/ui/cocoa/atom_native_widget_mac.h new file mode 100644 index 000000000000..a078fcb1ee02 --- /dev/null +++ b/atom/browser/ui/cocoa/atom_native_widget_mac.h @@ -0,0 +1,28 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_COCOA_ATOM_NATIVE_WIDGET_MAC_H_ +#define ATOM_BROWSER_UI_COCOA_ATOM_NATIVE_WIDGET_MAC_H_ + +#include "ui/views/widget/native_widget_mac.h" + +namespace atom { + +class AtomNativeWidgetMac : public views::NativeWidgetMac { + public: + explicit AtomNativeWidgetMac(views::internal::NativeWidgetDelegate* delegate); + ~AtomNativeWidgetMac() override; + + protected: + // NativeWidgetMac: + views::NativeWidgetMacNSWindow* CreateNSWindow( + const views::Widget::InitParams& params) override; + + private: + DISALLOW_COPY_AND_ASSIGN(AtomNativeWidgetMac); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_UI_COCOA_ATOM_NATIVE_WIDGET_MAC_H_ diff --git a/atom/browser/ui/cocoa/atom_native_widget_mac.mm b/atom/browser/ui/cocoa/atom_native_widget_mac.mm new file mode 100644 index 000000000000..01f2fa392674 --- /dev/null +++ b/atom/browser/ui/cocoa/atom_native_widget_mac.mm @@ -0,0 +1,22 @@ +// 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_native_widget_mac.h" + +namespace atom { + +AtomNativeWidgetMac::AtomNativeWidgetMac( + views::internal::NativeWidgetDelegate* delegate) + : views::NativeWidgetMac(delegate) { +} + +AtomNativeWidgetMac::~AtomNativeWidgetMac() { +} + +views::NativeWidgetMacNSWindow* AtomNativeWidgetMac::CreateNSWindow( + const views::Widget::InitParams& params) { + return views::NativeWidgetMac::CreateNSWindow(params); +} + +} // namespace atom diff --git a/filenames.gypi b/filenames.gypi index d607717e2780..a76b5d08d1d6 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -316,6 +316,8 @@ 'atom/browser/ui/cocoa/atom_bundle_mover.mm', 'atom/browser/ui/cocoa/atom_menu_controller.h', 'atom/browser/ui/cocoa/atom_menu_controller.mm', + 'atom/browser/ui/cocoa/atom_native_widget_mac.h', + 'atom/browser/ui/cocoa/atom_native_widget_mac.mm', 'atom/browser/ui/cocoa/atom_touch_bar.h', 'atom/browser/ui/cocoa/atom_touch_bar.mm', 'atom/browser/ui/cocoa/views_delegate_mac.h', From 1c6c75da4f01ccde0d5e4d264daa0c17f68ab924 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Apr 2018 15:38:33 +0900 Subject: [PATCH 3/9] Merge the logic of managing ViewsDelegate --- atom/browser/atom_browser_main_parts.cc | 4 ++++ atom/browser/atom_browser_main_parts.h | 8 ++++++++ brightray/browser/browser_main_parts.cc | 8 -------- brightray/browser/browser_main_parts.h | 10 ---------- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 24c4c7b31c27..8cccac09931f 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -37,6 +37,8 @@ #if defined(OS_MACOSX) #include "atom/browser/ui/cocoa/views_delegate_mac.h" +#else +#include "brightray/browser/views/views_delegate.h" #endif // Must be included after all other headers. @@ -181,6 +183,8 @@ void AtomBrowserMainParts::ToolkitInitialized() { brightray::BrowserMainParts::ToolkitInitialized(); #if defined(OS_MACOSX) views_delegate_.reset(new ViewsDelegateMac); +#else + views_delegate_.reset(new brightray::ViewsDelegate); #endif } diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index ff81a7c3b5cd..129ad2d86876 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -15,6 +15,12 @@ class BrowserProcess; +#if defined(TOOLKIT_VIEWS) +namespace brightray { +class ViewsDelegate; +} +#endif + namespace atom { class AtomBindings; @@ -76,6 +82,8 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { #if defined(OS_MACOSX) std::unique_ptr views_delegate_; +#else + std::unique_ptr views_delegate_; #endif // A fake BrowserProcess object that used to feed the source code from chrome. diff --git a/brightray/browser/browser_main_parts.cc b/brightray/browser/browser_main_parts.cc index 4006d96c9f04..4705abc98666 100644 --- a/brightray/browser/browser_main_parts.cc +++ b/brightray/browser/browser_main_parts.cc @@ -43,10 +43,6 @@ #include "ui/wm/core/wm_state.h" #endif -#if defined(TOOLKIT_VIEWS) -#include "brightray/browser/views/views_delegate.h" -#endif - #if defined(USE_X11) #include "base/environment.h" #include "base/nix/xdg_util.h" @@ -209,10 +205,6 @@ void BrowserMainParts::ToolkitInitialized() { wm_state_.reset(new wm::WMState); #endif -#if defined(TOOLKIT_VIEWS) - views_delegate_.reset(new ViewsDelegate); -#endif - #if defined(OS_WIN) gfx::PlatformFontWin::adjust_font_callback = &AdjustUIFont; gfx::PlatformFontWin::get_minimum_font_size_callback = &GetMinimumFontSize; diff --git a/brightray/browser/browser_main_parts.h b/brightray/browser/browser_main_parts.h index 2a31027431b9..217333985364 100644 --- a/brightray/browser/browser_main_parts.h +++ b/brightray/browser/browser_main_parts.h @@ -16,12 +16,6 @@ #include "content/public/browser/browser_main_parts.h" #include "ui/views/layout/layout_provider.h" -#if defined(TOOLKIT_VIEWS) -namespace brightray { -class ViewsDelegate; -} -#endif - #if defined(USE_AURA) namespace wm { class WMState; @@ -56,10 +50,6 @@ class BrowserMainParts : public content::BrowserMainParts { std::unique_ptr io_thread_; -#if defined(TOOLKIT_VIEWS) - std::unique_ptr views_delegate_; -#endif - #if defined(USE_AURA) std::unique_ptr wm_state_; #endif From ce54fd334d7d05ac786065df5b1c3d5b41fa3d5e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Apr 2018 16:01:19 +0900 Subject: [PATCH 4/9] Move AtomNSWindowDelegate to a new file --- atom/browser/native_window_mac.mm | 252 +----------------- .../browser/ui/cocoa/atom_native_widget_mac.h | 2 +- .../ui/cocoa/atom_native_widget_mac.mm | 2 +- .../ui/cocoa/atom_ns_window_delegate.h | 24 ++ .../ui/cocoa/atom_ns_window_delegate.mm | 249 +++++++++++++++++ filenames.gypi | 2 + script/cpplint.py | 1 + 7 files changed, 279 insertions(+), 253 deletions(-) create mode 100644 atom/browser/ui/cocoa/atom_ns_window_delegate.h create mode 100644 atom/browser/ui/cocoa/atom_ns_window_delegate.mm diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 95f0a2d96fa7..c1f826a8273a 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -8,8 +8,8 @@ #include #include -#include "atom/browser/browser.h" #include "atom/browser/native_browser_view_mac.h" +#include "atom/browser/ui/cocoa/atom_ns_window_delegate.h" #include "atom/browser/ui/cocoa/atom_touch_bar.h" #include "atom/browser/window_list.h" #include "atom/common/options_switches.h" @@ -165,256 +165,6 @@ bool ScopedDisableResize::disable_resize_ = false; @end -@interface AtomNSWindowDelegate : NSObject { - @private - atom::NativeWindowMac* shell_; - bool is_zooming_; - int level_; - bool is_resizable_; -} -- (id)initWithShell:(atom::NativeWindowMac*)shell; -@end - -@implementation AtomNSWindowDelegate - -- (id)initWithShell:(atom::NativeWindowMac*)shell { - if ((self = [super init])) { - shell_ = shell; - is_zooming_ = false; - level_ = [shell_->GetNativeWindow() level]; - } - return self; -} - -- (void)windowDidChangeOcclusionState:(NSNotification *)notification { - // notification.object is the window that changed its state. - // It's safe to use self.window instead if you don't assign one delegate to many windows - NSWindow *window = notification.object; - - // check occlusion binary flag - if (window.occlusionState & NSWindowOcclusionStateVisible) { - // The app is visible - shell_->NotifyWindowShow(); - } else { - // The app is not visible - shell_->NotifyWindowHide(); - } -} - -// Called when the user clicks the zoom button or selects it from the Window -// menu to determine the "standard size" of the window. -- (NSRect)windowWillUseStandardFrame:(NSWindow*)window - defaultFrame:(NSRect)frame { - if (!shell_->zoom_to_page_width()) - return frame; - - // If the shift key is down, maximize. - if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) - return frame; - - // Get preferred width from observers. Usually the page width. - int preferred_width = 0; - shell_->NotifyWindowRequestPreferredWith(&preferred_width); - - // Never shrink from the current size on zoom. - NSRect window_frame = [window frame]; - CGFloat zoomed_width = std::max(static_cast(preferred_width), - NSWidth(window_frame)); - - // |frame| determines our maximum extents. We need to set the origin of the - // frame -- and only move it left if necessary. - if (window_frame.origin.x + zoomed_width > NSMaxX(frame)) - frame.origin.x = NSMaxX(frame) - zoomed_width; - else - frame.origin.x = window_frame.origin.x; - - // Set the width. Don't touch y or height. - frame.size.width = zoomed_width; - - return frame; -} - -- (void)windowDidBecomeMain:(NSNotification*)notification { - shell_->NotifyWindowFocus(); -} - -- (void)windowDidResignMain:(NSNotification*)notification { - shell_->NotifyWindowBlur(); -} - -- (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize { - NSSize newSize = frameSize; - double aspectRatio = shell_->GetAspectRatio(); - - if (aspectRatio > 0.0) { - gfx::Size windowSize = shell_->GetSize(); - gfx::Size contentSize = shell_->GetContentSize(); - gfx::Size extraSize = shell_->GetAspectRatioExtraSize(); - - double extraWidthPlusFrame = - windowSize.width() - contentSize.width() + extraSize.width(); - double extraHeightPlusFrame = - windowSize.height() - contentSize.height() + extraSize.height(); - - newSize.width = - roundf((frameSize.height - extraHeightPlusFrame) * aspectRatio + - extraWidthPlusFrame); - newSize.height = - roundf((newSize.width - extraWidthPlusFrame) / aspectRatio + - extraHeightPlusFrame); - } - - return newSize; -} - -- (void)windowDidResize:(NSNotification*)notification { - shell_->NotifyWindowResize(); -} - -- (void)windowDidMove:(NSNotification*)notification { - // TODO(zcbenz): Remove the alias after figuring out a proper - // way to dispatch move. - shell_->NotifyWindowMove(); - shell_->NotifyWindowMoved(); -} - -- (void)windowWillMiniaturize:(NSNotification*)notification { - NSWindow* window = shell_->GetNativeWindow(); - // store the current status window level to be restored in windowDidDeminiaturize - level_ = [window level]; - [window setLevel:NSNormalWindowLevel]; -} - -- (void)windowDidMiniaturize:(NSNotification*)notification { - shell_->NotifyWindowMinimize(); -} - -- (void)windowDidDeminiaturize:(NSNotification*)notification { - [shell_->GetNativeWindow() setLevel:level_]; - shell_->NotifyWindowRestore(); -} - -- (BOOL)windowShouldZoom:(NSWindow*)window toFrame:(NSRect)newFrame { - is_zooming_ = true; - return YES; -} - -- (void)windowDidEndLiveResize:(NSNotification*)notification { - if (is_zooming_) { - if (shell_->IsMaximized()) - shell_->NotifyWindowMaximize(); - else - shell_->NotifyWindowUnmaximize(); - is_zooming_ = false; - } -} - -- (void)windowWillEnterFullScreen:(NSNotification*)notification { - // Setting resizable to true before entering fullscreen - is_resizable_ = shell_->IsResizable(); - shell_->SetResizable(true); - // Hide the native toolbar before entering fullscreen, so there is no visual - // artifacts. - if (@available(macOS 10.10, *)) { - if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { - NSWindow* window = shell_->GetNativeWindow(); - [window setToolbar:nil]; - } - } -} - -- (void)windowDidEnterFullScreen:(NSNotification*)notification { - shell_->NotifyWindowEnterFullScreen(); - - if (@available(macOS 10.10, *)) { - // For frameless window we don't show set title for normal mode since the - // titlebar is expected to be empty, but after entering fullscreen mode we - // have to set one, because title bar is visible here. - NSWindow* window = shell_->GetNativeWindow(); - if ((shell_->transparent() || !shell_->has_frame()) && - // FIXME(zcbenz): Showing titlebar for hiddenInset window is weird under - // fullscreen mode. - // Show title if fullscreen_window_title flag is set - (shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET || - shell_->fullscreen_window_title())) { - [window setTitleVisibility:NSWindowTitleVisible]; - } - - // Restore the native toolbar immediately after entering fullscreen, if we do - // this before leaving fullscreen, traffic light buttons will be jumping. - if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { - base::scoped_nsobject toolbar( - [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]); - [toolbar setShowsBaselineSeparator:NO]; - [window setToolbar:toolbar]; - - // Set window style to hide the toolbar, otherwise the toolbar will show in - // fullscreen mode. - shell_->SetStyleMask(true, NSFullSizeContentViewWindowMask); - } - } -} - -- (void)windowWillExitFullScreen:(NSNotification*)notification { - if (@available(macOS 10.10, *)) { - // Restore the titlebar visibility. - NSWindow* window = shell_->GetNativeWindow(); - if ((shell_->transparent() || !shell_->has_frame()) && - (shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET || - shell_->fullscreen_window_title())) { - [window setTitleVisibility:NSWindowTitleHidden]; - } - - // Turn off the style for toolbar. - if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { - shell_->SetStyleMask(false, NSFullSizeContentViewWindowMask); - } - } -} - -- (void)windowDidExitFullScreen:(NSNotification*)notification { - shell_->SetResizable(is_resizable_); - shell_->NotifyWindowLeaveFullScreen(); -} - -- (void)windowWillClose:(NSNotification*)notification { - shell_->NotifyWindowClosed(); - - // Clears the delegate when window is going to be closed, since EL Capitan it - // is possible that the methods of delegate would get called after the window - // has been closed. - [shell_->GetNativeWindow() setDelegate:nil]; -} - -- (BOOL)windowShouldClose:(id)window { - shell_->NotifyWindowCloseButtonClicked(); - return NO; -} - -- (NSRect)window:(NSWindow*)window - willPositionSheet:(NSWindow*)sheet usingRect:(NSRect)rect { - NSView* view = window.contentView; - - rect.origin.x = shell_->GetSheetOffsetX(); - rect.origin.y = view.frame.size.height - shell_->GetSheetOffsetY(); - return rect; -} - -- (void)windowWillBeginSheet:(NSNotification *)notification { - shell_->NotifyWindowSheetBegin(); -} - -- (void)windowDidEndSheet:(NSNotification *)notification { - shell_->NotifyWindowSheetEnd(); -} - -- (IBAction)newWindowForTab:(id)sender { - shell_->NotifyNewWindowForTab(); - atom::Browser::Get()->NewWindowForTab(); -} - -@end - @interface AtomPreviewItem : NSObject @property (nonatomic, retain) NSURL* previewItemURL; diff --git a/atom/browser/ui/cocoa/atom_native_widget_mac.h b/atom/browser/ui/cocoa/atom_native_widget_mac.h index a078fcb1ee02..49250239f3b1 100644 --- a/atom/browser/ui/cocoa/atom_native_widget_mac.h +++ b/atom/browser/ui/cocoa/atom_native_widget_mac.h @@ -16,7 +16,7 @@ class AtomNativeWidgetMac : public views::NativeWidgetMac { protected: // NativeWidgetMac: - views::NativeWidgetMacNSWindow* CreateNSWindow( + NativeWidgetMacNSWindow* CreateNSWindow( const views::Widget::InitParams& params) override; private: diff --git a/atom/browser/ui/cocoa/atom_native_widget_mac.mm b/atom/browser/ui/cocoa/atom_native_widget_mac.mm index 01f2fa392674..f9eaf38fc6fb 100644 --- a/atom/browser/ui/cocoa/atom_native_widget_mac.mm +++ b/atom/browser/ui/cocoa/atom_native_widget_mac.mm @@ -14,7 +14,7 @@ AtomNativeWidgetMac::AtomNativeWidgetMac( AtomNativeWidgetMac::~AtomNativeWidgetMac() { } -views::NativeWidgetMacNSWindow* AtomNativeWidgetMac::CreateNSWindow( +NativeWidgetMacNSWindow* AtomNativeWidgetMac::CreateNSWindow( const views::Widget::InitParams& params) { return views::NativeWidgetMac::CreateNSWindow(params); } diff --git a/atom/browser/ui/cocoa/atom_ns_window_delegate.h b/atom/browser/ui/cocoa/atom_ns_window_delegate.h new file mode 100644 index 000000000000..2cd4171b14ad --- /dev/null +++ b/atom/browser/ui/cocoa/atom_ns_window_delegate.h @@ -0,0 +1,24 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_COCOA_ATOM_NS_WINDOW_DELEGATE_H_ +#define ATOM_BROWSER_UI_COCOA_ATOM_NS_WINDOW_DELEGATE_H_ + +#include "ui/views/cocoa/views_nswindow_delegate.h" + +namespace atom { +class NativeWindowMac; +} + +@interface AtomNSWindowDelegate : NSObject { + @private + atom::NativeWindowMac* shell_; + bool is_zooming_; + int level_; + bool is_resizable_; +} +- (id)initWithShell:(atom::NativeWindowMac*)shell; +@end + +#endif // ATOM_BROWSER_UI_COCOA_ATOM_NS_WINDOW_DELEGATE_H_ diff --git a/atom/browser/ui/cocoa/atom_ns_window_delegate.mm b/atom/browser/ui/cocoa/atom_ns_window_delegate.mm new file mode 100644 index 000000000000..090e8db6e2cb --- /dev/null +++ b/atom/browser/ui/cocoa/atom_ns_window_delegate.mm @@ -0,0 +1,249 @@ +// 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_delegate.h" + +#include "atom/browser/browser.h" +#include "atom/browser/native_window_mac.h" +#include "base/mac/mac_util.h" + +@implementation AtomNSWindowDelegate + +- (id)initWithShell:(atom::NativeWindowMac*)shell { + if ((self = [super init])) { + shell_ = shell; + is_zooming_ = false; + level_ = [shell_->GetNativeWindow() level]; + } + return self; +} + +- (void)windowDidChangeOcclusionState:(NSNotification *)notification { + // notification.object is the window that changed its state. + // It's safe to use self.window instead if you don't assign one delegate to many windows + NSWindow *window = notification.object; + + // check occlusion binary flag + if (window.occlusionState & NSWindowOcclusionStateVisible) { + // The app is visible + shell_->NotifyWindowShow(); + } else { + // The app is not visible + shell_->NotifyWindowHide(); + } +} + +// Called when the user clicks the zoom button or selects it from the Window +// menu to determine the "standard size" of the window. +- (NSRect)windowWillUseStandardFrame:(NSWindow*)window + defaultFrame:(NSRect)frame { + if (!shell_->zoom_to_page_width()) + return frame; + + // If the shift key is down, maximize. + if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) + return frame; + + // Get preferred width from observers. Usually the page width. + int preferred_width = 0; + shell_->NotifyWindowRequestPreferredWith(&preferred_width); + + // Never shrink from the current size on zoom. + NSRect window_frame = [window frame]; + CGFloat zoomed_width = std::max(static_cast(preferred_width), + NSWidth(window_frame)); + + // |frame| determines our maximum extents. We need to set the origin of the + // frame -- and only move it left if necessary. + if (window_frame.origin.x + zoomed_width > NSMaxX(frame)) + frame.origin.x = NSMaxX(frame) - zoomed_width; + else + frame.origin.x = window_frame.origin.x; + + // Set the width. Don't touch y or height. + frame.size.width = zoomed_width; + + return frame; +} + +- (void)windowDidBecomeMain:(NSNotification*)notification { + shell_->NotifyWindowFocus(); +} + +- (void)windowDidResignMain:(NSNotification*)notification { + shell_->NotifyWindowBlur(); +} + +- (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize { + NSSize newSize = frameSize; + double aspectRatio = shell_->GetAspectRatio(); + + if (aspectRatio > 0.0) { + gfx::Size windowSize = shell_->GetSize(); + gfx::Size contentSize = shell_->GetContentSize(); + gfx::Size extraSize = shell_->GetAspectRatioExtraSize(); + + double extraWidthPlusFrame = + windowSize.width() - contentSize.width() + extraSize.width(); + double extraHeightPlusFrame = + windowSize.height() - contentSize.height() + extraSize.height(); + + newSize.width = + roundf((frameSize.height - extraHeightPlusFrame) * aspectRatio + + extraWidthPlusFrame); + newSize.height = + roundf((newSize.width - extraWidthPlusFrame) / aspectRatio + + extraHeightPlusFrame); + } + + return newSize; +} + +- (void)windowDidResize:(NSNotification*)notification { + shell_->NotifyWindowResize(); +} + +- (void)windowDidMove:(NSNotification*)notification { + // TODO(zcbenz): Remove the alias after figuring out a proper + // way to dispatch move. + shell_->NotifyWindowMove(); + shell_->NotifyWindowMoved(); +} + +- (void)windowWillMiniaturize:(NSNotification*)notification { + NSWindow* window = shell_->GetNativeWindow(); + // store the current status window level to be restored in windowDidDeminiaturize + level_ = [window level]; + [window setLevel:NSNormalWindowLevel]; +} + +- (void)windowDidMiniaturize:(NSNotification*)notification { + shell_->NotifyWindowMinimize(); +} + +- (void)windowDidDeminiaturize:(NSNotification*)notification { + [shell_->GetNativeWindow() setLevel:level_]; + shell_->NotifyWindowRestore(); +} + +- (BOOL)windowShouldZoom:(NSWindow*)window toFrame:(NSRect)newFrame { + is_zooming_ = true; + return YES; +} + +- (void)windowDidEndLiveResize:(NSNotification*)notification { + if (is_zooming_) { + if (shell_->IsMaximized()) + shell_->NotifyWindowMaximize(); + else + shell_->NotifyWindowUnmaximize(); + is_zooming_ = false; + } +} + +- (void)windowWillEnterFullScreen:(NSNotification*)notification { + // Setting resizable to true before entering fullscreen + is_resizable_ = shell_->IsResizable(); + shell_->SetResizable(true); + // Hide the native toolbar before entering fullscreen, so there is no visual + // artifacts. + if (@available(macOS 10.10, *)) { + if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { + NSWindow* window = shell_->GetNativeWindow(); + [window setToolbar:nil]; + } + } +} + +- (void)windowDidEnterFullScreen:(NSNotification*)notification { + shell_->NotifyWindowEnterFullScreen(); + + if (@available(macOS 10.10, *)) { + // For frameless window we don't show set title for normal mode since the + // titlebar is expected to be empty, but after entering fullscreen mode we + // have to set one, because title bar is visible here. + NSWindow* window = shell_->GetNativeWindow(); + if ((shell_->transparent() || !shell_->has_frame()) && + // FIXME(zcbenz): Showing titlebar for hiddenInset window is weird under + // fullscreen mode. + // Show title if fullscreen_window_title flag is set + (shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET || + shell_->fullscreen_window_title())) { + [window setTitleVisibility:NSWindowTitleVisible]; + } + + // Restore the native toolbar immediately after entering fullscreen, if we do + // this before leaving fullscreen, traffic light buttons will be jumping. + if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { + base::scoped_nsobject toolbar( + [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]); + [toolbar setShowsBaselineSeparator:NO]; + [window setToolbar:toolbar]; + + // Set window style to hide the toolbar, otherwise the toolbar will show in + // fullscreen mode. + shell_->SetStyleMask(true, NSFullSizeContentViewWindowMask); + } + } +} + +- (void)windowWillExitFullScreen:(NSNotification*)notification { + if (@available(macOS 10.10, *)) { + // Restore the titlebar visibility. + NSWindow* window = shell_->GetNativeWindow(); + if ((shell_->transparent() || !shell_->has_frame()) && + (shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET || + shell_->fullscreen_window_title())) { + [window setTitleVisibility:NSWindowTitleHidden]; + } + + // Turn off the style for toolbar. + if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { + shell_->SetStyleMask(false, NSFullSizeContentViewWindowMask); + } + } +} + +- (void)windowDidExitFullScreen:(NSNotification*)notification { + shell_->SetResizable(is_resizable_); + shell_->NotifyWindowLeaveFullScreen(); +} + +- (void)windowWillClose:(NSNotification*)notification { + shell_->NotifyWindowClosed(); + + // Clears the delegate when window is going to be closed, since EL Capitan it + // is possible that the methods of delegate would get called after the window + // has been closed. + [shell_->GetNativeWindow() setDelegate:nil]; +} + +- (BOOL)windowShouldClose:(id)window { + shell_->NotifyWindowCloseButtonClicked(); + return NO; +} + +- (NSRect)window:(NSWindow*)window + willPositionSheet:(NSWindow*)sheet usingRect:(NSRect)rect { + NSView* view = window.contentView; + + rect.origin.x = shell_->GetSheetOffsetX(); + rect.origin.y = view.frame.size.height - shell_->GetSheetOffsetY(); + return rect; +} + +- (void)windowWillBeginSheet:(NSNotification *)notification { + shell_->NotifyWindowSheetBegin(); +} + +- (void)windowDidEndSheet:(NSNotification *)notification { + shell_->NotifyWindowSheetEnd(); +} + +- (IBAction)newWindowForTab:(id)sender { + shell_->NotifyNewWindowForTab(); + atom::Browser::Get()->NewWindowForTab(); +} + +@end diff --git a/filenames.gypi b/filenames.gypi index a76b5d08d1d6..afed5285aa2f 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -318,6 +318,8 @@ 'atom/browser/ui/cocoa/atom_menu_controller.mm', 'atom/browser/ui/cocoa/atom_native_widget_mac.h', 'atom/browser/ui/cocoa/atom_native_widget_mac.mm', + 'atom/browser/ui/cocoa/atom_ns_window_delegate.h', + 'atom/browser/ui/cocoa/atom_ns_window_delegate.mm', 'atom/browser/ui/cocoa/atom_touch_bar.h', 'atom/browser/ui/cocoa/atom_touch_bar.mm', 'atom/browser/ui/cocoa/views_delegate_mac.h', diff --git a/script/cpplint.py b/script/cpplint.py index 78419745c240..346a3c18a877 100755 --- a/script/cpplint.py +++ b/script/cpplint.py @@ -12,6 +12,7 @@ IGNORE_FILES = set(os.path.join(*components) for components in [ ['atom', 'browser', 'mac', 'atom_application_delegate.h'], ['atom', 'browser', 'resources', 'win', 'resource.h'], ['atom', 'browser', 'ui', 'cocoa', 'atom_menu_controller.h'], + ['atom', 'browser', 'ui', 'cocoa', 'atom_ns_window_delegate.h'], ['atom', 'browser', 'ui', 'cocoa', 'atom_touch_bar.h'], ['atom', 'browser', 'ui', 'cocoa', 'touch_bar_forward_declarations.h'], ['atom', 'browser', 'ui', 'cocoa', 'NSColor+Hex.h'], From 8e9667d86cca9193697d2f6045a629efa4ab5183 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Apr 2018 16:12:11 +0900 Subject: [PATCH 5/9] Manage AtomTouchBar in NativeWindow instead of AtomNSWindow --- atom/browser/native_window_mac.h | 3 ++ atom/browser/native_window_mac.mm | 51 +++++++++++-------------------- 2 files changed, 20 insertions(+), 34 deletions(-) diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index b74f1b623827..926caf765ab9 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -17,6 +17,7 @@ @class AtomNSWindow; @class AtomNSWindowDelegate; +@class AtomTouchBar; @class FullSizeContentView; namespace atom { @@ -136,6 +137,7 @@ class NativeWindowMac : public NativeWindow { }; TitleBarStyle title_bar_style() const { return title_bar_style_; } + AtomTouchBar* atom_touch_bar() const { return atom_touch_bar_.get(); } bool zoom_to_page_width() const { return zoom_to_page_width_; } bool fullscreen_window_title() const { return fullscreen_window_title_; } bool simple_fullscreen() const { return always_simple_fullscreen_; } @@ -148,6 +150,7 @@ class NativeWindowMac : public NativeWindow { base::scoped_nsobject window_; base::scoped_nsobject window_delegate_; + base::scoped_nsobject atom_touch_bar_; std::unique_ptr widget_; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index c1f826a8273a..ffd1e9d705a9 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -213,7 +213,6 @@ enum { @private atom::NativeWindowMac* shell_; bool enable_larger_than_screen_; - base::scoped_nsobject atom_touch_bar_; CGFloat windowButtonsInterButtonSpacing_; } @property BOOL acceptsFirstMouse; @@ -226,9 +225,6 @@ enum { - (void)setShell:(atom::NativeWindowMac*)shell; - (void)setEnableLargerThanScreen:(bool)enable; - (void)enableWindowButtonsOffset; -- (void)resetTouchBar:(const std::vector&)settings; -- (void)refreshTouchBarItem:(const std::string&)item_id; -- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item; @end @@ -249,43 +245,21 @@ enum { enable_larger_than_screen_ = enable; } -- (void)resetTouchBar:(const std::vector&)settings - API_AVAILABLE(macosx(10.12.2)) { - if (![self respondsToSelector:@selector(touchBar)]) return; - - atom_touch_bar_.reset([[AtomTouchBar alloc] initWithDelegate:self - window:shell_ - settings:settings]); - self.touchBar = nil; -} - -- (void)refreshTouchBarItem:(const std::string&)item_id - API_AVAILABLE(macosx(10.12.2)) { - if (atom_touch_bar_ && self.touchBar) - [atom_touch_bar_ refreshTouchBarItem:self.touchBar id:item_id]; -} - - (NSTouchBar*)makeTouchBar API_AVAILABLE(macosx(10.12.2)) { - if (atom_touch_bar_) - return [atom_touch_bar_ makeTouchBar]; + if (shell_->atom_touch_bar()) + return [shell_->atom_touch_bar() makeTouchBar]; else return nil; } - (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier API_AVAILABLE(macosx(10.12.2)) { - if (touchBar && atom_touch_bar_) - return [atom_touch_bar_ makeItemForIdentifier:identifier]; + if (touchBar && shell_->atom_touch_bar()) + return [shell_->atom_touch_bar() makeItemForIdentifier:identifier]; else return nil; } -- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item - API_AVAILABLE(macosx(10.12.2)) { - if (atom_touch_bar_ && self.touchBar) - [atom_touch_bar_ setEscapeTouchBarItem:item forTouchBar:self.touchBar]; -} - // NSWindow overrides. - (void)swipeWithEvent:(NSEvent *)event { @@ -1538,15 +1512,24 @@ void NativeWindowMac::SetVibrancy(const std::string& type) { void NativeWindowMac::SetTouchBar( const std::vector& items) { - [window_ resetTouchBar:items]; + if (![window_ respondsToSelector:@selector(touchBar)]) + return; + + atom_touch_bar_.reset([[AtomTouchBar alloc] initWithDelegate:window_.get() + window:this + settings:items]); + [window_ setTouchBar:nil]; } void NativeWindowMac::RefreshTouchBarItem(const std::string& item_id) { - [window_ refreshTouchBarItem:item_id]; + if (atom_touch_bar_ && [window_ touchBar]) + [atom_touch_bar_ refreshTouchBarItem:[window_ touchBar] id:item_id]; } -void NativeWindowMac::SetEscapeTouchBarItem(const mate::PersistentDictionary& item) { - [window_ setEscapeTouchBarItem:item]; +void NativeWindowMac::SetEscapeTouchBarItem( + const mate::PersistentDictionary& item) { + if (atom_touch_bar_ && [window_ touchBar]) + [atom_touch_bar_ setEscapeTouchBarItem:item forTouchBar:[window_ touchBar]]; } gfx::Rect NativeWindowMac::ContentBoundsToWindowBounds( From f6a7e5ea235c10f88599a3a269b5740b003fb00c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Apr 2018 16:18:50 +0900 Subject: [PATCH 6/9] Move NSTouchBarDelegate to AtomNSWindowDelegate --- atom/browser/native_window_mac.mm | 17 +++++------------ atom/browser/ui/cocoa/atom_ns_window_delegate.h | 3 ++- .../browser/ui/cocoa/atom_ns_window_delegate.mm | 13 +++++++++++++ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index ffd1e9d705a9..fa4bffc9cc43 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -209,7 +209,7 @@ enum { #endif -@interface AtomNSWindow : EventDispatchingWindow { +@interface AtomNSWindow : EventDispatchingWindow { @private atom::NativeWindowMac* shell_; bool enable_larger_than_screen_; @@ -252,14 +252,6 @@ enum { return nil; } -- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar - makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier API_AVAILABLE(macosx(10.12.2)) { - if (touchBar && shell_->atom_touch_bar()) - return [shell_->atom_touch_bar() makeItemForIdentifier:identifier]; - else - return nil; -} - // NSWindow overrides. - (void)swipeWithEvent:(NSEvent *)event { @@ -1515,9 +1507,10 @@ void NativeWindowMac::SetTouchBar( if (![window_ respondsToSelector:@selector(touchBar)]) return; - atom_touch_bar_.reset([[AtomTouchBar alloc] initWithDelegate:window_.get() - window:this - settings:items]); + atom_touch_bar_.reset([[AtomTouchBar alloc] + initWithDelegate:window_delegate_.get() + window:this + settings:items]); [window_ setTouchBar:nil]; } diff --git a/atom/browser/ui/cocoa/atom_ns_window_delegate.h b/atom/browser/ui/cocoa/atom_ns_window_delegate.h index 2cd4171b14ad..62bcbee35723 100644 --- a/atom/browser/ui/cocoa/atom_ns_window_delegate.h +++ b/atom/browser/ui/cocoa/atom_ns_window_delegate.h @@ -11,7 +11,8 @@ namespace atom { class NativeWindowMac; } -@interface AtomNSWindowDelegate : NSObject { +@interface AtomNSWindowDelegate : NSObject { @private atom::NativeWindowMac* shell_; bool is_zooming_; diff --git a/atom/browser/ui/cocoa/atom_ns_window_delegate.mm b/atom/browser/ui/cocoa/atom_ns_window_delegate.mm index 090e8db6e2cb..0b71c6af79a5 100644 --- a/atom/browser/ui/cocoa/atom_ns_window_delegate.mm +++ b/atom/browser/ui/cocoa/atom_ns_window_delegate.mm @@ -6,6 +6,7 @@ #include "atom/browser/browser.h" #include "atom/browser/native_window_mac.h" +#include "atom/browser/ui/cocoa/atom_touch_bar.h" #include "base/mac/mac_util.h" @implementation AtomNSWindowDelegate @@ -19,6 +20,8 @@ return self; } +#pragma mark - NSWindowDelegate + - (void)windowDidChangeOcclusionState:(NSNotification *)notification { // notification.object is the window that changed its state. // It's safe to use self.window instead if you don't assign one delegate to many windows @@ -246,4 +249,14 @@ atom::Browser::Get()->NewWindowForTab(); } +#pragma mark - NSTouchBarDelegate + +- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar + makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier API_AVAILABLE(macosx(10.12.2)) { + if (touchBar && shell_->atom_touch_bar()) + return [shell_->atom_touch_bar() makeItemForIdentifier:identifier]; + else + return nil; +} + @end From 569967ac2143e1fe9fb3ae4cfe06f38ee1998ea3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Apr 2018 16:41:36 +0900 Subject: [PATCH 7/9] Move QLPreviewPanelDataSource to AtomNSWindowDelegate --- atom/browser/native_window_mac.h | 7 +- atom/browser/native_window_mac.mm | 70 +++++-------------- .../ui/cocoa/atom_ns_window_delegate.h | 5 +- .../ui/cocoa/atom_ns_window_delegate.mm | 16 ++++- atom/browser/ui/cocoa/atom_preview_item.h | 17 +++++ atom/browser/ui/cocoa/atom_preview_item.mm | 21 ++++++ filenames.gypi | 2 + script/cpplint.py | 1 + 8 files changed, 80 insertions(+), 59 deletions(-) create mode 100644 atom/browser/ui/cocoa/atom_preview_item.h create mode 100644 atom/browser/ui/cocoa/atom_preview_item.mm diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 926caf765ab9..42f24ccf169f 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -17,6 +17,7 @@ @class AtomNSWindow; @class AtomNSWindowDelegate; +@class AtomPreviewItem; @class AtomTouchBar; @class FullSizeContentView; @@ -137,7 +138,8 @@ class NativeWindowMac : public NativeWindow { }; TitleBarStyle title_bar_style() const { return title_bar_style_; } - AtomTouchBar* atom_touch_bar() const { return atom_touch_bar_.get(); } + AtomPreviewItem* preview_item() const { return preview_item_.get(); } + AtomTouchBar* touch_bar() const { return touch_bar_.get(); } bool zoom_to_page_width() const { return zoom_to_page_width_; } bool fullscreen_window_title() const { return fullscreen_window_title_; } bool simple_fullscreen() const { return always_simple_fullscreen_; } @@ -150,7 +152,8 @@ class NativeWindowMac : public NativeWindow { base::scoped_nsobject window_; base::scoped_nsobject window_delegate_; - base::scoped_nsobject atom_touch_bar_; + base::scoped_nsobject preview_item_; + base::scoped_nsobject touch_bar_; std::unique_ptr widget_; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index fa4bffc9cc43..edd9e4b27040 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -5,11 +5,12 @@ #include "atom/browser/native_window_mac.h" #include -#include + #include #include "atom/browser/native_browser_view_mac.h" #include "atom/browser/ui/cocoa/atom_ns_window_delegate.h" +#include "atom/browser/ui/cocoa/atom_preview_item.h" #include "atom/browser/ui/cocoa/atom_touch_bar.h" #include "atom/browser/window_list.h" #include "atom/common/options_switches.h" @@ -165,31 +166,6 @@ bool ScopedDisableResize::disable_resize_ = false; @end -@interface AtomPreviewItem : NSObject - -@property (nonatomic, retain) NSURL* previewItemURL; -@property (nonatomic, retain) NSString* previewItemTitle; - -- (id)initWithURL:(NSURL*)url title:(NSString*)title; - -@end - -@implementation AtomPreviewItem - -@synthesize previewItemURL; -@synthesize previewItemTitle; - -- (id)initWithURL:(NSURL*)url title:(NSString*)title { - self = [super init]; - if (self) { - self.previewItemURL = url; - self.previewItemTitle = title; - } - return self; -} - -@end - #if !defined(AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER) enum { @@ -209,7 +185,7 @@ enum { #endif -@interface AtomNSWindow : EventDispatchingWindow { +@interface AtomNSWindow : EventDispatchingWindow { @private atom::NativeWindowMac* shell_; bool enable_larger_than_screen_; @@ -219,7 +195,6 @@ enum { @property BOOL disableAutoHideCursor; @property BOOL disableKeyOrMainWindow; @property NSPoint windowButtonsOffset; -@property (nonatomic, retain) AtomPreviewItem* quickLookItem; @property (nonatomic, retain) NSView* vibrantView; - (void)setShell:(atom::NativeWindowMac*)shell; @@ -246,8 +221,8 @@ enum { } - (NSTouchBar*)makeTouchBar API_AVAILABLE(macosx(10.12.2)) { - if (shell_->atom_touch_bar()) - return [shell_->atom_touch_bar() makeTouchBar]; + if (shell_->touch_bar()) + return [shell_->touch_bar() makeTouchBar]; else return nil; } @@ -400,8 +375,8 @@ enum { } - (void)beginPreviewPanelControl:(QLPreviewPanel*)panel { - panel.delegate = self; - panel.dataSource = self; + panel.delegate = [self delegate]; + panel.dataSource = static_cast>([self delegate]); } - (void)endPreviewPanelControl:(QLPreviewPanel*)panel { @@ -409,20 +384,6 @@ enum { panel.dataSource = nil; } -- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel*)panel { - return 1; -} - -- (id )previewPanel:(QLPreviewPanel*)panel previewItemAtIndex:(NSInteger)index { - return [self quickLookItem]; -} - -- (void)previewFileAtPath:(NSString*)path withName:(NSString*) fileName { - NSURL* url = [[[NSURL alloc] initFileURLWithPath:path] autorelease]; - [self setQuickLookItem:[[[AtomPreviewItem alloc] initWithURL:url title:fileName] autorelease]]; - [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil]; -} - // Custom window button methods - (void)performClose:(id)sender { @@ -1007,9 +968,10 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio, void NativeWindowMac::PreviewFile(const std::string& path, const std::string& display_name) { - NSString* path_ns = [NSString stringWithUTF8String:path.c_str()]; - NSString* name_ns = [NSString stringWithUTF8String:display_name.c_str()]; - [window_ previewFileAtPath:path_ns withName:name_ns]; + preview_item_.reset([[AtomPreviewItem alloc] + initWithURL:[NSURL fileURLWithPath:base::SysUTF8ToNSString(path)] + title:base::SysUTF8ToNSString(display_name)]); + [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil]; } void NativeWindowMac::CloseFilePreview() { @@ -1507,7 +1469,7 @@ void NativeWindowMac::SetTouchBar( if (![window_ respondsToSelector:@selector(touchBar)]) return; - atom_touch_bar_.reset([[AtomTouchBar alloc] + touch_bar_.reset([[AtomTouchBar alloc] initWithDelegate:window_delegate_.get() window:this settings:items]); @@ -1515,14 +1477,14 @@ void NativeWindowMac::SetTouchBar( } void NativeWindowMac::RefreshTouchBarItem(const std::string& item_id) { - if (atom_touch_bar_ && [window_ touchBar]) - [atom_touch_bar_ refreshTouchBarItem:[window_ touchBar] id:item_id]; + if (touch_bar_ && [window_ touchBar]) + [touch_bar_ refreshTouchBarItem:[window_ touchBar] id:item_id]; } void NativeWindowMac::SetEscapeTouchBarItem( const mate::PersistentDictionary& item) { - if (atom_touch_bar_ && [window_ touchBar]) - [atom_touch_bar_ setEscapeTouchBarItem:item forTouchBar:[window_ touchBar]]; + if (touch_bar_ && [window_ touchBar]) + [touch_bar_ setEscapeTouchBarItem:item forTouchBar:[window_ touchBar]]; } gfx::Rect NativeWindowMac::ContentBoundsToWindowBounds( diff --git a/atom/browser/ui/cocoa/atom_ns_window_delegate.h b/atom/browser/ui/cocoa/atom_ns_window_delegate.h index 62bcbee35723..0947b0392147 100644 --- a/atom/browser/ui/cocoa/atom_ns_window_delegate.h +++ b/atom/browser/ui/cocoa/atom_ns_window_delegate.h @@ -5,6 +5,8 @@ #ifndef ATOM_BROWSER_UI_COCOA_ATOM_NS_WINDOW_DELEGATE_H_ #define ATOM_BROWSER_UI_COCOA_ATOM_NS_WINDOW_DELEGATE_H_ +#include + #include "ui/views/cocoa/views_nswindow_delegate.h" namespace atom { @@ -12,7 +14,8 @@ class NativeWindowMac; } @interface AtomNSWindowDelegate : NSObject { + NSTouchBarDelegate, + QLPreviewPanelDataSource> { @private atom::NativeWindowMac* shell_; bool is_zooming_; diff --git a/atom/browser/ui/cocoa/atom_ns_window_delegate.mm b/atom/browser/ui/cocoa/atom_ns_window_delegate.mm index 0b71c6af79a5..14857758a77b 100644 --- a/atom/browser/ui/cocoa/atom_ns_window_delegate.mm +++ b/atom/browser/ui/cocoa/atom_ns_window_delegate.mm @@ -6,6 +6,7 @@ #include "atom/browser/browser.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 "base/mac/mac_util.h" @@ -253,10 +254,21 @@ - (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier API_AVAILABLE(macosx(10.12.2)) { - if (touchBar && shell_->atom_touch_bar()) - return [shell_->atom_touch_bar() makeItemForIdentifier:identifier]; + if (touchBar && shell_->touch_bar()) + return [shell_->touch_bar() makeItemForIdentifier:identifier]; else return nil; } +#pragma mark - QLPreviewPanelDataSource + +- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel*)panel { + return 1; +} + +- (id )previewPanel:(QLPreviewPanel*)panel + previewItemAtIndex:(NSInteger)index { + return shell_->preview_item(); +} + @end diff --git a/atom/browser/ui/cocoa/atom_preview_item.h b/atom/browser/ui/cocoa/atom_preview_item.h new file mode 100644 index 000000000000..aef1d3ff6e2a --- /dev/null +++ b/atom/browser/ui/cocoa/atom_preview_item.h @@ -0,0 +1,17 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_COCOA_ATOM_PREVIEW_ITEM_H_ +#define ATOM_BROWSER_UI_COCOA_ATOM_PREVIEW_ITEM_H_ + +#import +#import + +@interface AtomPreviewItem : NSObject +@property (nonatomic, retain) NSURL* previewItemURL; +@property (nonatomic, retain) NSString* previewItemTitle; +- (id)initWithURL:(NSURL*)url title:(NSString*)title; +@end + +#endif // ATOM_BROWSER_UI_COCOA_ATOM_PREVIEW_ITEM_H_ diff --git a/atom/browser/ui/cocoa/atom_preview_item.mm b/atom/browser/ui/cocoa/atom_preview_item.mm new file mode 100644 index 000000000000..2bd273d444da --- /dev/null +++ b/atom/browser/ui/cocoa/atom_preview_item.mm @@ -0,0 +1,21 @@ +// 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_preview_item.h" + +@implementation AtomPreviewItem + +@synthesize previewItemURL; +@synthesize previewItemTitle; + +- (id)initWithURL:(NSURL*)url title:(NSString*)title { + self = [super init]; + if (self) { + self.previewItemURL = url; + self.previewItemTitle = title; + } + return self; +} + +@end diff --git a/filenames.gypi b/filenames.gypi index afed5285aa2f..f7d710bf6290 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -320,6 +320,8 @@ 'atom/browser/ui/cocoa/atom_native_widget_mac.mm', 'atom/browser/ui/cocoa/atom_ns_window_delegate.h', 'atom/browser/ui/cocoa/atom_ns_window_delegate.mm', + 'atom/browser/ui/cocoa/atom_preview_item.h', + 'atom/browser/ui/cocoa/atom_preview_item.mm', 'atom/browser/ui/cocoa/atom_touch_bar.h', 'atom/browser/ui/cocoa/atom_touch_bar.mm', 'atom/browser/ui/cocoa/views_delegate_mac.h', diff --git a/script/cpplint.py b/script/cpplint.py index 346a3c18a877..4521c0031154 100755 --- a/script/cpplint.py +++ b/script/cpplint.py @@ -13,6 +13,7 @@ IGNORE_FILES = set(os.path.join(*components) for components in [ ['atom', 'browser', 'resources', 'win', 'resource.h'], ['atom', 'browser', 'ui', 'cocoa', 'atom_menu_controller.h'], ['atom', 'browser', 'ui', 'cocoa', 'atom_ns_window_delegate.h'], + ['atom', 'browser', 'ui', 'cocoa', 'atom_preview_item.h'], ['atom', 'browser', 'ui', 'cocoa', 'atom_touch_bar.h'], ['atom', 'browser', 'ui', 'cocoa', 'touch_bar_forward_declarations.h'], ['atom', 'browser', 'ui', 'cocoa', 'NSColor+Hex.h'], From c44279bb10cc25e316655857e810935c1232edba Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Apr 2018 16:53:12 +0900 Subject: [PATCH 8/9] Move AtomNSWindow to a new file --- atom/browser/native_window_mac.mm | 244 +----------------------- atom/browser/ui/cocoa/atom_ns_window.h | 45 +++++ atom/browser/ui/cocoa/atom_ns_window.mm | 217 +++++++++++++++++++++ filenames.gypi | 2 + script/cpplint.py | 1 + 5 files changed, 266 insertions(+), 243 deletions(-) create mode 100644 atom/browser/ui/cocoa/atom_ns_window.h create mode 100644 atom/browser/ui/cocoa/atom_ns_window.mm diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index edd9e4b27040..38b082208d0b 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -9,6 +9,7 @@ #include #include "atom/browser/native_browser_view_mac.h" +#include "atom/browser/ui/cocoa/atom_ns_window.h" #include "atom/browser/ui/cocoa/atom_ns_window_delegate.h" #include "atom/browser/ui/cocoa/atom_preview_item.h" #include "atom/browser/ui/cocoa/atom_touch_bar.h" @@ -19,7 +20,6 @@ #include "base/strings/sys_string_conversions.h" #include "brightray/browser/inspectable_web_contents.h" #include "brightray/browser/inspectable_web_contents_view.h" -#include "brightray/browser/mac/event_dispatching_window.h" #include "content/public/browser/browser_accessibility_state.h" #include "native_mate/dictionary.h" #include "skia/ext/skia_utils_mac.h" @@ -27,24 +27,6 @@ #include "ui/gl/gpu_switching_manager.h" #include "ui/views/widget/widget.h" -namespace { - -// Prevents window from resizing during the scope. -class ScopedDisableResize { - public: - ScopedDisableResize() { disable_resize_ = true; } - ~ScopedDisableResize() { disable_resize_ = false; } - - static bool IsResizeDisabled() { return disable_resize_; } - - private: - static bool disable_resize_; -}; - -bool ScopedDisableResize::disable_resize_ = false; - -} // namespace - // Custom Quit, Minimize and Full Screen button container for frameless // windows. @interface CustomWindowButtonView : NSView { @@ -185,230 +167,6 @@ enum { #endif -@interface AtomNSWindow : EventDispatchingWindow { - @private - atom::NativeWindowMac* shell_; - bool enable_larger_than_screen_; - CGFloat windowButtonsInterButtonSpacing_; -} -@property BOOL acceptsFirstMouse; -@property BOOL disableAutoHideCursor; -@property BOOL disableKeyOrMainWindow; -@property NSPoint windowButtonsOffset; -@property (nonatomic, retain) NSView* vibrantView; - -- (void)setShell:(atom::NativeWindowMac*)shell; -- (void)setEnableLargerThanScreen:(bool)enable; -- (void)enableWindowButtonsOffset; - -@end - -@implementation AtomNSWindow - -@synthesize acceptsFirstMouse; -@synthesize disableAutoHideCursor; -@synthesize disableKeyOrMainWindow; -@synthesize windowButtonsOffset; -@synthesize quickLookItem; -@synthesize vibrantView; - -- (void)setShell:(atom::NativeWindowMac*)shell { - shell_ = shell; -} - -- (void)setEnableLargerThanScreen:(bool)enable { - enable_larger_than_screen_ = enable; -} - -- (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)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen { - // Resizing is disabled. - if (ScopedDisableResize::IsResizeDisabled()) - return [self frame]; - - // Enable the window to be larger than screen. - if (enable_larger_than_screen_) - 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 (!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>([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 - @interface AtomProgressBar : NSProgressIndicator @end diff --git a/atom/browser/ui/cocoa/atom_ns_window.h b/atom/browser/ui/cocoa/atom_ns_window.h new file mode 100644 index 000000000000..62d690b57e31 --- /dev/null +++ b/atom/browser/ui/cocoa/atom_ns_window.h @@ -0,0 +1,45 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_COCOA_ATOM_NS_WINDOW_H_ +#define ATOM_BROWSER_UI_COCOA_ATOM_NS_WINDOW_H_ + +#include "brightray/browser/mac/event_dispatching_window.h" +#include "ui/views/cocoa/native_widget_mac_nswindow.h" + +namespace atom { + +class NativeWindowMac; + +// Prevents window from resizing during the scope. +class ScopedDisableResize { + public: + ScopedDisableResize() { disable_resize_ = true; } + ~ScopedDisableResize() { disable_resize_ = false; } + + static bool IsResizeDisabled() { return disable_resize_; } + + private: + static bool disable_resize_; +}; + +} // namespace atom + +@interface AtomNSWindow : EventDispatchingWindow { + @private + atom::NativeWindowMac* shell_; + CGFloat windowButtonsInterButtonSpacing_; +} +@property BOOL acceptsFirstMouse; +@property BOOL enableLargerThanScreen; +@property BOOL disableAutoHideCursor; +@property BOOL disableKeyOrMainWindow; +@property NSPoint windowButtonsOffset; +@property (nonatomic, retain) NSView* vibrantView; +- (void)setShell:(atom::NativeWindowMac*)shell; +- (void)enableWindowButtonsOffset; +- (void)toggleFullScreenMode:(id)sender; +@end + +#endif // ATOM_BROWSER_UI_COCOA_ATOM_NS_WINDOW_H_ diff --git a/atom/browser/ui/cocoa/atom_ns_window.mm b/atom/browser/ui/cocoa/atom_ns_window.mm new file mode 100644 index 000000000000..e53ab91ab1c7 --- /dev/null +++ b/atom/browser/ui/cocoa/atom_ns_window.mm @@ -0,0 +1,217 @@ +// 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" + +namespace atom { + +bool ScopedDisableResize::disable_resize_ = false; + +} // namespace atom + +@implementation AtomNSWindow + +@synthesize acceptsFirstMouse; +@synthesize enableLargerThanScreen; +@synthesize disableAutoHideCursor; +@synthesize disableKeyOrMainWindow; +@synthesize windowButtonsOffset; +@synthesize vibrantView; + +- (void)setShell:(atom::NativeWindowMac*)shell { + shell_ = shell; +} + +- (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)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>([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 diff --git a/filenames.gypi b/filenames.gypi index f7d710bf6290..b04c41ad7d7d 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -318,6 +318,8 @@ 'atom/browser/ui/cocoa/atom_menu_controller.mm', 'atom/browser/ui/cocoa/atom_native_widget_mac.h', 'atom/browser/ui/cocoa/atom_native_widget_mac.mm', + 'atom/browser/ui/cocoa/atom_ns_window.h', + 'atom/browser/ui/cocoa/atom_ns_window.mm', 'atom/browser/ui/cocoa/atom_ns_window_delegate.h', 'atom/browser/ui/cocoa/atom_ns_window_delegate.mm', 'atom/browser/ui/cocoa/atom_preview_item.h', diff --git a/script/cpplint.py b/script/cpplint.py index 4521c0031154..da4b6212f4b1 100755 --- a/script/cpplint.py +++ b/script/cpplint.py @@ -12,6 +12,7 @@ IGNORE_FILES = set(os.path.join(*components) for components in [ ['atom', 'browser', 'mac', 'atom_application_delegate.h'], ['atom', 'browser', 'resources', 'win', 'resource.h'], ['atom', 'browser', 'ui', 'cocoa', 'atom_menu_controller.h'], + ['atom', 'browser', 'ui', 'cocoa', 'atom_ns_window.h'], ['atom', 'browser', 'ui', 'cocoa', 'atom_ns_window_delegate.h'], ['atom', 'browser', 'ui', 'cocoa', 'atom_preview_item.h'], ['atom', 'browser', 'ui', 'cocoa', 'atom_touch_bar.h'], From aa5c80f8a60e795749a32bcee34e810722251705 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 20 Apr 2018 19:23:21 +0900 Subject: [PATCH 9/9] Fix new clang warnings --- atom/browser/native_window_mac.mm | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 38b082208d0b..984a17dad582 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -1224,25 +1224,28 @@ void NativeWindowMac::SetVibrancy(const std::string& type) { void NativeWindowMac::SetTouchBar( const std::vector& items) { - if (![window_ respondsToSelector:@selector(touchBar)]) - return; - - touch_bar_.reset([[AtomTouchBar alloc] - initWithDelegate:window_delegate_.get() - window:this - settings:items]); - [window_ setTouchBar:nil]; + if (@available(macOS 10.12.2, *)) { + touch_bar_.reset([[AtomTouchBar alloc] + initWithDelegate:window_delegate_.get() + window:this + settings:items]); + [window_ setTouchBar:nil]; + } } void NativeWindowMac::RefreshTouchBarItem(const std::string& item_id) { - if (touch_bar_ && [window_ touchBar]) - [touch_bar_ refreshTouchBarItem:[window_ touchBar] id:item_id]; + if (@available(macOS 10.12.2, *)) { + if (touch_bar_ && [window_ touchBar]) + [touch_bar_ refreshTouchBarItem:[window_ touchBar] id:item_id]; + } } void NativeWindowMac::SetEscapeTouchBarItem( const mate::PersistentDictionary& item) { - if (touch_bar_ && [window_ touchBar]) - [touch_bar_ setEscapeTouchBarItem:item forTouchBar:[window_ touchBar]]; + if (@available(macOS 10.12.2, *)) { + if (touch_bar_ && [window_ touchBar]) + [touch_bar_ setEscapeTouchBarItem:item forTouchBar:[window_ touchBar]]; + } } gfx::Rect NativeWindowMac::ContentBoundsToWindowBounds(