Compare commits

...

26 Commits

Author SHA1 Message Date
mr. m
f4d9821fd7 Revert "gh-15144: Update windows registry on update" (gh-15153) 2026-08-29 01:35:20 +02:00
mr. m
221b909190 gh-15144: Update windows registry on update (gh-15145) 2026-08-28 11:56:05 +02:00
Nikola Hristov
ce0cbde336 gh-15134: Fixes tab removed from group getting focused (gh-15135)
Closes https://github.com/zen-browser/desktop/issues/15134

Fix video:

https://github.com/user-attachments/assets/1c06ea7f-d482-4d4a-8bbe-df41daa27616
2026-08-28 11:56:05 +02:00
mr. m
70ca9ad3bc gh-15119: Update windows registry with old certificates (gh-15120) 2026-08-26 17:51:26 +02:00
mr. m
81aece863f gh-14710: Fixed minimizing PiP window failing to collapse into the sidebar (gh-15111) 2026-08-26 08:31:00 +02:00
CocoLng
e0bb36ef26 gh-15039: Fix New Blank Window menu entry not in Title Case (gh-15056) 2026-08-26 00:11:12 +02:00
Henrik Nyh
1b299d0df4 gh-15039: Use Title Case for split view labels (gh-15059) 2026-08-26 00:11:11 +02:00
mr. m
928699e61c gh-15029: Fixed urlbar suggestion context not working (gh-15037) 2026-08-26 00:11:11 +02:00
mr. m
1f2fb08b09 gh-15031: Fixed duplicate separator on tab context menu (gh-15035) 2026-08-26 00:11:11 +02:00
mr. m
5404c990eb gh-15101: Sync upstream Firefox to version 154.0.1 (gh-15100) 2026-08-26 00:11:11 +02:00
mr. m
47bc3dc294 gh-14990: Prevent policyContainer from bloating the session file (gh-15098) 2026-08-26 00:11:11 +02:00
mr. m
eac29c4b1e gh-15085: Import mochitests for remote settings (gh-15086) 2026-08-26 00:11:10 +02:00
mr. m
cee4147767 gh-14959: Fix wrong wine download resource (gh-15018) 2026-08-19 00:19:10 +02:00
mr. m
6517dd8287 Revert "gh-14470: Add space and container sync (gh-14471)"
This reverts commit 647e219639.
2026-08-18 23:52:24 +02:00
mr. m
cebaa0cefa gh-14959: Sync upstream Firefox to version 154.0 (gh-15012) 2026-08-18 23:44:19 +02:00
mr. m
e2e1ab4e6d gh-12464: Implement a more efficient way of adding macos translucency (gh-15006) 2026-08-18 00:19:24 +02:00
mr. m
9f2771aff6 gh-15005: Improve feel of theme colors (gh-15004) 2026-08-17 23:28:23 +02:00
mr. m
67acee0791 Revert "gh-14974: New Crowdin updates" (#14999) 2026-08-17 11:50:14 +02:00
mr. m
82e1c79b60 gh-14990: Part 2 - Correctly set length hint for JSON writes (gh-14994) 2026-08-16 16:26:48 +02:00
mr. m
93776ce026 gh-14990: Pre-allocate session store bytes before writing (gh-14993) 2026-08-16 16:15:50 +02:00
mr. m
816ec2d40c gh-9649: Bump surfer version (gh-14988) 2026-08-16 11:31:18 +02:00
mr. m
13edb480c4 gh-9649: Start cross-compiling macos builds from linux (gh-14978) 2026-08-16 02:05:45 +02:00
mr. m
7e8ba31bab gh-14974: New Crowdin updates (gh-14983) 2026-08-16 00:15:44 +02:00
mr. m
f8daccb4c9 gh-14975: Fix multiple glance tabs when joining tabs (gh-14977) 2026-08-15 17:51:34 +02:00
mr. m
bdce5db518 gh-14959: Add untrusted web process flags for actors (gh-14973) 2026-08-15 12:58:09 +02:00
mr. m
7f40771405 gh-14959: Sync upstream Firefox to version 154.0 (gh-14960) 2026-08-14 16:44:17 +02:00
669 changed files with 85518 additions and 13055 deletions

2
.gitattributes vendored
View File

@@ -5,4 +5,4 @@
*.patch linguist-language=C++
*.d.ts linguist-language=TypeScript
src/zen/tests/*.js linguist-language=Test
src/zen/tests/** linguist-language=C++

View File

@@ -287,7 +287,7 @@ jobs:
with:
use-sccache: ${{ inputs.use-sccache }}
build-version: ${{ needs.build-data.outputs.version }}
generate-gpo: true
generate-pgo: true
profile-data-path-archive: zen-windows-profile-data-and-jarlog.zip
release-branch: ${{ inputs.update_branch }}
MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
@@ -313,7 +313,7 @@ jobs:
needs: [build-data, windows-step-2, start-self-host, buildid]
with:
build-version: ${{ needs.build-data.outputs.version }}
generate-gpo: false
generate-pgo: false
release-branch: ${{ inputs.update_branch }}
MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
use-sccache: ${{ inputs.use-sccache }}
@@ -331,15 +331,41 @@ jobs:
MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
use-sccache: ${{ inputs.use-sccache }}
mac:
name: macOS build
mac-step-1:
name: macOS build step 1 (PGO build)
uses: ./.github/workflows/macos-release-build.yml
needs: [build-data, buildid]
permissions:
contents: write
secrets: inherit
with:
use-sccache: ${{ inputs.use-sccache }}
build-version: ${{ needs.build-data.outputs.version }}
generate-pgo: true
release-branch: ${{ inputs.update_branch }}
MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
mac-step-2:
name: macOS build step 2 (Generate profile data)
uses: ./.github/workflows/macos-profile-build.yml
permissions:
contents: write
secrets: inherit
needs: [mac-step-1, build-data]
with:
build-version: ${{ needs.build-data.outputs.version }}
release-branch: ${{ inputs.update_branch }}
mac-step-3:
name: macOS build step 3 (build with profile data)
uses: ./.github/workflows/macos-release-build.yml
permissions:
contents: write
secrets: inherit
needs: [build-data, buildid]
needs: [build-data, mac-step-2, start-self-host, buildid]
with:
build-version: ${{ needs.build-data.outputs.version }}
generate-pgo: false
release-branch: ${{ inputs.update_branch }}
MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
use-sccache: ${{ inputs.use-sccache }}
@@ -350,7 +376,7 @@ jobs:
permissions:
contents: write
secrets: inherit
needs: [build-data, mac]
needs: [build-data, mac-step-3]
with:
build-version: ${{ needs.build-data.outputs.version }}
release-branch: ${{ inputs.update_branch }}

View File

@@ -105,6 +105,8 @@ jobs:
SURFER_COMPAT: ${{ matrix.arch }}
SURFER_CERT_PATCH_ISSUER: ${{ secrets.SURFER_CERT_PATCH_ISSUER }}
SURFER_CERT_PATCH_NAME: ${{ secrets.SURFER_CERT_PATCH_NAME }}
SURFER_CERT_PATCH_NAME_PREV: ${{ secrets.SURFER_CERT_PATCH_NAME_PREV }}
SURFER_CERT_PATCH_ISSUER_PREV: ${{ secrets.SURFER_CERT_PATCH_ISSUER_PREV }}
run: |
. "$HOME/.cargo/env"
npm run import

View File

@@ -0,0 +1,111 @@
name: macOS PGO Builds
permissions:
contents: read
on:
workflow_call:
inputs:
build-version:
description: "The version to build"
required: true
type: string
release-branch:
description: "The branch to build"
required: true
type: string
jobs:
macos-profile-build:
name: |
macOS Profile Build - ${{ matrix.arch }}
strategy:
fail-fast: false
matrix:
arch: [x86_64, aarch64]
runs-on: ${{ matrix.arch == 'x86_64' && 'macos-15-intel' || 'macos-26' }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
- name: Setup Python
uses: actions/setup-python@v5
- name: Setup Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Setup Rust
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain $(cat .rust-toolchain)
- name: Install dependencies
run: npm ci
- name: Load Surfer CI setup
run: npm run surfer -- ci --brand ${{ inputs.release-branch }} --display-version ${{ inputs.build-version }}
- name: Download instrumented app
uses: actions/download-artifact@v4
with:
path: ~/instrumented
name: macos-pgo-stage1-${{ matrix.arch }}
- name: Download Firefox and dependencies
run: npm run download
- name: Import patches
env:
SURFER_NO_BRANDING_PATCH: true
run: |
. "$HOME/.cargo/env"
npm run import
- name: Bootstrap
run: |
cd engine
export SURFER_PLATFORM="darwin"
./mach --no-interactive bootstrap --application-choice browser --exclude macos-sdk || true
- name: Extract instrumented app
run: |
set -ex
cd engine
./mach python -m mozbuild.action.unpack_dmg \
"$HOME/instrumented/zen-macos-pgo-stage1-${{ matrix.arch }}.dmg" \
"$HOME/instrumented/app"
APP=$(find "$HOME/instrumented/app" -maxdepth 1 -name "*.app" -type d | head -1)
codesign --force --deep --sign - "$APP" || true
- name: Generate profile data
run: |
set -ex
export LLVM_PROFDATA="$HOME/.mozbuild/clang/bin/llvm-profdata"
export JARLOG_FILE=en-US.log
BINARY=$(find "$HOME/instrumented" -type f -path "*/Contents/MacOS/zen" | head -1)
test -n "$BINARY"
cd engine
./mach python ../scripts/download_pgo_extended_corpus.py
./mach python build/pgo/profileserver.py --binary "$BINARY" --extended-corpus ./pgo-extended-corpus
- name: Move profile data
run: |
mv engine/merged.profdata merged.profdata
mv engine/en-US.log en-US.log
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
retention-days: 1
path: |
merged.profdata
en-US.log
name: macos-profdata-${{ matrix.arch }}

View File

@@ -1,10 +1,15 @@
name: macOS Release Build
permissions:
contents: read
on:
workflow_call:
inputs:
generate-pgo:
required: true
type: boolean
default: false
build-version:
description: "The version to build"
required: true
@@ -26,17 +31,22 @@ on:
jobs:
mac-build:
name: Build macOS - ${{ matrix.arch }}
runs-on: ${{ (inputs.release-branch == 'release') && 'blacksmith-6vcpu-macos-latest' || 'macos-26' }}
strategy:
fail-fast: false
matrix:
arch: [x86_64, aarch64]
runs-on: 'blacksmith-8vcpu-ubuntu-2404'
env:
SCCACHE_GHA_ENABLED: ${{ inputs.use-sccache && 'true' || 'false' }}
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
strategy:
fail-fast: false
matrix:
arch: [x86_64, aarch64]
steps:
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
- name: Checkout repository
uses: actions/checkout@v4
with:
@@ -44,16 +54,10 @@ jobs:
token: ${{ secrets.DEPLOY_KEY }}
- name: Setup Node.js
uses: actions/setup-node@v4
uses: useblacksmith/setup-node@v5
with:
node-version-file: ".nvmrc"
- name: Log SDK versions
run: |
ls /Library/Developer/CommandLineTools/SDKs/
xcrun --show-sdk-version
xcrun --show-sdk-path
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@main
if: ${{ inputs.use-sccache }}
@@ -67,157 +71,158 @@ jobs:
core.exportVariable('ACTIONS_CACHE_URL', process.env['ACTIONS_CACHE_URL'])
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN'])
- name: Setup Python
uses: actions/setup-python@v5
# note: This will use the version defined in '.python-version' by default
- name: Setup Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Install system dependencies
- name: Install dependencies
run: |
brew update
brew install cairo gnu-tar mercurial
sudo pip install setuptools
npm ci
sudo apt-get update
sudo apt-get install -y python3 python3-pip zstd yasm nasm build-essential libgtk2.0-dev libpython3-dev m4 uuid libasound2-dev libcurl4-openssl-dev libdbus-1-dev libdrm-dev libdbus-glib-1-dev libgtk-3-dev libpulse-dev libx11-xcb-dev libxt-dev xvfb --fix-missing
brew uninstall --ignore-dependencies python3.12 -f
- name: Load Surfer CI setup
run: npm run surfer -- ci --brand ${{ inputs.release-branch }} --display-version ${{ inputs.build-version }}
export PATH="$(python3 -m site --user-base)/bin":$PATH
python3 -m pip install --user mercurial
- name: Download Firefox and dependencies
run: npm run download
rm '/usr/local/bin/2to3-3.11' '/usr/local/bin/2to3-3.12' '/usr/local/bin/2to3'
rm '/usr/local/bin/idle3.11' '/usr/local/bin/idle3.12' '/usr/local/bin/idle3'
rm '/usr/local/bin/pydoc3.11' '/usr/local/bin/pydoc3.12' '/usr/local/bin/pydoc3'
rm '/usr/local/bin/python3.11' '/usr/local/bin/python3.12' '/usr/local/bin/python3'
rm '/usr/local/bin/python3.11-config' '/usr/local/bin/python3.12-config' '/usr/local/bin/python3-config'
- name: mac-cross Cache
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 5
id: cache-mac-cross
uses: useblacksmith/cache@v5
with:
path: ${HOME}/mac-cross
key: mac-cross
brew install watchman
- name: Setup for macOS (cctools and DMG tools)
if: steps.cache-mac-cross.outputs.cache-hit != 'true'
run: |
set -ex
mkdir -p ~/mac-cross
cd engine/
./mach artifact toolchain --from-build linux64-cctools-port linux64-libdmg linux64-hfsplus
mv cctools dmg hfsplus ~/mac-cross/
ls ~/mac-cross/cctools/bin/x86_64-apple-darwin-ld ~/mac-cross/cctools/bin/aarch64-apple-darwin-ld ~/mac-cross/dmg/dmg ~/mac-cross/hfsplus/newfs_hfs
- name: Setup Rust
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain $(cat .rust-toolchain)
source $HOME/.cargo/env
if test "${{ matrix.arch }}" = "aarch64"; then
rustup target add aarch64-apple-darwin
else
rustup target add x86_64-apple-darwin
fi
- name: Force usage of gnu-tar
run: |
echo 'export PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"' >> ~/.bash_profile
echo 'export PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"' >> ~/.zsh
source ~/.bash_profile
- name: Install dependencies
run: |
npm ci
- name: Load surfer CI setup
run: npm run surfer -- ci --brand ${{ inputs.release-branch }} --display-version ${{ inputs.build-version }}
- name: Download Firefox source and dependencies
run: npm run download
- name: Import
env:
SURFER_COMPAT: ${{ matrix.arch }}
SURFER_CERT_PATCH_ISSUER: ${{ secrets.SURFER_CERT_PATCH_ISSUER }}
SURFER_CERT_PATCH_NAME: ${{ secrets.SURFER_CERT_PATCH_NAME }}
run: npm run import
SURFER_CERT_PATCH_NAME_PREV: ${{ secrets.SURFER_CERT_PATCH_NAME_PREV }}
SURFER_CERT_PATCH_ISSUER_PREV: ${{ secrets.SURFER_CERT_PATCH_ISSUER_PREV }}
SURFER_PLATFORM: darwin
run: |
. "$HOME/.cargo/env"
npm run import -- --verbose
- name: Bootstrap
run: |
cd engine
set -x
export SURFER_PLATFORM="darwin"
export PATH="$(python3 -m site --user-base)/bin":$PATH
# Always exist with 0, even if bootstrap fails
./mach --no-interactive bootstrap --application-choice browser --exclude macos-sdk || true
cd ..
npm run bootstrap
- name: Build language packs
run: sh scripts/download-language-packs.sh
- name: Build Zen (PGO stage 1 - generate)
- name: Download artifact (if use profdata)
uses: actions/download-artifact@v4
if: ${{ !inputs.generate-pgo }}
with:
path: ~/artifact
name: macos-profdata-${{ matrix.arch }}
- name: Show artifact info
if: ${{ !inputs.generate-pgo }}
run: |
ls ~/artifact
ls ~/artifact/en-US.log
ls ~/artifact/merged.profdata
- name: Build
env:
SURFER_COMPAT: ${{ matrix.arch }}
ZEN_RELEASE_BRANCH: ${{ inputs.release-branch }}
ZEN_GA_GENERATE_PROFILE: 1
ZEN_SAFEBROWSING_API_KEY: ${{ secrets.ZEN_SAFEBROWSING_API_KEY }}
ZEN_MOZILLA_API_KEY: ${{ secrets.ZEN_MOZILLA_API_KEY }}
ZEN_GOOGLE_LOCATION_SERVICE_API_KEY: ${{ secrets.ZEN_GOOGLE_LOCATION_SERVICE_API_KEY }}
run: |
export SURFER_PLATFORM="darwin"
if [[ -n ${{ inputs.MOZ_BUILD_DATE }} ]];then
export MOZ_BUILD_DATE=${{ inputs.MOZ_BUILD_DATE }}
fi
bash .github/workflows/src/release-build.sh
- name: Generate PGO profile data
env:
SURFER_COMPAT: ${{ matrix.arch }}
run: |
set -x
export LLVM_PROFDATA="$HOME/.mozbuild/clang/bin/llvm-profdata"
export JARLOG_FILE=en-US.log
mkdir -p "$HOME/artifact"
cd engine
./mach python ../scripts/download_pgo_extended_corpus.py
./mach package
./mach python build/pgo/profileserver.py --extended-corpus ./pgo-extended-corpus
mv merged.profdata "$HOME/artifact/merged.profdata"
mv en-US.log "$HOME/artifact/en-US.log"
- name: Build Zen
env:
SURFER_COMPAT: ${{ matrix.arch }}
ZEN_RELEASE_BRANCH: ${{ inputs.release-branch }}
ZEN_SAFEBROWSING_API_KEY: ${{ secrets.ZEN_SAFEBROWSING_API_KEY }}
ZEN_MOZILLA_API_KEY: ${{ secrets.ZEN_MOZILLA_API_KEY }}
ZEN_GOOGLE_LOCATION_SERVICE_API_KEY: ${{ secrets.ZEN_GOOGLE_LOCATION_SERVICE_API_KEY }}
run: |
export SURFER_PLATFORM="darwin"
export ZEN_CROSS_COMPILING=1
if test ${{ inputs.generate-pgo }} = true; then
export ZEN_GA_GENERATE_PROFILE=1
fi
if [[ -n ${{ inputs.MOZ_BUILD_DATE }} ]];then
export MOZ_BUILD_DATE=${{ inputs.MOZ_BUILD_DATE }}
fi
bash .github/workflows/src/release-build.sh
- name: Package instrumented app (PGO stage 1)
if: ${{ inputs.generate-pgo }}
env:
SURFER_COMPAT: ${{ matrix.arch }}
ZEN_RELEASE: 1
SURFER_PLATFORM: darwin
ZEN_CROSS_COMPILING: 1
ZEN_GA_GENERATE_PROFILE: 1
run: |
set -ex
cd engine
./mach package
mv obj-${{ matrix.arch }}-apple-darwin/dist/*.dmg "$GITHUB_WORKSPACE/zen-macos-pgo-stage1-${{ matrix.arch }}.dmg"
- name: Upload artifact (PGO stage 1)
uses: actions/upload-artifact@v4
if: ${{ inputs.generate-pgo }}
with:
retention-days: 2
name: macos-pgo-stage1-${{ matrix.arch }}
path: ./zen-macos-pgo-stage1-${{ matrix.arch }}.dmg
- name: Package
if: ${{ !inputs.generate-pgo }}
env:
SURFER_COMPAT: ${{ matrix.arch }}
ZEN_GA_DISABLE_PGO: true
run: |
set -x
export SURFER_PLATFORM="darwin"
export ZEN_CROSS_COMPILING=1
export ZEN_RELEASE=1
npm run package
- name: Rename artifacts
if: ${{ !inputs.generate-pgo }}
run: |
echo "Tarballing DMG"
set -ex
mv ./dist/*.dmg ./zen-${{ matrix.arch }}-apple-darwin-dist.dmg
mv ./engine/obj-${{ matrix.arch }}-apple-darwin/dist/host/bin/mar ./zen-macos-host-mar
mv ./engine/obj-${{ matrix.arch }}-apple-darwin/dist/bin/platform.ini ./platform.ini
- name: Upload dist dmg
uses: actions/upload-artifact@v4
if: ${{ !inputs.generate-pgo }}
with:
retention-days: 1
name: zen-${{ matrix.arch }}-apple-darwin-dist.dmg
path: ./zen-${{ matrix.arch }}-apple-darwin-dist.dmg
- name: Upload host mar
uses: actions/upload-artifact@v4
if: matrix.arch == 'aarch64'
with:
retention-days: 1
name: zen-macos-host-mar
path: ./zen-macos-host-mar
- name: Upload platform.ini
uses: actions/upload-artifact@v4
if: matrix.arch == 'x86_64'
if: ${{ !inputs.generate-pgo && matrix.arch == 'x86_64' }}
with:
retention-days: 1
name: platform.ini

View File

@@ -99,6 +99,16 @@ jobs:
cd engine
./mach configure
- name: Build host mar tool
run: |
set -ex
cd engine
echo "ac_add_options --enable-project=tools/update-packaging" > mar-mozconfig
echo "mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-mar-tools" >> mar-mozconfig
MOZCONFIG=$PWD/mar-mozconfig ./mach build -v
cp obj-mar-tools/dist/host/bin/mar ../zen-macos-host-mar
rm -rf obj-mar-tools mar-mozconfig
- name: Download x86_64 DMG from artifacts
uses: actions/download-artifact@v4
with:
@@ -213,11 +223,6 @@ jobs:
--wait
xcrun stapler staple "zen.macos-universal.dmg"
- name: Download host mar
uses: actions/download-artifact@v4
with:
name: zen-macos-host-mar
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:

View File

@@ -6,7 +6,7 @@ permissions:
on:
workflow_call:
inputs:
generate-gpo:
generate-pgo:
required: true
type: boolean
default: false
@@ -35,7 +35,7 @@ jobs:
windows-build:
name: Build Windows - ${{ matrix.arch }}
# aarch64 does not need full 16x, and we also dont use full LTO when generating GPO
runs-on: ${{ (inputs.release-branch == 'release' && !inputs.generate-gpo && matrix.arch == 'x86_64') && 'self-hosted' || 'blacksmith-8vcpu-ubuntu-2404' }}
runs-on: ${{ (inputs.release-branch == 'release' && !inputs.generate-pgo && matrix.arch == 'x86_64') && 'self-hosted' || 'blacksmith-8vcpu-ubuntu-2404' }}
env:
SCCACHE_GHA_ENABLED: ${{ inputs.use-sccache && 'true' || 'false' }}
CARGO_TERM_COLOR: always
@@ -48,7 +48,7 @@ jobs:
steps:
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
if: ${{ !(inputs.generate-pgo && matrix.arch == 'aarch64') }}
with:
tool-cache: false
@@ -91,7 +91,7 @@ jobs:
run: npm run surfer -- ci --brand ${{ inputs.release-branch }} --display-version ${{ inputs.build-version }}
- name: Download Firefox and dependencies
if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
if: ${{ !(inputs.generate-pgo && matrix.arch == 'aarch64') }}
run: npm run download
- name: win-cross Cache
@@ -104,7 +104,7 @@ jobs:
key: win-cross
- name: Setup for Windows
if: steps.cache-win-cross.outputs.cache-hit != 'true' && !(inputs.generate-gpo && matrix.arch == 'aarch64')
if: steps.cache-win-cross.outputs.cache-hit != 'true' && !(inputs.generate-pgo && matrix.arch == 'aarch64')
run: |
set -x
mkdir -p ~/win-cross
@@ -154,24 +154,26 @@ jobs:
zlib1g-dev \
aria2
echo Setup wine
aria2c "https://firefox-ci-tc.services.mozilla.com/api/queue/v1/task/dQz_aHy8Rl-Lt0xf2WlrMw/artifacts/public/build/wine.tar.zst" -o wine.tar.zst
aria2c "https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/gecko.cache.level-3.toolchains.v3.linux64-wine.latest/artifacts/public/build/wine.tar.zst" -o wine.tar.zst
tar --zstd -xf wine.tar.zst -C ~/win-cross
rm wine.tar.zst
echo Setup Visual Studio
./mach python --virtualenv build taskcluster/scripts/misc/get_vs.py build/vs/vs2026.yaml ~/win-cross/vs2026
- name: Import
if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
if: ${{ !(inputs.generate-pgo && matrix.arch == 'aarch64') }}
env:
SURFER_COMPAT: ${{ matrix.arch }}
SURFER_CERT_PATCH_ISSUER: ${{ secrets.SURFER_CERT_PATCH_ISSUER }}
SURFER_CERT_PATCH_NAME: ${{ secrets.SURFER_CERT_PATCH_NAME }}
SURFER_CERT_PATCH_NAME_PREV: ${{ secrets.SURFER_CERT_PATCH_NAME_PREV }}
SURFER_CERT_PATCH_ISSUER_PREV: ${{ secrets.SURFER_CERT_PATCH_ISSUER_PREV }}
run: |
. "$HOME/.cargo/env"
npm run import -- --verbose
- name: Bootstrap
if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
if: ${{ !(inputs.generate-pgo && matrix.arch == 'aarch64') }}
run: |
set -x
cd engine/
@@ -189,7 +191,7 @@ jobs:
ls ~/win-cross/vs2026 || true
- name: Setup Rust
if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
if: ${{ !(inputs.generate-pgo && matrix.arch == 'aarch64') }}
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain $(cat .rust-toolchain)
source $HOME/.cargo/env
@@ -208,18 +210,18 @@ jobs:
echo "export MOZ_WINDOWS_RS_DIR=$(pwd)/windows-$WINDOWS_RS_VERSION" >> ../configs/common/mozconfig
- name: Build language packs
if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
if: ${{ !(inputs.generate-pgo && matrix.arch == 'aarch64') }}
run: sh scripts/download-language-packs.sh
- name: Download artifact (if use profdata)
uses: actions/download-artifact@v4
if: ${{ !inputs.generate-gpo && matrix.arch == 'x86_64' }}
if: ${{ !inputs.generate-pgo && matrix.arch == 'x86_64' }}
with:
path: ~/artifact
name: windows-profdata-${{ matrix.arch == 'aarch64' && 'arm64' || matrix.arch }}
- name: Show artifact info
if: ${{ !inputs.generate-gpo && matrix.arch == 'x86_64' }}
if: ${{ !inputs.generate-pgo && matrix.arch == 'x86_64' }}
run: |
ls ~/artifact
ls ~/artifact/en-US.log
@@ -228,7 +230,7 @@ jobs:
chmod +x ~/artifact/merged.profdata
- name: Build
if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
if: ${{ !(inputs.generate-pgo && matrix.arch == 'aarch64') }}
env:
SURFER_COMPAT: ${{ matrix.arch }}
ZEN_RELEASE_BRANCH: ${{ inputs.release-branch }}
@@ -241,7 +243,7 @@ jobs:
dos2unix configs/windows/mozconfig
export SURFER_PLATFORM="win32"
export ZEN_CROSS_COMPILING=1
if test ${{ inputs.generate-gpo }} = true; then
if test ${{ inputs.generate-pgo }} = true; then
export ZEN_GA_GENERATE_PROFILE=1
fi
if [[ -n ${{ inputs.MOZ_BUILD_DATE }} ]];then
@@ -250,7 +252,7 @@ jobs:
bash .github/workflows/src/release-build.sh
- name: Package
if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
if: ${{ !(inputs.generate-pgo && matrix.arch == 'aarch64') }}
env:
SURFER_COMPAT: ${{ matrix.arch }}
ZEN_GA_DISABLE_PGO: true
@@ -265,13 +267,13 @@ jobs:
ls .
- name: Move package for PGO upload
if: ${{ inputs.generate-gpo && matrix.arch == 'x86_64' }}
if: ${{ inputs.generate-pgo && matrix.arch == 'x86_64' }}
run: |
set -x
mv ./zen.win64.zip ./zen.win64-pgo-stage-1.zip
- name: Rename artifacts
if: ${{ !inputs.generate-gpo }}
if: ${{ !inputs.generate-pgo }}
run: |
mv ./zen.win64.zip zen.win-${{ matrix.arch == 'aarch64' && 'arm64' || matrix.arch }}.zip
mv ./dist/output.mar windows${{ matrix.arch == 'aarch64' && '-arm64' || '' }}.mar
@@ -279,14 +281,14 @@ jobs:
- name: Upload artifact (PGO)
uses: actions/upload-artifact@v4
if: ${{ inputs.generate-gpo && matrix.arch == 'x86_64' }}
if: ${{ inputs.generate-pgo && matrix.arch == 'x86_64' }}
with:
retention-days: 2
name: ${{ matrix.arch == 'aarch64' && 'arm64' || matrix.arch }}-${{ inputs.profile-data-path-archive }}
path: ./zen.win64-pgo-stage-1.zip
- name: Remove unnecessary files from obj
if: ${{ !inputs.generate-gpo }}
if: ${{ !inputs.generate-pgo }}
run: |
set -x
mkdir obj-${{ matrix.arch }}-pc-windows-msvc/
@@ -301,7 +303,7 @@ jobs:
cp -r --no-dereference engine/obj-${{ matrix.arch }}-pc-windows-msvc/* obj-${{ matrix.arch }}-pc-windows-msvc/ || true
- name: Upload dist object
if: ${{ !inputs.generate-gpo }}
if: ${{ !inputs.generate-pgo }}
uses: actions/upload-artifact@v4
with:
retention-days: 2
@@ -309,7 +311,7 @@ jobs:
path: obj-${{ matrix.arch }}-pc-windows-msvc
- name: Upload artifact (if Twilight branch, installer)
if: ${{ inputs.release-branch == 'twilight' && !inputs.generate-gpo }}
if: ${{ inputs.release-branch == 'twilight' && !inputs.generate-pgo }}
uses: actions/upload-artifact@v4
with:
retention-days: 5
@@ -317,7 +319,7 @@ jobs:
path: ./zen.installer${{ matrix.arch == 'aarch64' && '-arm64' || '' }}.exe
- name: Upload artifact (if Twilight branch, .mar)
if: ${{ inputs.release-branch == 'twilight' && !inputs.generate-gpo }}
if: ${{ inputs.release-branch == 'twilight' && !inputs.generate-pgo }}
uses: actions/upload-artifact@v4
with:
retention-days: 5
@@ -325,7 +327,7 @@ jobs:
path: ./windows${{ matrix.arch == 'aarch64' && '-arm64' || '' }}.mar
- name: Upload artifact (if Twilight branch, update manifests)
if: ${{ inputs.release-branch == 'twilight' && !inputs.generate-gpo }}
if: ${{ inputs.release-branch == 'twilight' && !inputs.generate-pgo }}
uses: actions/upload-artifact@v4
with:
retention-days: 5

View File

@@ -34,8 +34,8 @@ Zen is a firefox-based browser with the aim of pushing your productivity to a ne
### Firefox Versions
- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `153.0.4`! 🚀
- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 153.0.4`!
- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `154.0.1`!
- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 154.0.1`!
### Contributing

View File

@@ -1 +1 @@
5770c902793071359ace6016706281dec48c53af
bf4b57fd7fe94054457be7018e8e7beaf754c520

View File

@@ -3,8 +3,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
param(
[string][Parameter(Mandatory=$true)]$SignIdentity,
[string][Parameter(Mandatory=$true)]$SignIdentityIssuer,
[string][Parameter(Mandatory=$true)]$GithubRunId
)
@@ -24,12 +22,23 @@ mkdir windsign-temp -ErrorAction SilentlyContinue
# echo "Downloaded git objects repo to"
#} -Verbose -ArgumentList $PWD -Debug
$token = gh auth token
$env:SURFER_MOZCONFIG_ONLY="1"
$env:SURFER_SIGNING_MODE=""
# Fetch SignIdentity from the github repo secrets, with the name SURFER_CERT_PATCH_ISSUER
$SignIdentityIssuer = (Invoke-RestMethod -Uri "https://api.github.com/repos/zen-browser/desktop/actions/secrets/SURFER_CERT_PATCH_ISSUER" -Headers @{Authorization = "Bearer $token"}).value
$SignIdentity = (Invoke-RestMethod -Uri "https://api.github.com/repos/zen-browser/desktop/actions/secrets/SURFER_CERT_PATCH_NAME" -Headers @{Authorization = "Bearer $token"}).value
$SignIndentityIssuerPrev = (Invoke-RestMethod -Uri "https://api.github.com/repos/zen-browser/desktop/actions/secrets/SURFER_CERT_PATCH_ISSUER_PREV" -Headers @{Authorization = "Bearer $token"}).value
$SignIdentityPrev = (Invoke-RestMethod -Uri "https://api.github.com/repos/zen-browser/desktop/actions/secrets/SURFER_CERT_PATCH_NAME_PREV" -Headers @{Authorization = "Bearer $token"}).
$env:SURFER_CERT_PATCH_ISSUER=$SignIdentityIssuer
$env:SURFER_CERT_PATCH_NAME=$SignIdentity
$env:SURFER_CERT_PATCH_NAME_PREV=$SignIdentityPrev
$env:SURFER_CERT_PATCH_ISSUER_PREV=$SignIndentityIssuerPrev
Start-Job -Name "DownloadGitl10n" -ScriptBlock {
param($PWD)
cd $PWD
@@ -46,7 +55,6 @@ npm run build
echo "Downloading artifacts info"
$artifactsInfo=gh api repos/zen-browser/desktop/actions/runs/$GithubRunId/artifacts
$token = gh auth token
function New-TemporaryDirectory {
$tmp = [System.IO.Path]::GetTempPath() # Not $env:TEMP, see https://stackoverflow.com/a/946017
@@ -215,20 +223,12 @@ SignAndPackage x86_64
$files = Get-ChildItem .\windsign-temp\windows-x64-signed-x86_64, .\windsign-temp\windows-x64-signed-arm64 -Recurse -Include *.exe
signtool.exe sign /n "$SignIdentity" /t http://time.certum.pl/ /fd sha256 /v $files
# Compress each signed bundle into a single gzip tarball (`-C <dir> .` so it has
# no top-level directory) and upload it as a release asset on the windows-binaries
# repo, keyed to this build's run id. Release assets keep the bundles out of git
# (they were too large to commit) while still living in the windows-binaries repo.
# The gated release job downloads and expands these from that repo's releases.
$binariesRepo = "zen-browser/windows-binaries"
$stagingTag = "windows-signed-$GithubRunId"
echo "Ensuring staging release $stagingTag exists on $binariesRepo"
gh release view $stagingTag --repo $binariesRepo *> $null
gh release create $stagingTag --repo $binariesRepo --prerelease --title "Windows signed bundles ($GithubRunId)" --notes "Signed Windows bundles for run $GithubRunId, consumed by the release workflow. Safe to delete."
if ($LASTEXITCODE -ne 0) {
gh release create $stagingTag --repo $binariesRepo --prerelease --title "Windows signed bundles ($GithubRunId)" --notes "Signed Windows bundles for run $GithubRunId, consumed by the release workflow. Safe to delete."
if ($LASTEXITCODE -ne 0) {
throw "Failed to create staging release $stagingTag on $binariesRepo"
}
throw "Failed to create staging release $stagingTag on $binariesRepo"
}
foreach ($name in @("x86_64", "arm64")) {

Binary file not shown.

Binary file not shown.

View File

@@ -91,11 +91,6 @@ if test "$ZEN_RELEASE"; then
export MOZ_PACKAGE_JSSHELL=1
ac_add_options --disable-crashreporter
# Experimental flag, enabled only on nightly for Firefox.
# Should bring in some nice performance improvements,
# but may cause stability issues.
ac_add_options --enable-replace-malloc
fi
ac_add_options --enable-jxl

View File

@@ -7,7 +7,21 @@ unset MOZ_STDCXX_COMPAT
ac_add_options --disable-dmd
ac_add_options --enable-eme=widevine
if test "$ZEN_RELEASE"; then
if test "$ZEN_CROSS_COMPILING"; then
ZEN_MAC_CROSS="$HOME/mac-cross"
mk_add_options "export PATH=$ZEN_MAC_CROSS/cctools/bin:$PATH"
mk_add_options "export LD_LIBRARY_PATH=$HOME/.mozbuild/clang/lib:$LD_LIBRARY_PATH"
export MKFSHFS=$ZEN_MAC_CROSS/hfsplus/newfs_hfs
export DMG_TOOL=$ZEN_MAC_CROSS/dmg/dmg
export HFS_TOOL=$ZEN_MAC_CROSS/dmg/hfsplus
if test "$ZEN_RELEASE"; then
export MOZ_LD64_KNOWN_GOOD=1
ac_add_options --enable-linker=ld64
fi
elif test "$ZEN_RELEASE"; then
ALLOWED_SDKS="26.5 26.4"
for SDK in $ALLOWED_SDKS; do
if [ -d "/Library/Developer/CommandLineTools/SDKs/MacOSX${SDK}.sdk" ]; then
@@ -52,13 +66,3 @@ else
export CXXFLAGS="$CXXFLAGS -mcpu=apple-m1"
fi
fi
# Keep using ld64 on PGO/LTO builds because of performance regressions when using lld.
# Mozilla sets "MOZ_LD64_KNOWN_GOOD" to true when they do automated builds with PGO/LTO on macOS.
# See https://searchfox.org/firefox-main/rev/e61d59b5c9a651fd7bf28043f87c0dc669833496/build/moz.configure/lto-pgo.configure#261
# export MOZ_LD64_KNOWN_GOOD=1
# ac_add_options --enable-linker=ld64
#
# if test "$ZEN_RELEASE"; then
# mk_add_options MOZ_MAKE_FLAGS="-j4"
# fi

View File

@@ -164,5 +164,5 @@ zen-window-sync-migration-dialog-learn-more = Learn More
zen-window-sync-migration-dialog-accept = Got It
zen-appmenu-new-blank-window =
.label = New blank window
.label = New Blank Window

View File

@@ -5,14 +5,14 @@
tab-zen-split-tabs =
.label =
{ $tabCount ->
[-1] Split out tab
[1] Add split view...
[-1] Split Out Tab
[1] Add Split View...
*[other] Join { $tabCount } Tabs
}
.accesskey = S
zen-split-link =
.label = Split link to new tab
.label = Split Link to New Tab
.accesskey = S
zen-split-view-modifier-header = Split View

8
package-lock.json generated
View File

@@ -11,7 +11,7 @@
"devDependencies": {
"@babel/preset-typescript": "^7.27.0",
"@zen-browser/prettier": "^3.9.3",
"@zen-browser/surfer": "^1.14.6",
"@zen-browser/surfer": "^1.14.8",
"formal-git": "^1.2.9",
"globals": "^16.3.0",
"husky": "^9.1.7",
@@ -860,9 +860,9 @@
}
},
"node_modules/@zen-browser/surfer": {
"version": "1.14.6",
"resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.14.6.tgz",
"integrity": "sha512-hgTKadIJ/9/9dizHn4229ZZHQckd7D4OR6e7HVkcmtuq1Jke3OAn6SH7u7NjvzvYy35Mb2sXjVUvZEG1ITIfgg==",
"version": "1.14.8",
"resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.14.8.tgz",
"integrity": "sha512-5HHcfibwHIK5n3huhJL2TLBX2+8odj6ebCMA6U2EcUj9ROSrcz7/bjY2n5MIa9oIRL9gtV3ott0jwJj6SlapxA==",
"dev": true,
"license": "MPL-2.0",
"dependencies": {

View File

@@ -49,7 +49,7 @@
"devDependencies": {
"@babel/preset-typescript": "^7.27.0",
"@zen-browser/prettier": "^3.9.3",
"@zen-browser/surfer": "^1.14.6",
"@zen-browser/surfer": "^1.14.8",
"formal-git": "^1.2.9",
"globals": "^16.3.0",
"husky": "^9.1.7",

View File

@@ -99,3 +99,13 @@
# Only enabled for windows, doesn't really fit inside Zen.
- name: browser.startup.preXulSkeletonUI
value: false
- name: browser.preonboarding.enabled
value: false
- name: browser.referrals.enabled
value: false
locked: true
- name: browser.shell.customIcon.enabled
value: false # For now?

View File

@@ -2,18 +2,11 @@
# 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/.
- name: browser.lowMemoryResponseMask
value: 3
condition: "defined(XP_MACOSX)"
- name: network.predictor.enable-hover-on-ssl
value: true
# See https://github.com/zen-browser/desktop/issues/11599, this pref seems to
# have disabled itself on macos for some unknown reason.
# Make sure its in sync with:
# https://searchfox.org/firefox-main/rev/1477feb9706f4ccc5bd571c1c215832a6fbb7464/modules/libpref/init/StaticPrefList.yaml#7741-7748
# https://searchfox.org/firefox-main/rev/dd2579cb6e7f1761a27ce64fb84d92c61d85c27f/modules/libpref/init/StaticPrefList.yaml#8396
- name: gfx.webrender.compositor
condition: "defined(XP_WIN) || defined(XP_DARWIN)"
condition: "defined(XP_WIN) || defined(XP_DARWIN) || defined(MOZ_WIDGET_GTK)"
value: "@cond"
mirror: once

View File

@@ -2,10 +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/.
# Enable transparent background for macos
- name: widget.macos.sidebar-blend-mode.behind-window
# Give the whole window a translucent, blurred backdrop, using the material
# below. See ZenWindowMaterialView in nsCocoaWindow.mm.
- name: zen.widget.macos.window-vibrancy
value: true
condition: "defined(XP_MACOSX)"
cpptype: bool
mirror: always
type: static
# 1. hudWindow
# 2. fullScreenUI

View File

@@ -8,9 +8,5 @@
- name: svg.context-properties.content.enabled
value: true
- name: image.avif.enabled
value: true
locked: true
- name: media.eme.enabled
value: true

View File

@@ -1,12 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
- name: services.sync.engine.spaces
value: true
condition: "@IS_TWILIGHT@"
- name: services.sync.engine.spaces
value: false
locked: true
condition: "!@IS_TWILIGHT@"

View File

@@ -21,7 +21,7 @@
value: 100
- name: zen.workspaces.switch-animation-duration
value: 200
value: 250
- name: zen.workspaces.wrap-around-navigation
value: true
@@ -32,6 +32,9 @@
- name: zen.workspaces.scroll-modifier-key
value: ctrl
- name: services.sync.engine.workspaces
value: false
- name: zen.workspaces.separate-essentials
value: true

View File

@@ -8,4 +8,4 @@ packaging==24.2
pathspec==0.12.1
platformdirs==4.3.6
pycodestyle==2.12.1
requests==2.33.0
requests==2.34.2

View File

@@ -1,8 +1,8 @@
diff --git a/.prettierignore b/.prettierignore
index 949896ff064ae0b54b6a657ea074bc88e12820f7..5249f420972667bece4d85fe8d35073afaebeb8a 100644
index bd8ab46ff7175f5039b69b04c1afe53ab8efe746..7ae12a1ff3724e99aeec2e93518640a2fa9611e6 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1803,3 +1803,12 @@ tools/ts/test/baselines/
@@ -1807,3 +1807,12 @@ tools/ts/test/baselines/
try_task_config.json
xpcom/idl-parser/xpidl/fixtures/xpctest.d.json
**/package-lock.json
@@ -12,6 +12,6 @@ index 949896ff064ae0b54b6a657ea074bc88e12820f7..5249f420972667bece4d85fe8d35073a
+*.min.js
+*.min.mjs
+*.inc
+*/mochitests/*
+**/mochitests/**
+*.svg
+

View File

@@ -1,8 +1,8 @@
diff --git a/browser/base/content/aboutDialog.js b/browser/base/content/aboutDialog.js
index f6e1391baf12abb91c85a95107bb3923118746c0..cac04aa288e8a305d0c8b28e0c919abce87658e5 100644
index a2fb4433c7044e7f5681d5762285314fa3e00a5c..dac1e79e86c534247a470ae062e59f7e7cba6e38 100644
--- a/browser/base/content/aboutDialog.js
+++ b/browser/base/content/aboutDialog.js
@@ -52,7 +52,7 @@ function init() {
@@ -58,7 +58,7 @@ function init() {
]);
let versionIdKey = "base";
let versionAttributes = {
@@ -11,7 +11,7 @@ index f6e1391baf12abb91c85a95107bb3923118746c0..cac04aa288e8a305d0c8b28e0c919abc
};
let arch = Services.sysinfo.get("arch");
@@ -64,7 +64,7 @@ function init() {
@@ -70,7 +70,7 @@ function init() {
}
let version = Services.appinfo.version;
@@ -20,7 +20,7 @@ index f6e1391baf12abb91c85a95107bb3923118746c0..cac04aa288e8a305d0c8b28e0c919abc
versionIdKey += "-nightly";
let buildID = Services.appinfo.appBuildID;
let year = buildID.slice(0, 4);
@@ -125,14 +125,6 @@ function init() {
@@ -158,14 +158,6 @@ function init() {
window.close();
});
if (AppConstants.MOZ_UPDATER) {

View File

@@ -1,5 +1,5 @@
diff --git a/browser/base/content/aboutDialog.xhtml b/browser/base/content/aboutDialog.xhtml
index 3ffd464b960a4299a7dd0cd87e4fc2f781b9d593..7a831c8ee2b73bb89bf8a82ac24958b55c16a5aa 100644
index 067eaf8d4e23f76a2423d01a1d9fa71d9ef3c65f..e0badae05d1da7e6de43e1d517539d4b09ec90f5 100644
--- a/browser/base/content/aboutDialog.xhtml
+++ b/browser/base/content/aboutDialog.xhtml
@@ -102,10 +102,6 @@
@@ -13,7 +13,7 @@ index 3ffd464b960a4299a7dd0cd87e4fc2f781b9d593..7a831c8ee2b73bb89bf8a82ac24958b5
</vbox>
#endif
</hbox>
@@ -120,26 +116,22 @@
@@ -120,12 +116,12 @@
<vbox id="experimental" hidden="true">
<description class="text-blurb" id="warningDesc" data-l10n-id="warningDesc-version"></description>
<description class="text-blurb" id="communityExperimentalDesc" data-l10n-id="community-exp">
@@ -27,13 +27,8 @@ index 3ffd464b960a4299a7dd0cd87e4fc2f781b9d593..7a831c8ee2b73bb89bf8a82ac24958b5
+ <label is="text-link" href="https://github.com/zen-browser/desktop" data-l10n-name="community-mozillaLink"/>
<label is="text-link" useoriginprincipal="true" href="about:credits" data-l10n-name="community-creditsLink"/>
</description>
- <description class="text-blurb" id="contributeDesc" data-l10n-id="helpus">
- <label is="text-link" href="https://foundation.mozilla.org/?form=firefox-about" data-l10n-name="helpus-donateLink"/>
- <label is="text-link" href="https://www.mozilla.org/contribute/?utm_source=firefox-browser&#38;utm_medium=firefox-desktop&#38;utm_campaign=about-dialog" data-l10n-name="helpus-getInvolvedLink"/>
- </description>
</vbox>
</vbox>
</hbox>
<description class="text-blurb" id="contributeDesc" data-l10n-id="helpus">
@@ -144,8 +140,8 @@
<vbox id="bottomBox">
<hbox pack="center">
<label is="text-link" class="bottom-link" useoriginprincipal="true" href="about:license" data-l10n-id="bottomLinks-license"/>

View File

@@ -1,5 +1,5 @@
diff --git a/browser/base/content/browser-box.inc.xhtml b/browser/base/content/browser-box.inc.xhtml
index 4a16fe93daeefb88af024c1dac05bc1f518c3fcb..a420768e4047937c8becefb69c1017e13fc12231 100644
index cf35762fdcc4716932c7af7cf4af4b2f72aea038..6c13e42806ce80accce464d7ec7e022a0d8e0078 100644
--- a/browser/base/content/browser-box.inc.xhtml
+++ b/browser/base/content/browser-box.inc.xhtml
@@ -3,12 +3,22 @@
@@ -28,12 +28,12 @@ index 4a16fe93daeefb88af024c1dac05bc1f518c3fcb..a420768e4047937c8becefb69c1017e1
@@ -25,7 +35,7 @@
</stack>
</vbox>
<splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" resizebefore="sibling" resizeafter="none" hidden="true"/>
<splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" resizebefore="sibling" resizeafter="none" hidden="true" role="separator" aria-controls="sidebar-box" data-l10n-id="sidebar-resize-splitter"/>
- <tabbox id="tabbrowser-tabbox" flex="1" tabcontainer="tabbrowser-tabs">
+#include zen-tabbrowser-elements.inc.xhtml
<tabpanels id="tabbrowser-tabpanels" flex="1" selectedIndex="0"/>
</tabbox>
<splitter id="ai-window-splitter" class="chromeclass-extrachrome sidebar-splitter" resizebefore="none" resizeafter="sibling" collapsed="true"/>
<splitter id="ai-window-splitter" class="chromeclass-extrachrome sidebar-splitter" resizebefore="sibling" resizeafter="sibling" collapsed="true"/>
@@ -34,3 +44,5 @@
</stack>
</vbox>

View File

@@ -1,5 +1,5 @@
diff --git a/browser/base/content/browser-fullScreenAndPointerLock.js b/browser/base/content/browser-fullScreenAndPointerLock.js
index d0d3b6fc57800b073bb1c75f6e55212749815b0a..f3d5790eed58f1cb9a36229582e0fa00f3668962 100644
index 991cbab1fca19bc20adabb73c146c26a57db68eb..5c0debc58c9614b13916e758c7f64b522756c1d4 100644
--- a/browser/base/content/browser-fullScreenAndPointerLock.js
+++ b/browser/base/content/browser-fullScreenAndPointerLock.js
@@ -502,8 +502,6 @@ var FullScreen = {
@@ -7,7 +7,7 @@ index d0d3b6fc57800b073bb1c75f6e55212749815b0a..f3d5790eed58f1cb9a36229582e0fa00
let translate = shiftSize > 0 ? `0 ${shiftSize}px` : "";
gNavToolbox.classList.toggle("fullscreen-floating-toolbox", shiftSize > 0);
- gNavToolbox.style.translate = translate;
- gURLBar.style.translate = gURLBar.hasAttribute("breakout") ? translate : "";
let searchbar = document.getElementById("searchbar-new");
if (searchbar) {
searchbar.style.translate = searchbar.hasAttribute("breakout")
- gURLBar.style.setProperty("--toolbar-shift-translate", translate);
document
.getElementById("searchbar-new")
?.style.setProperty("--toolbar-shift-translate", translate);

View File

@@ -1,16 +1,16 @@
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 1026474bb1bc026987be01a8c18fa0927cb911bc..60294e0587147d86ace8e6d6985d8c6eae8248b6 100644
index 4960f4baed32a9e9f523262591eb93550ca9c4b0..9ee825057b1b3b5a08e1d2b2c1036f1be2088da6 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -34,6 +34,7 @@ ChromeUtils.defineESModuleGetters(this, {
"resource://gre/modules/ContextualIdentityService.sys.mjs",
"moz-src:///toolkit/components/contextualidentity/ContextualIdentityService.sys.mjs",
CustomizableUI:
"moz-src:///browser/components/customizableui/CustomizableUI.sys.mjs",
+ ZenCustomizableUI: "resource:///modules/ZenCustomizableUI.sys.mjs",
DevToolsSocketStatus:
"resource://devtools/shared/security/DevToolsSocketStatus.sys.mjs",
DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs",
@@ -816,7 +817,12 @@ function UpdateBackForwardCommands(aWebNavigation) {
@@ -831,7 +832,12 @@ function UpdateBackForwardCommands(aWebNavigation) {
var backDisabled = backCommand.hasAttribute("disabled");
var forwardDisabled = forwardCommand.hasAttribute("disabled");
@@ -24,7 +24,7 @@ index 1026474bb1bc026987be01a8c18fa0927cb911bc..60294e0587147d86ace8e6d6985d8c6e
if (backDisabled) {
backCommand.removeAttribute("disabled");
} else {
@@ -3719,7 +3725,7 @@ function warnAboutClosingWindow() {
@@ -3973,7 +3979,7 @@ function warnAboutClosingWindow() {
if (!isPBWindow && !toolbar.visible) {
return gBrowser.warnAboutClosingTabs(
@@ -33,7 +33,7 @@ index 1026474bb1bc026987be01a8c18fa0927cb911bc..60294e0587147d86ace8e6d6985d8c6e
gBrowser.closingTabsEnum.ALL
);
}
@@ -3759,7 +3765,7 @@ function warnAboutClosingWindow() {
@@ -4013,7 +4019,7 @@ function warnAboutClosingWindow() {
return (
isPBWindow ||
gBrowser.warnAboutClosingTabs(
@@ -42,7 +42,7 @@ index 1026474bb1bc026987be01a8c18fa0927cb911bc..60294e0587147d86ace8e6d6985d8c6e
gBrowser.closingTabsEnum.ALL
)
);
@@ -3784,7 +3790,7 @@ function warnAboutClosingWindow() {
@@ -4038,7 +4044,7 @@ function warnAboutClosingWindow() {
AppConstants.platform != "macosx" ||
isPBWindow ||
gBrowser.warnAboutClosingTabs(
@@ -51,7 +51,7 @@ index 1026474bb1bc026987be01a8c18fa0927cb911bc..60294e0587147d86ace8e6d6985d8c6e
gBrowser.closingTabsEnum.ALL
)
);
@@ -4744,6 +4750,16 @@ var ConfirmationHint = {
@@ -4998,6 +5004,16 @@ var ConfirmationHint = {
}
document.l10n.setAttributes(this._message, messageId, l10nArgs);

View File

@@ -1,5 +1,5 @@
diff --git a/browser/base/content/navigator-toolbox.inc.xhtml b/browser/base/content/navigator-toolbox.inc.xhtml
index e7e94e13a990c154fb54bda4a3420ca00bdac009..8253b7d403734973729a5982cceafc12bab24f54 100644
index dd2f391096968564086911c532f696dc7ffb8ae1..3de617bf4fb7fa35f7d4d7b618e4673b72b953ee 100644
--- a/browser/base/content/navigator-toolbox.inc.xhtml
+++ b/browser/base/content/navigator-toolbox.inc.xhtml
@@ -2,7 +2,7 @@
@@ -26,7 +26,7 @@ index e7e94e13a990c154fb54bda4a3420ca00bdac009..8253b7d403734973729a5982cceafc12
<toolbar id="TabsToolbar"
class="browser-toolbar browser-titlebar"
fullscreentoolbar="true"
@@ -62,6 +66,8 @@
@@ -54,6 +58,8 @@
<html:sidebar-pins-promo id="drag-to-pin-promo-card"></html:sidebar-pins-promo>
<arrowscrollbox id="pinned-tabs-container" orient="horizontal" clicktoscroll=""></arrowscrollbox>
<splitter orient="vertical" id="vertical-pinned-tabs-splitter" resizebefore="sibling" resizeafter="none" hidden="true"/>
@@ -34,8 +34,8 @@ index e7e94e13a990c154fb54bda4a3420ca00bdac009..8253b7d403734973729a5982cceafc12
+<html:div id="zen-tabs-wrapper">
<hbox class="tab-drop-indicator" hidden="true"/>
<arrowscrollbox id="tabbrowser-arrowscrollbox" orient="horizontal" flex="1" clicktoscroll="" scrolledtostart="" scrolledtoend="">
<tab is="tabbrowser-tab" class="tabbrowser-tab" selected="true" visuallyselected="" fadein=""/>
@@ -81,6 +87,7 @@
<tab is="tabbrowser-tab" class="tabbrowser-tab" selected="" visuallyselected="" fadein=""/>
@@ -73,6 +79,7 @@
tooltip="dynamic-shortcut-tooltip"
data-l10n-id="tabs-toolbar-new-tab"/>
<html:span id="tabbrowser-tab-a11y-desc" hidden="true"/>
@@ -43,7 +43,7 @@ index e7e94e13a990c154fb54bda4a3420ca00bdac009..8253b7d403734973729a5982cceafc12
</tabs>
<toolbarbutton id="new-tab-button"
@@ -115,9 +122,10 @@
@@ -99,9 +106,10 @@
<toolbarbutton class="content-analysis-indicator toolbarbutton-1 content-analysis-indicator-icon"/>

View File

@@ -1,12 +1,12 @@
diff --git a/browser/components/aiwindow/ui/modules/AIWindow.sys.mjs b/browser/components/aiwindow/ui/modules/AIWindow.sys.mjs
index 88c3545431cf1a300d968c296d9b171871b15fe5..754cd644f2e7b82db40d5c06618ac1764424484c 100644
index e0b78c29ad081e6eb541eb2aeae4cb6d5cbb9b9b..ae56a624523bee66bc1d1343b455fc7cb65ebef1 100644
--- a/browser/components/aiwindow/ui/modules/AIWindow.sys.mjs
+++ b/browser/components/aiwindow/ui/modules/AIWindow.sys.mjs
@@ -308,6 +308,7 @@ export const AIWindow = {
},
_updateToolbarButtonPositions(win) {
@@ -321,6 +321,7 @@ export const AIWindow = {
* @param {boolean} [options.isToggling]
*/
_updateHamburgerMenuPosition(win, { isToggling = false } = {}) {
+ return;
const modeSwitcherButton = win.document.getElementById("ai-window-toggle");
const hamburgerMenu = win.document.getElementById("PanelUI-button");
const hamburgerMenuShouldBeAdjacent =
const targetToolbar = win.document.getElementById(
this.verticalTabsEnabled ? "nav-bar" : "TabsToolbar"

View File

@@ -1,8 +1,8 @@
diff --git a/browser/components/asrouter/modules/FeatureCallout.sys.mjs b/browser/components/asrouter/modules/FeatureCallout.sys.mjs
index bc989826e648e2528b4142940e1ae4d192940235..4cd18e67fbb52ea33ae6a9b0a47cbf2359d1b832 100644
index f6230d6f7ed589f4336387b6115ae4527cdb071b..a289f7b3a665154025121cc9184ab851a74ea33d 100644
--- a/browser/components/asrouter/modules/FeatureCallout.sys.mjs
+++ b/browser/components/asrouter/modules/FeatureCallout.sys.mjs
@@ -809,6 +809,7 @@ export class FeatureCallout {
@@ -812,6 +812,7 @@ export class FeatureCallout {
) {
return false;
}
@@ -10,11 +10,11 @@ index bc989826e648e2528b4142940e1ae4d192940235..4cd18e67fbb52ea33ae6a9b0a47cbf23
const style = this.win.getComputedStyle(el);
return style?.visibility === "visible" && style?.display !== "none";
@@ -1107,7 +1108,6 @@ export class FeatureCallout {
@@ -1115,7 +1116,6 @@ export class FeatureCallout {
type="arrow"
consumeoutsideclicks="never"
norolluponanchor="true"
- nonnative=""
position="${panel_position.panel_position_string}"
position="${panel_position?.panel_position_string}"
${hide_arrow ? "" : 'show-arrow=""'}
${autohide ? "" : 'noautohide="true"'}

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/customizableui/CustomizableUI.sys.mjs b/browser/components/customizableui/CustomizableUI.sys.mjs
index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80bbcf503b2 100644
index 491161e48044f75167a8e8a0348779cfa22fc40e..867d51b8a6b74f841afc6d84dcdfd8f2681652e5 100644
--- a/browser/components/customizableui/CustomizableUI.sys.mjs
+++ b/browser/components/customizableui/CustomizableUI.sys.mjs
@@ -13,6 +13,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
@@ -10,7 +10,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
HomePage: "resource:///modules/HomePage.sys.mjs",
PanelMultiView:
"moz-src:///browser/components/customizableui/PanelMultiView.sys.mjs",
@@ -347,7 +348,7 @@ var CustomizableUIInternal = {
@@ -348,7 +349,7 @@ var CustomizableUIInternal = {
{
type: CustomizableUI.TYPE_PANEL,
defaultPlacements: [],
@@ -19,7 +19,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
},
false
);
@@ -357,20 +358,15 @@ var CustomizableUIInternal = {
@@ -358,27 +359,23 @@ var CustomizableUIInternal = {
"back-button",
"forward-button",
"stop-reload-button",
@@ -41,27 +41,26 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
this.registerArea(
CustomizableUI.AREA_NAVBAR,
{
@@ -378,8 +374,6 @@ var CustomizableUIInternal = {
type: CustomizableUI.TYPE_TOOLBAR,
overflowable: true,
defaultPlacements: navbarPlacements,
verticalTabsDefaultPlacements: [
- "firefox-view-button",
- "alltabs-button",
],
- verticalTabsDefaultPlacements: ["alltabs-button", "ai-window-toggle"],
+ verticalTabsDefaultPlacements: [
+ ],
defaultCollapsed: false,
},
@@ -403,10 +397,7 @@ var CustomizableUIInternal = {
{
true
@@ -402,9 +399,6 @@ var CustomizableUIInternal = {
type: CustomizableUI.TYPE_TOOLBAR,
defaultPlacements: [
- "firefox-view-button",
"tabbrowser-tabs",
- "new-tab-button",
- "alltabs-button",
- "ai-window-toggle",
],
verticalTabsDefaultPlacements: [],
defaultCollapsed: null,
@@ -486,6 +477,7 @@ var CustomizableUIInternal = {
@@ -484,6 +478,7 @@ var CustomizableUIInternal = {
CustomizableUI.AREA_NAVBAR,
CustomizableUI.AREA_BOOKMARKS,
CustomizableUI.AREA_TABSTRIP,
@@ -69,7 +68,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
]);
if (AppConstants.platform != "macosx") {
toolbars.add(CustomizableUI.AREA_MENUBAR);
@@ -1262,6 +1254,9 @@ var CustomizableUIInternal = {
@@ -1285,6 +1280,9 @@ var CustomizableUIInternal = {
placements = gPlacements.get(area);
}
@@ -79,7 +78,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
// For toolbars that need it, mark as dirty.
let defaultPlacements = areaProperties.get("defaultPlacements");
if (
@@ -1769,7 +1764,6 @@ var CustomizableUIInternal = {
@@ -1793,7 +1791,6 @@ var CustomizableUIInternal = {
lazy.log.info(
"Widget " + aWidgetId + " not found, unable to remove from " + aArea
);
@@ -87,7 +86,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
}
this.notifyDOMChange(widgetNode, null, container, true, () => {
@@ -1779,7 +1773,7 @@ var CustomizableUIInternal = {
@@ -1803,7 +1800,7 @@ var CustomizableUIInternal = {
// We also need to remove the panel context menu if it's there:
this.ensureButtonContextMenu(widgetNode);
if (gPalette.has(aWidgetId) || this.isSpecialWidget(aWidgetId)) {
@@ -96,7 +95,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
} else {
window.gNavToolbox.palette.appendChild(widgetNode);
}
@@ -1947,16 +1941,16 @@ var CustomizableUIInternal = {
@@ -1971,16 +1968,16 @@ var CustomizableUIInternal = {
elem.setAttribute("skipintoolbarset", "true");
}
}
@@ -116,7 +115,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
// Handle initial state of vertical tabs.
if (isVerticalTabs) {
// Show the vertical tabs toolbar
@@ -2198,6 +2192,10 @@ var CustomizableUIInternal = {
@@ -2222,6 +2219,10 @@ var CustomizableUIInternal = {
* The identifier string of the area that aNode is being inserted into.
*/
insertWidgetBefore(aNode, aNextNode, aContainer, aAreaId) {
@@ -127,7 +126,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
this.notifyDOMChange(aNode, aNextNode, aContainer, false, () => {
this.setLocationAttributes(aNode, aAreaId);
aContainer.insertBefore(aNode, aNextNode);
@@ -4562,7 +4560,7 @@ var CustomizableUIInternal = {
@@ -4592,7 +4593,7 @@ var CustomizableUIInternal = {
* For all registered areas, builds those areas to reflect the current
* placement state of all widgets.
*/
@@ -136,7 +135,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
for (let [areaId, areaNodes] of gBuildAreas) {
let placements = gPlacements.get(areaId);
let isFirstChangedToolbar = true;
@@ -4573,7 +4571,7 @@ var CustomizableUIInternal = {
@@ -4603,7 +4604,7 @@ var CustomizableUIInternal = {
if (area.get("type") == CustomizableUI.TYPE_TOOLBAR) {
let defaultCollapsed = area.get("defaultCollapsed");
let win = areaNode.documentGlobal;
@@ -145,7 +144,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
win.setToolbarVisibility(
areaNode,
typeof defaultCollapsed == "string"
@@ -5864,6 +5862,7 @@ export var CustomizableUI = {
@@ -5899,6 +5900,7 @@ export var CustomizableUI = {
unregisterArea(aName, aDestroyPlacements) {
CustomizableUIInternal.unregisterArea(aName, aDestroyPlacements);
},
@@ -153,7 +152,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
/**
* Add a widget to an area.
* If the area to which you try to add is not known to CustomizableUI,
@@ -7827,7 +7826,9 @@ class OverflowableToolbar {
@@ -7869,7 +7871,9 @@ class OverflowableToolbar {
);
if (webExtList && CustomizableUI.isWebExtensionWidget(child.id)) {
@@ -163,7 +162,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
webExtList.insertBefore(child, webExtList.firstElementChild);
} else {
child.setAttribute("cui-anchorid", this.#defaultListButton.id);
@@ -7887,7 +7888,7 @@ class OverflowableToolbar {
@@ -7929,7 +7933,7 @@ class OverflowableToolbar {
) {
continue;
}
@@ -172,7 +171,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
if (child != aExceptChild) {
sum += getInlineSize(child);
}
@@ -7911,11 +7912,11 @@ class OverflowableToolbar {
@@ -7953,11 +7957,11 @@ class OverflowableToolbar {
parseFloat(style.paddingLeft) -
parseFloat(style.paddingRight) -
toolbarChildrenWidth;
@@ -186,7 +185,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
});
lazy.log.debug(
@@ -7930,7 +7931,39 @@ class OverflowableToolbar {
@@ -7972,7 +7976,39 @@ class OverflowableToolbar {
Math.max(targetWidth, targetChildrenWidth)
);
totalAvailWidth = Math.ceil(totalAvailWidth);
@@ -227,7 +226,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
return { isOverflowing, targetContentWidth, totalAvailWidth };
}
@@ -7991,7 +8024,11 @@ class OverflowableToolbar {
@@ -8033,7 +8069,11 @@ class OverflowableToolbar {
return;
}
}
@@ -240,7 +239,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
lazy.log.debug(
`Need ${minSize} but width is ${totalAvailWidth} so bailing`
);
@@ -8024,7 +8061,7 @@ class OverflowableToolbar {
@@ -8066,7 +8106,7 @@ class OverflowableToolbar {
}
}
if (!inserted) {
@@ -249,7 +248,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
}
child.removeAttribute("cui-anchorid");
child.removeAttribute("overflowedItem");
@@ -8150,6 +8187,9 @@ class OverflowableToolbar {
@@ -8192,6 +8232,9 @@ class OverflowableToolbar {
* if no such list exists.
*/
get #webExtList() {
@@ -259,7 +258,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
if (!this.#webExtListRef) {
let targetID = this.#toolbar.getAttribute("addon-webext-overflowtarget");
if (!targetID) {
@@ -8161,6 +8201,9 @@ class OverflowableToolbar {
@@ -8203,6 +8246,9 @@ class OverflowableToolbar {
let win = this.#toolbar.documentGlobal;
let { panel } = win.gUnifiedExtensions;
this.#webExtListRef = panel.querySelector(`#${targetID}`);
@@ -269,7 +268,7 @@ index d5d4596739cde5d3d49d6294867f5da122c526b8..c206cfb374542c496be9bf0305a0a80b
}
return this.#webExtListRef;
}
@@ -8369,7 +8412,7 @@ class OverflowableToolbar {
@@ -8411,7 +8457,7 @@ class OverflowableToolbar {
break;
}
case "mousedown": {

View File

@@ -1,20 +0,0 @@
diff --git a/browser/components/preferences/config/account-sync.mjs b/browser/components/preferences/config/account-sync.mjs
index b503987a08e2ce64bfc01c4e3a21e5e19ef834f0..b1c03a0b219fd3eddd93c1deaeb18ab79c85f168 100644
--- a/browser/components/preferences/config/account-sync.mjs
+++ b/browser/components/preferences/config/account-sync.mjs
@@ -42,6 +42,7 @@ Preferences.addAll([
{ id: "services.sync.engine.creditcards", type: "bool" },
{ id: "services.sync.engine.addons", type: "bool" },
{ id: "services.sync.engine.prefs", type: "bool" },
+ { id: "services.sync.engine.spaces", type: "bool" },
]);
/**
@@ -546,6 +547,7 @@ const SYNC_ENGINE_SETTINGS = [
type: "payments",
},
{ id: "syncAddons", pref: "services.sync.engine.addons", type: "addons" },
+ { id: "syncSpaces", pref: "services.sync.engine.spaces", type: "workspaces" },
{ id: "syncSettings", pref: "services.sync.engine.prefs", type: "settings" },
];

View File

@@ -6,7 +6,7 @@ index 64aa0d98a0622c01f3dcfff1a04bfcda368354d2..2013e04b0881ad2295d6897b91e1573c
{ id: "services.sync.engine.passwords", type: "bool" },
{ id: "services.sync.engine.addresses", type: "bool" },
{ id: "services.sync.engine.creditcards", type: "bool" },
+ { id: "services.sync.engine.spaces", type: "bool" },
+ { id: "services.sync.engine.workspaces", type: "bool" },
]);
let gSyncChooseWhatToSync = {

View File

@@ -20,7 +20,7 @@ index a893c5ec3d007820d98f5d92dd039640faa2c181..9cbd00102e44ccf98b37845474d92d57
+ <html:div class="sync-engine-workspaces">
+ <checkbox
+ data-l10n-id="sync-engine-workspaces"
+ preference="services.sync.engine.spaces"
+ preference="services.sync.engine.workspaces"
+ />
+ </html:div>
</html:div>

View File

@@ -1,8 +1,8 @@
diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js
index fcbd421c99b24e53e46131a1e21ec690814cbf4f..fe3778a57aaeebc53f7f6763ea234cbb41816186 100644
index 88675d1bcbf000b10d85a9c0980bc6069d88052c..ed3a1e809eb0fcccc5a957be7affb77be8978e32 100644
--- a/browser/components/preferences/main.js
+++ b/browser/components/preferences/main.js
@@ -662,6 +662,11 @@ function createStartupConfig(hidden = false) {
@@ -528,6 +528,11 @@ function createStartupConfig(hidden = false) {
},
],
},
@@ -14,16 +14,16 @@ index fcbd421c99b24e53e46131a1e21ec690814cbf4f..fe3778a57aaeebc53f7f6763ea234cbb
{
id: "windowsLaunchOnLogin",
l10nId: "windows-launch-on-login",
@@ -709,7 +714,7 @@ function createStartupConfig(hidden = false) {
@@ -575,7 +580,7 @@ function createStartupConfig(hidden = false) {
SettingGroupManager.registerGroups({
defaultBrowser: createDefaultBrowserConfig(),
startup: createStartupConfig(
- Services.prefs.getBoolPref("browser-settings-redesign.enabled", false)
- Services.prefs.getBoolPref("browser.settings-redesign.enabled", false)
+ false
),
});
@@ -762,7 +767,7 @@ function getBundleForLocales(newLocales) {
@@ -628,7 +633,7 @@ function getBundleForLocales(newLocales) {
])
);
return new Localization(

View File

@@ -6,7 +6,7 @@ index c379e1a5f82692406a92d9fcd3bca2769dfac5b2..af037dd3d995813d966524ac44a3795d
<image class="sync-engine-image sync-engine-prefs" alt=""/>
<label data-l10n-id="sync-currently-syncing-settings"/>
</html:div>
+ <html:div engine_preference="services.sync.engine.spaces">
+ <html:div engine_preference="services.sync.engine.workspaces">
+ <image class="sync-engine-image sync-engine-workspaces" alt=""/>
+ <label data-l10n-id="sync-currently-syncing-workspaces"/>
+ </html:div>

View File

@@ -1,8 +1,16 @@
diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs
index 4ba4dda363b602cb6f4445ef056f2f9abb1b0e1e..6b4b407e05e26faca69d9d7ac6f31510620898fe 100644
index a33deeb5b587d6a950960a1a4781176e4e730ad7..e96cfb9a5ffbe4feccdffa8b6d18ececb48d4c52 100644
--- a/browser/components/sessionstore/TabState.sys.mjs
+++ b/browser/components/sessionstore/TabState.sys.mjs
@@ -99,10 +99,28 @@ class _TabState {
@@ -8,6 +8,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
PrivacyFilter: "resource://gre/modules/sessionstore/PrivacyFilter.sys.mjs",
TabAttributes: "resource:///modules/sessionstore/TabAttributes.sys.mjs",
TabStateCache: "resource:///modules/sessionstore/TabStateCache.sys.mjs",
+ UrlbarShared: "chrome://browser/content/urlbar/UrlbarShared.mjs",
sessionStoreLogger: "resource:///modules/sessionstore/SessionLogger.sys.mjs",
});
@@ -103,10 +104,28 @@ class _TabState {
}
}
@@ -25,7 +33,7 @@ index 4ba4dda363b602cb6f4445ef056f2f9abb1b0e1e..6b4b407e05e26faca69d9d7ac6f31510
browser,
true
);
+ if (tabData.searchMode?.source === tab.documentGlobal.UrlbarUtils.RESULT_SOURCE.ZEN_ACTIONS) {
+ if (tabData.searchMode?.source === lazy.UrlbarShared.RESULT_SOURCE.ZEN_ACTIONS) {
+ delete tabData.searchMode;
+ }

View File

@@ -0,0 +1,21 @@
diff --git a/browser/components/tabbrowser/content/tab-context-menu.js b/browser/components/tabbrowser/content/tab-context-menu.js
index 4a7cb33a4d9067d469bbe09d4cd8844581642f7a..d7f75471a207cccac6ca3dec49037ac30dd76163 100644
--- a/browser/components/tabbrowser/content/tab-context-menu.js
+++ b/browser/components/tabbrowser/content/tab-context-menu.js
@@ -839,13 +839,15 @@ var TabContextMenu = {
);
contextUnpinSelectedTabs.hidden =
!this.contextTab.pinned || !this.multiselected;
-
+ gZenViewSplitter.updateContextMenuItems();
+ gZenPinnedTabManager.updatePinnedTabContextMenu(this.contextTab);
// Build Ask Chat items. The classic layout shows the full ask-chat submenu
// (#context_askChat); the alt layout shows only a flat "Summarize Page" item
// (#context_askChatSummarize). Hide whichever one this layout doesn't use so
// a pref toggle reverses cleanly.
if (!this._altTabContextMenu) {
document.getElementById("context_askChatSummarize").hidden = true;
+ document.getElementById("context_aiSeparator").hidden = true;
TabContextMenu.GenAI.buildTabMenu(
document.getElementById("context_askChat"),
this

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tab.js b/browser/components/tabbrowser/content/tab.js
index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce785ca5c2c3 100644
index 6fcef5bf0f4ac8c58515afd127c7065f26251c7c..0307d79923612b8f728bf41c13b39aa8c579171b 100644
--- a/browser/components/tabbrowser/content/tab.js
+++ b/browser/components/tabbrowser/content/tab.js
@@ -21,6 +21,7 @@
@@ -52,7 +52,7 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
return;
}
@@ -220,11 +223,25 @@
@@ -216,11 +219,25 @@
}
get visible() {
@@ -83,7 +83,7 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
}
get hidden() {
@@ -303,7 +320,7 @@
@@ -299,7 +316,7 @@
return false;
}
@@ -92,7 +92,7 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
}
get lastAccessed() {
@@ -388,7 +405,18 @@
@@ -384,7 +401,18 @@
}
get group() {
@@ -112,7 +112,7 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
}
get splitview() {
@@ -470,6 +498,10 @@
@@ -466,6 +494,10 @@
}
}
@@ -123,7 +123,7 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
// If the previous target wasn't part of this tab then this is a mouseenter event.
if (!this.contains(event.relatedTarget)) {
this._mouseenter();
@@ -499,6 +531,7 @@
@@ -495,6 +527,7 @@
if (!this.contains(event.relatedTarget)) {
this._mouseleave();
}
@@ -131,7 +131,15 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
}
on_dragstart(event) {
@@ -533,6 +566,8 @@
@@ -506,6 +539,7 @@
if (event.eventPhase == Event.CAPTURING_PHASE) {
this.style.MozUserFocus = "";
} else if (
+ event.target.classList?.contains("tab-reset-button") ||
event.target.classList?.contains("tab-close-button") ||
gSharedTabWarning.willShowSharedTabWarning(this)
) {
@@ -529,6 +563,8 @@
this.style.MozUserFocus = "ignore";
} else if (
event.target.classList.contains("tab-close-button") ||
@@ -140,7 +148,7 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
event.target.classList.contains("tab-icon-overlay") ||
event.target.classList.contains("tab-audio-button")
) {
@@ -567,7 +602,7 @@
@@ -563,7 +599,7 @@
}
} else if (
event.altKey &&
@@ -149,7 +157,7 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
) {
eventMaySelectTab = false;
} else if (!this.selected && this.multiselected) {
@@ -592,6 +627,10 @@
@@ -600,6 +636,10 @@
this.style.MozUserFocus = "";
}
@@ -160,7 +168,7 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
on_click(event) {
if (event.button != 0) {
return;
@@ -615,14 +654,31 @@
@@ -623,14 +663,31 @@
trigger: "alt_click",
});
}
@@ -193,7 +201,7 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
gBrowser.multiSelectedTabsCount > 0 &&
!event.target.classList.contains("tab-close-button") &&
!event.target.classList.contains("tab-icon-overlay") &&
@@ -634,8 +690,9 @@
@@ -642,8 +699,9 @@
}
if (
@@ -205,16 +213,16 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
) {
if (this.activeMediaBlocked) {
if (this.multiselected) {
@@ -653,7 +710,7 @@
@@ -661,7 +719,7 @@
return;
}
- if (event.target.classList.contains("tab-close-button")) {
+ if (!event.getModifierState("Accel") && event.target.classList.contains("tab-close-button")) {
if (this.multiselected) {
gBrowser.removeMultiSelectedTabs(
lazy.TabMetrics.userTriggeredContext(
@@ -673,6 +730,14 @@
gBrowser.removeMultiSelectedTabs({
metricsContext: lazy.TabMetrics.userTriggeredContext(
@@ -681,6 +739,14 @@
// (see tabbrowser-tabs 'click' handler).
gBrowser.tabContainer._blockDblClick = true;
}
@@ -229,9 +237,9 @@ index 8f2ebf3a0bd4e2af01cf41024b16bd491e8ed961..27721e26c3cd8cb066b462dedfa4ce78
}
on_dblclick(event) {
@@ -696,6 +761,8 @@
animate: true,
triggeringEvent: event,
@@ -707,6 +773,8 @@
lazy.TabMetrics.METRIC_SOURCE.TAB_STRIP
),
});
+ } else if (this.hasAttribute('zen-essential') && !event.target.classList.contains("tab-icon-overlay")) {
+ gZenPinnedTabManager._onTabResetPinButton(event, this, 'reset');

View File

@@ -1,8 +1,8 @@
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645eb49d12e9 100644
index 39b5babee5942427a82a7a64ad69e1b16efebcc1..32beac13dd4215a16de3a783db6c32da5504f9d8 100644
--- a/browser/components/tabbrowser/content/tabbrowser.js
+++ b/browser/components/tabbrowser/content/tabbrowser.js
@@ -509,6 +509,7 @@
@@ -513,6 +513,7 @@
* @type {MozBrowser[]}
*/
get splitViewBrowsers() {
@@ -10,7 +10,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
const browsers = [];
if (this.#activeSplitView) {
for (const tab of this.#activeSplitView.tabs) {
@@ -578,15 +579,66 @@
@@ -611,15 +612,66 @@
return this.tabContainer.visibleTabs;
}
@@ -76,10 +76,10 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
+ return this.tabs.filter(tab => !tab.hasAttribute("zen-glance-tab"));
+ }
+
set selectedTab(val) {
if (
gSharedTabWarning.willShowSharedTabWarning(val) ||
@@ -595,6 +647,9 @@
setSelectedTab(val, metricsContext = null) {
if (this.selectedTab === val) {
return;
@@ -632,6 +684,9 @@
) {
return;
}
@@ -88,8 +88,8 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
+ }
// Update the tab
this.tabbox.selectedTab = val;
}
@@ -662,6 +717,10 @@
@@ -708,6 +763,10 @@
userContextId = parseInt(tabArgument.getAttribute("usercontextid"), 10);
}
@@ -100,7 +100,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (openWindowInfo) {
userContextId = openWindowInfo.originAttributes.userContextId;
}
@@ -763,6 +822,8 @@
@@ -809,6 +868,8 @@
this.tabpanels.appendChild(panel);
let tab = this.tabs[0];
@@ -109,10 +109,10 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
tab.linkedPanel = uniqueId;
this._selectedTab = tab;
this._selectedBrowser = browser;
@@ -1129,18 +1190,24 @@
aTab,
{ telemetrySource = this.TabMetrics.METRIC_SOURCE.UNKNOWN } = {}
) {
@@ -1178,18 +1239,24 @@
* The context for the operation for telemetry purposes, defaults to an unknown context.
*/
pinTab(aTab, { metricsContext = this.TabMetrics.UNKNOWN_CONTEXT } = {}) {
+ aTab = gZenGlanceManager.getTabOrGlanceParent(aTab);
if (aTab.pinned || aTab == FirefoxViewHandler.tab) {
return;
@@ -135,10 +135,10 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
aTab.setAttribute("pinned", "true");
this._updateTabBarForPinnedTabs();
@@ -1148,16 +1215,25 @@
}
unpinTab(aTab) {
@@ -1206,16 +1273,25 @@
* The context for the operation for telemetry purposes, defaults to an unknown context.
*/
unpinTab(aTab, { metricsContext = this.TabMetrics.UNKNOWN_CONTEXT } = {}) {
+ aTab = gZenGlanceManager.getTabOrGlanceParent(aTab);
if (!aTab.pinned) {
return;
@@ -162,7 +162,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
});
aTab.style.marginInlineStart = "";
@@ -1372,6 +1448,9 @@
@@ -1430,6 +1506,9 @@
let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"];
@@ -172,7 +172,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (
aIconURL &&
!LOCAL_PROTOCOLS.some(protocol => aIconURL.startsWith(protocol))
@@ -1381,6 +1460,9 @@
@@ -1439,6 +1518,9 @@
);
return;
}
@@ -182,7 +182,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
let browser = this.getBrowserForTab(aTab);
browser.mIconURL = aIconURL;
@@ -1703,7 +1785,6 @@
@@ -1761,7 +1843,6 @@
// Preview mode should not reset the owner
if (!this.#previewMode && !oldTab.selected) {
@@ -190,7 +190,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
let lastRelatedTab = this.#lastRelatedTabMap.get(oldTab);
@@ -1794,6 +1875,7 @@
@@ -1852,6 +1933,7 @@
if (!this.#previewMode) {
newTab.recordTimeFromUnloadToReload();
newTab.updateLastAccessed();
@@ -198,7 +198,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
oldTab.updateLastAccessed();
// if this is the foreground window, update the last-seen timestamps.
if (this.documentGlobal == BrowserWindowTracker.getTopWindow()) {
@@ -2008,6 +2090,9 @@
@@ -2066,6 +2148,9 @@
}
let activeEl = document.activeElement;
@@ -208,7 +208,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
// If focus is on the old tab, move it to the new tab.
if (activeEl == oldTab) {
newTab.focus();
@@ -2046,7 +2131,7 @@
@@ -2104,7 +2189,7 @@
// Focus the location bar if it was previously focused for that tab.
// In full screen mode, only bother making the location bar visible
// if the tab is a blank one.
@@ -217,7 +217,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
let selectURL = () => {
if (this._asyncTabSwitching) {
// Set _awaitingSetURI flag to suppress popup notification
@@ -2334,7 +2419,12 @@
@@ -2392,7 +2477,12 @@
return this._setTabLabel(aTab, aLabel);
}
@@ -231,7 +231,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (!aLabel || (isURL && /^about:reader\?url=/.test(aLabel))) {
return false;
}
@@ -2460,7 +2550,7 @@
@@ -2518,7 +2608,7 @@
newIndex = this.selectedTab._tPos + 1;
}
@@ -240,7 +240,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (this.isTabGroupLabel(targetTab)) {
throw new Error(
"Replacing a tab group label with a tab is not supported"
@@ -2735,6 +2825,7 @@
@@ -2793,6 +2883,7 @@
uriIsAboutBlank,
userContextId,
skipLoad,
@@ -248,7 +248,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
} = {}) {
let b = document.createXULElement("browser");
// Use the JSM global to create the permanentKey, so that if the
@@ -2808,8 +2899,7 @@
@@ -2866,8 +2957,7 @@
// we use a different attribute name for this?
b.setAttribute("name", name);
}
@@ -258,7 +258,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
b.setAttribute("transparent", "true");
}
@@ -2964,7 +3054,7 @@
@@ -3022,7 +3112,7 @@
let panel = this.getPanel(browser);
let uniqueId = this._generateUniquePanelID();
@@ -267,7 +267,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
aTab.linkedPanel = uniqueId;
// Inject the <browser> into the DOM if necessary.
@@ -3024,8 +3114,8 @@
@@ -3082,8 +3172,8 @@
// If we transitioned from one browser to two browsers, we need to set
// hasSiblings=false on both the existing browser and the new browser.
if (this.tabs.length == 2) {
@@ -278,7 +278,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
} else {
aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1;
}
@@ -3210,7 +3300,6 @@
@@ -3268,7 +3358,6 @@
this.selectedTab = this.addTrustedTab(BROWSER_NEW_TAB_URL, {
tabIndex: tab._tPos + 1,
userContextId: tab.userContextId,
@@ -286,7 +286,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
focusUrlBar: true,
});
resolve(this.selectedBrowser);
@@ -3320,6 +3409,10 @@
@@ -3378,6 +3467,10 @@
schemelessInput,
hasValidUserGestureActivation = false,
textDirectiveUserActivation = false,
@@ -297,7 +297,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
} = {}
) {
// all callers of addTab that pass a params object need to pass
@@ -3330,10 +3423,25 @@
@@ -3388,10 +3481,25 @@
);
}
@@ -323,7 +323,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
// If we're opening a foreground tab, set the owner by default.
ownerTab ??= inBackground ? null : this.selectedTab;
@@ -3341,6 +3449,7 @@
@@ -3399,6 +3507,7 @@
if (this.selectedTab.owner) {
this.selectedTab.owner = null;
}
@@ -331,7 +331,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
// Find the tab that opened this one, if any. This is used for
// determining positioning, and inherited attributes such as the
@@ -3393,6 +3502,22 @@
@@ -3451,6 +3560,22 @@
noInitialLabel,
skipBackgroundNotify,
});
@@ -354,7 +354,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (insertTab) {
// Insert the tab into the tab container in the correct position.
this.#insertTabAtIndex(t, {
@@ -3401,6 +3526,7 @@
@@ -3459,6 +3584,7 @@
ownerTab,
openerTab,
pinned,
@@ -362,7 +362,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
bulkOrderedOpen,
tabGroup: tabGroup ?? openerTab?.group,
});
@@ -3419,6 +3545,7 @@
@@ -3477,6 +3603,7 @@
openWindowInfo,
skipLoad,
triggeringRemoteType,
@@ -370,7 +370,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}));
if (focusUrlBar) {
@@ -3543,6 +3670,12 @@
@@ -3601,6 +3728,12 @@
}
}
@@ -383,7 +383,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
// Additionally send pinned tab events
if (pinned) {
this.#notifyPinnedStatus(t);
@@ -3553,6 +3686,15 @@
@@ -3611,6 +3744,15 @@
if (!inBackground) {
this.selectedTab = t;
}
@@ -399,15 +399,15 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
return t;
}
@@ -3785,6 +3927,7 @@
@@ -3834,6 +3976,7 @@
insertBefore = null,
isAdoptingGroup = false,
isUserTriggered = false,
telemetryUserCreateSource = "unknown",
metricsContext = this.TabMetrics.UNKNOWN_CONTEXT,
+ forSplitView = false,
} = {}
) {
if (
@@ -3795,9 +3938,6 @@
@@ -3844,9 +3987,6 @@
!this.isSplitViewWrapper(tabOrSplitView)
)
) {
@@ -417,7 +417,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
if (!color) {
@@ -3818,9 +3958,14 @@
@@ -3867,9 +4007,14 @@
label,
isAdoptingGroup
);
@@ -432,9 +432,9 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
group,
- insertBefore?.group ?? insertBefore
);
group.addTabs(tabsAndSplitViews);
group.addTabs(tabsAndSplitViews, metricsContext);
@@ -3941,7 +4086,7 @@
@@ -3973,7 +4118,7 @@
}
this.#handleTabMove(tab, () =>
@@ -443,7 +443,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
);
}
@@ -4027,6 +4172,7 @@
@@ -4059,6 +4204,7 @@
color: group.color,
insertBefore: newTabs[0],
isAdoptingGroup: true,
@@ -451,7 +451,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
});
}
@@ -4237,6 +4383,7 @@
@@ -4269,6 +4415,7 @@
openWindowInfo,
skipLoad,
triggeringRemoteType,
@@ -459,7 +459,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
) {
// If we don't have a preferred remote type (or it is `NOT_REMOTE`), and
@@ -4297,6 +4444,7 @@
@@ -4329,6 +4476,7 @@
openWindowInfo,
name,
skipLoad,
@@ -467,7 +467,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
});
}
@@ -4510,9 +4658,9 @@
@@ -4542,9 +4690,9 @@
}
// Add a new tab if needed.
@@ -479,7 +479,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
let url = "about:blank";
if (tabData.entries?.length) {
@@ -4545,8 +4693,10 @@
@@ -4577,8 +4725,10 @@
insertTab: false,
skipLoad: true,
preferredRemoteType,
@@ -491,7 +491,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (select) {
tabToSelect = tab;
}
@@ -4568,7 +4718,8 @@
@@ -4600,7 +4750,8 @@
this.pinTab(tab);
// Then ensure all the tab open/pinning information is sent.
this._fireTabOpen(tab, {});
@@ -501,7 +501,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
let { groupId } = tabData;
const tabGroup = tabGroupWorkingData.get(groupId);
// if a tab refers to a tab group we don't know, skip any group
@@ -4588,7 +4739,10 @@
@@ -4620,7 +4771,10 @@
tabGroup.stateData.id,
tabGroup.stateData.color,
tabGroup.stateData.collapsed,
@@ -513,7 +513,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
);
tabsFragment.appendChild(tabGroup.node);
}
@@ -4643,9 +4797,21 @@
@@ -4675,9 +4829,21 @@
// to remove the old selected tab.
if (tabToSelect) {
let leftoverTab = this.selectedTab;
@@ -535,7 +535,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (tabs.length > 1 || !tabs[0].selected) {
this._updateTabsAfterInsert();
@@ -4836,11 +5002,17 @@
@@ -4882,11 +5048,17 @@
if (ownerTab) {
tab.owner = ownerTab;
}
@@ -554,7 +554,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (
!bulkOrderedOpen &&
((openerTab &&
@@ -4852,7 +5024,7 @@
@@ -4898,7 +5070,7 @@
let lastRelatedTab =
openerTab && this.#lastRelatedTabMap.get(openerTab);
let previousTab = lastRelatedTab || openerTab || this.selectedTab;
@@ -563,7 +563,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
tabGroup = previousTab.group;
}
if (
@@ -4868,7 +5040,7 @@
@@ -4914,7 +5086,7 @@
previousTab.splitview
) + 1;
} else if (previousTab.visible) {
@@ -572,7 +572,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
} else if (previousTab == FirefoxViewHandler.tab) {
elementIndex = 0;
}
@@ -4896,14 +5068,14 @@
@@ -4942,14 +5114,14 @@
}
// Ensure index is within bounds.
if (tab.pinned) {
@@ -591,7 +591,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (pinned && !itemAfter?.pinned) {
itemAfter = null;
@@ -4920,7 +5092,7 @@
@@ -4966,7 +5138,7 @@
this.tabContainer._invalidateCachedTabs();
@@ -600,7 +600,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (
(this.isTab(itemAfter) && itemAfter.group == tabGroup) ||
this.isSplitViewWrapper(itemAfter)
@@ -4951,7 +5123,11 @@
@@ -4997,7 +5169,11 @@
const tabContainer = pinned
? this.tabContainer.pinnedTabsContainer
: this.tabContainer;
@@ -612,7 +612,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
if (tab.group?.collapsed) {
@@ -4966,6 +5142,7 @@
@@ -5012,6 +5188,7 @@
if (pinned) {
this._updateTabBarForPinnedTabs();
}
@@ -620,23 +620,23 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
TabBarVisibility.update();
}
@@ -5514,6 +5691,7 @@
telemetrySource,
@@ -5568,6 +5745,7 @@
metricsContext,
} = {}
) {
+ tabs = tabs.filter(tab => !tab.hasAttribute("zen-empty-tab"));
// When 'closeWindowWithLastTab' pref is enabled, closing all tabs
// can be considered equivalent to closing the window.
if (
@@ -5603,6 +5781,7 @@
if (lastToClose) {
this.removeTab(lastToClose, aParams);
@@ -5678,6 +5856,7 @@
closedTabCount -= 1;
}
}
+ gZenUIManager.onTabClose(undefined);
} catch (e) {
console.error(e);
}
@@ -5648,6 +5827,14 @@
if (closedTabCount > 0) {
this.recordTabMetrics(
@@ -5730,6 +5909,14 @@
return;
}
@@ -651,7 +651,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
let isVisibleTab = aTab.visible;
// We have to sample the tab width now, since _beginRemoveTab might
// end up modifying the DOM in such a way that aTab gets a new
@@ -5655,6 +5842,9 @@
@@ -5737,6 +5924,9 @@
// state).
let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width;
let isLastTab = this.#isLastTabInWindow(aTab);
@@ -661,8 +661,8 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (
!this._beginRemoveTab(aTab, {
closeWindowFastpath: true,
@@ -5666,13 +5856,14 @@
telemetrySource,
@@ -5747,13 +5937,14 @@
metricsContext,
})
) {
+ delete gZenWorkspaces._isClosingWindow;
@@ -677,7 +677,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
let lockTabSizing =
!this.tabContainer.verticalMode &&
!aTab.pinned &&
@@ -5703,7 +5894,13 @@
@@ -5784,7 +5975,13 @@
// We're not animating, so we can cancel the animation stopwatch.
Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId);
aTab._closeTimeAnimTimerId = null;
@@ -692,7 +692,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
return;
}
@@ -5746,7 +5943,7 @@
@@ -5827,7 +6024,7 @@
*/
#isLastTabInWindow(tab) {
for (const otherTab of this.tabs) {
@@ -701,7 +701,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
return false;
}
}
@@ -5837,7 +6034,7 @@
@@ -5917,7 +6114,7 @@
closeWindowWithLastTab != null
? closeWindowWithLastTab
: !window.toolbar.visible ||
@@ -710,7 +710,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (closeWindow) {
// We've already called beforeunload on all the relevant tabs if we get here,
@@ -5861,6 +6058,7 @@
@@ -5941,6 +6138,7 @@
newTab = true;
}
@@ -718,7 +718,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
aTab._endRemoveArgs = [closeWindow, newTab];
// swapBrowsersAndCloseOther will take care of closing the window without animation.
@@ -5901,13 +6099,7 @@
@@ -5982,13 +6180,7 @@
aTab._mouseleave();
if (newTab) {
@@ -733,7 +733,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
} else {
TabBarVisibility.update();
}
@@ -6040,6 +6232,7 @@
@@ -6128,6 +6320,7 @@
this.tabs[i]._tPos = i;
}
@@ -741,7 +741,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (!this.#windowIsClosing) {
// update tab close buttons state
this.tabContainer._updateCloseButtons();
@@ -6225,6 +6418,7 @@
@@ -6313,6 +6506,7 @@
memory_after: await getTotalMemoryUsage(),
time_to_unload_in_ms: timeElapsed,
});
@@ -749,7 +749,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
/**
@@ -6270,6 +6464,7 @@
@@ -6358,6 +6552,7 @@
}
let excludeTabs = new Set(aExcludeTabs);
@@ -757,7 +757,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
// If this tab has a successor, it should be selectable, since
// hiding or closing a tab removes that tab as a successor.
@@ -6282,15 +6477,22 @@
@@ -6370,13 +6565,13 @@
!excludeTabs.has(aTab.owner) &&
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")
) {
@@ -772,6 +772,11 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
+ tab => !excludeTabs.has(tab) && gZenWorkspaces._shouldChangeToTab(tab) && tab !== aTab
);
if (Services.prefs.getBoolPref("browser.tabs.selectMRUOnClose", false)) {
@@ -6392,6 +6587,13 @@
}
}
+ if (remainingTabs.length > 0 && Services.prefs.getBoolPref("zen.tabs.select-recently-used-on-close")) {
+ let mostRecentTab = remainingTabs.reduce((a, b) =>
+ b.lastAccessed > a.lastAccessed ? b : a
@@ -782,7 +787,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
let tab = this.tabContainer.findNextTab(aTab, {
direction: 1,
filter: _tab => remainingTabs.includes(_tab),
@@ -6304,7 +6506,7 @@
@@ -6405,7 +6607,7 @@
}
if (tab) {
@@ -791,7 +796,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
// If no qualifying visible tab was found, see if there is a tab in
@@ -6325,7 +6527,7 @@
@@ -6426,7 +6628,7 @@
});
}
@@ -800,7 +805,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
_blurTab(aTab) {
@@ -6336,7 +6538,7 @@
@@ -6437,7 +6639,7 @@
* @returns {boolean}
* False if swapping isn't permitted, true otherwise.
*/
@@ -809,7 +814,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
// Do not allow transfering a private tab to a non-private window
// and vice versa.
if (
@@ -6390,6 +6592,7 @@
@@ -6491,6 +6693,7 @@
// fire the beforeunload event in the process. Close the other
// window if this was its last tab.
if (
@@ -817,7 +822,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
!remoteBrowser._beginRemoveTab(aOtherTab, {
adoptedByTab: aOurTab,
closeWindowWithLastTab: true,
@@ -6401,7 +6604,7 @@
@@ -6502,7 +6705,7 @@
// If this is the last tab of the window, hide the window
// immediately without animation before the docshell swap, to avoid
// about:blank being painted.
@@ -826,7 +831,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (closeWindow) {
let win = aOtherTab.documentGlobal;
win.windowUtils.suppressAnimation(true);
@@ -6535,11 +6738,13 @@
@@ -6636,11 +6839,13 @@
}
// Finish tearing down the tab that's going away.
@@ -840,7 +845,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
this.setTabTitle(aOurTab);
@@ -6759,10 +6964,10 @@
@@ -6860,10 +7065,10 @@
SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
}
@@ -853,7 +858,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
aTab.selected ||
aTab.closing ||
// Tabs that are sharing the screen, microphone or camera cannot be hidden.
@@ -6822,7 +7027,8 @@
@@ -6923,7 +7128,8 @@
* @param {object} [aOptions={}]
* Key-value pairs that will be serialized into the features string.
*/
@@ -863,7 +868,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (this.tabs.length == 1) {
return null;
}
@@ -6839,7 +7045,7 @@
@@ -6940,7 +7146,7 @@
// tell a new window to take the "dropped" tab
let args = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
args.appendElement(aTab.splitview ?? aTab);
@@ -872,7 +877,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
private: PrivateBrowsingUtils.isWindowPrivate(window),
features: Object.entries(aOptions)
.map(([key, value]) => `${key}=${value}`)
@@ -6847,6 +7053,8 @@
@@ -6948,6 +7154,8 @@
openerWindow: window,
args,
});
@@ -881,7 +886,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
/**
@@ -6959,7 +7167,7 @@
@@ -7074,7 +7282,7 @@
* `true` if element is a `<tab-group>`
*/
isTabGroup(element) {
@@ -890,7 +895,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
/**
@@ -7044,8 +7252,8 @@
@@ -7146,8 +7354,8 @@
}
// Don't allow mixing pinned and unpinned tabs.
@@ -901,7 +906,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
} else {
tabIndex = Math.max(tabIndex, this.pinnedTabCount);
}
@@ -7091,8 +7299,8 @@
@@ -7193,8 +7401,8 @@
this.#handleTabMove(
element,
() => {
@@ -912,7 +917,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
neighbor = neighbor.group;
}
if (neighbor?.splitview) {
@@ -7103,6 +7311,12 @@
@@ -7205,6 +7413,12 @@
return;
}
}
@@ -925,8 +930,8 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
if (movingForwards && neighbor) {
neighbor.after(element);
@@ -7161,23 +7375,31 @@
#moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) {
@@ -7278,23 +7492,31 @@
) {
if (this.isTabGroupLabel(targetElement)) {
targetElement = targetElement.group;
- if (!moveBefore && !targetElement.collapsed) {
@@ -963,7 +968,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
} else if (!element.pinned && targetElement && targetElement.pinned) {
// If the caller asks to move an unpinned element next to a pinned
// tab, move the unpinned element to be the first unpinned element
@@ -7190,12 +7412,35 @@
@@ -7307,12 +7529,35 @@
// move the tab group right before the first unpinned tab.
// 4. Moving a tab group and the first unpinned tab is grouped:
// move the tab group right before the first unpinned tab's tab group.
@@ -1000,7 +1005,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
// We want to include the splitview wrapper if it's the targetElement, but
// not in the case where we want to reverse tabs within the same splitview.
@@ -7204,6 +7449,7 @@
@@ -7321,6 +7566,7 @@
}
let getContainer = () =>
@@ -1008,7 +1013,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
element.pinned
? this.tabContainer.pinnedTabsContainer
: this.tabContainer;
@@ -7212,11 +7458,15 @@
@@ -7329,11 +7575,15 @@
element,
() => {
if (moveBefore) {
@@ -1024,11 +1029,11 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
+ }
}
},
metricsContext
@@ -7290,11 +7540,15 @@
* @param {TabMetricsContext} [metricsContext]
{ metricsContext }
@@ -7411,11 +7661,15 @@
* The context for the operation for telemetry purposes.
*/
moveTabToExistingGroup(aTab, aGroup, metricsContext) {
moveTabToExistingGroup(aTab, aGroup, { metricsContext } = {}) {
- if (!this.isTab(aTab)) {
+ if (!this.isTab(aTab) && !aTab.hasAttribute('split-view-group')) {
throw new Error("Can only move a tab into a tab group");
@@ -1044,7 +1049,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
if (aTab.group && aTab.group.id === aGroup.id) {
return;
@@ -7366,6 +7620,7 @@
@@ -7489,6 +7743,7 @@
let state = {
tabIndex: tab._tPos,
@@ -1052,7 +1057,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
};
if (tab.visible) {
state.elementIndex = tab.elementIndex;
@@ -7397,7 +7652,7 @@
@@ -7527,7 +7782,7 @@
let changedSplitView =
previousTabState.splitViewId != currentTabState.splitViewId;
@@ -1061,7 +1066,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
tab.dispatchEvent(
new CustomEvent("TabMove", {
bubbles: true,
@@ -7444,6 +7699,10 @@
@@ -7579,6 +7834,10 @@
moveActionCallback();
@@ -1072,7 +1077,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
// Clear tabs cache after moving nodes because the order of tabs may have
// changed.
this.tabContainer._invalidateCachedTabs();
@@ -7494,7 +7753,22 @@
@@ -7626,7 +7885,22 @@
* @returns {object}
* The new tab in the current window, null if the tab couldn't be adopted.
*/
@@ -1096,7 +1101,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
// Swap the dropped tab with a new one we create and then close
// it in the other window (making it seem to have moved between
// windows). We also ensure that the tab we create to swap into has
@@ -7537,6 +7811,8 @@
@@ -7669,6 +7943,8 @@
}
params.skipLoad = true;
let newTab = this.addWebTab("about:blank", params);
@@ -1105,7 +1110,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
aTab.container.tabDragAndDrop.finishAnimateTabMove();
@@ -8247,7 +8523,7 @@
@@ -8448,7 +8724,7 @@
// preventDefault(). It will still raise the window if appropriate.
return;
}
@@ -1114,7 +1119,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
window.focus();
aEvent.preventDefault();
}
@@ -8264,7 +8540,6 @@
@@ -8465,7 +8741,6 @@
on_TabGroupCollapse(aEvent) {
aEvent.target.tabs.forEach(tab => {
@@ -1122,7 +1127,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
});
}
@@ -8618,7 +8893,9 @@
@@ -8819,7 +9094,9 @@
let filter = this.#tabFilters.get(tab);
if (filter) {
@@ -1132,7 +1137,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
let listener = this.#tabListeners.get(tab);
if (listener) {
@@ -9423,6 +9700,7 @@
@@ -9604,6 +9881,7 @@
aWebProgress.isTopLevel
) {
this._tab.setAttribute("busy", "true");
@@ -1140,7 +1145,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
gBrowser._tabAttrModified(this._tab, ["busy"]);
this._tab._notselectedsinceload = !this._tab.selected;
}
@@ -9503,6 +9781,7 @@
@@ -9684,6 +9962,7 @@
// known defaults. Note we use the original URL since about:newtab
// redirects to a prerendered page.
const shouldRemoveFavicon =
@@ -1148,7 +1153,7 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
!this._browser.mIconURL &&
!ignoreBlank &&
!(originalLocation.spec in FAVICON_DEFAULTS);
@@ -9677,13 +9956,6 @@
@@ -9858,13 +10137,6 @@
this._browser.originalURI = aRequest.originalURI;
}
@@ -1162,13 +1167,3 @@ index c42b1a1a8df6b38886c17f71ea88e5aaa7eebc80..c741404ed973ee3ac246fe246c0f645e
}
let userContextId = this._browser.getAttribute("usercontextid") || 0;
@@ -10532,7 +10804,8 @@ var TabContextMenu = {
);
contextUnpinSelectedTabs.hidden =
!this.contextTab.pinned || !this.multiselected;
-
+ gZenViewSplitter.updateContextMenuItems();
+ gZenPinnedTabManager.updatePinnedTabContextMenu(this.contextTab);
// Build Ask Chat items
TabContextMenu.GenAI.buildTabMenu(
document.getElementById("context_askChat"),

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tabgroup.js b/browser/components/tabbrowser/content/tabgroup.js
index e78fa0dec83424c0059c081f83fda0d23bdb5a94..a7de584d9029ff9e55d809d50377593e398ee999 100644
index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e356c9f8c6f 100644
--- a/browser/components/tabbrowser/content/tabgroup.js
+++ b/browser/components/tabbrowser/content/tabgroup.js
@@ -14,11 +14,11 @@
@@ -129,7 +129,7 @@ index e78fa0dec83424c0059c081f83fda0d23bdb5a94..a7de584d9029ff9e55d809d50377593e
}
get color() {
@@ -335,6 +366,9 @@
@@ -330,6 +361,9 @@
}
set collapsed(val) {
@@ -139,7 +139,7 @@ index e78fa0dec83424c0059c081f83fda0d23bdb5a94..a7de584d9029ff9e55d809d50377593e
if (!!val == this.collapsed) {
return;
}
@@ -421,7 +455,6 @@
@@ -416,7 +450,6 @@
tabGroupName,
})
.then(result => {
@@ -147,7 +147,7 @@ index e78fa0dec83424c0059c081f83fda0d23bdb5a94..a7de584d9029ff9e55d809d50377593e
});
}
@@ -496,13 +529,68 @@
@@ -491,13 +524,68 @@
* @returns {MozTabbrowserTab[]}
*/
get tabs() {
@@ -221,15 +221,17 @@ index e78fa0dec83424c0059c081f83fda0d23bdb5a94..a7de584d9029ff9e55d809d50377593e
}
/**
@@ -610,7 +698,6 @@
);
@@ -617,9 +705,6 @@
});
} else {
if (tabOrSplitView.pinned) {
- tabOrSplitView.documentGlobal.gBrowser.unpinTab(tabOrSplitView);
- tabOrSplitView.documentGlobal.gBrowser.unpinTab(tabOrSplitView, {
- metricsContext,
- });
}
let tabToMove =
this.documentGlobal === tabOrSplitView.documentGlobal
@@ -679,7 +766,7 @@
@@ -682,7 +767,7 @@
*/
on_click(event) {
let isToggleElement =
@@ -238,7 +240,7 @@ index e78fa0dec83424c0059c081f83fda0d23bdb5a94..a7de584d9029ff9e55d809d50377593e
event.target === this.#overflowCountLabel;
if (isToggleElement && event.button === 0) {
event.preventDefault();
@@ -758,5 +845,6 @@
@@ -761,5 +846,6 @@
}
}

View File

@@ -1,21 +0,0 @@
diff --git a/browser/components/urlbar/UrlbarController.sys.mjs b/browser/components/urlbar/UrlbarController.sys.mjs
index a05894d593e4149097c473822a38f87b2220625f..1660106c2a6548920fdffd2656e5a1f12c2d548b 100644
--- a/browser/components/urlbar/UrlbarController.sys.mjs
+++ b/browser/components/urlbar/UrlbarController.sys.mjs
@@ -305,7 +305,6 @@ export class UrlbarController {
const isMac = AppConstants.platform == "macosx";
// Handle readline/emacs-style navigation bindings on Mac.
if (
- isMac &&
this.view.isOpen &&
event.ctrlKey &&
(event.key == "n" || event.key == "p")
@@ -494,6 +493,8 @@ export class UrlbarController {
});
}
event.preventDefault();
+ } else if (!this.input.value && !(event.ctrlKey || event.altKey || event.shiftKey)) {
+ this.browserWindow.gZenUIManager.enableCommandsMode(event);
}
break;
}

View File

@@ -1,14 +1,14 @@
diff --git a/browser/components/urlbar/UrlbarMuxerStandard.sys.mjs b/browser/components/urlbar/UrlbarMuxerStandard.sys.mjs
index 16041c10755adced9d665539796737a9f55712de..2232bdcc02e20dbb384ca0529a8bd8ce73dc6284 100644
index 65bd41b2ea14c26d490632d4a5348d6cf33ee9dd..80fbd685156949b6c7e93ed9d0ef56350dd1a0fe 100644
--- a/browser/components/urlbar/UrlbarMuxerStandard.sys.mjs
+++ b/browser/components/urlbar/UrlbarMuxerStandard.sys.mjs
@@ -837,11 +837,16 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
@@ -925,11 +925,16 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
result.providerName == "UrlbarProviderHeuristicFallback" &&
state.context.heuristicResult?.providerName !=
"UrlbarProviderHeuristicFallback"
+ && !(
+ result.type == UrlbarUtils.RESULT_TYPE.SEARCH &&
+ state.context.heuristicResult?.type == UrlbarUtils.RESULT_TYPE.URL
+ result.type == lazy.UrlbarShared.RESULT_TYPE.SEARCH &&
+ state.context.heuristicResult?.type == lazy.UrlbarShared.RESULT_TYPE.URL
+ )
) {
return false;
@@ -19,11 +19,11 @@ index 16041c10755adced9d665539796737a9f55712de..2232bdcc02e20dbb384ca0529a8bd8ce
// Discard the result if a tab-to-search result was added already.
if (!state.canAddTabToSearch) {
return false;
@@ -1491,7 +1496,9 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
@@ -1593,7 +1598,9 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
usedLimits.maxResultCount++;
}
+ if (!(result.heuristic && result.source == UrlbarUtils.RESULT_SOURCE.ZEN_ACTIONS)) {
+ if (!(result.heuristic && result.source == lazy.UrlbarShared.RESULT_SOURCE.ZEN_ACTIONS)) {
state.usedResultSpan += span;
+ }
this._updateStatePostAdd(result, state);

View File

@@ -1,8 +1,18 @@
diff --git a/browser/components/urlbar/UrlbarPrefs.sys.mjs b/browser/components/urlbar/UrlbarPrefs.sys.mjs
index 2d21248256c6c2bfb8dac958133c10e3251ef564..f788bd10ec2c08e4b27b77cd3bb0489fb04e8b7a 100644
index 89f0d44d462de3d7d0f581d6371606f475443822..0d45ce5f6455e9c7276c54f504906bade5b3d286 100644
--- a/browser/components/urlbar/UrlbarPrefs.sys.mjs
+++ b/browser/components/urlbar/UrlbarPrefs.sys.mjs
@@ -462,6 +462,7 @@ const PREF_URLBAR_DEFAULTS = /** @type {PreferenceDefinition[]} */ ([
@@ -163,6 +163,9 @@ const PREF_URLBAR_DEFAULTS = /** @type {PreferenceDefinition[]} */ ([
// Feature gate pref for flight status suggestions in the urlbar.
["flightStatus.featureGate", false],
+ // Whether to close the urlbar when blurring the window while the urlbar is focused.
+ ["closeOnWindowBlur", true],
+
// The minimum prefix length of a flight status keyword the user must type to
// trigger the suggestion. 0 means the min length should be taken from Nimbus
// or remote settings.
@@ -482,6 +485,7 @@ const PREF_URLBAR_DEFAULTS = /** @type {PreferenceDefinition[]} */ ([
["shortcuts.tabs", true],
["shortcuts.history", true],
["shortcuts.actions", true],
@@ -10,7 +20,7 @@ index 2d21248256c6c2bfb8dac958133c10e3251ef564..f788bd10ec2c08e4b27b77cd3bb0489f
// Boolean to determine if the providers defined in `exposureResults`
// should be displayed in search results. This can be set by a
@@ -799,6 +800,8 @@ function makeDefaultResultGroups({ showSearchSuggestionsFirst }) {
@@ -840,6 +844,8 @@ function makeDefaultResultGroups({
*/
let rootGroup = {
children: [

View File

@@ -1,16 +1,16 @@
diff --git a/browser/components/urlbar/UrlbarProvidersManager.sys.mjs b/browser/components/urlbar/UrlbarProvidersManager.sys.mjs
index d2e2415e6b7c8833617dd1d4d01b16b110afbfa5..4a1e6e0940789b55144afd0566ecb91d88f7d590 100644
index 67f51c7996c24549f39594c9a518bc5316350ce7..d66969f2411bb687c15448ad828b64ddf43c3389 100644
--- a/browser/components/urlbar/UrlbarProvidersManager.sys.mjs
+++ b/browser/components/urlbar/UrlbarProvidersManager.sys.mjs
@@ -914,6 +914,7 @@ export class Query {
if (
result.heuristic &&
this.context.searchMode &&
+ !(this.context.searchMode.source === lazy.UrlbarUtils.RESULT_SOURCE.ZEN_ACTIONS && result.payload?.zenAction) &&
+ !(this.context.searchMode.source === lazy.UrlbarShared.RESULT_SOURCE.ZEN_ACTIONS && result.payload?.zenAction) &&
(!this.context.trimmedSearchString ||
(!this.context.searchMode.engineName && !result.autofill))
) {
@@ -1044,6 +1045,7 @@ function updateSourcesIfEmpty(context) {
@@ -1060,6 +1061,7 @@ function updateSourcesIfEmpty(context) {
lazy.UrlbarShared.TOKEN_TYPE.RESTRICT_TITLE,
lazy.UrlbarShared.TOKEN_TYPE.RESTRICT_URL,
lazy.UrlbarShared.TOKEN_TYPE.RESTRICT_ACTION,
@@ -18,11 +18,11 @@ index d2e2415e6b7c8833617dd1d4d01b16b110afbfa5..4a1e6e0940789b55144afd0566ecb91d
].includes(t.type)
);
@@ -1103,6 +1105,14 @@ function updateSourcesIfEmpty(context) {
@@ -1119,6 +1121,14 @@ function updateSourcesIfEmpty(context) {
acceptedSources.push(source);
}
break;
+ case lazy.UrlbarUtils.RESULT_SOURCE.WORKSPACES:
+ case lazy.UrlbarShared.RESULT_SOURCE.WORKSPACES:
+ if (
+ restrictTokenType === lazy.UrlbarShared.TOKEN_TYPE.RESTRICT_WORKSPACE ||
+ !restrictTokenType
@@ -30,6 +30,6 @@ index d2e2415e6b7c8833617dd1d4d01b16b110afbfa5..4a1e6e0940789b55144afd0566ecb91d
+ acceptedSources.push(source);
+ }
+ break;
case lazy.UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL:
case lazy.UrlbarUtils.RESULT_SOURCE.ADDON:
case lazy.UrlbarShared.RESULT_SOURCE.OTHER_LOCAL:
case lazy.UrlbarShared.RESULT_SOURCE.ADDON:
default:

View File

@@ -1,8 +1,8 @@
diff --git a/browser/components/urlbar/UrlbarUtils.sys.mjs b/browser/components/urlbar/UrlbarUtils.sys.mjs
index aa7c67f2bfaa3f15d592a14b527a8721dfc9bc6f..d2fe012796ea3a5be05090a732011b3cf92b78be 100644
index 78c76bde00b6b581184cee1cd0e1756e5f2da6a4..94c713470b1240729ef2350d090b0449f3801af4 100644
--- a/browser/components/urlbar/UrlbarUtils.sys.mjs
+++ b/browser/components/urlbar/UrlbarUtils.sys.mjs
@@ -110,6 +110,8 @@ export var UrlbarUtils = {
@@ -126,6 +126,8 @@ export var UrlbarUtils = {
SEMANTIC_HISTORY: "semanticHistory",
SUGGESTED_INDEX: "suggestedIndex",
TAIL_SUGGESTION: "tailSuggestion",
@@ -11,22 +11,13 @@ index aa7c67f2bfaa3f15d592a14b527a8721dfc9bc6f..d2fe012796ea3a5be05090a732011b3c
}),
// Defines provider types.
@@ -171,6 +173,8 @@ export var UrlbarUtils = {
OTHER_NETWORK: 6,
ADDON: 7,
ACTIONS: 8,
+ ZEN_ACTIONS: 9,
+ WORKSPACES: 10,
}),
// Per-result exposure telemetry.
@@ -320,6 +324,14 @@ export var UrlbarUtils = {
@@ -274,6 +276,14 @@ export var UrlbarUtils = {
telemetryLabel: "actions",
uiLabel: "urlbar-searchmode-actions2",
uiLabel: "urlbar-searchmode-actions3",
},
+ {
+ source: this.RESULT_SOURCE.WORKSPACES,
+ restrict: lazy.UrlbarShared.RESTRICT_TOKENS.WORKSPACE,
+ source: UrlbarShared.RESULT_SOURCE.WORKSPACES,
+ restrict: UrlbarShared.RESTRICT_TOKENS.WORKSPACE,
+ icon: "chrome://browser/skin/zen-icons/selectable/layers.svg",
+ pref: "shortcuts.workspaces",
+ telemetryLabel: "workspaces",
@@ -35,12 +26,12 @@ index aa7c67f2bfaa3f15d592a14b527a8721dfc9bc6f..d2fe012796ea3a5be05090a732011b3c
]);
},
@@ -612,6 +624,12 @@ export var UrlbarUtils = {
@@ -566,6 +576,12 @@ export var UrlbarUtils = {
return this.RESULT_GROUP.HEURISTIC_FALLBACK;
case "UrlbarProviderHistoryUrlHeuristic":
return this.RESULT_GROUP.HEURISTIC_HISTORY_URL;
+ case "ZenUrlbarProviderGlobalActions":
+ if (result.source == this.RESULT_SOURCE.WORKSPACES) {
+ if (result.source == UrlbarShared.RESULT_SOURCE.WORKSPACES) {
+ return this.RESULT_GROUP.ZEN_WORKSPACE;
+ } else {
+ return this.RESULT_GROUP.ZEN_ACTION;

View File

@@ -0,0 +1,21 @@
diff --git a/browser/components/urlbar/content/UrlbarChildController.mjs b/browser/components/urlbar/content/UrlbarChildController.mjs
index a8e9d3093d046612650a17970330a8279f55833f..063a3e8adf009d6c0ddc60430bc0e7485e812b8a 100644
--- a/browser/components/urlbar/content/UrlbarChildController.mjs
+++ b/browser/components/urlbar/content/UrlbarChildController.mjs
@@ -258,7 +258,6 @@ export class UrlbarChildController {
const isMac = AppConstants.platform == "macosx";
// Handle readline/emacs-style navigation bindings on Mac.
if (
- isMac &&
this.view.isOpen &&
event.ctrlKey &&
(event.key == "n" || event.key == "p")
@@ -450,6 +449,8 @@ export class UrlbarChildController {
});
}
event.preventDefault();
+ } else if (!this.input.value && !(event.ctrlKey || event.altKey || event.shiftKey)) {
+ this.window.gZenUIManager.enableCommandsMode(event);
}
break;
}

View File

@@ -1,9 +1,9 @@
diff --git a/browser/components/urlbar/content/UrlbarInput.mjs b/browser/components/urlbar/content/UrlbarInput.mjs
index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1403a3630 100644
index e7e9495e56076cd112beafb8297dece4ae4cea58..95e4333866a5f0d41fbdbe23910c396406a247e9 100644
--- a/browser/components/urlbar/content/UrlbarInput.mjs
+++ b/browser/components/urlbar/content/UrlbarInput.mjs
@@ -98,6 +98,13 @@ const lazy = XPCOMUtils.declareLazy({
logger: () => lazy.UrlbarUtils.getLogger({ prefix: "Input" }),
@@ -101,6 +101,13 @@ const lazy = XPCOMUtils.declareLazy({
logger: () => UrlbarShared.getLogger({ prefix: "Input" }),
});
+XPCOMUtils.defineLazyPreferenceGetter(
@@ -16,7 +16,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
const UNLIMITED_MAX_RESULTS = 99;
let getBoundsWithoutFlushing = element =>
@@ -770,7 +777,16 @@ ${
@@ -769,7 +776,16 @@ ${
// See _on_select(). HTMLInputElement.select() dispatches a "select"
// event but does not set the primary selection.
this._suppressPrimaryAdjustment = true;
@@ -33,7 +33,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
this._suppressPrimaryAdjustment = false;
}
@@ -844,6 +860,10 @@ ${
@@ -843,6 +859,10 @@ ${
hideSearchTerms = false,
isSameDocument = false,
} = {}) {
@@ -44,7 +44,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
if (!this.#isAddressbar) {
throw new Error(
"Cannot set URI for UrlbarInput that is not an address bar"
@@ -1138,7 +1158,16 @@ ${
@@ -1137,7 +1157,16 @@ ${
this.searchModeSwitcher?.updateSearchIcon();
}
@@ -61,7 +61,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
}
/**
@@ -1630,7 +1659,11 @@ ${
@@ -1626,7 +1655,11 @@ ${
openParams.avoidBrowserFocus = keepViewOpen;
if (!this.#providesSearchMode(result) && !keepViewOpen) {
@@ -74,7 +74,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
}
if (isCanonized) {
@@ -2940,6 +2973,42 @@ ${
@@ -2974,6 +3007,42 @@ ${
await this.#updateLayoutBreakoutDimensions();
}
@@ -117,7 +117,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
startLayoutExtend() {
if (!this.#allowBreakout || this.hasAttribute("breakout-extend")) {
// Do not expand if the Urlbar does not support being expanded or it is
@@ -2957,6 +3026,13 @@ ${
@@ -2988,6 +3057,13 @@ ${
this.toggleAttribute("breakout-extend", true);
this.#updateTextboxPosition();
@@ -131,7 +131,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
// Enable the animation only after the first extend call to ensure it
// doesn't run when opening a new window.
if (!this.hasAttribute("breakout-extend-animate")) {
@@ -2984,6 +3060,29 @@ ${
@@ -3011,6 +3087,29 @@ ${
return;
}
@@ -161,7 +161,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
this.toggleAttribute("breakout-extend", false);
this.#updateTextboxPosition();
}
@@ -3031,7 +3130,7 @@ ${
@@ -3049,7 +3148,7 @@ ${
forceUnifiedSearchButtonAvailable = false
) {
let prevState = this.getAttribute("pageproxystate");
@@ -170,7 +170,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
this.setAttribute("pageproxystate", state);
this._inputContainer.setAttribute("pageproxystate", state);
this._identityBox?.setAttribute("pageproxystate", state);
@@ -3314,10 +3413,12 @@ ${
@@ -3332,10 +3431,12 @@ ${
}
this.style.top = px(
@@ -183,7 +183,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
);
}
@@ -3376,9 +3477,10 @@ ${
@@ -3394,9 +3495,10 @@ ${
return;
}
@@ -195,7 +195,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
);
this.style.setProperty(
"--urlbar-height",
@@ -3883,6 +3985,7 @@ ${
@@ -3902,6 +4004,7 @@ ${
}
_toggleActionOverride(event) {
@@ -203,7 +203,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
if (
event.keyCode == KeyEvent.DOM_VK_SHIFT ||
event.keyCode == KeyEvent.DOM_VK_ALT ||
@@ -3995,8 +4098,8 @@ ${
@@ -4014,8 +4117,8 @@ ${
if (!this.#isAddressbar) {
return val;
}
@@ -214,7 +214,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
: val;
// Only trim value if the directionality doesn't change to RTL and we're not
// showing a strikeout https protocol.
@@ -4298,6 +4401,7 @@ ${
@@ -4317,6 +4420,7 @@ ${
browser = this.window.gBrowser.selectedBrowser,
keepViewOpen = false
) {
@@ -222,7 +222,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
if (this.#isAddressbar) {
this.#prepareAddressbarLoad(
url,
@@ -4411,6 +4515,10 @@ ${
@@ -4430,6 +4534,10 @@ ${
}
reuseEmpty = true;
}
@@ -233,7 +233,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
if (
where == "tab" &&
reuseEmpty &&
@@ -4418,6 +4526,9 @@ ${
@@ -4437,6 +4545,9 @@ ${
) {
where = "current";
}
@@ -243,7 +243,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
return where;
}
@@ -4672,6 +4783,7 @@ ${
@@ -4691,6 +4802,7 @@ ${
this.setResultForCurrentValue(null);
this.handleCommand();
this.controller.clearLastQueryContextCache();
@@ -251,7 +251,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
this._suppressStartQuery = false;
});
@@ -4679,7 +4791,6 @@ ${
@@ -4698,7 +4810,6 @@ ${
contextMenu.addEventListener("popupshowing", () => {
// Close the results pane when the input field contextual menu is open,
// because paste and go doesn't want a result selection.
@@ -259,7 +259,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
let controller =
this.document.commandDispatcher.getControllerForCommand("cmd_paste");
@@ -4842,7 +4953,11 @@ ${
@@ -4979,7 +5090,11 @@ ${
if (!engineName && !source && !this.hasAttribute("searchmode")) {
return;
}
@@ -272,7 +272,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
if (this._searchModeIndicatorTitle) {
this._searchModeIndicatorTitle.textContent = "";
this._searchModeIndicatorTitle.removeAttribute("data-l10n-id");
@@ -5159,6 +5274,7 @@ ${
@@ -5297,6 +5412,7 @@ ${
this.document.l10n.setAttributes(
this.inputField,
@@ -280,7 +280,20 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
l10nId,
l10nId == "urlbar-placeholder-with-name"
? { name: engineName }
@@ -5282,6 +5398,11 @@ ${
@@ -5347,6 +5463,12 @@ ${
}
lazy.logger.debug("Blur Event");
+ if (
+ this.document.commandDispatcher.focusedElement == this.inputField &&
+ !lazy.UrlbarPrefs.get("closeOnWindowBlur")
+ ) {
+ return;
+ }
// We cannot count every blur events after a missed engagement as abandoment
// because the user may have clicked on some view element that executes
// a command causing a focus change. For example opening preferences from
@@ -5424,6 +5546,11 @@ ${
}
_on_click(event) {
@@ -292,10 +305,10 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
switch (event.target) {
case this.inputField:
case this._inputContainer:
@@ -5371,10 +5492,11 @@ ${
@@ -5513,10 +5640,11 @@ ${
}
if (untrim) {
this._setValue(this._untrimmedValue);
this.setValue(this._untrimmedValue);
+ this.setSelectionRange(0, this.value.length);
}
}
@@ -305,7 +318,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
this.view.autoOpen({ event });
} else {
if (this._untrimOnFocusAfterKeydown) {
@@ -5414,9 +5536,16 @@ ${
@@ -5556,9 +5684,16 @@ ${
}
_on_mousedown(event) {
@@ -323,7 +336,7 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
if (
event.composedTarget != this.inputField &&
event.composedTarget != this._inputContainer
@@ -5426,6 +5555,10 @@ ${
@@ -5568,6 +5703,10 @@ ${
this.focusedViaMousedown = !this.focused;
this.#preventClickSelectsAll = this.focused;
@@ -334,21 +347,21 @@ index 0b1b4b2f0f8d6b0fb126aa1224409ab6f1ffb8d8..4405e1bf385477c2161ae3a5a62e32c1
// Keep the focus status, since the attribute may be changed
// upon calling this.focus().
@@ -5461,7 +5594,7 @@ ${
}
// Don't close the view when clicking on a tab; we may want to keep the
@@ -5605,7 +5744,7 @@ ${
// view open on tab switch, and the TabSelect event arrived earlier.
- if (event.target.closest?.("tab")) {
+ if (event.target.closest?.("tab") || event.target.closest?.("#tabs-newtab-button")) {
// Also ignore mousedown on the urlbarView context menu: opening/closing the
// view is already handled by the result opening flow.
- if (event.target.closest?.("tab, #urlbarView-context-menu")) {
+ if (event.target.closest?.("tab, #urlbarView-context-menu") || event.target.closest?.("#tabs-newtab-button")) {
break;
}
@@ -5750,7 +5883,7 @@ ${
@@ -5894,7 +6033,7 @@ ${
// When we are in actions search mode we can show more results so
// increase the limit.
let maxResults =
- this.searchMode?.source != lazy.UrlbarUtils.RESULT_SOURCE.ACTIONS
+ this.searchMode?.source != lazy.UrlbarUtils.RESULT_SOURCE.ZEN_ACTIONS
- this.searchMode?.source != UrlbarShared.RESULT_SOURCE.ACTIONS
+ this.searchMode?.source != UrlbarShared.RESULT_SOURCE.ZEN_ACTIONS
? lazy.UrlbarPrefs.get("maxRichResults")
: UNLIMITED_MAX_RESULTS;
let options = {

View File

@@ -1,8 +1,8 @@
diff --git a/browser/components/urlbar/content/UrlbarShared.mjs b/browser/components/urlbar/content/UrlbarShared.mjs
index 5522d8a8c8d9549453c1700ff6fec40be52747ce..7b8ad33cc337907249749074057254bf7e316994 100644
index 5b45afb747bfcdbd06782186737669aa2c4c634d..f68bd009f70415b5fb513abdfe19b4427ceefbfc 100644
--- a/browser/components/urlbar/content/UrlbarShared.mjs
+++ b/browser/components/urlbar/content/UrlbarShared.mjs
@@ -32,6 +32,7 @@ export const UrlbarShared = {
@@ -47,6 +47,7 @@ export const UrlbarShared = {
// `looksLikeOrigin()` returned `LOOKS_LIKE_ORIGIN.OTHER` for this token.
// It may or may not be an origin.
POSSIBLE_ORIGIN_BUT_SEARCH_ALLOWED: 12,
@@ -10,19 +10,28 @@ index 5522d8a8c8d9549453c1700ff6fec40be52747ce..7b8ad33cc337907249749074057254bf
}),
/**
@@ -52,6 +53,7 @@ export const UrlbarShared = {
@@ -67,6 +68,7 @@ export const UrlbarShared = {
TITLE: "#",
URL: "$",
ACTION: ">",
+ WORKSPACE: "`",
}),
// Defines UrlbarResult types.
@@ -112,6 +114,8 @@ export const UrlbarShared = {
OTHER_NETWORK: 6,
ADDON: 7,
ACTIONS: 8,
+ ZEN_ACTIONS: 9,
+ WORKSPACES: 10,
}),
/**
@@ -68,6 +70,7 @@ export const UrlbarShared = {
@@ -128,6 +132,7 @@ export const UrlbarShared = {
if (lazy.UrlbarPrefs.get("scotchBonnet.enableOverride")) {
keys.push(this.RESTRICT_TOKENS.ACTION);
}
+ keys.push(this.RESTRICT_TOKENS.WORKSPACE);
return new Set(keys);
},
};

View File

@@ -1,8 +1,8 @@
diff --git a/browser/components/urlbar/content/UrlbarView.mjs b/browser/components/urlbar/content/UrlbarView.mjs
index 8afb2bf4a757b3ef7902f5a6e6eed6b70ca2845e..440dea1e66540ca1998cb7464b6695ac823fedcb 100644
index e465806c4ae4fc372d9aa2b71aa7f0e74c65d026..c0b3781901298bedee2736819a93edbf545507a7 100644
--- a/browser/components/urlbar/content/UrlbarView.mjs
+++ b/browser/components/urlbar/content/UrlbarView.mjs
@@ -674,7 +674,7 @@ export class UrlbarView {
@@ -803,7 +803,7 @@ export class UrlbarView {
!this.input.value ||
this.input.getAttribute("pageproxystate") == "valid"
) {
@@ -11,7 +11,7 @@ index 8afb2bf4a757b3ef7902f5a6e6eed6b70ca2845e..440dea1e66540ca1998cb7464b6695ac
// Try to reuse the cached top-sites context. If it's not cached, then
// there will be a gap of time between when the input is focused and
// when the view opens that can be perceived as flicker.
@@ -812,10 +812,6 @@ export class UrlbarView {
@@ -941,10 +941,6 @@ export class UrlbarView {
}
// If search mode isn't active, close the view.
@@ -22,7 +22,7 @@ index 8afb2bf4a757b3ef7902f5a6e6eed6b70ca2845e..440dea1e66540ca1998cb7464b6695ac
// Search mode is active. If the one-offs should be shown, make sure they
// are enabled and show the view.
@@ -3031,6 +3027,8 @@ export class UrlbarView {
@@ -3203,6 +3199,8 @@ export class UrlbarView {
if (row?.hasAttribute("row-selectable")) {
row?.toggleAttribute("selected", true);
}
@@ -31,7 +31,7 @@ index 8afb2bf4a757b3ef7902f5a6e6eed6b70ca2845e..440dea1e66540ca1998cb7464b6695ac
if (element != row) {
row?.toggleAttribute("descendant-selected", true);
}
@@ -3544,7 +3542,7 @@ export class UrlbarView {
@@ -3715,7 +3713,7 @@ export class UrlbarView {
}
#enableOrDisableRowWrap() {
@@ -40,3 +40,16 @@ index 8afb2bf4a757b3ef7902f5a6e6eed6b70ca2845e..440dea1e66540ca1998cb7464b6695ac
this.#rows.toggleAttribute("wrap", wrap);
this.oneOffSearchButtons?.container.toggleAttribute("wrap", wrap);
}
@@ -4144,6 +4142,12 @@ export class UrlbarView {
}
on_blur() {
+ if (
+ this.document.commandDispatcher.focusedElement == this.input.inputField &&
+ !lazy.UrlbarPrefs.get("closeOnWindowBlur")
+ ) {
+ return;
+ }
// If the view is open without the input being focused, it will not close
// automatically when the window loses focus. We might be in this state
// after a Search Tip is shown on an engine homepage.

View File

@@ -1,11 +1,11 @@
diff --git a/browser/themes/linux/browser.css b/browser/themes/linux/browser.css
index 5e5d39787674d1d5ac8c39edccb04f8b8993fbb8..6c8b483ad19d9b26232592c68a7f2a6887161057 100644
index e735ec80b56e1a2da4bc5bec29136ce60353277b..330ea62d220d9acd96a95a605888839388e97452 100644
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -14,7 +14,6 @@
@media (-moz-gtk-theme-family) {
--tabs-navbar-separator-style: none;
@media (prefers-color-scheme: light) {
@media (prefers-color-scheme: light) and (not -moz-pref("browser.nova.enabled")) {
- --urlbar-box-background-color: #fafafa;
}
}

View File

@@ -1,8 +1,8 @@
diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css
index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285062fbbcc 100644
index 0820fa040642ee05c2a24f5d2cfa58da5c926647..2d93abcce1729744e5963f1c6ad47f253804576e 100644
--- a/browser/themes/shared/tabbrowser/tabs.css
+++ b/browser/themes/shared/tabbrowser/tabs.css
@@ -33,7 +33,7 @@
@@ -45,7 +45,7 @@
--tab-group-line-thickness: 2px;
--tab-group-line-toolbar-border-distance: 1px;
/* Collapsed tabs should be square, so set width to match the min height */
@@ -11,7 +11,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
--tab-collapsed-width: calc(var(--tab-collapsed-background-width) + 2 * var(--tab-inner-inline-margin));
--tab-pinned-min-width-expanded: calc(var(--tab-pinned-expanded-background-width) + 2 * var(--tab-pinned-margin-inline-expanded));
--tab-note-icon-end-margin: var(--dimension-4);
@@ -282,7 +282,6 @@ tab-split-view-wrapper[dragtarget] {
@@ -295,7 +295,6 @@ tab-split-view-wrapper[dragtarget] {
}
:root:not([uidensity="compact"], [sidebar-expand-on-hover]) &[pinned] {
@@ -19,7 +19,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
}
&:is([selected], [multiselected]) {
@@ -296,6 +295,7 @@ tab-split-view-wrapper[dragtarget] {
@@ -309,6 +308,7 @@ tab-split-view-wrapper[dragtarget] {
border-radius: inherit;
position: relative;
overflow: hidden;
@@ -27,7 +27,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
&::before {
position: absolute;
@@ -493,10 +493,6 @@ tab-split-view-wrapper[dragtarget] {
@@ -506,10 +506,6 @@ tab-split-view-wrapper[dragtarget] {
@media -moz-pref("browser.tabs.fadeOutUnloadedTabs") {
&[pending] {
@@ -38,7 +38,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
opacity: 0.5;
/* Fade the favicon out */
transition-property: filter, opacity;
@@ -512,10 +508,6 @@ tab-split-view-wrapper[dragtarget] {
@@ -525,10 +521,6 @@ tab-split-view-wrapper[dragtarget] {
@media -moz-pref("browser.tabs.fadeOutExplicitlyUnloadedTabs") {
&[pending][discarded] {
@@ -49,7 +49,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
opacity: 0.5;
/* Fade the favicon out */
transition-property: filter, opacity;
@@ -589,7 +581,7 @@ tab-split-view-wrapper[dragtarget] {
@@ -602,7 +594,7 @@ tab-split-view-wrapper[dragtarget] {
}
#tabbrowser-tabs[orient="vertical"] & {
@@ -58,7 +58,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
}
&[crashed] {
@@ -597,7 +589,7 @@ tab-split-view-wrapper[dragtarget] {
@@ -610,7 +602,7 @@ tab-split-view-wrapper[dragtarget] {
}
#tabbrowser-tabs[orient="vertical"]:not([expanded]) &:not([crashed]),
@@ -67,7 +67,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
&[soundplaying] {
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-playing-small.svg");
}
@@ -651,7 +643,7 @@ tab-split-view-wrapper[dragtarget] {
@@ -664,7 +656,7 @@ tab-split-view-wrapper[dragtarget] {
}
}
@@ -76,7 +76,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
&[crashed] {
display: revert;
}
@@ -811,7 +803,7 @@ tab-split-view-wrapper[dragtarget] {
@@ -824,7 +816,7 @@ tab-split-view-wrapper[dragtarget] {
has not been added to root. There are certain scenarios when that attribute is temporarily
removed from root such as when toggling the sidebar to expand with the toolbar button. */
#tabbrowser-tabs[orient="horizontal"] &:not([pinned]):not([crashed]),
@@ -85,7 +85,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
&:is([soundplaying], [muted], [activemedia-blocked]) {
display: flex;
}
@@ -1031,7 +1023,6 @@ tab-split-view-wrapper[dragtarget] {
@@ -1044,7 +1036,6 @@ tab-split-view-wrapper[dragtarget] {
.tabbrowser-tab:is([image], [pinned]) > .tab-stack > .tab-content[attention]:not([selected]),
.tabbrowser-tab > .tab-stack > .tab-content[pinned][titlechanged]:not([selected]),
#tabbrowser-tabs[orient="vertical"] .tabbrowser-tab > .tab-stack > .tab-content[titlechanged]:not([selected]) {
@@ -93,7 +93,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
background-position: center bottom 6.5px;
background-size: 4px 4px;
background-repeat: no-repeat;
@@ -1780,7 +1771,7 @@ tab-group {
@@ -1797,7 +1788,7 @@ tab-group {
}
#tabbrowser-tabs[orient="vertical"][expanded] {
@@ -102,7 +102,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
&[movingtab][movingtab-addToGroup]:not([movingtab-group], [movingtab-ungroup]) .tabbrowser-tab:is(:active, [multiselected]) {
margin-inline-start: var(--space-medium);
}
@@ -2335,7 +2326,7 @@ tab-group {
@@ -2351,7 +2342,7 @@ tab-group {
}
}
@@ -111,7 +111,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
#vertical-tabs-newtab-button {
appearance: none;
min-height: var(--tab-min-height);
@@ -2346,7 +2337,7 @@ tab-group {
@@ -2362,7 +2353,7 @@ tab-group {
margin-inline: var(--tab-inner-inline-margin);
#tabbrowser-tabs[orient="vertical"]:not([expanded]) & > .toolbarbutton-text {
@@ -120,16 +120,16 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
}
&:hover {
@@ -2370,7 +2361,7 @@ tab-group {
@@ -2386,7 +2377,7 @@ tab-group {
* flex container. #tabs-newtab-button is a child of the arrowscrollbox where
* we don't want a gap (between tabs), so we have to add some margin.
*/
-#tabbrowser-arrowscrollbox[orient="vertical"] > #tabbrowser-arrowscrollbox-periphery > #tabs-newtab-button {
+#tabbrowser-arrowscrollbox[orient="vertical"] #tabbrowser-arrowscrollbox-periphery > #tabs-newtab-button {
margin-block: var(--tab-block-margin);
margin-block: var(--tab-margin-block);
}
@@ -2560,7 +2551,6 @@ tab-group {
@@ -2576,7 +2567,6 @@ tab-group {
&:not([expanded]) {
.tabbrowser-tab[pinned] {
@@ -137,7 +137,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
}
.tab-background {
@@ -2599,8 +2589,8 @@ tab-group {
@@ -2615,8 +2605,8 @@ tab-group {
display: block;
position: absolute;
inset: auto;
@@ -148,7 +148,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
&:-moz-window-inactive {
background-image:
@@ -2698,9 +2688,6 @@ tab-group {
@@ -2714,9 +2704,6 @@ tab-group {
~ #tabbrowser-tabs[orient="horizontal"]::before {
display: flex;
content: "";
@@ -158,7 +158,7 @@ index 24ad9ab050a67d4a375eb1d05261a7f7c267d7d1..b2f2ae8e765ad1f052aa07ab1d47f285
}
}
@@ -2733,7 +2720,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button {
@@ -2749,7 +2736,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button {
list-style-image: url(chrome://global/skin/icons/plus.svg);
}

View File

@@ -1,5 +1,5 @@
diff --git a/browser/themes/shared/urlbar-searchbar.css b/browser/themes/shared/urlbar-searchbar.css
index cc595de7e3839f7e688122552bca95f9f9ad3988..da4b1e1b5013d7a1a9af3d45d94db7194a1826f7 100644
index 22d624d718a289dd7b84ffc2f04dd35893dfbe95..4f57f7853f3043e3ad01d893aa928b9d2e6f3c16 100644
--- a/browser/themes/shared/urlbar-searchbar.css
+++ b/browser/themes/shared/urlbar-searchbar.css
@@ -19,8 +19,8 @@
@@ -13,7 +13,7 @@ index cc595de7e3839f7e688122552bca95f9f9ad3988..da4b1e1b5013d7a1a9af3d45d94db719
}
@media (max-width: 770px) {
--urlbar-container-min-width: 240px;
@@ -114,7 +114,7 @@ toolbar[inactive="true"] .urlbar,
@@ -126,7 +126,7 @@ toolbar[inactive="true"] .urlbar,
.urlbar:not([usertyping]) > .urlbar-input-container > .urlbar-go-button,
.urlbar:not(#searchbar-new, [focused]) > .urlbar-input-container > .urlbar-go-button,
#urlbar-revert-button-container {
@@ -22,18 +22,18 @@ index cc595de7e3839f7e688122552bca95f9f9ad3988..da4b1e1b5013d7a1a9af3d45d94db719
}
/* Document Picture-in-Picture API window */
@@ -350,6 +350,10 @@ toolbar[inactive="true"] .urlbar,
@@ -403,6 +403,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);
+ }
+
&::selection {
border-radius: var(--urlbar-selection-border-radius);
}
@@ -464,10 +468,14 @@ toolbar[inactive="true"] .urlbar,
}
#urlbar-scheme {
@@ -492,10 +496,14 @@ toolbar[inactive="true"] .urlbar,
.urlbar[breakout][breakout-extend] {
height: auto;
@@ -46,5 +46,5 @@ index cc595de7e3839f7e688122552bca95f9f9ad3988..da4b1e1b5013d7a1a9af3d45d94db719
> .urlbar-input-container {
+ align-items: center;
height: var(--urlbar-container-height);
padding-block: calc((var(--urlbar-container-height) - var(--urlbar-height)) / 2 + var(--urlbar-input-container-padding));
padding-block: calc((var(--urlbar-container-height) - var(--urlbar-height)) / 2);
padding-inline: calc(var(--urlbar-margin-inline) + var(--urlbar-input-container-padding));

View File

@@ -1,18 +1,18 @@
diff --git a/browser/themes/shared/urlbar/view-proton.css b/browser/themes/shared/urlbar/view-proton.css
index 0b10c077a555e5d0fc488a3bb1b1b920f433204c..38e9d14e9838f2b8de6f654ff4e0700bb65506f0 100644
index 3620b33cb11f2e6bba189cbaf7532cca0e97cd3b..346c318ed178fb77a217b3b992b94706db6bf0ee 100644
--- a/browser/themes/shared/urlbar/view-proton.css
+++ b/browser/themes/shared/urlbar/view-proton.css
@@ -14,7 +14,7 @@
@@ -12,7 +12,7 @@
--urlbarView-small-font-size: 0.85em;
- --urlbarView-results-padding: 7px;
+ --urlbarView-results-padding: 8px;
--urlbarView-row-gutter: var(--space-xxsmall);
--urlbarview-row-padding-block: 6px;
--urlbarView-row-padding-inline: var(--urlbar-icon-padding);
--urlbarView-row-padding-block: 6px;
@@ -174,7 +174,6 @@
min-height: var(--urlbarView-row-min-height);
@@ -165,7 +165,6 @@
min-height: var(--urlbarview-row-min-height);
}
:root[uidensity="touch"] & {
- padding-block: 11px;

View File

@@ -1,5 +1,5 @@
diff --git a/dom/chrome-webidl/MediaController.webidl b/dom/chrome-webidl/MediaController.webidl
index 790bc66a31253a861b21658e67c83796ae939298..0fb7e6cfbb1d1d35aeceb8d7b903cd86bf64403c 100644
index 494ed7a424457dae822c86c0ef7f6d4e8685cd5e..a5a859cbdc76e0d79460780cfc41d7ed95e660e1 100644
--- a/dom/chrome-webidl/MediaController.webidl
+++ b/dom/chrome-webidl/MediaController.webidl
@@ -23,6 +23,12 @@ enum MediaControlKey {
@@ -13,9 +13,9 @@ index 790bc66a31253a861b21658e67c83796ae939298..0fb7e6cfbb1d1d35aeceb8d7b903cd86
+};
+
/**
* MediaController is used to control media playback for a tab, and each tab
* would only have one media controller, which can be accessed from the
@@ -36,6 +42,7 @@ interface MediaController : EventTarget {
* The reason a chrome caller is pausing the controller. "user" preserves the
* existing user-initiated pause; the "system-*" values represent an
@@ -49,6 +55,7 @@ interface MediaController : EventTarget {
readonly attribute boolean isPlaying;
readonly attribute boolean isAnyMediaBeingControlled;
readonly attribute MediaSessionPlaybackState playbackState;
@@ -23,7 +23,7 @@ index 790bc66a31253a861b21658e67c83796ae939298..0fb7e6cfbb1d1d35aeceb8d7b903cd86
// The effective audio-session type the tab is currently claiming. Chrome
// consumers can use this to apply tab/application level audio-focus
@@ -46,6 +53,9 @@ interface MediaController : EventTarget {
@@ -59,6 +66,9 @@ interface MediaController : EventTarget {
[Throws]
MediaMetadataInit getMetadata();

View File

@@ -1,16 +1,16 @@
diff --git a/dom/media/mediaelement/HTMLMediaElement.cpp b/dom/media/mediaelement/HTMLMediaElement.cpp
index b4ab1622d0e58781929aa6801dfd374f42567a7a..358f3d3cac3381ab9de3af65616095f69b9c7b23 100644
index 912f2e08bd0d50e7ba012ed11b583127cf3e35e5..b60ec40f06f4e1a0f433eadebb1a18d40fd6d60f 100644
--- a/dom/media/mediaelement/HTMLMediaElement.cpp
+++ b/dom/media/mediaelement/HTMLMediaElement.cpp
@@ -450,6 +450,7 @@ class HTMLMediaElement::MediaControlKeyListener final
// audible state. Therefore, in that case we would noitfy the audible state
// when media starts playing.
if (mState == MediaPlaybackState::ePlayed) {
@@ -495,6 +495,7 @@ class HTMLMediaElement::MediaControlKeyListener final
// started, since they never reach the playing state.
if (mState == MediaPlaybackState::ePlayed ||
(IsStarted() && mControlType == ControlType::eUncontrollable)) {
+ NotifyMediaPositionState();
NotifyAudibleStateChanged(mIsOwnerAudible
? MediaAudibleState::eAudible
: MediaAudibleState::eInaudible);
@@ -7450,6 +7451,9 @@ void HTMLMediaElement::FireTimeUpdate(TimeupdateType aType) {
NotifyAudibleStateChanged(newState);
}
}
@@ -7738,6 +7739,9 @@ void HTMLMediaElement::FireTimeUpdate(TimeupdateType aType) {
QueueTask(std::move(runner));
mQueueTimeUpdateRunnerTime = TimeStamp::Now();
mLastCurrentTime = CurrentTime();

View File

@@ -1,75 +0,0 @@
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -411,10 +411,13 @@
pref("browser.urlbar.maxRichResults", 10);
// The maximum number of historical search results to show.
pref("browser.urlbar.maxHistoricalSearchSuggestions", 2);
+// Whether to close the urlbar when blurring the window while the urlbar is focused.
+pref("browser.urlbar.closeOnWindowBlur", true);
+
// The default behavior for the urlbar can be configured to use any combination
// of the match filters with each additional filter adding more results (union).
pref("browser.urlbar.suggest.bookmark", true);
pref("browser.urlbar.suggest.clipboard", true);
pref("browser.urlbar.suggest.history", true);
diff --git a/browser/components/urlbar/UrlbarPrefs.sys.mjs b/browser/components/urlbar/UrlbarPrefs.sys.mjs
--- a/browser/components/urlbar/UrlbarPrefs.sys.mjs
+++ b/browser/components/urlbar/UrlbarPrefs.sys.mjs
@@ -152,10 +152,13 @@
["filter.javascript", true],
// Feature gate pref for flight status suggestions in the urlbar.
["flightStatus.featureGate", false],
+ // Whether to close the urlbar when blurring the window while the urlbar is focused.
+ ["closeOnWindowBlur", true],
+
// The minimum prefix length of a flight status keyword the user must type to
// trigger the suggestion. 0 means the min length should be taken from Nimbus
// or remote settings.
["flightStatus.minKeywordLength", 0],
diff --git a/browser/components/urlbar/content/UrlbarView.mjs b/browser/components/urlbar/content/UrlbarView.mjs
--- a/browser/components/urlbar/content/UrlbarView.mjs
+++ b/browser/components/urlbar/content/UrlbarView.mjs
@@ -3909,10 +3909,16 @@
}
}
}
on_blur() {
+ if (
+ this.document.commandDispatcher.focusedElement == this.input.inputField &&
+ !lazy.UrlbarPrefs.get("closeOnWindowBlur")
+ ) {
+ return;
+ }
// If the view is open without the input being focused, it will not close
// automatically when the window loses focus. We might be in this state
// after a Search Tip is shown on an engine homepage.
if (!lazy.UrlbarPrefs.get("ui.popup.disable_autohide")) {
this.close();
diff --git a/browser/components/urlbar/content/UrlbarInput.mjs b/browser/components/urlbar/content/UrlbarInput.mjs
--- a/browser/components/urlbar/content/UrlbarInput.mjs
+++ b/browser/components/urlbar/content/UrlbarInput.mjs
@@ -4783,10 +4783,16 @@
}
}
_on_blur(event) {
lazy.logger.debug("Blur Event");
+ if (
+ this.document.commandDispatcher.focusedElement == this.inputField &&
+ !lazy.UrlbarPrefs.get("closeOnWindowBlur")
+ ) {
+ return;
+ }
// We cannot count every blur events after a missed engagement as abandoment
// because the user may have clicked on some view element that executes
// a command causing a focus change. For example opening preferences from
// the oneoff settings button.
// For now we detect that case by discarding the event on command, but we
// may want to figure out a more robust way to detect abandonment.

View File

@@ -1,167 +0,0 @@
diff --git a/gfx/webrender_bindings/WebRenderAPI.cpp b/gfx/webrender_bindings/WebRenderAPI.cpp
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -298,11 +298,13 @@
panic_on_gl_error, picTileWidth, picTileHeight,
gfx::gfxVars::WebRenderRequiresHardwareDriver(),
StaticPrefs::gfx_webrender_low_quality_pinch_zoom_AtStartup(),
StaticPrefs::gfx_webrender_max_shared_surface_size_AtStartup(),
StaticPrefs::gfx_webrender_enable_subpixel_aa_AtStartup(),
- compositor->ShouldUseLayerCompositor())) {
+ compositor->ShouldUseLayerCompositor(),
+ StaticPrefs::
+ gfx_webrender_opaque_backdrop_fallback_AtStartup())) {
// wr_window_new puts a message into gfxCriticalNote if it returns
// false
MOZ_ASSERT(errorMessage);
error.AssignASCII(errorMessage);
wr_api_free_error_msg(errorMessage);
diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1998,10 +1998,11 @@
reject_software_rasterizer: bool,
low_quality_pinch_zoom: bool,
max_shared_surface_size: i32,
enable_subpixel_aa: bool,
use_layer_compositor: bool,
+ opaque_backdrop_fallback: bool,
) -> bool {
assert!(unsafe { is_in_render_thread() });
// Ensure the WR profiler callbacks are hooked up to the Gecko profiler.
set_profiler_hooks(Some(&PROFILER_HOOKS));
@@ -2164,10 +2165,11 @@
texture_cache_config,
reject_software_rasterizer,
low_quality_pinch_zoom,
max_shared_surface_size,
enable_dithering,
+ opaque_backdrop_fallback,
..Default::default()
};
let window_size = DeviceIntSize::new(window_width, window_height);
let notifier = Box::new(CppNotifier { window_id });
diff --git a/gfx/wr/webrender/src/device/gl.rs b/gfx/wr/webrender/src/device/gl.rs
--- a/gfx/wr/webrender/src/device/gl.rs
+++ b/gfx/wr/webrender/src/device/gl.rs
@@ -3982,10 +3982,14 @@
pub fn disable_color_write(&self) {
self.gl.color_mask(false, false, false, false);
}
+ pub fn set_color_mask(&self, r: bool, g: bool, b: bool, a: bool) {
+ self.gl.color_mask(r, g, b, a);
+ }
+
pub fn set_blend(&mut self, enable: bool) {
if enable {
self.gl.enable(gl::BLEND);
} else {
self.gl.disable(gl::BLEND);
diff --git a/gfx/wr/webrender/src/renderer/init.rs b/gfx/wr/webrender/src/renderer/init.rs
--- a/gfx/wr/webrender/src/renderer/init.rs
+++ b/gfx/wr/webrender/src/renderer/init.rs
@@ -204,6 +204,8 @@
pub low_quality_pinch_zoom: bool,
pub max_shared_surface_size: i32,
/// If true, open a debug socket to listen for remote debugger.
/// Relies on `debugger` cargo feature being enabled.
pub enable_debugger: bool,
+ /// See explanation of `gfx.webrender.opaque-backdrop-fallback`.
+ pub opaque_backdrop_fallback: bool,
}
@@ -277,9 +279,10 @@
enable_instancing: true,
reject_software_rasterizer: false,
low_quality_pinch_zoom: false,
max_shared_surface_size: 2048,
enable_debugger: true,
+ opaque_backdrop_fallback: false,
}
}
}
@@ -802,10 +805,11 @@
allocated_native_surfaces: FastHashSet::default(),
debug_overlay_state: DebugOverlayState::new(),
buffer_damage_tracker: BufferDamageTracker::default(),
max_primitive_instance_count,
enable_instancing: options.enable_instancing,
+ opaque_backdrop_fallback: options.opaque_backdrop_fallback,
consecutive_oom_frames: 0,
target_frame_publish_id: None,
pending_result_msg: None,
layer_compositor_frame_state_in_prev_frame: None,
external_composite_debug_items: Vec::new(),
diff --git a/gfx/wr/webrender/src/renderer/mod.rs b/gfx/wr/webrender/src/renderer/mod.rs
--- a/gfx/wr/webrender/src/renderer/mod.rs
+++ b/gfx/wr/webrender/src/renderer/mod.rs
@@ -867,10 +867,12 @@
buffer_damage_tracker: BufferDamageTracker,
max_primitive_instance_count: usize,
enable_instancing: bool,
+ opaque_backdrop_fallback: bool,
+
/// Count consecutive oom frames to detectif we are stuck unable to render
/// in a loop.
consecutive_oom_frames: u32,
/// update() defers processing of ResultMsg, if frame_publish_id of
@@ -2787,18 +2789,29 @@
let read_target = ReadTarget::from_texture(cache_texture);
// Should always be drawing to picture cache tiles or off-screen surface!
debug_assert!(!draw_target.is_default());
let device_to_framebuffer = Scale::new(1i32);
+ let dest_fb_rect = dest * device_to_framebuffer;
self.device.blit_render_target(
read_target,
src * device_to_framebuffer,
draw_target,
- dest * device_to_framebuffer,
+ dest_fb_rect,
TextureFilter::Linear,
);
+
+ if self.opaque_backdrop_fallback {
+ self.device.set_color_mask(false, false, false, true);
+ self.device.clear_target(
+ Some([0.0, 0.0, 0.0, 1.0]),
+ None,
+ Some(dest_fb_rect),
+ );
+ self.device.set_color_mask(true, true, true, true);
+ }
}
}
}
fn draw_picture_cache_target(
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
@@ -8439,10 +8439,17 @@
#else
value: false
#endif
mirror: once
+# Make backdrop-filter treat its captured backdrop as if it had been
+# composited over an opaque-black background. (See bug 2036640)
+- name: gfx.webrender.opaque-backdrop-fallback
+ type: bool
+ value: true
+ mirror: once
+
# Disable wait of GPU execution completion
- name: gfx.webrender.wait-gpu-finished.disabled
type: bool
value: false
mirror: once

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,166 @@
diff --git a/browser/components/sessionstore/test/browser.toml b/browser/components/sessionstore/test/browser.toml
--- a/browser/components/sessionstore/test/browser.toml
+++ b/browser/components/sessionstore/test/browser.toml
@@ -14,10 +14,12 @@
"browser_frame_history_c.html",
"browser_frame_history_c1.html",
"browser_frame_history_c2.html",
"browser_formdata_format_sample.html",
"browser_sessionHistory_slow.sjs",
+ "browser_policy_container_sample.html",
+ "browser_policy_container_sample_frame.html",
"browser_scrollPositions_sample.html",
"browser_scrollPositions_sample2.html",
"browser_scrollPositions_sample_frameset.html",
"browser_scrollPositions_readerModeArticle.html",
"browser_sessionStorage.html",
@@ -226,10 +228,12 @@
["browser_pinned_tabs.js"]
skip-if = [
"ccov", # Bug 1625525
]
+["browser_policy_container_not_stored.js"]
+
["browser_privatetabs.js"]
["browser_purge_domaindata.js"]
["browser_purge_shistory.js"]
diff --git a/browser/components/sessionstore/test/browser_policy_container_not_stored.js b/browser/components/sessionstore/test/browser_policy_container_not_stored.js
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_policy_container_not_stored.js
@@ -0,0 +1,51 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+"use strict";
+
+/**
+ * A session history entry only needs to retain the policy container for loads
+ * that inherit their policies (about:blank, about:srcdoc, blob:, data:, ...).
+ * Anything fetched over the network gets its policies from the response again,
+ * so storing them would only bloat the session store (bug 2011236).
+ */
+
+const TEST_ROOT = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "https://example.com"
+);
+const PARENT_URL = TEST_ROOT + "browser_policy_container_sample.html";
+const FRAME_URL = TEST_ROOT + "browser_policy_container_sample_frame.html";
+
+add_task(async function test_policy_container_only_for_inheriting_loads() {
+ const tab = BrowserTestUtils.addTab(gBrowser, PARENT_URL);
+ gBrowser.selectedTab = tab;
+ await promiseBrowserLoaded(tab.linkedBrowser, true, PARENT_URL);
+ await TabStateFlusher.flush(tab.linkedBrowser);
+
+ const state = JSON.parse(ss.getTabState(tab));
+ const topEntry = state.entries.at(-1);
+ is(topEntry.url, PARENT_URL, "collected the parent entry");
+
+ const children = topEntry.children ?? [];
+ const networkFrame = children.find(child => child.url === FRAME_URL);
+ const blankFrame = children.find(child => child.url === "about:blank");
+
+ ok(networkFrame, "collected the network-scheme subframe entry");
+ ok(blankFrame, "collected the about:blank subframe entry");
+
+ // The parent has a CSP, so both subframes inherit a policy container onto
+ // their load state. Only the one that cannot recover it from a response
+ // should keep it in session history.
+ ok(
+ !("policyContainer" in networkFrame),
+ "https subframe entry does not store a policyContainer"
+ );
+ ok(
+ "policyContainer" in blankFrame,
+ "about:blank subframe entry still stores its inherited policyContainer"
+ );
+
+ await BrowserTestUtils.removeTab(tab);
+});
diff --git a/browser/components/sessionstore/test/browser_policy_container_sample.html b/browser/components/sessionstore/test/browser_policy_container_sample.html
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_policy_container_sample.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Security-Policy" content="default-src * data: blob: 'unsafe-inline'">
+ <title>policyContainer session store sample</title>
+</head>
+<body>
+ <iframe id="network" src="browser_policy_container_sample_frame.html"></iframe>
+ <iframe id="blank" src="about:blank"></iframe>
+</body>
+</html>
diff --git a/browser/components/sessionstore/test/browser_policy_container_sample_frame.html b/browser/components/sessionstore/test/browser_policy_container_sample_frame.html
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_policy_container_sample_frame.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>policyContainer session store sample frame</title>
+</head>
+<body>
+ frame
+</body>
+</html>
diff --git a/docshell/shistory/SessionHistoryEntry.cpp b/docshell/shistory/SessionHistoryEntry.cpp
--- a/docshell/shistory/SessionHistoryEntry.cpp
+++ b/docshell/shistory/SessionHistoryEntry.cpp
@@ -41,10 +41,18 @@
extern mozilla::LazyLogModule gSHLog;
namespace mozilla {
namespace dom {
+// Only store policy container for loads that can't carry it themselves
+// (about:blank, about:srcdoc, blob:, data:, ...)
+// bug 1867137, bug 2011236
+static nsIPolicyContainer* PolicyContainerToStore(
+ nsIURI* aURI, nsIPolicyContainer* aPolicyContainer) {
+ return CSP_ShouldURIInheritCSP(aURI) ? aPolicyContainer : nullptr;
+}
+
SessionHistoryInfo::SessionHistoryInfo(nsDocShellLoadState* aLoadState,
nsIChannel* aChannel)
: mURI(aLoadState->URI()),
mOriginalURI(aLoadState->OriginalURI()),
mResultPrincipalURI(aLoadState->ResultPrincipalURI()),
@@ -59,9 +67,10 @@
mLoadReplace(aLoadState->LoadReplace()),
mHasUserActivation(aLoadState->HasValidUserGestureActivation()),
mSharedState(SharedState::Create(
aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(),
aLoadState->PartitionedPrincipalToInherit(),
- aLoadState->PolicyContainer(),
+ PolicyContainerToStore(aLoadState->URI(),
+ aLoadState->PolicyContainer()),
/* FIXME Is this correct? */
aLoadState->TypeHint())) {
// Pull the upload stream off of the channel instead of the load state, as
@@ -124,11 +133,12 @@
loadInfo->GetPrincipalToInherit(
getter_AddRefs(mSharedState.Get()->mPrincipalToInherit));
mSharedState.Get()->mPartitionedPrincipalToInherit =
aPartitionedPrincipalToInherit;
- mSharedState.Get()->mPolicyContainer = aPolicyContainer;
+ mSharedState.Get()->mPolicyContainer =
+ PolicyContainerToStore(mURI, aPolicyContainer);
aChannel->GetContentType(mSharedState.Get()->mContentType);
aChannel->GetOriginalURI(getter_AddRefs(mOriginalURI));
uint32_t loadFlags;
aChannel->GetLoadFlags(&loadFlags);

View File

@@ -2,15 +2,15 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -70,10 +70,11 @@
#include "nsDocShell.h"
#include "nsXULPopupManager.h"
#include "gfxPlatform.h"
#include "qcms.h"
+#import <objc/runtime.h>
#include <algorithm>
#include "mozilla/AutoRestore.h"
#include "mozilla/BasicEvents.h"
#include "mozilla/dom/Document.h"
#include "mozilla/Maybe.h"
#include "mozilla/NativeKeyBindingsType.h"
@@ -6948,10 +6949,31 @@

View File

@@ -1,136 +0,0 @@
diff --git a/browser/themes/linux/browser.css b/browser/themes/linux/browser.css
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -32,11 +32,11 @@
*/
@media (-moz-gtk-csd-transparency-available) {
:root[customtitlebar] {
background-color: transparent;
- &[sizemode="normal"]:not([gtktiledwindow]) {
+ &[sizemode="normal"]:not([tiled]) {
/* Firefox draws its contents to a child window, while GTK takes care of
* drawing the toplevel (which in most cases is just the window
* decorations).
*
* Due to how X11 child windows work, pixels painted by a child window will
diff --git a/browser/themes/shared/browser-shared.css b/browser/themes/shared/browser-shared.css
--- a/browser/themes/shared/browser-shared.css
+++ b/browser/themes/shared/browser-shared.css
@@ -433,18 +433,18 @@
}
}
@media (-moz-platform: linux) and (-moz-gtk-csd-reversed-placement: 0) {
:root:not([sizemode="normal"]) &[type="pre-tabs"],
- :root[gtktiledwindow] &[type="pre-tabs"] {
+ :root[tiled] &[type="pre-tabs"] {
display: none;
}
}
@media (-moz-gtk-csd-reversed-placement) {
:root:not([sizemode="normal"]) &[type="post-tabs"],
- :root[gtktiledwindow] &[type="post-tabs"] {
+ :root[tiled] &[type="post-tabs"] {
display: none;
}
}
@media (max-width: 500px) {
diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -3683,11 +3683,11 @@
#ifdef ACCESSIBILITY
DispatchRestoreEventAccessible();
#endif // ACCESSIBILITY
}
- mIsTiled = aEvent->new_window_state & GDK_WINDOW_STATE_TILED;
+ SetIsTiled(aEvent->new_window_state & GDK_WINDOW_STATE_TILED);
LOG("\tTiled: %d\n", int(mIsTiled));
mResizableEdges = [&] {
Sides result;
if (mSizeMode != nsSizeMode_Normal) {
return result;
diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1379,10 +1379,12 @@
protected:
// Returns whether compositing should use an external surface size.
virtual bool UseExternalCompositingSurface() const { return false; }
+ void SetIsTiled(bool);
+
/**
* Starts the OMTC compositor destruction sequence.
*
* When this function returns, the compositor should not be
* able to access the opengl context anymore.
diff --git a/widget/nsIWidget.cpp b/widget/nsIWidget.cpp
--- a/widget/nsIWidget.cpp
+++ b/widget/nsIWidget.cpp
@@ -327,10 +327,16 @@
void nsIWidget::QuitIME() {
IMEStateManager::WidgetOnQuit(this);
this->mIMEHasQuit = true;
}
+void nsIWidget::SetIsTiled(bool aIsTiled) {
+ // TODO: Do we want to report an event here or something when stuff changes?
+ // For now this is propagated in a somewhat out-of-band way via AppWindow.
+ mIsTiled = aIsTiled;
+}
+
void nsIWidget::DestroyCompositor() {
RevokeTransactionIdAllocator();
// We release this before releasing the compositor, since it may hold the
// last reference to our ClientLayerManager. ClientLayerManager's dtor can
diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py
--- a/xpcom/ds/StaticAtoms.py
+++ b/xpcom/ds/StaticAtoms.py
@@ -1512,11 +1512,10 @@
Atom("gamma", "gamma"),
Atom("glyphRef", "glyphRef"),
Atom("grad", "grad"),
Atom("gradientTransform", "gradientTransform"),
Atom("gradientUnits", "gradientUnits"),
- Atom("gtktiledwindow", "gtktiledwindow"),
Atom("hardLight", "hard-light"),
Atom("hue", "hue"),
Atom("hueRotate", "hueRotate"),
Atom("identity", "identity"),
Atom("image_rendering", "image-rendering"),
@@ -1950,10 +1949,11 @@
Atom("superscriptshift", "superscriptshift"),
Atom("symmetric", "symmetric"),
Atom("tanh", "tanh"),
Atom("tan", "tan"),
Atom("tendsto", "tendsto"),
+ Atom("tiled", "tiled"),
Atom("times", "times"),
Atom("transpose", "transpose"),
Atom("union_", "union"),
Atom("uplimit", "uplimit"),
Atom("variance", "variance"),
diff --git a/xpfe/appshell/AppWindow.cpp b/xpfe/appshell/AppWindow.cpp
--- a/xpfe/appshell/AppWindow.cpp
+++ b/xpfe/appshell/AppWindow.cpp
@@ -1992,11 +1992,11 @@
aRootElement.SetAttr(nsGkAtoms::sizemode, sizeString, IgnoreErrors());
if (aShouldPersist && aPersistString.Find(u"sizemode") >= 0) {
(void)SetPersistentValue(nsGkAtoms::sizemode, sizeString);
}
}
- aRootElement.SetBoolAttr(nsGkAtoms::gtktiledwindow, mWindow->IsTiled());
+ aRootElement.SetBoolAttr(nsGkAtoms::tiled, mWindow->IsTiled());
}
void AppWindow::SavePersistentAttributes(
const PersistentAttributes aAttributes) {
// can happen when the persistence timer fires at an inopportune time

View File

@@ -1,18 +0,0 @@
diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -6423,10 +6423,13 @@
// Skip window size change events below on minimization.
return;
}
}
+ // Recompute tiled state.
+ SetIsTiled(mWnd && ::IsWindowArranged(mWnd));
+
// Notify visibility change when window is activated.
if (!(wp->flags & SWP_NOACTIVATE) && NeedsToTrackWindowOcclusionState()) {
WinWindowOcclusionTracker::Get()->OnWindowVisibilityChanged(
this, mFrameState->GetSizeMode() != nsSizeMode_Minimized);
}

View File

@@ -1,21 +0,0 @@
diff --git a/gfx/wr/webrender/src/renderer/composite.rs b/gfx/wr/webrender/src/renderer/composite.rs
--- a/gfx/wr/webrender/src/renderer/composite.rs
+++ b/gfx/wr/webrender/src/renderer/composite.rs
@@ -974,12 +974,15 @@
.iter()
.chain(self.layer_compositor_frame_state_in_prev_frame.as_ref().unwrap().rects_without_id.iter()) {
combined_dirty_rect = combined_dirty_rect.union(&rect);
}
+ let device_rect = DeviceRect::from_size(device_size.to_f32());
+ let clipped_dirty_rect = combined_dirty_rect.intersection_unchecked(&device_rect);
+
partial_present_mode = Some(PartialPresentMode::Single {
- dirty_rect: combined_dirty_rect,
+ dirty_rect: clipped_dirty_rect,
});
} else {
partial_present_mode = None;
}

View File

@@ -0,0 +1,55 @@
diff --git a/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs b/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs
--- a/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs
+++ b/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs
@@ -119,10 +119,19 @@
}
case "PictureInPicture:VideoTabHidden": {
if (!lazy.PIP_ENABLED || !lazy.PIP_WHEN_SWITCHING_TABS) {
break;
}
+
+ // Suppress auto-toggle if the user deliberately closed this PiP window
+ if (
+ PictureInPicture.weakAutoPipBrowserClosedDeliberately.has(browser)
+ ) {
+ PictureInPicture.weakAutoPipBrowserClosedDeliberately.delete(browser);
+ break;
+ }
+
// If the tab is still selected, then we can ignore this event
if (browser.documentGlobal.gBrowser.selectedBrowser == browser) {
break;
}
let actor = browsingContext.currentWindowGlobal.getActor(
@@ -261,10 +270,12 @@
maxConcurrentPlayerCount: 0,
// Maps auto pip browser to PictureInPictureParent actor
weakAutoPipBrowserToParent: new WeakMap(),
+ weakAutoPipBrowserClosedDeliberately: new WeakSet(),
+
/**
* Returns the player window if one exists and if it hasn't yet been closed.
*
* @param {PictureInPictureParent} pipActorRef
* Reference to the calling PictureInPictureParent actor
@@ -899,10 +910,17 @@
const { reason, actorRef } = closeData;
const win = this.getWeakPipPlayer(actorRef);
if (!win) {
return;
}
+
+ const browser = this.weakWinToBrowser.get(win);
+
+ if (reason === "CloseButton") {
+ PictureInPicture.weakAutoPipBrowserClosedDeliberately.add(browser);
+ }
+
this.removePiPBrowserFromWeakMap(this.weakWinToBrowser.get(win));
this.weakAutoPipBrowserToParent.delete(this.weakWinToBrowser.get(win));
Glean.pictureinpicture["closedMethod" + reason].record();
await this.closePipWindow(win);

View File

@@ -0,0 +1,254 @@
diff --git a/browser/components/sessionstore/SessionWriter.sys.mjs b/browser/components/sessionstore/SessionWriter.sys.mjs
--- a/browser/components/sessionstore/SessionWriter.sys.mjs
+++ b/browser/components/sessionstore/SessionWriter.sys.mjs
@@ -80,10 +80,14 @@
return await SessionWriterInternal.wipe();
} finally {
unlock();
}
},
+
+ get _jsonLengthHint() {
+ return SessionWriterInternal._lastJsonLength;
+ },
};
const SessionWriterInternal = {
// Path to the files used by the SessionWriter
Paths: null,
@@ -104,10 +108,14 @@
/**
* Number of old upgrade backups that are being kept
*/
maxUpgradeBackups: null,
+ // Estimated JSON string length from the previous write, used to pre-size
+ // the serialization buffer and avoid incremental reallocations.
+ _lastJsonLength: 0,
+
/**
* Initialize (or reinitialize) the writer.
*
* @param {string} origin Which of sessionstore.js or its backups
* was used. One of the `STATE_*` constants defined above.
@@ -201,48 +209,60 @@
}
}
let startWriteMs = Date.now();
let fileStat;
+ // Add 5% headroom to the hint so small growth between saves doesn't
+ // cause reallocs. The compressed-size-based estimate already has
+ // sufficient margin from the 4x multiplier.
+ let jsonLengthHint = Math.ceil(this._lastJsonLength * 1.05);
+
+ let uncompressedBytes;
if (options.isFinalWrite) {
// We are shutting down. At this stage, we know that
// $Paths.clean is either absent or corrupted. If it was
// originally present and valid, it has been moved to
// $Paths.cleanBackup a long time ago. We can therefore write
// with the guarantees that we erase no important data.
- await IOUtils.writeJSON(this.Paths.clean, state, {
+ uncompressedBytes = await IOUtils.writeJSON(this.Paths.clean, state, {
tmpPath: this.Paths.clean + ".tmp",
compress: true,
+ lengthHint: jsonLengthHint,
});
fileStat = await IOUtils.stat(this.Paths.clean);
} else if (this.state == STATE_RECOVERY) {
// At this stage, either $Paths.recovery was written >= 15
// seconds ago during this session or we have just started
// from $Paths.recovery left from the previous session. Either
// way, $Paths.recovery is good. We can move $Path.backup to
// $Path.recoveryBackup without erasing a good file with a bad
// file.
- await IOUtils.writeJSON(this.Paths.recovery, state, {
+ uncompressedBytes = await IOUtils.writeJSON(this.Paths.recovery, state, {
tmpPath: this.Paths.recovery + ".tmp",
backupFile: this.Paths.recoveryBackup,
compress: true,
+ lengthHint: jsonLengthHint,
});
fileStat = await IOUtils.stat(this.Paths.recovery);
} else {
// In other cases, either $Path.recovery is not necessary, or
// it doesn't exist or it has been corrupted. Regardless,
// don't backup $Path.recovery.
- await IOUtils.writeJSON(this.Paths.recovery, state, {
+ uncompressedBytes = await IOUtils.writeJSON(this.Paths.recovery, state, {
tmpPath: this.Paths.recovery + ".tmp",
compress: true,
+ lengthHint: jsonLengthHint,
});
fileStat = await IOUtils.stat(this.Paths.recovery);
}
telemetry.writeFileMs = Date.now() - startWriteMs;
telemetry.fileSizeBytes = fileStat.size;
+ // Use the actual pre-compression size from this write as the hint
+ // for the next write's buffer allocation.
+ this._lastJsonLength = uncompressedBytes.jsonLength;
lazy.sessionStoreLogger.debug(
`SessionWriter.write wrote ${telemetry.fileSizeBytes} bytes in ${telemetry.writeFileMs}ms`
);
} catch (ex) {
// Don't throw immediately
@@ -375,10 +395,11 @@
} catch (ex) {
exn = exn || ex;
}
this.state = STATE_EMPTY;
+ this._lastJsonLength = 0;
if (exn) {
throw exn;
}
return { result: true };
diff --git a/browser/components/sessionstore/test/unit/test_write_json_length_hint.js b/browser/components/sessionstore/test/unit/test_write_json_length_hint.js
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/unit/test_write_json_length_hint.js
@@ -0,0 +1,73 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { SessionWriter } = ChromeUtils.importESModule(
+ "resource:///modules/sessionstore/SessionWriter.sys.mjs"
+);
+
+const profd = do_get_profile();
+const { SessionFile } = ChromeUtils.importESModule(
+ "resource:///modules/sessionstore/SessionFile.sys.mjs"
+);
+
+const { updateAppInfo } = ChromeUtils.importESModule(
+ "resource://testing-common/AppInfo.sys.mjs"
+);
+updateAppInfo({
+ name: "SessionRestoreTest",
+ ID: "{230de50e-4cd1-11dc-8314-0800200c9a66}",
+ version: "1",
+ platformVersion: "",
+});
+
+add_setup(async function () {
+ let source = do_get_file("data/sessionstore_valid.js");
+ source.copyTo(profd, "sessionstore.js");
+ await writeCompressedFile(
+ SessionFile.Paths.clean.replace("jsonlz4", "js"),
+ SessionFile.Paths.clean
+ );
+ await SessionFile.read();
+});
+
+add_task(async function test_length_hint_updates_after_write() {
+ Assert.equal(
+ SessionWriter._jsonLengthHint,
+ 0,
+ "Length hint starts at 0"
+ );
+
+ await SessionFile.write({});
+
+ let hintAfterSmall = SessionWriter._jsonLengthHint;
+ Assert.equal(
+ hintAfterSmall,
+ JSON.stringify({}).length,
+ "Hint matches the uncompressed JSON byte length"
+ );
+
+ let largerState = await IOUtils.readJSON(
+ PathUtils.join(do_get_cwd().path, "data", "sessionstore_complete.json")
+ );
+ await SessionFile.write(largerState);
+
+ Assert.greater(
+ SessionWriter._jsonLengthHint,
+ hintAfterSmall,
+ "Hint grows after writing a larger state"
+ );
+});
+
+add_task(async function test_length_hint_resets_on_wipe() {
+ await SessionFile.write({ windows: [{ tabs: [{ entries: [] }] }] });
+ Assert.greater(SessionWriter._jsonLengthHint, 0, "Hint is nonzero");
+
+ await SessionFile.wipe();
+ Assert.equal(
+ SessionWriter._jsonLengthHint,
+ 0,
+ "Hint resets to 0 after wipe"
+ );
+});
diff --git a/browser/components/sessionstore/test/unit/xpcshell.toml b/browser/components/sessionstore/test/unit/xpcshell.toml
--- a/browser/components/sessionstore/test/unit/xpcshell.toml
+++ b/browser/components/sessionstore/test/unit/xpcshell.toml
@@ -39,5 +39,10 @@
skip-if = [
"condprof", # Bug 1769154
]
["test_startup_session_async.js"]
+
+["test_write_json_length_hint.js"]
+support-files = [
+ "data/sessionstore_complete.json",
+]
diff --git a/dom/chrome-webidl/IOUtils.webidl b/dom/chrome-webidl/IOUtils.webidl
--- a/dom/chrome-webidl/IOUtils.webidl
+++ b/dom/chrome-webidl/IOUtils.webidl
@@ -101,12 +101,12 @@
*
* @param path An absolute file path
* @param value The value to be serialized.
* @param options Options for writing the file. The "append" mode is not supported.
*
- * @return Resolves with the number of bytes successfully written to the file,
- * otherwise rejects with a DOMException.
+ * @return Resolves with the pre-compression size of the serialized JSON in
+ * bytes (UTF-8), otherwise rejects with a DOMException.
*/
[NewObject]
Promise<WriteJSONResult> writeJSON(DOMString path, any value, optional WriteJSONOptions options = {});
/**
* Moves the file from |sourcePath| to |destPath|, creating necessary parents.
@@ -564,10 +564,16 @@
boolean flush = false;
/**
* If true, compress the data with LZ4-encoding before writing to the file.
*/
boolean compress = false;
+ /**
+ * For |writeJSON|, a hint for the expected JSON string length in UTF-16 code
+ * units. When provided, the JSON serializer pre-allocates a buffer of this
+ * size to avoid incremental reallocations.
+ */
+ unsigned long long jsonLengthHint = 0;
};
/**
* Options to be passed to the |IOUtils.writeJSON| method.
*/
diff --git a/xpcom/ioutils/IOUtils.cpp b/xpcom/ioutils/IOUtils.cpp
--- a/xpcom/ioutils/IOUtils.cpp
+++ b/xpcom/ioutils/IOUtils.cpp
@@ -629,10 +629,13 @@
}
JSContext* cx = aGlobal.Context();
JS::Rooted<JS::Value> value(cx, aValue);
nsString string;
+ if (opts.mLengthHint) {
+ string.SetCapacity(opts.mLengthHint);
+ }
if (!JS_StringifyWithLengthHint(cx, &value, nullptr,
JS::NullHandleValue, AppendJSON,
&string, opts.mLengthHint)) {
JS::Rooted<JS::Value> exn(cx, JS::UndefinedValue());
if (JS_GetPendingException(cx, &exn)) {

View File

@@ -7,14 +7,6 @@
"id": "D299584",
"name": "Native MacOS popovers fix"
},
{
"type": "phabricator",
"id": "D284404",
"name": "Add urlbar closeOnWindowBlur preference",
"replaces": {
"\n\n": "\n // may want to figure out a more robust way to detect abandonment."
}
},
{
"type": "local",
// TODO: Convert into https://phabricator.services.mozilla.com/D298079
@@ -37,22 +29,32 @@
},
{
"type": "phabricator",
"id": "D291714",
"name": "gh-12979 Clip dirty_rect to device_size"
},
{
"type": "phabricator",
"ids": [
"D312028",
"D312036",
"D312091"
],
"id": "D312091",
"name": "Expose tiled attribute to all platforms"
},
{
"type": "patch",
"url": "https://gitlab.archlinux.org/archlinux/packaging/packages/firefox/-/raw/main/0002-Bug-2057577-DOM-Media-Add-FFmpeg-63-support.-r-alwu-.patch",
"dest": "firefox",
"filename": "bug-2057577-ffmpeg-63-support.patch"
"type": "phabricator",
"id": "D298708",
"name": "Issue 14990",
"replaces": {
"this._lastJsonLength = uncompressedBytes;": "this._lastJsonLength = uncompressedBytes.jsonLength;",
" jsonLengthHint,": " lengthHint: jsonLengthHint,"
}
},
{
"type": "phabricator",
"id": "D320897",
"name": "Bug 2011236",
"replaces": {
// The upstream patch context includes a MOZ_DIAGNOSTIC_ASSERT that
// doesn't exist yet in our Firefox version.
"@@ -59,11 +67,12 @@": "@@ -59,9 +67,10 @@",
"aLoadState->TypeHint())) {\n MOZ_DIAGNOSTIC_ASSERT(!mURI->SchemeIs(\"javascript\"));\n \n // Pull": "aLoadState->TypeHint())) {\n // Pull"
}
},
{
"type": "phabricator",
"id": "D321446",
"name": "Issue 14710"
}
]

View File

@@ -1,16 +1,16 @@
diff --git a/gfx/layers/AnimationInfo.cpp b/gfx/layers/AnimationInfo.cpp
index b4941588bfbd94a337f2e848c659021723e1500d..8f91ca5b2fcca6ff04aa2c0af5ba26dd9fe7df0e 100644
index 538808aa15d1902fc517f79e3a6d62f4d7fd9d37..4b0760b7be9d872a926f99716d16f3f64dcb2378 100644
--- a/gfx/layers/AnimationInfo.cpp
+++ b/gfx/layers/AnimationInfo.cpp
@@ -14,6 +14,7 @@
#include "mozilla/MotionPathUtils.h"
#include "mozilla/PresShell.h"
#include "mozilla/ScrollContainerFrame.h"
@@ -18,6 +18,7 @@
#include "mozilla/layers/AnimationStorageData.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/WebRenderLayerManager.h"
+#include "mozilla/nsZenBoostsBackend.h"
#include "nsIContent.h"
#include "nsLayoutUtils.h"
#include "nsRefreshDriver.h"
@@ -341,9 +342,13 @@ static void SetAnimatable(NonCustomCSSPropertyId aProperty,
@@ -367,9 +368,13 @@ static void SetAnimatable(NonCustomCSSPropertyId aProperty,
case eCSSProperty_background_color: {
// We don't support color animation on the compositor yet so that we can
// resolve currentColor at this moment.

View File

@@ -1,5 +1,5 @@
diff --git a/layout/generic/nsTextPaintStyle.cpp b/layout/generic/nsTextPaintStyle.cpp
index f741ab5eb83778ec2460a5d975757f09b3f2865e..f39a019c0d82db7ba9a122ce5269d0833ae04568 100644
index 9dba72de611cd84ed07805f5ce40f882071240f0..782dea67f6d975ba5b7daa1e2e2ed862f7941952 100644
--- a/layout/generic/nsTextPaintStyle.cpp
+++ b/layout/generic/nsTextPaintStyle.cpp
@@ -240,7 +240,7 @@ bool nsTextPaintStyle::GetTargetTextColor(nscolor* aForeColor) {
@@ -39,17 +39,14 @@ index f741ab5eb83778ec2460a5d975757f09b3f2865e..f39a019c0d82db7ba9a122ce5269d083
return NS_GET_A(*aBackColor) != 0;
}
@@ -462,12 +463,12 @@ bool nsTextPaintStyle::InitSelectionColorsAndShadow() {
mSelectionPseudoStyle = std::move(style);
if (nscolor bgColor = mSelectionPseudoStyle->GetVisitedDependentColor(
- &nsStyleBackground::mBackgroundColor);
+ &nsStyleBackground::mBackgroundColor, mFrame);
mSelectionPseudoStyle->HasAuthorSpecifiedTextColor() ||
NS_GET_A(bgColor) > 0) {
mSelectionBGColor = bgColor;
@@ -463,9 +464,9 @@ bool nsTextPaintStyle::InitSelectionColorsAndShadow() {
if (mSelectionPseudoStyle->HasAuthorSpecifiedTextColor() ||
mSelectionPseudoStyle->HasAuthorSpecifiedBorderOrBackground()) {
mSelectionBGColor = mSelectionPseudoStyle->GetVisitedDependentColor(
- &nsStyleBackground::mBackgroundColor);
- mSelectionTextColor =
- mSelectionPseudoStyle->GetVisitedDependentColor(&nsStyleText::mColor);
+ &nsStyleBackground::mBackgroundColor, mFrame);
+ mSelectionTextColor = mSelectionPseudoStyle->GetVisitedDependentColor(
+ &nsStyleText::mColor, mFrame);
return true;

View File

@@ -1,5 +1,5 @@
diff --git a/layout/svg/SVGImageContext.cpp b/layout/svg/SVGImageContext.cpp
index 384401ae2cb80a1bf438b1fb3d849254de100210..e5ef332bc529e6588c33b507993880ca9def51d1 100644
index 4d43db157aa9447105eeb5459cad74de6cef01d6..327d8e4f7e21783824616800fa821218c8c848e8 100644
--- a/layout/svg/SVGImageContext.cpp
+++ b/layout/svg/SVGImageContext.cpp
@@ -10,6 +10,7 @@
@@ -39,20 +39,17 @@ index 384401ae2cb80a1bf438b1fb3d849254de100210..e5ef332bc529e6588c33b507993880ca
const nsStyleSVG* style = aStyle.StyleSVG();
if (!style->ExposesContextProperties()) {
// Content must have '-moz-context-properties' set to the names of the
@@ -64,12 +80,14 @@ void SVGImageContext::MaybeStoreContextPaint(SVGImageContext& aContext,
@@ -62,11 +78,11 @@ void SVGImageContext::MaybeStoreContextPaint(SVGImageContext& aContext,
if ((style->mMozContextProperties.bits & StyleContextPropertyBits::FILL) &&
style->mFill.kind.IsColor()) {
haveContextPaint = true;
- contextPaint->SetFill(style->mFill.kind.AsColor().CalcColor(aStyle));
+ contextPaint->SetFill(
+ style->mFill.kind.AsColor().CalcColor(aStyle, nullptr));
- fill = Some(style->mFill.kind.AsColor().CalcColor(aStyle));
+ fill = Some(style->mFill.kind.AsColor().CalcColor(aStyle, nullptr));
}
if ((style->mMozContextProperties.bits & StyleContextPropertyBits::STROKE) &&
style->mStroke.kind.IsColor()) {
haveContextPaint = true;
- contextPaint->SetStroke(style->mStroke.kind.AsColor().CalcColor(aStyle));
+ contextPaint->SetStroke(
+ style->mStroke.kind.AsColor().CalcColor(aStyle, nullptr));
- stroke = Some(style->mStroke.kind.AsColor().CalcColor(aStyle));
+ stroke = Some(style->mStroke.kind.AsColor().CalcColor(aStyle, nullptr));
}
if (style->mMozContextProperties.bits &
StyleContextPropertyBits::FILL_OPACITY) {
if ((style->mMozContextProperties.bits &
StyleContextPropertyBits::FILL_OPACITY) &&

View File

@@ -1,15 +0,0 @@
diff --git a/services/sync/modules/service.sys.mjs b/services/sync/modules/service.sys.mjs
index 4f4efe572909441abdd81909282936702c225621..81ab06a9414ed656b644a21b40b683f06a4f8dbf 100644
--- a/services/sync/modules/service.sys.mjs
+++ b/services/sync/modules/service.sys.mjs
@@ -99,6 +99,10 @@ function getEngineModules() {
whenTrue: "ExtensionStorageEngineKinto",
whenFalse: "ExtensionStorageEngineBridge",
};
+ result.Spaces = {
+ module: "resource:///modules/zen/ZenWorkspacesSync.sys.mjs",
+ symbol: "ZenWorkspacesEngine",
+ };
return result;
}

View File

@@ -0,0 +1,14 @@
diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py
index 403401613189ffb758037850dc6bbb1d55f194ab..cad28e245155eb54775e551885532026e56c5fa9 100755
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -2275,6 +2275,9 @@ class XPCShellTests:
appDirKey = None
if "appname" in self.mozInfo:
appDirKey = self.mozInfo["appname"] + "-appdir"
+ if appDirKey == "zen-appdir":
+ # Inherited manifests use firefox-appdir.
+ appDirKey = "firefox-appdir"
# We have to do this before we run tests that depend on having the node
# http/2 server.

View File

@@ -1,37 +0,0 @@
diff --git a/toolkit/components/contextualidentity/ContextualIdentityService.sys.mjs b/toolkit/components/contextualidentity/ContextualIdentityService.sys.mjs
index 5702ff28cc22206f5ce16584dac8a78d816562ce..3d08ecc97ce5995b30d8a4af0c33df329b428008 100644
--- a/toolkit/components/contextualidentity/ContextualIdentityService.sys.mjs
+++ b/toolkit/components/contextualidentity/ContextualIdentityService.sys.mjs
@@ -270,11 +270,29 @@ _ContextualIdentityService.prototype = {
});
},
- create(name, icon, color) {
+ create(name, icon, color, id = null) {
this.ensureDataReady();
- // Retrieve the next userContextId available.
- let userContextId = ++this._lastUserContextId;
+ if (id !== null) {
+ id = typeof id == "string" ? Number(id) : id;
+ if (!Number.isSafeInteger(id) || id <= 0) {
+ throw new Error(`Invalid userContextId '${id}'`);
+ }
+ }
+
+ let userContextId;
+ if (
+ id !== null &&
+ !this._identities.some(identity => identity.userContextId === id)
+ ) {
+ userContextId = id;
+ this._lastUserContextId = Math.max(
+ this._lastUserContextId,
+ userContextId
+ );
+ } else {
+ userContextId = ++this._lastUserContextId;
+ }
// Throw an error if the next userContextId available is invalid (the one associated to
// MAX_USER_CONTEXT_ID is already reserved to "userContextIdInternal.webextStorageLocal", which

View File

@@ -0,0 +1,29 @@
diff --git a/toolkit/content/widgets/panel-list/panel-list.mjs b/toolkit/content/widgets/panel-list/panel-list.mjs
index 68ad2fafc8b31dfff541cf8381d9b9533e376d1c..fa62fec6bfb33338091fc06d3736fb76fd5c47c4 100644
--- a/toolkit/content/widgets/panel-list/panel-list.mjs
+++ b/toolkit/content/widgets/panel-list/panel-list.mjs
@@ -223,7 +223,12 @@ export class PanelList extends HTMLElement {
this.setAttribute("showing", "true");
// Tell the host element to hide any overflow in case the panel extends off
// the page before the alignment is set.
- hostElement.style.overflow = "hidden";
+ const hostHidesOverflow = !getComputedStyle(hostElement)
+ .overflow.split(" ")
+ .includes("visible");
+ if (!hostHidesOverflow) {
+ hostElement.style.overflow = "hidden";
+ }
// Wait for a layout flush, then find the bounds.
let {
@@ -344,7 +349,9 @@ export class PanelList extends HTMLElement {
// Set the alignments and show the panel.
this.setAttribute("align", align);
this.setAttribute("valign", valign);
- hostElement.style.overflow = "";
+ if (!hostHidesOverflow) {
+ hostElement.style.overflow = "";
+ }
// Decide positioning based on where this panel will be rendered
const offsetParentIsBody =
this.supportsPopover() ||

View File

@@ -1,5 +1,5 @@
diff --git a/toolkit/content/widgets/tabbox.js b/toolkit/content/widgets/tabbox.js
index 9334120e818b609c6cb6792fd509e90c9b362551..2dde0c8698eb75bac0d0eb4d800d11b577e10a46 100644
index 402fe6a74b5327a30199667de18f053ad75fe910..9bcbc827d18db2f996d964f7c7e3439e064c9e0d 100644
--- a/toolkit/content/widgets/tabbox.js
+++ b/toolkit/content/widgets/tabbox.js
@@ -11,6 +11,23 @@
@@ -26,7 +26,7 @@ index 9334120e818b609c6cb6792fd509e90c9b362551..2dde0c8698eb75bac0d0eb4d800d11b5
let imports = {};
ChromeUtils.defineESModuleGetters(imports, {
DeferredTask: "resource://gre/modules/DeferredTask.sys.mjs",
@@ -225,7 +242,7 @@
@@ -226,7 +243,7 @@
) {
this._inAsyncOperation = false;
if (oldPanel != this._selectedPanel) {
@@ -35,7 +35,7 @@ index 9334120e818b609c6cb6792fd509e90c9b362551..2dde0c8698eb75bac0d0eb4d800d11b5
this._selectedPanel?.classList.add("deck-selected");
}
this.setAttribute("selectedIndex", val);
@@ -924,7 +941,7 @@
@@ -898,7 +915,7 @@
if (!tab) {
return;
}
@@ -44,7 +44,7 @@ index 9334120e818b609c6cb6792fd509e90c9b362551..2dde0c8698eb75bac0d0eb4d800d11b5
if (otherTab != tab && otherTab.selected) {
otherTab._selected = false;
}
@@ -960,6 +977,7 @@
@@ -934,6 +951,7 @@
* @param {MozTab|null} [val]
*/
set selectedItem(val) {
@@ -52,7 +52,7 @@ index 9334120e818b609c6cb6792fd509e90c9b362551..2dde0c8698eb75bac0d0eb4d800d11b5
if (val && !val.selected) {
// The selectedIndex setter ignores invalid values
// such as -1 if |val| isn't one of our child nodes.
@@ -1137,7 +1155,7 @@
@@ -1111,7 +1129,7 @@
if (tab == startTab) {
return null;
}
@@ -61,10 +61,10 @@ index 9334120e818b609c6cb6792fd509e90c9b362551..2dde0c8698eb75bac0d0eb4d800d11b5
return tab;
}
}
@@ -1199,13 +1217,30 @@
* @param {boolean} [aWrap]
@@ -1175,13 +1193,30 @@
*/
advanceSelectedTab(aDir, aWrap) {
// eslint-disable-next-line no-unused-vars
advanceSelectedTab(aDir, aWrap, aEvent) {
+ if (window?.gZenGlanceManager?._animating) return;
let { ariaFocusedItem } = this;
let startTab = ariaFocusedItem;
@@ -93,7 +93,7 @@ index 9334120e818b609c6cb6792fd509e90c9b362551..2dde0c8698eb75bac0d0eb4d800d11b5
// Handle keyboard navigation for a hidden tab that can be selected, like the Firefox View tab,
// which has a random placement in this.allTabs.
if (startTab.hidden) {
@@ -1218,7 +1253,7 @@
@@ -1194,7 +1229,7 @@
newTab = this.findNextTab(startTab, {
direction: aDir,
wrap: aWrap,

View File

@@ -1,5 +1,5 @@
diff --git a/toolkit/modules/JSONFile.sys.mjs b/toolkit/modules/JSONFile.sys.mjs
index 397991e4af8f49b6365d729fc11267b5c1113400..9b1d6fd3850b239000a3c4d2a2d5799a0989f4e3 100644
index 397991e4af8f49b6365d729fc11267b5c1113400..599ed16981aa1f1e9abfee2ad6c1883efd88e0ba 100644
--- a/toolkit/modules/JSONFile.sys.mjs
+++ b/toolkit/modules/JSONFile.sys.mjs
@@ -132,6 +132,7 @@ export function JSONFile(config) {
@@ -16,14 +16,14 @@ index 397991e4af8f49b6365d729fc11267b5c1113400..9b1d6fd3850b239000a3c4d2a2d5799a
try {
- await IOUtils.writeJSON(
+ if (this._useSizeHints && this._lastSavedSize) {
+ this._options.jsonLengthHint = Math.ceil(this._lastSavedSize * 1.05);
+ this._options.lengthHint = Math.ceil(this._lastSavedSize * 1.05);
+ }
+ const result = await IOUtils.writeJSON(
this.path,
this._data,
Object.assign({ tmpPath: this.path + ".tmp" }, this._options)
);
+ this._lastSavedSize = this._useSizeHints ? result : null;
+ this._lastSavedSize = this._useSizeHints ? result.jsonLength : null;
} catch (ex) {
if (typeof this._data.toJSONSafe == "function") {
// If serialization fails, try fallback safe JSON converter.

View File

@@ -1,13 +1,13 @@
diff --git a/toolkit/themes/shared/menulist.css b/toolkit/themes/shared/menulist.css
index 3b3e855f20c74f096324c42814e63cbdeb486051..f52e47fc8acea20a4e073b7f4a588d4d4e721aa8 100644
index d763691ab48424aebd1f5152c8b60011445f2244..984b39f8a21c9460d316f8c0b77003a279aa2b6e 100644
--- a/toolkit/themes/shared/menulist.css
+++ b/toolkit/themes/shared/menulist.css
@@ -53,7 +53,7 @@
@@ -55,7 +55,7 @@
:host(:not([native])) {
appearance: none;
- background-color: var(--button-background-color);
- background-color: var(--select-background-color);
+ background-color: light-dark(rgba(0,0,0,.1), rgba(255,255,255,.1));
color: var(--button-text-color);
border-radius: var(--button-border-radius);
padding-block: var(--space-xsmall);
color: var(--select-text-color);
border: var(--select-border);
border-radius: var(--select-border-radius);

View File

@@ -1,8 +1,8 @@
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
index b54980f967ab8fe9b9c13bbad8fae6323ec84f1f..f1a5481fb3bd44c1f8f6e40f4163aa7842623325 100644
index dcce3335e14f9f5d3c0b9fe6a86527be6011c143..ca788d6bd1db3a14d80bf571813e9c706456968f 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -1333,9 +1333,11 @@ nsresult nsXREDirProvider::AppendFromAppData(nsIFile* aFile, bool aIsDotted) {
@@ -1335,14 +1335,10 @@ nsresult nsXREDirProvider::AppendFromAppData(nsIFile* aFile, bool aIsDotted) {
// Similar to nsXREDirProvider::AppendProfilePath.
// TODO: Bug 1990407 - Evaluate if refactoring might be required there in the
// future?
@@ -10,12 +10,17 @@ index b54980f967ab8fe9b9c13bbad8fae6323ec84f1f..f1a5481fb3bd44c1f8f6e40f4163aa78
+ // Use aIsDotted for a different purpose here, will probably break in the future
+ if (gAppData->profile && aIsDotted) {
nsAutoCString profile;
profile = gAppData->profile;
-# if defined(MOZ_THUNDERBIRD)
- if (gAppData->profile[0] != '.') {
- profile.Assign('.');
- }
-# endif
- profile.Append(gAppData->profile);
+ profile = "."_ns + nsDependentCString(gAppData->profile);
MOZ_TRY(aFile->AppendRelativeNativePath(profile));
} else {
nsAutoCString vendor;
@@ -1345,8 +1347,6 @@ nsresult nsXREDirProvider::AppendFromAppData(nsIFile* aFile, bool aIsDotted) {
@@ -1352,8 +1348,6 @@ nsresult nsXREDirProvider::AppendFromAppData(nsIFile* aFile, bool aIsDotted) {
ToLowerCase(vendor);
ToLowerCase(appName);
@@ -24,11 +29,16 @@ index b54980f967ab8fe9b9c13bbad8fae6323ec84f1f..f1a5481fb3bd44c1f8f6e40f4163aa78
MOZ_TRY(aFile->AppendRelativeNativePath(appName));
}
@@ -1514,13 +1514,8 @@ nsresult nsXREDirProvider::GetLegacyOrXDGHomePath(const char* aHomeDir,
// If the build was made against a specific profile name, MOZ_APP_PROFILE=
// then make sure we respect this and dont move to XDG directory
- if (gAppData->profile) {
@@ -1530,18 +1524,8 @@ nsresult nsXREDirProvider::GetLegacyOrXDGHomePath(const char* aHomeDir,
// of a specific build where legacy needs to be forced, similar to the
// Firefox handling. Both casing are verified to account for systems where
// that matters.
- if (gAppData->profile
-# if defined(MOZ_THUNDERBIRD)
- && strcmp(gAppData->profile, "thunderbird") != 0 &&
- strcmp(gAppData->profile, "Thunderbird") != 0
-# endif
- ) {
- MOZ_TRY(NS_NewNativeLocalFile(nsDependentCString(aHomeDir),
- getter_AddRefs(localDir)));
- } else {

View File

@@ -1,15 +1,15 @@
diff --git a/widget/SwipeTracker.cpp b/widget/SwipeTracker.cpp
index 887d06d3bd9cdaa934880e0ae7a11ec8b737fb61..979f93ddab0d661ac1a1d73e7a0ba27fa2c8f9b7 100644
index 83b80a808261ce28e5c571dc802993556477f0c8..8de39d5c724e23f540a70f47e893e46bcf1112e6 100644
--- a/widget/SwipeTracker.cpp
+++ b/widget/SwipeTracker.cpp
@@ -3,6 +3,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SwipeTracker.h"
@@ -10,6 +10,7 @@
#include "mozilla/PresShell.h"
#include "mozilla/StaticPrefs_browser.h"
#include "mozilla/StaticPrefs_widget.h"
+#include "mozilla/StaticPrefs_zen.h"
#include "InputData.h"
#include "mozilla/FlushType.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/TouchEvents.h"
#include "mozilla/dom/SimpleGestureEventBinding.h"
@@ -67,6 +68,9 @@ double SwipeTracker::SwipeSuccessTargetValue() const {
}

View File

@@ -1,16 +1,16 @@
diff --git a/widget/Theme.cpp b/widget/Theme.cpp
index 766a8ca4bc6fcc98f719ad4f472b20bc1d198ac9..be4419cfafb55e5cac8f5de741185ee3cabc4722 100644
index 0d9c9014dabfe7177c25d6f983ff823c4435a327..7995de05ed556fa6373b83e3e44bffc1b857dd73 100644
--- a/widget/Theme.cpp
+++ b/widget/Theme.cpp
@@ -18,6 +18,7 @@
#include "mozilla/RelativeLuminanceUtils.h"
#include "mozilla/ScrollContainerFrame.h"
#include "mozilla/StaticPrefs_widget.h"
@@ -25,6 +25,7 @@
#include "mozilla/gfx/Filters.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/gfx/Types.h"
+#include "mozilla/nsZenBoostsBackend.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "nsCSSColorUtils.h"
#include "nsCSSRendering.h"
@@ -670,10 +671,15 @@ template <typename PaintBackendData>
@@ -671,10 +672,15 @@ template <typename PaintBackendData>
void Theme::PaintTextField(PaintBackendData& aPaintData,
const LayoutDeviceRect& aRect,
const ElementState& aState, const Colors& aColors,
@@ -27,7 +27,7 @@ index 766a8ca4bc6fcc98f719ad4f472b20bc1d198ac9..be4419cfafb55e5cac8f5de741185ee3
const CSSCoord radius = 2.0f;
ThemeDrawing::PaintRoundedRectWithRadius(aPaintData, aRect, backgroundColor,
@@ -690,9 +696,9 @@ template <typename PaintBackendData>
@@ -691,9 +697,9 @@ template <typename PaintBackendData>
void Theme::PaintListbox(PaintBackendData& aPaintData,
const LayoutDeviceRect& aRect,
const ElementState& aState, const Colors& aColors,
@@ -39,7 +39,7 @@ index 766a8ca4bc6fcc98f719ad4f472b20bc1d198ac9..be4419cfafb55e5cac8f5de741185ee3
}
template <typename PaintBackendData>
@@ -1158,10 +1164,12 @@ bool Theme::DoDrawWidgetBackground(PaintBackendData& aPaintData,
@@ -1159,10 +1165,12 @@ bool Theme::DoDrawWidgetBackground(PaintBackendData& aPaintData,
case StyleAppearance::Textfield:
case StyleAppearance::NumberInput:
case StyleAppearance::PasswordInput:

View File

@@ -1,16 +1,16 @@
diff --git a/widget/cocoa/VibrancyManager.mm b/widget/cocoa/VibrancyManager.mm
index 5df70a63afb235d2db11712276bb63f756222a0f..a2865aa2748433cbfd956ae46d197200fbbcfadd 100644
index bc62ff28285691c605fe0680e7a98927f11d5882..c209b63179df298e9b43182813ba0045f08328cc 100644
--- a/widget/cocoa/VibrancyManager.mm
+++ b/widget/cocoa/VibrancyManager.mm
@@ -11,6 +11,7 @@
@@ -9,6 +9,7 @@
#import <objc/message.h>
#include "nsCocoaWindow.h"
#include "mozilla/StaticPrefs_widget.h"
+#include "mozilla/StaticPrefs_zen.h"
#include "nsCocoaWindow.h"
using namespace mozilla;
@@ -29,6 +30,9 @@ static NSVisualEffectState VisualEffectStateForVibrancyType(
@@ -28,6 +29,9 @@ static NSVisualEffectState VisualEffectStateForVibrancyType(
case VibrancyType::Sidebar:
break;
}
@@ -20,44 +20,3 @@ index 5df70a63afb235d2db11712276bb63f756222a0f..a2865aa2748433cbfd956ae46d197200
return NSVisualEffectStateFollowsWindowActiveState;
}
@@ -36,7 +40,23 @@ static NSVisualEffectMaterial VisualEffectMaterialForVibrancyType(
VibrancyType aType) {
switch (aType) {
case VibrancyType::Sidebar:
- return NSVisualEffectMaterialSidebar;
+ switch (StaticPrefs::zen_widget_macos_window_material()) {
+ case 1:
+ return NSVisualEffectMaterialHUDWindow;
+ case 2:
+ return NSVisualEffectMaterialFullScreenUI;
+ case 3:
+ return NSVisualEffectMaterialPopover;
+ case 4:
+ return NSVisualEffectMaterialMenu;
+ case 5:
+ return NSVisualEffectMaterialToolTip;
+ case 6:
+ return NSVisualEffectMaterialHeaderView;
+ case 7:
+ default:
+ return NSVisualEffectMaterialUnderWindowBackground;
+ }
case VibrancyType::Titlebar:
return NSVisualEffectMaterialTitlebar;
}
@@ -76,6 +96,7 @@ - (NSView*)hitTest:(NSPoint)aPoint {
- (void)prefChanged {
self.blendingMode = VisualEffectBlendingModeForVibrancyType(mType);
+ self.material = VisualEffectMaterialForVibrancyType(mType);
}
@end
@@ -86,6 +107,7 @@ static void PrefChanged(const char* aPref, void* aClosure) {
static constexpr nsLiteralCString kObservedPrefs[] = {
"widget.macos.sidebar-blend-mode.behind-window"_ns,
"widget.macos.titlebar-blend-mode.behind-window"_ns,
+ "zen.widget.macos.window-material"_ns,
};
VibrancyManager::VibrancyManager(const nsCocoaWindow& aCoordinateConverter,

View File

@@ -0,0 +1,23 @@
diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h
index 312011c1c2ac41e78affecbdef25d72766a7c882..e5865c7d6259f0a3df48edf7a26b1b75a23cdb3a 100644
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -462,6 +462,10 @@ class nsCocoaWindow final : public nsIWidget {
void SetHideTitlebarSeparator(bool) override;
bool IsMacTitlebarDirectionRTL() override;
void SetCustomTitlebar(bool) override;
+ void SetWindowClass(const nsAString& aXulWinType,
+ const nsAString& aXulWinClass,
+ const nsAString& aXulWinName) override;
+ void UpdateWindowMaterial();
void UpdateThemeGeometries(
const nsTArray<ThemeGeometry>& aThemeGeometries) override;
void LockAspectRatio(bool aShouldLock) override;
@@ -672,6 +676,7 @@ class nsCocoaWindow final : public nsIWidget {
bool mAspectRatioLocked = false;
bool mIsAlert = false; // True if this is an non-native alert window.
bool mWasShown = false;
+ bool mIsBrowserWindow = false;
int32_t mNumModalDescendants = 0;

View File

@@ -0,0 +1,134 @@
diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
index 2efd02e4a92433fd29bbfdb707aa81cfec45031e..3b763c3927f07e529c826f8e4f62bc80a324b247 100644
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -86,6 +86,7 @@
#include "mozilla/StaticPrefs_gfx.h"
#include "mozilla/StaticPrefs_ui.h"
#include "mozilla/StaticPrefs_widget.h"
+#include "mozilla/StaticPrefs_zen.h"
#include "mozilla/WritingModes.h"
#include "mozilla/dom/Document.h"
#include "mozilla/layers/CompositorBridgeChild.h"
@@ -1332,6 +1333,110 @@ - (NSRect)_opaqueRectForWindowMoveWhenInTitlebar {
}
@end
+@interface ZenWindowMaterialView : NSVisualEffectView
+- (void)prefChanged;
+@end
+
+static void ZenWindowMaterialPrefChanged(const char* aPref, void* aClosure) {
+ [static_cast<ZenWindowMaterialView*>(aClosure) prefChanged];
+}
+
+static constexpr nsLiteralCString kZenWindowMaterialPrefs[] = {
+ "zen.widget.macos.window-material"_ns,
+ "zen.view.grey-out-inactive-windows"_ns,
+};
+
+static NSVisualEffectMaterial ZenWindowMaterial() {
+ switch (StaticPrefs::zen_widget_macos_window_material()) {
+ case 1:
+ return NSVisualEffectMaterialHUDWindow;
+ case 2:
+ return NSVisualEffectMaterialFullScreenUI;
+ case 3:
+ return NSVisualEffectMaterialPopover;
+ case 4:
+ return NSVisualEffectMaterialMenu;
+ case 5:
+ return NSVisualEffectMaterialToolTip;
+ case 6:
+ return NSVisualEffectMaterialHeaderView;
+ case 7:
+ default:
+ return NSVisualEffectMaterialUnderWindowBackground;
+ }
+}
+
+@implementation ZenWindowMaterialView
+- (instancetype)initWithFrame:(NSRect)aRect {
+ self = [super initWithFrame:aRect];
+ self.appearance = nil;
+ self.emphasized = NO;
+ self.blendingMode = NSVisualEffectBlendingModeBehindWindow;
+ [self prefChanged];
+ for (const auto& pref : kZenWindowMaterialPrefs) {
+ Preferences::RegisterCallback(ZenWindowMaterialPrefChanged, pref, self);
+ }
+ return self;
+}
+
+- (void)dealloc {
+ for (const auto& pref : kZenWindowMaterialPrefs) {
+ Preferences::UnregisterCallback(ZenWindowMaterialPrefChanged, pref, self);
+ }
+ [super dealloc];
+}
+
+- (void)prefChanged {
+ self.state = StaticPrefs::zen_view_grey_out_inactive_windows()
+ ? NSVisualEffectStateFollowsWindowActiveState
+ : NSVisualEffectStateActive;
+ self.material = ZenWindowMaterial();
+}
+@end
+
+static void ZenWindowVibrancyPrefChanged(const char* aPref, void* aClosure) {
+ static_cast<nsCocoaWindow*>(aClosure)->UpdateWindowMaterial();
+}
+
+void nsCocoaWindow::SetWindowClass(const nsAString& aXulWinType,
+ const nsAString& aXulWinClass,
+ const nsAString& aXulWinName) {
+ if (mWindowType != WindowType::TopLevel || mIsBrowserWindow ||
+ !aXulWinType.EqualsLiteral("navigator:browser")) {
+ return;
+ }
+ mIsBrowserWindow = true;
+ Preferences::RegisterCallback(ZenWindowVibrancyPrefChanged,
+ "zen.widget.macos.window-vibrancy", this);
+ UpdateWindowMaterial();
+}
+
+void nsCocoaWindow::UpdateWindowMaterial() {
+ NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
+
+ if (!mWindow) {
+ return;
+ }
+ bool wanted = StaticPrefs::zen_widget_macos_window_vibrancy();
+ if (wanted ==
+ [mWindow.contentView isKindOfClass:[ZenWindowMaterialView class]]) {
+ return;
+ }
+
+ NSRect frame = mWindow.contentView.frame;
+ NSView* wrapper = wanted ? [[ZenWindowMaterialView alloc] initWithFrame:frame]
+ : [[NSView alloc] initWithFrame:frame];
+ wrapper.wantsLayer = YES;
+ for (NSView* view in [mWindow contentViewContents]) {
+ [view removeFromSuperviewWithoutNeedingDisplay];
+ [wrapper addSubview:view];
+ }
+ mWindow.contentView = wrapper;
+ [wrapper release];
+
+ NS_OBJC_END_TRY_IGNORE_BLOCK;
+}
+
void nsCocoaWindow::UpdateWindowDraggingRegion(
const LayoutDeviceIntRegion& aRegion) {
// mChildView returns YES from mouseDownCanMoveWindow, so we need to put
@@ -4919,6 +5024,10 @@ - (BOOL)wantsBestResolutionOpenGLSurface {
nsCocoaWindow::~nsCocoaWindow() {
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
+ if (mIsBrowserWindow) {
+ Preferences::UnregisterCallback(ZenWindowVibrancyPrefChanged,
+ "zen.widget.macos.window-vibrancy", this);
+ }
RemoveAllChildren();
if (mWindow && mWindowMadeHere) {
CancelAllTransitions();

View File

@@ -1,16 +1,16 @@
diff --git a/widget/cocoa/nsDragService.mm b/widget/cocoa/nsDragService.mm
index 81fe6f749c1d046141003ad2413605b4d4acf9ed..f26c2556657ad683dad3fa712feca5965343175d 100644
index 340a9ad81c5cb23bb7e5f927d11d5cffdde7ce70..32fc707ccfa56fa8c307860868d092c4a9050419 100644
--- a/widget/cocoa/nsDragService.mm
+++ b/widget/cocoa/nsDragService.mm
@@ -22,6 +22,7 @@
#include "mozilla/PresShell.h"
@@ -10,6 +10,7 @@
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentInlines.h"
+#include "mozilla/nsZenDragAndDrop.h"
#include "nsIContent.h"
#include "nsCocoaUtils.h"
#include "mozilla/gfx/2D.h"
@@ -146,6 +147,10 @@
+#include "mozilla/nsZenDragAndDrop.h"
#include "nsArrayUtils.h"
#include "nsCOMPtr.h"
#include "nsClipboard.h"
@@ -145,6 +146,10 @@
bitsPerPixel:32];
uint8_t* dest = [imageRep bitmapData];
@@ -21,7 +21,7 @@ index 81fe6f749c1d046141003ad2413605b4d4acf9ed..f26c2556657ad683dad3fa712feca596
for (uint32_t i = 0; i < height; ++i) {
uint8_t* src = map.mData + i * map.mStride;
for (uint32_t j = 0; j < width; ++j) {
@@ -153,15 +158,15 @@
@@ -152,15 +157,15 @@
// is premultipled here. Also, Quartz likes RGBA, so do that translation
// as well.
#ifdef IS_BIG_ENDIAN

View File

@@ -4,6 +4,7 @@
import { nsZenMultiWindowFeature } from "chrome://browser/content/zen-components/ZenCommonUtils.mjs";
import { nsZenMenuBar } from "chrome://browser/content/zen-components/ZenMenubar.mjs";
import { UrlbarShared } from "chrome://browser/content/urlbar/UrlbarShared.mjs";
window.gZenUIManager = {
_popupTrackingElements: [],
@@ -467,7 +468,7 @@ window.gZenUIManager = {
let searchMode = null;
if (!currentSearchMode) {
searchMode = {
source: UrlbarUtils.RESULT_SOURCE.ZEN_ACTIONS,
source: UrlbarShared.RESULT_SOURCE.ZEN_ACTIONS,
isPreview: true,
};
}

View File

@@ -113,15 +113,6 @@ body,
}
#zen-browser-background {
/* This is conceptually a background, but putting this on a pseudo-element
* avoids it from suppressing the chrome-content separator border, etc.
*
* See bugzilla's 1949528 and bug 1476281 (which would make this unnecessary). */
@media (-moz-platform: macos) {
-moz-default-appearance: -moz-sidebar;
appearance: auto;
}
/*
* Important: We set the color to `AccentColor` so we can
* Compute the stylings and get the native accent color.

View File

@@ -642,7 +642,7 @@
.urlbarView-row {
--urlbarView-row-padding-inline: 8px;
--urlbarView-row-padding-block: 10px;
--urlbarview-row-padding-block: 10px;
color: light-dark(rgba(0, 0, 0, 0.7), rgba(255, 255, 255, 0.7)) !important;
&:hover {

View File

@@ -46,8 +46,8 @@
min-height: 30px;
}
/* Firefox View */
#firefox-view-button,
#ai-window-toggle,
#wrapper-firefox-view-button {
display: none !important;
}

View File

@@ -253,7 +253,7 @@
--zen-active-tab-scale: 0.985;
/* Define tab hover background color */
--tab-hover-background-color: var(--toolbarbutton-hover-background);
--tab-background-color-hover: var(--toolbarbutton-hover-background);
/* Sidebar Notifications */
--zen-sidebar-notification-bg: color-mix(

View File

@@ -29,6 +29,7 @@ let JSWINDOWACTORS = {
DOMContentLoaded: {},
},
},
safeForUntrustedWebProcess: true,
matches: [
...Services.prefs.getStringPref("zen.injections.match-urls").split(","),
"about:preferences",
@@ -55,6 +56,7 @@ let JSWINDOWACTORS = {
},
allFrames: true,
remoteTypes: ["web", "file"],
safeForUntrustedWebProcess: true,
enablePreference: "zen.glance.enabled",
},
ZenWindowDrag: {
@@ -71,6 +73,7 @@ let JSWINDOWACTORS = {
},
messageManagerGroups: ["browsers"],
remoteTypes: ["web", "file"],
safeForUntrustedWebProcess: true,
enablePreference: "zen.view.drag-window-from-content",
},
};
@@ -88,6 +91,7 @@ if (!Services.appinfo.inSafeMode) {
DOMWindowCreated: {},
},
},
safeForUntrustedWebProcess: true,
allFrames: true,
remoteTypes: ["web", "file"],
enablePreference: "zen.boosts.enabled",

View File

@@ -12,7 +12,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
class nsZenUIMigration {
PREF_NAME = "zen.ui.migration.version";
MIGRATION_VERSION = 6;
MIGRATION_VERSION = 7;
init(isNewProfile) {
if (!isNewProfile) {
@@ -150,6 +150,20 @@ class nsZenUIMigration {
}, 1000);
});
}
_migrateV7() {
if (
AppConstants.platform === "macosx" &&
Services.prefs.prefHasUserValue(
"widget.macos.sidebar-blend-mode.behind-window"
) &&
!Services.prefs.getBoolPref(
"widget.macos.sidebar-blend-mode.behind-window"
)
) {
Services.prefs.setBoolPref("zen.widget.macos.window-vibrancy", false);
}
}
}
export var gZenUIMigration = new nsZenUIMigration();

View File

@@ -832,8 +832,9 @@ window.gZenCompactModeManager = {
const onLeave = event => {
if (AppConstants.platform == "macosx") {
const buttonRect =
gZenVerticalTabsManager.actualWindowButtons.getBoundingClientRect();
const buttonRect = window.windowUtils.getBoundsWithoutFlushing(
gZenVerticalTabsManager.actualWindowButtons
);
const MAC_WINDOW_BUTTONS_X_BORDER = buttonRect.width + buttonRect.x;
const MAC_WINDOW_BUTTONS_Y_BORDER = buttonRect.height + buttonRect.y;
if (

View File

@@ -60,7 +60,7 @@ zen-folder {
}
}
margin: 0 var(--tab-block-margin);
margin: 0 var(--tab-margin-block);
margin-inline-end: 0;
& > .tab-group-label-container {
@@ -70,7 +70,7 @@ zen-folder {
--tab-group-color: transparent !important;
padding-block-end: 0 !important;
margin: 0 !important;
height: calc(var(--tab-block-margin) * 2 + var(--tab-min-height));
height: calc(var(--tab-margin-block) * 2 + var(--tab-min-height));
padding-inline: var(--tab-group-label-padding);
:root[zen-sidebar-expanded="true"] & {
@@ -161,7 +161,7 @@ zen-folder {
}
&:hover::before {
background-color: var(--tab-hover-background-color) !important;
background-color: var(--tab-background-color-hover) !important;
}
&:after {

View File

@@ -343,7 +343,6 @@ class nsZenLiveFoldersManager {
],
},
});
}
deleteFolder(id, deleteFolder = true) {

View File

@@ -346,7 +346,7 @@ class ZenMediaCard {
onToggle() {
if (this.controller?.isPlaying) {
this.controller.pause();
this.controller.pause("user");
} else {
this.controller?.play();
}
@@ -365,7 +365,7 @@ class ZenMediaCard {
}
onSeekDrag(event) {
this.controller?.pause();
this.controller?.pause("user");
const newTime = (event.target.value / 100) * this.duration;
this.currentTimeEl.textContent = this.formatSecondsToTime(newTime);
}
@@ -408,7 +408,7 @@ class ZenMediaCard {
onClose() {
if (this.controller) {
this.controller.pause();
this.controller.pause("user");
} else {
const webRTC =
this.browser.browsingContext.currentWindowGlobal.getActor("WebRTC");
@@ -494,39 +494,49 @@ class nsZenMediaController {
window.addEventListener("TabClose", onTabDiscardedOrClosed);
window.addEventListener("TabBrowserDiscarded", onTabDiscardedOrClosed);
window.addEventListener("DOMAudioPlaybackStarted", event => {
const browser = event.target;
// The card is created right away (while the controller is fresh)
// but only shown if the media is still playing a moment later, so
// short sounds (e.g. notification pings) never reveal it.
setTimeout(() => {
const card = this.#cardForBrowser(browser);
if (!card || card.isSharing) {
return;
}
if (card.controller.isPlaying) {
card.refreshVisibility();
} else if (card.element.hidden) {
// The sound was over before ever being shown (e.g. a
// notification ping): drop the card instead of keeping a ghost
// around.
card.destroy();
}
}, 1000);
this.activateMediaControls(
browser.browsingContext.mediaController,
browser
);
});
window.addEventListener("DOMAudioPlaybackStopped", () => {
for (const card of this.#cards.values()) {
card.updateMuteState();
window.addEventListener("TabAttrModified", event => {
if (!event.detail.changed.includes("soundplaying")) {
return;
}
const tab = event.target;
if (!tab.hasAttribute("soundplaying")) {
this.onAudioPlaybackStopped();
return;
}
this.onAudioPlaybackStarted(tab.linkedBrowser);
});
}
onAudioPlaybackStarted(browser) {
// The card is created right away (while the controller is fresh) but
// only shown if the media is still playing a moment later, so short
// sounds (e.g. notification pings) never reveal it.
setTimeout(() => {
const card = this.#cardForBrowser(browser);
if (!card || card.isSharing) {
return;
}
if (card.controller.isPlaying) {
card.refreshVisibility();
} else if (card.element.hidden) {
// The sound was over before ever being shown (e.g. a notification
// ping): drop the card instead of keeping a ghost around.
card.destroy();
}
}, 1000);
this.activateMediaControls(
browser.browsingContext?.mediaController,
browser
);
}
onAudioPlaybackStopped() {
for (const card of this.#cards.values()) {
card.updateMuteState();
}
}
get frontCard() {
return this.#orderedCards.find(card => !card.element.hidden) ?? null;
}
@@ -660,7 +670,7 @@ class nsZenMediaController {
this.#cards.set(key, card);
if (controller) {
// Media cards start hidden and appear via the delayed check in
// DOMAudioPlaybackStarted or on tab switch, like the original bar;
// onAudioPlaybackStarted or on tab switch, like the original bar;
// sharing cards show right away.
card.element.hidden = true;
} else {

View File

@@ -138,6 +138,9 @@
width: 100%;
padding: 4px 6px;
border-radius: var(--border-radius-medium);
@media (-moz-platform: macos) {
border-radius: calc(var(--border-radius-medium) - 2px);
}
outline: var(--zen-sidebar-notification-outline);
outline-offset: -1.5px;
box-shadow: var(--zen-sidebar-notification-shadow);

Some files were not shown because too many files have changed in this diff Show More