summaryrefslogtreecommitdiffstats
path: root/widget
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
commit8dd16259287f58f9273002717ec4d27e97127719 (patch)
tree3863e62a53829a84037444beab3abd4ed9dfc7d0 /widget
parentReleasing progress-linux version 126.0.1-1~progress7.99u1. (diff)
downloadfirefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz
firefox-8dd16259287f58f9273002717ec4d27e97127719.zip
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'widget')
-rw-r--r--widget/ClipboardWriteRequestParent.cpp13
-rw-r--r--widget/ClipboardWriteRequestParent.h3
-rw-r--r--widget/GfxDriverInfo.cpp72
-rw-r--r--widget/GfxDriverInfo.h1
-rw-r--r--widget/LookAndFeel.h2
-rw-r--r--widget/PuppetWidget.cpp24
-rw-r--r--widget/ScrollbarDrawingGTK.cpp5
-rw-r--r--widget/Theme.cpp13
-rw-r--r--widget/ThemeColors.h3
-rw-r--r--widget/android/GeckoTelemetryDelegate.h100
-rw-r--r--widget/android/jni/Utils.cpp13
-rw-r--r--widget/android/moz.build2
-rw-r--r--widget/android/nsAppShell.cpp3
-rw-r--r--widget/android/nsClipboard.cpp2
-rw-r--r--widget/cocoa/AppearanceOverride.h19
-rw-r--r--widget/cocoa/AppearanceOverride.mm90
-rw-r--r--widget/cocoa/VibrancyManager.h46
-rw-r--r--widget/cocoa/VibrancyManager.mm74
-rw-r--r--widget/cocoa/ViewRegion.h1
-rw-r--r--widget/cocoa/moz.build1
-rw-r--r--widget/cocoa/nsChildView.mm44
-rw-r--r--widget/cocoa/nsClipboard.mm13
-rw-r--r--widget/cocoa/nsCocoaWindow.mm80
-rw-r--r--widget/cocoa/nsLookAndFeel.mm27
-rw-r--r--widget/cocoa/nsNativeThemeCocoa.h90
-rw-r--r--widget/cocoa/nsNativeThemeCocoa.mm178
-rw-r--r--widget/gtk/AsyncGtkClipboardRequest.cpp38
-rw-r--r--widget/gtk/GfxInfo.cpp20
-rw-r--r--widget/gtk/GtkCompositorWidget.cpp13
-rw-r--r--widget/gtk/MozContainerWayland.cpp70
-rw-r--r--widget/gtk/MozContainerWayland.h4
-rw-r--r--widget/gtk/WidgetStyleCache.cpp9
-rw-r--r--widget/gtk/WindowSurfaceProvider.cpp1
-rw-r--r--widget/gtk/gtk3drawing.cpp103
-rw-r--r--widget/gtk/gtkdrawing.h49
-rw-r--r--widget/gtk/nsAppShell.cpp1
-rw-r--r--widget/gtk/nsClipboard.cpp339
-rw-r--r--widget/gtk/nsClipboard.h14
-rw-r--r--widget/gtk/nsClipboardWayland.cpp21
-rw-r--r--widget/gtk/nsClipboardX11.cpp25
-rw-r--r--widget/gtk/nsDragService.cpp2
-rw-r--r--widget/gtk/nsLookAndFeel.cpp8
-rw-r--r--widget/gtk/nsNativeThemeGTK.cpp33
-rw-r--r--widget/gtk/nsWaylandDisplay.cpp4
-rw-r--r--widget/gtk/nsWindow.cpp185
-rw-r--r--widget/gtk/nsWindow.h13
-rw-r--r--widget/headless/HeadlessLookAndFeelGTK.cpp3
-rw-r--r--widget/nsBaseClipboard.cpp302
-rw-r--r--widget/nsBaseClipboard.h25
-rw-r--r--widget/nsBaseDragService.cpp6
-rw-r--r--widget/nsClipboardHelper.cpp20
-rw-r--r--widget/nsClipboardProxy.cpp27
-rw-r--r--widget/nsIBaseWindow.idl6
-rw-r--r--widget/nsIClipboard.idl17
-rw-r--r--widget/nsIClipboardHelper.idl12
-rw-r--r--widget/nsIDeviceContextSpec.cpp4
-rw-r--r--widget/nsIDeviceContextSpec.h2
-rw-r--r--widget/nsIDragService.idl2
-rw-r--r--widget/nsIJumpListBuilder.idl4
-rw-r--r--widget/nsIScreen.idl2
-rw-r--r--widget/nsITransferable.idl3
-rw-r--r--widget/nsIWidget.h2
-rw-r--r--widget/nsIWidgetListener.cpp2
-rw-r--r--widget/nsIWidgetListener.h6
-rw-r--r--widget/nsNativeTheme.cpp1
-rw-r--r--widget/nsTransferable.cpp9
-rw-r--r--widget/nsTransferable.h2
-rw-r--r--widget/nsXPLookAndFeel.cpp7
-rw-r--r--widget/reftests/reftest.list2
-rw-r--r--widget/tests/browser/browser_test_InputContextURI.js3
-rw-r--r--widget/tests/browser/browser_test_scrollbar_colors.js45
-rw-r--r--widget/tests/file_test_clipboard.js15
-rw-r--r--widget/tests/file_test_clipboard_asyncSetData.js4
-rw-r--r--widget/uikit/nsLookAndFeel.mm3
-rw-r--r--widget/windows/CompositorWidgetParent.cpp12
-rw-r--r--widget/windows/GfxInfo.cpp6
-rw-r--r--widget/windows/JumpListBuilder.cpp109
-rw-r--r--widget/windows/RemoteBackbuffer.cpp16
-rw-r--r--widget/windows/ToastNotification.cpp3
-rw-r--r--widget/windows/WinCompositorWidget.h8
-rw-r--r--widget/windows/filedialog/PWinFileDialog.ipdl17
-rw-r--r--widget/windows/filedialog/WinFileDialogChild.cpp60
-rw-r--r--widget/windows/filedialog/WinFileDialogCommands.cpp111
-rw-r--r--widget/windows/filedialog/WinFileDialogCommands.h186
-rw-r--r--widget/windows/filedialog/WinFileDialogCommandsDefn.ipdlh13
-rw-r--r--widget/windows/filedialog/WinFileDialogParent.cpp80
-rw-r--r--widget/windows/filedialog/WinFileDialogParent.h15
-rw-r--r--widget/windows/nsDataObj.cpp6
-rw-r--r--widget/windows/nsFilePicker.cpp344
-rw-r--r--widget/windows/nsFilePicker.h19
-rw-r--r--widget/windows/nsNativeThemeWin.cpp44
-rw-r--r--widget/windows/nsUXThemeData.cpp2
-rw-r--r--widget/windows/nsUXThemeData.h1
-rw-r--r--widget/windows/nsWindow.cpp272
-rw-r--r--widget/windows/nsWindow.h16
-rw-r--r--widget/windows/tests/gtest/TestJumpListBuilder.cpp261
-rw-r--r--widget/windows/tests/gtest/TestWinDND.cpp2
97 files changed, 1941 insertions, 2069 deletions
diff --git a/widget/ClipboardWriteRequestParent.cpp b/widget/ClipboardWriteRequestParent.cpp
index 751befbe05..8a05c6a194 100644
--- a/widget/ClipboardWriteRequestParent.cpp
+++ b/widget/ClipboardWriteRequestParent.cpp
@@ -27,7 +27,9 @@ ClipboardWriteRequestParent::ClipboardWriteRequestParent(
ClipboardWriteRequestParent::~ClipboardWriteRequestParent() = default;
-nsresult ClipboardWriteRequestParent::Init(const int32_t& aClipboardType) {
+nsresult ClipboardWriteRequestParent::Init(
+ const int32_t& aClipboardType,
+ mozilla::dom::WindowContext* aSettingWindowContext) {
nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID));
if (!clipboard) {
Unused << PClipboardWriteRequestParent::Send__delete__(this,
@@ -35,8 +37,9 @@ nsresult ClipboardWriteRequestParent::Init(const int32_t& aClipboardType) {
return NS_ERROR_FAILURE;
}
- nsresult rv = clipboard->AsyncSetData(aClipboardType, this,
- getter_AddRefs(mAsyncSetClipboardData));
+ nsresult rv =
+ clipboard->AsyncSetData(aClipboardType, aSettingWindowContext, this,
+ getter_AddRefs(mAsyncSetClipboardData));
if (NS_FAILED(rv)) {
Unused << PClipboardWriteRequestParent::Send__delete__(this, rv);
return rv;
@@ -57,12 +60,12 @@ NS_IMETHODIMP ClipboardWriteRequestParent::OnComplete(nsresult aResult) {
IPCResult ClipboardWriteRequestParent::RecvSetData(
const IPCTransferable& aTransferable) {
if (!mManager->ValidatePrincipal(
- aTransferable.requestingPrincipal(),
+ aTransferable.dataPrincipal(),
{ContentParent::ValidatePrincipalOptions::AllowNullPtr,
ContentParent::ValidatePrincipalOptions::AllowExpanded,
ContentParent::ValidatePrincipalOptions::AllowSystem})) {
ContentParent::LogAndAssertFailedPrincipalValidationInfo(
- aTransferable.requestingPrincipal(), __func__);
+ aTransferable.dataPrincipal(), __func__);
}
if (!mAsyncSetClipboardData) {
diff --git a/widget/ClipboardWriteRequestParent.h b/widget/ClipboardWriteRequestParent.h
index 6027661bdb..73dcc98192 100644
--- a/widget/ClipboardWriteRequestParent.h
+++ b/widget/ClipboardWriteRequestParent.h
@@ -27,7 +27,8 @@ class ClipboardWriteRequestParent final
explicit ClipboardWriteRequestParent(ContentParent* aManager);
- nsresult Init(const int32_t& aClipboardType);
+ nsresult Init(const int32_t& aClipboardType,
+ mozilla::dom::WindowContext* aSettingWindowContext);
IPCResult RecvSetData(const IPCTransferable& aTransferable);
IPCResult Recv__delete__(nsresult aReason);
diff --git a/widget/GfxDriverInfo.cpp b/widget/GfxDriverInfo.cpp
index d60b023ddc..4deafa5ad0 100644
--- a/widget/GfxDriverInfo.cpp
+++ b/widget/GfxDriverInfo.cpp
@@ -358,6 +358,77 @@ const GfxDeviceFamily* GfxDriverInfo::GetDeviceFamily(DeviceFamily id) {
case DeviceFamily::IntelMobileHDGraphics:
APPEND_DEVICE(0x0046); /* IntelMobileHDGraphics */
break;
+ case DeviceFamily::IntelGen12:
+ // Rocket Lake
+ APPEND_DEVICE(0x4C8C); // rkl_gt05
+ APPEND_DEVICE(0x4C8A); // rkl_gt1
+ APPEND_DEVICE(0x4C8B); // rkl_gt1
+ APPEND_DEVICE(0x4C90); // rkl_gt1
+ APPEND_DEVICE(0x4C9A); // rkl_gt1
+ // Alder Lake
+ APPEND_DEVICE(0x4683); // adl_gt05
+ APPEND_DEVICE(0x4693); // adl_gt05
+ APPEND_DEVICE(0x4680); // adl_gt1
+ APPEND_DEVICE(0x4681); // adl_gt1
+ APPEND_DEVICE(0x4682); // adl_gt1
+ APPEND_DEVICE(0x4688); // adl_gt1
+ APPEND_DEVICE(0x4689); // adl_gt1
+ APPEND_DEVICE(0x4690); // adl_gt1
+ APPEND_DEVICE(0x4691); // adl_gt1
+ APPEND_DEVICE(0x4692); // adl_gt1
+ APPEND_DEVICE(0x4626); // adl_gt2
+ APPEND_DEVICE(0x4628); // adl_gt2
+ APPEND_DEVICE(0x462A); // adl_gt2
+ APPEND_DEVICE(0x46A0); // adl_gt2
+ APPEND_DEVICE(0x46A1); // adl_gt2
+ APPEND_DEVICE(0x46A2); // adl_gt2
+ APPEND_DEVICE(0x46A3); // adl_gt2
+ APPEND_DEVICE(0x46A6); // adl_gt2
+ APPEND_DEVICE(0x46A8); // adl_gt2
+ APPEND_DEVICE(0x46AA); // adl_gt2
+ APPEND_DEVICE(0x46B0); // adl_gt2
+ APPEND_DEVICE(0x46B1); // adl_gt2
+ APPEND_DEVICE(0x46B2); // adl_gt2
+ APPEND_DEVICE(0x46B3); // adl_gt2
+ APPEND_DEVICE(0x46C0); // adl_gt2
+ APPEND_DEVICE(0x46C1); // adl_gt2
+ APPEND_DEVICE(0x46C2); // adl_gt2
+ APPEND_DEVICE(0x46C3); // adl_gt2
+ APPEND_DEVICE(0x46D0); // adl_n
+ APPEND_DEVICE(0x46D1); // adl_n
+ APPEND_DEVICE(0x46D2); // adl_n
+ // Tiger Lake
+ APPEND_DEVICE(0x9A60); // tgl_gt1
+ APPEND_DEVICE(0x9A68); // tgl_gt1
+ APPEND_DEVICE(0x9A70); // tgl_gt1
+ APPEND_DEVICE(0x9A40); // tgl_gt2
+ APPEND_DEVICE(0x9A49); // tgl_gt2
+ APPEND_DEVICE(0x9A59); // tgl_gt2
+ APPEND_DEVICE(0x9A78); // tgl_gt2
+ APPEND_DEVICE(0x9AC0); // tgl_gt2
+ APPEND_DEVICE(0x9AC9); // tgl_gt2
+ APPEND_DEVICE(0x9AD9); // tgl_gt2
+ APPEND_DEVICE(0x9AF8); // tgl_gt2
+ // Raptop Lake
+ APPEND_DEVICE(0xA780); // rpl
+ APPEND_DEVICE(0xA781); // rpl
+ APPEND_DEVICE(0xA782); // rpl
+ APPEND_DEVICE(0xA783); // rpl
+ APPEND_DEVICE(0xA788); // rpl
+ APPEND_DEVICE(0xA789); // rpl
+ APPEND_DEVICE(0xA720); // rpl_p
+ APPEND_DEVICE(0xA721); // rpl_p
+ APPEND_DEVICE(0xA7A0); // rpl_p
+ APPEND_DEVICE(0xA7A1); // rpl_p
+ APPEND_DEVICE(0xA7A8); // rpl_p
+ APPEND_DEVICE(0xA7A9); // rpl_p
+ // DG1
+ APPEND_DEVICE(0x4905);
+ APPEND_DEVICE(0x4906);
+ APPEND_DEVICE(0x4907);
+ APPEND_DEVICE(0x4908);
+ APPEND_DEVICE(0x4909);
+ break;
case DeviceFamily::NvidiaBlockD3D9Layers:
// Glitches whilst scrolling (see bugs 612007, 644787, 645872)
APPEND_DEVICE(0x00f3); /* NV43 [GeForce 6200 (TM)] */
@@ -651,6 +722,7 @@ const nsAString& GfxDriverInfo::GetDeviceVendor(DeviceFamily id) {
case DeviceFamily::IntelKabyLake:
case DeviceFamily::IntelHD520:
case DeviceFamily::IntelMobileHDGraphics:
+ case DeviceFamily::IntelGen12:
case DeviceFamily::IntelWebRenderBlocked:
case DeviceFamily::Bug1116812:
case DeviceFamily::Bug1155608:
diff --git a/widget/GfxDriverInfo.h b/widget/GfxDriverInfo.h
index a584c7ac3f..0e1ba5c02d 100644
--- a/widget/GfxDriverInfo.h
+++ b/widget/GfxDriverInfo.h
@@ -181,6 +181,7 @@ enum class DeviceFamily : uint8_t {
IntelKabyLake,
IntelHD520,
IntelMobileHDGraphics,
+ IntelGen12,
NvidiaBlockD3D9Layers,
RadeonX1000,
RadeonCaicos,
diff --git a/widget/LookAndFeel.h b/widget/LookAndFeel.h
index 13219ff54b..2300f51388 100644
--- a/widget/LookAndFeel.h
+++ b/widget/LookAndFeel.h
@@ -92,8 +92,6 @@ class LookAndFeel {
TreeScrollDelay,
// the maximum number of lines to be scrolled at ones
TreeScrollLinesMax,
- // What type of tab-order to use
- TabFocusModel,
// Should menu items blink when they're chosen?
ChosenMenuItemsShouldBlink,
diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp
index 07b22d9a2b..7da6de3eaa 100644
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -900,17 +900,14 @@ void PuppetWidget::SetCursor(const Cursor& aCursor) {
return;
}
- bool hasCustomCursor = false;
- Maybe<mozilla::ipc::BigBuffer> customCursorData;
- size_t length = 0;
- IntSize customCursorSize;
- int32_t stride = 0;
- auto format = SurfaceFormat::B8G8R8A8;
ImageResolution resolution = aCursor.mResolution;
+ Maybe<IPCImage> customCursor;
if (aCursor.IsCustom()) {
- int32_t width = 0, height = 0;
+ int32_t width = 0;
+ int32_t height = 0;
aCursor.mContainer->GetWidth(&width);
aCursor.mContainer->GetHeight(&height);
+
const int32_t flags =
imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY;
RefPtr<SourceSurface> surface;
@@ -928,22 +925,17 @@ void PuppetWidget::SetCursor(const Cursor& aCursor) {
surface =
aCursor.mContainer->GetFrame(imgIContainer::FRAME_CURRENT, flags);
}
+
if (surface) {
if (RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface()) {
- hasCustomCursor = true;
- customCursorData =
- nsContentUtils::GetSurfaceData(*dataSurface, &length, &stride);
- customCursorSize = dataSurface->GetSize();
- format = dataSurface->GetFormat();
+ customCursor = nsContentUtils::SurfaceToIPCImage(*dataSurface);
}
}
}
if (!mBrowserChild->SendSetCursor(
- aCursor.mDefaultCursor, hasCustomCursor, std::move(customCursorData),
- customCursorSize.width, customCursorSize.height, resolution.mX,
- resolution.mY, stride, format, aCursor.mHotspotX, aCursor.mHotspotY,
- force)) {
+ aCursor.mDefaultCursor, std::move(customCursor), resolution.mX,
+ resolution.mY, aCursor.mHotspotX, aCursor.mHotspotY, force)) {
return;
}
mCursor = aCursor;
diff --git a/widget/ScrollbarDrawingGTK.cpp b/widget/ScrollbarDrawingGTK.cpp
index 3e0cad9179..9262667dcb 100644
--- a/widget/ScrollbarDrawingGTK.cpp
+++ b/widget/ScrollbarDrawingGTK.cpp
@@ -116,10 +116,7 @@ bool ScrollbarDrawingGTK::PaintScrollbarThumb(
}
bool ScrollbarDrawingGTK::ShouldDrawScrollbarButtons() {
- if (StaticPrefs::widget_non_native_theme_enabled()) {
- return StaticPrefs::widget_non_native_theme_gtk_scrollbar_allow_buttons();
- }
- return true;
+ return StaticPrefs::widget_non_native_theme_gtk_scrollbar_allow_buttons();
}
void ScrollbarDrawingGTK::RecomputeScrollbarParams() {
diff --git a/widget/Theme.cpp b/widget/Theme.cpp
index 15bf68ec01..fcfea14175 100644
--- a/widget/Theme.cpp
+++ b/widget/Theme.cpp
@@ -767,11 +767,11 @@ void Theme::PaintMenulistArrow(nsIFrame* aFrame, DrawTarget& aDrawTarget,
const auto direction = [&] {
const auto wm = aFrame->GetWritingMode();
switch (wm.GetBlockDir()) {
- case WritingMode::BlockDir::eBlockLR:
+ case WritingMode::BlockDir::LR:
return PhysicalArrowDirection::Right;
- case WritingMode::BlockDir::eBlockRL:
+ case WritingMode::BlockDir::RL:
return PhysicalArrowDirection::Left;
- case WritingMode::BlockDir::eBlockTB:
+ case WritingMode::BlockDir::TB:
return PhysicalArrowDirection::Bottom;
}
MOZ_ASSERT_UNREACHABLE("Unknown direction?");
@@ -1099,9 +1099,6 @@ bool Theme::CreateWebRenderCommandsForWidget(
const mozilla::layers::StackingContextHelper& aSc,
mozilla::layers::RenderRootStateManager* aManager, nsIFrame* aFrame,
StyleAppearance aAppearance, const nsRect& aRect) {
- if (!StaticPrefs::widget_non_native_theme_webrender()) {
- return false;
- }
WebRenderBackendData data{aBuilder, aResources, aSc, aManager};
return DoDrawWidgetBackground(data, aFrame, aAppearance, aRect,
DrawOverflow::Yes);
@@ -1208,6 +1205,7 @@ bool Theme::DoDrawWidgetBackground(PaintBackendData& aPaintData,
case StyleAppearance::Textarea:
case StyleAppearance::Textfield:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
PaintTextField(aPaintData, devPxRect, elementState, colors, dpiRatio);
break;
case StyleAppearance::Listbox:
@@ -1435,6 +1433,7 @@ LayoutDeviceIntMargin Theme::GetWidgetBorder(nsDeviceContext* aContext,
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Listbox:
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
@@ -1503,6 +1502,7 @@ bool Theme::GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFrame,
case StyleAppearance::Textarea:
case StyleAppearance::Textfield:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Listbox:
case StyleAppearance::MenulistButton:
case StyleAppearance::Menulist:
@@ -1678,6 +1678,7 @@ bool Theme::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame,
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::MozMenulistArrowButton:
case StyleAppearance::SpinnerUpbutton:
case StyleAppearance::SpinnerDownbutton:
diff --git a/widget/ThemeColors.h b/widget/ThemeColors.h
index 739a7ca0f0..0e0fd044bb 100644
--- a/widget/ThemeColors.h
+++ b/widget/ThemeColors.h
@@ -62,7 +62,8 @@ class ThemeColors {
explicit ThemeColors(const nsIFrame* aFrame, StyleAppearance aAppearance)
: mDoc(*aFrame->PresContext()->Document()),
mHighContrastInfo(ShouldBeHighContrast(*aFrame->PresContext())),
- mColorScheme(ColorSchemeForWidget(aFrame, aAppearance, mHighContrastInfo)),
+ mColorScheme(
+ ColorSchemeForWidget(aFrame, aAppearance, mHighContrastInfo)),
mAccentColor(*aFrame->Style(), mColorScheme) {}
virtual ~ThemeColors() = default;
diff --git a/widget/android/GeckoTelemetryDelegate.h b/widget/android/GeckoTelemetryDelegate.h
deleted file mode 100644
index 43b20d4ad6..0000000000
--- a/widget/android/GeckoTelemetryDelegate.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-#ifndef GeckoTelemetryDelegate_h__
-#define GeckoTelemetryDelegate_h__
-
-#include "geckoview/streaming/GeckoViewStreamingTelemetry.h"
-
-#include <jni.h>
-
-#include "mozilla/java/RuntimeTelemetryNatives.h"
-#include "mozilla/jni/Natives.h"
-
-namespace mozilla {
-namespace widget {
-
-class GeckoTelemetryDelegate final
- : public GeckoViewStreamingTelemetry::StreamingTelemetryDelegate,
- public mozilla::java::RuntimeTelemetry::Proxy::Natives<
- GeckoTelemetryDelegate> {
- public:
- // Implement Proxy native.
- static void RegisterDelegateProxy(
- mozilla::java::RuntimeTelemetry::Proxy::Param aProxy) {
- MOZ_ASSERT(aProxy);
-
- GeckoViewStreamingTelemetry::RegisterDelegate(
- new GeckoTelemetryDelegate(aProxy));
- }
-
- explicit GeckoTelemetryDelegate(
- mozilla::java::RuntimeTelemetry::Proxy::Param aProxy)
- : mProxy(aProxy) {}
-
- private:
- void DispatchHistogram(bool aIsCategorical, const nsCString& aName,
- const nsTArray<uint32_t>& aSamples) {
- if (!mozilla::jni::IsAvailable() || !mProxy || aSamples.Length() < 1) {
- return;
- }
-
- // Convert aSamples to an array of int64_t. We know |samples| required
- // capacity needs to match |aSamples.Length()|.
- nsTArray<int64_t> samples(aSamples.Length());
- for (size_t i = 0, l = aSamples.Length(); i < l; ++i) {
- samples.AppendElement(static_cast<int64_t>(aSamples[i]));
- }
-
- // LongArray::From *copies* the elements
- mProxy->DispatchHistogram(aIsCategorical, aName,
- mozilla::jni::LongArray::From(samples));
- }
-
- // Implement StreamingTelemetryDelegate.
- void ReceiveHistogramSamples(const nsCString& aName,
- const nsTArray<uint32_t>& aSamples) override {
- DispatchHistogram(/* isCategorical */ false, aName, aSamples);
- }
-
- void ReceiveCategoricalHistogramSamples(
- const nsCString& aName, const nsTArray<uint32_t>& aSamples) override {
- DispatchHistogram(/* isCategorical */ true, aName, aSamples);
- }
-
- void ReceiveBoolScalarValue(const nsCString& aName, bool aValue) override {
- if (!mozilla::jni::IsAvailable() || !mProxy) {
- return;
- }
-
- mProxy->DispatchBooleanScalar(aName, aValue);
- }
-
- void ReceiveStringScalarValue(const nsCString& aName,
- const nsCString& aValue) override {
- if (!mozilla::jni::IsAvailable() || !mProxy) {
- return;
- }
-
- mProxy->DispatchStringScalar(aName, aValue);
- }
-
- void ReceiveUintScalarValue(const nsCString& aName,
- uint32_t aValue) override {
- if (!mozilla::jni::IsAvailable() || !mProxy) {
- return;
- }
-
- mProxy->DispatchLongScalar(aName, static_cast<int64_t>(aValue));
- }
-
- mozilla::java::RuntimeTelemetry::Proxy::GlobalRef mProxy;
-};
-
-} // namespace widget
-} // namespace mozilla
-
-#endif // GeckoTelemetryDelegate_h__
diff --git a/widget/android/jni/Utils.cpp b/widget/android/jni/Utils.cpp
index 8d3800fd03..78e1ab647a 100644
--- a/widget/android/jni/Utils.cpp
+++ b/widget/android/jni/Utils.cpp
@@ -9,6 +9,7 @@
#include <android/log.h>
#include <pthread.h>
+#include <sys/prctl.h>
#include "mozilla/Assertions.h"
#include "mozilla/java/GeckoAppShellWrappers.h"
@@ -164,10 +165,20 @@ JNIEnv* GetEnvForThread() {
return env;
}
+ // By default the VM has a nasty habit of overwriting our lovely
+ // thread names with "Thread-<n>" making them hard to identify in a debugger,
+ // so we pass the name in AttachArgs below to prevent that from happening.
+ // PR_GET_NAME requires a 16 byte buffer: https://linux.die.net/man/2/prctl.
+ // JNI_VERSION_1_4 is required for NewDirectByteBuffer.
+ char threadName[16] = {'\0'};
+ prctl(PR_GET_NAME, threadName);
+ JavaVMAttachArgs attachArgs{
+ .version = JNI_VERSION_1_4, .name = threadName, .group = nullptr};
+
// We don't have a saved JNIEnv, so try to get one.
// AttachCurrentThread() does the same thing as GetEnv() when a thread is
// already attached, so we don't have to call GetEnv() at all.
- if (!sJavaVM->AttachCurrentThread(&env, nullptr)) {
+ if (!sJavaVM->AttachCurrentThread(&env, &attachArgs)) {
MOZ_ASSERT(env);
MOZ_ALWAYS_TRUE(!pthread_setspecific(sThreadEnvKey, env));
return env;
diff --git a/widget/android/moz.build b/widget/android/moz.build
index e4525bb747..2623442020 100644
--- a/widget/android/moz.build
+++ b/widget/android/moz.build
@@ -69,7 +69,6 @@ classes_with_WrapForJNI = [
"ImageDecoder",
"MediaDrmProxy",
"PanZoomController",
- "RuntimeTelemetry",
"Sample",
"SampleBuffer",
"ScreenManagerHelper",
@@ -193,7 +192,6 @@ LOCAL_INCLUDES += [
"/layout/forms",
"/layout/painting",
"/netwerk/base",
- "/toolkit/components/telemetry",
"/widget",
"/widget/headless",
"/xpcom/threads",
diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp
index 4d396945c4..c42f025b2c 100644
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -69,7 +69,6 @@
#include "GeckoNetworkManager.h"
#include "GeckoProcessManager.h"
#include "GeckoSystemStateListener.h"
-#include "GeckoTelemetryDelegate.h"
#include "GeckoVRManager.h"
#include "ImageDecoderSupport.h"
#include "JavaBuiltins.h"
@@ -412,7 +411,6 @@ nsAppShell::nsAppShell()
GeckoAppShellSupport::Init();
XPCOMEventTargetWrapper::Init();
mozilla::widget::Telemetry::Init();
- mozilla::widget::GeckoTelemetryDelegate::Init();
if (XRE_IsGPUProcess()) {
mozilla::gl::AndroidSurfaceTexture::Init();
@@ -443,7 +441,6 @@ nsAppShell::nsAppShell()
mozilla::widget::Base64UtilsSupport::Init();
nsWindow::InitNatives();
mozilla::gl::AndroidSurfaceTexture::Init();
- mozilla::widget::GeckoTelemetryDelegate::Init();
java::GeckoThread::SetState(java::GeckoThread::State::JNI_READY());
diff --git a/widget/android/nsClipboard.cpp b/widget/android/nsClipboard.cpp
index c2a03dd540..3c94b89c01 100644
--- a/widget/android/nsClipboard.cpp
+++ b/widget/android/nsClipboard.cpp
@@ -164,7 +164,7 @@ nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable,
}
}
- return NS_ERROR_FAILURE;
+ return NS_OK;
}
nsresult nsClipboard::EmptyNativeClipboardData(int32_t aWhichClipboard) {
diff --git a/widget/cocoa/AppearanceOverride.h b/widget/cocoa/AppearanceOverride.h
deleted file mode 100644
index c4ae629320..0000000000
--- a/widget/cocoa/AppearanceOverride.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
-/* 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/. */
-
-#ifndef AppearanceOverride_h
-#define AppearanceOverride_h
-
-#import <Cocoa/Cocoa.h>
-
-// Implements support for the browser.theme.toolbar-theme pref.
-// Use MOZGlobalAppearance.sharedInstance.effectiveAppearance
-// in all places where you would like the global override to be respected. The
-// effectiveAppearance property can be key-value observed.
-@interface MOZGlobalAppearance : NSObject <NSAppearanceCustomization>
-@property(class, readonly) MOZGlobalAppearance* sharedInstance;
-@end
-
-#endif
diff --git a/widget/cocoa/AppearanceOverride.mm b/widget/cocoa/AppearanceOverride.mm
deleted file mode 100644
index c3938d6b93..0000000000
--- a/widget/cocoa/AppearanceOverride.mm
+++ /dev/null
@@ -1,90 +0,0 @@
-/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
-/* 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/. */
-
-#import <Cocoa/Cocoa.h>
-
-#include "AppearanceOverride.h"
-
-#include "mozilla/Preferences.h"
-#include "mozilla/StaticPrefs_browser.h"
-#include "mozilla/StaticPrefs_widget.h"
-
-#include "nsXULAppAPI.h"
-
-static void ToolbarThemePrefChanged(const char* aPref, void* aUserInfo);
-
-@interface MOZGlobalAppearance ()
-@property NSInteger toolbarTheme;
-@end
-
-@implementation MOZGlobalAppearance
-
-+ (MOZGlobalAppearance*)sharedInstance {
- static MOZGlobalAppearance* sInstance = nil;
- if (!sInstance) {
- sInstance = [[MOZGlobalAppearance alloc] init];
- if (XRE_IsParentProcess()) {
- mozilla::Preferences::RegisterCallbackAndCall(
- &ToolbarThemePrefChanged,
- nsDependentCString(
- mozilla::StaticPrefs::GetPrefName_browser_theme_toolbar_theme()));
- }
- }
- return sInstance;
-}
-
-+ (NSSet*)keyPathsForValuesAffectingAppearance {
- return [NSSet setWithObjects:@"toolbarTheme", nil];
-}
-
-- (NSAppearance*)appearance {
- switch (self.toolbarTheme) { // Value for browser.theme.toolbar-theme pref
- case 0: // Dark
- return [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
- case 1: // Light
- return [NSAppearance appearanceNamed:NSAppearanceNameAqua];
- case 2: // System
- default:
- return nil; // nil means "no override".
- }
-}
-
-- (void)setAppearance:(NSAppearance*)aAppearance {
- // ignored
-}
-
-- (NSApplication*)_app {
- return NSApp;
-}
-
-+ (NSSet*)keyPathsForValuesAffectingEffectiveAppearance {
- // Automatically notify any key-value observers of our effectiveAppearance
- // property whenever the pref or the NSApp's effectiveAppearance change.
- return
- [NSSet setWithObjects:@"toolbarTheme", @"_app.effectiveAppearance", nil];
-}
-
-- (NSAppearance*)effectiveAppearance {
- switch (self.toolbarTheme) { // Value for browser.theme.toolbar-theme pref
- case 0: // Dark
- return [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
- case 1: // Light
- return [NSAppearance appearanceNamed:NSAppearanceNameAqua];
- case 2: // System
- default:
- // Use the NSApp effectiveAppearance. This is the system appearance.
- return NSApp.effectiveAppearance;
- }
-}
-
-@end
-
-static void ToolbarThemePrefChanged(const char* aPref, void* aUserInfo) {
- MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
-
- MOZGlobalAppearance.sharedInstance.toolbarTheme =
- mozilla::StaticPrefs::browser_theme_toolbar_theme();
-}
diff --git a/widget/cocoa/VibrancyManager.h b/widget/cocoa/VibrancyManager.h
index c70ec60a3b..43adace794 100644
--- a/widget/cocoa/VibrancyManager.h
+++ b/widget/cocoa/VibrancyManager.h
@@ -7,24 +7,24 @@
#ifndef VibrancyManager_h
#define VibrancyManager_h
-#include "mozilla/Assertions.h"
-#include "nsClassHashtable.h"
-#include "nsRegion.h"
-#include "nsTArray.h"
-#include "ViewRegion.h"
+#include "mozilla/EnumeratedArray.h"
+#include "Units.h"
-#import <Foundation/NSGeometry.h>
-
-@class NSColor;
@class NSView;
class nsChildView;
namespace mozilla {
+class ViewRegion;
+
enum class VibrancyType {
- TOOLTIP,
- MENU,
- TITLEBAR,
+ // Add new values here, or update MaxEnumValue below if you add them after.
+ Titlebar,
+};
+
+template <>
+struct MaxContiguousEnumValue<VibrancyType> {
+ static constexpr auto value = VibrancyType::Titlebar;
};
/**
@@ -51,9 +51,9 @@ class VibrancyManager {
* NSVisualEffectViews which will be created for vibrant regions.
*/
VibrancyManager(const nsChildView& aCoordinateConverter,
- NSView* aContainerView)
- : mCoordinateConverter(aCoordinateConverter),
- mContainerView(aContainerView) {}
+ NSView* aContainerView);
+
+ ~VibrancyManager();
/**
* Update the placement of the NSVisualEffectViews inside the container
@@ -66,26 +66,10 @@ class VibrancyManager {
bool UpdateVibrantRegion(VibrancyType aType,
const LayoutDeviceIntRegion& aRegion);
- bool HasVibrantRegions() { return !mVibrantRegions.IsEmpty(); }
-
- LayoutDeviceIntRegion GetUnionOfVibrantRegions() const;
-
- /**
- * Create an NSVisualEffectView for the specified vibrancy type. The return
- * value is not autoreleased. We return an object of type NSView* because we
- * compile with an SDK that does not contain a definition for
- * NSVisualEffectView.
- * @param aIsContainer Whether this NSView will have child views. This value
- * affects hit testing: Container views will pass through
- * hit testing requests to their children, and leaf views
- * will be transparent to hit testing.
- */
- static NSView* CreateEffectView(VibrancyType aType, BOOL aIsContainer = NO);
-
protected:
const nsChildView& mCoordinateConverter;
NSView* mContainerView;
- nsClassHashtable<nsUint32HashKey, ViewRegion> mVibrantRegions;
+ EnumeratedArray<VibrancyType, UniquePtr<ViewRegion>> mVibrantRegions;
};
} // namespace mozilla
diff --git a/widget/cocoa/VibrancyManager.mm b/widget/cocoa/VibrancyManager.mm
index 6062acb931..a2bef29a19 100644
--- a/widget/cocoa/VibrancyManager.mm
+++ b/widget/cocoa/VibrancyManager.mm
@@ -5,6 +5,9 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VibrancyManager.h"
+#include "ViewRegion.h"
+#include "nsRegion.h"
+#include "ViewRegion.h"
#import <objc/message.h>
@@ -20,18 +23,10 @@ using namespace mozilla;
vibrancyType:(VibrancyType)aVibrancyType;
@end
-@interface MOZVibrantLeafView : MOZVibrantView
-@end
-
static NSVisualEffectState VisualEffectStateForVibrancyType(
VibrancyType aType) {
switch (aType) {
- case VibrancyType::TOOLTIP:
- case VibrancyType::MENU:
- // Tooltip and menu windows are never "key", so we need to tell the
- // vibrancy effect to look active regardless of window state.
- return NSVisualEffectStateActive;
- case VibrancyType::TITLEBAR:
+ case VibrancyType::Titlebar:
break;
}
return NSVisualEffectStateFollowsWindowActiveState;
@@ -40,11 +35,7 @@ static NSVisualEffectState VisualEffectStateForVibrancyType(
static NSVisualEffectMaterial VisualEffectMaterialForVibrancyType(
VibrancyType aType) {
switch (aType) {
- case VibrancyType::TOOLTIP:
- return (NSVisualEffectMaterial)NSVisualEffectMaterialToolTip;
- case VibrancyType::MENU:
- return NSVisualEffectMaterialMenu;
- case VibrancyType::TITLEBAR:
+ case VibrancyType::Titlebar:
return NSVisualEffectMaterialTitlebar;
}
}
@@ -52,10 +43,7 @@ static NSVisualEffectMaterial VisualEffectMaterialForVibrancyType(
static NSVisualEffectBlendingMode VisualEffectBlendingModeForVibrancyType(
VibrancyType aType) {
switch (aType) {
- case VibrancyType::TOOLTIP:
- case VibrancyType::MENU:
- return NSVisualEffectBlendingModeBehindWindow;
- case VibrancyType::TITLEBAR:
+ case VibrancyType::Titlebar:
return StaticPrefs::widget_macos_titlebar_blend_mode_behind_window()
? NSVisualEffectBlendingModeBehindWindow
: NSVisualEffectBlendingModeWithinWindow;
@@ -63,7 +51,6 @@ static NSVisualEffectBlendingMode VisualEffectBlendingModeForVibrancyType(
}
@implementation MOZVibrantView
-
- (instancetype)initWithFrame:(NSRect)aRect vibrancyType:(VibrancyType)aType {
self = [super initWithFrame:aRect];
mType = aType;
@@ -76,50 +63,31 @@ static NSVisualEffectBlendingMode VisualEffectBlendingModeForVibrancyType(
return self;
}
-// Don't override allowsVibrancy here, because this view may have subviews, and
-// returning YES from allowsVibrancy forces on foreground vibrancy for all
-// descendant views, which can have unintended effects.
-
-@end
-
-@implementation MOZVibrantLeafView
-
- (NSView*)hitTest:(NSPoint)aPoint {
// This view must be transparent to mouse events.
return nil;
}
+@end
-// MOZVibrantLeafView does not have subviews, so we can return YES here without
-// having unintended effects on other contents of the window.
-- (BOOL)allowsVibrancy {
- return NO;
-}
+VibrancyManager::VibrancyManager(const nsChildView& aCoordinateConverter,
+ NSView* aContainerView)
+ : mCoordinateConverter(aCoordinateConverter),
+ mContainerView(aContainerView) {}
-@end
+VibrancyManager::~VibrancyManager() = default;
bool VibrancyManager::UpdateVibrantRegion(
VibrancyType aType, const LayoutDeviceIntRegion& aRegion) {
+ auto& slot = mVibrantRegions[aType];
if (aRegion.IsEmpty()) {
- return mVibrantRegions.Remove(uint32_t(aType));
+ bool hadRegion = !!slot;
+ slot = nullptr;
+ return hadRegion;
}
- auto& vr = *mVibrantRegions.GetOrInsertNew(uint32_t(aType));
- return vr.UpdateRegion(aRegion, mCoordinateConverter, mContainerView, ^() {
- return CreateEffectView(aType);
- });
-}
-
-LayoutDeviceIntRegion VibrancyManager::GetUnionOfVibrantRegions() const {
- LayoutDeviceIntRegion result;
- for (const auto& region : mVibrantRegions.Values()) {
- result.OrWith(region->Region());
+ if (!slot) {
+ slot = MakeUnique<ViewRegion>();
}
- return result;
-}
-
-/* static */ NSView* VibrancyManager::CreateEffectView(VibrancyType aType,
- BOOL aIsContainer) {
- return aIsContainer ? [[MOZVibrantView alloc] initWithFrame:NSZeroRect
- vibrancyType:aType]
- : [[MOZVibrantLeafView alloc] initWithFrame:NSZeroRect
- vibrancyType:aType];
+ return slot->UpdateRegion(aRegion, mCoordinateConverter, mContainerView, ^() {
+ return [[MOZVibrantView alloc] initWithFrame:NSZeroRect vibrancyType:aType];
+ });
}
diff --git a/widget/cocoa/ViewRegion.h b/widget/cocoa/ViewRegion.h
index b2ed0c8835..d44bde5f71 100644
--- a/widget/cocoa/ViewRegion.h
+++ b/widget/cocoa/ViewRegion.h
@@ -8,6 +8,7 @@
#define ViewRegion_h
#include "Units.h"
+#include "nsRegion.h"
#include "nsTArray.h"
class nsChildView;
diff --git a/widget/cocoa/moz.build b/widget/cocoa/moz.build
index d0939d34c7..125a7f2fc0 100644
--- a/widget/cocoa/moz.build
+++ b/widget/cocoa/moz.build
@@ -23,7 +23,6 @@ EXPORTS += [
]
UNIFIED_SOURCES += [
- "AppearanceOverride.mm",
"GfxInfo.mm",
"MOZIconHelper.mm",
"MOZMenuOpeningCoordinator.mm",
diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm
index d3241a983f..b57df15825 100644
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -1726,32 +1726,52 @@ static Maybe<VibrancyType> ThemeGeometryTypeToVibrancyType(
nsITheme::ThemeGeometryType aThemeGeometryType) {
switch (aThemeGeometryType) {
case eThemeGeometryTypeTitlebar:
- return Some(VibrancyType::TITLEBAR);
+ return Some(VibrancyType::Titlebar);
default:
return Nothing();
}
}
-static LayoutDeviceIntRegion GatherVibrantRegion(
- const nsTArray<nsIWidget::ThemeGeometry>& aThemeGeometries,
- VibrancyType aVibrancyType) {
- LayoutDeviceIntRegion region;
+static EnumeratedArray<VibrancyType, LayoutDeviceIntRegion>
+GatherVibrantRegions(Span<const nsIWidget::ThemeGeometry> aThemeGeometries) {
+ EnumeratedArray<VibrancyType, LayoutDeviceIntRegion> regions;
for (const auto& geometry : aThemeGeometries) {
- if (ThemeGeometryTypeToVibrancyType(geometry.mType) ==
- Some(aVibrancyType)) {
- region.OrWith(geometry.mRect);
+ auto vibrancyType = ThemeGeometryTypeToVibrancyType(geometry.mType);
+ if (!vibrancyType) {
+ continue;
}
+ regions[*vibrancyType].OrWith(geometry.mRect);
+ }
+ return regions;
+}
+
+// Subtracts parts from regions in such a way that they don't have any overlap.
+// Each region in the argument list will have the union of all the regions
+// *following* it subtracted from itself. In other words, the arguments are
+// treated as low priority to high priority.
+static void MakeRegionsNonOverlapping(Span<LayoutDeviceIntRegion> aRegions) {
+ LayoutDeviceIntRegion unionOfAll;
+ for (auto& region : aRegions) {
+ region.SubOut(unionOfAll);
+ unionOfAll.OrWith(region);
}
- return region;
}
void nsChildView::UpdateVibrancy(
const nsTArray<ThemeGeometry>& aThemeGeometries) {
- LayoutDeviceIntRegion titlebarRegion =
- GatherVibrantRegion(aThemeGeometries, VibrancyType::TITLEBAR);
+ auto regions = GatherVibrantRegions(aThemeGeometries);
+ MakeRegionsNonOverlapping(regions);
auto& vm = EnsureVibrancyManager();
- bool changed = vm.UpdateVibrantRegion(VibrancyType::TITLEBAR, titlebarRegion);
+ bool changed = false;
+
+ // EnumeratedArray doesn't have an iterator that also yields the enum type,
+ // but we rely on VibrancyType being contiguous and starting at 0, so we can
+ // do that manually.
+ size_t i = 0;
+ for (const auto& region : regions) {
+ changed |= vm.UpdateVibrantRegion(VibrancyType(i++), region);
+ }
if (changed) {
SuspendAsyncCATransactions();
diff --git a/widget/cocoa/nsClipboard.mm b/widget/cocoa/nsClipboard.mm
index ba747e5b27..1c4788460c 100644
--- a/widget/cocoa/nsClipboard.mm
+++ b/widget/cocoa/nsClipboard.mm
@@ -499,13 +499,12 @@ nsClipboard::HasNativeClipboardDataMatchingFlavors(
// XXX we only check the first pasteboard item as we only get data from
// first item in TransferableFromPasteboard for now.
if (NSPasteboardItem* item = [items objectAtIndex:0]) {
- if (NSString *availableType = [item
- availableTypeFromArray:
- [NSArray
- arrayWithObjects:[UTIHelper
- stringFromPboardType:
- (NSString*)kUTTypeFileURL],
- nil]]) {
+ if ([item availableTypeFromArray:
+ [NSArray
+ arrayWithObjects:[UTIHelper
+ stringFromPboardType:
+ (NSString*)kUTTypeFileURL],
+ nil]]) {
MOZ_CLIPBOARD_LOG(" has %s\n", mimeType.get());
return true;
}
diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
index 8e54d9e7fd..5032f35fa1 100644
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -6,7 +6,6 @@
#include "nsCocoaWindow.h"
-#include "AppearanceOverride.h"
#include "NativeKeyBindings.h"
#include "ScreenHelperCocoa.h"
#include "TextInputHandler.h"
@@ -158,6 +157,13 @@ void nsCocoaWindow::DestroyNativeWindow() {
// we clear our delegate.
EndOurNativeTransition();
+ // We are about to destroy mWindow. Before we do that, make sure that we
+ // hide the window using the Show() method, because it has several side
+ // effects that our parent and listeners might be expecting. If we don't
+ // do this now, then these side effects will never execute, though the
+ // window will definitely no longer be shown.
+ Show(false);
+
[mWindow releaseJSObjects];
// We want to unhook the delegate here because we don't want events
// sent to it after this object has been destroyed.
@@ -525,10 +531,6 @@ nsresult nsCocoaWindow::CreateNativeWindow(const NSRect& aRect,
[WindowDataMap.sharedWindowDataMap ensureDataForWindow:mWindow];
mWindowMadeHere = true;
- // Make the window respect the global appearance, which follows the
- // browser.theme.toolbar-theme pref.
- mWindow.appearanceSource = MOZGlobalAppearance.sharedInstance;
-
return NS_OK;
NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
@@ -1969,7 +1971,6 @@ void nsCocoaWindow::BackingScaleFactorChanged() {
if (PresShell* presShell = mWidgetListener->GetPresShell()) {
presShell->BackingScaleFactorChanged();
}
- mWidgetListener->UIResolutionChanged();
}
int32_t nsCocoaWindow::RoundsWidgetCoordinatesTo() {
@@ -2327,9 +2328,11 @@ void nsCocoaWindow::SetColorScheme(const Maybe<ColorScheme>& aScheme) {
if (!mWindow) {
return;
}
-
- mWindow.appearance = aScheme ? NSAppearanceForColorScheme(*aScheme) : nil;
-
+ NSAppearance* appearance =
+ aScheme ? NSAppearanceForColorScheme(*aScheme) : nil;
+ if (mWindow.appearance != appearance) {
+ mWindow.appearance = appearance;
+ }
NS_OBJC_END_TRY_IGNORE_BLOCK;
}
@@ -3071,10 +3074,6 @@ static NSMutableSet* gSwizzledFrameViewClasses = nil;
- (void)_setNeedsDisplayInRect:(NSRect)aRect;
@end
-@interface NSView (NSVisualEffectViewSetMaskImage)
-- (void)setMaskImage:(NSImage*)image;
-@end
-
@interface BaseWindow (Private)
- (void)removeTrackingArea;
- (void)cursorUpdated:(NSEvent*)aEvent;
@@ -3174,35 +3173,38 @@ static NSImage* GetMenuMaskImage() {
return maskImage;
}
-- (void)swapOutChildViewWrapper:(NSView*)aNewWrapper {
- aNewWrapper.frame = self.contentView.frame;
+// Add an effect view wrapper if needed so that the OS draws the appropriate
+// vibrancy effect and window border.
+- (void)setEffectViewWrapperForStyle:(WindowShadow)aStyle {
+ NSView* wrapper = [&]() -> NSView* {
+ if (aStyle == WindowShadow::Menu || aStyle == WindowShadow::Tooltip) {
+ const bool isMenu = aStyle == WindowShadow::Menu;
+ auto* effectView =
+ [[NSVisualEffectView alloc] initWithFrame:self.contentView.frame];
+ effectView.material =
+ isMenu ? NSVisualEffectMaterialMenu : NSVisualEffectMaterialToolTip;
+ // Tooltip and menu windows are never "key", so we need to tell the
+ // vibrancy effect to look active regardless of window state.
+ effectView.state = NSVisualEffectStateActive;
+ effectView.blendingMode = NSVisualEffectBlendingModeBehindWindow;
+ if (isMenu) {
+ // Turn on rounded corner masking.
+ effectView.maskImage = GetMenuMaskImage();
+ }
+ return effectView;
+ }
+ return [[NSView alloc] initWithFrame:self.contentView.frame];
+ }();
+
+ wrapper.wantsLayer = YES;
+ // Swap out our content view by the new view. Setting .contentView releases
+ // the old view.
NSView* childView = [self.mainChildView retain];
[childView removeFromSuperview];
- [aNewWrapper addSubview:childView];
+ [wrapper addSubview:childView];
[childView release];
- [super setContentView:aNewWrapper];
-}
-
-- (void)setEffectViewWrapperForStyle:(WindowShadow)aStyle {
- if (aStyle == WindowShadow::Menu || aStyle == WindowShadow::Tooltip) {
- // Add an effect view wrapper so that the OS draws the appropriate
- // vibrancy effect and window border.
- BOOL isMenu = aStyle == WindowShadow::Menu;
- NSView* effectView = VibrancyManager::CreateEffectView(
- isMenu ? VibrancyType::MENU : VibrancyType::TOOLTIP, YES);
- if (isMenu) {
- // Turn on rounded corner masking.
- [effectView setMaskImage:GetMenuMaskImage()];
- }
- [self swapOutChildViewWrapper:effectView];
- [effectView release];
- } else {
- // Remove the existing wrapper.
- NSView* wrapper = [[NSView alloc] initWithFrame:NSZeroRect];
- [wrapper setWantsLayer:YES];
- [self swapOutChildViewWrapper:wrapper];
- [wrapper release];
- }
+ super.contentView = wrapper;
+ [wrapper release];
}
- (NSTouchBar*)makeTouchBar {
diff --git a/widget/cocoa/nsLookAndFeel.mm b/widget/cocoa/nsLookAndFeel.mm
index 779984be0c..69bd348da8 100644
--- a/widget/cocoa/nsLookAndFeel.mm
+++ b/widget/cocoa/nsLookAndFeel.mm
@@ -3,7 +3,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "AppearanceOverride.h"
#include "mozilla/widget/ThemeChangeKind.h"
#include "nsLookAndFeel.h"
#include "nsCocoaFeatures.h"
@@ -239,9 +238,6 @@ nsresult nsLookAndFeel::NativeGetColor(ColorID aID, ColorScheme aScheme,
case ColorID::MozButtonhoverface:
case ColorID::MozButtonactiveface:
case ColorID::MozButtondisabledface:
- case ColorID::MozColheader:
- case ColorID::MozColheaderhover:
- case ColorID::MozColheaderactive:
color = GetColorFromNSColor(NSColor.controlColor);
if (!NS_GET_A(color)) {
color = GetColorFromNSColor(NSColor.controlBackgroundColor);
@@ -301,9 +297,6 @@ nsresult nsLookAndFeel::NativeGetColor(ColorID aID, ColorScheme aScheme,
case ColorID::Menutext:
case ColorID::Infotext:
case ColorID::MozCellhighlighttext:
- case ColorID::MozColheadertext:
- case ColorID::MozColheaderhovertext:
- case ColorID::MozColheaderactivetext:
case ColorID::MozSidebartext:
color = GetColorFromNSColor(NSColor.controlTextColor);
break;
@@ -319,6 +312,17 @@ nsresult nsLookAndFeel::NativeGetColor(ColorID aID, ColorScheme aScheme,
// For inactive list selection
color = GetColorFromNSColor(NSColor.secondarySelectedControlColor);
break;
+ case ColorID::MozColheadertext:
+ case ColorID::MozColheaderhovertext:
+ case ColorID::MozColheaderactivetext:
+ color = GetColorFromNSColor(NSColor.headerTextColor);
+ break;
+ case ColorID::MozColheaderactive:
+ color = GetColorFromNSColor(
+ NSColor.unemphasizedSelectedContentBackgroundColor);
+ break;
+ case ColorID::MozColheader:
+ case ColorID::MozColheaderhover:
case ColorID::MozEventreerow:
// Background color of even list rows.
color =
@@ -460,11 +464,6 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
case IntID::AlertNotificationOrigin:
aResult = NS_ALERT_TOP;
break;
- case IntID::TabFocusModel:
- aResult = [NSApp isFullKeyboardAccessEnabled]
- ? nsIContent::eTabFocus_any
- : nsIContent::eTabFocus_textControlsMask;
- break;
case IntID::ScrollToClick: {
aResult = [[NSUserDefaults standardUserDefaults]
boolForKey:@"AppleScrollerPagingBehavior"];
@@ -630,10 +629,6 @@ void nsLookAndFeel::RecordAccessibilityTelemetry() {
object:nil
suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
- [MOZGlobalAppearance.sharedInstance addObserver:self
- forKeyPath:@"effectiveAppearance"
- options:0
- context:nil];
[NSApp addObserver:self
forKeyPath:@"effectiveAppearance"
options:0
diff --git a/widget/cocoa/nsNativeThemeCocoa.h b/widget/cocoa/nsNativeThemeCocoa.h
index ebbf782264..66e5aec1df 100644
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -40,8 +40,6 @@ class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa {
eSquareBezelPushButton,
eArrowButton,
eHelpButton,
- eTreeTwistyPointingRight,
- eTreeTwistyPointingDown,
eDisclosureButtonClosed,
eDisclosureButtonOpen
};
@@ -131,12 +129,6 @@ class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa {
bool rtl = false;
};
- struct TreeHeaderCellParams {
- ControlParams controlParams;
- TreeSortDirection sortDirection = eTreeSortDirection_Natural;
- bool lastTreeHeaderCell = false;
- };
-
struct ScaleParams {
int32_t value = 0;
int32_t min = 0;
@@ -165,7 +157,6 @@ class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa {
eSearchField, // TextFieldParams
eProgressBar, // ProgressParams
eMeter, // MeterParams
- eTreeHeaderCell, // TreeHeaderCellParams
eScale, // ScaleParams
eMultilineTextField, // bool
eListBox,
@@ -221,9 +212,6 @@ class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa {
static WidgetInfo Meter(const MeterParams& aParams) {
return WidgetInfo(Widget::eMeter, aParams);
}
- static WidgetInfo TreeHeaderCell(const TreeHeaderCellParams& aParams) {
- return WidgetInfo(Widget::eTreeHeaderCell, aParams);
- }
static WidgetInfo Scale(const ScaleParams& aParams) {
return WidgetInfo(Widget::eScale, aParams);
}
@@ -251,7 +239,7 @@ class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa {
mozilla::Variant<mozilla::gfx::sRGBColor, CheckboxOrRadioParams,
ButtonParams, DropdownParams, SpinButtonParams,
SegmentParams, TextFieldParams, ProgressParams,
- MeterParams, TreeHeaderCellParams, ScaleParams, bool>
+ MeterParams, ScaleParams, bool>
mVariant;
enum Widget mWidget;
@@ -262,47 +250,42 @@ class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa {
NS_DECL_ISUPPORTS_INHERITED
// The nsITheme interface.
- NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
- StyleAppearance aAppearance,
- const nsRect& aRect, const nsRect& aDirtyRect,
+ NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame*,
+ StyleAppearance, const nsRect& aRect,
+ const nsRect& aDirtyRect,
DrawOverflow) override;
bool CreateWebRenderCommandsForWidget(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const mozilla::layers::StackingContextHelper& aSc,
- mozilla::layers::RenderRootStateManager* aManager, nsIFrame* aFrame,
- StyleAppearance aAppearance, const nsRect& aRect) override;
- [[nodiscard]] LayoutDeviceIntMargin GetWidgetBorder(
- nsDeviceContext* aContext, nsIFrame* aFrame,
- StyleAppearance aAppearance) override;
-
- bool GetWidgetPadding(nsDeviceContext* aContext, nsIFrame* aFrame,
- StyleAppearance aAppearance,
+ mozilla::layers::RenderRootStateManager* aManager, nsIFrame*,
+ StyleAppearance, const nsRect& aRect) override;
+ [[nodiscard]] LayoutDeviceIntMargin GetWidgetBorder(nsDeviceContext* aContext,
+ nsIFrame*,
+ StyleAppearance) override;
+
+ bool GetWidgetPadding(nsDeviceContext* aContext, nsIFrame*, StyleAppearance,
LayoutDeviceIntMargin* aResult) override;
- virtual bool GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFrame,
- StyleAppearance aAppearance,
- nsRect* aOverflowRect) override;
+ bool GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame*, StyleAppearance,
+ nsRect* aOverflowRect) override;
LayoutDeviceIntSize GetMinimumWidgetSize(nsPresContext*, nsIFrame*,
StyleAppearance) override;
- NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, StyleAppearance aAppearance,
- nsAtom* aAttribute, bool* aShouldRepaint,
+ NS_IMETHOD WidgetStateChanged(nsIFrame*, StyleAppearance, nsAtom* aAttribute,
+ bool* aShouldRepaint,
const nsAttrValue* aOldValue) override;
NS_IMETHOD ThemeChanged() override;
- bool ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame,
- StyleAppearance aAppearance) override;
- bool WidgetIsContainer(StyleAppearance aAppearance) override;
+ bool ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame*,
+ StyleAppearance) override;
+ bool WidgetIsContainer(StyleAppearance) override;
bool ThemeDrawsFocusForWidget(nsIFrame*, StyleAppearance) override;
bool ThemeNeedsComboboxDropmarker() override;
- virtual bool WidgetAppearanceDependsOnWindowFocus(
- StyleAppearance aAppearance) override;
- virtual ThemeGeometryType ThemeGeometryTypeForWidget(
- nsIFrame* aFrame, StyleAppearance aAppearance) override;
- virtual Transparency GetWidgetTransparency(
- nsIFrame* aFrame, StyleAppearance aAppearance) override;
- mozilla::Maybe<WidgetInfo> ComputeWidgetInfo(nsIFrame* aFrame,
- StyleAppearance aAppearance,
+ bool WidgetAppearanceDependsOnWindowFocus(StyleAppearance) override;
+ ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame*,
+ StyleAppearance) override;
+ Transparency GetWidgetTransparency(nsIFrame*, StyleAppearance) override;
+ mozilla::Maybe<WidgetInfo> ComputeWidgetInfo(nsIFrame*, StyleAppearance,
const nsRect& aRect);
void DrawProgress(CGContextRef context, const HIRect& inBoxRect,
const ProgressParams& aParams);
@@ -310,24 +293,18 @@ class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa {
protected:
virtual ~nsNativeThemeCocoa();
- LayoutDeviceIntMargin DirectionAwareMargin(
- const LayoutDeviceIntMargin& aMargin, nsIFrame* aFrame);
+ LayoutDeviceIntMargin DirectionAwareMargin(const LayoutDeviceIntMargin&,
+ nsIFrame*);
nsIFrame* SeparatorResponsibility(nsIFrame* aBefore, nsIFrame* aAfter);
- ControlParams ComputeControlParams(nsIFrame* aFrame,
- mozilla::dom::ElementState aEventState);
- SegmentParams ComputeSegmentParams(nsIFrame* aFrame,
- mozilla::dom::ElementState aEventState,
- SegmentType aSegmentType);
- TextFieldParams ComputeTextFieldParams(
- nsIFrame* aFrame, mozilla::dom::ElementState aEventState);
- ProgressParams ComputeProgressParams(nsIFrame* aFrame,
- mozilla::dom::ElementState aEventState,
+ ControlParams ComputeControlParams(nsIFrame*, mozilla::dom::ElementState);
+ SegmentParams ComputeSegmentParams(nsIFrame*, mozilla::dom::ElementState,
+ SegmentType);
+ TextFieldParams ComputeTextFieldParams(nsIFrame*, mozilla::dom::ElementState);
+ ProgressParams ComputeProgressParams(nsIFrame*, mozilla::dom::ElementState,
bool aIsHorizontal);
- MeterParams ComputeMeterParams(nsIFrame* aFrame);
- TreeHeaderCellParams ComputeTreeHeaderCellParams(
- nsIFrame* aFrame, mozilla::dom::ElementState aEventState);
+ MeterParams ComputeMeterParams(nsIFrame*);
mozilla::Maybe<ScaleParams> ComputeHTMLScaleParams(
- nsIFrame* aFrame, mozilla::dom::ElementState aEventState);
+ nsIFrame*, mozilla::dom::ElementState);
// HITheme drawing routines
void DrawMeter(CGContextRef context, const HIRect& inBoxRect,
@@ -363,8 +340,6 @@ class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa {
const ControlParams& aParams);
void DrawButton(CGContextRef context, const HIRect& inBoxRect,
const ButtonParams& aParams);
- void DrawTreeHeaderCell(CGContextRef context, const HIRect& inBoxRect,
- const TreeHeaderCellParams& aParams);
void DrawDropdown(CGContextRef context, const HIRect& inBoxRect,
const DropdownParams& aParams);
HIThemeButtonDrawInfo SpinButtonDrawInfo(ThemeButtonKind aKind,
@@ -396,7 +371,6 @@ class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa {
NSComboBoxCell* mComboBoxCell;
NSProgressBarCell* mProgressBarCell;
NSLevelIndicatorCell* mMeterBarCell;
- NSTableHeaderCell* mTreeHeaderCell;
MOZCellDrawWindow* mCellDrawWindow = nil;
MOZCellDrawView* mCellDrawView;
};
diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm
index 18913facea..ad16fac04a 100644
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -458,8 +458,6 @@ nsNativeThemeCocoa::nsNativeThemeCocoa() : ThemeCocoa(ScrollbarStyle()) {
mMeterBarCell = [[NSLevelIndicatorCell alloc]
initWithLevelIndicatorStyle:NSLevelIndicatorStyleContinuousCapacity];
- mTreeHeaderCell = [[NSTableHeaderCell alloc] init];
-
mCellDrawView = [[MOZCellDrawView alloc] init];
if (XRE_IsParentProcess()) {
@@ -498,7 +496,6 @@ nsNativeThemeCocoa::~nsNativeThemeCocoa() {
[mSearchFieldCell release];
[mDropdownCell release];
[mComboBoxCell release];
- [mTreeHeaderCell release];
[mCellDrawWindow release];
[mCellDrawView release];
@@ -1094,6 +1091,7 @@ static bool ShouldUnconditionallyDrawFocusRingIfFocused(nsIFrame* aFrame) {
// Mac always draws focus rings for textboxes and lists.
switch (aFrame->StyleDisplay()->EffectiveAppearance()) {
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::Searchfield:
@@ -1316,17 +1314,6 @@ static void RenderButton(CGContextRef cgContext, const HIRect& aRenderRect,
NULL);
}
-static ThemeDrawState ToThemeDrawState(
- const nsNativeThemeCocoa::ControlParams& aParams) {
- if (aParams.disabled) {
- return kThemeStateUnavailable;
- }
- if (aParams.pressed) {
- return kThemeStatePressed;
- }
- return kThemeStateActive;
-}
-
void nsNativeThemeCocoa::DrawHIThemeButton(
CGContextRef cgContext, const HIRect& aRect, ThemeButtonKind aKind,
ThemeButtonValue aValue, ThemeDrawState aState,
@@ -1376,16 +1363,6 @@ void nsNativeThemeCocoa::DrawButton(CGContextRef cgContext,
case ButtonType::eHelpButton:
DrawHelpButton(cgContext, inBoxRect, controlParams);
return;
- case ButtonType::eTreeTwistyPointingRight:
- DrawHIThemeButton(cgContext, inBoxRect, kThemeDisclosureButton,
- kThemeDisclosureRight, ToThemeDrawState(controlParams),
- kThemeAdornmentNone, controlParams);
- return;
- case ButtonType::eTreeTwistyPointingDown:
- DrawHIThemeButton(cgContext, inBoxRect, kThemeDisclosureButton,
- kThemeDisclosureDown, ToThemeDrawState(controlParams),
- kThemeAdornmentNone, controlParams);
- return;
case ButtonType::eDisclosureButtonClosed:
DrawDisclosureButton(cgContext, inBoxRect, controlParams,
NSControlStateValueOff);
@@ -1397,87 +1374,6 @@ void nsNativeThemeCocoa::DrawButton(CGContextRef cgContext,
}
}
-nsNativeThemeCocoa::TreeHeaderCellParams
-nsNativeThemeCocoa::ComputeTreeHeaderCellParams(nsIFrame* aFrame,
- ElementState aEventState) {
- TreeHeaderCellParams params;
- params.controlParams = ComputeControlParams(aFrame, aEventState);
- params.sortDirection = GetTreeSortDirection(aFrame);
- params.lastTreeHeaderCell = IsLastTreeHeaderCell(aFrame);
- return params;
-}
-
-@interface NSTableHeaderCell (NSTableHeaderCell_setSortable)
-// This method has been present in the same form since at least macOS 10.4.
-- (void)_setSortable:(BOOL)arg1
- showSortIndicator:(BOOL)arg2
- ascending:(BOOL)arg3
- priority:(NSInteger)arg4
- highlightForSort:(BOOL)arg5;
-@end
-
-void nsNativeThemeCocoa::DrawTreeHeaderCell(
- CGContextRef cgContext, const HIRect& inBoxRect,
- const TreeHeaderCellParams& aParams) {
- NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
-
- // Without clearing the cell's title, it takes on a default value of "Field",
- // which is displayed underneath the title set in the front-end.
- NSCell* cell = (NSCell*)mTreeHeaderCell;
- cell.title = @"";
-
- if ([mTreeHeaderCell
- respondsToSelector:@selector
- (_setSortable:
- showSortIndicator:ascending:priority:highlightForSort:)]) {
- switch (aParams.sortDirection) {
- case eTreeSortDirection_Ascending:
- [mTreeHeaderCell _setSortable:YES
- showSortIndicator:YES
- ascending:YES
- priority:0
- highlightForSort:YES];
- break;
- case eTreeSortDirection_Descending:
- [mTreeHeaderCell _setSortable:YES
- showSortIndicator:YES
- ascending:NO
- priority:0
- highlightForSort:YES];
- break;
- default:
- // eTreeSortDirection_Natural
- [mTreeHeaderCell _setSortable:YES
- showSortIndicator:NO
- ascending:YES
- priority:0
- highlightForSort:NO];
- break;
- }
- }
-
- mTreeHeaderCell.enabled = !aParams.controlParams.disabled;
- mTreeHeaderCell.state =
- (mTreeHeaderCell.enabled && aParams.controlParams.pressed)
- ? NSControlStateValueOn
- : NSControlStateValueOff;
-
- mCellDrawView._drawingEndSeparator = !aParams.lastTreeHeaderCell;
-
- NSGraphicsContext* savedContext = NSGraphicsContext.currentContext;
- NSGraphicsContext.currentContext =
- [NSGraphicsContext graphicsContextWithCGContext:cgContext flipped:YES];
- DrawCellIncludingFocusRing(mTreeHeaderCell, inBoxRect, mCellDrawView);
- NSGraphicsContext.currentContext = savedContext;
-
-#if DRAW_IN_FRAME_DEBUG
- CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
- CGContextFillRect(cgContext, inBoxRect);
-#endif
-
- NS_OBJC_END_TRY_IGNORE_BLOCK;
-}
-
static const CellRenderSettings dropdownSettings = {
{
NSMakeSize(0, 16), // mini
@@ -2159,8 +2055,6 @@ Maybe<nsNativeThemeCocoa::WidgetInfo> nsNativeThemeCocoa::ComputeWidgetInfo(
switch (aAppearance) {
case StyleAppearance::Menupopup:
- return Nothing();
-
case StyleAppearance::Tooltip:
return Nothing();
@@ -2323,6 +2217,7 @@ Maybe<nsNativeThemeCocoa::WidgetInfo> nsNativeThemeCocoa::ComputeWidgetInfo(
case StyleAppearance::Textfield:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
return Some(
WidgetInfo::TextField(ComputeTextFieldParams(aFrame, elementState)));
@@ -2348,30 +2243,6 @@ Maybe<nsNativeThemeCocoa::WidgetInfo> nsNativeThemeCocoa::ComputeWidgetInfo(
// Do nothing: progress and meter bars cases will draw chunks.
break;
- case StyleAppearance::Treetwisty:
- return Some(WidgetInfo::Button(
- ButtonParams{ComputeControlParams(aFrame, elementState),
- ButtonType::eTreeTwistyPointingRight}));
-
- case StyleAppearance::Treetwistyopen:
- return Some(WidgetInfo::Button(
- ButtonParams{ComputeControlParams(aFrame, elementState),
- ButtonType::eTreeTwistyPointingDown}));
-
- case StyleAppearance::Treeheadercell:
- return Some(WidgetInfo::TreeHeaderCell(
- ComputeTreeHeaderCellParams(aFrame, elementState)));
-
- case StyleAppearance::Treeitem:
- case StyleAppearance::Treeview:
- return Some(WidgetInfo::ColorFill(sRGBColor(1.0, 1.0, 1.0, 1.0)));
-
- case StyleAppearance::Treeheader:
- // do nothing, taken care of by individual header cells
- case StyleAppearance::Treeline:
- // do nothing, these lines don't exist on macos
- break;
-
case StyleAppearance::Range: {
Maybe<ScaleParams> params = ComputeHTMLScaleParams(aFrame, elementState);
if (params) {
@@ -2581,12 +2452,6 @@ void nsNativeThemeCocoa::RenderWidget(const WidgetInfo& aWidgetInfo,
DrawMeter(cgContext, macRect, params);
break;
}
- case Widget::eTreeHeaderCell: {
- TreeHeaderCellParams params =
- aWidgetInfo.Params<TreeHeaderCellParams>();
- DrawTreeHeaderCell(cgContext, macRect, params);
- break;
- }
case Widget::eScale: {
ScaleParams params = aWidgetInfo.Params<ScaleParams>();
DrawScale(cgContext, macRect, params);
@@ -2668,14 +2533,10 @@ bool nsNativeThemeCocoa::CreateWebRenderCommandsForWidget(
case StyleAppearance::MozMenulistArrowButton:
case StyleAppearance::Textfield:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Searchfield:
case StyleAppearance::ProgressBar:
case StyleAppearance::Meter:
- case StyleAppearance::Treeheadercell:
- case StyleAppearance::Treetwisty:
- case StyleAppearance::Treetwistyopen:
- case StyleAppearance::Treeitem:
- case StyleAppearance::Treeview:
case StyleAppearance::Range:
return false;
@@ -2747,6 +2608,7 @@ LayoutDeviceIntMargin nsNativeThemeCocoa::GetWidgetBorder(
break;
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield: {
SInt32 frameOutset = 0;
::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset);
@@ -2845,6 +2707,7 @@ bool nsNativeThemeCocoa::GetWidgetOverflow(nsDeviceContext* aContext,
case StyleAppearance::MozMacHelpButton:
case StyleAppearance::Toolbarbutton:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::Searchfield:
@@ -2957,6 +2820,7 @@ LayoutDeviceIntSize nsNativeThemeCocoa::GetMinimumWidgetSize(
}
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::Searchfield: {
@@ -2985,23 +2849,6 @@ LayoutDeviceIntSize nsNativeThemeCocoa::GetMinimumWidgetSize(
break;
}
- case StyleAppearance::Treetwisty:
- case StyleAppearance::Treetwistyopen: {
- SInt32 twistyHeight = 0, twistyWidth = 0;
- ::GetThemeMetric(kThemeMetricDisclosureButtonWidth, &twistyWidth);
- ::GetThemeMetric(kThemeMetricDisclosureButtonHeight, &twistyHeight);
- result.SizeTo(twistyWidth, twistyHeight);
- break;
- }
-
- case StyleAppearance::Treeheader:
- case StyleAppearance::Treeheadercell: {
- SInt32 headerHeight = 0;
- ::GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight);
- result.SizeTo(0, headerHeight);
- break;
- }
-
case StyleAppearance::Tab: {
result.SizeTo(0, tabHeights[miniControlSize]);
break;
@@ -3128,6 +2975,7 @@ bool nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext,
case StyleAppearance::SpinnerDownbutton:
case StyleAppearance::Statusbar:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::Searchfield:
@@ -3140,14 +2988,6 @@ bool nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext,
case StyleAppearance::Tabpanels:
case StyleAppearance::Tab:
- case StyleAppearance::Treetwisty:
- case StyleAppearance::Treetwistyopen:
- case StyleAppearance::Treeview:
- case StyleAppearance::Treeheader:
- case StyleAppearance::Treeheadercell:
- case StyleAppearance::Treeitem:
- case StyleAppearance::Treeline:
-
case StyleAppearance::Range:
return !IsWidgetStyled(aPresContext, aFrame, aAppearance);
@@ -3184,6 +3024,7 @@ bool nsNativeThemeCocoa::ThemeDrawsFocusForWidget(nsIFrame*,
case StyleAppearance::Textfield:
case StyleAppearance::Searchfield:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
case StyleAppearance::Button:
@@ -3212,9 +3053,8 @@ bool nsNativeThemeCocoa::WidgetAppearanceDependsOnWindowFocus(
case StyleAppearance::SpinnerDownbutton:
case StyleAppearance::Separator:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
- case StyleAppearance::Treeview:
- case StyleAppearance::Treeline:
case StyleAppearance::Textarea:
case StyleAppearance::Listbox:
return false;
diff --git a/widget/gtk/AsyncGtkClipboardRequest.cpp b/widget/gtk/AsyncGtkClipboardRequest.cpp
index 75801c698d..872b005bfd 100644
--- a/widget/gtk/AsyncGtkClipboardRequest.cpp
+++ b/widget/gtk/AsyncGtkClipboardRequest.cpp
@@ -17,17 +17,17 @@ AsyncGtkClipboardRequest::AsyncGtkClipboardRequest(ClipboardDataType aDataType,
switch (aDataType) {
case ClipboardDataType::Data:
- LOGCLIP(" getting DATA MIME %s\n", aMimeType);
+ MOZ_CLIPBOARD_LOG(" getting DATA MIME %s\n", aMimeType);
gtk_clipboard_request_contents(clipboard,
gdk_atom_intern(aMimeType, FALSE),
OnDataReceived, mRequest.get());
break;
case ClipboardDataType::Text:
- LOGCLIP(" getting TEXT\n");
+ MOZ_CLIPBOARD_LOG(" getting TEXT\n");
gtk_clipboard_request_text(clipboard, OnTextReceived, mRequest.get());
break;
case ClipboardDataType::Targets:
- LOGCLIP(" getting TARGETS\n");
+ MOZ_CLIPBOARD_LOG(" getting TARGETS\n");
gtk_clipboard_request_contents(clipboard,
gdk_atom_intern("TARGETS", FALSE),
OnDataReceived, mRequest.get());
@@ -39,9 +39,10 @@ void AsyncGtkClipboardRequest::OnDataReceived(GtkClipboard* clipboard,
GtkSelectionData* selection_data,
gpointer data) {
int whichClipboard = GetGeckoClipboardType(clipboard);
- LOGCLIP("OnDataReceived(%s) callback\n",
- whichClipboard == nsClipboard::kSelectionClipboard ? "primary"
- : "clipboard");
+ MOZ_CLIPBOARD_LOG("OnDataReceived(%s) callback\n",
+ whichClipboard == nsClipboard::kSelectionClipboard
+ ? "primary"
+ : "clipboard");
static_cast<Request*>(data)->Complete(selection_data);
}
@@ -49,14 +50,16 @@ void AsyncGtkClipboardRequest::OnTextReceived(GtkClipboard* clipboard,
const gchar* text,
gpointer data) {
int whichClipboard = GetGeckoClipboardType(clipboard);
- LOGCLIP("OnTextReceived(%s) callback\n",
- whichClipboard == nsClipboard::kSelectionClipboard ? "primary"
- : "clipboard");
+ MOZ_CLIPBOARD_LOG("OnTextReceived(%s) callback\n",
+ whichClipboard == nsClipboard::kSelectionClipboard
+ ? "primary"
+ : "clipboard");
static_cast<Request*>(data)->Complete(text);
}
void AsyncGtkClipboardRequest::Request::Complete(const void* aData) {
- LOGCLIP("Request::Complete(), aData = %p, timedOut = %d\n", aData, mTimedOut);
+ MOZ_CLIPBOARD_LOG("Request::Complete(), aData = %p, timedOut = %d\n", aData,
+ mTimedOut);
if (mTimedOut) {
delete this;
@@ -75,13 +78,14 @@ void AsyncGtkClipboardRequest::Request::Complete(const void* aData) {
// Negative size means no data or data error.
if (dataLength <= 0) {
- LOGCLIP(" zero dataLength, quit.\n");
+ MOZ_CLIPBOARD_LOG(" zero dataLength, quit.\n");
return;
}
switch (mDataType) {
case ClipboardDataType::Targets: {
- LOGCLIP(" getting %d bytes of clipboard targets.\n", dataLength);
+ MOZ_CLIPBOARD_LOG(" getting %d bytes of clipboard targets.\n",
+ dataLength);
gint n_targets = 0;
GdkAtom* targets = nullptr;
if (!gtk_selection_data_get_targets((GtkSelectionData*)aData, &targets,
@@ -95,16 +99,18 @@ void AsyncGtkClipboardRequest::Request::Complete(const void* aData) {
break;
}
case ClipboardDataType::Text: {
- LOGCLIP(" getting %d bytes of text.\n", dataLength);
+ MOZ_CLIPBOARD_LOG(" getting %d bytes of text.\n", dataLength);
mData->SetText(Span(static_cast<const char*>(aData), dataLength));
- LOGCLIP(" done, mClipboardData = %p\n", mData->AsSpan().data());
+ MOZ_CLIPBOARD_LOG(" done, mClipboardData = %p\n",
+ mData->AsSpan().data());
break;
}
case ClipboardDataType::Data: {
- LOGCLIP(" getting %d bytes of data.\n", dataLength);
+ MOZ_CLIPBOARD_LOG(" getting %d bytes of data.\n", dataLength);
mData->SetData(Span(gtk_selection_data_get_data((GtkSelectionData*)aData),
dataLength));
- LOGCLIP(" done, mClipboardData = %p\n", mData->AsSpan().data());
+ MOZ_CLIPBOARD_LOG(" done, mClipboardData = %p\n",
+ mData->AsSpan().data());
break;
}
}
diff --git a/widget/gtk/GfxInfo.cpp b/widget/gtk/GfxInfo.cpp
index 457b2c72ce..9c4faa26bb 100644
--- a/widget/gtk/GfxInfo.cpp
+++ b/widget/gtk/GfxInfo.cpp
@@ -1042,30 +1042,14 @@ const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() {
////////////////////////////////////
// FEATURE_DMABUF_SURFACE_EXPORT
- // Disabled due to:
+ // Disabled on all Mesa drivers due to various issue, among them:
// https://gitlab.freedesktop.org/mesa/mesa/-/issues/6666
// https://gitlab.freedesktop.org/mesa/mesa/-/issues/6796
- APPEND_TO_DRIVER_BLOCKLIST_EXT(
- OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
- WindowProtocol::All, DriverVendor::MesaAll, DeviceFamily::AtiAll,
- nsIGfxInfo::FEATURE_DMABUF_SURFACE_EXPORT,
- nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
- V(0, 0, 0, 0), "FEATURE_FAILURE_BROKEN_DRIVER", "");
-
- // Disabled due to:
// https://gitlab.freedesktop.org/mesa/mesa/-/issues/6688
- APPEND_TO_DRIVER_BLOCKLIST_EXT(
- OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
- WindowProtocol::All, DriverVendor::MesaAll, DeviceFamily::IntelAll,
- nsIGfxInfo::FEATURE_DMABUF_SURFACE_EXPORT,
- nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
- V(0, 0, 0, 0), "FEATURE_FAILURE_BROKEN_DRIVER", "");
-
- // Disabled due to:
// https://gitlab.freedesktop.org/mesa/mesa/-/issues/6988
APPEND_TO_DRIVER_BLOCKLIST_EXT(
OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
- WindowProtocol::All, DriverVendor::MesaAll, DeviceFamily::QualcommAll,
+ WindowProtocol::All, DriverVendor::MesaAll, DeviceFamily::All,
nsIGfxInfo::FEATURE_DMABUF_SURFACE_EXPORT,
nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
V(0, 0, 0, 0), "FEATURE_FAILURE_BROKEN_DRIVER", "");
diff --git a/widget/gtk/GtkCompositorWidget.cpp b/widget/gtk/GtkCompositorWidget.cpp
index 073ad5248f..50eb90a0c8 100644
--- a/widget/gtk/GtkCompositorWidget.cpp
+++ b/widget/gtk/GtkCompositorWidget.cpp
@@ -141,15 +141,12 @@ bool GtkCompositorWidget::SetEGLNativeWindowSize(
}
LayoutDeviceIntRegion GtkCompositorWidget::GetTransparentRegion() {
- // We need to clear target buffer alpha values of popup windows as
- // SW-WR paints with alpha blending (see Bug 1674473).
- if (!mWidget || mWidget->IsPopup()) {
- return LayoutDeviceIntRect(LayoutDeviceIntPoint(0, 0), GetClientSize());
+ LayoutDeviceIntRegion fullRegion(
+ LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetClientSize()));
+ if (mWidget) {
+ fullRegion.SubOut(mWidget->GetOpaqueRegion());
}
-
- // Clear background of titlebar area to render titlebar
- // transparent corners correctly.
- return mWidget->GetTitlebarRect();
+ return fullRegion;
}
#ifdef MOZ_WAYLAND
diff --git a/widget/gtk/MozContainerWayland.cpp b/widget/gtk/MozContainerWayland.cpp
index 39e8a48390..3a4660f4e0 100644
--- a/widget/gtk/MozContainerWayland.cpp
+++ b/widget/gtk/MozContainerWayland.cpp
@@ -84,7 +84,8 @@ using namespace mozilla::widget;
static bool moz_container_wayland_surface_create_locked(
const MutexAutoLock& aProofOfLock, MozContainer* container);
static void moz_container_wayland_set_opaque_region_locked(
- const MutexAutoLock& aProofOfLock, MozContainer* container);
+ const MutexAutoLock& aProofOfLock, MozContainer* container,
+ const LayoutDeviceIntRegion&);
// Lock mozcontainer and get wayland surface of it. You need to pair with
// moz_container_wayland_surface_unlock() even
@@ -413,7 +414,10 @@ gboolean moz_container_wayland_map_event(GtkWidget* widget,
nsWindow* window = moz_container_get_nsWindow(MOZ_CONTAINER(widget));
moz_container_wayland_set_scale_factor_locked(lock, MOZ_CONTAINER(widget),
window->GdkCeiledScaleFactor());
- moz_container_wayland_set_opaque_region_locked(lock, MOZ_CONTAINER(widget));
+ if (container->data.wl_container.opaque_region_needs_updates) {
+ moz_container_wayland_set_opaque_region_locked(lock, container,
+ window->GetOpaqueRegion());
+ }
moz_container_clear_input_region(MOZ_CONTAINER(widget));
moz_container_wayland_invalidate(MOZ_CONTAINER(widget));
return FALSE;
@@ -456,7 +460,10 @@ void moz_container_wayland_size_allocate(GtkWidget* widget,
nsWindow* window = moz_container_get_nsWindow(container);
moz_container_wayland_set_scale_factor_locked(
lock, container, window->GdkCeiledScaleFactor());
- moz_container_wayland_set_opaque_region_locked(lock, container);
+ if (container->data.wl_container.opaque_region_needs_updates) {
+ moz_container_wayland_set_opaque_region_locked(lock, container,
+ window->GetOpaqueRegion());
+ }
moz_container_wayland_move_locked(lock, container, allocation->x,
allocation->y);
moz_container_clear_input_region(container);
@@ -465,54 +472,28 @@ void moz_container_wayland_size_allocate(GtkWidget* widget,
}
}
-static wl_region* moz_container_wayland_create_opaque_region(
- int aX, int aY, int aWidth, int aHeight, int aCornerRadius) {
- struct wl_compositor* compositor = WaylandDisplayGet()->GetCompositor();
- wl_region* region = wl_compositor_create_region(compositor);
- wl_region_add(region, aX, aY, aWidth, aHeight);
- if (aCornerRadius) {
- wl_region_subtract(region, aX, aY, aCornerRadius, aCornerRadius);
- wl_region_subtract(region, aX + aWidth - aCornerRadius, aY, aCornerRadius,
- aCornerRadius);
- wl_region_subtract(region, aX, aY + aHeight - aCornerRadius, aCornerRadius,
- aCornerRadius);
- wl_region_subtract(region, aX + aWidth - aCornerRadius,
- aY + aHeight - aCornerRadius, aCornerRadius,
- aCornerRadius);
- }
- return region;
-}
-
static void moz_container_wayland_set_opaque_region_locked(
- const MutexAutoLock& aProofOfLock, MozContainer* container) {
+ const MutexAutoLock& aProofOfLock, MozContainer* container,
+ const LayoutDeviceIntRegion& aRegion) {
MozContainerWayland* wl_container = &container->data.wl_container;
-
- if (!wl_container->opaque_region_needs_updates) {
+ MOZ_ASSERT(wl_container->opaque_region_needs_updates);
+ if (!wl_container->surface) {
return;
}
+ wl_container->opaque_region_needs_updates = false;
if (!wl_container->opaque_region_used) {
- wl_container->opaque_region_needs_updates = false;
return;
}
- GtkAllocation allocation;
- gtk_widget_get_allocation(GTK_WIDGET(container), &allocation);
-
- wl_region* region = moz_container_wayland_create_opaque_region(
- 0, 0, allocation.width, allocation.height,
- wl_container->opaque_region_corner_radius);
+ wl_region* region =
+ wl_compositor_create_region(WaylandDisplayGet()->GetCompositor());
+ for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
+ const auto& rect = iter.Get();
+ wl_region_add(region, rect.x, rect.y, rect.Width(), rect.Height());
+ }
wl_surface_set_opaque_region(wl_container->surface, region);
wl_region_destroy(region);
- wl_container->opaque_region_needs_updates = false;
-}
-
-static void moz_container_wayland_set_opaque_region(MozContainer* container) {
- MozContainerWayland* wl_container = &container->data.wl_container;
- MutexAutoLock lock(wl_container->container_lock);
- if (wl_container->surface) {
- moz_container_wayland_set_opaque_region_locked(lock, container);
- }
}
static void moz_container_wayland_surface_set_scale_locked(
@@ -757,17 +738,18 @@ gboolean moz_container_wayland_has_egl_window(MozContainer* container) {
return !!container->data.wl_container.eglwindow;
}
-void moz_container_wayland_update_opaque_region(MozContainer* container,
- int corner_radius) {
+void moz_container_wayland_update_opaque_region(MozContainer* container) {
MozContainerWayland* wl_container = &container->data.wl_container;
+ MutexAutoLock lock(wl_container->container_lock);
wl_container->opaque_region_needs_updates = true;
- wl_container->opaque_region_corner_radius = corner_radius;
// When GL compositor / WebRender is used,
// moz_container_wayland_get_egl_window() is called only once when window
// is created or resized so update opaque region now.
if (moz_container_wayland_has_egl_window(container)) {
- moz_container_wayland_set_opaque_region(container);
+ nsWindow* window = moz_container_get_nsWindow(container);
+ moz_container_wayland_set_opaque_region_locked(lock, container,
+ window->GetOpaqueRegion());
}
}
diff --git a/widget/gtk/MozContainerWayland.h b/widget/gtk/MozContainerWayland.h
index 068c674256..6a33df2642 100644
--- a/widget/gtk/MozContainerWayland.h
+++ b/widget/gtk/MozContainerWayland.h
@@ -42,7 +42,6 @@ struct MozContainerWayland {
struct wp_viewport* viewport = nullptr;
struct wp_fractional_scale_v1* fractional_scale = nullptr;
gboolean opaque_region_needs_updates = false;
- int opaque_region_corner_radius = 0;
gboolean opaque_region_used = false;
gboolean ready_to_draw = false;
gboolean commit_to_parent = false;
@@ -97,8 +96,7 @@ void moz_container_wayland_add_or_fire_initial_draw_callback(
void moz_container_wayland_clear_initial_draw_callback(MozContainer* container);
wl_surface* moz_gtk_widget_get_wl_surface(GtkWidget* aWidget);
-void moz_container_wayland_update_opaque_region(MozContainer* container,
- int corner_radius);
+void moz_container_wayland_update_opaque_region(MozContainer* container);
gboolean moz_container_wayland_can_draw(MozContainer* container);
double moz_container_wayland_get_scale(MozContainer* container);
double moz_container_wayland_get_fractional_scale(MozContainer* container);
diff --git a/widget/gtk/WidgetStyleCache.cpp b/widget/gtk/WidgetStyleCache.cpp
index 13b194a64e..b3d9bfcbbd 100644
--- a/widget/gtk/WidgetStyleCache.cpp
+++ b/widget/gtk/WidgetStyleCache.cpp
@@ -1079,11 +1079,6 @@ static GtkStyleContext* GetCssNodeStyleInternal(WidgetNodeType aNodeType) {
// TODO - create from CSS node
style = CreateSubStyleWithClass(MOZ_GTK_TREEVIEW, GTK_STYLE_CLASS_VIEW);
break;
- case MOZ_GTK_TREEVIEW_EXPANDER:
- // TODO - create from CSS node
- style =
- CreateSubStyleWithClass(MOZ_GTK_TREEVIEW, GTK_STYLE_CLASS_EXPANDER);
- break;
case MOZ_GTK_SPLITTER_SEPARATOR_HORIZONTAL:
style = CreateChildCSSNode("separator", MOZ_GTK_SPLITTER_HORIZONTAL);
break;
@@ -1218,10 +1213,6 @@ static GtkStyleContext* GetWidgetStyleInternal(WidgetNodeType aNodeType) {
case MOZ_GTK_TREEVIEW_VIEW:
style = CreateSubStyleWithClass(MOZ_GTK_TREEVIEW, GTK_STYLE_CLASS_VIEW);
break;
- case MOZ_GTK_TREEVIEW_EXPANDER:
- style =
- CreateSubStyleWithClass(MOZ_GTK_TREEVIEW, GTK_STYLE_CLASS_EXPANDER);
- break;
case MOZ_GTK_SPLITTER_SEPARATOR_HORIZONTAL:
style = CreateSubStyleWithClass(MOZ_GTK_SPLITTER_HORIZONTAL,
GTK_STYLE_CLASS_PANE_SEPARATOR);
diff --git a/widget/gtk/WindowSurfaceProvider.cpp b/widget/gtk/WindowSurfaceProvider.cpp
index c8b2c5a7d6..204718bd49 100644
--- a/widget/gtk/WindowSurfaceProvider.cpp
+++ b/widget/gtk/WindowSurfaceProvider.cpp
@@ -12,6 +12,7 @@
#include "mozilla/layers/LayersTypes.h"
#include "nsWindow.h"
#include "mozilla/ScopeExit.h"
+#include "WidgetUtilsGtk.h"
#ifdef MOZ_WAYLAND
# include "mozilla/StaticPrefs_widget.h"
diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp
index 122b43d688..c67716b90e 100644
--- a/widget/gtk/gtk3drawing.cpp
+++ b/widget/gtk/gtk3drawing.cpp
@@ -260,7 +260,8 @@ gint moz_gtk_splitter_get_metrics(gint orientation, gint* size) {
}
static void CalculateToolbarButtonMetrics(WidgetNodeType aAppearance,
- ToolbarButtonGTKMetrics* aMetrics) {
+ ToolbarButtonGTKMetrics* aMetrics,
+ gint* aMaxInlineMargin) {
gint iconWidth, iconHeight;
if (!gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &iconWidth, &iconHeight)) {
NS_WARNING("Failed to get Gtk+ icon size for titlebar button!");
@@ -292,6 +293,11 @@ static void CalculateToolbarButtonMetrics(WidgetNodeType aAppearance,
aMetrics->iconXPosition = (width - iconWidth) / 2;
aMetrics->iconYPosition = (height - iconHeight) / 2;
aMetrics->minSizeWithBorder = {width, height};
+
+ GtkBorder margin = {0};
+ gtk_style_context_get_margin(style, gtk_style_context_get_state(style),
+ &margin);
+ *aMaxInlineMargin = std::max(*aMaxInlineMargin, margin.left + margin.right);
}
size_t GetGtkHeaderBarButtonLayout(Span<ButtonLayout> aButtonLayout,
@@ -353,8 +359,7 @@ static void EnsureToolbarMetrics() {
if (sToolbarMetrics.initialized) {
return;
}
- // Make sure we have clean cache after theme reset, etc.
- memset(&sToolbarMetrics, 0, sizeof(sToolbarMetrics));
+ sToolbarMetrics = {};
// Calculate titlebar button visibility and positions.
ButtonLayout buttonLayout[TOOLBAR_BUTTONS];
@@ -364,9 +369,15 @@ static void EnsureToolbarMetrics() {
for (const auto& layout : Span(buttonLayout, activeButtonNums)) {
int buttonIndex = layout.mType - MOZ_GTK_HEADER_BAR_BUTTON_CLOSE;
ToolbarButtonGTKMetrics* metrics = &sToolbarMetrics.button[buttonIndex];
- CalculateToolbarButtonMetrics(layout.mType, metrics);
+ CalculateToolbarButtonMetrics(layout.mType, metrics,
+ &sToolbarMetrics.inlineSpacing);
}
+ // Account for the spacing property in the header bar.
+ // Default to 6 pixels (gtk/gtkheaderbar.c)
+ gint spacing = 6;
+ g_object_get(GetWidget(MOZ_GTK_HEADER_BAR), "spacing", &spacing, nullptr);
+ sToolbarMetrics.inlineSpacing += spacing;
sToolbarMetrics.initialized = true;
}
@@ -380,6 +391,11 @@ const ToolbarButtonGTKMetrics* GetToolbarButtonMetrics(
return sToolbarMetrics.button + buttonIndex;
}
+gint moz_gtk_get_titlebar_button_spacing() {
+ EnsureToolbarMetrics();
+ return sToolbarMetrics.inlineSpacing;
+}
+
static gint moz_gtk_window_decoration_paint(cairo_t* cr,
const GdkRectangle* rect,
GtkWidgetState* state,
@@ -937,54 +953,7 @@ static gint moz_gtk_treeview_paint(cairo_t* cr, GdkRectangle* rect,
return MOZ_GTK_SUCCESS;
}
-static gint moz_gtk_tree_header_cell_paint(cairo_t* cr,
- const GdkRectangle* aRect,
- GtkWidgetState* state,
- gboolean isSorted,
- GtkTextDirection direction) {
- moz_gtk_button_paint(cr, aRect, state, GTK_RELIEF_NORMAL,
- GetWidget(MOZ_GTK_TREE_HEADER_CELL), direction);
- return MOZ_GTK_SUCCESS;
-}
-
-/* See gtk_expander_paint() for reference.
- */
-static gint moz_gtk_treeview_expander_paint(cairo_t* cr, GdkRectangle* rect,
- GtkWidgetState* state,
- GtkExpanderStyle expander_state,
- GtkTextDirection direction) {
- /* Because the frame we get is of the entire treeview, we can't get the
- * precise event state of one expander, thus rendering hover and active
- * feedback useless. */
- GtkStateFlags state_flags =
- state->disabled ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
-
- if (state->inHover)
- state_flags =
- static_cast<GtkStateFlags>(state_flags | GTK_STATE_FLAG_PRELIGHT);
- if (state->selected)
- state_flags =
- static_cast<GtkStateFlags>(state_flags | GTK_STATE_FLAG_SELECTED);
-
- /* GTK_STATE_FLAG_ACTIVE controls expanded/colapsed state rendering
- * in gtk_render_expander()
- */
- if (expander_state == GTK_EXPANDER_EXPANDED)
- state_flags =
- static_cast<GtkStateFlags>(state_flags | checkbox_check_state);
- else
- state_flags =
- static_cast<GtkStateFlags>(state_flags & ~(checkbox_check_state));
-
- GtkStyleContext* style = GetStyleContext(
- MOZ_GTK_TREEVIEW_EXPANDER, state->image_scale, direction, state_flags);
- gtk_render_expander(style, cr, rect->x, rect->y, rect->width, rect->height);
-
- return MOZ_GTK_SUCCESS;
-}
-
-/* See gtk_separator_draw() for reference.
- */
+/* See gtk_separator_draw() for reference. */
static gint moz_gtk_combo_box_paint(cairo_t* cr, const GdkRectangle* aRect,
GtkWidgetState* state,
GtkTextDirection direction) {
@@ -1572,18 +1541,6 @@ gint moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top,
moz_gtk_add_style_border(style, left, top, right, bottom);
return MOZ_GTK_SUCCESS;
}
- case MOZ_GTK_TREE_HEADER_CELL: {
- /* A Tree Header in GTK is just a different styled button
- * It must be placed in a TreeView for getting the correct style
- * assigned.
- * That is why the following code is the same as for MOZ_GTK_BUTTON.
- * */
- *left = *top = *right = *bottom = gtk_container_get_border_width(
- GTK_CONTAINER(GetWidget(MOZ_GTK_TREE_HEADER_CELL)));
- style = GetStyleContext(MOZ_GTK_TREE_HEADER_CELL);
- moz_gtk_add_border_padding(style, left, top, right, bottom);
- return MOZ_GTK_SUCCESS;
- }
case MOZ_GTK_DROPDOWN: {
/* We need to account for the arrow on the dropdown, so text
* doesn't come too close to the arrow, or in some cases spill
@@ -1669,7 +1626,6 @@ gint moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top,
case MOZ_GTK_PROGRESS_CHUNK:
case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE:
case MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE:
- case MOZ_GTK_TREEVIEW_EXPANDER:
case MOZ_GTK_HEADER_BAR:
case MOZ_GTK_HEADER_BAR_MAXIMIZED:
case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
@@ -1777,18 +1733,6 @@ void moz_gtk_get_arrow_size(WidgetNodeType widgetType, gint* width,
}
}
-gint moz_gtk_get_expander_size(gint* size) {
- GtkStyleContext* style = GetStyleContext(MOZ_GTK_EXPANDER);
- gtk_style_context_get_style(style, "expander-size", size, NULL);
- return MOZ_GTK_SUCCESS;
-}
-
-gint moz_gtk_get_treeview_expander_size(gint* size) {
- GtkStyleContext* style = GetStyleContext(MOZ_GTK_TREEVIEW);
- gtk_style_context_get_style(style, "expander-size", size, NULL);
- return MOZ_GTK_SUCCESS;
-}
-
void moz_gtk_get_entry_min_height(gint* min_content_height,
gint* border_padding_height) {
GtkStyleContext* style = GetStyleContext(MOZ_GTK_ENTRY);
@@ -2057,11 +2001,6 @@ gint moz_gtk_widget_paint(WidgetNodeType widget, cairo_t* cr,
}
case MOZ_GTK_TREEVIEW:
return moz_gtk_treeview_paint(cr, rect, state, direction);
- case MOZ_GTK_TREE_HEADER_CELL:
- return moz_gtk_tree_header_cell_paint(cr, rect, state, flags, direction);
- case MOZ_GTK_TREEVIEW_EXPANDER:
- return moz_gtk_treeview_expander_paint(
- cr, rect, state, (GtkExpanderStyle)flags, direction);
case MOZ_GTK_ENTRY:
case MOZ_GTK_DROPDOWN_ENTRY: {
GtkStyleContext* style =
diff --git a/widget/gtk/gtkdrawing.h b/widget/gtk/gtkdrawing.h
index 4ca226d9c7..227a33d9a9 100644
--- a/widget/gtk/gtkdrawing.h
+++ b/widget/gtk/gtkdrawing.h
@@ -69,38 +69,39 @@ struct MozGtkSize {
}
};
-typedef struct {
+struct ToggleGTKMetrics {
bool initialized;
MozGtkSize minSizeWithBorder;
GtkBorder borderAndPadding;
-} ToggleGTKMetrics;
+};
-typedef struct {
- MozGtkSize minSizeWithBorder;
- gint iconXPosition;
- gint iconYPosition;
-} ToolbarButtonGTKMetrics;
+struct ToolbarButtonGTKMetrics {
+ MozGtkSize minSizeWithBorder{};
+ gint iconXPosition = 0;
+ gint iconYPosition = 0;
+};
#define TOOLBAR_BUTTONS 3
-typedef struct {
- bool initialized;
+struct ToolbarGTKMetrics {
+ bool initialized = false;
+ gint inlineSpacing = 0;
ToolbarButtonGTKMetrics button[TOOLBAR_BUTTONS];
-} ToolbarGTKMetrics;
+};
-typedef struct {
+struct CSDWindowDecorationSize {
bool initialized;
GtkBorder decorationSize;
-} CSDWindowDecorationSize;
+};
/** flags for tab state **/
-typedef enum {
+enum GtkTabFlags {
/* first eight bits are used to pass a margin */
MOZ_GTK_TAB_MARGIN_MASK = 0xFF,
/* the first tab in the group */
MOZ_GTK_TAB_FIRST = 1 << 9,
/* the selected tab */
MOZ_GTK_TAB_SELECTED = 1 << 10
-} GtkTabFlags;
+};
/*** result/error codes ***/
#define MOZ_GTK_SUCCESS 0
@@ -211,8 +212,6 @@ enum WidgetNodeType : int {
MOZ_GTK_TREEVIEW_VIEW,
/* Paints treeheader cells */
MOZ_GTK_TREE_HEADER_CELL,
- /* Paints an expander for a GtkTreeView */
- MOZ_GTK_TREEVIEW_EXPANDER,
/* Paints the background of menus, context menus. */
MOZ_GTK_MENUPOPUP,
/* Menubar for -moz-headerbar colors */
@@ -458,22 +457,6 @@ void moz_gtk_get_entry_min_height(gint* min_content_height,
gint moz_gtk_get_toolbar_separator_width(gint* size);
/**
- * Get the size of a regular GTK expander that shows/hides content
- * size: [OUT] the size of the GTK expander, size = width = height.
- *
- * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
- */
-gint moz_gtk_get_expander_size(gint* size);
-
-/**
- * Get the size of a treeview's expander (we call them twisties)
- * size: [OUT] the size of the GTK expander, size = width = height.
- *
- * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
- */
-gint moz_gtk_get_treeview_expander_size(gint* size);
-
-/**
* Get the desired size of a splitter
* orientation: [IN] GTK_ORIENTATION_HORIZONTAL or GTK_ORIENTATION_VERTICAL
* size: [OUT] width or height of the splitter handle
@@ -493,6 +476,8 @@ gint moz_gtk_get_tab_thickness(WidgetNodeType aNodeType);
const ToolbarButtonGTKMetrics* GetToolbarButtonMetrics(
WidgetNodeType aAppearance);
+gint moz_gtk_get_titlebar_button_spacing();
+
/**
* Get toolbar button layout.
* aButtonLayout: [OUT] An array which will be filled by ButtonLayout
diff --git a/widget/gtk/nsAppShell.cpp b/widget/gtk/nsAppShell.cpp
index d26b43737d..652801fe69 100644
--- a/widget/gtk/nsAppShell.cpp
+++ b/widget/gtk/nsAppShell.cpp
@@ -53,7 +53,6 @@ LazyLogModule gWidgetWaylandLog("WidgetWayland");
LazyLogModule gWidgetPopupLog("WidgetPopup");
LazyLogModule gWidgetVsync("WidgetVsync");
LazyLogModule gDmabufLog("Dmabuf");
-LazyLogModule gClipboardLog("WidgetClipboard");
static GPollFunc sPollFunc;
diff --git a/widget/gtk/nsClipboard.cpp b/widget/gtk/nsClipboard.cpp
index 571b43f1cc..206c8ddeb3 100644
--- a/widget/gtk/nsClipboard.cpp
+++ b/widget/gtk/nsClipboard.cpp
@@ -88,7 +88,8 @@ static void SetTransferableData(nsITransferable* aTransferable,
const nsACString& aFlavor,
const char* aClipboardData,
uint32_t aClipboardDataLength) {
- LOGCLIP("SetTransferableData MIME %s\n", PromiseFlatCString(aFlavor).get());
+ MOZ_CLIPBOARD_LOG("SetTransferableData MIME %s\n",
+ PromiseFlatCString(aFlavor).get());
nsCOMPtr<nsISupports> wrapper;
nsPrimitiveHelpers::CreatePrimitiveForData(
aFlavor, aClipboardData, aClipboardDataLength, getter_AddRefs(wrapper));
@@ -161,29 +162,30 @@ int GetGeckoClipboardType(GtkClipboard* aGtkClipboard) {
void nsRetrievalContext::ClearCachedTargetsClipboard(GtkClipboard* aClipboard,
GdkEvent* aEvent,
gpointer data) {
- LOGCLIP("nsRetrievalContext::ClearCachedTargetsClipboard()");
+ MOZ_CLIPBOARD_LOG("nsRetrievalContext::ClearCachedTargetsClipboard()");
sClipboardTargets.Clear();
}
void nsRetrievalContext::ClearCachedTargetsPrimary(GtkClipboard* aClipboard,
GdkEvent* aEvent,
gpointer data) {
- LOGCLIP("nsRetrievalContext::ClearCachedTargetsPrimary()");
+ MOZ_CLIPBOARD_LOG("nsRetrievalContext::ClearCachedTargetsPrimary()");
sPrimaryTargets.Clear();
}
ClipboardTargets nsRetrievalContext::GetTargets(int32_t aWhichClipboard) {
- LOGCLIP("nsRetrievalContext::GetTargets(%s)\n",
- aWhichClipboard == nsClipboard::kSelectionClipboard ? "primary"
- : "clipboard");
+ MOZ_CLIPBOARD_LOG("nsRetrievalContext::GetTargets(%s)\n",
+ aWhichClipboard == nsClipboard::kSelectionClipboard
+ ? "primary"
+ : "clipboard");
ClipboardTargets& storedTargets =
(aWhichClipboard == nsClipboard::kSelectionClipboard) ? sPrimaryTargets
: sClipboardTargets;
if (!storedTargets) {
- LOGCLIP(" getting targets from system");
+ MOZ_CLIPBOARD_LOG(" getting targets from system");
storedTargets.Set(GetTargetsImpl(aWhichClipboard));
} else {
- LOGCLIP(" using cached targets");
+ MOZ_CLIPBOARD_LOG(" using cached targets");
}
return storedTargets.Clone();
}
@@ -249,7 +251,7 @@ nsClipboard::Observe(nsISupports* aSubject, const char* aTopic,
// runnable.
return SchedulerGroup::Dispatch(
NS_NewRunnableFunction("gtk_clipboard_store()", []() {
- LOGCLIP("nsClipboard storing clipboard content\n");
+ MOZ_CLIPBOARD_LOG("nsClipboard storing clipboard content\n");
gtk_clipboard_store(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
}));
}
@@ -269,8 +271,9 @@ nsClipboard::SetNativeClipboardData(nsITransferable* aTransferable,
return NS_OK;
}
- LOGCLIP("nsClipboard::SetNativeClipboardData (%s)\n",
- aWhichClipboard == kSelectionClipboard ? "primary" : "clipboard");
+ MOZ_CLIPBOARD_LOG(
+ "nsClipboard::SetNativeClipboardData (%s)\n",
+ aWhichClipboard == kSelectionClipboard ? "primary" : "clipboard");
// List of suported targets
GtkTargetList* list = gtk_target_list_new(nullptr, 0);
@@ -279,7 +282,7 @@ nsClipboard::SetNativeClipboardData(nsITransferable* aTransferable,
nsTArray<nsCString> flavors;
nsresult rv = aTransferable->FlavorsTransferableCanExport(flavors);
if (NS_FAILED(rv)) {
- LOGCLIP(" FlavorsTransferableCanExport failed!\n");
+ MOZ_CLIPBOARD_LOG(" FlavorsTransferableCanExport failed!\n");
// Fall through. |gtkTargets| will be null below.
}
@@ -287,11 +290,11 @@ nsClipboard::SetNativeClipboardData(nsITransferable* aTransferable,
bool imagesAdded = false;
for (uint32_t i = 0; i < flavors.Length(); i++) {
nsCString& flavorStr = flavors[i];
- LOGCLIP(" processing target %s\n", flavorStr.get());
+ MOZ_CLIPBOARD_LOG(" processing target %s\n", flavorStr.get());
// Special case text/plain since we can handle all of the string types.
if (flavorStr.EqualsLiteral(kTextMime)) {
- LOGCLIP(" adding TEXT targets\n");
+ MOZ_CLIPBOARD_LOG(" adding TEXT targets\n");
gtk_target_list_add_text_targets(list, 0);
continue;
}
@@ -300,7 +303,7 @@ nsClipboard::SetNativeClipboardData(nsITransferable* aTransferable,
// Don't bother adding image targets twice
if (!imagesAdded) {
// accept any writable image type
- LOGCLIP(" adding IMAGE targets\n");
+ MOZ_CLIPBOARD_LOG(" adding IMAGE targets\n");
gtk_target_list_add_image_targets(list, 0, TRUE);
imagesAdded = true;
}
@@ -308,14 +311,14 @@ nsClipboard::SetNativeClipboardData(nsITransferable* aTransferable,
}
if (flavorStr.EqualsLiteral(kFileMime)) {
- LOGCLIP(" adding text/uri-list target\n");
+ MOZ_CLIPBOARD_LOG(" adding text/uri-list target\n");
GdkAtom atom = gdk_atom_intern(kURIListMime, FALSE);
gtk_target_list_add(list, atom, 0, 0);
continue;
}
// Add this to our list of valid targets
- LOGCLIP(" adding OTHER target %s\n", flavorStr.get());
+ MOZ_CLIPBOARD_LOG(" adding OTHER target %s\n", flavorStr.get());
GdkAtom atom = gdk_atom_intern(flavorStr.get(), FALSE);
gtk_target_list_add(list, atom, 0, 0);
}
@@ -328,7 +331,7 @@ nsClipboard::SetNativeClipboardData(nsITransferable* aTransferable,
GtkTargetEntry* gtkTargets =
gtk_target_table_new_from_list(list, &numTargets);
if (!gtkTargets || numTargets == 0) {
- LOGCLIP(
+ MOZ_CLIPBOARD_LOG(
" gtk_target_table_new_from_list() failed or empty list of "
"targets!\n");
// Clear references to the any old data and let GTK know that it is no
@@ -356,7 +359,7 @@ nsClipboard::SetNativeClipboardData(nsITransferable* aTransferable,
rv = NS_OK;
} else {
- LOGCLIP(" gtk_clipboard_set_with_data() failed!\n");
+ MOZ_CLIPBOARD_LOG(" gtk_clipboard_set_with_data() failed!\n");
EmptyNativeClipboardData(aWhichClipboard);
rv = NS_ERROR_FAILURE;
}
@@ -390,11 +393,11 @@ static bool IsMIMEAtFlavourList(const nsTArray<nsCString>& aFlavourList,
// So if clipboard contains images only remove text MIME offer.
bool nsClipboard::FilterImportedFlavors(int32_t aWhichClipboard,
nsTArray<nsCString>& aFlavors) {
- LOGCLIP("nsClipboard::FilterImportedFlavors");
+ MOZ_CLIPBOARD_LOG("nsClipboard::FilterImportedFlavors");
auto targets = mContext->GetTargets(aWhichClipboard);
if (!targets) {
- LOGCLIP(" X11: no targes at clipboard (null), quit.\n");
+ MOZ_CLIPBOARD_LOG(" X11: no targes at clipboard (null), quit.\n");
return true;
}
@@ -419,7 +422,8 @@ bool nsClipboard::FilterImportedFlavors(int32_t aWhichClipboard,
}
// We have some other MIME type on clipboard which can be hopefully
// converted to text without any problem.
- LOGCLIP(" X11: text types in clipboard, no need to filter them.\n");
+ MOZ_CLIPBOARD_LOG(
+ " X11: text types in clipboard, no need to filter them.\n");
return true;
}
@@ -436,9 +440,9 @@ bool nsClipboard::FilterImportedFlavors(int32_t aWhichClipboard,
}
aFlavors.SwapElements(clipboardFlavors);
#ifdef MOZ_LOGGING
- LOGCLIP(" X11: Flavors which match clipboard content:\n");
+ MOZ_CLIPBOARD_LOG(" X11: Flavors which match clipboard content:\n");
for (uint32_t i = 0; i < aFlavors.Length(); i++) {
- LOGCLIP(" %s\n", aFlavors[i].get());
+ MOZ_CLIPBOARD_LOG(" %s\n", aFlavors[i].get());
}
#endif
return true;
@@ -452,13 +456,13 @@ static nsresult GetTransferableFlavors(nsITransferable* aTransferable,
// Get a list of flavors this transferable can import
nsresult rv = aTransferable->FlavorsTransferableCanImport(aFlavors);
if (NS_FAILED(rv)) {
- LOGCLIP(" FlavorsTransferableCanImport falied!\n");
+ MOZ_CLIPBOARD_LOG(" FlavorsTransferableCanImport falied!\n");
return rv;
}
#ifdef MOZ_LOGGING
- LOGCLIP(" Flavors which can be imported:");
+ MOZ_CLIPBOARD_LOG(" Flavors which can be imported:");
for (const auto& flavor : aFlavors) {
- LOGCLIP(" %s", flavor.get());
+ MOZ_CLIPBOARD_LOG(" %s", flavor.get());
}
#endif
return NS_OK;
@@ -476,7 +480,7 @@ static bool TransferableSetFile(nsITransferable* aTransferable,
rv = fileURL->GetFile(getter_AddRefs(file));
if (NS_SUCCEEDED(rv)) {
aTransferable->SetTransferData(kFileMime, file);
- LOGCLIP(" successfully set file to clipboard\n");
+ MOZ_CLIPBOARD_LOG(" successfully set file to clipboard\n");
return true;
}
}
@@ -492,17 +496,20 @@ static bool TransferableSetHTML(nsITransferable* aTransferable,
nsAutoCString charset;
if (!GetHTMLCharset(aData, charset)) {
// Fall back to utf-8 in case html/data is missing kHTMLMarkupPrefix.
- LOGCLIP("Failed to get html/text encoding, fall back to utf-8.\n");
+ MOZ_CLIPBOARD_LOG(
+ "Failed to get html/text encoding, fall back to utf-8.\n");
charset.AssignLiteral("utf-8");
}
- LOGCLIP("TransferableSetHTML: HTML detected charset %s", charset.get());
+ MOZ_CLIPBOARD_LOG("TransferableSetHTML: HTML detected charset %s",
+ charset.get());
// app which use "text/html" to copy&paste
// get the decoder
auto encoding = Encoding::ForLabelNoReplacement(charset);
if (!encoding) {
- LOGCLIP("TransferableSetHTML: get unicode decoder error (charset: %s)",
- charset.get());
+ MOZ_CLIPBOARD_LOG(
+ "TransferableSetHTML: get unicode decoder error (charset: %s)",
+ charset.get());
return false;
}
@@ -523,16 +530,15 @@ static bool TransferableSetHTML(nsITransferable* aTransferable,
nsAutoString unicodeData;
auto [rv, enc] = encoding->Decode(AsBytes(aData), unicodeData);
#if MOZ_LOGGING
- if (enc != UTF_8_ENCODING &&
- MOZ_LOG_TEST(gClipboardLog, mozilla::LogLevel::Debug)) {
+ if (enc != UTF_8_ENCODING && MOZ_CLIPBOARD_LOG_ENABLED()) {
nsCString decoderName;
enc->Name(decoderName);
- LOGCLIP("TransferableSetHTML: expected UTF-8 decoder but got %s",
- decoderName.get());
+ MOZ_CLIPBOARD_LOG("TransferableSetHTML: expected UTF-8 decoder but got %s",
+ decoderName.get());
}
#endif
if (NS_FAILED(rv)) {
- LOGCLIP("TransferableSetHTML: failed to decode HTML");
+ MOZ_CLIPBOARD_LOG("TransferableSetHTML: failed to decode HTML");
return false;
}
SetTransferableData(aTransferable, mimeType,
@@ -548,8 +554,9 @@ nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable,
MOZ_DIAGNOSTIC_ASSERT(
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
- LOGCLIP("nsClipboard::GetNativeClipboardData (%s)\n",
- aWhichClipboard == kSelectionClipboard ? "primary" : "clipboard");
+ MOZ_CLIPBOARD_LOG(
+ "nsClipboard::GetNativeClipboardData (%s)\n",
+ aWhichClipboard == kSelectionClipboard ? "primary" : "clipboard");
// TODO: Ensure we don't re-enter here.
if (!mContext) {
@@ -564,7 +571,7 @@ nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable,
// see Bug 1611407
if (widget::GdkIsX11Display() &&
!FilterImportedFlavors(aWhichClipboard, flavors)) {
- LOGCLIP(" Missing suitable clipboard data, quit.");
+ MOZ_CLIPBOARD_LOG(" Missing suitable clipboard data, quit.");
return NS_OK;
}
@@ -580,12 +587,13 @@ nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable,
flavorStr.Assign(kJPEGImageMime);
}
- LOGCLIP(" Getting image %s MIME clipboard data\n", flavorStr.get());
+ MOZ_CLIPBOARD_LOG(" Getting image %s MIME clipboard data\n",
+ flavorStr.get());
auto clipboardData =
mContext->GetClipboardData(flavorStr.get(), aWhichClipboard);
if (!clipboardData) {
- LOGCLIP(" %s type is missing\n", flavorStr.get());
+ MOZ_CLIPBOARD_LOG(" %s type is missing\n", flavorStr.get());
continue;
}
@@ -593,18 +601,19 @@ nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable,
NS_NewByteInputStream(getter_AddRefs(byteStream), clipboardData.AsSpan(),
NS_ASSIGNMENT_COPY);
aTransferable->SetTransferData(flavorStr.get(), byteStream);
- LOGCLIP(" got %s MIME data\n", flavorStr.get());
+ MOZ_CLIPBOARD_LOG(" got %s MIME data\n", flavorStr.get());
return NS_OK;
}
// Special case text/plain since we can convert any
// string into text/plain
if (flavorStr.EqualsLiteral(kTextMime)) {
- LOGCLIP(" Getting text %s MIME clipboard data\n", flavorStr.get());
+ MOZ_CLIPBOARD_LOG(" Getting text %s MIME clipboard data\n",
+ flavorStr.get());
auto clipboardData = mContext->GetClipboardText(aWhichClipboard);
if (!clipboardData) {
- LOGCLIP(" failed to get text data\n");
+ MOZ_CLIPBOARD_LOG(" failed to get text data\n");
// If the type was text/plain and we couldn't get
// text off the clipboard, run the next loop
// iteration.
@@ -617,17 +626,18 @@ nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable,
(const char*)ucs2string.BeginReading(),
ucs2string.Length() * 2);
- LOGCLIP(" got text data, length %zd\n", ucs2string.Length());
+ MOZ_CLIPBOARD_LOG(" got text data, length %zd\n", ucs2string.Length());
return NS_OK;
}
if (flavorStr.EqualsLiteral(kFileMime)) {
- LOGCLIP(" Getting %s file clipboard data\n", flavorStr.get());
+ MOZ_CLIPBOARD_LOG(" Getting %s file clipboard data\n",
+ flavorStr.get());
auto clipboardData =
mContext->GetClipboardData(kURIListMime, aWhichClipboard);
if (!clipboardData) {
- LOGCLIP(" text/uri-list type is missing\n");
+ MOZ_CLIPBOARD_LOG(" text/uri-list type is missing\n");
continue;
}
@@ -638,19 +648,19 @@ nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable,
return NS_OK;
}
- LOGCLIP(" Getting %s MIME clipboard data\n", flavorStr.get());
+ MOZ_CLIPBOARD_LOG(" Getting %s MIME clipboard data\n", flavorStr.get());
auto clipboardData =
mContext->GetClipboardData(flavorStr.get(), aWhichClipboard);
#ifdef MOZ_LOGGING
if (!clipboardData) {
- LOGCLIP(" %s type is missing\n", flavorStr.get());
+ MOZ_CLIPBOARD_LOG(" %s type is missing\n", flavorStr.get());
}
#endif
if (clipboardData) {
- LOGCLIP(" got %s mime type data.\n", flavorStr.get());
+ MOZ_CLIPBOARD_LOG(" got %s mime type data.\n", flavorStr.get());
// Special case text/html since we can convert into UCS2
if (flavorStr.EqualsLiteral(kHTMLMime)) {
@@ -666,7 +676,7 @@ nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable,
}
}
- LOGCLIP(" failed to get clipboard content.\n");
+ MOZ_CLIPBOARD_LOG(" failed to get clipboard content.\n");
return NS_OK;
}
@@ -692,11 +702,11 @@ struct DataCallbackHandler {
mMimeType(aMimeType),
mDataType(aDataType) {
MOZ_COUNT_CTOR(DataCallbackHandler);
- LOGCLIP("DataCallbackHandler created [%p] MIME %s type %d", this,
- mMimeType.get(), mDataType);
+ MOZ_CLIPBOARD_LOG("DataCallbackHandler created [%p] MIME %s type %d", this,
+ mMimeType.get(), mDataType);
}
~DataCallbackHandler() {
- LOGCLIP("DataCallbackHandler deleted [%p]", this);
+ MOZ_CLIPBOARD_LOG("DataCallbackHandler deleted [%p]", this);
MOZ_COUNT_DTOR(DataCallbackHandler);
}
};
@@ -704,20 +714,21 @@ struct DataCallbackHandler {
static void AsyncGetTextImpl(nsITransferable* aTransferable,
int32_t aWhichClipboard,
nsBaseClipboard::GetDataCallback&& aCallback) {
- LOGCLIP("AsyncGetText() type '%s'",
- aWhichClipboard == nsClipboard::kSelectionClipboard ? "primary"
- : "clipboard");
+ MOZ_CLIPBOARD_LOG("AsyncGetText() type '%s'",
+ aWhichClipboard == nsClipboard::kSelectionClipboard
+ ? "primary"
+ : "clipboard");
gtk_clipboard_request_text(
gtk_clipboard_get(GetSelectionAtom(aWhichClipboard)),
[](GtkClipboard* aClipboard, const gchar* aText, gpointer aData) -> void {
UniquePtr<DataCallbackHandler> ref(
static_cast<DataCallbackHandler*>(aData));
- LOGCLIP("AsyncGetText async handler of [%p]", aData);
+ MOZ_CLIPBOARD_LOG("AsyncGetText async handler of [%p]", aData);
size_t dataLength = aText ? strlen(aText) : 0;
if (dataLength <= 0) {
- LOGCLIP(" quit, text is not available");
+ MOZ_CLIPBOARD_LOG(" quit, text is not available");
ref->mDataCallback(NS_OK);
return;
}
@@ -728,7 +739,7 @@ static void AsyncGetTextImpl(nsITransferable* aTransferable,
SetTransferableData(ref->mTransferable, flavor,
(const char*)utf16string.BeginReading(),
utf16string.Length() * 2);
- LOGCLIP(" text is set, length = %d", (int)dataLength);
+ MOZ_CLIPBOARD_LOG(" text is set, length = %d", (int)dataLength);
ref->mDataCallback(NS_OK);
},
new DataCallbackHandler(aTransferable, std::move(aCallback), kTextMime));
@@ -738,9 +749,10 @@ static void AsyncGetDataImpl(nsITransferable* aTransferable,
int32_t aWhichClipboard, const char* aMimeType,
DataType aDataType,
nsBaseClipboard::GetDataCallback&& aCallback) {
- LOGCLIP("AsyncGetData() type '%s'",
- aWhichClipboard == nsClipboard::kSelectionClipboard ? "primary"
- : "clipboard");
+ MOZ_CLIPBOARD_LOG("AsyncGetData() type '%s'",
+ aWhichClipboard == nsClipboard::kSelectionClipboard
+ ? "primary"
+ : "clipboard");
const char* gtkMIMEType = nullptr;
switch (aDataType) {
@@ -762,8 +774,8 @@ static void AsyncGetDataImpl(nsITransferable* aTransferable,
gpointer aData) -> void {
UniquePtr<DataCallbackHandler> ref(
static_cast<DataCallbackHandler*>(aData));
- LOGCLIP("AsyncGetData async handler [%p] MIME %s type %d", aData,
- ref->mMimeType.get(), ref->mDataType);
+ MOZ_CLIPBOARD_LOG("AsyncGetData async handler [%p] MIME %s type %d",
+ aData, ref->mMimeType.get(), ref->mDataType);
int dataLength = gtk_selection_data_get_length(aSelection);
if (dataLength <= 0) {
@@ -777,7 +789,7 @@ static void AsyncGetDataImpl(nsITransferable* aTransferable,
}
switch (ref->mDataType) {
case DATATYPE_IMAGE: {
- LOGCLIP(" set image clipboard data");
+ MOZ_CLIPBOARD_LOG(" set image clipboard data");
nsCOMPtr<nsIInputStream> byteStream;
NS_NewByteInputStream(getter_AddRefs(byteStream),
Span(data, dataLength), NS_ASSIGNMENT_COPY);
@@ -786,19 +798,19 @@ static void AsyncGetDataImpl(nsITransferable* aTransferable,
break;
}
case DATATYPE_FILE: {
- LOGCLIP(" set file clipboard data");
+ MOZ_CLIPBOARD_LOG(" set file clipboard data");
nsDependentCSubstring file(data, dataLength);
TransferableSetFile(ref->mTransferable, file);
break;
}
case DATATYPE_HTML: {
- LOGCLIP(" html clipboard data");
+ MOZ_CLIPBOARD_LOG(" html clipboard data");
Span dataSpan(data, dataLength);
TransferableSetHTML(ref->mTransferable, dataSpan);
break;
}
case DATATYPE_RAW: {
- LOGCLIP(" raw clipboard data %s", ref->mMimeType.get());
+ MOZ_CLIPBOARD_LOG(" raw clipboard data %s", ref->mMimeType.get());
SetTransferableData(ref->mTransferable, ref->mMimeType, data,
dataLength);
break;
@@ -821,7 +833,8 @@ static void AsyncGetDataFlavor(nsITransferable* aTransferable,
if (aFlavorStr.EqualsLiteral(kJPGImageMime)) {
aFlavorStr.Assign(kJPEGImageMime);
}
- LOGCLIP(" Getting image %s MIME clipboard data", aFlavorStr.get());
+ MOZ_CLIPBOARD_LOG(" Getting image %s MIME clipboard data",
+ aFlavorStr.get());
AsyncGetDataImpl(aTransferable, aWhichClipboard, aFlavorStr.get(),
DATATYPE_IMAGE, std::move(aCallback));
return;
@@ -829,23 +842,23 @@ static void AsyncGetDataFlavor(nsITransferable* aTransferable,
// Special case text/plain since we can convert any
// string into text/plain
if (aFlavorStr.EqualsLiteral(kTextMime)) {
- LOGCLIP(" Getting unicode clipboard data");
+ MOZ_CLIPBOARD_LOG(" Getting unicode clipboard data");
AsyncGetTextImpl(aTransferable, aWhichClipboard, std::move(aCallback));
return;
}
if (aFlavorStr.EqualsLiteral(kFileMime)) {
- LOGCLIP(" Getting file clipboard data\n");
+ MOZ_CLIPBOARD_LOG(" Getting file clipboard data\n");
AsyncGetDataImpl(aTransferable, aWhichClipboard, aFlavorStr.get(),
DATATYPE_FILE, std::move(aCallback));
return;
}
if (aFlavorStr.EqualsLiteral(kHTMLMime)) {
- LOGCLIP(" Getting HTML clipboard data");
+ MOZ_CLIPBOARD_LOG(" Getting HTML clipboard data");
AsyncGetDataImpl(aTransferable, aWhichClipboard, aFlavorStr.get(),
DATATYPE_HTML, std::move(aCallback));
return;
}
- LOGCLIP(" Getting raw %s MIME clipboard data\n", aFlavorStr.get());
+ MOZ_CLIPBOARD_LOG(" Getting raw %s MIME clipboard data\n", aFlavorStr.get());
AsyncGetDataImpl(aTransferable, aWhichClipboard, aFlavorStr.get(),
DATATYPE_RAW, std::move(aCallback));
}
@@ -857,9 +870,10 @@ void nsClipboard::AsyncGetNativeClipboardData(nsITransferable* aTransferable,
MOZ_DIAGNOSTIC_ASSERT(
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
- LOGCLIP("nsClipboard::AsyncGetNativeClipboardData (%s)",
- aWhichClipboard == nsClipboard::kSelectionClipboard ? "primary"
- : "clipboard");
+ MOZ_CLIPBOARD_LOG("nsClipboard::AsyncGetNativeClipboardData (%s)",
+ aWhichClipboard == nsClipboard::kSelectionClipboard
+ ? "primary"
+ : "clipboard");
nsTArray<nsCString> importedFlavors;
nsresult rv = GetTransferableFlavors(aTransferable, importedFlavors);
if (NS_FAILED(rv)) {
@@ -874,8 +888,9 @@ void nsClipboard::AsyncGetNativeClipboardData(nsITransferable* aTransferable,
}
#ifdef MOZ_LOGGING
if (flavorsNum > 1) {
- LOGCLIP(" Only first MIME type (%s) will be imported from clipboard!",
- importedFlavors[0].get());
+ MOZ_CLIPBOARD_LOG(
+ " Only first MIME type (%s) will be imported from clipboard!",
+ importedFlavors[0].get());
}
#endif
@@ -894,7 +909,7 @@ void nsClipboard::AsyncGetNativeClipboardData(nsITransferable* aTransferable,
nsTArray<nsCString> clipboardFlavors =
std::move(aResultOrError.unwrap());
if (!clipboardFlavors.Length()) {
- LOGCLIP(" no flavors in clipboard, quit.");
+ MOZ_CLIPBOARD_LOG(" no flavors in clipboard, quit.");
callback(NS_OK);
return;
}
@@ -914,8 +929,9 @@ nsresult nsClipboard::EmptyNativeClipboardData(int32_t aWhichClipboard) {
MOZ_DIAGNOSTIC_ASSERT(
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
- LOGCLIP("nsClipboard::EmptyNativeClipboardData (%s)\n",
- aWhichClipboard == kSelectionClipboard ? "primary" : "clipboard");
+ MOZ_CLIPBOARD_LOG(
+ "nsClipboard::EmptyNativeClipboardData (%s)\n",
+ aWhichClipboard == kSelectionClipboard ? "primary" : "clipboard");
if (aWhichClipboard == kSelectionClipboard) {
if (mSelectionTransferable) {
gtk_clipboard_clear(gtk_clipboard_get(GDK_SELECTION_PRIMARY));
@@ -947,20 +963,21 @@ static bool FlavorMatchesTarget(const nsACString& aFlavor, GdkAtom aTarget) {
return false;
}
if (aFlavor.Equals(atom_name.get())) {
- LOGCLIP(" has %s\n", atom_name.get());
+ MOZ_CLIPBOARD_LOG(" has %s\n", atom_name.get());
return true;
}
// X clipboard supports image/jpeg, but we want to emulate support
// for image/jpg as well
if (aFlavor.EqualsLiteral(kJPGImageMime) &&
!strcmp(atom_name.get(), kJPEGImageMime)) {
- LOGCLIP(" has image/jpg\n");
+ MOZ_CLIPBOARD_LOG(" has image/jpg\n");
return true;
}
// application/x-moz-file should be treated like text/uri-list
if (aFlavor.EqualsLiteral(kFileMime) &&
!strcmp(atom_name.get(), kURIListMime)) {
- LOGCLIP(" has text/uri-list treating as application/x-moz-file");
+ MOZ_CLIPBOARD_LOG(
+ " has text/uri-list treating as application/x-moz-file");
return true;
}
return false;
@@ -972,8 +989,9 @@ nsClipboard::HasNativeClipboardDataMatchingFlavors(
MOZ_DIAGNOSTIC_ASSERT(
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
- LOGCLIP("nsClipboard::HasNativeClipboardDataMatchingFlavors (%s)\n",
- aWhichClipboard == kSelectionClipboard ? "primary" : "clipboard");
+ MOZ_CLIPBOARD_LOG(
+ "nsClipboard::HasNativeClipboardDataMatchingFlavors (%s)\n",
+ aWhichClipboard == kSelectionClipboard ? "primary" : "clipboard");
if (!mContext) {
return Err(NS_ERROR_FAILURE);
@@ -981,25 +999,25 @@ nsClipboard::HasNativeClipboardDataMatchingFlavors(
auto targets = mContext->GetTargets(aWhichClipboard);
if (!targets) {
- LOGCLIP(" no targes at clipboard (null)\n");
+ MOZ_CLIPBOARD_LOG(" no targes at clipboard (null)\n");
return false;
}
#ifdef MOZ_LOGGING
- if (LOGCLIP_ENABLED()) {
- LOGCLIP(" Asking for content:\n");
+ if (MOZ_CLIPBOARD_LOG_ENABLED()) {
+ MOZ_CLIPBOARD_LOG(" Asking for content:\n");
for (auto& flavor : aFlavorList) {
- LOGCLIP(" MIME %s\n", flavor.get());
+ MOZ_CLIPBOARD_LOG(" MIME %s\n", flavor.get());
}
- LOGCLIP(" Clipboard content (target nums %zu):\n",
- targets.AsSpan().Length());
+ MOZ_CLIPBOARD_LOG(" Clipboard content (target nums %zu):\n",
+ targets.AsSpan().Length());
for (const auto& target : targets.AsSpan()) {
GUniquePtr<gchar> atom_name(gdk_atom_name(target));
if (!atom_name) {
- LOGCLIP(" failed to get MIME\n");
+ MOZ_CLIPBOARD_LOG(" failed to get MIME\n");
continue;
}
- LOGCLIP(" MIME %s\n", atom_name.get());
+ MOZ_CLIPBOARD_LOG(" MIME %s\n", atom_name.get());
}
}
#endif
@@ -1011,7 +1029,7 @@ nsClipboard::HasNativeClipboardDataMatchingFlavors(
if (flavor.EqualsLiteral(kTextMime) &&
gtk_targets_include_text(targets.AsSpan().data(),
targets.AsSpan().Length())) {
- LOGCLIP(" has kTextMime\n");
+ MOZ_CLIPBOARD_LOG(" has kTextMime\n");
return true;
}
for (const auto& target : targets.AsSpan()) {
@@ -1021,7 +1039,7 @@ nsClipboard::HasNativeClipboardDataMatchingFlavors(
}
}
- LOGCLIP(" no targes at clipboard (bad match)\n");
+ MOZ_CLIPBOARD_LOG(" no targes at clipboard (bad match)\n");
return false;
}
@@ -1030,10 +1048,10 @@ struct TragetCallbackHandler {
nsBaseClipboard::HasMatchingFlavorsCallback&& aCallback)
: mAcceptedFlavorList(aAcceptedFlavorList.Clone()),
mCallback(std::move(aCallback)) {
- LOGCLIP("TragetCallbackHandler(%p) created", this);
+ MOZ_CLIPBOARD_LOG("TragetCallbackHandler(%p) created", this);
}
~TragetCallbackHandler() {
- LOGCLIP("TragetCallbackHandler(%p) deleted", this);
+ MOZ_CLIPBOARD_LOG("TragetCallbackHandler(%p) deleted", this);
}
nsTArray<nsCString> mAcceptedFlavorList;
nsBaseClipboard::HasMatchingFlavorsCallback mCallback;
@@ -1045,15 +1063,17 @@ void nsClipboard::AsyncHasNativeClipboardDataMatchingFlavors(
MOZ_DIAGNOSTIC_ASSERT(
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
- LOGCLIP("nsClipboard::AsyncHasNativeClipboardDataMatchingFlavors (%s)",
- aWhichClipboard == kSelectionClipboard ? "primary" : "clipboard");
+ MOZ_CLIPBOARD_LOG(
+ "nsClipboard::AsyncHasNativeClipboardDataMatchingFlavors (%s)",
+ aWhichClipboard == kSelectionClipboard ? "primary" : "clipboard");
gtk_clipboard_request_contents(
gtk_clipboard_get(GetSelectionAtom(aWhichClipboard)),
gdk_atom_intern("TARGETS", FALSE),
[](GtkClipboard* aClipboard, GtkSelectionData* aSelection,
gpointer aData) -> void {
- LOGCLIP("gtk_clipboard_request_contents async handler (%p)", aData);
+ MOZ_CLIPBOARD_LOG("gtk_clipboard_request_contents async handler (%p)",
+ aData);
UniquePtr<TragetCallbackHandler> handler(
static_cast<TragetCallbackHandler*>(aData));
@@ -1061,15 +1081,30 @@ void nsClipboard::AsyncHasNativeClipboardDataMatchingFlavors(
gint targetsNum = 0;
if (gtk_selection_data_get_length(aSelection) > 0) {
gtk_selection_data_get_targets(aSelection, &targets, &targetsNum);
+
+#ifdef MOZ_LOGGING
+ if (MOZ_CLIPBOARD_LOG_ENABLED()) {
+ MOZ_CLIPBOARD_LOG(" Clipboard content (target nums %d):\n",
+ targetsNum);
+ for (int i = 0; i < targetsNum; i++) {
+ GUniquePtr<gchar> atom_name(gdk_atom_name(targets[i]));
+ if (!atom_name) {
+ MOZ_CLIPBOARD_LOG(" failed to get MIME\n");
+ continue;
+ }
+ MOZ_CLIPBOARD_LOG(" MIME %s\n", atom_name.get());
+ }
+ }
+#endif
}
nsTArray<nsCString> results;
if (targetsNum) {
for (auto& flavor : handler->mAcceptedFlavorList) {
- LOGCLIP(" looking for %s", flavor.get());
+ MOZ_CLIPBOARD_LOG(" looking for %s", flavor.get());
if (flavor.EqualsLiteral(kTextMime) &&
gtk_targets_include_text(targets, targetsNum)) {
results.AppendElement(flavor);
- LOGCLIP(" has kTextMime\n");
+ MOZ_CLIPBOARD_LOG(" has kTextMime\n");
continue;
}
for (int i = 0; i < targetsNum; i++) {
@@ -1113,14 +1148,16 @@ void nsClipboard::SelectionGetEvent(GtkClipboard* aClipboard,
else
return; // THAT AIN'T NO CLIPBOARD I EVER HEARD OF
- LOGCLIP("nsClipboard::SelectionGetEvent (%s)\n",
- whichClipboard == kSelectionClipboard ? "primary" : "clipboard");
+ MOZ_CLIPBOARD_LOG(
+ "nsClipboard::SelectionGetEvent (%s)\n",
+ whichClipboard == kSelectionClipboard ? "primary" : "clipboard");
nsCOMPtr<nsITransferable> trans = GetTransferable(whichClipboard);
if (!trans) {
// We have nothing to serve
- LOGCLIP("nsClipboard::SelectionGetEvent() - %s clipboard is empty!\n",
- whichClipboard == kSelectionClipboard ? "Primary" : "Clipboard");
+ MOZ_CLIPBOARD_LOG(
+ "nsClipboard::SelectionGetEvent() - %s clipboard is empty!\n",
+ whichClipboard == kSelectionClipboard ? "Primary" : "Clipboard");
return;
}
@@ -1128,18 +1165,18 @@ void nsClipboard::SelectionGetEvent(GtkClipboard* aClipboard,
nsCOMPtr<nsISupports> item;
GdkAtom selectionTarget = gtk_selection_data_get_target(aSelectionData);
- LOGCLIP(" selection target %s\n",
- GUniquePtr<gchar>(gdk_atom_name(selectionTarget)).get());
+ MOZ_CLIPBOARD_LOG(" selection target %s\n",
+ GUniquePtr<gchar>(gdk_atom_name(selectionTarget)).get());
// Check to see if the selection data is some text type.
if (gtk_targets_include_text(&selectionTarget, 1)) {
- LOGCLIP(" providing text/plain data\n");
+ MOZ_CLIPBOARD_LOG(" providing text/plain data\n");
// Try to convert our internal type into a text string. Get
// the transferable for this clipboard and try to get the
// text/plain type for it.
rv = trans->GetTransferData("text/plain", getter_AddRefs(item));
if (NS_FAILED(rv) || !item) {
- LOGCLIP(" GetTransferData() failed to get text/plain!\n");
+ MOZ_CLIPBOARD_LOG(" GetTransferData() failed to get text/plain!\n");
return;
}
@@ -1151,9 +1188,9 @@ void nsClipboard::SelectionGetEvent(GtkClipboard* aClipboard,
wideString->GetData(ucs2string);
NS_ConvertUTF16toUTF8 utf8string(ucs2string);
- LOGCLIP(" sent %zd bytes of utf-8 data\n", utf8string.Length());
+ MOZ_CLIPBOARD_LOG(" sent %zd bytes of utf-8 data\n", utf8string.Length());
if (selectionTarget == gdk_atom_intern("text/plain;charset=utf-8", FALSE)) {
- LOGCLIP(
+ MOZ_CLIPBOARD_LOG(
" using gtk_selection_data_set for 'text/plain;charset=utf-8'\n");
// Bypass gtk_selection_data_set_text, which will convert \n to \r\n
// in some versions of GTK.
@@ -1169,7 +1206,7 @@ void nsClipboard::SelectionGetEvent(GtkClipboard* aClipboard,
// Check to see if the selection data is an image type
if (gtk_targets_include_image(&selectionTarget, 1, TRUE)) {
- LOGCLIP(" providing image data\n");
+ MOZ_CLIPBOARD_LOG(" providing image data\n");
// Look through our transfer data for the image
static const char* const imageMimeTypes[] = {kNativeImageMime,
kPNGImageMime, kJPEGImageMime,
@@ -1179,47 +1216,50 @@ void nsClipboard::SelectionGetEvent(GtkClipboard* aClipboard,
for (uint32_t i = 0; i < ArrayLength(imageMimeTypes); i++) {
rv = trans->GetTransferData(imageMimeTypes[i], getter_AddRefs(imageItem));
if (NS_FAILED(rv)) {
- LOGCLIP(" %s is missing at GetTransferData()\n", imageMimeTypes[i]);
+ MOZ_CLIPBOARD_LOG(" %s is missing at GetTransferData()\n",
+ imageMimeTypes[i]);
continue;
}
image = do_QueryInterface(imageItem);
if (image) {
- LOGCLIP(" %s is available at GetTransferData()\n",
- imageMimeTypes[i]);
+ MOZ_CLIPBOARD_LOG(" %s is available at GetTransferData()\n",
+ imageMimeTypes[i]);
break;
}
}
if (!image) { // Not getting an image for an image mime type!?
- LOGCLIP(" Failed to get any image mime from GetTransferData()!\n");
+ MOZ_CLIPBOARD_LOG(
+ " Failed to get any image mime from GetTransferData()!\n");
return;
}
RefPtr<GdkPixbuf> pixbuf = nsImageToPixbuf::ImageToPixbuf(image);
if (!pixbuf) {
- LOGCLIP(" nsImageToPixbuf::ImageToPixbuf() failed!\n");
+ MOZ_CLIPBOARD_LOG(" nsImageToPixbuf::ImageToPixbuf() failed!\n");
return;
}
- LOGCLIP(" Setting pixbuf image data as %s\n",
- GUniquePtr<gchar>(gdk_atom_name(selectionTarget)).get());
+ MOZ_CLIPBOARD_LOG(" Setting pixbuf image data as %s\n",
+ GUniquePtr<gchar>(gdk_atom_name(selectionTarget)).get());
gtk_selection_data_set_pixbuf(aSelectionData, pixbuf);
return;
}
if (selectionTarget == gdk_atom_intern(kHTMLMime, FALSE)) {
- LOGCLIP(" providing %s data\n", kHTMLMime);
+ MOZ_CLIPBOARD_LOG(" providing %s data\n", kHTMLMime);
rv = trans->GetTransferData(kHTMLMime, getter_AddRefs(item));
if (NS_FAILED(rv) || !item) {
- LOGCLIP(" failed to get %s data by GetTransferData()!\n", kHTMLMime);
+ MOZ_CLIPBOARD_LOG(" failed to get %s data by GetTransferData()!\n",
+ kHTMLMime);
return;
}
nsCOMPtr<nsISupportsString> wideString;
wideString = do_QueryInterface(item);
if (!wideString) {
- LOGCLIP(" failed to get wideString interface!");
+ MOZ_CLIPBOARD_LOG(" failed to get wideString interface!");
return;
}
@@ -1231,8 +1271,8 @@ void nsClipboard::SelectionGetEvent(GtkClipboard* aClipboard,
html.AppendLiteral(kHTMLMarkupPrefix);
AppendUTF16toUTF8(ucs2string, html);
- LOGCLIP(" Setting %zd bytes of %s data\n", html.Length(),
- GUniquePtr<gchar>(gdk_atom_name(selectionTarget)).get());
+ MOZ_CLIPBOARD_LOG(" Setting %zd bytes of %s data\n", html.Length(),
+ GUniquePtr<gchar>(gdk_atom_name(selectionTarget)).get());
gtk_selection_data_set(aSelectionData, selectionTarget, 8,
(const guchar*)html.get(), html.Length());
return;
@@ -1240,53 +1280,54 @@ void nsClipboard::SelectionGetEvent(GtkClipboard* aClipboard,
// We put kFileMime onto the clipboard as kURIListMime.
if (selectionTarget == gdk_atom_intern(kURIListMime, FALSE)) {
- LOGCLIP(" providing %s data\n", kURIListMime);
+ MOZ_CLIPBOARD_LOG(" providing %s data\n", kURIListMime);
rv = trans->GetTransferData(kFileMime, getter_AddRefs(item));
if (NS_FAILED(rv) || !item) {
- LOGCLIP(" failed to get %s data by GetTransferData()!\n", kFileMime);
+ MOZ_CLIPBOARD_LOG(" failed to get %s data by GetTransferData()!\n",
+ kFileMime);
return;
}
nsCOMPtr<nsIFile> file = do_QueryInterface(item);
if (!file) {
- LOGCLIP(" failed to get nsIFile interface!");
+ MOZ_CLIPBOARD_LOG(" failed to get nsIFile interface!");
return;
}
nsCOMPtr<nsIURI> fileURI;
rv = NS_NewFileURI(getter_AddRefs(fileURI), file);
if (NS_FAILED(rv)) {
- LOGCLIP(" failed to get fileURI\n");
+ MOZ_CLIPBOARD_LOG(" failed to get fileURI\n");
return;
}
nsAutoCString uri;
if (NS_FAILED(fileURI->GetSpec(uri))) {
- LOGCLIP(" failed to get fileURI spec\n");
+ MOZ_CLIPBOARD_LOG(" failed to get fileURI spec\n");
return;
}
- LOGCLIP(" Setting %zd bytes of data\n", uri.Length());
+ MOZ_CLIPBOARD_LOG(" Setting %zd bytes of data\n", uri.Length());
gtk_selection_data_set(aSelectionData, selectionTarget, 8,
(const guchar*)uri.get(), uri.Length());
return;
}
- LOGCLIP(" Try if we have anything at GetTransferData() for %s\n",
- GUniquePtr<gchar>(gdk_atom_name(selectionTarget)).get());
+ MOZ_CLIPBOARD_LOG(" Try if we have anything at GetTransferData() for %s\n",
+ GUniquePtr<gchar>(gdk_atom_name(selectionTarget)).get());
// Try to match up the selection data target to something our
// transferable provides.
GUniquePtr<gchar> target_name(gdk_atom_name(selectionTarget));
if (!target_name) {
- LOGCLIP(" Failed to get target name!\n");
+ MOZ_CLIPBOARD_LOG(" Failed to get target name!\n");
return;
}
rv = trans->GetTransferData(target_name.get(), getter_AddRefs(item));
// nothing found?
if (NS_FAILED(rv) || !item) {
- LOGCLIP(" Failed to get anything from GetTransferData()!\n");
+ MOZ_CLIPBOARD_LOG(" Failed to get anything from GetTransferData()!\n");
return;
}
@@ -1295,12 +1336,12 @@ void nsClipboard::SelectionGetEvent(GtkClipboard* aClipboard,
nsPrimitiveHelpers::CreateDataFromPrimitive(
nsDependentCString(target_name.get()), item, &primitive_data, &dataLen);
if (!primitive_data) {
- LOGCLIP(" Failed to get primitive data!\n");
+ MOZ_CLIPBOARD_LOG(" Failed to get primitive data!\n");
return;
}
- LOGCLIP(" Setting %s as a primitive data type, %d bytes\n",
- target_name.get(), dataLen);
+ MOZ_CLIPBOARD_LOG(" Setting %s as a primitive data type, %d bytes\n",
+ target_name.get(), dataLen);
gtk_selection_data_set(aSelectionData, selectionTarget,
8, /* 8 bits in a unit */
(const guchar*)primitive_data, dataLen);
@@ -1320,8 +1361,9 @@ void nsClipboard::SelectionClearEvent(GtkClipboard* aGtkClipboard) {
if (whichClipboard < 0) {
return;
}
- LOGCLIP("nsClipboard::SelectionClearEvent (%s)\n",
- whichClipboard == kSelectionClipboard ? "primary" : "clipboard");
+ MOZ_CLIPBOARD_LOG(
+ "nsClipboard::SelectionClearEvent (%s)\n",
+ whichClipboard == kSelectionClipboard ? "primary" : "clipboard");
ClearCachedTargets(whichClipboard);
ClearTransferable(whichClipboard);
ClearClipboardCache(whichClipboard);
@@ -1333,8 +1375,9 @@ void nsClipboard::OwnerChangedEvent(GtkClipboard* aGtkClipboard,
if (whichClipboard < 0) {
return;
}
- LOGCLIP("nsClipboard::OwnerChangedEvent (%s)\n",
- whichClipboard == kSelectionClipboard ? "primary" : "clipboard");
+ MOZ_CLIPBOARD_LOG(
+ "nsClipboard::OwnerChangedEvent (%s)\n",
+ whichClipboard == kSelectionClipboard ? "primary" : "clipboard");
GtkWidget* gtkWidget = [aEvent]() -> GtkWidget* {
if (!aEvent->owner) {
return nullptr;
@@ -1360,13 +1403,13 @@ void nsClipboard::OwnerChangedEvent(GtkClipboard* aGtkClipboard,
void clipboard_get_cb(GtkClipboard* aGtkClipboard,
GtkSelectionData* aSelectionData, guint info,
gpointer user_data) {
- LOGCLIP("clipboard_get_cb() callback\n");
+ MOZ_CLIPBOARD_LOG("clipboard_get_cb() callback\n");
nsClipboard* clipboard = static_cast<nsClipboard*>(user_data);
clipboard->SelectionGetEvent(aGtkClipboard, aSelectionData);
}
void clipboard_clear_cb(GtkClipboard* aGtkClipboard, gpointer user_data) {
- LOGCLIP("clipboard_clear_cb() callback\n");
+ MOZ_CLIPBOARD_LOG("clipboard_clear_cb() callback\n");
nsClipboard* clipboard = static_cast<nsClipboard*>(user_data);
clipboard->SelectionClearEvent(aGtkClipboard);
}
@@ -1374,7 +1417,7 @@ void clipboard_clear_cb(GtkClipboard* aGtkClipboard, gpointer user_data) {
void clipboard_owner_change_cb(GtkClipboard* aGtkClipboard,
GdkEventOwnerChange* aEvent,
gpointer aUserData) {
- LOGCLIP("clipboard_owner_change_cb() callback\n");
+ MOZ_CLIPBOARD_LOG("clipboard_owner_change_cb() callback\n");
nsClipboard* clipboard = static_cast<nsClipboard*>(aUserData);
clipboard->OwnerChangedEvent(aGtkClipboard, aEvent);
}
diff --git a/widget/gtk/nsClipboard.h b/widget/gtk/nsClipboard.h
index 0ddbb59827..358136ae4e 100644
--- a/widget/gtk/nsClipboard.h
+++ b/widget/gtk/nsClipboard.h
@@ -17,20 +17,6 @@
#include "GUniquePtr.h"
#include <gtk/gtk.h>
-#ifdef MOZ_LOGGING
-# include "mozilla/Logging.h"
-# include "nsTArray.h"
-# include "Units.h"
-extern mozilla::LazyLogModule gClipboardLog;
-# define LOGCLIP(...) \
- MOZ_LOG(gClipboardLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-# define LOGCLIP_ENABLED() \
- MOZ_LOG_TEST(gClipboardLog, mozilla::LogLevel::Debug)
-#else
-# define LOGCLIP(...)
-# define LOGCLIP_ENABLED() false
-#endif /* MOZ_LOGGING */
-
class ClipboardTargets {
friend class ClipboardData;
diff --git a/widget/gtk/nsClipboardWayland.cpp b/widget/gtk/nsClipboardWayland.cpp
index d179f242dd..316fcf90b6 100644
--- a/widget/gtk/nsClipboardWayland.cpp
+++ b/widget/gtk/nsClipboardWayland.cpp
@@ -22,7 +22,7 @@ nsRetrievalContextWayland::nsRetrievalContextWayland() = default;
ClipboardTargets nsRetrievalContextWayland::GetTargetsImpl(
int32_t aWhichClipboard) {
- LOGCLIP("nsRetrievalContextWayland::GetTargetsImpl()\n");
+ MOZ_CLIPBOARD_LOG("nsRetrievalContextWayland::GetTargetsImpl()\n");
return WaitForClipboardData(ClipboardDataType::Targets, aWhichClipboard)
.ExtractTargets();
@@ -30,7 +30,8 @@ ClipboardTargets nsRetrievalContextWayland::GetTargetsImpl(
ClipboardData nsRetrievalContextWayland::GetClipboardData(
const char* aMimeType, int32_t aWhichClipboard) {
- LOGCLIP("nsRetrievalContextWayland::GetClipboardData() mime %s\n", aMimeType);
+ MOZ_CLIPBOARD_LOG("nsRetrievalContextWayland::GetClipboardData() mime %s\n",
+ aMimeType);
return WaitForClipboardData(ClipboardDataType::Data, aWhichClipboard,
aMimeType);
@@ -40,8 +41,9 @@ GUniquePtr<char> nsRetrievalContextWayland::GetClipboardText(
int32_t aWhichClipboard) {
GdkAtom selection = GetSelectionAtom(aWhichClipboard);
- LOGCLIP("nsRetrievalContextWayland::GetClipboardText(), clipboard %s\n",
- (selection == GDK_SELECTION_PRIMARY) ? "Primary" : "Selection");
+ MOZ_CLIPBOARD_LOG(
+ "nsRetrievalContextWayland::GetClipboardText(), clipboard %s\n",
+ (selection == GDK_SELECTION_PRIMARY) ? "Primary" : "Selection");
return WaitForClipboardData(ClipboardDataType::Text, aWhichClipboard)
.ExtractText();
@@ -50,8 +52,8 @@ GUniquePtr<char> nsRetrievalContextWayland::GetClipboardText(
ClipboardData nsRetrievalContextWayland::WaitForClipboardData(
ClipboardDataType aDataType, int32_t aWhichClipboard,
const char* aMimeType) {
- LOGCLIP("nsRetrievalContextWayland::WaitForClipboardData, MIME %s\n",
- aMimeType);
+ MOZ_CLIPBOARD_LOG(
+ "nsRetrievalContextWayland::WaitForClipboardData, MIME %s\n", aMimeType);
AsyncGtkClipboardRequest request(aDataType, aWhichClipboard, aMimeType);
int iteration = 1;
@@ -62,12 +64,13 @@ ClipboardData nsRetrievalContextWayland::WaitForClipboardData(
/* sleep for 10 ms/iteration */
PR_Sleep(PR_MillisecondsToInterval(10));
if (PR_Now() - entryTime > kClipboardTimeout) {
- LOGCLIP(" failed to get async clipboard data in time limit\n");
+ MOZ_CLIPBOARD_LOG(
+ " failed to get async clipboard data in time limit\n");
break;
}
}
- LOGCLIP("doing iteration %d msec %ld ...\n", (iteration - 1),
- (long)((PR_Now() - entryTime) / 1000));
+ MOZ_CLIPBOARD_LOG("doing iteration %d msec %ld ...\n", (iteration - 1),
+ (long)((PR_Now() - entryTime) / 1000));
gtk_main_iteration();
}
diff --git a/widget/gtk/nsClipboardX11.cpp b/widget/gtk/nsClipboardX11.cpp
index db12d1e69c..2693622922 100644
--- a/widget/gtk/nsClipboardX11.cpp
+++ b/widget/gtk/nsClipboardX11.cpp
@@ -138,25 +138,27 @@ ClipboardData nsRetrievalContextX11::WaitForClipboardData(
(poll_result == -1 && errno == EINTR));
}
- LOGCLIP("exceeded clipboard timeout");
+ MOZ_CLIPBOARD_LOG("exceeded clipboard timeout");
return {};
}
ClipboardTargets nsRetrievalContextX11::GetTargetsImpl(
int32_t aWhichClipboard) {
- LOGCLIP("nsRetrievalContextX11::GetTargetsImpl(%s)\n",
- aWhichClipboard == nsClipboard::kSelectionClipboard ? "primary"
- : "clipboard");
+ MOZ_CLIPBOARD_LOG("nsRetrievalContextX11::GetTargetsImpl(%s)\n",
+ aWhichClipboard == nsClipboard::kSelectionClipboard
+ ? "primary"
+ : "clipboard");
return WaitForClipboardData(ClipboardDataType::Targets, aWhichClipboard)
.ExtractTargets();
}
ClipboardData nsRetrievalContextX11::GetClipboardData(const char* aMimeType,
int32_t aWhichClipboard) {
- LOGCLIP("nsRetrievalContextX11::GetClipboardData(%s) MIME %s\n",
- aWhichClipboard == nsClipboard::kSelectionClipboard ? "primary"
- : "clipboard",
- aMimeType);
+ MOZ_CLIPBOARD_LOG("nsRetrievalContextX11::GetClipboardData(%s) MIME %s\n",
+ aWhichClipboard == nsClipboard::kSelectionClipboard
+ ? "primary"
+ : "clipboard",
+ aMimeType);
return WaitForClipboardData(ClipboardDataType::Data, aWhichClipboard,
aMimeType);
@@ -164,9 +166,10 @@ ClipboardData nsRetrievalContextX11::GetClipboardData(const char* aMimeType,
GUniquePtr<char> nsRetrievalContextX11::GetClipboardText(
int32_t aWhichClipboard) {
- LOGCLIP("nsRetrievalContextX11::GetClipboardText(%s)\n",
- aWhichClipboard == nsClipboard::kSelectionClipboard ? "primary"
- : "clipboard");
+ MOZ_CLIPBOARD_LOG("nsRetrievalContextX11::GetClipboardText(%s)\n",
+ aWhichClipboard == nsClipboard::kSelectionClipboard
+ ? "primary"
+ : "clipboard");
return WaitForClipboardData(ClipboardDataType::Text, aWhichClipboard)
.ExtractText();
diff --git a/widget/gtk/nsDragService.cpp b/widget/gtk/nsDragService.cpp
index 6cabfbbe2e..c3a3136013 100644
--- a/widget/gtk/nsDragService.cpp
+++ b/widget/gtk/nsDragService.cpp
@@ -1750,7 +1750,7 @@ nsresult nsDragService::CreateTempFile(nsITransferable* aItem,
}
// create and open channel for source uri
- nsCOMPtr<nsIPrincipal> principal = aItem->GetRequestingPrincipal();
+ nsCOMPtr<nsIPrincipal> principal = aItem->GetDataPrincipal();
nsContentPolicyType contentPolicyType = aItem->GetContentPolicyType();
nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
aItem->GetCookieJarSettings();
diff --git a/widget/gtk/nsLookAndFeel.cpp b/widget/gtk/nsLookAndFeel.cpp
index 8702c154d6..bfd3f1b6f4 100644
--- a/widget/gtk/nsLookAndFeel.cpp
+++ b/widget/gtk/nsLookAndFeel.cpp
@@ -904,8 +904,7 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
break;
}
case IntID::MenusCanOverlapOSBar:
- // we want XUL popups to be able to overlap the task bar.
- aResult = 1;
+ aResult = 0;
break;
case IntID::SkipNavigatingDisabledMenuItem:
aResult = 1;
@@ -1975,10 +1974,7 @@ void nsLookAndFeel::PerThemeData::Init() {
mTitlebar = GetColorPair(style, GTK_STATE_FLAG_NORMAL);
mTitlebarInactive = GetColorPair(style, GTK_STATE_FLAG_BACKDROP);
mTitlebarRadius = IsSolidCSDStyleUsed() ? 0 : GetBorderRadius(style);
- // Get titlebar spacing, a default one is 6 pixels (gtk/gtkheaderbar.c)
- mTitlebarButtonSpacing = 6;
- g_object_get(GetWidget(MOZ_GTK_HEADER_BAR), "spacing",
- &mTitlebarButtonSpacing, nullptr);
+ mTitlebarButtonSpacing = moz_gtk_get_titlebar_button_spacing();
}
// We special-case the header bar color in Adwaita, Yaru and Breeze to be the
diff --git a/widget/gtk/nsNativeThemeGTK.cpp b/widget/gtk/nsNativeThemeGTK.cpp
index 78d4e925fe..5c858d2313 100644
--- a/widget/gtk/nsNativeThemeGTK.cpp
+++ b/widget/gtk/nsNativeThemeGTK.cpp
@@ -195,14 +195,6 @@ bool nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aAppearance,
aAppearance == StyleAppearance::Menulist ||
aAppearance == StyleAppearance::MenulistButton) {
aState->active &= aState->inHover;
- } else if (aAppearance == StyleAppearance::Treetwisty ||
- aAppearance == StyleAppearance::Treetwistyopen) {
- if (nsTreeBodyFrame* treeBodyFrame = do_QueryFrame(aFrame)) {
- const mozilla::AtomArray& atoms =
- treeBodyFrame->GetPropertyArrayForCurrentDrawingItem();
- aState->selected = atoms.Contains(nsGkAtoms::selected);
- aState->inHover = atoms.Contains(nsGkAtoms::hover);
- }
}
if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) {
@@ -292,6 +284,7 @@ bool nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aAppearance,
break;
}
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
aGtkWidgetType = MOZ_GTK_ENTRY;
break;
@@ -299,17 +292,8 @@ bool nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aAppearance,
aGtkWidgetType = MOZ_GTK_TEXT_VIEW;
break;
case StyleAppearance::Listbox:
- case StyleAppearance::Treeview:
aGtkWidgetType = MOZ_GTK_TREEVIEW;
break;
- case StyleAppearance::Treetwisty:
- aGtkWidgetType = MOZ_GTK_TREEVIEW_EXPANDER;
- if (aWidgetFlags) *aWidgetFlags = GTK_EXPANDER_COLLAPSED;
- break;
- case StyleAppearance::Treetwistyopen:
- aGtkWidgetType = MOZ_GTK_TREEVIEW_EXPANDER;
- if (aWidgetFlags) *aWidgetFlags = GTK_EXPANDER_EXPANDED;
- break;
case StyleAppearance::MenulistButton:
case StyleAppearance::Menulist:
aGtkWidgetType = MOZ_GTK_DROPDOWN;
@@ -1091,6 +1075,7 @@ LayoutDeviceIntSize nsNativeThemeGTK::GetMinimumWidgetSize(
result.height += border.TopBottom();
} break;
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield: {
gint contentHeight = 0;
gint borderPaddingHeight = 0;
@@ -1135,12 +1120,6 @@ LayoutDeviceIntSize nsNativeThemeGTK::GetMinimumWidgetSize(
result.width = 14;
result.height = 13;
break;
- case StyleAppearance::Treetwisty:
- case StyleAppearance::Treetwistyopen: {
- gint expander_size;
- moz_gtk_get_treeview_expander_size(&expander_size);
- result.width = result.height = expander_size;
- } break;
default:
break;
}
@@ -1243,12 +1222,6 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
case StyleAppearance::ButtonArrowNext:
case StyleAppearance::ButtonArrowPrevious:
case StyleAppearance::Listbox:
- case StyleAppearance::Treeview:
- // case StyleAppearance::Treeitem:
- case StyleAppearance::Treetwisty:
- // case StyleAppearance::Treeline:
- // case StyleAppearance::Treeheader:
- case StyleAppearance::Treetwistyopen:
case StyleAppearance::ProgressBar:
case StyleAppearance::Progresschunk:
case StyleAppearance::Tab:
@@ -1262,6 +1235,7 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
case StyleAppearance::SpinnerDownbutton:
case StyleAppearance::SpinnerTextfield:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::Range:
@@ -1315,6 +1289,7 @@ bool nsNativeThemeGTK::ThemeDrawsFocusForWidget(nsIFrame* aFrame,
case StyleAppearance::Textarea:
case StyleAppearance::Textfield:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
return true;
default:
return false;
diff --git a/widget/gtk/nsWaylandDisplay.cpp b/widget/gtk/nsWaylandDisplay.cpp
index 1ea87b3bc5..c63c8f6564 100644
--- a/widget/gtk/nsWaylandDisplay.cpp
+++ b/widget/gtk/nsWaylandDisplay.cpp
@@ -28,7 +28,6 @@ void WaylandDisplayRelease() {
MOZ_RELEASE_ASSERT(NS_IsMainThread(),
"WaylandDisplay can be released in main thread only!");
if (!gWaylandDisplay) {
- NS_WARNING("WaylandDisplayRelease(): Wayland display is missing!");
return;
}
delete gWaylandDisplay;
@@ -151,7 +150,6 @@ static void global_registry_handler(void* data, wl_registry* registry,
registry, id, &xdg_dbus_annotation_manager_v1_interface, 1);
display->SetXdgDbusAnnotationManager(annotationManager);
} else if (iface.EqualsLiteral("wl_seat")) {
- // Install keyboard handlers for main thread only
auto* seat =
WaylandRegistryBind<wl_seat>(registry, id, &wl_seat_interface, 1);
KeymapWrapper::SetSeat(seat, id);
@@ -173,7 +171,7 @@ static void global_registry_remover(void* data, wl_registry* registry,
static const struct wl_registry_listener registry_listener = {
global_registry_handler, global_registry_remover};
-nsWaylandDisplay::~nsWaylandDisplay() {}
+nsWaylandDisplay::~nsWaylandDisplay() = default;
static void WlLogHandler(const char* format, va_list args) {
char error[1000];
diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
index 0a78d0c8ec..2971497969 100644
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -389,8 +389,7 @@ static void GtkWindowSetTransientFor(GtkWindow* aWindow, GtkWindow* aParent) {
}
nsWindow::nsWindow()
- : mTitlebarRectMutex("nsWindow::mTitlebarRectMutex"),
- mWindowVisibilityMutex("nsWindow::mWindowVisibilityMutex"),
+ : mWindowVisibilityMutex("nsWindow::mWindowVisibilityMutex"),
mIsMapped(false),
mIsDestroyed(false),
mIsShown(false),
@@ -514,10 +513,6 @@ void nsWindow::MaybeDispatchResized() {
<< mBounds << " size state " << mSizeMode;
}
- if (IsTopLevelWindowType()) {
- UpdateTopLevelOpaqueRegion();
- }
-
// Notify the GtkCompositorWidget of a ClientSizeChange
if (mCompositorWidgetDelegate) {
mCompositorWidgetDelegate->NotifyClientSizeChanged(GetClientSize());
@@ -591,6 +586,7 @@ void nsWindow::Destroy() {
mWaylandVsyncSource = nullptr;
}
mWaylandVsyncDispatcher = nullptr;
+ UnlockNativePointer();
#endif
// dragService will be null after shutdown of the service manager.
@@ -3216,9 +3212,7 @@ LayoutDeviceIntRect nsWindow::GetScreenBounds() {
return rect;
}
-LayoutDeviceIntSize nsWindow::GetClientSize() {
- return LayoutDeviceIntSize(mBounds.width, mBounds.height);
-}
+LayoutDeviceIntSize nsWindow::GetClientSize() { return mBounds.Size(); }
LayoutDeviceIntRect nsWindow::GetClientBounds() {
// GetBounds returns a rect whose top left represents the top left of the
@@ -5379,8 +5373,6 @@ void nsWindow::OnWindowStateEvent(GtkWidget* aWidget,
} else {
ClearTransparencyBitmap();
}
- } else {
- SetTitlebarRect();
}
}
@@ -5391,7 +5383,6 @@ void nsWindow::OnDPIChanged() {
if (PresShell* presShell = mWidgetListener->GetPresShell()) {
presShell->BackingScaleFactorChanged();
}
- mWidgetListener->UIResolutionChanged();
}
NotifyAPZOfDPIChange();
}
@@ -6934,80 +6925,99 @@ LayoutDeviceIntCoord nsWindow::GetTitlebarRadius() {
return GdkCoordToDevicePixels(cssCoord);
}
+LayoutDeviceIntRegion nsWindow::GetOpaqueRegion() const {
+ AutoReadLock r(mOpaqueRegionLock);
+ return mOpaqueRegion;
+}
+
// See subtract_corners_from_region() at gtk/gtkwindow.c
// We need to subtract corners from toplevel window opaque region
// to draw transparent corners of default Gtk titlebar.
// Both implementations (cairo_region_t and wl_region) needs to be synced.
-static void SubtractTitlebarCorners(cairo_region_t* aRegion, int aX, int aY,
- int aWindowWidth, int aWindowHeight,
- int aTitlebarRadius) {
- if (!aTitlebarRadius) {
- return;
- }
- cairo_rectangle_int_t rect = {aX, aY, aTitlebarRadius, aTitlebarRadius};
- cairo_region_subtract_rectangle(aRegion, &rect);
- rect = {
- aX + aWindowWidth - aTitlebarRadius,
- aY,
- aTitlebarRadius,
- aTitlebarRadius,
- };
- cairo_region_subtract_rectangle(aRegion, &rect);
- rect = {
- aX,
- aY + aWindowHeight - aTitlebarRadius,
- aTitlebarRadius,
- aTitlebarRadius,
- };
- cairo_region_subtract_rectangle(aRegion, &rect);
- rect = {
- aX + aWindowWidth - aTitlebarRadius,
- aY + aWindowHeight - aTitlebarRadius,
- aTitlebarRadius,
- aTitlebarRadius,
- };
- cairo_region_subtract_rectangle(aRegion, &rect);
+static void SubtractTitlebarCorners(LayoutDeviceIntRegion& aRegion,
+ const LayoutDeviceIntRect& aRect,
+ LayoutDeviceIntCoord aRadius) {
+ if (!aRadius) {
+ return;
+ }
+ const LayoutDeviceIntSize size(aRadius, aRadius);
+ aRegion.SubOut(LayoutDeviceIntRect(aRect.TopLeft(), size));
+ aRegion.SubOut(LayoutDeviceIntRect(
+ aRect.TopRight() - LayoutDeviceIntPoint(aRadius, 0), size));
+ aRegion.SubOut(LayoutDeviceIntRect(
+ aRect.BottomLeft() - LayoutDeviceIntPoint(0, aRadius), size));
+ aRegion.SubOut(LayoutDeviceIntRect(
+ aRect.BottomRight() - LayoutDeviceIntPoint(aRadius, aRadius), size));
+}
+
+void nsWindow::UpdateOpaqueRegion(const LayoutDeviceIntRegion& aRegion) {
+ LayoutDeviceIntRegion region = aRegion;
+ SubtractTitlebarCorners(region, LayoutDeviceIntRect({}, mBounds.Size()),
+ GetTitlebarRadius());
+ {
+ AutoReadLock r(mOpaqueRegionLock);
+ if (mOpaqueRegion == region) {
+ return;
+ }
+ }
+ {
+ AutoWriteLock w(mOpaqueRegionLock);
+ mOpaqueRegion = region;
+ }
+ UpdateOpaqueRegionInternal();
}
-void nsWindow::UpdateTopLevelOpaqueRegion() {
+void nsWindow::UpdateOpaqueRegionInternal() {
if (!mCompositedScreen) {
return;
}
+ if (!IsTopLevelWindowType()) {
+ // We need to clear target buffer alpha values of popup windows as
+ // SW-WR paints with alpha blending (see Bug 1674473).
+ return;
+ }
+
GdkWindow* window = GetToplevelGdkWindow();
if (!window) {
return;
}
MOZ_ASSERT(gdk_window_get_window_type(window) == GDK_WINDOW_TOPLEVEL);
- int x = 0;
- int y = 0;
-
- gdk_window_get_position(mGdkWindow, &x, &y);
-
- int width = DevicePixelsToGdkCoordRoundDown(mBounds.width);
- int height = DevicePixelsToGdkCoordRoundDown(mBounds.height);
-
- cairo_region_t* region = cairo_region_create();
- cairo_rectangle_int_t rect = {x, y, width, height};
- cairo_region_union_rectangle(region, &rect);
-
- // TODO: We actually could get a proper opaque region from layout, see
- // nsIWidget::UpdateOpaqueRegion. This could simplify titlebar drawing.
- int radius = DoDrawTilebarCorners() ? int(GetTitlebarRadius()) : 0;
- SubtractTitlebarCorners(region, x, y, width, height, radius);
-
- gdk_window_set_opaque_region(window, region);
-
- cairo_region_destroy(region);
+ {
+ AutoReadLock lock(mOpaqueRegionLock);
+ cairo_region_t* region = nullptr;
+ if (!mOpaqueRegion.IsEmpty()) {
+ // NOTE(emilio): The opaque region is relative to our mContainer /
+ // mGdkWindow / inner window, but we're setting it on the top level
+ // GdkWindow / mShell.
+ //
+ // So we need to offset the rects by the position of mGdkWindow, in order
+ // for them to be in the right coordinate system.
+ GdkPoint offset{0, 0};
+ gdk_window_get_position(mGdkWindow, &offset.x, &offset.y);
+
+ region = cairo_region_create();
+
+ for (auto iter = mOpaqueRegion.RectIter(); !iter.Done(); iter.Next()) {
+ auto gdkRect = DevicePixelsToGdkRectRoundIn(iter.Get());
+ cairo_rectangle_int_t rect = {gdkRect.x + offset.x,
+ gdkRect.y + offset.y, gdkRect.width,
+ gdkRect.height};
+ cairo_region_union_rectangle(region, &rect);
+ }
+ }
+ gdk_window_set_opaque_region(window, region);
+ if (region) {
+ cairo_region_destroy(region);
+ }
+ }
#ifdef MOZ_WAYLAND
if (GdkIsWaylandDisplay()) {
- moz_container_wayland_update_opaque_region(mContainer, radius);
+ moz_container_wayland_update_opaque_region(mContainer);
}
#endif
-
- SetTitlebarRect();
}
bool nsWindow::IsChromeWindowTitlebar() {
@@ -7181,24 +7191,6 @@ nsresult nsWindow::UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
return NS_OK;
}
-#define TITLEBAR_HEIGHT 10
-
-void nsWindow::SetTitlebarRect() {
- MutexAutoLock lock(mTitlebarRectMutex);
-
- if (!mGdkWindow || !DoDrawTilebarCorners()) {
- mTitlebarRect = LayoutDeviceIntRect();
- return;
- }
- mTitlebarRect = LayoutDeviceIntRect(0, 0, mBounds.width,
- GdkCeiledScaleFactor() * TITLEBAR_HEIGHT);
-}
-
-LayoutDeviceIntRect nsWindow::GetTitlebarRect() {
- MutexAutoLock lock(mTitlebarRectMutex);
- return mTitlebarRect;
-}
-
void nsWindow::UpdateTitlebarTransparencyBitmap() {
NS_ASSERTION(mTransparencyBitmapForTitlebar,
"Transparency bitmap is already used to draw window shape");
@@ -8243,7 +8235,9 @@ static void toplevel_window_size_allocate_cb(GtkWidget* widget,
return;
}
- window->UpdateTopLevelOpaqueRegion();
+ // NOTE(emilio): We need to do this here to override GTK's own opaque region
+ // setting (which would clobber ours).
+ window->UpdateOpaqueRegionInternal();
}
static gboolean delete_event_cb(GtkWidget* widget, GdkEventAny* event) {
@@ -9180,9 +9174,11 @@ void nsWindow::SetDrawsInTitlebar(bool aState) {
} else {
ClearTransparencyBitmap();
}
- } else {
- SetTitlebarRect();
}
+
+ // Recompute the input region (which should generally be null, but this is
+ // enough to work around bug 1844497, which is probably a gtk bug).
+ SetInputRegion(mInputRegion);
}
GtkWindow* nsWindow::GetCurrentTopmostWindow() const {
@@ -9249,6 +9245,16 @@ GdkRectangle nsWindow::DevicePixelsToGdkRectRoundOut(
return {x, y, right - x, bottom - y};
}
+GdkRectangle nsWindow::DevicePixelsToGdkRectRoundIn(
+ const LayoutDeviceIntRect& aRect) {
+ double scale = FractionalScaleFactor();
+ int x = ceil(aRect.x / scale);
+ int y = ceil(aRect.y / scale);
+ int right = floor((aRect.x + aRect.width) / scale);
+ int bottom = floor((aRect.y + aRect.height) / scale);
+ return {x, y, std::max(right - x, 0), std::max(bottom - y, 0)};
+}
+
GdkRectangle nsWindow::DevicePixelsToGdkSizeRoundUp(
const LayoutDeviceIntSize& aSize) {
double scale = FractionalScaleFactor();
@@ -9843,9 +9849,7 @@ void nsWindow::LockNativePointer() {
return;
}
- if (mLockedPointer || mRelativePointer) {
- UnlockNativePointer();
- }
+ UnlockNativePointer();
mLockedPointer = zwp_pointer_constraints_v1_lock_pointer(
pointerConstraints, surface, pointer, nullptr,
@@ -9869,9 +9873,6 @@ void nsWindow::LockNativePointer() {
}
void nsWindow::UnlockNativePointer() {
- if (!GdkIsWaylandDisplay()) {
- return;
- }
if (mRelativePointer) {
zwp_relative_pointer_v1_destroy(mRelativePointer);
mRelativePointer = nullptr;
diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
index 25d68129d8..1dd1f1dce8 100644
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -19,6 +19,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/TouchEvents.h"
#include "mozilla/UniquePtr.h"
+#include "mozilla/RWLock.h"
#include "mozilla/widget/WindowSurface.h"
#include "mozilla/widget/WindowSurfaceProvider.h"
#include "nsBaseWidget.h"
@@ -257,7 +258,9 @@ class nsWindow final : public nsBaseWidget {
gint GetInputRegionMarginInGdkCoords();
- void UpdateTopLevelOpaqueRegion();
+ void UpdateOpaqueRegionInternal();
+ void UpdateOpaqueRegion(const LayoutDeviceIntRegion&) override;
+ LayoutDeviceIntRegion GetOpaqueRegion() const;
already_AddRefed<mozilla::gfx::DrawTarget> StartRemoteDrawingInRegion(
const LayoutDeviceIntRegion& aInvalidRegion,
@@ -369,9 +372,7 @@ class nsWindow final : public nsBaseWidget {
nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override;
void SetDrawsInTitlebar(bool aState);
- void SetTitlebarRect();
mozilla::LayoutDeviceIntCoord GetTitlebarRadius();
- LayoutDeviceIntRect GetTitlebarRect();
void UpdateWindowDraggingRegion(
const LayoutDeviceIntRegion& aRegion) override;
@@ -389,6 +390,7 @@ class nsWindow final : public nsBaseWidget {
GdkPoint DevicePixelsToGdkPointRoundDown(const LayoutDeviceIntPoint&);
GdkRectangle DevicePixelsToGdkSizeRoundUp(const LayoutDeviceIntSize&);
GdkRectangle DevicePixelsToGdkRectRoundOut(const LayoutDeviceIntRect&);
+ GdkRectangle DevicePixelsToGdkRectRoundIn(const LayoutDeviceIntRect&);
// From GDK
int GdkCoordToDevicePixels(gint);
@@ -631,9 +633,6 @@ class nsWindow final : public nsBaseWidget {
// If true, draw our own window titlebar.
bool mDrawInTitlebar = false;
- mozilla::Mutex mTitlebarRectMutex;
- LayoutDeviceIntRect mTitlebarRect MOZ_GUARDED_BY(mTitlebarRectMutex);
-
// This mutex protect window visibility changes.
mozilla::Mutex mWindowVisibilityMutex;
@@ -1018,6 +1017,8 @@ class nsWindow final : public nsBaseWidget {
// Running in kiosk mode and requested to stay on specified monitor.
// If monitor is removed minimize the window.
mozilla::Maybe<int> mKioskMonitor;
+ LayoutDeviceIntRegion mOpaqueRegion MOZ_GUARDED_BY(mOpaqueRegionLock);
+ mutable mozilla::RWLock mOpaqueRegionLock{"nsWindow::mOpaqueRegion"};
};
#endif /* __nsWindow_h__ */
diff --git a/widget/headless/HeadlessLookAndFeelGTK.cpp b/widget/headless/HeadlessLookAndFeelGTK.cpp
index aa55bcc347..09938e1983 100644
--- a/widget/headless/HeadlessLookAndFeelGTK.cpp
+++ b/widget/headless/HeadlessLookAndFeelGTK.cpp
@@ -84,9 +84,6 @@ nsresult HeadlessLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
case IntID::TreeScrollLinesMax:
aResult = 3;
break;
- case IntID::TabFocusModel:
- aResult = nsIContent::eTabFocus_textControlsMask;
- break;
case IntID::ChosenMenuItemsShouldBlink:
aResult = 1;
break;
diff --git a/widget/nsBaseClipboard.cpp b/widget/nsBaseClipboard.cpp
index 9ffc53b4c2..1eb2e8e9e0 100644
--- a/widget/nsBaseClipboard.cpp
+++ b/widget/nsBaseClipboard.cpp
@@ -7,7 +7,6 @@
#include "ContentAnalysis.h"
#include "mozilla/Components.h"
-#include "mozilla/contentanalysis/ContentAnalysisIPCTypes.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/Document.h"
@@ -19,14 +18,12 @@
#include "mozilla/MoveOnlyFunction.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Services.h"
-#include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/StaticPrefs_widget.h"
#include "nsContentUtils.h"
#include "nsFocusManager.h"
#include "nsIClipboardOwner.h"
#include "nsIPromptService.h"
-#include "nsISupportsPrimitives.h"
#include "nsError.h"
#include "nsXPCOM.h"
@@ -38,6 +35,8 @@ using mozilla::dom::CanonicalBrowsingContext;
using mozilla::dom::ClipboardCapabilities;
using mozilla::dom::Document;
+mozilla::LazyLogModule gWidgetClipboardLog("WidgetClipboard");
+
static const int32_t kGetAvailableFlavorsRetryCount = 5;
namespace {
@@ -211,9 +210,11 @@ NS_IMPL_ISUPPORTS(nsBaseClipboard::AsyncSetClipboardData,
nsBaseClipboard::AsyncSetClipboardData::AsyncSetClipboardData(
int32_t aClipboardType, nsBaseClipboard* aClipboard,
+ mozilla::dom::WindowContext* aSettingWindowContext,
nsIAsyncClipboardRequestCallback* aCallback)
: mClipboardType(aClipboardType),
mClipboard(aClipboard),
+ mWindowContext(aSettingWindowContext),
mCallback(aCallback) {
MOZ_ASSERT(mClipboard);
MOZ_ASSERT(
@@ -247,7 +248,8 @@ nsBaseClipboard::AsyncSetClipboardData::SetData(nsITransferable* aTransferable,
RefPtr<AsyncSetClipboardData> request =
std::move(mClipboard->mPendingWriteRequests[mClipboardType]);
- nsresult rv = mClipboard->SetData(aTransferable, aOwner, mClipboardType);
+ nsresult rv = mClipboard->SetData(aTransferable, aOwner, mClipboardType,
+ mWindowContext);
MaybeNotifyCallback(rv);
return rv;
@@ -292,7 +294,8 @@ void nsBaseClipboard::RejectPendingAsyncSetDataRequestIfAny(
}
NS_IMETHODIMP nsBaseClipboard::AsyncSetData(
- int32_t aWhichClipboard, nsIAsyncClipboardRequestCallback* aCallback,
+ int32_t aWhichClipboard, mozilla::dom::WindowContext* aSettingWindowContext,
+ nsIAsyncClipboardRequestCallback* aCallback,
nsIAsyncSetClipboardData** _retval) {
MOZ_CLIPBOARD_LOG("%s: clipboard=%d", __FUNCTION__, aWhichClipboard);
@@ -308,241 +311,13 @@ NS_IMETHODIMP nsBaseClipboard::AsyncSetData(
// Create a new AsyncSetClipboardData.
RefPtr<AsyncSetClipboardData> request =
- mozilla::MakeRefPtr<AsyncSetClipboardData>(aWhichClipboard, this,
- aCallback);
+ mozilla::MakeRefPtr<AsyncSetClipboardData>(
+ aWhichClipboard, this, aSettingWindowContext, aCallback);
mPendingWriteRequests[aWhichClipboard] = request;
request.forget(_retval);
return NS_OK;
}
-namespace {
-class SafeContentAnalysisResultCallback final
- : public nsIContentAnalysisCallback {
- public:
- explicit SafeContentAnalysisResultCallback(
- std::function<void(RefPtr<nsIContentAnalysisResult>&&)> aResolver)
- : mResolver(std::move(aResolver)) {}
- void Callback(RefPtr<nsIContentAnalysisResult>&& aResult) {
- MOZ_ASSERT(mResolver, "Called SafeContentAnalysisResultCallback twice!");
- if (auto resolver = std::move(mResolver)) {
- resolver(std::move(aResult));
- }
- }
-
- NS_IMETHODIMP ContentResult(nsIContentAnalysisResponse* aResponse) override {
- using namespace mozilla::contentanalysis;
- RefPtr<ContentAnalysisResult> result =
- ContentAnalysisResult::FromContentAnalysisResponse(aResponse);
- Callback(result);
- return NS_OK;
- }
-
- NS_IMETHODIMP Error(nsresult aError) override {
- using namespace mozilla::contentanalysis;
- Callback(ContentAnalysisResult::FromNoResult(
- NoContentAnalysisResult::DENY_DUE_TO_OTHER_ERROR));
- return NS_OK;
- }
-
- NS_DECL_THREADSAFE_ISUPPORTS
- private:
- // Private destructor to force this to be allocated in a RefPtr, which is
- // necessary for safe usage.
- ~SafeContentAnalysisResultCallback() {
- MOZ_ASSERT(!mResolver, "SafeContentAnalysisResultCallback never called!");
- }
- mozilla::MoveOnlyFunction<void(RefPtr<nsIContentAnalysisResult>&&)> mResolver;
-};
-NS_IMPL_ISUPPORTS(SafeContentAnalysisResultCallback,
- nsIContentAnalysisCallback);
-} // namespace
-
-// Returning:
-// - true means a content analysis request was fired
-// - false means there is no text data in the transferable
-// - NoContentAnalysisResult means there was an error
-static mozilla::Result<bool, mozilla::contentanalysis::NoContentAnalysisResult>
-CheckClipboardContentAnalysisAsText(
- uint64_t aInnerWindowId, SafeContentAnalysisResultCallback* aResolver,
- nsIURI* aDocumentURI, nsIContentAnalysis* aContentAnalysis,
- nsITransferable* aTextTrans) {
- using namespace mozilla::contentanalysis;
-
- nsCOMPtr<nsISupports> transferData;
- if (NS_FAILED(aTextTrans->GetTransferData(kTextMime,
- getter_AddRefs(transferData)))) {
- return false;
- }
- nsCOMPtr<nsISupportsString> textData = do_QueryInterface(transferData);
- if (MOZ_UNLIKELY(!textData)) {
- return false;
- }
- nsString text;
- if (NS_FAILED(textData->GetData(text))) {
- return mozilla::Err(NoContentAnalysisResult::DENY_DUE_TO_OTHER_ERROR);
- }
- if (text.IsEmpty()) {
- // Content Analysis doesn't expect to analyze an empty string.
- // Just approve it.
- return true;
- }
- RefPtr<mozilla::dom::WindowGlobalParent> window =
- mozilla::dom::WindowGlobalParent::GetByInnerWindowId(aInnerWindowId);
- if (!window) {
- // The window has gone away in the meantime
- return mozilla::Err(NoContentAnalysisResult::DENY_DUE_TO_OTHER_ERROR);
- }
- nsCOMPtr<nsIContentAnalysisRequest> contentAnalysisRequest =
- new ContentAnalysisRequest(
- nsIContentAnalysisRequest::AnalysisType::eBulkDataEntry,
- std::move(text), false, EmptyCString(), aDocumentURI,
- nsIContentAnalysisRequest::OperationType::eClipboard, window);
- nsresult rv = aContentAnalysis->AnalyzeContentRequestCallback(
- contentAnalysisRequest, /* aAutoAcknowledge */ true, aResolver);
- if (NS_FAILED(rv)) {
- return mozilla::Err(NoContentAnalysisResult::DENY_DUE_TO_OTHER_ERROR);
- }
- return true;
-}
-
-// Returning:
-// - true means a content analysis request was fired
-// - false means there is no file data in the transferable
-// - NoContentAnalysisResult means there was an error
-static mozilla::Result<bool, mozilla::contentanalysis::NoContentAnalysisResult>
-CheckClipboardContentAnalysisAsFile(
- uint64_t aInnerWindowId, SafeContentAnalysisResultCallback* aResolver,
- nsIURI* aDocumentURI, nsIContentAnalysis* aContentAnalysis,
- nsITransferable* aFileTrans) {
- using namespace mozilla::contentanalysis;
-
- nsCOMPtr<nsISupports> transferData;
- nsresult rv =
- aFileTrans->GetTransferData(kFileMime, getter_AddRefs(transferData));
- nsString filePath;
- if (NS_SUCCEEDED(rv)) {
- if (nsCOMPtr<nsIFile> file = do_QueryInterface(transferData)) {
- rv = file->GetPath(filePath);
- } else {
- MOZ_ASSERT_UNREACHABLE("clipboard data had kFileMime but no nsIFile!");
- return mozilla::Err(NoContentAnalysisResult::DENY_DUE_TO_OTHER_ERROR);
- }
- }
- if (NS_FAILED(rv) || filePath.IsEmpty()) {
- return false;
- }
- RefPtr<mozilla::dom::WindowGlobalParent> window =
- mozilla::dom::WindowGlobalParent::GetByInnerWindowId(aInnerWindowId);
- if (!window) {
- // The window has gone away in the meantime
- return mozilla::Err(NoContentAnalysisResult::DENY_DUE_TO_OTHER_ERROR);
- }
- // Let the content analysis code calculate the digest
- nsCOMPtr<nsIContentAnalysisRequest> contentAnalysisRequest =
- new ContentAnalysisRequest(
- nsIContentAnalysisRequest::AnalysisType::eBulkDataEntry,
- std::move(filePath), true, EmptyCString(), aDocumentURI,
- nsIContentAnalysisRequest::OperationType::eCustomDisplayString,
- window);
- rv = aContentAnalysis->AnalyzeContentRequestCallback(
- contentAnalysisRequest,
- /* aAutoAcknowledge */ true, aResolver);
- if (NS_FAILED(rv)) {
- return mozilla::Err(NoContentAnalysisResult::DENY_DUE_TO_OTHER_ERROR);
- }
- return true;
-}
-
-static void CheckClipboardContentAnalysis(
- mozilla::dom::WindowGlobalParent* aWindow, nsITransferable* aTransferable,
- SafeContentAnalysisResultCallback* aResolver) {
- using namespace mozilla::contentanalysis;
-
- // Content analysis is only needed if an outside webpage has access to
- // the data. So, skip content analysis if there is:
- // - no associated window (for example, scripted clipboard read by system
- // code)
- // - the window is a chrome docshell
- // - the window is being rendered in the parent process (for example,
- // about:support and the like)
- if (!aWindow || aWindow->GetBrowsingContext()->IsChrome() ||
- aWindow->IsInProcess()) {
- aResolver->Callback(ContentAnalysisResult::FromNoResult(
- NoContentAnalysisResult::
- ALLOW_DUE_TO_CONTEXT_EXEMPT_FROM_CONTENT_ANALYSIS));
- return;
- }
- nsCOMPtr<nsIContentAnalysis> contentAnalysis =
- mozilla::components::nsIContentAnalysis::Service();
- if (!contentAnalysis) {
- aResolver->Callback(ContentAnalysisResult::FromNoResult(
- NoContentAnalysisResult::DENY_DUE_TO_OTHER_ERROR));
- return;
- }
-
- bool contentAnalysisIsActive;
- nsresult rv = contentAnalysis->GetIsActive(&contentAnalysisIsActive);
- if (MOZ_LIKELY(NS_FAILED(rv) || !contentAnalysisIsActive)) {
- aResolver->Callback(ContentAnalysisResult::FromNoResult(
- NoContentAnalysisResult::ALLOW_DUE_TO_CONTENT_ANALYSIS_NOT_ACTIVE));
- return;
- }
-
- nsCOMPtr<nsIURI> currentURI = aWindow->Canonical()->GetDocumentURI();
- uint64_t innerWindowId = aWindow->InnerWindowId();
- nsTArray<nsCString> flavors;
- rv = aTransferable->FlavorsTransferableCanExport(flavors);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- aResolver->Callback(ContentAnalysisResult::FromNoResult(
- NoContentAnalysisResult::DENY_DUE_TO_OTHER_ERROR));
- return;
- }
- bool keepChecking = true;
- if (flavors.Contains(kFileMime)) {
- auto fileResult = CheckClipboardContentAnalysisAsFile(
- innerWindowId, aResolver, currentURI, contentAnalysis, aTransferable);
-
- if (fileResult.isErr()) {
- aResolver->Callback(
- ContentAnalysisResult::FromNoResult(fileResult.unwrapErr()));
- return;
- }
- keepChecking = !fileResult.unwrap();
- }
- if (keepChecking) {
- // Failed to get the clipboard data as a file, so try as text
- auto textResult = CheckClipboardContentAnalysisAsText(
- innerWindowId, aResolver, currentURI, contentAnalysis, aTransferable);
- if (textResult.isErr()) {
- aResolver->Callback(
- ContentAnalysisResult::FromNoResult(textResult.unwrapErr()));
- return;
- }
- if (!textResult.unwrap()) {
- // Couldn't get file or text data from this
- aResolver->Callback(ContentAnalysisResult::FromNoResult(
- NoContentAnalysisResult::ALLOW_DUE_TO_COULD_NOT_GET_DATA));
- return;
- }
- }
-}
-
-static bool CheckClipboardContentAnalysisSync(
- mozilla::dom::WindowGlobalParent* aWindow,
- const nsCOMPtr<nsITransferable>& trans) {
- bool requestDone = false;
- RefPtr<nsIContentAnalysisResult> result;
- auto callback = mozilla::MakeRefPtr<SafeContentAnalysisResultCallback>(
- [&requestDone, &result](RefPtr<nsIContentAnalysisResult>&& aResult) {
- result = std::move(aResult);
- requestDone = true;
- });
- CheckClipboardContentAnalysis(aWindow, trans, callback);
- mozilla::SpinEventLoopUntil("CheckClipboardContentAnalysisSync"_ns,
- [&requestDone]() -> bool { return requestDone; });
- return result->GetShouldAllowContent();
-}
-
nsBaseClipboard::nsBaseClipboard(const ClipboardCapabilities& aClipboardCaps)
: mClipboardCaps(aClipboardCaps) {
using mozilla::MakeUnique;
@@ -574,9 +349,9 @@ NS_IMPL_ISUPPORTS(nsBaseClipboard, nsIClipboard)
* Sets the transferable object
*
*/
-NS_IMETHODIMP nsBaseClipboard::SetData(nsITransferable* aTransferable,
- nsIClipboardOwner* aOwner,
- int32_t aWhichClipboard) {
+NS_IMETHODIMP nsBaseClipboard::SetData(
+ nsITransferable* aTransferable, nsIClipboardOwner* aOwner,
+ int32_t aWhichClipboard, mozilla::dom::WindowContext* aWindowContext) {
NS_ASSERTION(aTransferable, "clipboard given a null transferable");
MOZ_CLIPBOARD_LOG("%s: clipboard=%d", __FUNCTION__, aWhichClipboard);
@@ -627,21 +402,22 @@ NS_IMETHODIMP nsBaseClipboard::SetData(nsITransferable* aTransferable,
return result.unwrapErr();
}
- clipboardCache->Update(aTransferable, aOwner, result.unwrap());
+ clipboardCache->Update(aTransferable, aOwner, result.unwrap(),
+ aWindowContext
+ ? mozilla::Some(aWindowContext->InnerWindowId())
+ : mozilla::Nothing());
return NS_OK;
}
nsresult nsBaseClipboard::GetDataFromClipboardCache(
nsITransferable* aTransferable, int32_t aClipboardType) {
MOZ_ASSERT(aTransferable);
- MOZ_ASSERT(nsIClipboard::IsClipboardTypeSupported(aClipboardType));
MOZ_ASSERT(mozilla::StaticPrefs::widget_clipboard_use_cached_data_enabled());
const auto* clipboardCache = GetClipboardCacheIfValid(aClipboardType);
if (!clipboardCache) {
return NS_ERROR_FAILURE;
}
-
return clipboardCache->GetData(aTransferable);
}
@@ -671,8 +447,10 @@ NS_IMETHODIMP nsBaseClipboard::GetData(
if (NS_SUCCEEDED(
GetDataFromClipboardCache(aTransferable, aWhichClipboard))) {
// maybe try to fill in more types? Is there a point?
- if (!CheckClipboardContentAnalysisSync(aWindowContext->Canonical(),
- aTransferable)) {
+ if (!mozilla::contentanalysis::ContentAnalysis::
+ CheckClipboardContentAnalysisSync(
+ this, aWindowContext->Canonical(), aTransferable,
+ aWhichClipboard)) {
aTransferable->ClearAllData();
return NS_ERROR_CONTENT_BLOCKED;
}
@@ -686,8 +464,9 @@ NS_IMETHODIMP nsBaseClipboard::GetData(
if (NS_FAILED(rv)) {
return rv;
}
- if (!CheckClipboardContentAnalysisSync(aWindowContext->Canonical(),
- aTransferable)) {
+ if (!mozilla::contentanalysis::ContentAnalysis::
+ CheckClipboardContentAnalysisSync(this, aWindowContext->Canonical(),
+ aTransferable, aWhichClipboard)) {
aTransferable->ClearAllData();
return NS_ERROR_CONTENT_BLOCKED;
}
@@ -795,7 +574,7 @@ NS_IMETHODIMP nsBaseClipboard::AsyncGetData(
nsCOMPtr<nsITransferable> trans = clipboardCache->GetTransferable();
MOZ_ASSERT(trans);
- if (nsCOMPtr<nsIPrincipal> principal = trans->GetRequestingPrincipal()) {
+ if (nsCOMPtr<nsIPrincipal> principal = trans->GetDataPrincipal()) {
if (aRequestingPrincipal->Subsumes(principal)) {
MOZ_CLIPBOARD_LOG("%s: native clipboard data is from same-origin page.",
__FUNCTION__);
@@ -1228,7 +1007,8 @@ NS_IMETHODIMP nsBaseClipboard::AsyncGetClipboardData::GetData(
MOZ_ASSERT(mClipboard);
auto contentAnalysisCallback =
- mozilla::MakeRefPtr<SafeContentAnalysisResultCallback>(
+ mozilla::MakeRefPtr<mozilla::contentanalysis::ContentAnalysis::
+ SafeContentAnalysisResultCallback>(
[transferable = nsCOMPtr{aTransferable},
callback = nsCOMPtr{aCallback}](
RefPtr<nsIContentAnalysisResult>&& aResult) {
@@ -1249,10 +1029,11 @@ NS_IMETHODIMP nsBaseClipboard::AsyncGetClipboardData::GetData(
MOZ_DIAGNOSTIC_ASSERT(clipboardCache->GetSequenceNumber() ==
mSequenceNumber);
if (NS_SUCCEEDED(clipboardCache->GetData(aTransferable))) {
- CheckClipboardContentAnalysis(mRequestingWindowContext
- ? mRequestingWindowContext->Canonical()
- : nullptr,
- aTransferable, contentAnalysisCallback);
+ mozilla::contentanalysis::ContentAnalysis::CheckClipboardContentAnalysis(
+ mClipboard,
+ mRequestingWindowContext ? mRequestingWindowContext->Canonical()
+ : nullptr,
+ aTransferable, mClipboardType, contentAnalysisCallback);
return NS_OK;
}
@@ -1278,11 +1059,13 @@ NS_IMETHODIMP nsBaseClipboard::AsyncGetClipboardData::GetData(
callback->OnComplete(NS_ERROR_FAILURE);
return;
}
- CheckClipboardContentAnalysis(
- self->mRequestingWindowContext
- ? self->mRequestingWindowContext->Canonical()
- : nullptr,
- transferable, contentAnalysisCallback);
+ mozilla::contentanalysis::ContentAnalysis::
+ CheckClipboardContentAnalysis(
+ self->mClipboard,
+ self->mRequestingWindowContext
+ ? self->mRequestingWindowContext->Canonical()
+ : nullptr,
+ transferable, self->mClipboardType, contentAnalysisCallback);
});
return NS_OK;
}
@@ -1320,6 +1103,13 @@ bool nsBaseClipboard::AsyncGetClipboardData::IsValid() {
return true;
}
+mozilla::Maybe<uint64_t> nsBaseClipboard::GetClipboardCacheInnerWindowId(
+ int32_t aClipboardType) {
+ auto* clipboardCache = GetClipboardCacheIfValid(aClipboardType);
+ return clipboardCache ? clipboardCache->GetInnerWindowId()
+ : mozilla::Nothing();
+}
+
nsBaseClipboard::ClipboardCache* nsBaseClipboard::GetClipboardCacheIfValid(
int32_t aClipboardType) {
MOZ_ASSERT(nsIClipboard::IsClipboardTypeSupported(aClipboardType));
diff --git a/widget/nsBaseClipboard.h b/widget/nsBaseClipboard.h
index ffa68d6240..625421c342 100644
--- a/widget/nsBaseClipboard.h
+++ b/widget/nsBaseClipboard.h
@@ -14,11 +14,11 @@
#include "nsITransferable.h"
#include "nsCOMPtr.h"
-static mozilla::LazyLogModule sWidgetClipboardLog("WidgetClipboard");
+extern mozilla::LazyLogModule gWidgetClipboardLog;
#define MOZ_CLIPBOARD_LOG(...) \
- MOZ_LOG(sWidgetClipboardLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
+ MOZ_LOG(gWidgetClipboardLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
#define MOZ_CLIPBOARD_LOG_ENABLED() \
- MOZ_LOG_TEST(sWidgetClipboardLog, mozilla::LogLevel::Debug)
+ MOZ_LOG_TEST(gWidgetClipboardLog, mozilla::LogLevel::Debug)
class nsITransferable;
class nsIClipboardOwner;
@@ -42,9 +42,12 @@ class nsBaseClipboard : public nsIClipboard {
NS_DECL_ISUPPORTS
// nsIClipboard
- NS_IMETHOD SetData(nsITransferable* aTransferable, nsIClipboardOwner* aOwner,
- int32_t aWhichClipboard) override final;
+ NS_IMETHOD SetData(
+ nsITransferable* aTransferable, nsIClipboardOwner* aOwner,
+ int32_t aWhichClipboard,
+ mozilla::dom::WindowContext* aWindowContext) override final;
NS_IMETHOD AsyncSetData(int32_t aWhichClipboard,
+ mozilla::dom::WindowContext* aSettingWindowContext,
nsIAsyncClipboardRequestCallback* aCallback,
nsIAsyncSetClipboardData** _retval) override final;
NS_IMETHOD GetData(
@@ -75,6 +78,9 @@ class nsBaseClipboard : public nsIClipboard {
using HasMatchingFlavorsCallback = mozilla::MoveOnlyFunction<void(
mozilla::Result<nsTArray<nsCString>, nsresult>)>;
+ mozilla::Maybe<uint64_t> GetClipboardCacheInnerWindowId(
+ int32_t aClipboardType);
+
protected:
virtual ~nsBaseClipboard();
@@ -106,6 +112,7 @@ class nsBaseClipboard : public nsIClipboard {
NS_DECL_NSIASYNCSETCLIPBOARDDATA
AsyncSetClipboardData(int32_t aClipboardType, nsBaseClipboard* aClipboard,
+ mozilla::dom::WindowContext* aRequestingWindowContext,
nsIAsyncClipboardRequestCallback* aCallback);
private:
@@ -123,6 +130,7 @@ class nsBaseClipboard : public nsIClipboard {
// NotifyCallback()) once nsBaseClipboard stops tracking us. This is
// also used to indicate whether this request is valid.
nsBaseClipboard* mClipboard;
+ RefPtr<mozilla::dom::WindowContext> mWindowContext;
// mCallback will be nullified once the callback is notified to ensure the
// callback is only notified once.
nsCOMPtr<nsIAsyncClipboardRequestCallback> mCallback;
@@ -172,22 +180,26 @@ class nsBaseClipboard : public nsIClipboard {
*/
void Clear();
void Update(nsITransferable* aTransferable,
- nsIClipboardOwner* aClipboardOwner, int32_t aSequenceNumber) {
+ nsIClipboardOwner* aClipboardOwner, int32_t aSequenceNumber,
+ mozilla::Maybe<uint64_t> aInnerWindowId) {
// Clear first to notify the old clipboard owner.
Clear();
mTransferable = aTransferable;
mClipboardOwner = aClipboardOwner;
mSequenceNumber = aSequenceNumber;
+ mInnerWindowId = aInnerWindowId;
}
nsITransferable* GetTransferable() const { return mTransferable; }
nsIClipboardOwner* GetClipboardOwner() const { return mClipboardOwner; }
int32_t GetSequenceNumber() const { return mSequenceNumber; }
+ mozilla::Maybe<uint64_t> GetInnerWindowId() const { return mInnerWindowId; }
nsresult GetData(nsITransferable* aTransferable) const;
private:
nsCOMPtr<nsITransferable> mTransferable;
nsCOMPtr<nsIClipboardOwner> mClipboardOwner;
int32_t mSequenceNumber = -1;
+ mozilla::Maybe<uint64_t> mInnerWindowId;
};
void MaybeRetryGetAvailableFlavors(
@@ -203,7 +215,6 @@ class nsBaseClipboard : public nsIClipboard {
int32_t aClipboardType);
nsresult GetDataFromClipboardCache(nsITransferable* aTransferable,
int32_t aClipboardType);
-
void RequestUserConfirmation(int32_t aClipboardType,
const nsTArray<nsCString>& aFlavorList,
mozilla::dom::WindowContext* aWindowContext,
diff --git a/widget/nsBaseDragService.cpp b/widget/nsBaseDragService.cpp
index 22ed844595..c79d5bbb6d 100644
--- a/widget/nsBaseDragService.cpp
+++ b/widget/nsBaseDragService.cpp
@@ -368,7 +368,7 @@ nsBaseDragService::InvokeDragSession(
nsCOMPtr<nsITransferable> trans =
do_CreateInstance("@mozilla.org/widget/transferable;1");
trans->Init(nullptr);
- trans->SetRequestingPrincipal(mSourceNode->NodePrincipal());
+ trans->SetDataPrincipal(mSourceNode->NodePrincipal());
trans->SetContentPolicyType(mContentPolicyType);
trans->SetCookieJarSettings(aCookieJarSettings);
mutableArray->AppendElement(trans);
@@ -378,8 +378,8 @@ nsBaseDragService::InvokeDragSession(
nsCOMPtr<nsITransferable> trans =
do_QueryElementAt(aTransferableArray, i);
if (trans) {
- // Set the requestingPrincipal on the transferable.
- trans->SetRequestingPrincipal(mSourceNode->NodePrincipal());
+ // Set the dataPrincipal on the transferable.
+ trans->SetDataPrincipal(mSourceNode->NodePrincipal());
trans->SetContentPolicyType(mContentPolicyType);
trans->SetCookieJarSettings(aCookieJarSettings);
}
diff --git a/widget/nsClipboardHelper.cpp b/widget/nsClipboardHelper.cpp
index 3439adef48..87e697a4c6 100644
--- a/widget/nsClipboardHelper.cpp
+++ b/widget/nsClipboardHelper.cpp
@@ -36,9 +36,10 @@ nsClipboardHelper::~nsClipboardHelper() {
*****************************************************************************/
NS_IMETHODIMP
-nsClipboardHelper::CopyStringToClipboard(const nsAString& aString,
- int32_t aClipboardID,
- SensitiveData aSensitive) {
+nsClipboardHelper::CopyStringToClipboard(
+ const nsAString& aString, int32_t aClipboardID,
+ mozilla::dom::WindowContext* aSettingWindowContext,
+ SensitiveData aSensitive) {
nsresult rv;
// get the clipboard
@@ -92,20 +93,22 @@ nsClipboardHelper::CopyStringToClipboard(const nsAString& aString,
NS_ENSURE_SUCCESS(rv, rv);
// put the transferable on the clipboard
- rv = clipboard->SetData(trans, nullptr, aClipboardID);
+ rv = clipboard->SetData(trans, nullptr, aClipboardID, aSettingWindowContext);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
-nsClipboardHelper::CopyString(const nsAString& aString,
- SensitiveData aSensitive) {
+nsClipboardHelper::CopyString(
+ const nsAString& aString,
+ mozilla::dom::WindowContext* aSettingWindowContext,
+ SensitiveData aSensitive) {
nsresult rv;
// copy to the global clipboard. it's bad if this fails in any way.
rv = CopyStringToClipboard(aString, nsIClipboard::kGlobalClipboard,
- aSensitive);
+ aSettingWindowContext, aSensitive);
NS_ENSURE_SUCCESS(rv, rv);
// unix also needs us to copy to the selection clipboard. this will
@@ -117,7 +120,8 @@ nsClipboardHelper::CopyString(const nsAString& aString,
// if this fails in any way other than "not being unix", we'll get
// the assertion we need in CopyStringToClipboard, and we needn't
// assert again here.
- CopyStringToClipboard(aString, nsIClipboard::kSelectionClipboard, aSensitive);
+ CopyStringToClipboard(aString, nsIClipboard::kSelectionClipboard,
+ aSettingWindowContext, aSensitive);
return NS_OK;
}
diff --git a/widget/nsClipboardProxy.cpp b/widget/nsClipboardProxy.cpp
index 3b27d5954d..5855374566 100644
--- a/widget/nsClipboardProxy.cpp
+++ b/widget/nsClipboardProxy.cpp
@@ -32,7 +32,8 @@ nsClipboardProxy::nsClipboardProxy() : mClipboardCaps(false, false, false) {}
NS_IMETHODIMP
nsClipboardProxy::SetData(nsITransferable* aTransferable,
- nsIClipboardOwner* anOwner, int32_t aWhichClipboard) {
+ nsIClipboardOwner* anOwner, int32_t aWhichClipboard,
+ mozilla::dom::WindowContext* aWindowContext) {
#if defined(ACCESSIBILITY) && defined(XP_WIN)
a11y::Compatibility::SuppressA11yForClipboardCopy();
#endif
@@ -41,17 +42,19 @@ nsClipboardProxy::SetData(nsITransferable* aTransferable,
IPCTransferable ipcTransferable;
nsContentUtils::TransferableToIPCTransferable(aTransferable, &ipcTransferable,
false, nullptr);
- child->SendSetClipboard(std::move(ipcTransferable), aWhichClipboard);
+ child->SendSetClipboard(std::move(ipcTransferable), aWhichClipboard,
+ aWindowContext);
return NS_OK;
}
NS_IMETHODIMP nsClipboardProxy::AsyncSetData(
- int32_t aWhichClipboard, nsIAsyncClipboardRequestCallback* aCallback,
+ int32_t aWhichClipboard, mozilla::dom::WindowContext* aSettingWindowContext,
+ nsIAsyncClipboardRequestCallback* aCallback,
nsIAsyncSetClipboardData** _retval) {
RefPtr<ClipboardWriteRequestChild> request =
MakeRefPtr<ClipboardWriteRequestChild>(aCallback);
ContentChild::GetSingleton()->SendPClipboardWriteRequestConstructor(
- request, aWhichClipboard);
+ request, aWhichClipboard, aSettingWindowContext);
request.forget(_retval);
return NS_OK;
}
@@ -69,12 +72,18 @@ nsClipboardProxy::GetData(nsITransferable* aTransferable,
nsTArray<nsCString> types;
aTransferable->FlavorsTransferableCanImport(types);
- IPCTransferableData transferable;
- ContentChild::GetSingleton()->SendGetClipboard(types, aWhichClipboard,
- aWindowContext, &transferable);
+ IPCTransferableDataOrError transferableOrError;
+ ContentChild::GetSingleton()->SendGetClipboard(
+ types, aWhichClipboard, aWindowContext, &transferableOrError);
+
+ if (transferableOrError.type() == IPCTransferableDataOrError::Tnsresult) {
+ MOZ_ASSERT(NS_FAILED(transferableOrError.get_nsresult()));
+ return transferableOrError.get_nsresult();
+ }
+
return nsContentUtils::IPCTransferableDataToTransferable(
- transferable, false /* aAddDataFlavor */, aTransferable,
- false /* aFilterUnknownFlavors */);
+ transferableOrError.get_IPCTransferableData(), false /* aAddDataFlavor */,
+ aTransferable, false /* aFilterUnknownFlavors */);
}
namespace {
diff --git a/widget/nsIBaseWindow.idl b/widget/nsIBaseWindow.idl
index 3cf7193788..3e0dadbdd5 100644
--- a/widget/nsIBaseWindow.idl
+++ b/widget/nsIBaseWindow.idl
@@ -161,7 +161,7 @@ interface nsIBaseWindow : nsISupports
*
* @see DimensionRequest
*/
- void setDimensions(in DimensionRequest aRequest);
+ [noscript] void setDimensions(in DimensionRequest aRequest);
/**
* Gets the dimensions of the window. The caller may pass nullptr for any
@@ -178,7 +178,7 @@ interface nsIBaseWindow : nsISupports
*
* @see DimensionRequest
*/
- void getDimensions(in DimensionKind aDimensionKind, out long aX, out long aY, out long aCX, out long aCY);
+ [noscript] void getDimensions(in DimensionKind aDimensionKind, out long aX, out long aY, out long aCX, out long aCY);
/**
* Tell the window to repaint itself
@@ -210,7 +210,7 @@ interface nsIBaseWindow : nsISupports
On controls that don't support setting nativeWindow parents, setting this
will return a NS_ERROR_NOT_IMPLEMENTED error.
*/
- attribute nativeWindow parentNativeWindow;
+ [noscript] attribute nativeWindow parentNativeWindow;
/*
This is the handle (HWND, GdkWindow*, ...) to the native window of the
diff --git a/widget/nsIClipboard.idl b/widget/nsIClipboard.idl
index a34f0f9298..fc1f8bf8c3 100644
--- a/widget/nsIClipboard.idl
+++ b/widget/nsIClipboard.idl
@@ -115,20 +115,28 @@ interface nsIClipboard : nsISupports
* @param aTransferable The transferable
* @param anOwner The owner of the transferable
* @param aWhichClipboard Specifies the clipboard to which this operation applies.
- * @result NS_Ok if no errors
+ * @param aSettingWindowContext [optional]
+ * The window context that is setting the clipboard, if any. This is used
+ * to possibly bypass Content Analysis if a set clipboard and get clipboard
+ * operation are done on the same page.
+ * @result NS_OK if no errors
*/
- void setData ( in nsITransferable aTransferable, in nsIClipboardOwner anOwner,
- in long aWhichClipboard ) ;
+ void setData (in nsITransferable aTransferable, in nsIClipboardOwner anOwner,
+ in long aWhichClipboard, [optional] in WindowContext aSettingWindowContext);
/**
- * Requests setting data to the native clipboard. The acutal set occur
+ * Requests setting data to the native clipboard. The actual set occurs
* when the data is provided by calling nsIAsyncSetClipboardData::setData().
* The result will be notified by nsIClipboardCallback. A new set request
* will cancel any prior pending requests, if any exist.
*
* @param aWhichClipboard
* Specifies the clipboard to which this operation applies.
+ * @param aSettingWindowContext [optional]
+ * The window context that is setting the clipboard, if any. This is used
+ * to possibly bypass Content Analysis if a set clipboard and get clipboard
+ * operation are done on the same page.
* @param aCallback [optional]
* The callback object that will be notified upon completion.
* @return nsIAsyncSetClipboardData
@@ -136,6 +144,7 @@ interface nsIClipboard : nsISupports
* data is provided by calling nsIAsyncSetClipboardData::setData().
*/
nsIAsyncSetClipboardData asyncSetData(in long aWhichClipboard,
+ [optional] in WindowContext aSettingWindowContext,
[optional] in nsIAsyncClipboardRequestCallback aCallback);
/**
diff --git a/widget/nsIClipboardHelper.idl b/widget/nsIClipboardHelper.idl
index ed4af112f1..370c652b31 100644
--- a/widget/nsIClipboardHelper.idl
+++ b/widget/nsIClipboardHelper.idl
@@ -29,17 +29,29 @@ interface nsIClipboardHelper : nsISupports
* @param aString, the string to copy to the clipboard
* @param aClipboardID, the ID of the clipboard to copy to
* (eg. kSelectionClipboard -- see nsIClipboard.idl)
+ * @param aSettingWindowContext
+ * The window context that is setting the clipboard, if any. This is used
+ * to possibly bypass Content Analysis if a set clipboard and get clipboard
+ * operation are done on the same page.
* @param aSensitive, optional flag to indicate that data is sensitive, like a password.
* That will exclude data from Cloud Clipboard/Clipboard History on Windows.
*/
void copyStringToClipboard(in AString aString, in long aClipboardID,
+ [optional] in WindowContext aSettingWindowContext,
[optional, default(NotSensitive)] in nsIClipboardHelper_SensitiveData aSensitive);
/**
* copy string to (default) clipboard
*
* @param aString, the string to copy to the clipboard
+ * @param aSettingWindowContext
+ * The window context that is setting the clipboard, if any. This is used
+ * to possibly bypass Content Analysis if a set clipboard and get clipboard
+ * operation are done on the same page.
+ * @param aSensitive, optional flag to indicate that data is sensitive, like a password.
+ * That will exclude data from Cloud Clipboard/Clipboard History on Windows.
*/
void copyString(in AString aString,
+ [optional] in WindowContext aSettingWindowContext,
[optional, default(NotSensitive)] in nsIClipboardHelper_SensitiveData aSensitive);
};
diff --git a/widget/nsIDeviceContextSpec.cpp b/widget/nsIDeviceContextSpec.cpp
index 5ab442415d..2ec5946bb0 100644
--- a/widget/nsIDeviceContextSpec.cpp
+++ b/widget/nsIDeviceContextSpec.cpp
@@ -58,8 +58,8 @@ gfxPoint nsIDeviceContextSpec::GetPrintingTranslate() {
}
RefPtr<PrintEndDocumentPromise>
-nsIDeviceContextSpec::EndDocumentPromiseFromResult(nsresult aResult,
- const char* aSite) {
+nsIDeviceContextSpec::EndDocumentPromiseFromResult(
+ nsresult aResult, mozilla::StaticString aSite) {
return NS_SUCCEEDED(aResult)
? PrintEndDocumentPromise::CreateAndResolve(true, aSite)
: PrintEndDocumentPromise::CreateAndReject(aResult, aSite);
diff --git a/widget/nsIDeviceContextSpec.h b/widget/nsIDeviceContextSpec.h
index 6afe4ea850..33ebaecd62 100644
--- a/widget/nsIDeviceContextSpec.h
+++ b/widget/nsIDeviceContextSpec.h
@@ -95,7 +95,7 @@ class nsIDeviceContextSpec : public nsISupports {
const char* aCallSite, AsyncEndDocumentFunction aFunction);
static RefPtr<mozilla::gfx::PrintEndDocumentPromise>
- EndDocumentPromiseFromResult(nsresult aResult, const char* aSite);
+ EndDocumentPromiseFromResult(nsresult aResult, mozilla::StaticString aSite);
nsCOMPtr<nsIPrintSettings> mPrintSettings;
diff --git a/widget/nsIDragService.idl b/widget/nsIDragService.idl
index a35d3128a8..619c8f8a82 100644
--- a/widget/nsIDragService.idl
+++ b/widget/nsIDragService.idl
@@ -126,7 +126,7 @@ interface nsIDragService : nsISupports
*
* Note: This method is deprecated for non-native code.
*/
- [can_run_script]
+ [noscript, can_run_script]
void invokeDragSessionWithSelection(in Selection aSelection,
in nsIPrincipal aPrincipal,
in nsIContentSecurityPolicy aCsp,
diff --git a/widget/nsIJumpListBuilder.idl b/widget/nsIJumpListBuilder.idl
index 1b7b93e5e7..a52f09d7da 100644
--- a/widget/nsIJumpListBuilder.idl
+++ b/widget/nsIJumpListBuilder.idl
@@ -100,9 +100,9 @@ interface nsIJumpListBuilder : nsISupports
*/
[implicit_jscontext]
Promise populateJumpList(
- in Array<jsval> aTaskDescriptions,
+ in jsval aTaskDescriptions,
in AString aCustomTitle,
- in Array<jsval> aCustomDescriptions
+ in jsval aCustomDescriptions
);
/**
diff --git a/widget/nsIScreen.idl b/widget/nsIScreen.idl
index af8371edb3..619b8bc284 100644
--- a/widget/nsIScreen.idl
+++ b/widget/nsIScreen.idl
@@ -75,7 +75,7 @@ interface nsIScreen : nsISupports
/**
* ScreenColorGamut is native type, which cannot be declared [infallible].
*/
- readonly attribute ScreenColorGamut colorGamut;
+ [noscript] readonly attribute ScreenColorGamut colorGamut;
/**
* The number of device pixels per desktop pixel for this screen (for
diff --git a/widget/nsITransferable.idl b/widget/nsITransferable.idl
index 0a8419c4bb..c6e424d7cb 100644
--- a/widget/nsITransferable.idl
+++ b/widget/nsITransferable.idl
@@ -203,9 +203,8 @@ interface nsITransferable : nsISupports
* node principal of the source DOM node from which this transferable was
* created, or the principal of the global from which this transferable was
* created.
- * XXXedgar: Rename it to something more generic, bug 1867636.
*/
- [notxpcom, nostdcall] attribute nsIPrincipal requestingPrincipal;
+ [notxpcom, nostdcall] attribute nsIPrincipal dataPrincipal;
/**
* the contentPolicyType for this transferable.
diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h
index 06eab558eb..29c127c146 100644
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1397,6 +1397,8 @@ class nsIWidget : public nsISupports {
const nsAString& xulWinClass,
const nsAString& xulWinName) = 0;
+ virtual void SetIsEarlyBlankWindow(bool) {}
+
/**
* Enables/Disables system capture of any and all events that would cause a
* popup to be rolled up. aListener should be set to a non-null value for
diff --git a/widget/nsIWidgetListener.cpp b/widget/nsIWidgetListener.cpp
index b9f236f159..13eba4eeeb 100644
--- a/widget/nsIWidgetListener.cpp
+++ b/widget/nsIWidgetListener.cpp
@@ -36,8 +36,6 @@ void nsIWidgetListener::SizeModeChanged(nsSizeMode aSizeMode) {}
void nsIWidgetListener::SafeAreaInsetsChanged(const mozilla::ScreenIntMargin&) {
}
-void nsIWidgetListener::UIResolutionChanged() {}
-
#if defined(MOZ_WIDGET_ANDROID)
void nsIWidgetListener::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight) {
}
diff --git a/widget/nsIWidgetListener.h b/widget/nsIWidgetListener.h
index aff753aaec..950d4b4622 100644
--- a/widget/nsIWidgetListener.h
+++ b/widget/nsIWidgetListener.h
@@ -81,12 +81,6 @@ class nsIWidgetListener {
*/
virtual void SizeModeChanged(nsSizeMode aSizeMode);
- /**
- * Called when the DPI (device resolution scaling factor) is changed,
- * such that UI elements may need to be rescaled.
- */
- virtual void UIResolutionChanged();
-
#if defined(MOZ_WIDGET_ANDROID)
virtual void DynamicToolbarMaxHeightChanged(mozilla::ScreenIntCoord aHeight);
virtual void DynamicToolbarOffsetChanged(mozilla::ScreenIntCoord aOffset);
diff --git a/widget/nsNativeTheme.cpp b/widget/nsNativeTheme.cpp
index 6900414ff3..fcb30f5a7b 100644
--- a/widget/nsNativeTheme.cpp
+++ b/widget/nsNativeTheme.cpp
@@ -120,6 +120,7 @@ NS_IMPL_ISUPPORTS(nsNativeTheme, nsITimerCallback, nsINamed)
case StyleAppearance::Menulist:
case StyleAppearance::NumberInput:
case StyleAppearance::Textfield:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Searchfield:
case StyleAppearance::Textarea: {
if (CheckBooleanAttr(aFrame, nsGkAtoms::focused)) {
diff --git a/widget/nsTransferable.cpp b/widget/nsTransferable.cpp
index 58a8630801..b1e1f60ade 100644
--- a/widget/nsTransferable.cpp
+++ b/widget/nsTransferable.cpp
@@ -511,17 +511,16 @@ void nsTransferable::SetIsPrivateData(bool aIsPrivateData) {
mPrivateData = aIsPrivateData;
}
-nsIPrincipal* nsTransferable::GetRequestingPrincipal() {
+nsIPrincipal* nsTransferable::GetDataPrincipal() {
MOZ_ASSERT(mInitialized);
- return mRequestingPrincipal;
+ return mDataPrincipal;
}
-void nsTransferable::SetRequestingPrincipal(
- nsIPrincipal* aRequestingPrincipal) {
+void nsTransferable::SetDataPrincipal(nsIPrincipal* aDataPrincipal) {
MOZ_ASSERT(mInitialized);
- mRequestingPrincipal = aRequestingPrincipal;
+ mDataPrincipal = aDataPrincipal;
}
nsContentPolicyType nsTransferable::GetContentPolicyType() {
diff --git a/widget/nsTransferable.h b/widget/nsTransferable.h
index 02f2b0459c..191be3e74a 100644
--- a/widget/nsTransferable.h
+++ b/widget/nsTransferable.h
@@ -80,7 +80,7 @@ class nsTransferable : public nsITransferable {
nsTArray<DataStruct> mDataArray;
nsCOMPtr<nsIFormatConverter> mFormatConv;
bool mPrivateData;
- nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
+ nsCOMPtr<nsIPrincipal> mDataPrincipal;
nsContentPolicyType mContentPolicyType;
nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
diff --git a/widget/nsXPLookAndFeel.cpp b/widget/nsXPLookAndFeel.cpp
index 0c5b5207f2..cb34f7b067 100644
--- a/widget/nsXPLookAndFeel.cpp
+++ b/widget/nsXPLookAndFeel.cpp
@@ -146,7 +146,6 @@ static const char sIntPrefs[][45] = {
"ui.treeLazyScrollDelay",
"ui.treeScrollDelay",
"ui.treeScrollLinesMax",
- "accessibility.tabfocus", // Weird one...
"ui.chosenMenuItemsShouldBlink",
"ui.windowsAccentColorInTitlebar",
"ui.macBigSurTheme",
@@ -527,9 +526,6 @@ void nsXPLookAndFeel::Init() {
// for each types. Then, we could reduce the unnecessary loop from
// nsXPLookAndFeel::OnPrefChanged().
Preferences::RegisterPrefixCallback(OnPrefChanged, "ui.");
- // We really do just want the accessibility.tabfocus pref, not other prefs
- // that start with that string.
- Preferences::RegisterCallback(OnPrefChanged, "accessibility.tabfocus");
for (const auto& pref : kMediaQueryPrefs) {
Preferences::RegisterCallback(
@@ -1237,8 +1233,7 @@ void LookAndFeel::DoHandleGlobalThemeChange() {
//
// We can use the *DoNotUseDirectly functions directly here, because we want
// to notify all possible themes in a given process (but just once).
- if (XRE_IsParentProcess() ||
- !StaticPrefs::widget_non_native_theme_enabled()) {
+ if (XRE_IsParentProcess()) {
if (nsCOMPtr<nsITheme> theme = do_GetNativeThemeDoNotUseDirectly()) {
theme->ThemeChanged();
}
diff --git a/widget/reftests/reftest.list b/widget/reftests/reftest.list
index dc788a31aa..2170fec443 100644
--- a/widget/reftests/reftest.list
+++ b/widget/reftests/reftest.list
@@ -6,4 +6,4 @@ load 664925.xhtml
pref(apz.allow_zooming,true) pref(ui.useOverlayScrollbars,0) skip-if(!cocoaWidget) != scaled-scrollbar.html about:blank
# Test that scrollbar buttons are inhibited on Linux using the non-native theme.
-skip-if(!gtkWidget) pref(widget.non-native-theme.enabled,true) test-pref(ui.scrollArrowStyle,4097) ref-pref(ui.scrollArrowStyle,0) == scrollbar-buttons.html scrollbar-buttons.html
+skip-if(!gtkWidget) test-pref(ui.scrollArrowStyle,4097) ref-pref(ui.scrollArrowStyle,0) == scrollbar-buttons.html scrollbar-buttons.html
diff --git a/widget/tests/browser/browser_test_InputContextURI.js b/widget/tests/browser/browser_test_InputContextURI.js
index 52f05d90f9..ccdfc86def 100644
--- a/widget/tests/browser/browser_test_InputContextURI.js
+++ b/widget/tests/browser/browser_test_InputContextURI.js
@@ -86,6 +86,9 @@ add_task(async () => {
await test_url_bar_url("check after remote content sets the URI");
});
add_task(async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.security.https_first", false]],
+ });
await test_input_in_http_or_https(false);
});
diff --git a/widget/tests/browser/browser_test_scrollbar_colors.js b/widget/tests/browser/browser_test_scrollbar_colors.js
index 2152412071..458cadd84e 100644
--- a/widget/tests/browser/browser_test_scrollbar_colors.js
+++ b/widget/tests/browser/browser_test_scrollbar_colors.js
@@ -27,15 +27,6 @@ add_task(async () => {
// == Native theme ==
- const WIN_REFERENCES = [
- // Yellow background
- ["255,255,0", 6889],
- // Blue scrollbar face
- ["0,0,255", 540],
- // Cyan scrollbar track
- ["0,255,255", 2487],
- ];
-
const MAC_REFERENCES = [
// Yellow background
["255,255,0", 7225],
@@ -45,19 +36,9 @@ add_task(async () => {
["0,255,255", 1760],
];
- // Values have been updated from 8100, 720, 1180 for linux1804
- const LINUX_REFERENCES = [
- // Yellow background
- ["255,255,0", 7744],
- // Blue scrollbar face
- ["0,0,255", 1104],
- // Cyan scrollbar track
- ["0,255,255", 1152],
- ];
-
// == Non-native theme ==
- const WIN10_NNT_REFERENCES = [
+ const WIN10_REFERENCES = [
// Yellow background
["255,255,0", 6889],
// Blue scrollbar face
@@ -66,7 +47,7 @@ add_task(async () => {
["0,255,255", 2355],
];
- const WIN11_NNT_REFERENCES = [
+ const WIN11_REFERENCES = [
// Yellow background
["255,255,0", 6889],
// Blue scrollbar face
@@ -75,9 +56,7 @@ add_task(async () => {
["0,255,255", 2787],
];
- const MAC_NNT_REFERENCES = MAC_REFERENCES;
-
- const LINUX_NNT_REFERENCES = [
+ const LINUX_REFERENCES = [
// Yellow background
["255,255,0", 7744],
// Blue scrollbar face
@@ -116,23 +95,19 @@ add_task(async () => {
let canvas = snapshotRect(content.window, outerRect);
let stats = countPixels(canvas);
- let isNNT = SpecialPowers.getBoolPref("widget.non-native-theme.enabled");
-
let references;
if (content.navigator.platform.startsWith("Win")) {
- if (!isNNT) {
- references = WIN_REFERENCES;
- } else if (WindowsVersionInfo.get().buildNumber >= 22000) {
- // Windows 11 NNT
- references = WIN11_NNT_REFERENCES;
+ if (WindowsVersionInfo.get().buildNumber >= 22000) {
+ // Windows 11
+ references = WIN11_REFERENCES;
} else {
- // Windows 10 NNT
- references = WIN10_NNT_REFERENCES;
+ // Windows 10
+ references = WIN10_REFERENCES;
}
} else if (content.navigator.platform.startsWith("Mac")) {
- references = isNNT ? MAC_NNT_REFERENCES : MAC_REFERENCES;
+ references = MAC_REFERENCES;
} else if (content.navigator.platform.startsWith("Linux")) {
- references = isNNT ? LINUX_NNT_REFERENCES : LINUX_REFERENCES;
+ references = LINUX_REFERENCES;
} else {
ok(false, "Unsupported platform");
}
diff --git a/widget/tests/file_test_clipboard.js b/widget/tests/file_test_clipboard.js
index 76bdbaa84d..4e720b6383 100644
--- a/widget/tests/file_test_clipboard.js
+++ b/widget/tests/file_test_clipboard.js
@@ -149,5 +149,20 @@ clipboardTypes.forEach(function (clipboardType) {
// Clear all clipboard data.
cleanupAllClipboard();
});
+
+ add_task(function test_unsupport_flavor() {
+ try {
+ is(
+ getClipboardData("foo/bar", clipboardType),
+ null,
+ `Test getData for clipboard type ${clipboardType}`
+ );
+ } catch (e) {
+ ok(
+ false,
+ `getData should not throw error for clipboard type ${clipboardType}`
+ );
+ }
+ });
}
});
diff --git a/widget/tests/file_test_clipboard_asyncSetData.js b/widget/tests/file_test_clipboard_asyncSetData.js
index cceecd2c44..5eb73f90fa 100644
--- a/widget/tests/file_test_clipboard_asyncSetData.js
+++ b/widget/tests/file_test_clipboard_asyncSetData.js
@@ -21,7 +21,7 @@ clipboardTypes.forEach(function (type) {
let priorResult;
let priorRequest;
let priorPromise = new Promise(resolve => {
- priorRequest = clipboard.asyncSetData(type, {
+ priorRequest = clipboard.asyncSetData(type, null, {
QueryInterface: SpecialPowers.ChromeUtils.generateQI([
"nsIAsyncSetClipboardDataCallback",
]),
@@ -119,7 +119,7 @@ clipboardTypes.forEach(function (type) {
// Create a pending asyncSetData request
let result;
- let request = clipboard.asyncSetData(type, rv => {
+ let request = clipboard.asyncSetData(type, null, rv => {
result = rv;
});
diff --git a/widget/uikit/nsLookAndFeel.mm b/widget/uikit/nsLookAndFeel.mm
index 51a9a95b52..f720a8681e 100644
--- a/widget/uikit/nsLookAndFeel.mm
+++ b/widget/uikit/nsLookAndFeel.mm
@@ -282,9 +282,6 @@ nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
case IntID::TreeScrollLinesMax:
aResult = 3;
break;
- case IntID::TabFocusModel:
- aResult = 1; // default to just textboxes
- break;
case IntID::ScrollToClick:
aResult = 0;
break;
diff --git a/widget/windows/CompositorWidgetParent.cpp b/widget/windows/CompositorWidgetParent.cpp
index b25d30d9d5..d38125f4ca 100644
--- a/widget/windows/CompositorWidgetParent.cpp
+++ b/widget/windows/CompositorWidgetParent.cpp
@@ -149,16 +149,12 @@ mozilla::ipc::IPCResult CompositorWidgetParent::RecvNotifyVisibilityUpdated(
return IPC_OK();
}
-nsSizeMode CompositorWidgetParent::CompositorWidgetParent::GetWindowSizeMode()
- const {
- nsSizeMode sizeMode = mSizeMode;
- return sizeMode;
+nsSizeMode CompositorWidgetParent::GetWindowSizeMode() const {
+ return mSizeMode;
}
-bool CompositorWidgetParent::CompositorWidgetParent::GetWindowIsFullyOccluded()
- const {
- bool isFullyOccluded = mIsFullyOccluded;
- return isFullyOccluded;
+bool CompositorWidgetParent::GetWindowIsFullyOccluded() const {
+ return mIsFullyOccluded;
}
mozilla::ipc::IPCResult CompositorWidgetParent::RecvClearTransparentWindow() {
diff --git a/widget/windows/GfxInfo.cpp b/widget/windows/GfxInfo.cpp
index 6d8429f1cc..bb9b19e3a1 100644
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -1808,6 +1808,12 @@ const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() {
V(10, 18, 15, 4256), V(10, 18, 15, 4293), "FEATURE_FAILURE_BUG_1833809",
"Intel driver 10.18.15.*");
+ APPEND_TO_DRIVER_BLOCKLIST2(
+ OperatingSystem::Windows, DeviceFamily::IntelGen12,
+ nsIGfxInfo::FEATURE_REUSE_DECODER_DEVICE,
+ nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
+ V(0, 0, 0, 0), "FEATURE_FAILURE_BUG_1896823");
+
////////////////////////////////////
// FEATURE_OVERLAY_VP_AUTO_HDR
diff --git a/widget/windows/JumpListBuilder.cpp b/widget/windows/JumpListBuilder.cpp
index e25c8c038f..69a46d5aad 100644
--- a/widget/windows/JumpListBuilder.cpp
+++ b/widget/windows/JumpListBuilder.cpp
@@ -18,6 +18,17 @@
#include "nsServiceManagerUtils.h"
#include "WinUtils.h"
+#ifdef __MINGW32__
+// The PKEY_Link_Arguments property key does not exist in the MINGW32
+// build configuration, so we define it ourselves here.
+# define INITGUID // This alters the behavior of DEFINE_PROPERTYKEY so that
+ // we define PKEY_Link_Arguments rather than declare it.
+# include <propkeydef.h> // For DEFINE_PROPERTYKEY() definition
+DEFINE_PROPERTYKEY(PKEY_Link_Arguments, 0x436F2667, 0x14E2, 0x4FEB, 0xB3, 0x0A,
+ 0x14, 0x6C, 0x53, 0xB5, 0xB6, 0x74, 100);
+# undef INITGUID
+#endif
+
using mozilla::dom::Promise;
using mozilla::dom::WindowsJumpListShortcutDescription;
@@ -291,15 +302,35 @@ JumpListBuilder::CheckForRemovals(JSContext* aCx, Promise** aPromise) {
}
NS_IMETHODIMP
-JumpListBuilder::PopulateJumpList(
- const nsTArray<JS::Value>& aTaskDescriptions, const nsAString& aCustomTitle,
- const nsTArray<JS::Value>& aCustomDescriptions, JSContext* aCx,
- Promise** aPromise) {
+JumpListBuilder::PopulateJumpList(JS::Handle<JS::Value> aTaskDescriptions,
+ const nsAString& aCustomTitle,
+ JS::Handle<JS::Value> aCustomDescriptions,
+ JSContext* aCx, Promise** aPromise) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPromise);
MOZ_ASSERT(mIOThread);
- if (aCustomDescriptions.Length() && aCustomTitle.IsEmpty()) {
+ if (!aTaskDescriptions.isObject() || !aCustomDescriptions.isObject()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ JS::Rooted<JSObject*> taskDescriptionsObj(aCx, &aTaskDescriptions.toObject());
+ JS::Rooted<JSObject*> customDescriptionsObj(aCx,
+ &aCustomDescriptions.toObject());
+
+ uint32_t taskDescriptionsLength = 0;
+ uint32_t customDescriptionsLength = 0;
+ if (NS_WARN_IF(!JS::GetArrayLength(aCx, taskDescriptionsObj,
+ &taskDescriptionsLength))) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ if (NS_WARN_IF(!JS::GetArrayLength(aCx, customDescriptionsObj,
+ &customDescriptionsLength))) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ if (customDescriptionsLength && aCustomTitle.IsEmpty()) {
return NS_ERROR_INVALID_ARG;
}
@@ -309,9 +340,11 @@ JumpListBuilder::PopulateJumpList(
mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
nsTArray<WindowsJumpListShortcutDescription> taskDescs;
- for (auto& jsval : aTaskDescriptions) {
+ for (uint32_t arrayIndex = 0; arrayIndex < taskDescriptionsLength;
+ arrayIndex++) {
JS::Rooted<JS::Value> rootedVal(aCx);
- if (NS_WARN_IF(!dom::ToJSValue(aCx, jsval, &rootedVal))) {
+ if (NS_WARN_IF(
+ !JS_GetElement(aCx, taskDescriptionsObj, arrayIndex, &rootedVal))) {
return NS_ERROR_INVALID_ARG;
}
@@ -324,9 +357,11 @@ JumpListBuilder::PopulateJumpList(
}
nsTArray<WindowsJumpListShortcutDescription> customDescs;
- for (auto& jsval : aCustomDescriptions) {
+ for (uint32_t arrayIndex = 0; arrayIndex < customDescriptionsLength;
+ arrayIndex++) {
JS::Rooted<JS::Value> rootedVal(aCx);
- if (NS_WARN_IF(!dom::ToJSValue(aCx, jsval, &rootedVal))) {
+ if (NS_WARN_IF(!JS_GetElement(aCx, customDescriptionsObj, arrayIndex,
+ &rootedVal))) {
return NS_ERROR_INVALID_ARG;
}
@@ -592,7 +627,14 @@ void JumpListBuilder::DoPopulateJumpList(
reinterpret_cast<const wchar_t*>(aCustomTitle.BeginReading()),
pCustomArray);
- if (FAILED(hr)) {
+ // E_ACCESSDENIED might be returned if Windows is configured not to show
+ // recently opened items in the start menu or jump lists. In that case, we
+ // still want to populate the tasks, so we ignore the error and commit
+ // the list.
+ //
+ // See
+ // https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-icustomdestinationlist-appendcategory
+ if (FAILED(hr) && hr != E_ACCESSDENIED) {
rv = NS_ERROR_UNEXPECTED;
return;
}
@@ -659,26 +701,47 @@ void JumpListBuilder::RemoveIconCacheAndGetJumplistShortcutURIs(
if (FAILED(aObjArray->GetAt(idx, IID_IShellLinkW,
static_cast<void**>(getter_AddRefs(pLink))))) {
+ NS_WARNING("Could not get a IShellLink from the IObjectArray");
continue;
}
- wchar_t buf[MAX_PATH];
- HRESULT hres = pLink->GetArguments(buf, MAX_PATH);
- if (SUCCEEDED(hres)) {
- LPWSTR* arglist;
- int32_t numArgs;
-
- arglist = ::CommandLineToArgvW(buf, &numArgs);
- if (arglist && numArgs > 0) {
- nsString spec(arglist[0]);
- aURISpecs.AppendElement(std::move(spec));
- ::LocalFree(arglist);
- }
+ RefPtr<IPropertyStore> pPropStore = nullptr;
+ if (NS_WARN_IF(FAILED(pLink->QueryInterface(
+ IID_IPropertyStore,
+ static_cast<void**>(getter_AddRefs(pPropStore)))))) {
+ NS_WARNING("Could not get IPropertyStore from IShellLink");
+ continue;
+ }
+
+ PROPVARIANT pv;
+ PropVariantInit(&pv);
+ auto cleanupPropVariant = MakeScopeExit([&] { PropVariantClear(&pv); });
+ if (NS_WARN_IF(FAILED(pPropStore->GetValue(PKEY_Link_Arguments, &pv)))) {
+ NS_WARNING("Could not get PKEY_Link_Arguments from IPropertyStore");
+ continue;
+ }
+
+ if (pv.vt != VT_LPWSTR) {
+ NS_WARNING("Unexpected type returned for PKEY_Link_Arguments");
+ continue;
+ }
+
+ LPCWSTR args(char16ptr_t(pv.pwszVal));
+ LPWSTR* arglist;
+ int32_t numArgs;
+
+ arglist = ::CommandLineToArgvW(args, &numArgs);
+ if (arglist && numArgs > 0) {
+ nsString spec(arglist[0]);
+ aURISpecs.AppendElement(std::move(spec));
+ ::LocalFree(arglist);
}
int iconIdx = 0;
- hres = pLink->GetIconLocation(buf, MAX_PATH, &iconIdx);
+ wchar_t buf[MAX_PATH + 1];
+ HRESULT hres = pLink->GetIconLocation(buf, MAX_PATH, &iconIdx);
if (SUCCEEDED(hres)) {
+ buf[MAX_PATH] = '\0';
nsDependentString spec(buf);
DeleteIconFromDisk(spec);
}
diff --git a/widget/windows/RemoteBackbuffer.cpp b/widget/windows/RemoteBackbuffer.cpp
index 56a8bae0fe..2d53570c3e 100644
--- a/widget/windows/RemoteBackbuffer.cpp
+++ b/widget/windows/RemoteBackbuffer.cpp
@@ -89,6 +89,8 @@ class SharedImage {
}
bool Initialize(int32_t aWidth, int32_t aHeight) {
+ MOZ_ASSERT(aWidth);
+ MOZ_ASSERT(aHeight);
MOZ_ASSERT(aWidth > 0);
MOZ_ASSERT(aHeight > 0);
@@ -183,9 +185,9 @@ class SharedImage {
}
}
- int32_t GetWidth() { return mWidth; }
+ int32_t GetWidth() const { return mWidth; }
- int32_t GetHeight() { return mHeight; }
+ int32_t GetHeight() const { return mHeight; }
SharedImage(const SharedImage&) = delete;
SharedImage(SharedImage&&) = delete;
@@ -515,7 +517,7 @@ void Provider::HandleBorrowRequest(BorrowResponseData* aResponseData,
aResponseData->result = ResponseResult::Error;
- RECT clientRect = {};
+ RECT clientRect{};
if (!::GetClientRect(mWindowHandle, &clientRect)) {
return;
}
@@ -523,12 +525,12 @@ void Provider::HandleBorrowRequest(BorrowResponseData* aResponseData,
MOZ_ASSERT(clientRect.left == 0);
MOZ_ASSERT(clientRect.top == 0);
- int32_t width = clientRect.right ? clientRect.right : 1;
- int32_t height = clientRect.bottom ? clientRect.bottom : 1;
+ const int32_t width = std::max(int32_t(clientRect.right), 1);
+ const int32_t height = std::max(int32_t(clientRect.bottom), 1);
bool needNewBackbuffer = !aAllowSameBuffer || !mBackbuffer ||
- (mBackbuffer->GetWidth() != width) ||
- (mBackbuffer->GetHeight() != height);
+ mBackbuffer->GetWidth() != width ||
+ mBackbuffer->GetHeight() != height;
if (!needNewBackbuffer) {
aResponseData->result = ResponseResult::BorrowSameBuffer;
diff --git a/widget/windows/ToastNotification.cpp b/widget/windows/ToastNotification.cpp
index afdffc19ac..83692b26a1 100644
--- a/widget/windows/ToastNotification.cpp
+++ b/widget/windows/ToastNotification.cpp
@@ -776,6 +776,9 @@ ToastNotification::CloseAlert(const nsAString& aAlertName,
bool aContextClosed) {
RefPtr<ToastNotificationHandler> handler;
if (NS_WARN_IF(!mActiveHandlers.Get(aAlertName, getter_AddRefs(handler)))) {
+ // This can happen when the handler is gone but the closure signal is not
+ // yet reached to the content process, and then the process tries closing
+ // the same signal.
return NS_OK;
}
diff --git a/widget/windows/WinCompositorWidget.h b/widget/windows/WinCompositorWidget.h
index fef967380c..df5d443067 100644
--- a/widget/windows/WinCompositorWidget.h
+++ b/widget/windows/WinCompositorWidget.h
@@ -18,8 +18,7 @@
class nsWindow;
-namespace mozilla {
-namespace widget {
+namespace mozilla::widget {
class PlatformCompositorWidgetDelegate : public CompositorWidgetDelegate {
public:
@@ -74,7 +73,7 @@ class WinCompositorWidget : public CompositorWidget {
void UpdateCompositorWndSizeIfNecessary();
void RequestFxrOutput();
- bool HasFxrOutputHandler() const { return mFxrHandler != nullptr; }
+ bool HasFxrOutputHandler() const { return !!mFxrHandler; }
FxROutputHandler* GetFxrOutputHandler() const { return mFxrHandler.get(); }
virtual nsSizeMode GetWindowSizeMode() const = 0;
@@ -97,7 +96,6 @@ class WinCompositorWidget : public CompositorWidget {
UniquePtr<FxROutputHandler> mFxrHandler;
};
-} // namespace widget
-} // namespace mozilla
+} // namespace mozilla::widget
#endif // widget_windows_WinCompositorWidget_h
diff --git a/widget/windows/filedialog/PWinFileDialog.ipdl b/widget/windows/filedialog/PWinFileDialog.ipdl
index 812db7e103..b61bfc0432 100644
--- a/widget/windows/filedialog/PWinFileDialog.ipdl
+++ b/widget/windows/filedialog/PWinFileDialog.ipdl
@@ -12,6 +12,16 @@ namespace mozilla {
namespace widget {
namespace filedialog {
+union FileResult {
+ Results?;
+ RemoteError;
+};
+
+union FolderResult {
+ nsString?;
+ RemoteError;
+};
+
[ChildProc=Utility]
protocol PWinFileDialog {
@@ -19,12 +29,13 @@ child:
// Exactly one Show function should be called per instance. Further calls will
// result in IPC failure.
//
- // Each will return `Nothing` iff the operation was canceled by the user.
+ // Each will return `Ok(Nothing)` if the operation was canceled by the user,
+ // or `Err(...)` if the operation actually failed.
async ShowFileDialog(WindowsHandle parentHwnd, FileDialogType type, Command[] commands)
- returns (Results? results);
+ returns (FileResult result);
async ShowFolderDialog(WindowsHandle parentHwnd, Command[] commands)
- returns (nsString? path);
+ returns (FolderResult result);
};
} // namespace filedialog
diff --git a/widget/windows/filedialog/WinFileDialogChild.cpp b/widget/windows/filedialog/WinFileDialogChild.cpp
index a41018ff0e..ddb972534a 100644
--- a/widget/windows/filedialog/WinFileDialogChild.cpp
+++ b/widget/windows/filedialog/WinFileDialogChild.cpp
@@ -46,34 +46,23 @@ WinFileDialogChild::IPCResult WinFileDialogChild::MakeIpcFailure(
return IPC_FAIL(this, what);
}
-#define MOZ_IPC_ENSURE_HRESULT_OK(hr, what) \
- do { \
- MOZ_LOG(sLogFileDialog, LogLevel::Verbose, \
- ("checking HRESULT for %s", what)); \
- HRESULT const _hr_ = (hr); \
- if (FAILED(_hr_)) { \
- MOZ_LOG(sLogFileDialog, LogLevel::Error, \
- ("HRESULT %8lX while %s", (hr), (what))); \
- return MakeIpcFailure(_hr_, (what)); \
- } \
- } while (0)
-
WinFileDialogChild::IPCResult WinFileDialogChild::RecvShowFileDialog(
uintptr_t parentHwnd, FileDialogType type, nsTArray<Command> commands,
FileResolver&& resolver) {
MOZ_ABORT_IF_ALREADY_USED();
- SpawnFilePicker(HWND(parentHwnd), type, std::move(commands))
- ->Then(
- GetMainThreadSerialEventTarget(), __PRETTY_FUNCTION__,
- [resolver = std::move(resolver)](Maybe<Results> const& res) {
- resolver(res);
- },
- [self = RefPtr(this)](HRESULT hr) {
- // this doesn't need to be returned anywhere; it'll crash the
- // process as a side effect of construction
- self->MakeIpcFailure(hr, "SpawnFilePicker");
- });
+ auto promise = SpawnFilePicker(HWND(parentHwnd), type, std::move(commands));
+ using RRV = std::decay_t<decltype(*promise)>::ResolveOrRejectValue;
+
+ promise->Then(GetMainThreadSerialEventTarget(), __PRETTY_FUNCTION__,
+ [resolver = std::move(resolver)](RRV&& val) -> void {
+ if (val.IsResolve()) {
+ resolver(val.ResolveValue());
+ } else {
+ auto err = val.RejectValue();
+ resolver(RemoteError(err.where.Serialize(), err.why));
+ }
+ });
return IPC_OK();
}
@@ -83,23 +72,22 @@ WinFileDialogChild::IPCResult WinFileDialogChild::RecvShowFolderDialog(
FolderResolver&& resolver) {
MOZ_ABORT_IF_ALREADY_USED();
- SpawnFolderPicker(HWND(parentHwnd), std::move(commands))
- ->Then(
- GetMainThreadSerialEventTarget(), __PRETTY_FUNCTION__,
- [resolver = std::move(resolver)](Maybe<nsString> const& res) {
- resolver(res);
- },
- [self = RefPtr(this), resolver](HRESULT hr) {
- // this doesn't need to be returned anywhere; it'll crash the
- // process as a side effect of construction
- self->MakeIpcFailure(hr, "SpawnFolderPicker");
- });
+ auto promise = SpawnFolderPicker(HWND(parentHwnd), std::move(commands));
+ using RRV = std::decay_t<decltype(*promise)>::ResolveOrRejectValue;
+
+ promise->Then(GetMainThreadSerialEventTarget(), __PRETTY_FUNCTION__,
+ [resolver = std::move(resolver)](RRV&& val) -> void {
+ if (val.IsResolve()) {
+ resolver(val.ResolveValue());
+ } else {
+ auto err = val.RejectValue();
+ resolver(RemoteError(err.where.Serialize(), err.why));
+ }
+ });
return IPC_OK();
}
-#undef MOZ_IPC_ENSURE_HRESULT_OK
-
void WinFileDialogChild::ProcessingError(Result aCode, const char* aReason) {
detail::LogProcessingError(sLogFileDialog, this, aCode, aReason);
}
diff --git a/widget/windows/filedialog/WinFileDialogCommands.cpp b/widget/windows/filedialog/WinFileDialogCommands.cpp
index 838856893d..75abbad343 100644
--- a/widget/windows/filedialog/WinFileDialogCommands.cpp
+++ b/widget/windows/filedialog/WinFileDialogCommands.cpp
@@ -22,6 +22,20 @@
namespace mozilla::widget::filedialog {
+const char* Error::KindName(Error::Kind kind) {
+ switch (kind) {
+ case LocalError:
+ return "LocalError";
+ case RemoteError:
+ return "RemoteError";
+ case IPCError:
+ return "IPCError";
+ default:
+ MOZ_ASSERT(false);
+ return "<bad value>";
+ }
+}
+
// Visitor to apply commands to the dialog.
struct Applicator {
IFileDialog* dialog = nullptr;
@@ -98,13 +112,15 @@ static HRESULT GetShellItemPath(IShellItem* aItem, nsString& aResultString) {
}
} // namespace
-#define MOZ_ENSURE_HRESULT_OK(call_) \
- do { \
- HRESULT const _tmp_hr_ = (call_); \
- if (FAILED(_tmp_hr_)) return Err(_tmp_hr_); \
+#define MOZ_ENSURE_HRESULT_OK(where, call_) \
+ do { \
+ HRESULT const _tmp_hr_ = (call_); \
+ if (FAILED(_tmp_hr_)) { \
+ return mozilla::Err(MOZ_FD_LOCAL_ERROR(where, _tmp_hr_)); \
+ } \
} while (0)
-mozilla::Result<RefPtr<IFileDialog>, HRESULT> MakeFileDialog(
+mozilla::Result<RefPtr<IFileDialog>, Error> MakeFileDialog(
FileDialogType type) {
RefPtr<IFileDialog> dialog;
@@ -112,43 +128,45 @@ mozilla::Result<RefPtr<IFileDialog>, HRESULT> MakeFileDialog(
: CLSID_FileSaveDialog;
HRESULT const hr = CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER,
IID_IFileDialog, getter_AddRefs(dialog));
- MOZ_ENSURE_HRESULT_OK(hr);
+ // more properly: "CoCreateInstance(CLSID_...)", but this suffices
+ MOZ_ENSURE_HRESULT_OK("MakeFileDialog", hr);
return std::move(dialog);
}
-HRESULT ApplyCommands(::IFileDialog* dialog,
- nsTArray<Command> const& commands) {
+mozilla::Result<Ok, Error> ApplyCommands(::IFileDialog* dialog,
+ nsTArray<Command> const& commands) {
Applicator applicator{.dialog = dialog};
for (auto const& cmd : commands) {
HRESULT const hr = applicator.Visit(cmd);
- if (FAILED(hr)) {
- return hr;
- }
+ MOZ_ENSURE_HRESULT_OK("ApplyCommands", hr);
}
- return S_OK;
+ return Ok{};
}
-mozilla::Result<Results, HRESULT> GetFileResults(::IFileDialog* dialog) {
+mozilla::Result<Results, Error> GetFileResults(::IFileDialog* dialog) {
FILEOPENDIALOGOPTIONS fos;
- MOZ_ENSURE_HRESULT_OK(dialog->GetOptions(&fos));
+ MOZ_ENSURE_HRESULT_OK("IFileDialog::GetOptions", dialog->GetOptions(&fos));
using widget::WinUtils;
// Extract which filter type the user selected
UINT index;
- MOZ_ENSURE_HRESULT_OK(dialog->GetFileTypeIndex(&index));
+ MOZ_ENSURE_HRESULT_OK("IFileDialog::GetFileTypeIndex",
+ dialog->GetFileTypeIndex(&index));
// single selection
if ((fos & FOS_ALLOWMULTISELECT) == 0) {
RefPtr<IShellItem> item;
- MOZ_ENSURE_HRESULT_OK(dialog->GetResult(getter_AddRefs(item)));
+ MOZ_ENSURE_HRESULT_OK("IFileDialog::GetResult",
+ dialog->GetResult(getter_AddRefs(item)));
if (!item) {
- return Err(E_FAIL);
+ return Err(MOZ_FD_LOCAL_ERROR("IFileDialog::GetResult: item", E_POINTER));
}
nsAutoString path;
- MOZ_ENSURE_HRESULT_OK(GetShellItemPath(item, path));
+ MOZ_ENSURE_HRESULT_OK("GetFileResults: GetShellItemPath (1)",
+ GetShellItemPath(item, path));
return Results({path}, index);
}
@@ -158,25 +176,29 @@ mozilla::Result<Results, HRESULT> GetFileResults(::IFileDialog* dialog) {
dialog->QueryInterface(IID_IFileOpenDialog, getter_AddRefs(openDlg));
if (!openDlg) {
MOZ_ASSERT(false, "a file-save dialog was given FOS_ALLOWMULTISELECT?");
- return Err(E_UNEXPECTED);
+ return Err(MOZ_FD_LOCAL_ERROR("Save + FOS_ALLOWMULTISELECT", E_UNEXPECTED));
}
RefPtr<IShellItemArray> items;
- MOZ_ENSURE_HRESULT_OK(openDlg->GetResults(getter_AddRefs(items)));
+ MOZ_ENSURE_HRESULT_OK("IFileOpenDialog::GetResults",
+ openDlg->GetResults(getter_AddRefs(items)));
if (!items) {
- return Err(E_FAIL);
+ return Err(
+ MOZ_FD_LOCAL_ERROR("IFileOpenDialog::GetResults: items", E_POINTER));
}
nsTArray<nsString> paths;
DWORD count = 0;
- MOZ_ENSURE_HRESULT_OK(items->GetCount(&count));
+ MOZ_ENSURE_HRESULT_OK("IShellItemArray::GetCount", items->GetCount(&count));
for (DWORD idx = 0; idx < count; idx++) {
RefPtr<IShellItem> item;
- MOZ_ENSURE_HRESULT_OK(items->GetItemAt(idx, getter_AddRefs(item)));
+ MOZ_ENSURE_HRESULT_OK("IShellItemArray::GetItemAt",
+ items->GetItemAt(idx, getter_AddRefs(item)));
nsAutoString str;
- MOZ_ENSURE_HRESULT_OK(GetShellItemPath(item, str));
+ MOZ_ENSURE_HRESULT_OK("GetFileResults: GetShellItemPath (2)",
+ GetShellItemPath(item, str));
paths.EmplaceBack(str);
}
@@ -184,15 +206,17 @@ mozilla::Result<Results, HRESULT> GetFileResults(::IFileDialog* dialog) {
return Results(std::move(paths), std::move(index));
}
-mozilla::Result<nsString, HRESULT> GetFolderResults(::IFileDialog* dialog) {
+mozilla::Result<nsString, Error> GetFolderResults(::IFileDialog* dialog) {
RefPtr<IShellItem> item;
- MOZ_ENSURE_HRESULT_OK(dialog->GetResult(getter_AddRefs(item)));
+ MOZ_ENSURE_HRESULT_OK("IFileDialog::GetResult",
+ dialog->GetResult(getter_AddRefs(item)));
+
if (!item) {
// shouldn't happen -- probably a precondition failure on our part, but
// might be due to misbehaving shell extensions?
MOZ_ASSERT(false,
"unexpected lack of item: was `Show`'s return value checked?");
- return Err(E_FAIL);
+ return Err(MOZ_FD_LOCAL_ERROR("IFileDialog::GetResult: item", E_POINTER));
}
// If the user chose a Win7 Library, resolve to the library's
@@ -200,6 +224,7 @@ mozilla::Result<nsString, HRESULT> GetFolderResults(::IFileDialog* dialog) {
RefPtr<IShellLibrary> shellLib;
RefPtr<IShellItem> folderPath;
MOZ_ENSURE_HRESULT_OK(
+ "CoCreateInstance(CLSID_ShellLibrary)",
CoCreateInstance(CLSID_ShellLibrary, nullptr, CLSCTX_INPROC_SERVER,
IID_IShellLibrary, getter_AddRefs(shellLib)));
@@ -211,7 +236,7 @@ mozilla::Result<nsString, HRESULT> GetFolderResults(::IFileDialog* dialog) {
// get the folder's file system path
nsAutoString str;
- MOZ_ENSURE_HRESULT_OK(GetShellItemPath(item, str));
+ MOZ_ENSURE_HRESULT_OK("GetShellItemPath", GetShellItemPath(item, str));
return str;
}
@@ -312,12 +337,22 @@ void LogProcessingError(LogModule* aModule, ipc::IProtocol* aCaller,
template <typename Res, typename Action, size_t N>
RefPtr<Promise<Res>> SpawnFileDialogThread(const char (&where)[N],
Action action) {
+ {
+ using ActionRetT = std::invoke_result_t<Action>;
+ using Info = detail::DestructureResult<ActionRetT>;
+
+ MOZ_ASSERT_SAME_TYPE(
+ typename Info::ErrorT, Error,
+ "supplied Action must return Result<T, filedialog::Err>");
+ }
+
RefPtr<nsIThread> thread;
{
nsresult rv = NS_NewNamedThread("File Dialog", getter_AddRefs(thread),
nullptr, {.isUiThread = true});
if (NS_FAILED(rv)) {
- return Promise<Res>::CreateAndReject((HRESULT)rv, where);
+ return Promise<Res>::CreateAndReject(
+ MOZ_FD_LOCAL_ERROR("NS_NewNamedThread", (HRESULT)rv), where);
}
}
// `thread` is single-purpose, and should not perform any additional work
@@ -393,7 +428,7 @@ RefPtr<Promise<Res>> SpawnFileDialogThread(const char (&where)[N],
}
// Actually invoke the action and report the result.
- Result<Res, HRESULT> val = action();
+ Result<Res, Error> val = action();
if (val.isErr()) {
promise->Reject(val.unwrapErr(), where);
} else {
@@ -407,16 +442,16 @@ RefPtr<Promise<Res>> SpawnFileDialogThread(const char (&where)[N],
// For F returning `Result<T, E>`, yields the type `T`.
template <typename F, typename... Args>
using inner_result_of =
- typename std::remove_reference_t<decltype(std::declval<F>()(
- std::declval<Args>()...))>::ok_type;
+ typename detail::DestructureResult<std::invoke_result_t<F, Args...>>::OkT;
template <typename ExtractorF,
typename RetT = inner_result_of<ExtractorF, IFileDialog*>>
auto SpawnPickerT(HWND parent, FileDialogType type, ExtractorF&& extractor,
nsTArray<Command> commands) -> RefPtr<Promise<Maybe<RetT>>> {
+ using ActionRetT = Result<Maybe<RetT>, Error>;
+
return detail::SpawnFileDialogThread<Maybe<RetT>>(
- __PRETTY_FUNCTION__,
- [=, commands = std::move(commands)]() -> Result<Maybe<RetT>, HRESULT> {
+ __PRETTY_FUNCTION__, [=, commands = std::move(commands)]() -> ActionRetT {
// On Win10, the picker doesn't support per-monitor DPI, so we create it
// with our context set temporarily to system-dpi-aware.
WinUtils::AutoSystemDpiAware dpiAwareness;
@@ -424,15 +459,13 @@ auto SpawnPickerT(HWND parent, FileDialogType type, ExtractorF&& extractor,
RefPtr<IFileDialog> dialog;
MOZ_TRY_VAR(dialog, MakeFileDialog(type));
- if (HRESULT const rv = ApplyCommands(dialog, commands); FAILED(rv)) {
- return mozilla::Err(rv);
- }
+ MOZ_TRY(ApplyCommands(dialog, commands));
if (HRESULT const rv = dialog->Show(parent); FAILED(rv)) {
if (rv == HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
- return Result<Maybe<RetT>, HRESULT>(Nothing());
+ return ActionRetT{Nothing()};
}
- return mozilla::Err(rv);
+ return mozilla::Err(MOZ_FD_LOCAL_ERROR("IFileDialog::Show", rv));
}
RetT res;
diff --git a/widget/windows/filedialog/WinFileDialogCommands.h b/widget/windows/filedialog/WinFileDialogCommands.h
index ca4561a8f2..800ce832d5 100644
--- a/widget/windows/filedialog/WinFileDialogCommands.h
+++ b/widget/windows/filedialog/WinFileDialogCommands.h
@@ -19,27 +19,200 @@ struct IFileOpenDialog;
namespace mozilla::widget::filedialog {
+namespace detail {
+
+template <typename T, typename E, bool B>
+struct PromiseInfo {
+ using ResolveT = T;
+ using RejectT = E;
+ constexpr static const bool IsExclusive = B;
+ using Promise = MozPromise<T, E, B>;
+};
+
+template <typename P>
+auto DestructurePromiseImpl(P&&) {
+ // Debugging hint: A type in the instantiation chain (here named `P`) was
+ // expected to be a `RefPtr<MozPromise<...>>`, but was some other type.
+ static_assert(false, "expected P = RefPtr<MozPromise< ... >>");
+}
+
+template <typename T, typename E, bool B>
+auto DestructurePromiseImpl(RefPtr<MozPromise<T, E, B>>&&)
+ -> PromiseInfo<T, E, B>;
+
+template <typename P>
+using DestructurePromise =
+ std::decay_t<decltype(DestructurePromiseImpl(std::declval<P>()))>;
+
+template <typename T, typename E>
+struct ResultInfo {
+ using OkT = T;
+ using ErrorT = E;
+};
+
+template <typename R>
+auto DestructureResultImpl(R&&) {
+ // Debugging hint: A type in the instantiation chain (here named `R`) was
+ // expected to be a `mozilla::Result<...>`, but was some other type.
+ static_assert(false, "expected R = mozilla::Result< ... >");
+}
+
+template <typename T, typename E>
+auto DestructureResultImpl(mozilla::Result<T, E>&&) -> ResultInfo<T, E>;
+
+template <typename R>
+using DestructureResult =
+ std::decay_t<decltype(DestructureResultImpl(std::declval<R>()))>;
+
+#define MOZ_ASSERT_SAME_TYPE(T1, T2, ...) \
+ static_assert(std::is_same_v<T1, T2>, ##__VA_ARGS__)
+} // namespace detail
+
extern LazyLogModule sLogFileDialog;
+// Simple struct for reporting errors.
+struct Error {
+ enum Kind {
+ // This error's source was within the local (current) process.
+ LocalError,
+ // This error's source was within the remote host process, and it was
+ // reported via noncatastrophic channels.
+ RemoteError,
+ // This error was reported via the IPC subsystem. (This includes unexpected
+ // remote host-process crashes.)
+ IPCError,
+ };
+
+ // "Enum" denoting error-location. Members are in `VALID_STRINGS`, and have no
+ // name other than their string.
+ //
+ // (Note: under C++20, this could reasonably be replaced with an `nsString`
+ // alongside a check that all constructors are either a) consteval or b) from
+ // IPC.)
+ class Location {
+ uint32_t value;
+ constexpr explicit Location(uint32_t value) : value(value) {}
+
+ // Valid locations for errors. (Indices do not need to remain stable between
+ // releases; but -- where meaningful -- string values themselves should, for
+ // ease of telemetry-aggregation.)
+ constexpr static std::string_view const VALID_STRINGS[] = {
+ "ApplyCommands",
+ "CoCreateInstance(CLSID_ShellLibrary)",
+ "GetFileResults: GetShellItemPath (1)",
+ "GetFileResults: GetShellItemPath (2)",
+ "GetShellItemPath",
+ "IFileDialog::GetFileTypeIndex",
+ "IFileDialog::GetOptions",
+ "IFileDialog::GetResult",
+ "IFileDialog::GetResult: item",
+ "IFileDialog::Show",
+ "IFileOpenDialog::GetResults",
+ "IFileOpenDialog::GetResults: items",
+ "IPC",
+ "IShellItemArray::GetCount",
+ "IShellItemArray::GetItemAt",
+ "MakeFileDialog",
+ "NS_NewNamedThread",
+ "Save + FOS_ALLOWMULTISELECT",
+ "ShowFilePicker",
+ "ShowFolderPicker",
+ "ShowRemote: UtilityProcessManager::GetSingleton",
+ "ShowRemote: invocation of CreateWinFileDialogActor",
+ "UtilityProcessManager::CreateWinFileDialogActor",
+ "internal IPC failure?",
+ };
+ constexpr static size_t VALID_STRINGS_COUNT =
+ std::extent_v<decltype(VALID_STRINGS)>;
+
+ // Prevent duplicates from occurring in VALID_STRINGS by forcing it to be
+ // sorted. (Note that std::is_sorted is not constexpr until C++20.)
+ static_assert(
+ []() {
+ for (size_t i = 0; i + 1 < VALID_STRINGS_COUNT; ++i) {
+ if (!(VALID_STRINGS[i] < VALID_STRINGS[i + 1])) {
+ return false;
+ }
+ }
+ return true;
+ }(),
+ "VALID_STRINGS should be ASCIIbetically sorted");
+
+ public:
+ constexpr uint32_t Serialize() const { return value; }
+ constexpr static Location Deserialize(uint32_t val) {
+ return Location{val};
+ }
+
+ public:
+ constexpr static Location npos() { return Location{~uint32_t(0)}; }
+
+ constexpr bool IsValid() const { return value < VALID_STRINGS_COUNT; }
+
+ constexpr std::string_view ToString() const {
+ return value < VALID_STRINGS_COUNT ? VALID_STRINGS[value]
+ : "<bad filedialog::Error::Location?>";
+ }
+ constexpr static Location FromString(std::string_view str) {
+ for (uint32_t i = 0; i < VALID_STRINGS_COUNT; ++i) {
+ if (str == VALID_STRINGS[i]) return Location{i};
+ }
+ return npos();
+ }
+
+ constexpr char const* c_str() const { return ToString().data(); }
+ };
+
+ // Where and how (run-time) this error occurred.
+ Kind kind;
+ // Where (compile-time) this error occurred.
+ Location where;
+ // Why (run-time) this error occurred. Probably an HRESULT.
+ uint32_t why;
+
+ // `impl Debug for Kind`
+ static const char* KindName(Kind);
+};
+
+// Create a filedialog::Error, confirming at compile-time that the supplied
+// where-string is valid.
+#define MOZ_FD_ERROR(kind_, where_, why_) \
+ ([](HRESULT why_arg_) -> ::mozilla::widget::filedialog::Error { \
+ using Error = ::mozilla::widget::filedialog::Error; \
+ constexpr static const Error::Location loc = \
+ Error::Location::FromString(where_); \
+ static_assert( \
+ loc.IsValid(), \
+ "filedialog::Error: location not found in Error::VALID_STRINGS"); \
+ return Error{ \
+ .kind = Error::kind_, .where = loc, .why = (uint32_t)why_arg_}; \
+ }(why_))
+
+// Create a filedialog::Error of kind LocalError (the usual case).
+#define MOZ_FD_LOCAL_ERROR(where_, why_) MOZ_FD_ERROR(LocalError, where_, why_)
+
+template <typename R>
+using Promise = MozPromise<R, Error, true>;
+
enum class FileDialogType : uint8_t { Open, Save };
// Create a file-dialog of the relevant type. Requires MSCOM to be initialized.
-mozilla::Result<RefPtr<IFileDialog>, HRESULT> MakeFileDialog(FileDialogType);
+mozilla::Result<RefPtr<IFileDialog>, Error> MakeFileDialog(FileDialogType);
// Apply the selected commands to the IFileDialog, in preparation for showing
// it. (The actual showing step is left to the caller.)
-[[nodiscard]] HRESULT ApplyCommands(::IFileDialog*,
- nsTArray<Command> const& commands);
+mozilla::Result<Ok, Error> ApplyCommands(::IFileDialog*,
+ nsTArray<Command> const& commands);
// Extract one or more results from the file-picker dialog.
//
// Requires that Show() has been called and has returned S_OK.
-mozilla::Result<Results, HRESULT> GetFileResults(::IFileDialog*);
+mozilla::Result<Results, Error> GetFileResults(::IFileDialog*);
// Extract the chosen folder from the folder-picker dialog.
//
// Requires that Show() has been called and has returned S_OK.
-mozilla::Result<nsString, HRESULT> GetFolderResults(::IFileDialog*);
+mozilla::Result<nsString, Error> GetFolderResults(::IFileDialog*);
namespace detail {
// Log the error. If it's a notable error, kill the child process.
@@ -48,9 +221,6 @@ void LogProcessingError(LogModule* aModule, ipc::IProtocol* aCaller,
} // namespace detail
-template <typename R>
-using Promise = MozPromise<R, HRESULT, true>;
-
// Show a file-picker on another thread in the current process.
RefPtr<Promise<Maybe<Results>>> SpawnFilePicker(HWND parent,
FileDialogType type,
diff --git a/widget/windows/filedialog/WinFileDialogCommandsDefn.ipdlh b/widget/windows/filedialog/WinFileDialogCommandsDefn.ipdlh
index dd85942f24..352b46df17 100644
--- a/widget/windows/filedialog/WinFileDialogCommandsDefn.ipdlh
+++ b/widget/windows/filedialog/WinFileDialogCommandsDefn.ipdlh
@@ -44,6 +44,19 @@ struct Results {
uint32_t selectedFileTypeIndex;
};
+// Homolog of filedialog::Err. (Always Err::Kind::RemoteError, by definition.)
+struct RemoteError {
+ // An enum (`filedialog::Error::Location`) describing the compile-time location
+ // where the error was detected.
+ //
+ // (This value is validated at use-sites; if the child process sends a bad
+ // value, nothing of import will happen.)
+ uint32_t where;
+ // An error code describing the error itself more precisely. Its semantics
+ // depend on the context provided by `where`, but it's probably an HRESULT.
+ uint32_t why;
+};
+
} // namespace filedialog
} // namespace widget
} // namespace mozilla
diff --git a/widget/windows/filedialog/WinFileDialogParent.cpp b/widget/windows/filedialog/WinFileDialogParent.cpp
index 2c256a1506..329c72cc94 100644
--- a/widget/windows/filedialog/WinFileDialogParent.cpp
+++ b/widget/windows/filedialog/WinFileDialogParent.cpp
@@ -54,6 +54,86 @@ PWinFileDialogParent::nsresult WinFileDialogParent::BindToUtilityProcess(
return NS_OK;
}
+// Convert the raw IPC promise-type to a filedialog::Promise.
+template <typename T, typename Ex, size_t N>
+static auto ConvertToFDPromise(
+ const char (&aMethod)[N], // __func__
+ Ex&& extractor,
+ RefPtr<MozPromise<T, mozilla::ipc::ResponseRejectReason, true>>
+ aSrcPromise) {
+ // The extractor must produce a `mozilla::Result<..., Error>` from `T`.
+ using SrcResultInfo = detail::DestructureResult<std::invoke_result_t<Ex, T>>;
+ using ResolveT = typename SrcResultInfo::OkT;
+ static_assert(std::is_same_v<typename SrcResultInfo::ErrorT, Error>,
+ "expected T to be a Result<..., Error>");
+
+ using SrcPromiseT = MozPromise<T, mozilla::ipc::ResponseRejectReason, true>;
+ using DstPromiseT = MozPromise<ResolveT, Error, true>;
+
+ RefPtr<DstPromiseT> ret = aSrcPromise->Then(
+ mozilla::GetCurrentSerialEventTarget(), aMethod,
+
+ [extractor, aMethod](T&& val) {
+ mozilla::Result<ResolveT, Error> result = extractor(std::move(val));
+ if (result.isOk()) {
+ return DstPromiseT::CreateAndResolve(result.unwrap(), aMethod);
+ }
+ return DstPromiseT::CreateAndReject(result.unwrapErr(), aMethod);
+ },
+ [aMethod](typename mozilla::ipc::ResponseRejectReason&& val) {
+ return DstPromiseT::CreateAndReject(
+ MOZ_FD_ERROR(IPCError, "IPC", (uint32_t)val), aMethod);
+ });
+
+ return ret;
+}
+
+template <typename Input, typename Output>
+struct Extractor {
+ template <typename Input::Type tag_, Output const& (Input::*getter_)() const>
+ static auto get() {
+ return [](Input&& res) -> Result<Output, Error> {
+ if (res.type() == tag_) {
+ return (res.*getter_)();
+ }
+ if (res.type() == Input::TRemoteError) {
+ RemoteError err = res.get_RemoteError();
+ return Err(Error{.kind = Error::RemoteError,
+ .where = Error::Location::Deserialize(err.where()),
+ .why = err.why()});
+ }
+ MOZ_ASSERT_UNREACHABLE("internal IPC failure?");
+ return Err(MOZ_FD_ERROR(IPCError, "internal IPC failure?", E_FAIL));
+ };
+ }
+};
+
+[[nodiscard]] RefPtr<WinFileDialogParent::ShowFileDialogPromise>
+WinFileDialogParent::ShowFileDialogImpl(HWND parent, const FileDialogType& type,
+ mozilla::Span<Command const> commands) {
+ auto inner_promise = PWinFileDialogParent::SendShowFileDialog(
+ reinterpret_cast<WindowsHandle>(parent), type, std::move(commands));
+
+ return ConvertToFDPromise(
+ __func__,
+ Extractor<FileResult, Maybe<Results>>::get<
+ FileResult::TMaybeResults, &FileResult::get_MaybeResults>(),
+ std::move(inner_promise));
+}
+
+[[nodiscard]] RefPtr<WinFileDialogParent::ShowFolderDialogPromise>
+WinFileDialogParent::ShowFolderDialogImpl(
+ HWND parent, mozilla::Span<Command const> commands) {
+ auto inner_promise = PWinFileDialogParent::SendShowFolderDialog(
+ reinterpret_cast<WindowsHandle>(parent), std::move(commands));
+
+ return ConvertToFDPromise(
+ __func__,
+ Extractor<FolderResult, Maybe<nsString>>::get<
+ FolderResult::TMaybensString, &FolderResult::get_MaybensString>(),
+ std::move(inner_promise));
+}
+
void WinFileDialogParent::ProcessingError(Result aCode, const char* aReason) {
detail::LogProcessingError(sLogFileDialog, this, aCode, aReason);
}
diff --git a/widget/windows/filedialog/WinFileDialogParent.h b/widget/windows/filedialog/WinFileDialogParent.h
index a2c1197c55..a1eb547444 100644
--- a/widget/windows/filedialog/WinFileDialogParent.h
+++ b/widget/windows/filedialog/WinFileDialogParent.h
@@ -21,11 +21,14 @@
namespace mozilla::widget::filedialog {
-class WinFileDialogParent : public PWinFileDialogParent {
+class WinFileDialogParent final : private PWinFileDialogParent {
public:
using UtilityActorName = ::mozilla::UtilityActorName;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WinFileDialogParent, override);
+ using ShowFileDialogPromise = Promise<Maybe<Results>>;
+ using ShowFolderDialogPromise = Promise<Maybe<nsString>>;
+
public:
WinFileDialogParent();
nsresult BindToUtilityProcess(
@@ -35,6 +38,16 @@ class WinFileDialogParent : public PWinFileDialogParent {
return UtilityActorName::WindowsFileDialog;
}
+ bool CanSend() const { return PWinFileDialogParent::CanSend(); }
+ void Close() { return PWinFileDialogParent::Close(); }
+
+ [[nodiscard]] RefPtr<ShowFileDialogPromise> ShowFileDialogImpl(
+ HWND parent, const FileDialogType& type,
+ mozilla::Span<Command const> commands);
+
+ [[nodiscard]] RefPtr<ShowFolderDialogPromise> ShowFolderDialogImpl(
+ HWND parent, mozilla::Span<Command const> commands);
+
private:
~WinFileDialogParent();
diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp
index 88a2a2ad09..60e2784f37 100644
--- a/widget/windows/nsDataObj.cpp
+++ b/widget/windows/nsDataObj.cpp
@@ -346,10 +346,10 @@ HRESULT nsDataObj::CreateStream(IStream** outStream) {
pStream->AddRef();
- // query the requestingPrincipal from the transferable and add it to the new
- // channel
+ // query the dataPrincipal from the transferable and add it to the new
+ // channel.
nsCOMPtr<nsIPrincipal> requestingPrincipal =
- mTransferable->GetRequestingPrincipal();
+ mTransferable->GetDataPrincipal();
MOZ_ASSERT(requestingPrincipal, "can not create channel without a principal");
// Note that the cookieJarSettings could be null if the data object is for the
diff --git a/widget/windows/nsFilePicker.cpp b/widget/windows/nsFilePicker.cpp
index 2a45937988..89b10ce4ee 100644
--- a/widget/windows/nsFilePicker.cpp
+++ b/widget/windows/nsFilePicker.cpp
@@ -44,15 +44,17 @@
#include "mozilla/widget/filedialog/WinFileDialogCommands.h"
#include "mozilla/widget/filedialog/WinFileDialogParent.h"
+using mozilla::LogLevel;
using mozilla::UniquePtr;
using namespace mozilla::widget;
+template <typename Res>
+using FDPromise = filedialog::Promise<Res>;
+
UniquePtr<char16_t[], nsFilePicker::FreeDeleter>
nsFilePicker::sLastUsedUnicodeDirectory;
-using mozilla::LogLevel;
-
#define MAX_EXTENSION_LENGTH 10
///////////////////////////////////////////////////////////////////////////////
@@ -106,27 +108,29 @@ NS_IMETHODIMP nsFilePicker::Init(
}
namespace mozilla::detail {
+using Error = mozilla::widget::filedialog::Error;
+
// Boilerplate for remotely showing a file dialog.
template <typename ActionType,
typename ReturnType = typename decltype(std::declval<ActionType>()(
nullptr))::element_type::ResolveValueType>
-static auto ShowRemote(ActionType&& action)
- -> RefPtr<MozPromise<ReturnType, HRESULT, true>> {
- using RetPromise = MozPromise<ReturnType, HRESULT, true>;
+static auto ShowRemote(ActionType&& action) -> RefPtr<FDPromise<ReturnType>> {
+ using RetPromise = FDPromise<ReturnType>;
- constexpr static const auto fail = []() {
- return RetPromise::CreateAndReject(E_FAIL, __PRETTY_FUNCTION__);
- };
+// "function-local" #define
+#define FAIL(where_, why_) \
+ return RetPromise::CreateAndReject(MOZ_FD_LOCAL_ERROR(where_, why_), \
+ __PRETTY_FUNCTION__)
auto mgr = mozilla::ipc::UtilityProcessManager::GetSingleton();
if (!mgr) {
MOZ_ASSERT(false);
- return fail();
+ FAIL("ShowRemote: UtilityProcessManager::GetSingleton", E_POINTER);
}
auto wfda = mgr->CreateWinFileDialogActor();
if (!wfda) {
- return fail();
+ FAIL("ShowRemote: invocation of CreateWinFileDialogActor", E_POINTER);
}
using mozilla::widget::filedialog::sLogFileDialog;
@@ -135,32 +139,70 @@ static auto ShowRemote(ActionType&& action)
mozilla::GetMainThreadSerialEventTarget(),
"nsFilePicker ShowRemote acquire",
[action = std::forward<ActionType>(action)](
- filedialog::ProcessProxy const& p) -> RefPtr<RetPromise> {
+ filedialog::ProcessProxy p) -> RefPtr<RetPromise> {
MOZ_LOG(sLogFileDialog, LogLevel::Info,
("nsFilePicker ShowRemote first callback: p = [%p]", p.get()));
// false positive: not actually redundant
// NOLINTNEXTLINE(readability-redundant-smartptr-get)
- return action(p.get())->Then(
- mozilla::GetMainThreadSerialEventTarget(),
- "nsFilePicker ShowRemote call",
- [p](ReturnType ret) {
- return RetPromise::CreateAndResolve(std::move(ret),
- __PRETTY_FUNCTION__);
- },
- [](mozilla::ipc::ResponseRejectReason error) {
- MOZ_LOG(sLogFileDialog, LogLevel::Error,
- ("IPC call rejected: %zu", size_t(error)));
- return fail();
+ auto promise = action(p.get());
+ return promise->Map(
+ mozilla::GetMainThreadSerialEventTarget(), __func__,
+ [p = std::move(p)](typename RetPromise::ResolveValueType&& val) {
+ // explicitly retain the ProcessProxy until at least this point
+ return std::move(val);
});
},
[](nsresult error) -> RefPtr<RetPromise> {
MOZ_LOG(sLogFileDialog, LogLevel::Error,
("could not acquire WinFileDialog: %zu", size_t(error)));
- return fail();
+ // TODO: pipe more data up from utility-process creation
+ FAIL("UtilityProcessManager::CreateWinFileDialogActor",
+ (uint32_t)error);
+ });
+
+#undef FAIL
+}
+
+namespace {
+
+static RefPtr<FDPromise<Maybe<filedialog::Results>>> ShowFilePickerRemote(
+ HWND parent, filedialog::FileDialogType type,
+ nsTArray<filedialog::Command> const& commands) {
+ using mozilla::widget::filedialog::sLogFileDialog;
+ return mozilla::detail::ShowRemote(
+ [parent, type,
+ commands = commands.Clone()](filedialog::WinFileDialogParent* p) {
+ MOZ_LOG(sLogFileDialog, LogLevel::Info,
+ ("%s: p = [%p]", __PRETTY_FUNCTION__, p));
+ return p->ShowFileDialogImpl(parent, type, commands);
});
}
+static RefPtr<FDPromise<Maybe<nsString>>> ShowFolderPickerRemote(
+ HWND parent, nsTArray<filedialog::Command> const& commands) {
+ using mozilla::widget::filedialog::sLogFileDialog;
+ return mozilla::detail::ShowRemote([parent, commands = commands.Clone()](
+ filedialog::WinFileDialogParent* p) {
+ MOZ_LOG(sLogFileDialog, LogLevel::Info,
+ ("%s: p = [%p]", __PRETTY_FUNCTION__, p));
+ return p->ShowFolderDialogImpl(parent, commands);
+ });
+}
+
+static RefPtr<FDPromise<Maybe<filedialog::Results>>> ShowFilePickerLocal(
+ HWND parent, filedialog::FileDialogType type,
+ nsTArray<filedialog::Command> const& commands) {
+ return filedialog::SpawnFilePicker(parent, type, commands.Clone());
+}
+
+static RefPtr<FDPromise<Maybe<nsString>>> ShowFolderPickerLocal(
+ HWND parent, nsTArray<filedialog::Command> const& commands) {
+ return filedialog::SpawnFolderPicker(parent, commands.Clone());
+}
+
+} // namespace
+
// fd_async
//
// Wrapper-namespace for the AsyncExecute() and AsyncAll() functions.
@@ -296,31 +338,83 @@ static void RecordFailure(uint64_t (&&time)[3], HRESULT hrRemote,
}
} // namespace telemetry
+
+/* N.B.: L and R stand for Local and Remote, not just Left and Right */
+template <typename FnL, typename FnR, typename... Args>
+struct AsyncExecuteInfo {
+ template <typename T>
+ using DestructurePromise = widget::filedialog::detail::DestructurePromise<T>;
+
+ using Unit = ::mozilla::Ok;
+
+ using RetL = std::invoke_result_t<FnL, Args...>;
+ using RetR = std::invoke_result_t<FnR, Args...>;
+
+ using InfoL = DestructurePromise<RetL>;
+ using InfoR = DestructurePromise<RetR>;
+
+ MOZ_ASSERT_SAME_TYPE(
+ typename InfoL::ResolveT, typename InfoR::ResolveT,
+ "local and remote promises must have identical resolve-types");
+
+ // At present, the local and remote promises have the same type, but this
+ // isn't logically necessary. (In particular, a future refactor may remove the
+ // redundant `.kind` from the local promises' return types.)
+ MOZ_ASSERT_SAME_TYPE(typename InfoL::RejectT, filedialog::Error,
+ "local promise must reject with a filedialog::Error");
+
+ MOZ_ASSERT_SAME_TYPE(typename InfoR::RejectT, filedialog::Error,
+ "remote promise must reject with a filedialog::Error");
+
+ using ResolveT = typename InfoL::ResolveT;
+ using PromiseT = MozPromise<ResolveT, Unit, true>;
+
+ using RetT = RefPtr<PromiseT>;
+};
+
} // namespace details
-// Invoke either or both of a "do locally" and "do remotely" function with the
-// provided arguments, depending on the relevant preference-value and whether
-// or not the remote version fails.
+// Invoke either or both of a promise-returning "do locally" and "do remotely"
+// function with the provided arguments, depending on the relevant preference's
+// value and on whether or not the remote version fails (returns a rejection-
+// promise).
//
-// Both functions must be asynchronous, returning a `RefPtr<MozPromise<...>>`.
-// "Failure" is defined as the promise being rejected.
+// Both provided functions must return a `RefPtr<filedialog::MozPromise<T>>`. As
+// `AsyncExecute` reports failures itself, its rejection-type is `()`.
template <typename Fn1, typename Fn2, typename... Args>
-static auto AsyncExecute(Fn1 local, Fn2 remote, Args const&... args)
- -> std::invoke_result_t<Fn1, Args...> {
+static auto AsyncExecute(Fn1 local, Fn2 remote, Args const&... args) ->
+ typename details::AsyncExecuteInfo<Fn1, Fn2, Args...>::RetT {
using namespace details;
+ using Info = AsyncExecuteInfo<Fn1, Fn2, Args...>;
- static_assert(std::is_same_v<std::invoke_result_t<Fn1, Args...>,
- std::invoke_result_t<Fn2, Args...>>);
- using PromiseT = typename std::invoke_result_t<Fn1, Args...>::element_type;
+ using ResolveT = typename Info::ResolveT;
+ using PromiseT = typename Info::PromiseT;
+ using LPromiseT = typename Info::InfoL::Promise;
+ using RPromiseT = typename Info::InfoR::Promise;
constexpr static char kFunctionName[] = "LocalAndOrRemote::AsyncExecute";
switch (GetStrategy()) {
- case Local:
- return local(args...);
+ case Local: {
+ return local(args...)->MapErr(
+ NS_GetCurrentThread(), __func__, [](Error const& err) {
+ MOZ_ASSERT(err.kind == Error::LocalError);
+ MOZ_LOG(filedialog::sLogFileDialog, LogLevel::Info,
+ ("local file-dialog failed: where=%s, why=%08" PRIX32,
+ err.where.c_str(), err.why));
+ return Ok();
+ });
+ }
case Remote:
- return remote(args...);
+ return remote(args...)->MapErr(
+ NS_GetCurrentThread(), __func__, [](Error const& err) {
+ MOZ_LOG(
+ filedialog::sLogFileDialog, LogLevel::Info,
+ ("remote file-dialog failed: kind=%s, where=%s, why=%08" PRIX32,
+ Error::KindName(err.kind), err.where.c_str(), err.why));
+ return Ok();
+ });
case RemoteWithFallback:
// more complicated; continue below
@@ -337,34 +431,40 @@ static auto AsyncExecute(Fn1 local, Fn2 remote, Args const&... args)
return remote(args...)->Then(
NS_GetCurrentThread(), kFunctionName,
- [t0](typename PromiseT::ResolveValueType result) -> RefPtr<PromiseT> {
+ [t0](typename RPromiseT::ResolveValueType result) -> RefPtr<PromiseT> {
// success; stop here
auto const t1 = GetTime();
// record success
telemetry::RecordSuccess({t0, t1});
- return PromiseT::CreateAndResolve(result, kFunctionName);
+ return PromiseT::CreateAndResolve(std::move(result), kFunctionName);
},
// initialized lambda pack captures are C++20 (clang 9, gcc 9);
// `make_tuple` is just a C++17 workaround
[=, tuple = std::make_tuple(Copy(args)...)](
- typename PromiseT::RejectValueType err) mutable -> RefPtr<PromiseT> {
+ typename RPromiseT::RejectValueType err) mutable -> RefPtr<PromiseT> {
// failure; record time
auto const t1 = GetTime();
- HRESULT const hrRemote = err;
+ // TODO: also propagate `err.where` into telemetry
+ HRESULT const hrRemote = err.why;
// retry locally...
auto p0 = std::apply(local, std::move(tuple));
// ...then record the telemetry event
return p0->Then(
NS_GetCurrentThread(), kFunctionName,
- [t0, t1,
- hrRemote](typename PromiseT::ResolveOrRejectValue const& val)
+ [t0, t1, hrRemote](typename LPromiseT::ResolveOrRejectValue&& val)
-> RefPtr<PromiseT> {
auto const t2 = GetTime();
- HRESULT const hrLocal = val.IsReject() ? val.RejectValue() : S_OK;
+ HRESULT const hrLocal =
+ val.IsReject() ? (HRESULT)val.RejectValue().why : S_OK;
telemetry::RecordFailure({t0, t1, t2}, hrRemote, hrLocal);
- return PromiseT::CreateAndResolveOrReject(val, kFunctionName);
+ using V = typename PromiseT::ResolveOrRejectValue;
+ return PromiseT::CreateAndResolveOrReject(
+ val.IsResolve()
+ ? V::MakeResolve(std::move(val).ResolveValue())
+ : V::MakeReject(Ok{}),
+ kFunctionName);
});
});
}
@@ -393,45 +493,6 @@ using fd_async::AsyncExecute;
} // namespace mozilla::detail
-/* static */
-nsFilePicker::FPPromise<filedialog::Results> nsFilePicker::ShowFilePickerRemote(
- HWND parent, filedialog::FileDialogType type,
- nsTArray<filedialog::Command> const& commands) {
- using mozilla::widget::filedialog::sLogFileDialog;
- return mozilla::detail::ShowRemote(
- [parent, type,
- commands = commands.Clone()](filedialog::WinFileDialogParent* p) {
- MOZ_LOG(sLogFileDialog, LogLevel::Info,
- ("%s: p = [%p]", __PRETTY_FUNCTION__, p));
- return p->SendShowFileDialog((uintptr_t)parent, type, commands);
- });
-}
-
-/* static */
-nsFilePicker::FPPromise<nsString> nsFilePicker::ShowFolderPickerRemote(
- HWND parent, nsTArray<filedialog::Command> const& commands) {
- using mozilla::widget::filedialog::sLogFileDialog;
- return mozilla::detail::ShowRemote([parent, commands = commands.Clone()](
- filedialog::WinFileDialogParent* p) {
- MOZ_LOG(sLogFileDialog, LogLevel::Info,
- ("%s: p = [%p]", __PRETTY_FUNCTION__, p));
- return p->SendShowFolderDialog((uintptr_t)parent, commands);
- });
-}
-
-/* static */
-nsFilePicker::FPPromise<filedialog::Results> nsFilePicker::ShowFilePickerLocal(
- HWND parent, filedialog::FileDialogType type,
- nsTArray<filedialog::Command> const& commands) {
- return filedialog::SpawnFilePicker(parent, type, commands.Clone());
-}
-
-/* static */
-nsFilePicker::FPPromise<nsString> nsFilePicker::ShowFolderPickerLocal(
- HWND parent, nsTArray<filedialog::Command> const& commands) {
- return filedialog::SpawnFolderPicker(parent, commands.Clone());
-}
-
/*
* Folder picker invocation
*/
@@ -447,16 +508,8 @@ nsFilePicker::FPPromise<nsString> nsFilePicker::ShowFolderPickerLocal(
* - resolves to false if the dialog was cancelled by the user;
* - is rejected with the associated HRESULT if some error occurred.
*/
-RefPtr<mozilla::MozPromise<bool, HRESULT, true>> nsFilePicker::ShowFolderPicker(
- const nsString& aInitialDir) {
- using Promise = mozilla::MozPromise<bool, HRESULT, true>;
- constexpr static auto Ok = [](bool val) {
- return Promise::CreateAndResolve(val, "nsFilePicker::ShowFolderPicker");
- };
- constexpr static auto NotOk = [](HRESULT val = E_FAIL) {
- return Promise::CreateAndReject(val, "nsFilePicker::ShowFolderPicker");
- };
-
+RefPtr<mozilla::MozPromise<bool, nsFilePicker::Unit, true>>
+nsFilePicker::ShowFolderPicker(const nsString& aInitialDir) {
namespace fd = ::mozilla::widget::filedialog;
nsTArray<fd::Command> commands = {
fd::SetOptions(FOS_PICKFOLDERS),
@@ -474,23 +527,18 @@ RefPtr<mozilla::MozPromise<bool, HRESULT, true>> nsFilePicker::ShowFolderPicker(
ScopedRtlShimWindow shim(mParentWidget.get());
AutoWidgetPickerState awps(mParentWidget);
- return mozilla::detail::AsyncExecute(&ShowFolderPickerLocal,
- &ShowFolderPickerRemote, shim.get(),
- commands)
- ->Then(
- NS_GetCurrentThread(), __PRETTY_FUNCTION__,
- [self = RefPtr(this), shim = std::move(shim),
- awps = std::move(awps)](Maybe<nsString> val) {
- if (val) {
- self->mUnicodeFile = val.extract();
- return Ok(true);
- }
- return Ok(false);
- },
- [](HRESULT err) {
- NS_WARNING("ShowFolderPicker failed");
- return NotOk(err);
- });
+ return mozilla::detail::AsyncExecute(&mozilla::detail::ShowFolderPickerLocal,
+ &mozilla::detail::ShowFolderPickerRemote,
+ shim.get(), commands)
+ ->Map(NS_GetCurrentThread(), __PRETTY_FUNCTION__,
+ [self = RefPtr(this), shim = std::move(shim),
+ awps = std::move(awps)](Maybe<nsString> val) {
+ if (val) {
+ self->mUnicodeFile = val.extract();
+ return true;
+ }
+ return false;
+ });
}
/*
@@ -508,16 +556,16 @@ RefPtr<mozilla::MozPromise<bool, HRESULT, true>> nsFilePicker::ShowFolderPicker(
* - resolves to false if the dialog was cancelled by the user;
* - is rejected with the associated HRESULT if some error occurred.
*/
-RefPtr<mozilla::MozPromise<bool, HRESULT, true>> nsFilePicker::ShowFilePicker(
- const nsString& aInitialDir) {
+RefPtr<mozilla::MozPromise<bool, nsFilePicker::Unit, true>>
+nsFilePicker::ShowFilePicker(const nsString& aInitialDir) {
AUTO_PROFILER_LABEL("nsFilePicker::ShowFilePicker", OTHER);
- using Promise = mozilla::MozPromise<bool, HRESULT, true>;
+ using Promise = mozilla::MozPromise<bool, Unit, true>;
constexpr static auto Ok = [](bool val) {
return Promise::CreateAndResolve(val, "nsFilePicker::ShowFilePicker");
};
- constexpr static auto NotOk = [](HRESULT val = E_FAIL) {
- return Promise::CreateAndReject(val, "nsFilePicker::ShowFilePicker");
+ constexpr static auto NotOk = []() {
+ return Promise::CreateAndReject(Unit(), "nsFilePicker::ShowFilePicker");
};
namespace fd = ::mozilla::widget::filedialog;
@@ -551,7 +599,7 @@ RefPtr<mozilla::MozPromise<bool, HRESULT, true>> nsFilePicker::ShowFilePicker(
case modeGetFolder:
MOZ_ASSERT(false, "file-picker opened in directory-picker mode");
- return NotOk(E_FAIL);
+ return NotOk();
}
commands.AppendElement(fd::SetOptions(fos));
@@ -605,7 +653,8 @@ RefPtr<mozilla::MozPromise<bool, HRESULT, true>> nsFilePicker::ShowFilePicker(
auto type = mMode == modeSave ? FileDialogType::Save : FileDialogType::Open;
auto promise = mozilla::detail::AsyncExecute(
- &ShowFilePickerLocal, &ShowFilePickerRemote, shim.get(), type, commands);
+ &mozilla::detail::ShowFilePickerLocal,
+ &mozilla::detail::ShowFilePickerRemote, shim.get(), type, commands);
return promise->Then(
mozilla::GetMainThreadSerialEventTarget(), __PRETTY_FUNCTION__,
@@ -641,9 +690,9 @@ RefPtr<mozilla::MozPromise<bool, HRESULT, true>> nsFilePicker::ShowFilePicker(
return Ok(true);
},
- [](HRESULT err) {
+ [](Unit err) {
NS_WARNING("ShowFilePicker failed");
- return NotOk(err);
+ return NotOk();
});
}
@@ -752,43 +801,29 @@ nsFilePicker::CheckContentAnalysisService() {
return promise;
};
- // Since getting the files to analyze might be asynchronous, use a MozPromise
- // to unify the logic below.
- auto getFilesToAnalyzePromise = mozilla::MakeRefPtr<mozilla::MozPromise<
- nsTArray<mozilla::PathString>, nsresult, true>::Private>(__func__);
+ nsCOMArray<nsIFile> files;
if (mMode == modeGetFolder) {
- nsCOMPtr<nsISupports> tmp;
- nsresult rv = GetDomFileOrDirectory(getter_AddRefs(tmp));
+ nsCOMPtr<nsIFile> file;
+ nsresult rv = GetFile(getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
- getFilesToAnalyzePromise->Reject(rv, __func__);
return nsFilePicker::ContentAnalysisResponse::CreateAndReject(rv,
__func__);
}
- auto* directory = static_cast<mozilla::dom::Directory*>(tmp.get());
- mozilla::dom::OwningFileOrDirectory owningDirectory;
- owningDirectory.SetAsDirectory() = directory;
- nsTArray<mozilla::dom::OwningFileOrDirectory> directoryArray{
- std::move(owningDirectory)};
-
- mozilla::ErrorResult error;
- RefPtr<mozilla::dom::GetFilesHelper> helper =
- mozilla::dom::GetFilesHelper::Create(directoryArray, true, error);
- rv = error.StealNSResult();
+ nsCOMPtr<nsIDirectoryEnumerator> iter;
+ rv = file->GetDirectoryEntries(getter_AddRefs(iter));
if (NS_WARN_IF(NS_FAILED(rv))) {
- getFilesToAnalyzePromise->Reject(rv, __func__);
return nsFilePicker::ContentAnalysisResponse::CreateAndReject(rv,
__func__);
}
- auto getFilesCallback = mozilla::MakeRefPtr<GetFilesInDirectoryCallback>(
- getFilesToAnalyzePromise);
- helper->AddCallback(getFilesCallback);
+ nsCOMPtr<nsIFile> entry;
+ while (NS_SUCCEEDED(iter->GetNextFile(getter_AddRefs(entry))) && entry) {
+ files.AppendElement(entry);
+ }
} else {
- nsCOMArray<nsIFile> files;
if (!mUnicodeFile.IsEmpty()) {
nsCOMPtr<nsIFile> file;
rv = GetFile(getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
- getFilesToAnalyzePromise->Reject(rv, __func__);
return nsFilePicker::ContentAnalysisResponse::CreateAndReject(rv,
__func__);
}
@@ -796,22 +831,13 @@ nsFilePicker::CheckContentAnalysisService() {
} else {
files.AppendElements(mFiles);
}
- nsTArray<mozilla::PathString> paths(files.Length());
- std::transform(files.begin(), files.end(), MakeBackInserter(paths),
- [](auto* entry) { return entry->NativePath(); });
- getFilesToAnalyzePromise->Resolve(std::move(paths), __func__);
}
+ nsTArray<mozilla::PathString> paths(files.Length());
+ std::transform(files.begin(), files.end(), MakeBackInserter(paths),
+ [](auto* entry) { return entry->NativePath(); });
- return getFilesToAnalyzePromise->Then(
- mozilla::GetMainThreadSerialEventTarget(), __func__,
- [processOneItem](nsTArray<mozilla::PathString> aPaths) mutable {
- return mozilla::detail::AsyncAll<mozilla::PathString>(std::move(aPaths),
- processOneItem);
- },
- [](nsresult aError) {
- return nsFilePicker::ContentAnalysisResponse::CreateAndReject(aError,
- __func__);
- });
+ return mozilla::detail::AsyncAll<mozilla::PathString>(std::move(paths),
+ processOneItem);
};
///////////////////////////////////////////////////////////////////////////////
@@ -891,10 +917,8 @@ nsresult nsFilePicker::Open(nsIFilePickerShownCallback* aCallback) {
callback->Done(retValue);
},
- [callback = RefPtr(aCallback)](HRESULT err) {
- using mozilla::widget::filedialog::sLogFileDialog;
- MOZ_LOG(sLogFileDialog, LogLevel::Error,
- ("nsFilePicker: Show failed with hr=0x%08lX", err));
+ [callback = RefPtr(aCallback)](Unit _) {
+ // logging already handled
callback->Done(ResultCode::returnCancel);
});
diff --git a/widget/windows/nsFilePicker.h b/widget/windows/nsFilePicker.h
index 59108bc0dd..5a4272d30f 100644
--- a/widget/windows/nsFilePicker.h
+++ b/widget/windows/nsFilePicker.h
@@ -56,8 +56,6 @@ class nsFilePicker final : public nsBaseWinFilePicker {
using Maybe = mozilla::Maybe<T>;
template <typename T>
using Result = mozilla::Result<T, HRESULT>;
- template <typename Res>
- using FPPromise = RefPtr<mozilla::MozPromise<Maybe<Res>, HRESULT, true>>;
using Command = mozilla::widget::filedialog::Command;
using Results = mozilla::widget::filedialog::Results;
@@ -89,23 +87,12 @@ class nsFilePicker final : public nsBaseWinFilePicker {
NS_IMETHOD Open(nsIFilePickerShownCallback* aCallback) override;
private:
- RefPtr<mozilla::MozPromise<bool, HRESULT, true>> ShowFolderPicker(
+ using Unit = mozilla::Ok;
+ RefPtr<mozilla::MozPromise<bool, Unit, true>> ShowFolderPicker(
const nsString& aInitialDir);
- RefPtr<mozilla::MozPromise<bool, HRESULT, true>> ShowFilePicker(
+ RefPtr<mozilla::MozPromise<bool, Unit, true>> ShowFilePicker(
const nsString& aInitialDir);
- // Show the dialog out-of-process.
- static FPPromise<Results> ShowFilePickerRemote(
- HWND aParent, FileDialogType type, nsTArray<Command> const& commands);
- static FPPromise<nsString> ShowFolderPickerRemote(
- HWND aParent, nsTArray<Command> const& commands);
-
- // Show the dialog in-process.
- static FPPromise<Results> ShowFilePickerLocal(
- HWND aParent, FileDialogType type, nsTArray<Command> const& commands);
- static FPPromise<nsString> ShowFolderPickerLocal(
- HWND aParent, nsTArray<Command> const& commands);
-
void ClearFiles();
using ContentAnalysisResponse = mozilla::MozPromise<bool, nsresult, true>;
RefPtr<ContentAnalysisResponse> CheckContentAnalysisService();
diff --git a/widget/windows/nsNativeThemeWin.cpp b/widget/windows/nsNativeThemeWin.cpp
index 7ef968baf6..b988fb4ec5 100644
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -481,6 +481,7 @@ mozilla::Maybe<nsUXThemeClass> nsNativeThemeWin::GetThemeClass(
case StyleAppearance::Button:
return Some(eUXButton);
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
return Some(eUXEdit);
@@ -500,12 +501,7 @@ mozilla::Maybe<nsUXThemeClass> nsNativeThemeWin::GetThemeClass(
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
return Some(eUXCombobox);
- case StyleAppearance::Treeheadercell:
- return Some(eUXHeader);
case StyleAppearance::Listbox:
- case StyleAppearance::Treeview:
- case StyleAppearance::Treetwistyopen:
- case StyleAppearance::Treeitem:
return Some(eUXListview);
default:
return Nothing();
@@ -594,6 +590,7 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame,
return NS_OK;
}
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea: {
ElementState elementState = GetContentState(aFrame, aAppearance);
@@ -716,7 +713,6 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame,
}
return NS_OK;
}
- case StyleAppearance::Treeview:
case StyleAppearance::Listbox: {
aPart = TREEVIEW_BODY;
aState = TS_NORMAL;
@@ -753,17 +749,6 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame,
return NS_OK;
}
- case StyleAppearance::Treeheadercell: {
- aPart = 1;
- if (!aFrame) {
- aState = TS_NORMAL;
- return NS_OK;
- }
-
- aState = StandardGetState(aFrame, aAppearance, true);
-
- return NS_OK;
- }
case StyleAppearance::MenulistButton:
case StyleAppearance::Menulist: {
nsIContent* content = aFrame->GetContent();
@@ -956,6 +941,7 @@ RENDER_AGAIN:
DrawThemeBackground(theme, hdc, part, state, &contentRect, &clipRect);
} else if (aAppearance == StyleAppearance::NumberInput ||
+ aAppearance == StyleAppearance::PasswordInput ||
aAppearance == StyleAppearance::Textfield ||
aAppearance == StyleAppearance::Textarea) {
DrawThemeBackground(theme, hdc, part, state, &widgetRect, &clipRect);
@@ -1088,6 +1074,7 @@ LayoutDeviceIntMargin nsNativeThemeWin::GetWidgetBorder(
}
if (aFrame && (aAppearance == StyleAppearance::NumberInput ||
+ aAppearance == StyleAppearance::PasswordInput ||
aAppearance == StyleAppearance::Textfield ||
aAppearance == StyleAppearance::Textarea)) {
nsIContent* content = aFrame->GetContent();
@@ -1128,6 +1115,7 @@ bool nsNativeThemeWin::GetWidgetPadding(nsDeviceContext* aContext,
* added, see bug 430212)
*/
if (aAppearance == StyleAppearance::NumberInput ||
+ aAppearance == StyleAppearance::PasswordInput ||
aAppearance == StyleAppearance::Textfield ||
aAppearance == StyleAppearance::Textarea) {
aResult->top = aResult->bottom = 2;
@@ -1236,12 +1224,12 @@ LayoutDeviceIntSize nsNativeThemeWin::GetMinimumWidgetSize(
switch (aAppearance) {
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Progresschunk:
case StyleAppearance::Tabpanels:
case StyleAppearance::Tabpanel:
case StyleAppearance::Listbox:
- case StyleAppearance::Treeview:
return {}; // Don't worry about it.
default:
break;
@@ -1386,6 +1374,7 @@ bool nsNativeThemeWin::ThemeDrawsFocusForWidget(nsIFrame* aFrame,
case StyleAppearance::Textarea:
case StyleAppearance::Textfield:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
return true;
default:
return false;
@@ -1438,6 +1427,7 @@ bool nsNativeThemeWin::ClassicThemeSupportsWidget(nsIFrame* aFrame,
switch (aAppearance) {
case StyleAppearance::Button:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::Range:
@@ -1445,7 +1435,6 @@ bool nsNativeThemeWin::ClassicThemeSupportsWidget(nsIFrame* aFrame,
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
case StyleAppearance::Listbox:
- case StyleAppearance::Treeview:
case StyleAppearance::ProgressBar:
case StyleAppearance::Progresschunk:
case StyleAppearance::Tab:
@@ -1465,11 +1454,11 @@ LayoutDeviceIntMargin nsNativeThemeWin::ClassicGetWidgetBorder(
result.top = result.left = result.bottom = result.right = 2;
break;
case StyleAppearance::Listbox:
- case StyleAppearance::Treeview:
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
case StyleAppearance::Tab:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
result.top = result.left = result.bottom = result.right = 2;
@@ -1516,8 +1505,8 @@ LayoutDeviceIntSize nsNativeThemeWin::ClassicGetMinimumWidgetSize(
case StyleAppearance::MenulistButton:
case StyleAppearance::Button:
case StyleAppearance::Listbox:
- case StyleAppearance::Treeview:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::Progresschunk:
@@ -1574,8 +1563,8 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(
return NS_OK;
}
case StyleAppearance::Listbox:
- case StyleAppearance::Treeview:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::Menulist:
@@ -1767,6 +1756,7 @@ RENDER_AGAIN:
}
// Draw controls with 2px 3D inset border
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::Listbox:
@@ -1787,15 +1777,6 @@ RENDER_AGAIN:
break;
}
- case StyleAppearance::Treeview: {
- // Draw inset edge
- ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
-
- // Fill in window color background
- ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_WINDOW + 1));
-
- break;
- }
// Draw 3D face background controls
case StyleAppearance::ProgressBar:
// Draw 3D border
@@ -1903,6 +1884,7 @@ uint32_t nsNativeThemeWin::GetWidgetNativeDrawingFlags(
switch (aAppearance) {
case StyleAppearance::Button:
case StyleAppearance::NumberInput:
+ case StyleAppearance::PasswordInput:
case StyleAppearance::Textfield:
case StyleAppearance::Textarea:
case StyleAppearance::Menulist:
diff --git a/widget/windows/nsUXThemeData.cpp b/widget/windows/nsUXThemeData.cpp
index ce8b0f3479..88546b01c6 100644
--- a/widget/windows/nsUXThemeData.cpp
+++ b/widget/windows/nsUXThemeData.cpp
@@ -72,8 +72,6 @@ const wchar_t* nsUXThemeData::GetClassName(nsUXThemeClass cls) {
return L"Trackbar";
case eUXCombobox:
return L"Combobox";
- case eUXHeader:
- return L"Header";
case eUXListview:
return L"Listview";
case eUXMenu:
diff --git a/widget/windows/nsUXThemeData.h b/widget/windows/nsUXThemeData.h
index 24fe07d128..b59c2aae04 100644
--- a/widget/windows/nsUXThemeData.h
+++ b/widget/windows/nsUXThemeData.h
@@ -24,7 +24,6 @@ enum nsUXThemeClass {
eUXTab,
eUXTrackbar,
eUXCombobox,
- eUXHeader,
eUXListview,
eUXMenu,
eUXNumClasses
diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp
index 22d20d099e..ac393e8b09 100644
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -166,7 +166,6 @@
#include "mozilla/StaticPrefs_ui.h"
#include "mozilla/StaticPrefs_widget.h"
#include "nsNativeAppSupportWin.h"
-#include "mozilla/browser/NimbusFeatures.h"
#include "nsIGfxInfo.h"
#include "nsUXThemeConstants.h"
@@ -188,7 +187,6 @@
# include "mozilla/a11y/DocAccessible.h"
# include "mozilla/a11y/LazyInstantiator.h"
# include "mozilla/a11y/Platform.h"
-# include "mozilla/StaticPrefs_accessibility.h"
# if !defined(WINABLEAPI)
# include <winable.h>
# endif // !defined(WINABLEAPI)
@@ -348,6 +346,12 @@ static SystemTimeConverter<DWORD>& TimeConverter() {
return timeConverterSingleton;
}
+static const wchar_t* GetMainWindowClass();
+static const wchar_t* ChooseWindowClass(mozilla::widget::WindowType);
+// This method registers the given window class, and returns the class name.
+static void RegisterWindowClass(const wchar_t* aClassName, UINT aExtraStyle,
+ LPWSTR aIconID);
+
// Global event hook for window cloaking. Never deregistered.
// - `Nothing` if not yet set.
// - `Some(nullptr)` if no attempt should be made to set it.
@@ -990,13 +994,11 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
}
if (aInitData->mIsPrivate) {
- if (NimbusFeatures::GetBool("majorRelease2022"_ns,
- "feltPrivacyWindowSeparation"_ns, true) &&
- // Although permanent Private Browsing mode is indeed Private Browsing,
- // we choose to make it look like regular Firefox in terms of the icon
- // it uses (which also means we shouldn't use the Private Browsing
- // AUMID).
- !StaticPrefs::browser_privatebrowsing_autostart()) {
+ // Although permanent Private Browsing mode is indeed Private Browsing,
+ // we choose to make it look like regular Firefox in terms of the icon
+ // it uses (which also means we shouldn't use the Private Browsing
+ // AUMID).
+ if (!StaticPrefs::browser_privatebrowsing_autostart()) {
RefPtr<IPropertyStore> pPropStore;
if (!FAILED(SHGetPropertyStoreForWindow(mWnd, IID_IPropertyStore,
getter_AddRefs(pPropStore)))) {
@@ -1189,40 +1191,28 @@ void nsWindow::Destroy() {
*
**************************************************************/
-/* static */
-const wchar_t* nsWindow::RegisterWindowClass(const wchar_t* aClassName,
- UINT aExtraStyle, LPWSTR aIconID) {
- WNDCLASSW wc;
+static void RegisterWindowClass(const wchar_t* aClassName, UINT aExtraStyle,
+ LPWSTR aIconID) {
+ WNDCLASSW wc = {};
if (::GetClassInfoW(nsToolkit::mDllInstance, aClassName, &wc)) {
// already registered
- return aClassName;
+ return;
}
wc.style = CS_DBLCLKS | aExtraStyle;
wc.lpfnWndProc = WinUtils::NonClientDpiScalingDefWindowProcW;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
wc.hInstance = nsToolkit::mDllInstance;
wc.hIcon =
aIconID ? ::LoadIconW(::GetModuleHandleW(nullptr), aIconID) : nullptr;
- wc.hCursor = nullptr;
- wc.hbrBackground = nullptr;
- wc.lpszMenuName = nullptr;
wc.lpszClassName = aClassName;
- if (!::RegisterClassW(&wc)) {
- // For older versions of Win32 (i.e., not XP), the registration may
- // fail with aExtraStyle, so we have to re-register without it.
- wc.style = CS_DBLCLKS;
- ::RegisterClassW(&wc);
- }
- return aClassName;
+ // Failures are ignored as they are handled when ::CreateWindow fails
+ ::RegisterClassW(&wc);
}
static LPWSTR const gStockApplicationIcon = MAKEINTRESOURCEW(32512);
-/* static */
-const wchar_t* nsWindow::ChooseWindowClass(WindowType aWindowType) {
+static const wchar_t* ChooseWindowClass(WindowType aWindowType) {
const wchar_t* className = [aWindowType] {
switch (aWindowType) {
case WindowType::Invisible:
@@ -1235,7 +1225,8 @@ const wchar_t* nsWindow::ChooseWindowClass(WindowType aWindowType) {
return GetMainWindowClass();
}
}();
- return RegisterWindowClass(className, 0, gStockApplicationIcon);
+ RegisterWindowClass(className, 0, gStockApplicationIcon);
+ return className;
}
/**************************************************************
@@ -1246,24 +1237,62 @@ const wchar_t* nsWindow::ChooseWindowClass(WindowType aWindowType) {
*
**************************************************************/
+const DWORD kTitlebarItemsWindowStyles =
+ WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
+const DWORD kAllBorderStyles =
+ kTitlebarItemsWindowStyles | WS_THICKFRAME | WS_DLGFRAME;
+
+static DWORD WindowStylesRemovedForBorderStyle(BorderStyle aStyle) {
+ if (aStyle == BorderStyle::Default || aStyle == BorderStyle::All) {
+ return 0;
+ }
+ if (aStyle == BorderStyle::None) {
+ return kAllBorderStyles;
+ }
+ DWORD toRemove = 0;
+ if (!(aStyle & BorderStyle::Border)) {
+ toRemove |= WS_BORDER;
+ }
+ if (!(aStyle & BorderStyle::Title)) {
+ toRemove |= WS_DLGFRAME;
+ }
+ if (!(aStyle & (BorderStyle::Menu | BorderStyle::Close))) {
+ // Looks like getting rid of the system menu also does away with the close
+ // box. So, we only get rid of the system menu and the close box if you
+ // want neither. How does the Windows "Dialog" window class get just
+ // closebox and no sysmenu? Who knows.
+ toRemove |= WS_SYSMENU;
+ }
+ if (!(aStyle & BorderStyle::ResizeH)) {
+ toRemove |= WS_THICKFRAME;
+ }
+ if (!(aStyle & BorderStyle::Minimize)) {
+ toRemove |= WS_MINIMIZEBOX;
+ }
+ if (!(aStyle & BorderStyle::Maximize)) {
+ toRemove |= WS_MAXIMIZEBOX;
+ }
+ return toRemove;
+}
+
// Return nsWindow styles
DWORD nsWindow::WindowStyle() {
DWORD style;
-
switch (mWindowType) {
case WindowType::Child:
style = WS_OVERLAPPED;
break;
case WindowType::Dialog:
- style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_3DLOOK |
+ style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU |
DS_MODALFRAME | WS_CLIPCHILDREN;
- if (mBorderStyle != BorderStyle::Default)
+ if (mBorderStyle != BorderStyle::Default) {
style |= WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
+ }
break;
case WindowType::Popup:
- style = WS_POPUP | WS_OVERLAPPED;
+ style = WS_OVERLAPPED | WS_POPUP;
break;
default:
@@ -1272,48 +1301,12 @@ DWORD nsWindow::WindowStyle() {
case WindowType::TopLevel:
case WindowType::Invisible:
- style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU |
- WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPCHILDREN;
+ style = WS_OVERLAPPED | WS_CLIPCHILDREN | WS_DLGFRAME | WS_BORDER |
+ WS_THICKFRAME | kTitlebarItemsWindowStyles;
break;
}
- if (mBorderStyle != BorderStyle::Default &&
- mBorderStyle != BorderStyle::All) {
- if (mBorderStyle == BorderStyle::None ||
- !(mBorderStyle & BorderStyle::Border))
- style &= ~WS_BORDER;
-
- if (mBorderStyle == BorderStyle::None ||
- !(mBorderStyle & BorderStyle::Title)) {
- style &= ~WS_DLGFRAME;
- }
-
- if (mBorderStyle == BorderStyle::None ||
- !(mBorderStyle & BorderStyle::Close))
- style &= ~0;
- // XXX The close box can only be removed by changing the window class,
- // as far as I know --- roc+moz@cs.cmu.edu
-
- if (mBorderStyle == BorderStyle::None ||
- !(mBorderStyle & (BorderStyle::Menu | BorderStyle::Close)))
- style &= ~WS_SYSMENU;
- // Looks like getting rid of the system menu also does away with the
- // close box. So, we only get rid of the system menu if you want neither it
- // nor the close box. How does the Windows "Dialog" window class get just
- // closebox and no sysmenu? Who knows.
-
- if (mBorderStyle == BorderStyle::None ||
- !(mBorderStyle & BorderStyle::ResizeH))
- style &= ~WS_THICKFRAME;
-
- if (mBorderStyle == BorderStyle::None ||
- !(mBorderStyle & BorderStyle::Minimize))
- style &= ~WS_MINIMIZEBOX;
-
- if (mBorderStyle == BorderStyle::None ||
- !(mBorderStyle & BorderStyle::Maximize))
- style &= ~WS_MAXIMIZEBOX;
- }
+ style &= ~WindowStylesRemovedForBorderStyle(mBorderStyle);
if (mIsChildWindow) {
style |= WS_CLIPCHILDREN;
@@ -2471,46 +2464,6 @@ void nsWindow::ResetLayout() {
Invalidate();
}
-// Internally track the caption status via a window property. Required
-// due to our internal handling of WM_NCACTIVATE when custom client
-// margins are set.
-static const wchar_t kManageWindowInfoProperty[] = L"ManageWindowInfoProperty";
-typedef BOOL(WINAPI* GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
-static WindowsDllInterceptor::FuncHookType<GetWindowInfoPtr>
- sGetWindowInfoPtrStub;
-
-BOOL WINAPI GetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi) {
- if (!sGetWindowInfoPtrStub) {
- NS_ASSERTION(FALSE, "Something is horribly wrong in GetWindowInfoHook!");
- return FALSE;
- }
- int windowStatus =
- reinterpret_cast<LONG_PTR>(GetPropW(hWnd, kManageWindowInfoProperty));
- // No property set, return the default data.
- if (!windowStatus) return sGetWindowInfoPtrStub(hWnd, pwi);
- // Call GetWindowInfo and update dwWindowStatus with our
- // internally tracked value.
- BOOL result = sGetWindowInfoPtrStub(hWnd, pwi);
- if (result && pwi)
- pwi->dwWindowStatus = (windowStatus == 1 ? 0 : WS_ACTIVECAPTION);
- return result;
-}
-
-void nsWindow::UpdateGetWindowInfoCaptionStatus(bool aActiveCaption) {
- if (!mWnd) return;
-
- sUser32Intercept.Init("user32.dll");
- sGetWindowInfoPtrStub.Set(sUser32Intercept, "GetWindowInfo",
- &GetWindowInfoHook);
- if (!sGetWindowInfoPtrStub) {
- return;
- }
-
- // Update our internally tracked caption status
- SetPropW(mWnd, kManageWindowInfoProperty,
- reinterpret_cast<HANDLE>(static_cast<INT_PTR>(aActiveCaption) + 1));
-}
-
#define DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 19
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
@@ -2703,6 +2656,8 @@ bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
mNonClientOffset = NormalWindowNonClientOffset();
}
+ UpdateOpaqueRegionInternal();
+
if (aReflowWindow) {
// Force a reflow of content based on the new client
// dimensions.
@@ -2713,8 +2668,9 @@ bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
}
nsresult nsWindow::SetNonClientMargins(const LayoutDeviceIntMargin& margins) {
- if (!mIsTopWidgetWindow || mBorderStyle == BorderStyle::None)
+ if (!mIsTopWidgetWindow || mBorderStyle == BorderStyle::None) {
return NS_ERROR_INVALID_ARG;
+ }
if (mHideChrome) {
mFutureMarginsOnceChromeShows = margins;
@@ -2731,19 +2687,13 @@ nsresult nsWindow::SetNonClientMargins(const LayoutDeviceIntMargin& margins) {
// Force a reflow of content based on the new client
// dimensions.
ResetLayout();
-
- int windowStatus =
- reinterpret_cast<LONG_PTR>(GetPropW(mWnd, kManageWindowInfoProperty));
- if (windowStatus) {
- ::SendMessageW(mWnd, WM_NCACTIVATE, 1 != windowStatus, 0);
- }
-
return NS_OK;
}
if (margins.top < -1 || margins.bottom < -1 || margins.left < -1 ||
- margins.right < -1)
+ margins.right < -1) {
return NS_ERROR_INVALID_ARG;
+ }
mNonClientMargins = margins;
mCustomNonClient = true;
@@ -3999,10 +3949,8 @@ uint32_t nsWindow::GetMaxTouchPoints() const {
return WinUtils::GetMaxTouchPoints();
}
-void nsWindow::SetWindowClass(const nsAString& xulWinType,
- const nsAString& xulWinClass,
- const nsAString& xulWinName) {
- mIsEarlyBlankWindow = xulWinType.EqualsLiteral("navigator:blank");
+void nsWindow::SetIsEarlyBlankWindow(bool aIsEarlyBlankWindow) {
+ mIsEarlyBlankWindow = aIsEarlyBlankWindow;
}
/**************************************************************
@@ -5194,8 +5142,6 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
* WM_NCACTIVATE paints nc areas. Avoid this and re-route painting
* through WM_NCPAINT via InvalidateNonClientRegion.
*/
- UpdateGetWindowInfoCaptionStatus(FALSE != wParam);
-
if (!mCustomNonClient) {
break;
}
@@ -5684,9 +5630,6 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
if (WinUtils::LogToPhysFactor(mWnd) != mDefaultScale) {
ChangedDPI();
ResetLayout();
- if (mWidgetListener) {
- mWidgetListener->UIResolutionChanged();
- }
}
}
break;
@@ -5724,9 +5667,6 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
case WM_DISPLAYCHANGE: {
ScreenHelperWin::RefreshScreens();
- if (mWidgetListener) {
- mWidgetListener->UIResolutionChanged();
- }
break;
}
@@ -5925,19 +5865,12 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
a11y::LazyInstantiator::EnableBlindAggregation(mWnd);
result = true;
}
- } else if (objId == UiaRootObjectId &&
- StaticPrefs::accessibility_uia_enable()) {
- if (a11y::LocalAccessible* acc = GetAccessible()) {
- RefPtr<IAccessible> ia;
- acc->GetNativeInterface(getter_AddRefs(ia));
- MOZ_ASSERT(ia);
- RefPtr<IRawElementProviderSimple> uia;
- ia->QueryInterface(IID_IRawElementProviderSimple,
- getter_AddRefs(uia));
- if (uia) {
- *aRetValue = UiaReturnRawElementProvider(mWnd, wParam, lParam, uia);
- result = true;
- }
+ } else if (objId == UiaRootObjectId) {
+ if (RefPtr<IRawElementProviderSimple> root =
+ a11y::LazyInstantiator::GetRootUia(mWnd)) {
+ *aRetValue = UiaReturnRawElementProvider(mWnd, wParam, lParam, root);
+ a11y::LazyInstantiator::EnableBlindAggregation(mWnd);
+ result = true;
}
}
} break;
@@ -7420,7 +7353,9 @@ a11y::LocalAccessible* nsWindow::GetAccessible() {
**************************************************************/
void nsWindow::SetWindowTranslucencyInner(TransparencyMode aMode) {
- if (aMode == mTransparencyMode) return;
+ if (aMode == mTransparencyMode) {
+ return;
+ }
// stop on dialogs and popups!
HWND hWnd = WinUtils::GetTopLevelHWND(mWnd, true);
@@ -7458,10 +7393,11 @@ void nsWindow::SetWindowTranslucencyInner(TransparencyMode aMode) {
}
}
- if (aMode == TransparencyMode::Transparent)
+ if (aMode == TransparencyMode::Transparent) {
exStyle |= WS_EX_LAYERED;
- else
+ } else {
exStyle &= ~WS_EX_LAYERED;
+ }
VERIFY_WINDOW_STYLE(style);
::SetWindowLongPtrW(hWnd, GWL_STYLE, style);
@@ -7469,11 +7405,47 @@ void nsWindow::SetWindowTranslucencyInner(TransparencyMode aMode) {
mTransparencyMode = aMode;
+ UpdateOpaqueRegionInternal();
+
if (mCompositorWidgetDelegate) {
mCompositorWidgetDelegate->UpdateTransparency(aMode);
}
}
+void nsWindow::UpdateOpaqueRegion(const LayoutDeviceIntRegion& aRegion) {
+ if (aRegion == mOpaqueRegion) {
+ return;
+ }
+ mOpaqueRegion = aRegion;
+ UpdateOpaqueRegionInternal();
+}
+
+void nsWindow::UpdateOpaqueRegionInternal() {
+ MARGINS margins{0};
+ if (mTransparencyMode == TransparencyMode::Transparent) {
+ // If there is no opaque region, set margins to support a full sheet of
+ // glass. Comments in MSDN indicate all values must be set to -1 to get a
+ // full sheet of glass.
+ margins = {-1, -1, -1, -1};
+ if (!mOpaqueRegion.IsEmpty()) {
+ LayoutDeviceIntRect clientBounds = GetClientBounds();
+ // Find the largest rectangle and use that to calculate the inset.
+ LayoutDeviceIntRect largest = mOpaqueRegion.GetLargestRectangle();
+ margins.cxLeftWidth = largest.X();
+ margins.cxRightWidth = clientBounds.Width() - largest.XMost();
+ margins.cyBottomHeight = clientBounds.Height() - largest.YMost();
+ margins.cyTopHeight = largest.Y();
+
+ auto ncmargin = NonClientSizeMargin();
+ margins.cxLeftWidth += ncmargin.left;
+ margins.cyTopHeight += ncmargin.top;
+ margins.cxRightWidth += ncmargin.right;
+ margins.cyBottomHeight += ncmargin.bottom;
+ }
+ }
+ DwmExtendFrameIntoClientArea(mWnd, &margins);
+}
+
/**************************************************************
**************************************************************
**
@@ -8200,7 +8172,7 @@ bool nsWindow::CanTakeFocus() {
return false;
}
-/* static */ const wchar_t* nsWindow::GetMainWindowClass() {
+static const wchar_t* GetMainWindowClass() {
static const wchar_t* sMainWindowClass = nullptr;
if (!sMainWindowClass) {
nsAutoString className;
diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h
index a2b2a701bd..9c4b4417f8 100644
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -261,8 +261,7 @@ class nsWindow final : public nsBaseWidget {
const LayoutDeviceIntRegion& aRegion) override;
uint32_t GetMaxTouchPoints() const override;
- void SetWindowClass(const nsAString& xulWinType, const nsAString& xulWinClass,
- const nsAString& xulWinName) override;
+ void SetIsEarlyBlankWindow(bool) override;
/**
* Event helpers
@@ -518,10 +517,8 @@ class nsWindow final : public nsBaseWidget {
bool CanTakeFocus();
bool UpdateNonClientMargins(bool aReflowWindow = true);
void UpdateDarkModeToolbar();
- void UpdateGetWindowInfoCaptionStatus(bool aActiveCaption);
void ResetLayout();
void InvalidateNonClientRegion();
- static const wchar_t* GetMainWindowClass();
HWND GetOwnerWnd() const { return ::GetWindow(mWnd, GW_OWNER); }
bool IsOwnerForegroundWindow() const {
HWND owner = GetOwnerWnd();
@@ -592,11 +589,6 @@ class nsWindow final : public nsBaseWidget {
DWORD WindowStyle();
DWORD WindowExStyle();
- static const wchar_t* ChooseWindowClass(WindowType);
- // This method registers the given window class, and returns the class name.
- static const wchar_t* RegisterWindowClass(const wchar_t* aClassName,
- UINT aExtraStyle, LPWSTR aIconID);
-
/**
* Popup hooks
*/
@@ -620,6 +612,9 @@ class nsWindow final : public nsBaseWidget {
bool IsSimulatedClientArea(int32_t clientX, int32_t clientY);
bool IsWindowButton(int32_t hitTestResult);
+ void UpdateOpaqueRegion(const LayoutDeviceIntRegion&) override;
+ void UpdateOpaqueRegionInternal();
+
bool DispatchTouchEventFromWMPointer(UINT msg, LPARAM aLParam,
const WinPointerInfo& aPointerInfo,
mozilla::MouseButton aButton);
@@ -808,6 +803,8 @@ class nsWindow final : public nsBaseWidget {
// Draggable titlebar region maintained by UpdateWindowDraggingRegion
LayoutDeviceIntRegion mDraggableRegion;
+ // Opaque region maintained by UpdateOpaqueRegion
+ LayoutDeviceIntRegion mOpaqueRegion;
// Graphics
LayoutDeviceIntRect mLastPaintBounds;
@@ -816,7 +813,6 @@ class nsWindow final : public nsBaseWidget {
// Transparency
TransparencyMode mTransparencyMode = TransparencyMode::Opaque;
- nsIntRegion mPossiblyTransparentRegion;
// Win7 Gesture processing and management
nsWinGesture mGesture;
diff --git a/widget/windows/tests/gtest/TestJumpListBuilder.cpp b/widget/windows/tests/gtest/TestJumpListBuilder.cpp
index 5494c42d37..531e326465 100644
--- a/widget/windows/tests/gtest/TestJumpListBuilder.cpp
+++ b/widget/windows/tests/gtest/TestJumpListBuilder.cpp
@@ -275,14 +275,14 @@ class TestingJumpListBackend : public JumpListBackend {
* @param {nsTArray<WindowsJumpListShortcutDescription>&} aArray
* The outparam for the array of generated
* WindowsJumpListShortcutDescriptions.
- * @param {nsTArray<JS::Value>&} aJSValArray
+ * @param {JS::Handle<JSObject*>} aJSArrayObj
* The outparam for the array of JS::Value's representing the generated
* WindowsJumpListShortcutDescriptions.
*/
void GenerateWindowsJumpListShortcutDescriptions(
JSContext* aCx, uint32_t howMany, bool longDescription,
nsTArray<WindowsJumpListShortcutDescription>& aArray,
- nsTArray<JS::Value>& aJSValArray) {
+ JS::Handle<JSObject*> aJSArrayObj) {
for (uint32_t i = 0; i < howMany; ++i) {
WindowsJumpListShortcutDescription desc;
nsAutoString title(u"Test Task #");
@@ -321,7 +321,8 @@ void GenerateWindowsJumpListShortcutDescriptions(
aArray.AppendElement(desc);
JS::Rooted<JS::Value> descJSValue(aCx);
ASSERT_TRUE(ToJSValue(aCx, desc, &descJSValue));
- aJSValArray.AppendElement(std::move(descJSValue));
+
+ MOZ_ALWAYS_TRUE(JS_SetElement(aCx, aJSArrayObj, i, descJSValue));
}
}
@@ -393,15 +394,15 @@ TEST(JumpListBuilder, CheckForRemovals)
EXPECT_CALL(*testBackend, BeginList)
.WillOnce([](UINT* pcMinSlots, REFIID riid, void** ppv) {
RefPtr<IObjectCollection> collection;
- DebugOnly<HRESULT> hr = CoCreateInstance(
+ HRESULT hr = CoCreateInstance(
CLSID_EnumerableObjectCollection, nullptr, CLSCTX_INPROC_SERVER,
IID_IObjectCollection, getter_AddRefs(collection));
- MOZ_ASSERT(SUCCEEDED(hr));
+ MOZ_RELEASE_ASSERT(SUCCEEDED(hr));
RefPtr<IShellLinkW> link;
hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER,
IID_IShellLinkW, getter_AddRefs(link));
- MOZ_ASSERT(SUCCEEDED(hr));
+ MOZ_RELEASE_ASSERT(SUCCEEDED(hr));
nsAutoString firstLinkHref(u"https://example.com"_ns);
link->SetArguments(firstLinkHref.get());
@@ -421,7 +422,7 @@ TEST(JumpListBuilder, CheckForRemovals)
RefPtr<IObjectArray> pArray;
hr = collection->QueryInterface(IID_IObjectArray,
getter_AddRefs(pArray));
- MOZ_ASSERT(SUCCEEDED(hr));
+ MOZ_RELEASE_ASSERT(SUCCEEDED(hr));
*ppv = static_cast<IObjectArray*>(pArray);
(static_cast<IUnknown*>(*ppv))->AddRef();
@@ -478,6 +479,115 @@ TEST(JumpListBuilder, CheckForRemovals)
}
/**
+ * Tests calling CheckForRemovals and receiving a jump list entry with a very
+ * long URL doesn't result in JumpListBuilder truncating the URL before handing
+ * it back to the caller. Expects the following calls in order:
+ *
+ * - SetAppID
+ * - AbortList
+ * - BeginList
+ * - AbortList
+ */
+TEST(JumpListBuilder, CheckForRemovalsLongURL)
+{
+ RefPtr<StrictMock<TestingJumpListBackend>> testBackend =
+ new StrictMock<TestingJumpListBackend>();
+ nsAutoString aumid(u"TestApplicationID");
+ // We set up this expectation here because SetAppID will be called soon
+ // after construction of the JumpListBuilder via the background thread.
+ EXPECT_CALL(*testBackend, SetAppID(_)).Times(1);
+
+ nsCOMPtr<nsIJumpListBuilder> builder =
+ new JumpListBuilder(aumid, testBackend);
+ ASSERT_TRUE(builder);
+
+ EXPECT_CALL(*testBackend, AbortList()).Times(2);
+
+ constexpr static const nsLiteralString veryLongHref(
+ u"https://example.verylongurl.test/first/second/third/fourth/fifth/"
+ "sixth/seventh/eighth/ninth/tenth/eleventh/twelfth/thirteenth/"
+ "fourteenth/fifteenth-path-item/some/more/junk/after/that/more/more/"
+ "more/more/more/more/more/more/more/more/more/more/more/more/more/more/"
+ "more/more/more/more/more/more/more/more/more/more/more"_ns);
+ // This test ensures that URLs longer than MAX_PATH do not get truncated by
+ // JumpListBuilder or one of its utilities, so we must ensure that the static
+ // URL we just defined is actually longer than MAX_PATH.
+ static_assert(veryLongHref.Length() > MAX_PATH);
+
+ // Let's prepare BeginList to return a one entry collection of IShellLinks.
+ // The IShellLink will have the URL be very long - over MAX_PATH characters.
+ EXPECT_CALL(*testBackend, BeginList)
+ .WillOnce([](UINT* pcMinSlots, REFIID riid, void** ppv) {
+ RefPtr<IObjectCollection> collection;
+ HRESULT hr = CoCreateInstance(
+ CLSID_EnumerableObjectCollection, nullptr, CLSCTX_INPROC_SERVER,
+ IID_IObjectCollection, getter_AddRefs(collection));
+ MOZ_RELEASE_ASSERT(SUCCEEDED(hr));
+
+ RefPtr<IShellLinkW> link;
+ hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER,
+ IID_IShellLinkW, getter_AddRefs(link));
+ MOZ_RELEASE_ASSERT(SUCCEEDED(hr));
+
+ link->SetArguments(veryLongHref.get());
+
+ nsAutoString appPath(u"C:\\Tmp\\firefox.exe"_ns);
+ link->SetIconLocation(appPath.get(), 0);
+
+ collection->AddObject(link);
+
+ RefPtr<IObjectArray> pArray;
+ hr = collection->QueryInterface(IID_IObjectArray,
+ getter_AddRefs(pArray));
+ MOZ_RELEASE_ASSERT(SUCCEEDED(hr));
+
+ *ppv = static_cast<IObjectArray*>(pArray);
+ (static_cast<IUnknown*>(*ppv))->AddRef();
+
+ // This is the default value to return, according to
+ // https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-icustomdestinationlist-beginlist
+ *pcMinSlots = 10;
+
+ return S_OK;
+ });
+
+ AutoJSAPI jsapi;
+ MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope()));
+ JSContext* cx = jsapi.cx();
+ RefPtr<Promise> promise;
+ nsresult rv = builder->CheckForRemovals(cx, getter_AddRefs(promise));
+ ASSERT_TRUE(NS_SUCCEEDED(rv));
+ ASSERT_TRUE(promise);
+
+ RefPtr<WaitForResolver> resolver = new WaitForResolver();
+ promise->AppendNativeHandler(resolver);
+ JS::Rooted<JS::Value> result(cx);
+ resolver->SpinUntilResolvedWithResult(&result);
+
+ ASSERT_TRUE(result.isObject());
+ JS::Rooted<JSObject*> obj(cx, result.toObjectOrNull());
+
+ bool isArray;
+ ASSERT_TRUE(JS::IsArrayObject(cx, obj, &isArray));
+ ASSERT_TRUE(isArray);
+
+ // We should expect to see 1 URL string returned in the array.
+ uint32_t length = 0;
+ ASSERT_TRUE(JS::GetArrayLength(cx, obj, &length));
+ ASSERT_EQ(length, 1U);
+
+ // The URL should match veryLongHref
+ JS::Rooted<JS::Value> returnedURLValue(cx);
+ ASSERT_TRUE(JS_GetElement(cx, obj, 0, &returnedURLValue));
+ JS::Rooted<JSString*> returnedURLValueJSString(cx,
+ returnedURLValue.toString());
+ nsAutoJSString returnedURLValueAutoString;
+ ASSERT_TRUE(returnedURLValueAutoString.init(cx, returnedURLValueJSString));
+
+ ASSERT_TRUE(returnedURLValueAutoString.Equals(veryLongHref));
+}
+
+/**
* Tests calling PopulateJumpList with empty arguments, which should call the
* following methods on the backend, in order:
*
@@ -506,9 +616,13 @@ TEST(JumpListBuilder, PopulateJumpListEmpty)
JSContext* cx = jsapi.cx();
RefPtr<Promise> promise;
- nsTArray<JS::Value> taskDescJSVals;
+ JS::Rooted<JSObject*> taskDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> taskDescsJSVal(cx, JS::ObjectValue(*taskDescsObj));
+
nsAutoString customTitle(u"");
- nsTArray<JS::Value> customDescJSVals;
+
+ JS::Rooted<JSObject*> customDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> customDescsJSVal(cx, JS::ObjectValue(*customDescsObj));
EXPECT_CALL(*testBackend, AbortList()).Times(1);
EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1);
@@ -516,7 +630,7 @@ TEST(JumpListBuilder, PopulateJumpListEmpty)
EXPECT_CALL(*testBackend, DeleteList(_)).Times(0);
nsresult rv =
- builder->PopulateJumpList(taskDescJSVals, customTitle, customDescJSVals,
+ builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal,
cx, getter_AddRefs(promise));
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_TRUE(promise);
@@ -558,13 +672,15 @@ TEST(JumpListBuilder, PopulateJumpListOnlyTasks)
JSContext* cx = jsapi.cx();
RefPtr<Promise> promise;
- nsTArray<JS::Value> taskDescJSVals;
+ JS::Rooted<JSObject*> taskDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> taskDescsJSVal(cx, JS::ObjectValue(*taskDescsObj));
nsTArray<WindowsJumpListShortcutDescription> taskDescs;
GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, taskDescs,
- taskDescJSVals);
+ taskDescsObj);
nsAutoString customTitle(u"");
- nsTArray<JS::Value> customDescJSVals;
+ JS::Rooted<JSObject*> customDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> customDescsJSVal(cx, JS::ObjectValue(*customDescsObj));
EXPECT_CALL(*testBackend, AbortList()).Times(1);
EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1);
@@ -575,7 +691,7 @@ TEST(JumpListBuilder, PopulateJumpListOnlyTasks)
EXPECT_CALL(*testBackend, DeleteList(_)).Times(0);
nsresult rv =
- builder->PopulateJumpList(taskDescJSVals, customTitle, customDescJSVals,
+ builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal,
cx, getter_AddRefs(promise));
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_TRUE(promise);
@@ -617,13 +733,17 @@ TEST(JumpListBuilder, PopulateJumpListOnlyCustomItems)
JSContext* cx = jsapi.cx();
RefPtr<Promise> promise;
- nsTArray<WindowsJumpListShortcutDescription> descs;
- nsTArray<JS::Value> customDescJSVals;
- GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, descs,
- customDescJSVals);
+ JS::Rooted<JSObject*> taskDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> taskDescsJSVal(cx);
+ taskDescsJSVal.setObject(*taskDescsObj);
nsAutoString customTitle(u"My custom title");
- nsTArray<JS::Value> taskDescJSVals;
+
+ JS::Rooted<JSObject*> customDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> customDescsJSVal(cx, JS::ObjectValue(*customDescsObj));
+ nsTArray<WindowsJumpListShortcutDescription> descs;
+ GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, descs,
+ customDescsObj);
EXPECT_CALL(*testBackend, AbortList()).Times(1);
EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1);
@@ -636,7 +756,7 @@ TEST(JumpListBuilder, PopulateJumpListOnlyCustomItems)
EXPECT_CALL(*testBackend, DeleteList(_)).Times(0);
nsresult rv =
- builder->PopulateJumpList(taskDescJSVals, customTitle, customDescJSVals,
+ builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal,
cx, getter_AddRefs(promise));
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_TRUE(promise);
@@ -679,30 +799,102 @@ TEST(JumpListBuilder, PopulateJumpList)
JSContext* cx = jsapi.cx();
RefPtr<Promise> promise;
+ JS::Rooted<JSObject*> taskDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> taskDescsJSVal(cx, JS::ObjectValue(*taskDescsObj));
nsTArray<WindowsJumpListShortcutDescription> taskDescs;
- nsTArray<JS::Value> taskDescJSVals;
GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, taskDescs,
- taskDescJSVals);
+ taskDescsObj);
+
+ nsAutoString customTitle(u"My custom title");
+ JS::Rooted<JSObject*> customDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> customDescsJSVal(cx, JS::ObjectValue(*customDescsObj));
nsTArray<WindowsJumpListShortcutDescription> customDescs;
- nsTArray<JS::Value> customDescJSVals;
GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, customDescs,
- customDescJSVals);
+ customDescsObj);
+
+ EXPECT_CALL(*testBackend, AbortList()).Times(1);
+ EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1);
+ EXPECT_CALL(*testBackend, AddUserTasks(ShellLinksEq(&taskDescs))).Times(1);
+
+ EXPECT_CALL(*testBackend, AppendCategory(LPCWSTREq(customTitle.get()),
+ ShellLinksEq(&customDescs)))
+ .Times(1);
+ EXPECT_CALL(*testBackend, CommitList()).Times(1);
+ EXPECT_CALL(*testBackend, DeleteList(_)).Times(0);
+
+ nsresult rv =
+ builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal,
+ cx, getter_AddRefs(promise));
+ ASSERT_TRUE(NS_SUCCEEDED(rv));
+ ASSERT_TRUE(promise);
+
+ RefPtr<WaitForResolver> resolver = new WaitForResolver();
+ promise->AppendNativeHandler(resolver);
+ JS::Rooted<JS::Value> result(cx);
+ resolver->SpinUntilResolved();
+}
+
+/**
+ * Tests calling PopulateJumpList with tasks and custom items, but makes it so
+ * that AppendCategory returns E_ACCESSDENIED, which can occur if Windows is
+ * configured to not show recently opened items. The PopulateJumpList Promise
+ * should still resolve.
+ *
+ * - SetAppID
+ * - AbortList
+ * - BeginList
+ * - AddUserTasks
+ * - AppendCategory
+ * - CommitList
+ *
+ * This should result in a jump list with just built-in tasks.
+ */
+TEST(JumpListBuilder, PopulateJumpListNoOpenedItems)
+{
+ RefPtr<StrictMock<TestingJumpListBackend>> testBackend =
+ new StrictMock<TestingJumpListBackend>();
+ nsAutoString aumid(u"TestApplicationID");
+ // We set up this expectation here because SetAppID will be called soon
+ // after construction of the JumpListBuilder via the background thread.
+ EXPECT_CALL(*testBackend, SetAppID(_)).Times(1);
+
+ nsCOMPtr<nsIJumpListBuilder> builder =
+ new JumpListBuilder(aumid, testBackend);
+ ASSERT_TRUE(builder);
+
+ AutoJSAPI jsapi;
+ MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope()));
+ JSContext* cx = jsapi.cx();
+ RefPtr<Promise> promise;
+
+ JS::Rooted<JSObject*> taskDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> taskDescsJSVal(cx, JS::ObjectValue(*taskDescsObj));
+ nsTArray<WindowsJumpListShortcutDescription> taskDescs;
+ GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, taskDescs,
+ taskDescsObj);
nsAutoString customTitle(u"My custom title");
+ JS::Rooted<JSObject*> customDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> customDescsJSVal(cx, JS::ObjectValue(*customDescsObj));
+ nsTArray<WindowsJumpListShortcutDescription> customDescs;
+ GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, customDescs,
+ customDescsObj);
+
EXPECT_CALL(*testBackend, AbortList()).Times(1);
EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1);
EXPECT_CALL(*testBackend, AddUserTasks(ShellLinksEq(&taskDescs))).Times(1);
EXPECT_CALL(*testBackend, AppendCategory(LPCWSTREq(customTitle.get()),
ShellLinksEq(&customDescs)))
- .Times(1);
+ .WillOnce([] { return E_ACCESSDENIED; });
+
EXPECT_CALL(*testBackend, CommitList()).Times(1);
EXPECT_CALL(*testBackend, DeleteList(_)).Times(0);
nsresult rv =
- builder->PopulateJumpList(taskDescJSVals, customTitle, customDescJSVals,
+ builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal,
cx, getter_AddRefs(promise));
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_TRUE(promise);
@@ -780,15 +972,20 @@ TEST(JumpListBuilder, TruncateDescription)
JSContext* cx = jsapi.cx();
RefPtr<Promise> promise;
+ JS::Rooted<JSObject*> taskDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> taskDescsJSVal(cx, JS::ObjectValue(*taskDescsObj));
nsTArray<WindowsJumpListShortcutDescription> taskDescs;
- nsTArray<JS::Value> taskDescJSVals;
GenerateWindowsJumpListShortcutDescriptions(cx, 2, true, taskDescs,
- taskDescJSVals);
+ taskDescsObj);
+ nsAutoString customTitle(u"My custom title");
+
+ JS::Rooted<JSObject*> customDescsObj(cx, JS::NewArrayObject(cx, 0));
+ JS::Rooted<JS::Value> customDescsJSVal(cx, JS::ObjectValue(*customDescsObj));
nsTArray<WindowsJumpListShortcutDescription> customDescs;
- nsTArray<JS::Value> customDescJSVals;
GenerateWindowsJumpListShortcutDescriptions(cx, 2, true, customDescs,
- customDescJSVals);
+ customDescsObj);
+
// We expect the long descriptions to be truncated to 260 characters, so
// we'll truncate the descriptions here ourselves.
for (auto& taskDesc : taskDescs) {
@@ -798,8 +995,6 @@ TEST(JumpListBuilder, TruncateDescription)
customDesc.mDescription.SetLength(MAX_PATH - 1);
}
- nsAutoString customTitle(u"My custom title");
-
EXPECT_CALL(*testBackend, AbortList()).Times(1);
EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1);
EXPECT_CALL(*testBackend, AddUserTasks(ShellLinksEq(&taskDescs))).Times(1);
@@ -811,7 +1006,7 @@ TEST(JumpListBuilder, TruncateDescription)
EXPECT_CALL(*testBackend, DeleteList(_)).Times(0);
nsresult rv =
- builder->PopulateJumpList(taskDescJSVals, customTitle, customDescJSVals,
+ builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal,
cx, getter_AddRefs(promise));
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_TRUE(promise);
diff --git a/widget/windows/tests/gtest/TestWinDND.cpp b/widget/windows/tests/gtest/TestWinDND.cpp
index fb7849fd79..9a4b8c3db1 100644
--- a/widget/windows/tests/gtest/TestWinDND.cpp
+++ b/widget/windows/tests/gtest/TestWinDND.cpp
@@ -693,7 +693,7 @@ nsCOMPtr<nsIFile> GetTemporaryDirectory() {
#define ENSURE(expr) NS_ENSURE_SUCCESS(expr, nullptr);
ENSURE(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpdir)));
- MOZ_ASSERT(tmpdir);
+ MOZ_RELEASE_ASSERT(tmpdir);
ENSURE(tmpdir->AppendNative("TestWinDND"_ns));
ENSURE(tmpdir->CreateUnique(nsIFile::DIRECTORY_TYPE, 0777));