From 64e1e71e2d82d65aab1eea78a5fde7c853de8697 Mon Sep 17 00:00:00 2001 From: andreiisaila Date: Mon, 30 May 2022 19:56:27 +0200 Subject: [PATCH 1/8] feat: add NSPanel support for BrowserWindow --- docs/api/browser-window.md | 6 ++- filenames.gni | 2 + shell/browser/native_window_mac.mm | 7 +++- .../ui/cocoa/electron_native_widget_mac.h | 3 ++ .../ui/cocoa/electron_native_widget_mac.mm | 13 ++++++- shell/browser/ui/cocoa/electron_ns_panel.h | 17 ++++++++ shell/browser/ui/cocoa/electron_ns_panel.mm | 39 +++++++++++++++++++ 7 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 shell/browser/ui/cocoa/electron_ns_panel.h create mode 100644 shell/browser/ui/cocoa/electron_ns_panel.mm diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 2f00cd1f5feb7..746e580095d6f 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -425,13 +425,17 @@ Possible values are: * On Linux, possible types are `desktop`, `dock`, `toolbar`, `splash`, `notification`. -* On macOS, possible types are `desktop`, `textured`. +* On macOS, possible types are `desktop`, `textured`, `panel`. * The `textured` type adds metal gradient appearance (`NSWindowStyleMaskTexturedBackground`). * The `desktop` type places the window at the desktop background window level (`kCGDesktopWindowLevel - 1`). Note that desktop window will not receive focus, keyboard or mouse events, but you can use `globalShortcut` to receive input sparingly. + * The `panel` type sets the window level to float (`NSFloatingWindowLevel`) and + makes it appear in all spaces. The `NSWindowStyleMaskNonactivatingPanel` style + mask is added on runtime, such that the window can float on top of full-screened + apps. * On Windows, possible type is `toolbar`. ### Instance Events diff --git a/filenames.gni b/filenames.gni index e2f6aa294f8a9..3d892ae81cf65 100644 --- a/filenames.gni +++ b/filenames.gni @@ -165,6 +165,8 @@ filenames = { "shell/browser/ui/cocoa/electron_native_widget_mac.mm", "shell/browser/ui/cocoa/electron_ns_window_delegate.h", "shell/browser/ui/cocoa/electron_ns_window_delegate.mm", + "shell/browser/ui/cocoa/electron_ns_panel.h", + "shell/browser/ui/cocoa/electron_ns_panel.mm", "shell/browser/ui/cocoa/electron_ns_window.h", "shell/browser/ui/cocoa/electron_ns_window.mm", "shell/browser/ui/cocoa/electron_preview_item.h", diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index 1563a7b2cf09c..5efe83883c442 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -317,7 +317,8 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { params.bounds = bounds; params.delegate = this; params.type = views::Widget::InitParams::TYPE_WINDOW; - params.native_widget = new ElectronNativeWidgetMac(this, styleMask, widget()); + params.native_widget = + new ElectronNativeWidgetMac(this, windowType, styleMask, widget()); widget()->Init(std::move(params)); SetCanResize(resizable); window_ = static_cast( @@ -355,6 +356,10 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { NSWindowCollectionBehaviorIgnoresCycle)]; } + if (windowType == "panel") { + [window_ setLevel:NSFloatingWindowLevel]; + } + bool focusable; if (options.Get(options::kFocusable, &focusable) && !focusable) [window_ setDisableKeyOrMainWindow:YES]; diff --git a/shell/browser/ui/cocoa/electron_native_widget_mac.h b/shell/browser/ui/cocoa/electron_native_widget_mac.h index 7fdfd0433a01a..7242511fb9bd9 100644 --- a/shell/browser/ui/cocoa/electron_native_widget_mac.h +++ b/shell/browser/ui/cocoa/electron_native_widget_mac.h @@ -5,6 +5,7 @@ #ifndef ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_NATIVE_WIDGET_MAC_H_ #define ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_NATIVE_WIDGET_MAC_H_ +#include #include "ui/views/widget/native_widget_mac.h" namespace electron { @@ -14,6 +15,7 @@ class NativeWindowMac; class ElectronNativeWidgetMac : public views::NativeWidgetMac { public: ElectronNativeWidgetMac(NativeWindowMac* shell, + const std::string& window_type, NSUInteger style_mask, views::internal::NativeWidgetDelegate* delegate); ~ElectronNativeWidgetMac() override; @@ -29,6 +31,7 @@ class ElectronNativeWidgetMac : public views::NativeWidgetMac { private: NativeWindowMac* shell_; + std::string window_type_; NSUInteger style_mask_; }; diff --git a/shell/browser/ui/cocoa/electron_native_widget_mac.mm b/shell/browser/ui/cocoa/electron_native_widget_mac.mm index 4247a45229f93..bafaf2479d401 100644 --- a/shell/browser/ui/cocoa/electron_native_widget_mac.mm +++ b/shell/browser/ui/cocoa/electron_native_widget_mac.mm @@ -4,24 +4,33 @@ #include "shell/browser/ui/cocoa/electron_native_widget_mac.h" +#include +#include "shell/browser/ui/cocoa/electron_ns_panel.h" #include "shell/browser/ui/cocoa/electron_ns_window.h" namespace electron { ElectronNativeWidgetMac::ElectronNativeWidgetMac( NativeWindowMac* shell, + const std::string& window_type, NSUInteger style_mask, views::internal::NativeWidgetDelegate* delegate) : views::NativeWidgetMac(delegate), shell_(shell), + window_type_(window_type), style_mask_(style_mask) {} ElectronNativeWidgetMac::~ElectronNativeWidgetMac() = default; NativeWidgetMacNSWindow* ElectronNativeWidgetMac::CreateNSWindow( const remote_cocoa::mojom::CreateWindowParams* params) { - return [[[ElectronNSWindow alloc] initWithShell:shell_ - styleMask:style_mask_] autorelease]; + if (window_type_ == "panel") { + return [[[ElectronNSPanel alloc] initWithShell:shell_ + styleMask:style_mask_] autorelease]; + } else { + return [[[ElectronNSWindow alloc] initWithShell:shell_ + styleMask:style_mask_] autorelease]; + } } } // namespace electron diff --git a/shell/browser/ui/cocoa/electron_ns_panel.h b/shell/browser/ui/cocoa/electron_ns_panel.h new file mode 100644 index 0000000000000..d33d5d25d7c8f --- /dev/null +++ b/shell/browser/ui/cocoa/electron_ns_panel.h @@ -0,0 +1,17 @@ +// Copyright (c) 2022 Microsoft, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef SHELL_BROWSER_UI_COCOA_ELECTRON_NS_PANEL_H_ +#define SHELL_BROWSER_UI_COCOA_ELECTRON_NS_PANEL_H_ + +#include "shell/browser/ui/cocoa/electron_ns_window.h" + +@interface ElectronNSPanel : ElectronNSWindow +@property NSWindowStyleMask styleMask; +@property NSWindowStyleMask originalStyleMask; +- (id)initWithShell:(electron::NativeWindowMac*)shell + styleMask:(NSUInteger)styleMask; +@end + +#endif // SHELL_BROWSER_UI_COCOA_ELECTRON_NS_PANEL_H_ diff --git a/shell/browser/ui/cocoa/electron_ns_panel.mm b/shell/browser/ui/cocoa/electron_ns_panel.mm new file mode 100644 index 0000000000000..581c142ede5ef --- /dev/null +++ b/shell/browser/ui/cocoa/electron_ns_panel.mm @@ -0,0 +1,39 @@ +// Copyright (c) 2022 Microsoft, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "shell/browser/ui/cocoa/electron_ns_panel.h" + +@implementation ElectronNSPanel + +@synthesize originalStyleMask; + +- (id)initWithShell:(electron::NativeWindowMac*)shell + styleMask:(NSUInteger)styleMask { + if (self = [super initWithShell:shell styleMask:styleMask]) { + originalStyleMask = styleMask; + } + return self; +} + +@dynamic styleMask; +// The Nonactivating mask is reserverd for NSPanel, +// but we can use this workaround to add it at runtime +- (NSWindowStyleMask)styleMask { + return originalStyleMask | NSWindowStyleMaskNonactivatingPanel; +} + +- (void)setStyleMask:(NSWindowStyleMask)styleMask { + originalStyleMask = styleMask; + // Notify change of style mask. + [super setStyleMask:styleMask]; +} + +- (void)setCollectionBehavior:(NSWindowCollectionBehavior)collectionBehavior { + NSWindowCollectionBehavior panelBehavior = + (NSWindowCollectionBehaviorCanJoinAllSpaces | + NSWindowCollectionBehaviorFullScreenAuxiliary); + [super setCollectionBehavior:collectionBehavior | panelBehavior]; +} + +@end From fc958f7d46bf57055a8521c34f6206ff665d6c9b Mon Sep 17 00:00:00 2001 From: andreiisaila Date: Thu, 2 Jun 2022 16:39:42 +0200 Subject: [PATCH 2/8] change header guard to satisfy linter --- shell/browser/ui/cocoa/electron_ns_panel.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/browser/ui/cocoa/electron_ns_panel.h b/shell/browser/ui/cocoa/electron_ns_panel.h index d33d5d25d7c8f..755271acec135 100644 --- a/shell/browser/ui/cocoa/electron_ns_panel.h +++ b/shell/browser/ui/cocoa/electron_ns_panel.h @@ -2,8 +2,8 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#ifndef SHELL_BROWSER_UI_COCOA_ELECTRON_NS_PANEL_H_ -#define SHELL_BROWSER_UI_COCOA_ELECTRON_NS_PANEL_H_ +#ifndef ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_NS_PANEL_H_ +#define ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_NS_PANEL_H_ #include "shell/browser/ui/cocoa/electron_ns_window.h" @@ -14,4 +14,4 @@ styleMask:(NSUInteger)styleMask; @end -#endif // SHELL_BROWSER_UI_COCOA_ELECTRON_NS_PANEL_H_ +#endif // ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_NS_PANEL_H_ From 6f3f80f94a7040e1d612a2a65952753bbafd437d Mon Sep 17 00:00:00 2001 From: andreiisaila Date: Thu, 2 Jun 2022 17:04:28 +0200 Subject: [PATCH 3/8] change panel wording in browser-window --- .husky/pre-commit | 4 ---- .husky/pre-push | 4 ---- docs/api/browser-window.md | 8 ++++---- 3 files changed, 4 insertions(+), 12 deletions(-) delete mode 100755 .husky/pre-commit delete mode 100755 .husky/pre-push diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index feac116af9ca6..0000000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npm run precommit \ No newline at end of file diff --git a/.husky/pre-push b/.husky/pre-push deleted file mode 100755 index 7482fdf10c359..0000000000000 --- a/.husky/pre-push +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npm run prepack diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 746e580095d6f..d2a4ef468b5e5 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -432,10 +432,10 @@ Possible values are: (`kCGDesktopWindowLevel - 1`). Note that desktop window will not receive focus, keyboard or mouse events, but you can use `globalShortcut` to receive input sparingly. - * The `panel` type sets the window level to float (`NSFloatingWindowLevel`) and - makes it appear in all spaces. The `NSWindowStyleMaskNonactivatingPanel` style - mask is added on runtime, such that the window can float on top of full-screened - apps. + * The `panel` type enables the window to float on top of full-screened apps + by adding the `NSWindowStyleMaskNonactivatingPanel` style mask,normally + reserved for NSPanel, at runtime. Also, the window will appear on all + spaces (desktops). * On Windows, possible type is `toolbar`. ### Instance Events From 6e5bc6199f091f5fb66c62a5ed918db5bf5c010d Mon Sep 17 00:00:00 2001 From: andreiisaila Date: Thu, 2 Jun 2022 17:17:33 +0200 Subject: [PATCH 4/8] Revert "change panel wording in browser-window" This reverts commit 6f3f80f94a7040e1d612a2a65952753bbafd437d. --- .husky/pre-commit | 4 ++++ .husky/pre-push | 4 ++++ docs/api/browser-window.md | 8 ++++---- 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100755 .husky/pre-commit create mode 100755 .husky/pre-push diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000000000..feac116af9ca6 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npm run precommit \ No newline at end of file diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 0000000000000..7482fdf10c359 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npm run prepack diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index d2a4ef468b5e5..746e580095d6f 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -432,10 +432,10 @@ Possible values are: (`kCGDesktopWindowLevel - 1`). Note that desktop window will not receive focus, keyboard or mouse events, but you can use `globalShortcut` to receive input sparingly. - * The `panel` type enables the window to float on top of full-screened apps - by adding the `NSWindowStyleMaskNonactivatingPanel` style mask,normally - reserved for NSPanel, at runtime. Also, the window will appear on all - spaces (desktops). + * The `panel` type sets the window level to float (`NSFloatingWindowLevel`) and + makes it appear in all spaces. The `NSWindowStyleMaskNonactivatingPanel` style + mask is added on runtime, such that the window can float on top of full-screened + apps. * On Windows, possible type is `toolbar`. ### Instance Events From 73d2d900d93c989eba6acdcbbbaa9ba6f8d6f0ff Mon Sep 17 00:00:00 2001 From: andreiisaila Date: Thu, 2 Jun 2022 17:22:24 +0200 Subject: [PATCH 5/8] change wording in browser-window --- docs/api/browser-window.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 746e580095d6f..d2a4ef468b5e5 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -432,10 +432,10 @@ Possible values are: (`kCGDesktopWindowLevel - 1`). Note that desktop window will not receive focus, keyboard or mouse events, but you can use `globalShortcut` to receive input sparingly. - * The `panel` type sets the window level to float (`NSFloatingWindowLevel`) and - makes it appear in all spaces. The `NSWindowStyleMaskNonactivatingPanel` style - mask is added on runtime, such that the window can float on top of full-screened - apps. + * The `panel` type enables the window to float on top of full-screened apps + by adding the `NSWindowStyleMaskNonactivatingPanel` style mask,normally + reserved for NSPanel, at runtime. Also, the window will appear on all + spaces (desktops). * On Windows, possible type is `toolbar`. ### Instance Events From 68839d52ca76ad888ecd7714a26165832ab9668b Mon Sep 17 00:00:00 2001 From: isailaandrei Date: Mon, 6 Jun 2022 13:28:32 +0200 Subject: [PATCH 6/8] Update shell/browser/ui/cocoa/electron_native_widget_mac.mm Co-authored-by: Cheng Zhao --- shell/browser/ui/cocoa/electron_native_widget_mac.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/browser/ui/cocoa/electron_native_widget_mac.mm b/shell/browser/ui/cocoa/electron_native_widget_mac.mm index bafaf2479d401..12a9469b92ba6 100644 --- a/shell/browser/ui/cocoa/electron_native_widget_mac.mm +++ b/shell/browser/ui/cocoa/electron_native_widget_mac.mm @@ -5,6 +5,7 @@ #include "shell/browser/ui/cocoa/electron_native_widget_mac.h" #include + #include "shell/browser/ui/cocoa/electron_ns_panel.h" #include "shell/browser/ui/cocoa/electron_ns_window.h" From 70f9ccb439cc8e2cd1350460c059dabe2c5a9502 Mon Sep 17 00:00:00 2001 From: isailaandrei Date: Mon, 6 Jun 2022 13:28:43 +0200 Subject: [PATCH 7/8] Update shell/browser/ui/cocoa/electron_native_widget_mac.h Co-authored-by: Cheng Zhao --- shell/browser/ui/cocoa/electron_native_widget_mac.h | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/browser/ui/cocoa/electron_native_widget_mac.h b/shell/browser/ui/cocoa/electron_native_widget_mac.h index 7242511fb9bd9..2e378ce0fa7e3 100644 --- a/shell/browser/ui/cocoa/electron_native_widget_mac.h +++ b/shell/browser/ui/cocoa/electron_native_widget_mac.h @@ -6,6 +6,7 @@ #define ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_NATIVE_WIDGET_MAC_H_ #include + #include "ui/views/widget/native_widget_mac.h" namespace electron { From 44b7bd95b6d5a223fed59f18a1c29d3037ef15e7 Mon Sep 17 00:00:00 2001 From: andreiisaila Date: Fri, 10 Jun 2022 14:12:16 +0100 Subject: [PATCH 8/8] Changed ScopedDisableResize class to allow for nesting --- shell/browser/native_window_mac.mm | 1 + shell/browser/ui/cocoa/electron_ns_window.h | 9 +++++---- shell/browser/ui/cocoa/electron_ns_window.mm | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index 5efe83883c442..cf13a07ba5cc5 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -829,6 +829,7 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { } void NativeWindowMac::SetResizable(bool resizable) { + ScopedDisableResize disable_resize; SetStyleMask(resizable, NSWindowStyleMaskResizable); SetCanResize(resizable); } diff --git a/shell/browser/ui/cocoa/electron_ns_window.h b/shell/browser/ui/cocoa/electron_ns_window.h index 50ad1ca8a96d2..f5d7b80b0399b 100644 --- a/shell/browser/ui/cocoa/electron_ns_window.h +++ b/shell/browser/ui/cocoa/electron_ns_window.h @@ -16,13 +16,14 @@ class NativeWindowMac; // Prevents window from resizing during the scope. class ScopedDisableResize { public: - ScopedDisableResize() { disable_resize_ = true; } - ~ScopedDisableResize() { disable_resize_ = false; } + ScopedDisableResize() { disable_resize_++; } + ~ScopedDisableResize() { disable_resize_--; } - static bool IsResizeDisabled() { return disable_resize_; } + // True if there are 1+ nested ScopedDisableResize objects in the scope + static bool IsResizeDisabled() { return disable_resize_ > 0; } private: - static bool disable_resize_; + static int disable_resize_; }; } // namespace electron diff --git a/shell/browser/ui/cocoa/electron_ns_window.mm b/shell/browser/ui/cocoa/electron_ns_window.mm index f4cc2bc5bcbf1..a8929237e4030 100644 --- a/shell/browser/ui/cocoa/electron_ns_window.mm +++ b/shell/browser/ui/cocoa/electron_ns_window.mm @@ -13,7 +13,7 @@ namespace electron { -bool ScopedDisableResize::disable_resize_ = false; +int ScopedDisableResize::disable_resize_ = 0; } // namespace electron