Bug 1666874 - Support maximized windows for skeleton UI r=agashlin

Most of this patch is a dance to avoid size flickering of the skeleton UI
window. We change all Resize/Move/SetSizeMode calls from before the first
nsWindow::Show call. Normally those have no effect, since the window isn't
shown yet, and if the window is not maximized, they typically match the
sizes we've gotten out of the registry anyway. However, if we are maximized,
then they produce a lot of visual noise. We can however achieve the desired
effect by just calling SetWindowPlacement.

Similarly, we switch the window styles of the skeleton UI window to match those
of the toplevel Windows window, and adjust the client rect from our window proc
in a way that matches the adjustments in nsWindow in the WM_NCCALCSIZE handler.
We do this because otherwise we get a flicker as soon as we change the styles
and nonclient margins as the fake chrome pops up and then back down.

Lastly we also change the extended window styles so that they match. We
historically added WS_EX_TOOLWINDOW here to hide the toolbar entry, because it
would otherwise switch out to a new toolbar entry when we changed the window
styles. However since our new styles match, we no longer need to do this. It
was also causing the maximized window to paint over the Windows taskbar.

Differential Revision: https://phabricator.services.mozilla.com/D93534
This commit is contained in:
Doug Thayer 2020-10-29 19:04:02 +00:00
Родитель 620dfb6899
Коммит 30478629cf
6 изменённых файлов: 341 добавлений и 114 удалений

Просмотреть файл

