From 270ba496043824cabbbb2c4ad225ca179f1efc87 Mon Sep 17 00:00:00 2001 From: Chris Martin Date: Wed, 19 Feb 2020 22:20:33 +0000 Subject: [PATCH] Bug 1616000 - Fix broken push notifications r=handyman Bug 1604412 enabled "remote backbuffer" compositing when using non-accelerated layers. However, due to my misunderstanding of how nWindow and compositing handles layered windows, I broke the usecase where a child window is transparent. In this case, it is the top-level anscestor window that has the WS_EX_LAYERED attribute and not the child window. The ancestor is the one that needs to be repainted when a present is requested. Differential Revision: https://phabricator.services.mozilla.com/D63377 --HG-- extra : moz-landing-system : lando --- widget/windows/CompositorWidgetChild.cpp | 5 ++++- widget/windows/RemoteBackbuffer.cpp | 25 +++++++++++++++++------- widget/windows/RemoteBackbuffer.h | 7 ++++++- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/widget/windows/CompositorWidgetChild.cpp b/widget/windows/CompositorWidgetChild.cpp index 4a00ba916d1f..da2c15e9f53d 100644 --- a/widget/windows/CompositorWidgetChild.cpp +++ b/widget/windows/CompositorWidgetChild.cpp @@ -36,7 +36,8 @@ CompositorWidgetChild::~CompositorWidgetChild() {} bool CompositorWidgetChild::Initialize() { mRemoteBackbufferProvider = std::make_unique(); - if (!mRemoteBackbufferProvider->Initialize(mWnd, OtherPid())) { + if (!mRemoteBackbufferProvider->Initialize(mWnd, OtherPid(), + mTransparencyMode)) { return false; } @@ -67,6 +68,8 @@ bool CompositorWidgetChild::OnWindowResize(const LayoutDeviceIntSize& aSize) { void CompositorWidgetChild::OnWindowModeChange(nsSizeMode aSizeMode) {} void CompositorWidgetChild::UpdateTransparency(nsTransparencyMode aMode) { + mTransparencyMode = aMode; + mRemoteBackbufferProvider->UpdateTransparencyMode(aMode); Unused << SendUpdateTransparency(aMode); } diff --git a/widget/windows/RemoteBackbuffer.cpp b/widget/windows/RemoteBackbuffer.cpp index cd085efb52f3..cde9c6dc1663 100644 --- a/widget/windows/RemoteBackbuffer.cpp +++ b/widget/windows/RemoteBackbuffer.cpp @@ -206,16 +206,20 @@ class PresentableSharedImage { return true; } - bool PresentToWindow(HWND aWindowHandle) { - bool isLayered = - ::GetWindowLongPtrW(aWindowHandle, GWL_EXSTYLE) & WS_EX_LAYERED; + bool PresentToWindow(HWND aWindowHandle, + nsTransparencyMode aTransparencyMode) { + if (aTransparencyMode == eTransparencyTransparent) { + // If our window is a child window or a child-of-a-child, the window + // that needs to be updated is the top level ancestor of the tree + HWND topLevelWindow = WinUtils::GetTopLevelHWND(aWindowHandle, true); + MOZ_ASSERT(::GetWindowLongPtr(topLevelWindow, GWL_EXSTYLE) & + WS_EX_LAYERED); - if (isLayered) { BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; SIZE winSize = {mSharedImage.GetWidth(), mSharedImage.GetHeight()}; POINT srcPos = {0, 0}; return !!::UpdateLayeredWindow( - aWindowHandle, nullptr /*paletteDC*/, nullptr /*newPos*/, &winSize, + topLevelWindow, nullptr /*paletteDC*/, nullptr /*newPos*/, &winSize, mDeviceContext, &srcPos, 0 /*colorKey*/, &bf, ULW_ALPHA); } @@ -294,7 +298,8 @@ Provider::~Provider() { } } -bool Provider::Initialize(HWND aWindowHandle, DWORD aTargetProcessId) { +bool Provider::Initialize(HWND aWindowHandle, DWORD aTargetProcessId, + nsTransparencyMode aTransparencyMode) { MOZ_ASSERT(aWindowHandle); MOZ_ASSERT(aTargetProcessId); @@ -335,6 +340,8 @@ bool Provider::Initialize(HWND aWindowHandle, DWORD aTargetProcessId) { mServiceThread = std::thread([this] { this->ThreadMain(); }); + mTransparencyMode = aTransparencyMode; + return true; } @@ -365,6 +372,10 @@ Maybe Provider::CreateRemoteHandles() { reinterpret_cast(responseReadyEvent))); } +void Provider::UpdateTransparencyMode(nsTransparencyMode aTransparencyMode) { + mTransparencyMode = aTransparencyMode; +} + void Provider::ThreadMain() { while (true) { MOZ_ALWAYS_TRUE(::WaitForSingleObject(mRequestReadyEvent, INFINITE) == @@ -457,7 +468,7 @@ void Provider::HandlePresentRequest(PresentResponseData* aResponseData) { return; } - if (!mBackbuffer->PresentToWindow(mWindowHandle)) { + if (!mBackbuffer->PresentToWindow(mWindowHandle, mTransparencyMode)) { return; } diff --git a/widget/windows/RemoteBackbuffer.h b/widget/windows/RemoteBackbuffer.h index edb1e1cab139..bb4e486f410f 100644 --- a/widget/windows/RemoteBackbuffer.h +++ b/widget/windows/RemoteBackbuffer.h @@ -25,10 +25,13 @@ class Provider { Provider(); ~Provider(); - bool Initialize(HWND aWindowHandle, DWORD aTargetProcessId); + bool Initialize(HWND aWindowHandle, DWORD aTargetProcessId, + nsTransparencyMode aTransparencyMode); Maybe CreateRemoteHandles(); + void UpdateTransparencyMode(nsTransparencyMode aTransparencyMode); + Provider(const Provider&) = delete; Provider(Provider&&) = delete; Provider& operator=(const Provider&) = delete; @@ -49,6 +52,8 @@ class Provider { bool mStopServiceThread; std::thread mServiceThread; std::unique_ptr mBackbuffer; + mozilla::Atomic + mTransparencyMode; }; class Client {