mirror of
https://github.com/zen-browser/desktop.git
synced 2026-03-29 03:41:51 +00:00
feat: Add native popover UI for macos, p=#12456
This commit is contained in:
@@ -20,3 +20,10 @@
|
||||
cpptype: uint32_t
|
||||
mirror: always
|
||||
type: static
|
||||
|
||||
# Enable native popovers on macOS, we've sent this patch to upstream
|
||||
# but we enable it by default anyways in case they decide to not use it,
|
||||
# or to disable it by default.
|
||||
- name: widget.macos.native-popovers
|
||||
value: true
|
||||
condition: "defined(XP_MACOSX)"
|
||||
|
||||
@@ -59,6 +59,15 @@ def main():
|
||||
output_file = os.path.join(OUTPUT_DIR, "firefox", f"{name}.patch")
|
||||
print(f"Processing Phabricator patch: {phab_id} -> {output_file}")
|
||||
download_phab_patch(phab_id, output_file)
|
||||
replaces = patch.get("replaces", {})
|
||||
for replace in replaces.keys():
|
||||
value = replaces[replace]
|
||||
with open(output_file, 'r') as f:
|
||||
content = f.read()
|
||||
if replace not in content:
|
||||
die(f"Replace string '{replace}' not found in {output_file}")
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(content.replace(replace, value))
|
||||
expected_files.add(output_file)
|
||||
elif patch.get("type") == "local":
|
||||
print(f"Local patch: {patch.get('path')}")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
<panel id="zen-folder-tabs-popup" type="arrow" orient="vertical" side="left">
|
||||
<panel id="zen-folder-tabs-popup" hidepopovertail="true" type="arrow" orient="vertical" side="left">
|
||||
<hbox class="tabs-list-header" flex="1">
|
||||
<image class="zen-folder-tabs-list-search-icon" src="chrome://global/skin/icons/search-glass.svg"/>
|
||||
<html:input id="zen-folder-tabs-list-search"
|
||||
|
||||
@@ -2,7 +2,14 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
<panel flip="side" type="arrow" popupalign="center" orient="vertical" id="PanelUI-zen-gradient-generator" position="bottomright topright" mainview="true" side="left">
|
||||
<panel flip="side" type="arrow"
|
||||
opupalign="center"
|
||||
orient="vertical"
|
||||
id="PanelUI-zen-gradient-generator"
|
||||
position="bottomright topright"
|
||||
mainview="true"
|
||||
hidepopovertail="true"
|
||||
side="left">
|
||||
<panelmultiview id="PanelUI-zen-gradient-generator-multiview" mainViewId="PanelUI-zen-gradient-generator-view">
|
||||
<panelview id="PanelUI-zen-gradient-generator-view" class="PanelUI-subView zen-theme-picker" role="document" mainview-with-header="true" has-custom-header="true">
|
||||
<hbox class="zen-theme-picker-gradient">
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
diff --git a/devtools/server/actors/animation-type-longhand.js b/devtools/server/actors/animation-type-longhand.js
|
||||
index f6cd7b4599ab74fbdc301f316fd7ecc2e2eb841c..8279a943803ca75fe0a231606ae26a678fcc0b60 100644
|
||||
--- a/devtools/server/actors/animation-type-longhand.js
|
||||
+++ b/devtools/server/actors/animation-type-longhand.js
|
||||
@@ -342,6 +342,7 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
||||
"transform-origin",
|
||||
"translate",
|
||||
"-moz-window-transform",
|
||||
+ "-zen-window-transform-origin",
|
||||
"-webkit-line-clamp",
|
||||
]),
|
||||
],
|
||||
@@ -1,50 +0,0 @@
|
||||
diff --git a/dom/base/use_counter_metrics.yaml b/dom/base/use_counter_metrics.yaml
|
||||
index 84aa1ac40d01bc73f5039bd5c589c3fdf3a6c8ce..090f9e1eef46ed45c0a98a73013ad59faeb3414f 100644
|
||||
--- a/dom/base/use_counter_metrics.yaml
|
||||
+++ b/dom/base/use_counter_metrics.yaml
|
||||
@@ -22106,6 +22106,22 @@ use.counter.css.page:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
+ css_zen_window_transform_origin:
|
||||
+ type: counter
|
||||
+ description: >
|
||||
+ Whether a page used the CSS property -zen-window-transform-origin.
|
||||
+ Compare against `use.counter.top_level_content_documents_destroyed`
|
||||
+ to calculate the rate.
|
||||
+ bugs:
|
||||
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
+ data_reviews:
|
||||
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
+ notification_emails:
|
||||
+ - dom-core@mozilla.com
|
||||
+ expires: never
|
||||
+ send_in_pings:
|
||||
+ - use-counters
|
||||
+
|
||||
css_transform_origin:
|
||||
type: counter
|
||||
description: >
|
||||
@@ -34076,6 +34092,22 @@ use.counter.css.doc:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
+ css_zen_window_transform_origin:
|
||||
+ type: counter
|
||||
+ description: >
|
||||
+ Whether a document used the CSS property -zen-window-transform-origin.
|
||||
+ Compare against `use.counter.content_documents_destroyed`
|
||||
+ to calculate the rate.
|
||||
+ bugs:
|
||||
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
+ data_reviews:
|
||||
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
+ notification_emails:
|
||||
+ - dom-core@mozilla.com
|
||||
+ expires: never
|
||||
+ send_in_pings:
|
||||
+ - use-counters
|
||||
+
|
||||
css_transform_origin:
|
||||
type: counter
|
||||
description: >
|
||||
527
src/external-patches/firefox/native_macos_popovers.patch
Normal file
527
src/external-patches/firefox/native_macos_popovers.patch
Normal file
@@ -0,0 +1,527 @@
|
||||
diff --git a/browser/components/customizableui/content/panelUI.inc.xhtml b/browser/components/customizableui/content/panelUI.inc.xhtml
|
||||
--- a/browser/components/customizableui/content/panelUI.inc.xhtml
|
||||
+++ b/browser/components/customizableui/content/panelUI.inc.xhtml
|
||||
@@ -276,10 +276,11 @@
|
||||
role="group"
|
||||
type="arrow"
|
||||
hidden="true"
|
||||
flip="slide"
|
||||
position="bottomright topright"
|
||||
+ hidepopovertail="true"
|
||||
noautofocus="true">
|
||||
<panelmultiview id="appMenu-multiView" mainViewId="appMenu-mainView"
|
||||
viewCacheId="appMenu-viewCache">
|
||||
</panelmultiview>
|
||||
</panel>
|
||||
diff --git a/layout/xul/nsMenuPopupFrame.h b/layout/xul/nsMenuPopupFrame.h
|
||||
--- a/layout/xul/nsMenuPopupFrame.h
|
||||
+++ b/layout/xul/nsMenuPopupFrame.h
|
||||
@@ -516,18 +516,10 @@
|
||||
|
||||
// Move the popup to the position specified in its |left| and |top|
|
||||
// attributes.
|
||||
void MoveToAttributePosition();
|
||||
|
||||
- // Returns true if the popup should try to remain at the same relative
|
||||
- // location as the anchor while it is open. If the anchor becomes hidden
|
||||
- // either directly or indirectly because a parent popup or other element
|
||||
- // is no longer visible, or a parent deck page is changed, the popup hides
|
||||
- // as well. The second variation also sets the anchor rectangle, relative to
|
||||
- // the popup frame.
|
||||
- bool ShouldFollowAnchor() const;
|
||||
-
|
||||
nsIFrame* GetAnchorFrame() const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Return whether the popup direction should be RTL.
|
||||
@@ -536,10 +528,18 @@
|
||||
*
|
||||
* Return whether the popup direction should be RTL.
|
||||
*/
|
||||
bool IsDirectionRTL() const;
|
||||
|
||||
+ // Returns true if the popup should try to remain at the same relative
|
||||
+ // location as the anchor while it is open. If the anchor becomes hidden
|
||||
+ // either directly or indirectly because a parent popup or other element
|
||||
+ // is no longer visible, or a parent deck page is changed, the popup hides
|
||||
+ // as well. The second variation also sets the anchor rectangle, relative to
|
||||
+ // the popup frame.
|
||||
+ bool ShouldFollowAnchor() const;
|
||||
+
|
||||
bool ShouldFollowAnchor(nsRect& aRect);
|
||||
|
||||
// Returns parent menu widget for submenus that are in the same
|
||||
// frame hierarchy, it's needed for Linux/Wayland which demands
|
||||
// strict popup windows hierarchy.
|
||||
diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml
|
||||
--- a/modules/libpref/init/StaticPrefList.yaml
|
||||
+++ b/modules/libpref/init/StaticPrefList.yaml
|
||||
@@ -19311,10 +19311,19 @@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
||||
+# If true, use native NSPopover for arrow panel popups (type="arrow") on macOS
|
||||
+# Someone like Zen browser will use this pref by default, so
|
||||
+# please take this into account when you change the behavior of
|
||||
+# native popover. Note: Only panels with type="arrow" will use NSPopover.
|
||||
+- name: widget.macos.native-popovers
|
||||
+ type: RelaxedAtomicBool
|
||||
+ value: false
|
||||
+ mirror: always
|
||||
+
|
||||
# Whether to shift by the menubar height on fullscreen mode.
|
||||
# 0: never
|
||||
# 1: always
|
||||
# 2: auto (tries to detect when it is needed)
|
||||
- name: widget.macos.shift-by-menubar-on-fullscreen
|
||||
diff --git a/toolkit/themes/shared/global-shared.css b/toolkit/themes/shared/global-shared.css
|
||||
--- a/toolkit/themes/shared/global-shared.css
|
||||
+++ b/toolkit/themes/shared/global-shared.css
|
||||
@@ -100,10 +100,19 @@
|
||||
--panel-padding: var(--arrowpanel-padding);
|
||||
--panel-shadow-margin: var(--arrowpanel-shadow-margin);
|
||||
--menuitem-border-radius: var(--arrowpanel-menuitem-border-radius);
|
||||
--menuitem-padding: var(--arrowpanel-menuitem-padding);
|
||||
--menuitem-margin: var(--arrowpanel-menuitem-margin);
|
||||
+
|
||||
+ /* stylelint-disable-next-line media-query-no-invalid */
|
||||
+ @media -moz-pref("widget.macos.native-popovers") and (-moz-platform: macos) {
|
||||
+ background-color: transparent;
|
||||
+ --panel-background: transparent;
|
||||
+ --panel-shadow: none;
|
||||
+ --panel-border-color: transparent;
|
||||
+ --panel-shadow-margin: 0px;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Lightweight theme roots */
|
||||
|
||||
:root[lwtheme] {
|
||||
diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h
|
||||
--- a/widget/cocoa/nsCocoaWindow.h
|
||||
+++ b/widget/cocoa/nsCocoaWindow.h
|
||||
@@ -133,23 +133,38 @@
|
||||
// to create its "frame view".
|
||||
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
|
||||
|
||||
@end
|
||||
|
||||
-@interface PopupWindow : BaseWindow {
|
||||
+@interface PopupWindow : BaseWindow <NSPopoverDelegate> {
|
||||
@private
|
||||
BOOL mIsContextMenu;
|
||||
+
|
||||
+ // NSPopover support for native appearance
|
||||
+ NSPopover* mPopover;
|
||||
+ NSViewController* mPopoverViewController;
|
||||
+ BOOL mUsePopover;
|
||||
}
|
||||
|
||||
- (id)initWithContentRect:(NSRect)contentRect
|
||||
styleMask:(NSUInteger)styleMask
|
||||
backing:(NSBackingStoreType)bufferingType
|
||||
defer:(BOOL)deferCreation;
|
||||
- (BOOL)isContextMenu;
|
||||
- (void)setIsContextMenu:(BOOL)flag;
|
||||
- (BOOL)canBecomeMainWindow;
|
||||
|
||||
+// NSPopover support
|
||||
+- (void)setAllowPopover;
|
||||
+- (BOOL)usePopover;
|
||||
+- (void)showPopoverRelativeToRect:(NSRect)positioningRect
|
||||
+ ofView:(NSView*)positioningView
|
||||
+ preferredEdge:(NSRectEdge)preferredEdge
|
||||
+ hiddenAnchor:(BOOL)hiddenAnchor;
|
||||
+- (void)closePopover;
|
||||
+- (void)updatePopoverContent;
|
||||
+
|
||||
@end
|
||||
|
||||
@interface BorderlessWindow : BaseWindow {
|
||||
}
|
||||
|
||||
@@ -201,10 +216,13 @@
|
||||
typedef nsIWidget Inherited;
|
||||
|
||||
public:
|
||||
nsCocoaWindow();
|
||||
|
||||
+ // Check if this window should use NSPopover for popup/menu display
|
||||
+ bool ShouldUseNSPopover() const;
|
||||
+
|
||||
[[nodiscard]] nsresult Create(nsIWidget* aParent, const DesktopIntRect& aRect,
|
||||
const InitData&) override;
|
||||
|
||||
[[nodiscard]] nsresult Create(nsIWidget* aParent,
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
--- a/widget/cocoa/nsCocoaWindow.mm
|
||||
+++ b/widget/cocoa/nsCocoaWindow.mm
|
||||
@@ -5,10 +5,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsCocoaWindow.h"
|
||||
|
||||
#include "nsArrayUtils.h"
|
||||
+#include "nsMenuPopupFrame.h"
|
||||
+#include "mozilla/dom/XULPopupElement.h"
|
||||
#include "MOZDynamicCursor.h"
|
||||
#include "nsIAppStartup.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
#include "nsILocalFileMac.h"
|
||||
#include "CocoaCompositorWidget.h"
|
||||
@@ -4958,10 +4960,15 @@
|
||||
if (mWindowType == WindowType::Popup) {
|
||||
SetPopupWindowLevel();
|
||||
mWindow.backgroundColor = NSColor.clearColor;
|
||||
mWindow.opaque = NO;
|
||||
|
||||
+ // Enable NSPopover for panel popup types when preference is enabled
|
||||
+ if ([mWindow isKindOfClass:[PopupWindow class]] && ShouldUseNSPopover()) {
|
||||
+ [(PopupWindow*)mWindow setAllowPopover];
|
||||
+ }
|
||||
+
|
||||
// When multiple spaces are in use and the browser is assigned to a
|
||||
// particular space, override the "Assign To" space and display popups on
|
||||
// the active space. Does not work with multiple displays. See
|
||||
// NeedsRecreateToReshow() for multi-display with multi-space workaround.
|
||||
mWindow.collectionBehavior = mWindow.collectionBehavior |
|
||||
@@ -5163,10 +5170,56 @@
|
||||
NS_OBJC_END_TRY_IGNORE_BLOCK;
|
||||
}
|
||||
|
||||
bool nsCocoaWindow::IsRunningAppModal() { return [NSApp _isRunningAppModal]; }
|
||||
|
||||
+static NSRectEdge AlignmentPositionToNSRectEdge(int8_t aPosition) {
|
||||
+ switch (aPosition) {
|
||||
+ case POPUPPOSITION_BEFORESTART:
|
||||
+ case POPUPPOSITION_BEFOREEND:
|
||||
+ return NSRectEdgeMaxY;
|
||||
+ case POPUPPOSITION_AFTERSTART:
|
||||
+ case POPUPPOSITION_AFTEREND:
|
||||
+ return NSRectEdgeMinY;
|
||||
+ case POPUPPOSITION_STARTBEFORE:
|
||||
+ case POPUPPOSITION_STARTAFTER:
|
||||
+ return NSRectEdgeMaxX;
|
||||
+ case POPUPPOSITION_ENDBEFORE:
|
||||
+ case POPUPPOSITION_ENDAFTER:
|
||||
+ return NSRectEdgeMinX;
|
||||
+ default:
|
||||
+ return NSRectEdgeMinY;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void SyncPopoverBounds(NSPopover* aPopover,
|
||||
+ nsMenuPopupFrame* aPopupFrame) {
|
||||
+ if (!aPopover || !aPopover.shown) {
|
||||
+ return;
|
||||
+ }
|
||||
+ NSWindow* popoverWindow = aPopover.contentViewController.view.window;
|
||||
+ if (!popoverWindow) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // Synchronizing the internal bounds with the actual bounds
|
||||
+ // that macOS calculated
|
||||
+ NSView* contentView = popoverWindow.contentView;
|
||||
+ NSRect contentFrame = [contentView convertRect:contentView.bounds toView:nil];
|
||||
+ NSRect windowFrame = [popoverWindow convertRectToScreen:contentFrame];
|
||||
+ NSScreen* screen = [popoverWindow screen];
|
||||
+
|
||||
+ if (screen) {
|
||||
+ // Inverting the y axis. We convert from a cocoa point to a css point
|
||||
+ CGFloat screenHeight = screen.frame.size.height;
|
||||
+ mozilla::CSSPoint cssPos(
|
||||
+ windowFrame.origin.x,
|
||||
+ screenHeight - windowFrame.origin.y - windowFrame.size.height);
|
||||
+ aPopupFrame->MoveTo(cssPos, false);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// Hide or show this window
|
||||
void nsCocoaWindow::Show(bool aState) {
|
||||
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
|
||||
|
||||
if (!mWindow) {
|
||||
@@ -5227,10 +5280,58 @@
|
||||
mWindow.contentView.needsDisplay = YES;
|
||||
if (!nativeParentWindow || mPopupLevel != PopupLevel::Parent) {
|
||||
[mWindow orderFront:nil];
|
||||
}
|
||||
NS_OBJC_END_TRY_IGNORE_BLOCK;
|
||||
+ nsMenuPopupFrame* popupFrame = GetPopupFrame();
|
||||
+ if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
||||
+ [(PopupWindow*)mWindow usePopover] && popupFrame &&
|
||||
+ popupFrame->ShouldFollowAnchor()) {
|
||||
+ if (nativeParentWindow) {
|
||||
+ NSRectEdge preferredEdge =
|
||||
+ AlignmentPositionToNSRectEdge(popupFrame->GetAlignmentPosition());
|
||||
+ nsRect anchorRectAppUnits = popupFrame->GetUntransformedAnchorRect();
|
||||
+ mozilla::CSSIntRect cssAnchorRect =
|
||||
+ mozilla::CSSIntRect::FromAppUnitsRounded(anchorRectAppUnits);
|
||||
+ mozilla::LayoutDeviceIntRect layoutRect =
|
||||
+ mozilla::LayoutDeviceIntRect::FromUnknownRect(
|
||||
+ (cssAnchorRect.ToUnknownRect()));
|
||||
+ mozilla::DesktopIntRect popupAnchorRectScaled =
|
||||
+ mozilla::DesktopIntRect::RoundOut(layoutRect.X(), layoutRect.Y(),
|
||||
+ layoutRect.Width(),
|
||||
+ layoutRect.Height());
|
||||
+ // Taking the now correctly scaled anchor rect and turning it into a
|
||||
+ // gecko rect this accounts for the y-axis inversion that cocoa needs,
|
||||
+ // as the origin is in the bottom left. This rect is in screen space
|
||||
+ NSRect cocoaScreenRect =
|
||||
+ nsCocoaUtils::GeckoRectToCocoaRect(popupAnchorRectScaled);
|
||||
+ // We take the screen space rect and convert it to window space
|
||||
+ // coordinates, as NSPopover requires the coordinates to be in view
|
||||
+ // space and inside the view. If the coordinates are outside our view,
|
||||
+ // the popover will fail silently
|
||||
+ NSRect windowRect =
|
||||
+ [nativeParentWindow convertRectFromScreen:cocoaScreenRect];
|
||||
+ NSView* parentView = [nativeParentWindow contentView];
|
||||
+ // We take the window space rect and convert it to view space for the
|
||||
+ // specific parent view
|
||||
+ NSRect positioningRect = [parentView convertRect:windowRect
|
||||
+ fromView:nil];
|
||||
+ BOOL shouldHideAnchor = NO;
|
||||
+ if (auto popoverElement = GetPopupFrame()) {
|
||||
+ auto& element = popoverElement->PopupElement();
|
||||
+ if (element.GetBoolAttr(nsGkAtoms::hidepopovertail)) {
|
||||
+ shouldHideAnchor = YES;
|
||||
+ }
|
||||
+ }
|
||||
+ [(PopupWindow*)mWindow showPopoverRelativeToRect:positioningRect
|
||||
+ ofView:parentView
|
||||
+ preferredEdge:preferredEdge
|
||||
+ hiddenAnchor:shouldHideAnchor];
|
||||
+ SyncPopoverBounds([(PopupWindow*)mWindow popover], popupFrame);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
// If our popup window is a non-native context menu, tell the OS (and
|
||||
// other programs) that a menu has opened. This is how the OS knows to
|
||||
// close other programs' context menus when ours open.
|
||||
if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
||||
[(PopupWindow*)mWindow isContextMenu]) {
|
||||
@@ -5301,10 +5402,15 @@
|
||||
// of a window it hides the parent window.
|
||||
if (mWindowType == WindowType::Popup && nativeParentWindow) {
|
||||
[nativeParentWindow removeChildWindow:mWindow];
|
||||
}
|
||||
|
||||
+ // Handle NSPopover hiding or traditional window hiding
|
||||
+ if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
||||
+ [(PopupWindow*)mWindow usePopover]) {
|
||||
+ [(PopupWindow*)mWindow closePopover];
|
||||
+ }
|
||||
[mWindow orderOut:nil];
|
||||
// If our popup window is a non-native context menu, tell the OS (and
|
||||
// other programs) that a menu has closed.
|
||||
if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
||||
[(PopupWindow*)mWindow isContextMenu]) {
|
||||
@@ -5351,10 +5457,17 @@
|
||||
return false;
|
||||
}
|
||||
return nsIWidget::ShouldUseOffMainThreadCompositing();
|
||||
}
|
||||
|
||||
+bool nsCocoaWindow::ShouldUseNSPopover() const {
|
||||
+ // Use NSPopover for panel popups when the preference is enabled
|
||||
+ // But not for detached popups - they should use traditional window logic
|
||||
+ return mWindowType == WindowType::Popup && mPopupType == PopupType::Panel &&
|
||||
+ mozilla::StaticPrefs::widget_macos_native_popovers();
|
||||
+}
|
||||
+
|
||||
TransparencyMode nsCocoaWindow::GetTransparencyMode() {
|
||||
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
|
||||
|
||||
return mWindow.isOpaque ? TransparencyMode::Opaque
|
||||
: TransparencyMode::Transparent;
|
||||
@@ -6313,10 +6426,20 @@
|
||||
// We ignore aRepaint -- we have to call display:YES, otherwise the
|
||||
// title bar doesn't immediately get repainted and is displayed in
|
||||
// the wrong place, leading to a visual jump.
|
||||
[mWindow setFrame:newFrame display:YES];
|
||||
|
||||
+ if (ShouldUseNSPopover() && [(PopupWindow*)mWindow usePopover]) {
|
||||
+ [(PopupWindow*)mWindow updatePopoverContent];
|
||||
+ // A popover won't resize by setting the frame
|
||||
+ // as it's size is calculated based on the content size
|
||||
+ // Therefor the content size has to be changed as well
|
||||
+ NSSize contentSize = NSMakeSize(aWidth, aHeight);
|
||||
+ [[(PopupWindow*)mWindow popover] setContentSize:contentSize];
|
||||
+ SyncPopoverBounds([(PopupWindow*)mWindow popover], GetPopupFrame());
|
||||
+ }
|
||||
+
|
||||
NS_OBJC_END_TRY_IGNORE_BLOCK;
|
||||
}
|
||||
|
||||
void nsCocoaWindow::Resize(const DesktopRect& aRect, bool aRepaint) {
|
||||
DoResize(aRect.x, aRect.y, aRect.width, aRect.height, aRepaint, false);
|
||||
@@ -8277,18 +8400,27 @@
|
||||
backing:(NSBackingStoreType)bufferingType
|
||||
defer:(BOOL)deferCreation {
|
||||
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
|
||||
|
||||
mIsContextMenu = false;
|
||||
+ mPopover = nil;
|
||||
+ mPopoverViewController = nil;
|
||||
+ mUsePopover = NO;
|
||||
return [super initWithContentRect:contentRect
|
||||
styleMask:styleMask
|
||||
backing:bufferingType
|
||||
defer:deferCreation];
|
||||
|
||||
NS_OBJC_END_TRY_BLOCK_RETURN(nil);
|
||||
}
|
||||
|
||||
+- (void)dealloc {
|
||||
+ [mPopover release];
|
||||
+ [mPopoverViewController release];
|
||||
+ [super dealloc];
|
||||
+}
|
||||
+
|
||||
// Override the private API _backdropBleedAmount. This determines how much the
|
||||
// desktop wallpaper contributes to the vibrancy backdrop.
|
||||
// Return 0 in order to match what the system does for sheet windows and
|
||||
// _NSPopoverWindows.
|
||||
- (CGFloat)_backdropBleedAmount {
|
||||
@@ -8342,10 +8474,120 @@
|
||||
|
||||
- (void)setIsContextMenu:(BOOL)flag {
|
||||
mIsContextMenu = flag;
|
||||
}
|
||||
|
||||
+- (void)setAllowPopover {
|
||||
+ mUsePopover = YES;
|
||||
+
|
||||
+ if (!mPopover) {
|
||||
+ mPopover = [[NSPopover alloc] init];
|
||||
+
|
||||
+ // Use NSPopoverBehaviorApplicationDefined to prevent auto-closing
|
||||
+ // when other popovers are opened, and to respect the disable_autohide
|
||||
+ // preference
|
||||
+ mPopover.behavior = NSPopoverBehaviorApplicationDefined;
|
||||
+ mPopover.delegate = self;
|
||||
+
|
||||
+ // Create view controller that will contain our content view
|
||||
+ mPopoverViewController = [[NSViewController alloc] init];
|
||||
+
|
||||
+ NSView* contentView = self.contentView;
|
||||
+ if (contentView) {
|
||||
+ // Ensure the content view is properly configured
|
||||
+ [contentView
|
||||
+ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
+
|
||||
+ mPopoverViewController.view = contentView;
|
||||
+ mPopover.contentViewController = mPopoverViewController;
|
||||
+
|
||||
+ // Set popover size to match our window content size
|
||||
+ NSRect contentRect = [contentView frame];
|
||||
+ if (contentRect.size.width > 0 && contentRect.size.height > 0) {
|
||||
+ [mPopover setContentSize:contentRect.size];
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+- (BOOL)usePopover {
|
||||
+ return mUsePopover && !mIsContextMenu;
|
||||
+}
|
||||
+
|
||||
+- (void)showPopoverRelativeToRect:(NSRect)positioningRect
|
||||
+ ofView:(NSView*)positioningView
|
||||
+ preferredEdge:(NSRectEdge)preferredEdge
|
||||
+ hiddenAnchor:(BOOL)hiddenAnchor {
|
||||
+ NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
|
||||
+ if (!mPopover) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // Close existing popover if it's already shown
|
||||
+ if (mPopover.shown) {
|
||||
+ [mPopover close];
|
||||
+ }
|
||||
+
|
||||
+ // Force content update before showing
|
||||
+ [self updatePopoverContent];
|
||||
+
|
||||
+ if (mPopoverViewController.view) {
|
||||
+ mPopover.behavior = NSPopoverBehaviorApplicationDefined;
|
||||
+
|
||||
+ // This is a hidden API that prevents the popover from showing its arrow
|
||||
+ // pointing to the anchor.
|
||||
+ [mPopover setShouldHideAnchor:hiddenAnchor];
|
||||
+
|
||||
+ [mPopover showRelativeToRect:positioningRect
|
||||
+ ofView:positioningView
|
||||
+ preferredEdge:preferredEdge];
|
||||
+ }
|
||||
+
|
||||
+ NSWindow* popoverWindow = mPopover.contentViewController.view.window;
|
||||
+ [popoverWindow setAcceptsMouseMovedEvents:YES];
|
||||
+
|
||||
+ NS_OBJC_END_TRY_IGNORE_BLOCK;
|
||||
+}
|
||||
+
|
||||
+- (void)closePopover {
|
||||
+ NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
|
||||
+
|
||||
+ if (mPopover && mPopover.shown) {
|
||||
+ [mPopover close];
|
||||
+ }
|
||||
+
|
||||
+ NS_OBJC_END_TRY_IGNORE_BLOCK;
|
||||
+}
|
||||
+
|
||||
+- (void)updatePopoverContent {
|
||||
+ NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
|
||||
+
|
||||
+ if (mPopover && mPopoverViewController) {
|
||||
+ NSView* contentView = self.contentView;
|
||||
+ if (contentView) {
|
||||
+ // Ensure proper hit testing for hover events
|
||||
+ [contentView setWantsLayer:YES];
|
||||
+ [contentView setAcceptsTouchEvents:YES];
|
||||
+
|
||||
+ // Update the popover content view to match current window content
|
||||
+ mPopoverViewController.view = contentView;
|
||||
+
|
||||
+ // Update popover size to match content
|
||||
+ NSRect contentRect = [contentView frame];
|
||||
+ if (contentRect.size.width > 0 && contentRect.size.height > 0) {
|
||||
+ mPopover.contentSize = contentRect.size;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ NS_OBJC_END_TRY_IGNORE_BLOCK;
|
||||
+}
|
||||
+
|
||||
+- (NSPopover*)popover {
|
||||
+ return mPopover;
|
||||
+}
|
||||
+
|
||||
- (BOOL)canBecomeMainWindow {
|
||||
// This is overriden because the default is 'yes' when a titlebar is present.
|
||||
return NO;
|
||||
}
|
||||
|
||||
diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py
|
||||
--- a/xpcom/ds/StaticAtoms.py
|
||||
+++ b/xpcom/ds/StaticAtoms.py
|
||||
@@ -535,10 +535,11 @@
|
||||
Atom("hgroup", "hgroup"),
|
||||
Atom("hidden", "hidden"),
|
||||
Atom("hidechrome", "hidechrome"),
|
||||
Atom("hidecolumnpicker", "hidecolumnpicker"),
|
||||
Atom("hidetitlebarseparator", "hidetitlebarseparator"),
|
||||
+ Atom("hidepopovertail", "hidepopovertail"),
|
||||
Atom("hide_popover", "hide-popover"),
|
||||
Atom("high", "high"),
|
||||
Atom("highest", "highest"),
|
||||
Atom("horizontal", "horizontal"),
|
||||
Atom("hover", "hover"),
|
||||
|
||||
@@ -7,6 +7,16 @@
|
||||
"id": "D279007",
|
||||
"name": "Fix MacOS Crash on Shutdown Firefox 149"
|
||||
},
|
||||
{
|
||||
"type": "phabricator",
|
||||
"id": "D284084",
|
||||
"name": "Native MacOS popovers",
|
||||
"replaces": {
|
||||
// The patch we sent was for firefox 149, but we are currently in 148, so theres
|
||||
// a conflict in the patch. See https://bugzilla.mozilla.org/show_bug.cgi?id=2015354
|
||||
"overridden": "overriden"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "local",
|
||||
"path": "firefox/no_liquid_glass_icon.patch"
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp
|
||||
index 67ae256038fae1d61824d58f5e544f65505a1ed5..b6e70376f1d9230df9beb01216092969e9322c8f 100644
|
||||
--- a/layout/generic/nsIFrame.cpp
|
||||
+++ b/layout/generic/nsIFrame.cpp
|
||||
@@ -11973,6 +11973,11 @@ gfx::Matrix nsIFrame::ComputeWidgetTransform() const {
|
||||
gfx::Matrix4x4 matrix = nsStyleTransformMatrix::ReadTransforms(
|
||||
uiReset->mMozWindowTransform, refBox, float(appUnitsPerDevPixel));
|
||||
|
||||
+ const StyleTransformOrigin& origin = uiReset->mWindowTransformOrigin;
|
||||
+ Point transformOrigin = nsStyleTransformMatrix::Convert2DPosition(
|
||||
+ origin.horizontal, origin.vertical, refBox, appUnitsPerDevPixel);
|
||||
+ matrix.ChangeBasis(Point3D(transformOrigin.x, transformOrigin.y, 0));
|
||||
+
|
||||
gfx::Matrix result2d;
|
||||
if (!matrix.CanDraw2D(&result2d)) {
|
||||
// FIXME: It would be preferable to reject non-2D transforms at parse time.
|
||||
@@ -1,22 +0,0 @@
|
||||
diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp
|
||||
index e5883b377afee44626a2928a97205382e6d07e40..57ae3b0567fbd7afbcfb60a2cd662f611339e5ad 100644
|
||||
--- a/layout/style/nsStyleStruct.cpp
|
||||
+++ b/layout/style/nsStyleStruct.cpp
|
||||
@@ -3287,6 +3287,9 @@ nsStyleUIReset::nsStyleUIReset()
|
||||
mWindowShadow(StyleWindowShadow::Auto),
|
||||
mWindowOpacity(1.0),
|
||||
mMozWindowInputRegionMargin(StyleLength::Zero()),
|
||||
+ mWindowTransformOrigin{LengthPercentage::FromPercentage(0.5),
|
||||
+ LengthPercentage::FromPercentage(0.5),
|
||||
+ {0.}},
|
||||
mTransitions(
|
||||
nsStyleAutoArray<StyleTransition>::WITH_SINGLE_INITIAL_ELEMENT),
|
||||
mTransitionTimingFunctionCount(1),
|
||||
@@ -3331,6 +3334,7 @@ nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource)
|
||||
mWindowOpacity(aSource.mWindowOpacity),
|
||||
mMozWindowInputRegionMargin(aSource.mMozWindowInputRegionMargin),
|
||||
mMozWindowTransform(aSource.mMozWindowTransform),
|
||||
+ mWindowTransformOrigin(aSource.mWindowTransformOrigin),
|
||||
mTransitions(aSource.mTransitions.Clone()),
|
||||
mTransitionTimingFunctionCount(aSource.mTransitionTimingFunctionCount),
|
||||
mTransitionDurationCount(aSource.mTransitionDurationCount),
|
||||
@@ -1,12 +0,0 @@
|
||||
diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h
|
||||
index 14c24446880b7342f6c194bb068f5fd54657ec85..8a0067b2694029242a0fbe6d806b1dd0153f1715 100644
|
||||
--- a/layout/style/nsStyleStruct.h
|
||||
+++ b/layout/style/nsStyleStruct.h
|
||||
@@ -2094,6 +2094,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset {
|
||||
// The margin of the window region that should be transparent to events.
|
||||
mozilla::StyleLength mMozWindowInputRegionMargin;
|
||||
mozilla::StyleTransform mMozWindowTransform;
|
||||
+ mozilla::StyleTransformOrigin mWindowTransformOrigin;
|
||||
|
||||
nsStyleAutoArray<mozilla::StyleTransition> mTransitions;
|
||||
// The number of elements in mTransitions that are not from repeating
|
||||
@@ -1,12 +0,0 @@
|
||||
diff --git a/layout/style/test/ListCSSProperties.cpp b/layout/style/test/ListCSSProperties.cpp
|
||||
index 1870bfc3735255f2d41356b00dc52faf95d9d9f2..59ad4fb11c7d48d9ba84dceef09a67a42b486ed8 100644
|
||||
--- a/layout/style/test/ListCSSProperties.cpp
|
||||
+++ b/layout/style/test/ListCSSProperties.cpp
|
||||
@@ -110,6 +110,7 @@ const char* gInaccessibleProperties[] = {
|
||||
"-moz-window-opacity", // chrome-only internal properties
|
||||
"-moz-window-transform", // chrome-only internal properties
|
||||
"-moz-window-shadow", // chrome-only internal properties
|
||||
+ "-zen-window-transform-origin", // chrome-only internal properties
|
||||
};
|
||||
|
||||
inline int is_inaccessible(const char* aPropName) {
|
||||
@@ -1,23 +0,0 @@
|
||||
diff --git a/servo/components/style/properties/longhands/ui.mako.rs b/servo/components/style/properties/longhands/ui.mako.rs
|
||||
index 24e1e1b7e8fe4d4b70aaa4f5f022500c3dcfcbae..1176bf5d12885b4d96abb2f72288f6c631072578 100644
|
||||
--- a/servo/components/style/properties/longhands/ui.mako.rs
|
||||
+++ b/servo/components/style/properties/longhands/ui.mako.rs
|
||||
@@ -284,6 +284,18 @@ ${helpers.predefined_type(
|
||||
affects="",
|
||||
)}
|
||||
|
||||
+${helpers.predefined_type(
|
||||
+ "-zen-window-transform-origin",
|
||||
+ "TransformOrigin",
|
||||
+ "computed::TransformOrigin::initial_value()",
|
||||
+ engines="gecko",
|
||||
+ gecko_ffi_name="mWindowTransformOrigin",
|
||||
+ boxed=True,
|
||||
+ spec="None (Nonstandard internal property)",
|
||||
+ enabled_in="chrome",
|
||||
+ affects="overflow",
|
||||
+)}
|
||||
+
|
||||
${helpers.predefined_type(
|
||||
"animation-fill-mode",
|
||||
"AnimationFillMode",
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/toolkit/themes/shared/popup.css b/toolkit/themes/shared/popup.css
|
||||
index c2618b86d7e8bb71f9f7f71ef9916c8140ca1ead..96a602f9cbfb77ee0a52151ce8ccf7ba17cf5c43 100644
|
||||
index c2618b86d7e8bb71f9f7f71ef9916c8140ca1ead..9e2006015e22f1ac043c46066c4c9a85fe053a21 100644
|
||||
--- a/toolkit/themes/shared/popup.css
|
||||
+++ b/toolkit/themes/shared/popup.css
|
||||
@@ -22,8 +22,8 @@ panel {
|
||||
@@ -13,24 +13,3 @@ index c2618b86d7e8bb71f9f7f71ef9916c8140ca1ead..96a602f9cbfb77ee0a52151ce8ccf7ba
|
||||
-moz-window-input-region-margin: var(--panel-shadow-margin);
|
||||
margin: calc(-1 * var(--panel-shadow-margin));
|
||||
|
||||
@@ -143,11 +143,7 @@ panel[type="arrow"] {
|
||||
-moz-window-transform,
|
||||
-moz-window-opacity;
|
||||
@media not (prefers-reduced-motion) {
|
||||
- -moz-window-transform: translateY(-70px);
|
||||
-
|
||||
- &:where([side="bottom"]) {
|
||||
- -moz-window-transform: translateY(70px);
|
||||
- }
|
||||
+ -moz-window-transform: scale(0);
|
||||
}
|
||||
/* Only do the fade-in animation on pre-Big Sur to avoid missing shadows on
|
||||
* Big Sur+, see bug 1672091. */
|
||||
@@ -161,7 +157,6 @@ panel[type="arrow"] {
|
||||
}
|
||||
|
||||
&[animate="cancel"] {
|
||||
- -moz-window-transform: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,38 +3,6 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
panel[type="arrow"] {
|
||||
@media (-moz-platform: macos) and (-moz-panel-animations) {
|
||||
&[side="bottom"] {
|
||||
/* Animate from the bottom */
|
||||
-zen-window-transform-origin: 0 100%;
|
||||
}
|
||||
&[side="left"] {
|
||||
/* Animate from the left and center */
|
||||
-zen-window-transform-origin: 0 50%;
|
||||
}
|
||||
&[side="right"] {
|
||||
/* Animate from the right */
|
||||
-zen-window-transform-origin: 100% 50%;
|
||||
}
|
||||
:root[zen-right-side="true"] & {
|
||||
/* Animate from the right */
|
||||
-zen-window-transform-origin: 100% 0;
|
||||
&[side="bottom"] {
|
||||
/* Animate from the bottom right */
|
||||
-zen-window-transform-origin: 100% 100%;
|
||||
}
|
||||
&[side="left"] {
|
||||
/* Animate from the right */
|
||||
-zen-window-transform-origin: 100% 50%;
|
||||
}
|
||||
&[side="right"] {
|
||||
/* Animate from the right */
|
||||
-zen-window-transform-origin: 100% 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menupopup,
|
||||
panel[type="arrow"]:not(#feature-callout) {
|
||||
@@ -62,12 +30,6 @@ panel[type="arrow"]:not(#feature-callout) {
|
||||
}
|
||||
|
||||
@media (-moz-platform: macos) {
|
||||
appearance: auto !important;
|
||||
-moz-default-appearance: menupopup;
|
||||
/* We set the default background here, rather than on ::part(content),
|
||||
* because otherwise it'd interfere with the native look. Non-native-looking
|
||||
* popups should get their background via --panel-background */
|
||||
background-color: Menu;
|
||||
--panel-shadow-margin: 0px !important;
|
||||
--panel-background: transparent !important;
|
||||
--panel-border-color: transparent;
|
||||
|
||||
Reference in New Issue
Block a user