From 5c37a0a9d4e18be29c77aeeedd2b46b414c0edf3 Mon Sep 17 00:00:00 2001 From: jakubiakdev Date: Sun, 10 May 2026 23:26:52 +0200 Subject: [PATCH] no-bug: Improve flaky URLBar scrolling (gh-13645) Co-authored-by: mr. m --- .../urlbar/UrlbarValueFormatter-sys-mjs.patch | 29 +++++++++-- .../themes/shared/urlbar-searchbar-css.patch | 15 +++++- .../D284084.patch} | 0 .../native_macos_popovers/D299584.patch | 51 +++++++++++++++++++ src/external-patches/manifest.json | 9 +++- src/zen/common/modules/ZenUIManager.mjs | 5 -- 6 files changed, 97 insertions(+), 12 deletions(-) rename src/external-patches/firefox/{native_macos_popovers.patch => native_macos_popovers/D284084.patch} (100%) create mode 100644 src/external-patches/firefox/native_macos_popovers/D299584.patch diff --git a/src/browser/components/urlbar/UrlbarValueFormatter-sys-mjs.patch b/src/browser/components/urlbar/UrlbarValueFormatter-sys-mjs.patch index 469665532..d5826627d 100644 --- a/src/browser/components/urlbar/UrlbarValueFormatter-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarValueFormatter-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/urlbar/UrlbarValueFormatter.sys.mjs b/browser/components/urlbar/UrlbarValueFormatter.sys.mjs -index f28d277764158566bc9406ce0e6160d92d346a63..82dd5f8568ec1b12e87676e5c2b243824628b5af 100644 +index f28d277764158566bc9406ce0e6160d92d346a63..aee17083999f99670c2de7b47cb917e400da86a6 100644 --- a/browser/components/urlbar/UrlbarValueFormatter.sys.mjs +++ b/browser/components/urlbar/UrlbarValueFormatter.sys.mjs @@ -77,7 +77,7 @@ export class UrlbarValueFormatter { @@ -11,7 +11,30 @@ index f28d277764158566bc9406ce0e6160d92d346a63..82dd5f8568ec1b12e87676e5c2b24382 }); } -@@ -371,7 +371,7 @@ export class UrlbarValueFormatter { +@@ -105,6 +105,22 @@ export class UrlbarValueFormatter { + } + + #ensureFormattedHostVisible(urlMetaData) { ++ // Make sure the domain is visible even with long subdomains when the single sidebar is being used ++ if ( ++ this.#window.gZenVerticalTabsManager?._hasSetSingleToolbar ++ && Services.prefs.getBoolPref("zen.urlbar.show-domain-only-in-sidebar") ++ ) { ++ const hoverAttr = "zen-has-implicit-hover"; ++ const hasHover = this.#window.gNavToolbox.hasAttribute(hoverAttr); ++ this.#window.gNavToolbox.removeAttribute(hoverAttr); ++ ++ this.#inputField.scrollLeft = this.#inputField.scrollLeftMax; ++ ++ if (hasHover) { ++ this.#window.gNavToolbox.setAttribute(hoverAttr, true); ++ } ++ return; ++ } + // Make sure the host is always visible. Since it is aligned on + // the first strong directional character, we set scrollLeft + // appropriately to ensure the domain stays visible in case of an +@@ -371,7 +387,7 @@ export class UrlbarValueFormatter { * @returns {boolean} * True if formatting was applied and false if not. */ @@ -20,7 +43,7 @@ index f28d277764158566bc9406ce0e6160d92d346a63..82dd5f8568ec1b12e87676e5c2b24382 let urlMetaData = this.#getUrlMetaData(); if (!urlMetaData) { return false; -@@ -640,6 +640,7 @@ export class UrlbarValueFormatter { +@@ -640,6 +656,7 @@ export class UrlbarValueFormatter { this.#window.requestAnimationFrame(() => { if (instance == this.#resizeInstance) { this.#ensureFormattedHostVisible(); diff --git a/src/browser/themes/shared/urlbar-searchbar-css.patch b/src/browser/themes/shared/urlbar-searchbar-css.patch index 8f644678a..9e8591778 100644 --- a/src/browser/themes/shared/urlbar-searchbar-css.patch +++ b/src/browser/themes/shared/urlbar-searchbar-css.patch @@ -1,5 +1,5 @@ diff --git a/browser/themes/shared/urlbar-searchbar.css b/browser/themes/shared/urlbar-searchbar.css -index 0ee35cfe67c9bce37a844d4b7d9715d4fb50f709..5cdb8037e49a68ea4126af349690af8a16b5e59b 100644 +index 0ee35cfe67c9bce37a844d4b7d9715d4fb50f709..034cf876c8cef5a2b4c0ca5f209d127dbfc90b20 100644 --- a/browser/themes/shared/urlbar-searchbar.css +++ b/browser/themes/shared/urlbar-searchbar.css @@ -10,7 +10,7 @@ @@ -20,7 +20,18 @@ index 0ee35cfe67c9bce37a844d4b7d9715d4fb50f709..5cdb8037e49a68ea4126af349690af8a } /* Document Picture-in-Picture API window */ -@@ -333,10 +333,14 @@ toolbar[inactive="true"] .urlbar, +@@ -200,6 +200,10 @@ toolbar[inactive="true"] .urlbar, + .urlbar:not([focused])[textoverflow="left"][domaindir="rtl"] > .urlbar-input-container > .urlbar-input-box > & { + mask-image: linear-gradient(to right, transparent var(--urlbar-scheme-size), black calc(var(--urlbar-scheme-size) + 3ch)); + } ++ ++ #navigator-toolbox[zen-has-implicit-hover="true"] .urlbar:not([focused])[textoverflow="left"] > .urlbar-input-container > .urlbar-input-box > & { ++ mask-image: linear-gradient(to right, transparent, black 3ch, black calc(100% - 3ch), transparent); ++ } + } + + #urlbar-scheme { +@@ -333,10 +337,14 @@ toolbar[inactive="true"] .urlbar, .urlbar[breakout][breakout-extend] { height: auto; diff --git a/src/external-patches/firefox/native_macos_popovers.patch b/src/external-patches/firefox/native_macos_popovers/D284084.patch similarity index 100% rename from src/external-patches/firefox/native_macos_popovers.patch rename to src/external-patches/firefox/native_macos_popovers/D284084.patch diff --git a/src/external-patches/firefox/native_macos_popovers/D299584.patch b/src/external-patches/firefox/native_macos_popovers/D299584.patch new file mode 100644 index 000000000..a729c092c --- /dev/null +++ b/src/external-patches/firefox/native_macos_popovers/D299584.patch @@ -0,0 +1,51 @@ +diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h +--- a/widget/cocoa/nsCocoaWindow.h ++++ b/widget/cocoa/nsCocoaWindow.h +@@ -140,10 +140,11 @@ + + // NSPopover support for native appearance + NSPopover* mPopover; + NSViewController* mPopoverViewController; + BOOL mUsePopover; ++ NSRect mLastPopoverRect; + } + + - (id)initWithContentRect:(NSRect)contentRect + styleMask:(NSUInteger)styleMask + backing:(NSBackingStoreType)bufferingType +diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm +--- a/widget/cocoa/nsCocoaWindow.mm ++++ b/widget/cocoa/nsCocoaWindow.mm +@@ -5597,11 +5597,10 @@ + return false; + } + nsMenuPopupFrame* popupFrame = GetPopupFrame(); + return [mWindow isKindOfClass:[PopupWindow class]] && + [(PopupWindow*)mWindow usePopover] && popupFrame && +- popupFrame->ShouldFollowAnchor() && + !popupFrame->PopupElement().GetBoolAttr(nsGkAtoms::nonnativepopover); + } + + TransparencyMode nsCocoaWindow::GetTransparencyMode() { + NS_OBJC_BEGIN_TRY_BLOCK_RETURN; +@@ -8775,10 +8774,19 @@ + NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; + if (!mPopover) { + return; + } + ++ if (!positioningRect.size.width && !positioningRect.size.height && ++ mLastPopoverRect.size.width && mLastPopoverRect.size.height) { ++ // Sometimes, specially when downloading addons from unofficial sources, ++ // the popover is shown in a very fast motion and the positioningRect is ++ // empty. ++ positioningRect = mLastPopoverRect; ++ } ++ mLastPopoverRect = positioningRect; ++ + // Close existing popover if it's already shown + if (mPopover.shown) { + [mPopover close]; + } + + diff --git a/src/external-patches/manifest.json b/src/external-patches/manifest.json index 62bc49c6d..f3f3b6318 100644 --- a/src/external-patches/manifest.json +++ b/src/external-patches/manifest.json @@ -4,7 +4,10 @@ [ { "type": "phabricator", - "id": "D284084", + "ids": [ + "D284084", + "D299584" + ], "name": "Native MacOS popovers", "replaces": { // Specifically trying to target FeatureCallout.sys.mjs's change. @@ -22,7 +25,9 @@ " #include \"nsISupportsPrimitives.h\"\n": "", " Atom(\"nonnative\", \"nonnative\"),\n": "", - "Atom(\"noscript\", \"noscript\"),": "Atom(\"noscript\", \"noscript\"),\n Atom(\"noshade\", \"noshade\")," + "Atom(\"noscript\", \"noscript\"),": "Atom(\"noscript\", \"noscript\"),\n Atom(\"noshade\", \"noshade\"),", + + "GetBoolAttr(nsGkAtoms::nonnative)": "GetBoolAttr(nsGkAtoms::nonnativepopover)" } }, { diff --git a/src/zen/common/modules/ZenUIManager.mjs b/src/zen/common/modules/ZenUIManager.mjs index ef46848e6..d400d98c1 100644 --- a/src/zen/common/modules/ZenUIManager.mjs +++ b/src/zen/common/modules/ZenUIManager.mjs @@ -698,11 +698,6 @@ window.gZenUIManager = { this.urlbarShowDomainOnly ) { let url = BrowserUIUtils.removeSingleTrailingSlashFromURL(aURL); - requestIdleCallback(() => { - // Scroll the urlbar all the way to the right so that - // the domain is always visible when the url is too long. - gURLBar.inputField.scrollLeft = gURLBar.inputField.scrollWidth; - }); let stripped = url.startsWith("https://") ? url.split("/")[2] : url; if (stripped.startsWith("www.")) { stripped = stripped.substring(4);