@ -71,6 +71,10 @@ static uint32_t* sPixelBuffer = nullptr;
static Vector<ColorRect>* sAnimatedRects = nullptr;
static int sTotalChromeHeight = 0;
static volatile LONG sAnimationControlFlag = 0;
static bool sMaximized = false;
static int sNonClientVerticalMargins = 0;
static int sNonClientHorizontalMargins = 0;
static uint32_t sDpi = 0;
// Color values needed by the animation loop
static uint32_t sBackgroundColor;
@ -96,8 +100,6 @@ typedef BOOL(WINAPI* ShowWindowProc)(HWND, int);
ShowWindowProc sShowWindow = NULL;
typedef BOOL(WINAPI* SetWindowPosProc)(HWND, HWND, int, int, int, int, UINT);
SetWindowPosProc sSetWindowPos = NULL;
typedef BOOL(WINAPI* RedrawWindowProc)(HWND, const RECT*, HRGN, UINT);
RedrawWindowProc sRedrawWindow = NULL;
typedef HDC(WINAPI* GetWindowDCProc)(HWND);
GetWindowDCProc sGetWindowDC = NULL;
typedef int(WINAPI* FillRectProc)(HDC, const RECT*, HBRUSH);
@ -106,6 +108,12 @@ typedef BOOL(WINAPI* DeleteObjectProc)(HGDIOBJ);
DeleteObjectProc sDeleteObject = NULL;
typedef int(WINAPI* ReleaseDCProc)(HWND, HDC);
ReleaseDCProc sReleaseDC = NULL;
typedef HMONITOR(WINAPI* MonitorFromWindowProc)(HWND, DWORD);
MonitorFromWindowProc sMonitorFromWindow = NULL;
typedef BOOL(WINAPI* GetMonitorInfoWProc)(HMONITOR, LPMONITORINFO);
GetMonitorInfoWProc sGetMonitorInfoW = NULL;
typedef LONG_PTR(WINAPI* SetWindowLongPtrWProc)(HWND, int, LONG_PTR);
SetWindowLongPtrWProc sSetWindowLongPtrW = NULL;
typedef int(WINAPI* StretchDIBitsProc)(HDC, int, int, int, int, int, int, int,
int, const VOID*, const BITMAPINFO*,
UINT, DWORD);
@ -117,23 +125,6 @@ static uint32_t sWindowWidth;
static uint32_t sWindowHeight;
static double sCSSToDevPixelScaling;
// We style our initial blank window as a WS_POPUP to eliminate the window
// caption and all that jazz. Alternatively, we could do a big dance in our
// window proc to paint into the nonclient area similarly to what we do in
// nsWindow, but it would be nontrivial code duplication, and the added
// complexity would not be worth it, given that we can just change the
// window style to our liking when we consume sPreXULSkeletonUIWindow from
// nsWindow.
static DWORD sWindowStyle = WS_POPUP;
// We add WS_EX_TOOLWINDOW here so that we do not produce a toolbar entry.
// We were not able to avoid flickering in the toolbar without this change,
// as the call to ::SetWindowLongPtrW to restyle the window inside
// nsWindow causes the toolbar entry to momentarily disappear. Not sure of
// the cause of this, but it doesn't feel too wrong to be missing a toolbar
// entry only so long as we are displaying a skeleton UI.
static DWORD sWindowStyleEx = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW;
static const int kAnimationCSSPixelsPerFrame = 21;
static const int kAnimationCSSExtraWindowSize = 300;
@ -198,22 +189,26 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
uint32_t urlbarColor = 0xffffff;
int chromeHorMargin = CSSToDevPixels(2, sCSSToDevPixelScaling);
int dpi = sGetDpiForWindow(hWnd);
int verticalOffset = sGetSystemMetricsForDpi(SM_CYBORDER, dpi);
int nonClientHorMargins = sGetSystemMetricsForDpi(SM_CXFRAME, dpi) +
sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
int horizontalOffset = nonClientHorMargins - chromeHorMargin;
int verticalOffset = sMaximized ? sNonClientVerticalMargins : 0;
int horizontalOffset =
sNonClientHorizontalMargins - (sMaximized ? 0 : chromeHorMargin);
// found in browser-aero.css, ":root[sizemode=normal][tabsintitlebar]"
int topBorderHeight =
sMaximized ? 0 : CSSToDevPixels(1, sCSSToDevPixelScaling);
// found in tabs.inc.css, "--tab-min-height" - depends on uidensity variable
int tabBarHeight = CSSToDevPixels(33, sCSSToDevPixelScaling) + verticalOffset;
// found in tabs.inc.css, ".titlebar-spacer"
int titlebarSpacerWidth =
CSSToDevPixels(40, sCSSToDevPixelScaling) + horizontalOffset;
(sMaximized ? 0 : CSSToDevPixels(40, sCSSToDevPixelScaling)) +
horizontalOffset;
// found in tabs.inc.css, ".tab-line"
int tabLineHeight = CSSToDevPixels(2, sCSSToDevPixelScaling) + verticalOffset;
int selectedTabWidth = CSSToDevPixels(224, sCSSToDevPixelScaling);
int toolbarHeight = CSSToDevPixels(39, sCSSToDevPixelScaling);
// found in urlbar-searchbar.inc.css, "#urlbar[breakout]"
int urlbarTopOffset = CSSToDevPixels(5, sCSSToDevPixelScaling);
int urlbarHeight = CSSToDevPixels(30, sCSSToDevPixelScaling);
int tabPlaceholderBarMarginTop = CSSToDevPixels(13, sCSSToDevPixelScaling);
int tabPlaceholderBarMarginLeft = CSSToDevPixels(10, sCSSToDevPixelScaling);
@ -234,11 +229,18 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
std::min((int)urlbarWidthCSS - 10, 260), sCSSToDevPixelScaling);
int urlbarTextPlaceholderHeight = CSSToDevPixels(10, sCSSToDevPixelScaling);
ColorRect topBorder = {};
topBorder.color = 0x00000000;
topBorder.x = 0;
topBorder.y = 0;
topBorder.width = sWindowWidth;
topBorder.height = topBorderHeight;
// The (traditionally dark blue on Windows) background of the tab bar.
ColorRect tabBar = {};
tabBar.color = tabBarColor;
tabBar.x = 0;
tabBar.y = 0;
tabBar.y = topBorder.height;
tabBar.width = sWindowWidth;
tabBar.height = tabBarHeight;
@ -246,7 +248,7 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
ColorRect tabLine = {};
tabLine.color = tabLineColor;
tabLine.x = titlebarSpacerWidth;
tabLine.y = 0;
tabLine.y = topBorder.height;
tabLine.width = selectedTabWidth;
tabLine.height = tabLineHeight;
@ -254,9 +256,9 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
ColorRect selectedTab = {};
selectedTab.color = sBackgroundColor;
selectedTab.x = titlebarSpacerWidth;
selectedTab.y = tabLineHeight;
selectedTab.y = tabLine.y + tabLineHeight;
selectedTab.width = selectedTabWidth;
selectedTab.height = tabBarHeight;
selectedTab.height = tabBar.y + tabBar.height - selectedTab.y;
// A placeholder rect representing text that will fill the selected tab title
ColorRect tabTextPlaceholder = {};
@ -270,7 +272,7 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
ColorRect toolbar = {};
toolbar.color = sBackgroundColor;
toolbar.x = 0;
toolbar.y = tabBarHeight;
toolbar.y = tabBar.y + tabBarHeight;
toolbar.width = sWindowWidth;
toolbar.height = toolbarHeight;
@ -308,9 +310,9 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
urlbar.color = urlbarColor;
urlbar.x = CSSToDevPixels(urlbarHorizontalOffsetCSS, sCSSToDevPixelScaling) +
horizontalOffset;
urlbar.y = CSSToDevPixels(39, sCSSToDevPixelScaling);
urlbar.y = tabBar.y + tabBarHeight + urlbarTopOffset;
urlbar.width = CSSToDevPixels(urlbarWidthCSS, sCSSToDevPixelScaling);
urlbar.height = CSSToDevPixels(30, sCSSToDevPixelScaling);
urlbar.height = urlbarHeight;
// The urlbar placeholder rect representating text that will fill the urlbar
// The placeholder rects should all be y-aligned.
@ -324,6 +326,7 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
urlbarTextPlaceholder.height = urlbarTextPlaceholderHeight;
ColorRect rects[] = {
topBorder,
tabBar,
tabLine,
selectedTab,
@ -336,6 +339,12 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
urlbarTextPlaceholder,
};
sTotalChromeHeight = chromeContentDivider.y + chromeContentDivider.height;
if (sTotalChromeHeight > sWindowHeight) {
printf_stderr("Exiting drawing skeleton UI because window is too small.\n");
return;
}
if (!sAnimatedRects->append(tabTextPlaceholder) ||
!sAnimatedRects->append(leftToolbarPlaceholder) ||
!sAnimatedRects->append(rightToolbarPlaceholder) ||
@ -345,8 +354,6 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
return;
}
sTotalChromeHeight = chromeContentDivider.y + chromeContentDivider.height;
sPixelBuffer =
(uint32_t*)calloc(sWindowWidth * sTotalChromeHeight, sizeof(uint32_t));
@ -555,10 +562,35 @@ DWORD WINAPI AnimateSkeletonUI(void* aUnused) {
LRESULT WINAPI PreXULSkeletonUIProc(HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam) {
// NOTE: this block was copied from WinUtils.cpp, and needs to be kept in
// sync.
if (msg == WM_NCCREATE && sEnableNonClientDpiScaling) {
sEnableNonClientDpiScaling(hWnd);
}
// NOTE: this block was paraphrased from the WM_NCCALCSIZE handler in
// nsWindow.cpp, and will need to be kept in sync.
if (msg == WM_NCCALCSIZE) {
RECT* clientRect =
wParam ? &(reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam))->rgrc[0]
: (reinterpret_cast<RECT*>(lParam));
// These match the margins set in browser-tabsintitlebar.js with
// default prefs on Windows. Bug 1673092 tracks lining this up with
// that more correctly instead of hard-coding it.
int horizontalOffset =
sNonClientHorizontalMargins -
(sMaximized ? 0 : CSSToDevPixels(2, sCSSToDevPixelScaling));
int verticalOffset =
sNonClientHorizontalMargins -
(sMaximized ? 0 : CSSToDevPixels(2, sCSSToDevPixelScaling));
clientRect->top = clientRect->top;
clientRect->left += horizontalOffset;
clientRect->right -= horizontalOffset;
clientRect->bottom -= verticalOffset;
return 0;
}
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
}
@ -635,10 +667,6 @@ bool LoadGdi32AndUser32Procedures() {
if (!sSetWindowPos) {
return false;
}
sRedrawWindow = (RedrawWindowProc)::GetProcAddress(user32Dll, "RedrawWindow");
if (!sRedrawWindow) {
return false;
}
sGetWindowDC = (GetWindowDCProc)::GetProcAddress(user32Dll, "GetWindowDC");
if (!sGetWindowDC) {
return false;
@ -659,7 +687,21 @@ bool LoadGdi32AndUser32Procedures() {
if (!sLoadCursorW) {
return false;
}
sMonitorFromWindow =
(MonitorFromWindowProc)::GetProcAddress(user32Dll, "MonitorFromWindow");
if (!sMonitorFromWindow) {
return false;
}
sGetMonitorInfoW =
(GetMonitorInfoWProc)::GetProcAddress(user32Dll, "GetMonitorInfoW");
if (!sGetMonitorInfoW) {
return false;
}
sSetWindowLongPtrW =
(SetWindowLongPtrWProc)::GetProcAddress(user32Dll, "SetWindowLongPtrW");
if (!sSetWindowLongPtrW) {
return false;
}
sStretchDIBits =
(StretchDIBitsProc)::GetProcAddress(gdi32Dll, "StretchDIBits");
if (!sStretchDIBits) {
@ -737,20 +779,32 @@ void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance) {
return;
}
uint32_t windowWidth;
result = ::RegGetValueW(regKey, nullptr, L"width", RRF_RT_REG_DWORD, nullptr,
reinterpret_cast<PBYTE>(&sWindowWidth), &dataLen);
reinterpret_cast<PBYTE>(&windowWidth), &dataLen);
if (result != ERROR_SUCCESS) {
printf_stderr("Error reading width %lu\n", GetLastError());
return;
}
uint32_t windowHeight;
result = ::RegGetValueW(regKey, nullptr, L"height", RRF_RT_REG_DWORD, nullptr,
reinterpret_cast<PBYTE>(&sWindowHeight), &dataLen);
reinterpret_cast<PBYTE>(&windowHeight), &dataLen);
if (result != ERROR_SUCCESS) {
printf_stderr("Error reading height %lu\n", GetLastError());
return;
}
uint32_t maximized;
result =
::RegGetValueW(regKey, nullptr, L"maximized", RRF_RT_REG_DWORD, nullptr,
reinterpret_cast<PBYTE>(&maximized), &dataLen);
if (result != ERROR_SUCCESS) {
printf_stderr("Error reading maximized %lu\n", GetLastError());
return;
}
sMaximized = maximized != 0;
dataLen = sizeof(double);
double urlbarHorizontalOffsetCSS;
result = ::RegGetValueW(
@ -779,18 +833,55 @@ void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance) {
return;
}
sPreXULSkeletonUIWindow =
sCreateWindowExW(sWindowStyleEx, L"MozillaWindowClass", L"", sWindowStyle,
screenX, screenY, sWindowWidth, sWindowHeight, nullptr,
nullptr, hInstance, nullptr);
int showCmd = SW_SHOWNORMAL;
DWORD windowStyle = kPreXULSkeletonUIWindowStyle;
if (sMaximized) {
showCmd = SW_SHOWMAXIMIZED;
windowStyle |= WS_MAXIMIZE;
}
sPreXULSkeletonUIWindow =
sCreateWindowExW(kPreXULSkeletonUIWindowStyleEx, L"MozillaWindowClass",
L"", windowStyle, screenX, screenY, windowWidth,
windowHeight, nullptr, nullptr, hInstance, nullptr);
sShowWindow(sPreXULSkeletonUIWindow, showCmd);
sDpi = sGetDpiForWindow(sPreXULSkeletonUIWindow);
sNonClientHorizontalMargins =
sGetSystemMetricsForDpi(SM_CXFRAME, sDpi) +
sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, sDpi);
sNonClientVerticalMargins = sGetSystemMetricsForDpi(SM_CYFRAME, sDpi) +
sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, sDpi);
if (sMaximized) {
HMONITOR monitor =
sMonitorFromWindow(sPreXULSkeletonUIWindow, MONITOR_DEFAULTTONULL);
if (!monitor) {
// NOTE: we specifically don't clean up the window here. If we're unable
// to finish setting up the window how we want it, we still need to keep
// it around and consume it with the first real toplevel window we
// create, to avoid flickering.
return;
}
MONITORINFO mi = {sizeof(MONITORINFO)};
if (!sGetMonitorInfoW(monitor, &mi)) {
return;
}
sWindowWidth =
mi.rcWork.right - mi.rcWork.left + sNonClientHorizontalMargins * 2;
sWindowHeight =
mi.rcWork.bottom - mi.rcWork.top + sNonClientVerticalMargins * 2;
} else {
sWindowWidth = windowWidth;
sWindowHeight = windowHeight;
}
sShowWindow(sPreXULSkeletonUIWindow, SW_SHOWNORMAL);
sSetWindowPos(sPreXULSkeletonUIWindow, 0, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
DrawSkeletonUI(sPreXULSkeletonUIWindow, urlbarHorizontalOffsetCSS,
urlbarWidthCSS);
sRedrawWindow(sPreXULSkeletonUIWindow, NULL, NULL, RDW_INVALIDATE);
if (sAnimatedRects) {
sPreXULSKeletonUIAnimationThread = ::CreateThread(
@ -798,6 +889,8 @@ void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance) {
}
}
bool WasPreXULSkeletonUIMaximized() { return sMaximized; }
HWND ConsumePreXULSkeletonUIHandle() {
// NOTE: we need to make sure that everything that runs here is a no-op if
// it failed to be set, which is a possibility. If anything fails to be set
@ -825,7 +918,8 @@ HWND ConsumePreXULSkeletonUIHandle() {
}
void PersistPreXULSkeletonUIValues(int screenX, int screenY, int width,
int height, double urlbarHorizontalOffsetCSS,
int height, bool maximized,
double urlbarHorizontalOffsetCSS,
double urlbarWidthCSS,
double cssToDevPixelScaling) {
if (!sPreXULSkeletonUIEnabled) {
@ -867,6 +961,14 @@ void PersistPreXULSkeletonUIValues(int screenX, int screenY, int width,
return;
}
DWORD maximizedDword = maximized ? 1 : 0;
result = ::RegSetValueExW(regKey, L"maximized", 0, REG_DWORD,
reinterpret_cast<PBYTE>(&maximizedDword),
sizeof(maximizedDword));
if (result != ERROR_SUCCESS) {
printf_stderr("Failed persisting maximized to Windows registry\n");
}
result = ::RegSetValueExW(regKey, L"urlbarHorizontalOffsetCSS", 0, REG_BINARY,
reinterpret_cast<PBYTE>(&urlbarHorizontalOffsetCSS),
sizeof(urlbarHorizontalOffsetCSS));

Просмотреть файл

@ -12,10 +12,20 @@
namespace mozilla {
// These unfortunately need to be kept in sync with the window style and
// extended window style computations in nsWindow. Luckily those styles seem
// to not vary based off of any user settings for the initial toplevel window,
// so we're safe here for now.
static const DWORD kPreXULSkeletonUIWindowStyle =
WS_CLIPCHILDREN | WS_DLGFRAME | WS_BORDER | WS_MAXIMIZEBOX |
WS_MINIMIZEBOX | WS_SIZEBOX | WS_SYSMENU;
static const DWORD kPreXULSkeletonUIWindowStyleEx = WS_EX_WINDOWEDGE;
MFBT_API void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance);
MFBT_API HWND ConsumePreXULSkeletonUIHandle();
MFBT_API bool WasPreXULSkeletonUIMaximized();
MFBT_API void PersistPreXULSkeletonUIValues(int screenX, int screenY, int width,
int height,
int height, bool maximized,
double urlbarHorizontalOffsetCSS,
double urlbarWidthCSS,
double cssToDevPixelScaling);

Просмотреть файл

@ -463,6 +463,9 @@ void WinUtils::Initialize() {
LRESULT WINAPI WinUtils::NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg,
WPARAM wParam,
LPARAM lParam) {
// NOTE: this function was copied out into the body of the pre-XUL skeleton
// UI window proc (PreXULSkeletonUI.cpp). If this function changes at any
// point, we should probably factor this out and use it from both locations.
if (msg == WM_NCCREATE && sEnableNonClientDpiScaling) {
sEnableNonClientDpiScaling(hWnd);
}

Просмотреть файл

@ -602,7 +602,7 @@ nsWindow::nsWindow(bool aIsChildWindow)
mMouseInDraggableArea = false;
mDestroyCalled = false;
mIsEarlyBlankWindow = false;
mWasPreXulSkeletonUI = false;
mIsShowingPreXULSkeletonUI = false;
mResizable = false;
mHasTaskbarIconBeenCreated = false;
mMouseTransparent = false;
@ -896,9 +896,34 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
if (aInitData->mWindowType == eWindowType_toplevel && !aParent) {
mWnd = ConsumePreXULSkeletonUIHandle();
if (mWnd) {
mWasPreXulSkeletonUI = true;
::SetWindowLongPtrW(mWnd, GWL_STYLE, style);
::SetWindowLongPtrW(mWnd, GWL_EXSTYLE, extendedStyle);
MOZ_ASSERT(style == kPreXULSkeletonUIWindowStyle,
"The skeleton UI window style should match the expected "
"style for the first window created");
MOZ_ASSERT(extendedStyle == kPreXULSkeletonUIWindowStyleEx,
"The skeleton UI window extended style should match the "
"expected extended style for the first window created");
mIsShowingPreXULSkeletonUI = true;
// If we successfully consumed the pre-XUL skeleton UI, just update
// our internal state to match what is currently being displayed.
mIsVisible = true;
mSizeMode = WasPreXULSkeletonUIMaximized() ? nsSizeMode_Maximized
: nsSizeMode_Normal;
// These match the margins set in browser-tabsintitlebar.js with
// default prefs on Windows. Bug 1673092 tracks lining this up with
// that more correctly instead of hard-coding it.
LayoutDeviceIntMargin margins(0, 2, 2, 2);
SetNonClientMargins(margins);
// Reset the WNDPROC for this window and its whole class, as we had
// to use our own WNDPROC when creating the the skeleton UI window.
::SetWindowLongPtrW(mWnd, GWLP_WNDPROC,
reinterpret_cast<LONG_PTR>(
WinUtils::NonClientDpiScalingDefWindowProcW));
::SetClassLongPtrW(mWnd, GCLP_WNDPROC,
reinterpret_cast<LONG_PTR>(
WinUtils::NonClientDpiScalingDefWindowProcW));
}
}
@ -1569,6 +1594,13 @@ already_AddRefed<SourceSurface> nsWindow::GetFallbackScrollSnapshot(
**************************************************************/
void nsWindow::Show(bool bState) {
if (bState) {
// The first time we decide to actually show the window is when we decide
// that we've taken over the window from the skeleton UI, and we should
// no longer treat resizes / moves specially.
mIsShowingPreXULSkeletonUI = false;
}
if (mWindowType == eWindowType_popup) {
// See bug 603793. When we try to draw D3D9/10 windows with a drop shadow
// without the DWM on a secondary monitor, windows fails to composite
@ -1917,24 +1949,56 @@ void nsWindow::Move(double aX, double aY) {
}
}
#endif
ClearThemeRegion();
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE;
// Workaround SetWindowPos bug with D3D9. If our window has a clip
// region, some drivers or OSes may incorrectly copy into the clipped-out
// area.
if (IsPlugin() && !mLayerManager && mClipRects &&
(mClipRectCount != 1 ||
!mClipRects[0].IsEqualInterior(
LayoutDeviceIntRect(0, 0, mBounds.Width(), mBounds.Height())))) {
flags |= SWP_NOCOPYBITS;
}
double oldScale = mDefaultScale;
mResizeState = IN_SIZEMOVE;
VERIFY(::SetWindowPos(mWnd, nullptr, x, y, 0, 0, flags));
mResizeState = NOT_RESIZING;
if (WinUtils::LogToPhysFactor(mWnd) != oldScale) {
ChangedDPI();
// Normally, when the skeleton UI is disabled, we resize+move the window
// before showing it in order to ensure that it restores to the correct
// position when the user un-maximizes it. However, when we are using the
// skeleton UI, this results in the skeleton UI window being moved around
// undesirably before being locked back into the maximized position. To
// avoid this, we simply set the placement to restore to via
// SetWindowPlacement. It's a little bit more of a dance, though, since we
// need to convert the workspace coords that SetWindowPlacement uses to the
// screen space coordinates we normally use with SetWindowPos.
if (mIsShowingPreXULSkeletonUI && WasPreXULSkeletonUIMaximized()) {
WINDOWPLACEMENT pl = {sizeof(WINDOWPLACEMENT)};
VERIFY(::GetWindowPlacement(mWnd, &pl));
HMONITOR monitor = ::MonitorFromWindow(mWnd, MONITOR_DEFAULTTONULL);
if (NS_WARN_IF(!monitor)) {
return;
}
MONITORINFO mi = {sizeof(MONITORINFO)};
VERIFY(::GetMonitorInfo(monitor, &mi));
int32_t deltaX =
x + mi.rcWork.left - mi.rcMonitor.left - pl.rcNormalPosition.left;
int32_t deltaY =
y + mi.rcWork.top - mi.rcMonitor.top - pl.rcNormalPosition.top;
pl.rcNormalPosition.left += deltaX;
pl.rcNormalPosition.right += deltaX;
pl.rcNormalPosition.top += deltaY;
pl.rcNormalPosition.bottom += deltaY;
VERIFY(::SetWindowPlacement(mWnd, &pl));
} else {
ClearThemeRegion();
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE;
// Workaround SetWindowPos bug with D3D9. If our window has a clip
// region, some drivers or OSes may incorrectly copy into the clipped-out
// area.
if (IsPlugin() && !mLayerManager && mClipRects &&
(mClipRectCount != 1 ||
!mClipRects[0].IsEqualInterior(
LayoutDeviceIntRect(0, 0, mBounds.Width(), mBounds.Height())))) {
flags |= SWP_NOCOPYBITS;
}
double oldScale = mDefaultScale;
mResizeState = IN_SIZEMOVE;
VERIFY(::SetWindowPos(mWnd, nullptr, x, y, 0, 0, flags));
mResizeState = NOT_RESIZING;
if (WinUtils::LogToPhysFactor(mWnd) != oldScale) {
ChangedDPI();
}
}
SetThemeRegion();
@ -1970,24 +2034,36 @@ void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
mBounds.SizeTo(width, height);
if (mWnd) {
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE;
// Refer to the comment above a similar check in nsWindow::Move
if (mIsShowingPreXULSkeletonUI && WasPreXULSkeletonUIMaximized()) {
WINDOWPLACEMENT pl = {sizeof(WINDOWPLACEMENT)};
VERIFY(::GetWindowPlacement(mWnd, &pl));
pl.rcNormalPosition.right = pl.rcNormalPosition.left + width;
pl.rcNormalPosition.bottom = pl.rcNormalPosition.top + GetHeight(height);
mResizeState = RESIZING;
VERIFY(::SetWindowPlacement(mWnd, &pl));
mResizeState = NOT_RESIZING;
} else {
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE;
if (!aRepaint) {
flags |= SWP_NOREDRAW;
if (!aRepaint) {
flags |= SWP_NOREDRAW;
}
ClearThemeRegion();
double oldScale = mDefaultScale;
mResizeState = RESIZING;
VERIFY(
::SetWindowPos(mWnd, nullptr, 0, 0, width, GetHeight(height), flags));
mResizeState = NOT_RESIZING;
if (WinUtils::LogToPhysFactor(mWnd) != oldScale) {
ChangedDPI();
}
SetThemeRegion();
ResizeDirectManipulationViewport();
}
ClearThemeRegion();
double oldScale = mDefaultScale;
mResizeState = RESIZING;
VERIFY(
::SetWindowPos(mWnd, nullptr, 0, 0, width, GetHeight(height), flags));
mResizeState = NOT_RESIZING;
if (WinUtils::LogToPhysFactor(mWnd) != oldScale) {
ChangedDPI();
}
SetThemeRegion();
ResizeDirectManipulationViewport();
}
if (aRepaint) Invalidate();
@ -2024,30 +2100,55 @@ void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
mBounds.SetRect(x, y, width, height);
if (mWnd) {
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE;
if (!aRepaint) {
flags |= SWP_NOREDRAW;
}
// Refer to the comment above a similar check in nsWindow::Move
if (mIsShowingPreXULSkeletonUI && WasPreXULSkeletonUIMaximized()) {
WINDOWPLACEMENT pl = {sizeof(WINDOWPLACEMENT)};
VERIFY(::GetWindowPlacement(mWnd, &pl));
ClearThemeRegion();
double oldScale = mDefaultScale;
mResizeState = RESIZING;
VERIFY(
::SetWindowPos(mWnd, nullptr, x, y, width, GetHeight(height), flags));
mResizeState = NOT_RESIZING;
if (WinUtils::LogToPhysFactor(mWnd) != oldScale) {
ChangedDPI();
}
if (mTransitionWnd) {
// If we have a fullscreen transition window, we need to make
// it topmost again, otherwise the taskbar may be raised by
// the system unexpectedly when we leave fullscreen state.
::SetWindowPos(mTransitionWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
SetThemeRegion();
HMONITOR monitor = ::MonitorFromWindow(mWnd, MONITOR_DEFAULTTONULL);
if (NS_WARN_IF(!monitor)) {
return;
}
MONITORINFO mi = {sizeof(MONITORINFO)};
VERIFY(::GetMonitorInfo(monitor, &mi));
ResizeDirectManipulationViewport();
int32_t deltaX =
x + mi.rcWork.left - mi.rcMonitor.left - pl.rcNormalPosition.left;
int32_t deltaY =
y + mi.rcWork.top - mi.rcMonitor.top - pl.rcNormalPosition.top;
pl.rcNormalPosition.left += deltaX;
pl.rcNormalPosition.right = pl.rcNormalPosition.left + width;
pl.rcNormalPosition.top += deltaY;
pl.rcNormalPosition.bottom = pl.rcNormalPosition.top + GetHeight(height);
VERIFY(::SetWindowPlacement(mWnd, &pl));
} else {
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE;
if (!aRepaint) {
flags |= SWP_NOREDRAW;
}
ClearThemeRegion();
double oldScale = mDefaultScale;
mResizeState = RESIZING;
VERIFY(
::SetWindowPos(mWnd, nullptr, x, y, width, GetHeight(height), flags));
mResizeState = NOT_RESIZING;
if (WinUtils::LogToPhysFactor(mWnd) != oldScale) {
ChangedDPI();
}
if (mTransitionWnd) {
// If we have a fullscreen transition window, we need to make
// it topmost again, otherwise the taskbar may be raised by
// the system unexpectedly when we leave fullscreen state.
::SetWindowPos(mTransitionWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
SetThemeRegion();
ResizeDirectManipulationViewport();
}
}
if (aRepaint) Invalidate();
@ -2167,6 +2268,14 @@ void nsWindow::SetSizeMode(nsSizeMode aMode) {
// calls us directly, and then the OS triggers another call to us.)
if (aMode == mSizeMode) return;
// If we are still displaying a maximized pre-XUL skeleton UI, ignore the
// noise of sizemode changes. Once we have "shown" the window for the first
// time (called nsWindow::Show(true), even though the window is already
// technically displayed), we will again accept sizemode changes.
if (mIsShowingPreXULSkeletonUI && WasPreXULSkeletonUIMaximized()) {
return;
}
// save the requested state
mLastSizeMode = mSizeMode;
nsBaseWidget::SetSizeMode(aMode);
@ -5318,6 +5427,8 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
} break;
case WM_NCCALCSIZE: {
// NOTE: the following block is mirrored in PreXULSkeletonUI.cpp, and
// will need to be kept in sync.
if (mCustomNonClient) {
// If `wParam` is `FALSE`, `lParam` points to a `RECT` that contains
// the proposed window rectangle for our window. During our
@ -8692,7 +8803,7 @@ bool nsWindow::SynchronouslyRepaintOnResize() {
}
void nsWindow::MaybeDispatchInitialFocusEvent() {
if (mWasPreXulSkeletonUI && ::GetActiveWindow() == mWnd) {
if (mIsShowingPreXULSkeletonUI && ::GetActiveWindow() == mWnd) {
DispatchFocusToTopLevelWindow(true);
}
}

Просмотреть файл

@ -606,7 +606,7 @@ class nsWindow final : public nsWindowBase {
bool mOpeningAnimationSuppressed;
bool mAlwaysOnTop;
bool mIsEarlyBlankWindow;
bool mWasPreXulSkeletonUI;
bool mIsShowingPreXULSkeletonUI;
bool mResizable;
DWORD_PTR mOldStyle;
DWORD_PTR mOldExStyle;

Просмотреть файл

@ -1835,9 +1835,10 @@ nsresult AppWindow::MaybeSaveEarlyWindowPersistentValues(
urlbarWidth -= (double)(2 * (urlbarBreakoutExtend + urlbarMarginInline));
}
PersistPreXULSkeletonUIValues(aRect.X(), aRect.Y(), aRect.Width(),
aRect.Height(), urlbarX, urlbarWidth,
mWindow->GetDefaultScale().scale);
PersistPreXULSkeletonUIValues(
aRect.X(), aRect.Y(), aRect.Width(), aRect.Height(),
mWindow->SizeMode() == nsSizeMode_Maximized, urlbarX, urlbarWidth,
mWindow->GetDefaultScale().scale);
#endif
return NS_OK;