From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- widget/windows/GfxInfo.cpp | 69 ++++---- widget/windows/JumpListBuilder.cpp | 12 +- widget/windows/JumpListBuilder.h | 2 +- widget/windows/WinTaskbar.cpp | 5 + widget/windows/WindowsSMTCProvider.cpp | 179 ++++++++++++++++++++- widget/windows/WindowsSMTCProvider.h | 12 +- widget/windows/filedialog/WinFileDialogChild.cpp | 7 +- .../windows/filedialog/WinFileDialogCommands.cpp | 2 +- widget/windows/nsFilePicker.cpp | 14 +- widget/windows/nsFilePicker.h | 6 +- widget/windows/nsLookAndFeel.cpp | 3 - widget/windows/nsWindow.cpp | 136 +++++++++++----- widget/windows/nsWindow.h | 4 +- 13 files changed, 340 insertions(+), 111 deletions(-) (limited to 'widget/windows') diff --git a/widget/windows/GfxInfo.cpp b/widget/windows/GfxInfo.cpp index 6f033785f5..0e1b4002d3 100644 --- a/widget/windows/GfxInfo.cpp +++ b/widget/windows/GfxInfo.cpp @@ -1092,25 +1092,20 @@ void GfxInfo::AddCrashReportAnnotations() { } nsString deviceID, vendorID, driverVersion, subsysID; - nsCString narrowDeviceID, narrowVendorID, narrowDriverVersion, narrowSubsysID; GetAdapterDeviceID(deviceID); - CopyUTF16toUTF8(deviceID, narrowDeviceID); GetAdapterVendorID(vendorID); - CopyUTF16toUTF8(vendorID, narrowVendorID); GetAdapterDriverVersion(driverVersion); - CopyUTF16toUTF8(driverVersion, narrowDriverVersion); GetAdapterSubsysID(subsysID); - CopyUTF16toUTF8(subsysID, narrowSubsysID); - CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterVendorID, - narrowVendorID); - CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterDeviceID, - narrowDeviceID); - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::AdapterDriverVersion, narrowDriverVersion); - CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterSubsysID, - narrowSubsysID); + CrashReporter::RecordAnnotationNSString( + CrashReporter::Annotation::AdapterVendorID, vendorID); + CrashReporter::RecordAnnotationNSString( + CrashReporter::Annotation::AdapterDeviceID, deviceID); + CrashReporter::RecordAnnotationNSString( + CrashReporter::Annotation::AdapterDriverVersion, driverVersion); + CrashReporter::RecordAnnotationNSString( + CrashReporter::Annotation::AdapterSubsysID, subsysID); /* Add an App Note, this contains extra information. */ nsAutoCString note; @@ -1740,24 +1735,6 @@ const nsTArray& GfxInfo::GetGfxDriverInfo() { DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions, "FEATURE_UNQUALIFIED_P010_NVIDIA"); - //////////////////////////////////// - // FEATURE_VIDEO_OVERLAY - ALLOWLIST -#ifdef EARLY_BETA_OR_EARLIER - APPEND_TO_DRIVER_BLOCKLIST2( - OperatingSystem::Windows, DeviceFamily::All, - nsIGfxInfo::FEATURE_VIDEO_OVERLAY, nsIGfxInfo::FEATURE_ALLOW_ALWAYS, - DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), "FEATURE_ROLLOUT_ALL"); -#else - APPEND_TO_DRIVER_BLOCKLIST2( - OperatingSystem::Windows, DeviceFamily::IntelAll, - nsIGfxInfo::FEATURE_VIDEO_OVERLAY, nsIGfxInfo::FEATURE_ALLOW_ALWAYS, - DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), "FEATURE_ROLLOUT_INTEL"); - APPEND_TO_DRIVER_BLOCKLIST2( - OperatingSystem::Windows, DeviceFamily::NvidiaAll, - nsIGfxInfo::FEATURE_VIDEO_OVERLAY, nsIGfxInfo::FEATURE_ALLOW_ALWAYS, - DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), "FEATURE_ROLLOUT_NVIDIA"); -#endif - //////////////////////////////////// // FEATURE_HW_DECODED_VIDEO_ZERO_COPY @@ -1801,9 +1778,13 @@ const nsTArray& GfxInfo::GetGfxDriverInfo() { //////////////////////////////////// // FEATURE_HW_DECODED_VIDEO_ZERO_COPY - ALLOWLIST - - // XXX ZeroCopyNV12Texture is disabled with non-intel GPUs for now. - // See Bug 1798242 +#ifdef EARLY_BETA_OR_EARLIER + APPEND_TO_DRIVER_BLOCKLIST2( + OperatingSystem::Windows, DeviceFamily::NvidiaAll, + nsIGfxInfo::FEATURE_HW_DECODED_VIDEO_ZERO_COPY, + nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_COMPARISON_IGNORED, + V(0, 0, 0, 0), "FEATURE_ROLLOUT_ALL"); +#endif APPEND_TO_DRIVER_BLOCKLIST2( OperatingSystem::Windows, DeviceFamily::IntelAll, nsIGfxInfo::FEATURE_HW_DECODED_VIDEO_ZERO_COPY, @@ -1827,6 +1808,26 @@ const nsTArray& GfxInfo::GetGfxDriverInfo() { V(10, 18, 15, 4256), V(10, 18, 15, 4293), "FEATURE_FAILURE_BUG_1833809", "Intel driver 10.18.15.*"); + //////////////////////////////////// + // FEATURE_OVERLAY_VP_AUTO_HDR + + APPEND_TO_DRIVER_BLOCKLIST( + OperatingSystem::Windows, DeviceFamily::NvidiaAll, + nsIGfxInfo::FEATURE_OVERLAY_VP_AUTO_HDR, + nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN_OR_EQUAL, + V(31, 0, 15, 5050), "FEATURE_FAILURE_VP_AUTO_HDR", + "nVidia driver > 550.50"); + + //////////////////////////////////// + // FEATURE_OVERLAY_VP_SUPER_RESOLUTION + + APPEND_TO_DRIVER_BLOCKLIST( + OperatingSystem::Windows, DeviceFamily::NvidiaAll, + nsIGfxInfo::FEATURE_OVERLAY_VP_SUPER_RESOLUTION, + nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN_OR_EQUAL, + V(31, 0, 15, 3000), "FEATURE_FAILURE_VP_AUTO_HDR", + "nVidia driver > 530.00"); + //////////////////////////////////// // FEATURE_WEBRENDER // Block 8.56.1.15/16 diff --git a/widget/windows/JumpListBuilder.cpp b/widget/windows/JumpListBuilder.cpp index 80b1c29aa7..e25c8c038f 100644 --- a/widget/windows/JumpListBuilder.cpp +++ b/widget/windows/JumpListBuilder.cpp @@ -176,8 +176,9 @@ JumpListBuilder::JumpListBuilder(const nsAString& aAppUserModelId, // the app, as it is set in the package manifest instead. if (!mozilla::widget::WinUtils::HasPackageIdentity()) { mIOThread->Dispatch( - NewRunnableMethod( - "SetAppID", this, &JumpListBuilder::DoSetAppID, aAppUserModelId), + NewRunnableMethod("SetAppID", this, + &JumpListBuilder::DoSetAppIDIfAvailable, + aAppUserModelId), NS_DISPATCH_NORMAL); } } @@ -203,10 +204,13 @@ void JumpListBuilder::DoShutdownBackend() { mJumpListBackend = nullptr; } -void JumpListBuilder::DoSetAppID(nsString aAppUserModelID) { +void JumpListBuilder::DoSetAppIDIfAvailable(nsString aAppUserModelID) { MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(mJumpListBackend); - mJumpListBackend->SetAppID(aAppUserModelID.get()); + + if (mJumpListBackend->IsAvailable()) { + mJumpListBackend->SetAppID(aAppUserModelID.get()); + } } NS_IMETHODIMP diff --git a/widget/windows/JumpListBuilder.h b/widget/windows/JumpListBuilder.h index e228669f11..b8d5253153 100644 --- a/widget/windows/JumpListBuilder.h +++ b/widget/windows/JumpListBuilder.h @@ -64,7 +64,7 @@ class JumpListBuilder : public nsIJumpListBuilder, public nsIObserver { void DoSetupBackend(); void DoSetupTestingBackend(RefPtr aTestingBackend); void DoShutdownBackend(); - void DoSetAppID(nsString aAppUserModelID); + void DoSetAppIDIfAvailable(nsString aAppUserModelID); void DoIsAvailable(const nsMainThreadPtrHandle& aPromiseHolder); void DoCheckForRemovals( const nsMainThreadPtrHandle& aPromiseHolder); diff --git a/widget/windows/WinTaskbar.cpp b/widget/windows/WinTaskbar.cpp index 56608503da..66854f3ee2 100644 --- a/widget/windows/WinTaskbar.cpp +++ b/widget/windows/WinTaskbar.cpp @@ -223,6 +223,11 @@ bool WinTaskbar::GenerateAppUserModelID(nsAString& aAppUserModelId, id.AppendInt(HashString(path)); if (!id.IsEmpty()) { aAppUserModelId.Assign(id); + + if (aPrivateBrowsing) { + aAppUserModelId.AppendLiteral(";PrivateBrowsingAUMID"); + } + return true; } } diff --git a/widget/windows/WindowsSMTCProvider.cpp b/widget/windows/WindowsSMTCProvider.cpp index 04d833a8e7..69915cafd8 100644 --- a/widget/windows/WindowsSMTCProvider.cpp +++ b/widget/windows/WindowsSMTCProvider.cpp @@ -255,6 +255,25 @@ void WindowsSMTCProvider::UnregisterEvents() { if (mControls && mButtonPressedToken.value != 0) { mControls->remove_ButtonPressed(mButtonPressedToken); } + + if (mControls && mSeekRegistrationToken.value != 0) { + ComPtr smtc2; + HRESULT hr = mControls.As(&smtc2); + if (FAILED(hr)) { + LOG("Failed to cast controls to ISystemMediaTransportControls2 (hr=%lx)", + hr); + return; + } + MOZ_ASSERT(smtc2); + + hr = smtc2->remove_PlaybackPositionChangeRequested(mSeekRegistrationToken); + if (FAILED(hr)) { + LOG("SystemMediaTransportControls: Failed unregister position change " + "event (hr=%lx)", + hr); + return; + } + } } bool WindowsSMTCProvider::RegisterEvents() { @@ -289,6 +308,48 @@ bool WindowsSMTCProvider::RegisterEvents() { return false; } + ComPtr smtc2; + HRESULT hr = mControls.As(&smtc2); + if (FAILED(hr)) { + LOG("Failed to cast controls to ISystemMediaTransportControls2 (hr=%lx)", + hr); + return false; + } + MOZ_ASSERT(smtc2); + + auto positionChangeRequested = + Callback>( + [this, self]( + ISystemMediaTransportControls*, + IPlaybackPositionChangeRequestedEventArgs* pArgs) -> HRESULT { + MOZ_ASSERT(pArgs); + + TimeSpan value; + HRESULT hr = pArgs->get_RequestedPlaybackPosition(&value); + if (FAILED(hr)) { + LOG("SystemMediaTransportControls: Playback Position Change - " + "failed to get requested position (hr=%lx)", + hr); + return S_OK; // Propagating the error probably wouldn't help. + } + + double position = + static_cast(value.Duration) / (1e6 * 10.0); + this->OnPositionChangeRequested(position); + + return S_OK; + }); + + hr = smtc2->add_PlaybackPositionChangeRequested(positionChangeRequested.Get(), + &mSeekRegistrationToken); + if (FAILED(hr)) { + LOG("SystemMediaTransportControls: Failed to register position change " + "event (hr=%lx)", + hr); + return false; + } + return true; } @@ -309,12 +370,14 @@ bool WindowsSMTCProvider::EnableControl(bool aEnabled) const { return SUCCEEDED(mControls->put_IsEnabled(aEnabled)); } -bool WindowsSMTCProvider::UpdateButtons() const { +bool WindowsSMTCProvider::UpdateButtons() { static const mozilla::dom::MediaControlKey kKeys[] = { - mozilla::dom::MediaControlKey::Play, mozilla::dom::MediaControlKey::Pause, + mozilla::dom::MediaControlKey::Play, + mozilla::dom::MediaControlKey::Pause, mozilla::dom::MediaControlKey::Previoustrack, mozilla::dom::MediaControlKey::Nexttrack, - mozilla::dom::MediaControlKey::Stop}; + mozilla::dom::MediaControlKey::Stop, + mozilla::dom::MediaControlKey::Seekto}; bool success = true; for (const mozilla::dom::MediaControlKey& key : kKeys) { @@ -347,12 +410,28 @@ bool WindowsSMTCProvider::EnableKey(mozilla::dom::MediaControlKey aKey, return SUCCEEDED(mControls->put_IsNextEnabled(aEnable)); case mozilla::dom::MediaControlKey::Stop: return SUCCEEDED(mControls->put_IsStopEnabled(aEnable)); + case mozilla::dom::MediaControlKey::Seekto: + // The callback for the event checks if the key is supported + return mSeekRegistrationToken.value != 0; default: LOG("No button for %s", ToMediaControlKeyStr(aKey)); return false; } } +void WindowsSMTCProvider::OnPositionChangeRequested(double aPosition) const { + if (!IsKeySupported(mozilla::dom::MediaControlKey::Seekto)) { + LOG("Seekto is not supported"); + return; + } + + for (const auto& listener : mListeners) { + listener->OnActionPerformed( + mozilla::dom::MediaControlAction(mozilla::dom::MediaControlKey::Seekto, + mozilla::dom::SeekDetails(aPosition))); + } +} + bool WindowsSMTCProvider::InitDisplayAndControls() { // As Open() might be called multiple times, "cache" the results of the COM // API @@ -422,6 +501,100 @@ bool WindowsSMTCProvider::SetMusicMetadata(const nsString& aArtist, return true; } +void WindowsSMTCProvider::SetPositionState( + const mozilla::Maybe& aState) { + ComPtr smtc2; + HRESULT hr = mControls.As(&smtc2); + if (FAILED(hr)) { + LOG("Failed to cast controls to ISystemMediaTransportControls2 (hr=%lx)", + hr); + return; + } + MOZ_ASSERT(smtc2); + + ComPtr properties; + hr = RoActivateInstance( + HStringReference( + RuntimeClass_Windows_Media_SystemMediaTransportControlsTimelineProperties) + .Get(), + &properties); + if (FAILED(hr)) { + LOG("Failed to create timeline properties (hr=%lx)", hr); + return; + } + MOZ_ASSERT(properties); + + // Converts a value in seconds to a TimeSpan + // The TimeSpan's Duration is a value in 100ns ticks + // https://learn.microsoft.com/en-us/windows/win32/api/windows.foundation/ns-windows-foundation-timespan#members + auto toTimeSpan = [this](double seconds) { + constexpr double kMaxMicroseconds = + static_cast(std::numeric_limits::max() / 10); + + double microseconds = seconds * 1e6; + + if (microseconds > kMaxMicroseconds) { + LOG("Failed to convert %f microseconds to TimeSpan (overflow)", + microseconds); + return TimeSpan{0}; + } + + return TimeSpan{static_cast(microseconds * 10.0)}; + }; + + TimeSpan endTime{0}; + TimeSpan position{0}; + double playbackRate = 1.0; + + if (aState) { + endTime = toTimeSpan(aState->mDuration); + position = toTimeSpan(aState->CurrentPlaybackPosition()); + playbackRate = aState->mPlaybackRate; + } + + hr = properties->put_StartTime({0}); + if (FAILED(hr)) { + LOG("Failed to set the start time (hr=%lx)", hr); + return; + } + + hr = properties->put_MinSeekTime({0}); + if (FAILED(hr)) { + LOG("Failed to set the min seek time (hr=%lx)", hr); + return; + } + + hr = properties->put_EndTime(endTime); + if (FAILED(hr)) { + LOG("Failed to set the end time (hr=%lx)", hr); + return; + } + + hr = properties->put_MaxSeekTime(endTime); + if (FAILED(hr)) { + LOG("Failed to set the max seek time (hr=%lx)", hr); + return; + } + + hr = properties->put_Position(position); + if (FAILED(hr)) { + LOG("Failed to set the playback position (hr=%lx)", hr); + return; + } + + hr = smtc2->UpdateTimelineProperties(properties.Get()); + if (FAILED(hr)) { + LOG("Failed to update timeline properties (hr=%lx)", hr); + return; + } + + hr = smtc2->put_PlaybackRate(playbackRate); + if (FAILED(hr)) { + LOG("Failed to set the playback rate (hr=%lx)", hr); + return; + } +} + void WindowsSMTCProvider::LoadThumbnail( const nsTArray& aArtwork) { MOZ_ASSERT(NS_IsMainThread()); diff --git a/widget/windows/WindowsSMTCProvider.h b/widget/windows/WindowsSMTCProvider.h index 3926618d1f..2f0d1f8344 100644 --- a/widget/windows/WindowsSMTCProvider.h +++ b/widget/windows/WindowsSMTCProvider.h @@ -46,6 +46,9 @@ class WindowsSMTCProvider final : public mozilla::dom::MediaControlKeySource { void SetSupportedMediaKeys(const MediaKeysArray& aSupportedKeys) override; + void SetPositionState( + const mozilla::Maybe& aState) override; + private: ~WindowsSMTCProvider(); void UnregisterEvents(); @@ -54,12 +57,14 @@ class WindowsSMTCProvider final : public mozilla::dom::MediaControlKeySource { void OnButtonPressed(mozilla::dom::MediaControlKey aKey) const; // Enable the SMTC interface bool EnableControl(bool aEnabled) const; - // Sets the play, pause, next, previous buttons on the SMTC interface by - // mSupportedKeys - bool UpdateButtons() const; + // Sets the play, pause, next, previous, seekto buttons on the SMTC interface + // by mSupportedKeys + bool UpdateButtons(); bool IsKeySupported(mozilla::dom::MediaControlKey aKey) const; bool EnableKey(mozilla::dom::MediaControlKey aKey, bool aEnable) const; + void OnPositionChangeRequested(double aPosition) const; + bool InitDisplayAndControls(); // Sets the Metadata for the currently playing media and sets the playback @@ -122,6 +127,7 @@ class WindowsSMTCProvider final : public mozilla::dom::MediaControlKeySource { // EventRegistrationTokens are used to have a handle on a callback (to remove // it again) EventRegistrationToken mButtonPressedToken; + EventRegistrationToken mSeekRegistrationToken; }; #endif // __MINGW32__ diff --git a/widget/windows/filedialog/WinFileDialogChild.cpp b/widget/windows/filedialog/WinFileDialogChild.cpp index 1a2903f8ec..a41018ff0e 100644 --- a/widget/windows/filedialog/WinFileDialogChild.cpp +++ b/widget/windows/filedialog/WinFileDialogChild.cpp @@ -40,11 +40,8 @@ WinFileDialogChild::~WinFileDialogChild() { template WinFileDialogChild::IPCResult WinFileDialogChild::MakeIpcFailure( HRESULT hr, const char (&what)[N]) { - // The crash-report annotator stringifies integer values anyway. We do so - // eagerly here to avoid questions about C int/long conversion semantics. - nsPrintfCString data("%lu", hr); - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::WindowsFileDialogErrorCode, data); + CrashReporter::RecordAnnotationU32( + CrashReporter::Annotation::WindowsFileDialogErrorCode, hr); return IPC_FAIL(this, what); } diff --git a/widget/windows/filedialog/WinFileDialogCommands.cpp b/widget/windows/filedialog/WinFileDialogCommands.cpp index f0503ab8f0..838856893d 100644 --- a/widget/windows/filedialog/WinFileDialogCommands.cpp +++ b/widget/windows/filedialog/WinFileDialogCommands.cpp @@ -294,7 +294,7 @@ void LogProcessingError(LogModule* aModule, ipc::IProtocol* aCaller, ipc::SandboxingKind::WINDOWS_FILE_DIALOG); } else { // ... which (presumably) is us - CrashReporter::AnnotateCrashReport( + CrashReporter::AutoRecordAnnotation( CrashReporter::Annotation::ipc_channel_error, reason); MOZ_CRASH("IPC error"); diff --git a/widget/windows/nsFilePicker.cpp b/widget/windows/nsFilePicker.cpp index 310c54bb40..fb4c6e80b5 100644 --- a/widget/windows/nsFilePicker.cpp +++ b/widget/windows/nsFilePicker.cpp @@ -19,6 +19,7 @@ #include "mozilla/BackgroundHangMonitor.h" #include "mozilla/Components.h" #include "mozilla/dom/BrowsingContext.h" +#include "mozilla/dom/CanonicalBrowsingContext.h" #include "mozilla/dom/Directory.h" #include "mozilla/Logging.h" #include "mozilla/ipc/UtilityProcessManager.h" @@ -94,19 +95,14 @@ nsFilePicker::nsFilePicker() : mSelectedType(1) {} NS_IMPL_ISUPPORTS(nsFilePicker, nsIFilePicker) NS_IMETHODIMP nsFilePicker::Init( - mozIDOMWindowProxy* aParent, const nsAString& aTitle, - nsIFilePicker::Mode aMode, - mozilla::dom::BrowsingContext* aBrowsingContext) { + mozilla::dom::BrowsingContext* aBrowsingContext, const nsAString& aTitle, + nsIFilePicker::Mode aMode) { // Don't attempt to open a real file-picker in headless mode. if (gfxPlatform::IsHeadless()) { return nsresult::NS_ERROR_NOT_AVAILABLE; } - nsCOMPtr window = do_QueryInterface(aParent); - nsIDocShell* docShell = window ? window->GetDocShell() : nullptr; - mLoadContext = do_QueryInterface(docShell); - - return nsBaseFilePicker::Init(aParent, aTitle, aMode, aBrowsingContext); + return nsBaseFilePicker::Init(aBrowsingContext, aTitle, aMode); } namespace mozilla::detail { @@ -1053,7 +1049,7 @@ void nsFilePicker::RememberLastUsedDirectory() { } bool nsFilePicker::IsPrivacyModeEnabled() { - return mLoadContext && mLoadContext->UsePrivateBrowsing(); + return mBrowsingContext && mBrowsingContext->UsePrivateBrowsing(); } bool nsFilePicker::IsDefaultPathLink() { diff --git a/widget/windows/nsFilePicker.h b/widget/windows/nsFilePicker.h index 1938b8bcb6..59108bc0dd 100644 --- a/widget/windows/nsFilePicker.h +++ b/widget/windows/nsFilePicker.h @@ -66,9 +66,8 @@ class nsFilePicker final : public nsBaseWinFilePicker { public: nsFilePicker(); - NS_IMETHOD Init(mozIDOMWindowProxy* aParent, const nsAString& aTitle, - nsIFilePicker::Mode aMode, - mozilla::dom::BrowsingContext* aBrowsingContext) override; + NS_IMETHOD Init(mozilla::dom::BrowsingContext* aBrowsingContext, + const nsAString& aTitle, nsIFilePicker::Mode aMode) override; NS_DECL_ISUPPORTS @@ -117,7 +116,6 @@ class nsFilePicker final : public nsBaseWinFilePicker { bool IsDefaultPathLink(); bool IsDefaultPathHtml(); - nsCOMPtr mLoadContext; nsCOMPtr mParentWidget; nsString mTitle; nsCString mFile; diff --git a/widget/windows/nsLookAndFeel.cpp b/widget/windows/nsLookAndFeel.cpp index 01b126cd42..6122000c9e 100644 --- a/widget/windows/nsLookAndFeel.cpp +++ b/widget/windows/nsLookAndFeel.cpp @@ -409,9 +409,6 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) { // (400ms) on error. aResult = GetSystemParam(SPI_GETMENUSHOWDELAY, 400); break; - case IntID::TooltipDelay: - aResult = 500; - break; case IntID::MenusCanOverlapOSBar: // we want XUL popups to be able to overlap the task bar. aResult = 1; diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 1a8646d620..b304d2efac 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -175,12 +175,11 @@ #include #include -#if defined(ACCESSIBILITY) - +#ifdef ACCESSIBILITY # ifdef DEBUG # include "mozilla/a11y/Logging.h" # endif - +# include "mozilla/a11y/Compatibility.h" # include "oleidl.h" # include # include "nsAccessibilityService.h" @@ -190,7 +189,7 @@ # if !defined(WINABLEAPI) # include # endif // !defined(WINABLEAPI) -#endif // defined(ACCESSIBILITY) +#endif #include "WindowsUIUtils.h" @@ -1221,18 +1220,19 @@ static LPWSTR const gStockApplicationIcon = MAKEINTRESOURCEW(32512); /* static */ const wchar_t* nsWindow::ChooseWindowClass(WindowType aWindowType) { - switch (aWindowType) { - case WindowType::Invisible: - return RegisterWindowClass(kClassNameHidden, 0, gStockApplicationIcon); - case WindowType::Dialog: - return RegisterWindowClass(kClassNameDialog, 0, nullptr); - case WindowType::Popup: - return RegisterWindowClass(kClassNameDropShadow, 0, - gStockApplicationIcon); - default: - return RegisterWindowClass(GetMainWindowClass(), 0, - gStockApplicationIcon); - } + const wchar_t* className = [aWindowType] { + switch (aWindowType) { + case WindowType::Invisible: + return kClassNameHidden; + case WindowType::Dialog: + return kClassNameDialog; + case WindowType::Popup: + return kClassNameDropShadow; + default: + return GetMainWindowClass(); + } + }(); + return RegisterWindowClass(className, 0, gStockApplicationIcon); } /************************************************************** @@ -1310,13 +1310,6 @@ DWORD nsWindow::WindowStyle() { if (mBorderStyle == BorderStyle::None || !(mBorderStyle & BorderStyle::Maximize)) style &= ~WS_MAXIMIZEBOX; - - if (IsPopupWithTitleBar()) { - style |= WS_CAPTION; - if (mBorderStyle & BorderStyle::Close) { - style |= WS_SYSMENU; - } - } } if (mIsChildWindow) { @@ -1332,7 +1325,6 @@ DWORD nsWindow::WindowStyle() { // Return nsWindow extended styles DWORD nsWindow::WindowExStyle() { - MOZ_ASSERT_IF(mIsAlert, mWindowType == WindowType::Dialog); switch (mWindowType) { case WindowType::Child: return 0; @@ -1343,18 +1335,18 @@ DWORD nsWindow::WindowExStyle() { } return extendedStyle; } - case WindowType::Dialog: { - if (mIsAlert) { - return WS_EX_TOOLWINDOW | WS_EX_TOPMOST; - } - return WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME; - } case WindowType::Sheet: MOZ_FALLTHROUGH_ASSERT("Sheets are macOS specific"); + case WindowType::Dialog: case WindowType::TopLevel: case WindowType::Invisible: break; } + if (mIsAlert) { + MOZ_ASSERT(mWindowType == WindowType::Dialog, + "Expect alert windows to have type=dialog"); + return WS_EX_TOOLWINDOW | WS_EX_TOPMOST; + } return WS_EX_WINDOWEDGE; } @@ -3058,9 +3050,7 @@ void nsWindow::SetTransparencyMode(TransparencyMode aMode) { void nsWindow::UpdateWindowDraggingRegion( const LayoutDeviceIntRegion& aRegion) { - if (mDraggableRegion != aRegion) { - mDraggableRegion = aRegion; - } + mDraggableRegion = aRegion; } /************************************************************** @@ -3674,7 +3664,7 @@ LayoutDeviceIntPoint nsWindow::WidgetToScreenOffset() { } LayoutDeviceIntMargin nsWindow::ClientToWindowMargin() { - if (mWindowType == WindowType::Popup && !IsPopupWithTitleBar()) { + if (mWindowType == WindowType::Popup) { return {}; } @@ -4420,6 +4410,17 @@ HWND nsWindow::GetTopLevelForFocus(HWND aCurWnd) { } void nsWindow::DispatchFocusToTopLevelWindow(bool aIsActivate) { + if (aIsActivate && mPickerDisplayCount) { + // We disable the root window when a picker opens. See PickerOpen. When the + // picker closes (but before PickerClosed is called), our window will get + // focus, but it will still be disabled. This confuses the focus system. + // Therefore, we ignore this focus and explicitly call this function once + // we re-enable the window. Rarely, the picker seems to re-enable our root + // window before we do, but for simplicity, we always ignore focus before + // the final call to PickerClosed. See bug 1883568 for further details. + return; + } + if (aIsActivate) { sJustGotActivate = false; } @@ -5039,6 +5040,44 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam, break; } + case WM_GETTITLEBARINFOEX: { + if (!mCustomNonClient) { + break; + } + auto* info = reinterpret_cast(lParam); + const LayoutDeviceIntPoint origin = WidgetToScreenOffset(); + auto GeckoClientToWinScreenRect = + [&origin](LayoutDeviceIntRect aRect) -> RECT { + aRect.MoveBy(origin); + return { + .left = aRect.x, + .top = aRect.y, + .right = aRect.XMost(), + .bottom = aRect.YMost(), + }; + }; + auto SetButton = [&](size_t aIndex, WindowButtonType aType) { + info->rgrect[aIndex] = + GeckoClientToWinScreenRect(mWindowBtnRect[aType]); + DWORD& state = info->rgstate[aIndex]; + if (mWindowBtnRect[aType].IsEmpty()) { + state = STATE_SYSTEM_INVISIBLE; + } else { + state = STATE_SYSTEM_FOCUSABLE; + } + }; + info->rgrect[0] = info->rcTitleBar = + GeckoClientToWinScreenRect(mDraggableRegion.GetBounds()); + info->rgstate[0] = 0; + SetButton(2, WindowButtonType::Minimize); + SetButton(3, WindowButtonType::Maximize); + SetButton(5, WindowButtonType::Close); + // We don't have a help button. + info->rgstate[4] = STATE_SYSTEM_INVISIBLE; + info->rgrect[4] = {0, 0, 0, 0}; + result = true; + } break; + case WM_NCHITTEST: { if (mInputRegion.mFullyTransparent) { // Treat this window as transparent. @@ -6169,6 +6208,9 @@ int32_t nsWindow::ClientMarginHitTestPoint(int32_t aX, int32_t aY) { if (mWindowBtnRect[WindowButtonType::Minimize].Contains(pt)) { testResult = HTMINBUTTON; } else if (mWindowBtnRect[WindowButtonType::Maximize].Contains(pt)) { +#ifdef ACCESSIBILITY + a11y::Compatibility::SuppressA11yForSnapLayouts(); +#endif testResult = HTMAXBUTTON; } else if (mWindowBtnRect[WindowButtonType::Close].Contains(pt)) { testResult = HTCLOSE; @@ -8168,8 +8210,23 @@ WPARAM nsWindow::wParamFromGlobalMouseState() { return result; } +// WORKAROUND FOR UNDOCUMENTED BEHAVIOR: `IFileDialog::Show` disables the +// top-level ancestor of its provided owner-window. If the modal window's +// container process crashes, it will never get a chance to undo that. +// +// For simplicity's sake we simply unconditionally perform both the disabling +// and reenabling here, synchronously, on the main thread, rather than leaving +// it to happen in our asynchronously-operated IFileDialog. + void nsWindow::PickerOpen() { AssertIsOnMainThread(); + + // Disable the root-level window synchronously before any file-dialogs get a + // chance to fight over doing it asynchronously. + if (!mPickerDisplayCount) { + ::EnableWindow(::GetAncestor(GetWindowHandle(), GA_ROOT), FALSE); + } + mPickerDisplayCount++; } @@ -8179,16 +8236,10 @@ void nsWindow::PickerClosed() { if (!mPickerDisplayCount) return; mPickerDisplayCount--; - // WORKAROUND FOR UNDOCUMENTED BEHAVIOR: `IFileDialog::Show` disables the - // top-level ancestor of its provided owner-window. If the modal window's - // container process crashes, it will never get a chance to undo that, so we - // do it manually here. - // - // Note that this may cause problems in the embedded case if you reparent a - // subtree of the native window hierarchy containing a Gecko window while that - // Gecko window has a file-dialog open. + // Once all the file-dialogs are gone, reenable the root-level window. if (!mPickerDisplayCount) { ::EnableWindow(::GetAncestor(GetWindowHandle(), GA_ROOT), TRUE); + DispatchFocusToTopLevelWindow(true); } if (!mPickerDisplayCount && mDestroyCalled) { @@ -8528,6 +8579,7 @@ void nsWindow::ChangedDPI() { presShell->BackingScaleFactorChanged(); } } + NotifyAPZOfDPIChange(); } static Result PointerStateToFlag( diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index c75c9d174d..3a521fb978 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -887,8 +887,8 @@ class nsWindow final : public nsBaseWidget { mozilla::UniquePtr mDmOwner; // Client rect for minimize, maximize and close buttons. - mozilla::EnumeratedArray + mozilla::EnumeratedArray mWindowBtnRect; mozilla::DataMutex mDesktopId; -- cgit v1.2.3