diff --git a/prefs/zen/view.yaml b/prefs/zen/view.yaml index fc433c617..3cb5c0338 100644 --- a/prefs/zen/view.yaml +++ b/prefs/zen/view.yaml @@ -50,7 +50,7 @@ value: true - name: zen.view.drag-window-from-content.height-percentage - value: 10 + value: 5 - name: zen.view.borderless-fullscreen value: true diff --git a/src/zen/common/styles/zen-theme.css b/src/zen/common/styles/zen-theme.css index 345453e5b..15d632dea 100644 --- a/src/zen/common/styles/zen-theme.css +++ b/src/zen/common/styles/zen-theme.css @@ -262,7 +262,7 @@ light-dark(white, black) ); --zen-sidebar-notification-shadow: 0 0 6px light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.3)); - --zen-sidebar-notification-outline: 1px solid light-dark(transparent, rgba(255, 255, 255, 0.15)); + --zen-sidebar-notification-outline: 1px solid light-dark(transparent, rgba(255, 255, 255, 0.1)); --zen-sidebar-themed-icon-fill: light-dark(color-mix(in srgb, var(--zen-primary-color) 50%, black), color-mix(in srgb, var(--zen-colors-primary) 15%, #ebebeb)); diff --git a/src/zen/media/ZenMediaController.mjs b/src/zen/media/ZenMediaController.mjs index 95ea84e72..4d2adc0cf 100644 --- a/src/zen/media/ZenMediaController.mjs +++ b/src/zen/media/ZenMediaController.mjs @@ -451,10 +451,22 @@ class nsZenMediaController { window.addEventListener("TabBrowserDiscarded", onTabDiscardedOrClosed); window.addEventListener("DOMAudioPlaybackStarted", event => { - this.activateMediaControls( - event.target.browsingContext.mediaController, - event.target - ); + const browser = event.target; + // Only create the card if the media is still playing a moment + // later, so short sounds (e.g. notification pings) never produce + // one. + setTimeout(() => { + const mediaController = browser.browsingContext?.mediaController; + if (!mediaController?.isPlaying) { + return; + } + + this.activateMediaControls(mediaController, browser); + const card = this.#cardForBrowser(browser); + if (card && !card.isSharing) { + card.refreshVisibility(); + } + }, 1000); }); window.addEventListener("DOMAudioPlaybackStopped", () => { @@ -483,8 +495,23 @@ class nsZenMediaController { ); } + #cardForBrowser(browser) { + return ( + Array.from(this.#cards.values()).find( + card => card.browser.browserId === browser.browserId + ) ?? null + ); + } + activateMediaControls(mediaController, browser) { - if (!mediaController?.isActive || this.#cards.has(mediaController.id)) { + if ( + !mediaController?.isActive || + this.#cards.has(mediaController.id) || + // Never stack more than one card for the same browser: sites that + // activate a fresh controller for every sound they play (e.g. + // notification pings) keep their one card. + this.#cardForBrowser(browser) + ) { return; } @@ -572,7 +599,14 @@ class nsZenMediaController { const element = this.#createCardElement(); const card = new ZenMediaCard(this, element, browser, controller); this.#cards.set(key, card); - card.refreshVisibility(); + if (controller) { + // Media cards start hidden and appear via the delayed check in + // DOMAudioPlaybackStarted or on tab switch, like the original bar; + // sharing cards show right away. + card.element.hidden = true; + } else { + card.refreshVisibility(); + } this.onCardVisibilityChanged(); return card; } diff --git a/src/zen/window-drag/actors/ZenWindowDragChild.sys.mjs b/src/zen/window-drag/actors/ZenWindowDragChild.sys.mjs index d20c47454..94fd85f08 100644 --- a/src/zen/window-drag/actors/ZenWindowDragChild.sys.mjs +++ b/src/zen/window-drag/actors/ZenWindowDragChild.sys.mjs @@ -54,33 +54,6 @@ const kInteractiveRoles = new Set([ "treegrid", ]); -// Cursors that signal the page considers the area interactive or draggable. -const kInteractiveCursors = new Set([ - "pointer", - "grab", - "grabbing", - "move", - "all-scroll", - "text", - "vertical-text", - "cell", - "crosshair", - "col-resize", - "row-resize", - "n-resize", - "e-resize", - "s-resize", - "w-resize", - "ne-resize", - "nw-resize", - "se-resize", - "sw-resize", - "ew-resize", - "ns-resize", - "nesw-resize", - "nwse-resize", -]); - const kGestureListenerOptions = { mozSystemGroup: true, capture: true }; const kGestureEvents = ["mousemove", "mouseup", "dragstart", "unload"]; @@ -276,7 +249,12 @@ export class ZenWindowDragChild extends JSWindowActorChild { return true; } } - return this.#hasInteractiveCursor(target); + // The effective cursor, resolved the same way it is shown to the user. + return lazy.zenWindowDragUtils.isInteractiveCursor( + event.composedTarget, + event.clientX, + event.clientY + ); } #isSelectableText(node) { @@ -307,15 +285,4 @@ export class ZenWindowDragChild extends JSWindowActorChild { const role = element.getAttribute?.("role"); return !!role && kInteractiveRoles.has(role.toLowerCase()); } - - #hasInteractiveCursor(element) { - const style = element.ownerGlobal?.getComputedStyle(element); - if (!style) { - return false; - } - // The keyword is always the last component of the computed value. - // Don't split on "," as url() cursor images may contain commas. - const cursor = style.cursor.match(/[a-z-]+$/)?.[0]; - return kInteractiveCursors.has(cursor); - } } diff --git a/src/zen/window-drag/nsIZenWindowDragUtils.idl b/src/zen/window-drag/nsIZenWindowDragUtils.idl index 8389bbd01..995f67089 100644 --- a/src/zen/window-drag/nsIZenWindowDragUtils.idl +++ b/src/zen/window-drag/nsIZenWindowDragUtils.idl @@ -20,4 +20,15 @@ interface nsIZenWindowDragUtils : nsISupports { * @param node The node to check. */ boolean isInteractiveContent(in Node node); + + /** + * @brief Whether the effective cursor for the given node signals + * interactive or draggable content (pointer, text, move, resize, ...). + * Unlike computed style, this resolves cursor: auto the same way the + * cursor actually shown to the user is chosen. + * @param node The deepest node hit by the event. + * @param clientX Viewport X coordinate of the event, in CSS pixels. + * @param clientY Viewport Y coordinate of the event, in CSS pixels. + */ + boolean isInteractiveCursor(in Node node, in float clientX, in float clientY); }; diff --git a/src/zen/window-drag/nsZenWindowDragUtils.cpp b/src/zen/window-drag/nsZenWindowDragUtils.cpp index 06ef834b3..bd8d6cb2b 100644 --- a/src/zen/window-drag/nsZenWindowDragUtils.cpp +++ b/src/zen/window-drag/nsZenWindowDragUtils.cpp @@ -4,9 +4,13 @@ #include "nsZenWindowDragUtils.h" +#include "Units.h" +#include "mozilla/PresShell.h" +#include "mozilla/ServoStyleConsts.h" #include "mozilla/dom/Element.h" #include "nsContentUtils.h" #include "nsIContent.h" +#include "nsIFrame.h" namespace zen { @@ -30,4 +34,57 @@ nsZenWindowDragUtils::IsInteractiveContent(nsINode* aNode, bool* aResult) { return NS_OK; } +NS_IMETHODIMP +nsZenWindowDragUtils::IsInteractiveCursor(nsINode* aNode, float aClientX, + float aClientY, bool* aResult) { + using mozilla::StyleCursorKind; + + *aResult = false; + NS_ENSURE_ARG_POINTER(aNode); + + nsIContent* content = nsIContent::FromNode(aNode); + nsIFrame* frame = content ? content->GetPrimaryFrame() : nullptr; + if (!frame) { + return NS_OK; + } + nsIFrame* rootFrame = frame->PresShell()->GetRootFrame(); + if (!rootFrame) { + return NS_OK; + } + nsPoint point(mozilla::CSSPixel::ToAppUnits(aClientX), + mozilla::CSSPixel::ToAppUnits(aClientY)); + point -= frame->GetOffsetTo(rootFrame); + + switch (frame->GetCursor(point).mCursor) { + case StyleCursorKind::Pointer: + case StyleCursorKind::Cell: + case StyleCursorKind::Crosshair: + case StyleCursorKind::Text: + case StyleCursorKind::VerticalText: + case StyleCursorKind::Move: + case StyleCursorKind::Grab: + case StyleCursorKind::Grabbing: + case StyleCursorKind::EResize: + case StyleCursorKind::NResize: + case StyleCursorKind::NeResize: + case StyleCursorKind::NwResize: + case StyleCursorKind::SResize: + case StyleCursorKind::SeResize: + case StyleCursorKind::SwResize: + case StyleCursorKind::WResize: + case StyleCursorKind::EwResize: + case StyleCursorKind::NsResize: + case StyleCursorKind::NeswResize: + case StyleCursorKind::NwseResize: + case StyleCursorKind::ColResize: + case StyleCursorKind::RowResize: + case StyleCursorKind::AllScroll: + *aResult = true; + break; + default: + break; + } + return NS_OK; +} + } // namespace zen diff --git a/surfer.json b/surfer.json index 282e1f8a1..dc8662fbc 100644 --- a/surfer.json +++ b/surfer.json @@ -20,7 +20,7 @@ "brandShortName": "Zen", "brandFullName": "Zen Browser", "release": { - "displayVersion": "1.21.11b", + "displayVersion": "1.21.12b", "github": { "repo": "zen-browser/desktop" },