зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1835851 - [1/3] signal taskbar after message has been processed r=handyman,gstoll
To work around a race condition involving unminimizing windows, post a message to our own message queue, to notify the taskbar that fullscreen state recalculation is potentially necessary. (This notification must occur _after_ we have finished processing the `WM_WINDOWPOSCHANGING` message.) Differential Revision: https://phabricator.services.mozilla.com/D184762
This commit is contained in:
Родитель
eb41625b1c
Коммит
d9c931ba57
|
@ -15564,6 +15564,13 @@
|
|||
value: true
|
||||
mirror: always
|
||||
|
||||
# Whether to give explorer.exe a delated nudge to recalculate the fullscreenness
|
||||
# of a window after maximizing it.
|
||||
- name: widget.windows.fullscreen_remind_taskbar
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# The number of messages of each type to keep for display in
|
||||
# about:windows-messages
|
||||
- name: widget.windows.messages_to_log
|
||||
|
|
|
@ -33,10 +33,13 @@
|
|||
#define MOZ_WM_NOTIY_TSF_OF_LAYOUT_CHANGE (WM_APP + 0x0315)
|
||||
// Internal message used in correcting backwards clock skew
|
||||
#define MOZ_WM_SKEWFIX (WM_APP + 0x0316)
|
||||
|
||||
// Internal message used for rolling up popups for dmanip events
|
||||
#define MOZ_WM_DMANIP (WM_APP + 0x0317)
|
||||
|
||||
// Internal message used to work around race condition in explorer.exe's
|
||||
// fullscreen window-state update handler in Windows 10+. (See bug 1835851.)
|
||||
#define MOZ_WM_FULLSCREEN_STATE_UPDATE (WM_APP + 0x0318)
|
||||
|
||||
// XXX Should rename them to MOZ_WM_* and use safer values!
|
||||
// Messages for fullscreen transition window
|
||||
#define WM_FULLSCREEN_TRANSITION_BEFORE (WM_USER + 0)
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include "mozilla/widget/WinMessages.h"
|
||||
#include "nsWindow.h"
|
||||
#include "nsWindowTaskbarConcealer.h"
|
||||
#include "nsAppRunner.h"
|
||||
|
@ -5921,6 +5922,12 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
result = true;
|
||||
} break;
|
||||
|
||||
// Workaround for race condition in explorer.exe.
|
||||
case MOZ_WM_FULLSCREEN_STATE_UPDATE: {
|
||||
TaskbarConcealer::OnAsyncStateUpdateRequest(mWnd);
|
||||
result = true;
|
||||
} break;
|
||||
|
||||
case WM_GETMINMAXINFO: {
|
||||
MINMAXINFO* mmi = (MINMAXINFO*)lParam;
|
||||
// Set the constraints. The minimum size should also be constrained to the
|
||||
|
@ -9091,6 +9098,21 @@ void nsWindow::FrameState::EnsureSizeMode(nsSizeMode aMode,
|
|||
return;
|
||||
}
|
||||
|
||||
if (::IsWin10OrLater() &&
|
||||
StaticPrefs::widget_windows_fullscreen_remind_taskbar()) {
|
||||
// If we're unminimizing a window, asynchronously notify the taskbar after
|
||||
// the message has been processed. This redundant notification works around
|
||||
// a race condition in explorer.exe. (See bug 1835851, or comments in
|
||||
// TaskbarConcealer.)
|
||||
//
|
||||
// Note that we notify regardless of `aMode`: unminimizing a non-fullscreen
|
||||
// window can also affect the correct taskbar state, yet fail to affect the
|
||||
// current taskbar state.
|
||||
if (mSizeMode == nsSizeMode_Minimized) {
|
||||
::PostMessage(mWindow->mWnd, MOZ_WM_FULLSCREEN_STATE_UPDATE, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (aMode == nsSizeMode_Fullscreen) {
|
||||
EnsureFullscreenMode(true, aDoShowWindow);
|
||||
MOZ_ASSERT(mSizeMode == nsSizeMode_Fullscreen);
|
||||
|
|
|
@ -362,6 +362,50 @@ void nsWindow::TaskbarConcealer::OnWindowPosChanged(nsWindow* aWin) {
|
|||
UpdateAllState();
|
||||
}
|
||||
|
||||
void nsWindow::TaskbarConcealer::OnAsyncStateUpdateRequest(HWND hwnd) {
|
||||
MOZ_LOG(sTaskbarConcealerLog, LogLevel::Info,
|
||||
("==> OnAsyncStateUpdateRequest()"));
|
||||
|
||||
// Work around a race condition in explorer.exe.
|
||||
//
|
||||
// When a window is unminimized (and on several other events), the taskbar
|
||||
// receives a notification that it needs to recalculate the current
|
||||
// is-a-fullscreen-window-active-here-state ("rudeness") of each monitor.
|
||||
// Unfortunately, this notification is sent concurrently with the
|
||||
// WM_WINDOWPOSCHANGING message that performs the unminimization.
|
||||
//
|
||||
// Until that message is resolved, the window's position is still "minimized".
|
||||
// If the taskbar processes its notification faster than the window handles
|
||||
// its WM_WINDOWPOSCHANGING message, then the window will appear to the
|
||||
// taskbar to still be minimized, and won't be taken into account for
|
||||
// computing rudeness. This usually presents as a just-unminimized Firefox
|
||||
// fullscreen-window occasionally having the taskbar stuck above it.
|
||||
//
|
||||
// Unfortunately, it's a bit difficult to improve Firefox's speed-of-response
|
||||
// to WM_WINDOWPOSCHANGING messages (we can, and do, execute JavaScript during
|
||||
// these), and even if we could that wouldn't always fix it. We instead adopt
|
||||
// a variant of a strategy by Etienne Duchamps, who has investigated and
|
||||
// documented this issue extensively[0]: we simply send another signal to the
|
||||
// shell to notify it to recalculate the current rudeness state of all
|
||||
// monitors.
|
||||
//
|
||||
// [0] https://github.com/dechamps/RudeWindowFixer#a-race-condition-activating-a-minimized-window
|
||||
//
|
||||
if (::IsWin10OrLater()) {
|
||||
static UINT const shellHookMsg = ::RegisterWindowMessageW(L"SHELLHOOK");
|
||||
if (shellHookMsg != 0) {
|
||||
// Identifying the particular thread of the particular instance of the
|
||||
// shell associated with our current desktop is probably possible, but
|
||||
// also probably not worth the effort. Just broadcast the message
|
||||
// globally.
|
||||
DWORD info = BSM_APPLICATIONS;
|
||||
::BroadcastSystemMessage(BSF_POSTMESSAGE | BSF_IGNORECURRENTTASK, &info,
|
||||
shellHookMsg, HSHELL_WINDOWACTIVATED,
|
||||
(LPARAM)hwnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsWindow::TaskbarConcealer::OnCloakChanged() {
|
||||
if (!UseAlternateFullscreenHeuristics()) {
|
||||
return;
|
||||
|
|
|
@ -35,6 +35,9 @@ class nsWindow::TaskbarConcealer {
|
|||
// all windows' internal cloaking-state mirror variables are up-to-date.)
|
||||
static void OnCloakChanged();
|
||||
|
||||
// To be called upon receipt of MOZ_WM_FULLSCREEN_STATE_UPDATE.
|
||||
static void OnAsyncStateUpdateRequest(HWND);
|
||||
|
||||
private:
|
||||
static void UpdateAllState(HWND destroyedHwnd = nullptr);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче