mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Backed out 2 changesets (bug 1666874, bug 1665455) for causing bustage on PreXULSkeletonUI.cpp. CLOSED TREE
Backed out changeset 967c4cf56fd2 (bug 1666874) Backed out changeset e46238e6aabf (bug 1665455)
This commit is contained in:
parent
8745656461
commit
304bfab038
@ -8,56 +8,15 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/glue/Debug.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "mozilla/WindowsDpiAwareness.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "prthread.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct ColorRect {
|
||||
uint32_t color;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
struct NormalizedRGB {
|
||||
double r;
|
||||
double g;
|
||||
double b;
|
||||
};
|
||||
|
||||
NormalizedRGB UintToRGB(uint32_t color) {
|
||||
double r = static_cast<double>(color >> 16 & 0xff) / 255.0;
|
||||
double g = static_cast<double>(color >> 8 & 0xff) / 255.0;
|
||||
double b = static_cast<double>(color >> 0 & 0xff) / 255.0;
|
||||
return NormalizedRGB{r, g, b};
|
||||
}
|
||||
|
||||
uint32_t RGBToUint(const NormalizedRGB& rgb) {
|
||||
return (static_cast<uint32_t>(rgb.r * 255.0) << 16) |
|
||||
(static_cast<uint32_t>(rgb.g * 255.0) << 8) |
|
||||
(static_cast<uint32_t>(rgb.b * 255.0) << 0);
|
||||
}
|
||||
|
||||
double Lerp(double a, double b, double x) { return a + x * (b - a); }
|
||||
|
||||
NormalizedRGB Lerp(const NormalizedRGB& a, const NormalizedRGB& b, double x) {
|
||||
return NormalizedRGB{Lerp(a.r, b.r, x), Lerp(a.g, b.g, x), Lerp(a.b, b.b, x)};
|
||||
}
|
||||
|
||||
// Produces a smooth curve in [0,1] based on a linear input in [0,1]
|
||||
double SmoothStep3(double x) { return x * x * (3.0 - 2.0 * x); }
|
||||
|
||||
static const wchar_t kPreXULSkeletonUIKeyPath[] =
|
||||
L"SOFTWARE"
|
||||
L"\\" MOZ_APP_VENDOR L"\\" MOZ_APP_BASENAME L"\\PreXULSkeletonUISettings";
|
||||
@ -66,20 +25,6 @@ static bool sPreXULSkeletonUIEnabled = false;
|
||||
static HWND sPreXULSkeletonUIWindow;
|
||||
static LPWSTR const gStockApplicationIcon = MAKEINTRESOURCEW(32512);
|
||||
static LPWSTR const gIDCWait = MAKEINTRESOURCEW(32514);
|
||||
static HANDLE sPreXULSKeletonUIAnimationThread;
|
||||
|
||||
static uint32_t* sPixelBuffer = nullptr;
|
||||
static StaticAutoPtr<Vector<ColorRect>> sAnimatedRects;
|
||||
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;
|
||||
static uint32_t sToolbarForegroundColor;
|
||||
|
||||
typedef BOOL(WINAPI* EnableNonClientDpiScalingProc)(HWND);
|
||||
static EnableNonClientDpiScalingProc sEnableNonClientDpiScaling = NULL;
|
||||
@ -101,6 +46,8 @@ 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);
|
||||
@ -109,12 +56,6 @@ 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);
|
||||
@ -126,8 +67,22 @@ static uint32_t sWindowWidth;
|
||||
static uint32_t sWindowHeight;
|
||||
static double sCSSToDevPixelScaling;
|
||||
|
||||
static const int kAnimationCSSPixelsPerFrame = 21;
|
||||
static const int kAnimationCSSExtraWindowSize = 300;
|
||||
// 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;
|
||||
|
||||
// We could use nsAutoRegKey, but including nsWindowsHelpers.h causes build
|
||||
// failures in random places because we're in mozglue. Overall it should be
|
||||
@ -149,8 +104,20 @@ int CSSToDevPixels(int cssPixels, double scaling) {
|
||||
return CSSToDevPixels((double)cssPixels, scaling);
|
||||
}
|
||||
|
||||
struct ColorRect {
|
||||
uint32_t color;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
|
||||
double urlbarWidthCSS) {
|
||||
if (!sGetSystemMetricsForDpi || !sGetDpiForWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: we opt here to paint a pixel buffer for the application chrome by
|
||||
// hand, without using native UI library methods. Why do we do this?
|
||||
//
|
||||
@ -172,44 +139,37 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
|
||||
// manipulating raw pixels should not be *too* hard to maintain and
|
||||
// understand so long as it is only painting such simple shapes.
|
||||
|
||||
// NOTE: these could be constants, but eventually they won't be, and they will
|
||||
// need to be set here.
|
||||
// --toolbar-non-lwt-bgcolor in browser.css
|
||||
sBackgroundColor = 0xf9f9fa;
|
||||
// We define this, but it will need to differ based on theme
|
||||
sToolbarForegroundColor = 0xe5e5e5;
|
||||
|
||||
// found in browser-aero.css ":root[tabsintitlebar]:not(:-moz-lwtheme)"
|
||||
// (set to "hsl(235,33%,19%)")
|
||||
uint32_t tabBarColor = 0x202340;
|
||||
// --toolbar-non-lwt-bgcolor in browser.css
|
||||
uint32_t backgroundColor = 0xf9f9fa;
|
||||
// --chrome-content-separator-color in browser.css
|
||||
uint32_t chromeContentDividerColor = 0xe2e1e3;
|
||||
// We define this, but it will need to differ based on theme
|
||||
uint32_t toolbarForegroundColor = 0xe5e5e5;
|
||||
// controlled by css variable --tab-line-color
|
||||
uint32_t tabLineColor = 0x0a75d3;
|
||||
// controlled by css variable --toolbar-color
|
||||
uint32_t urlbarColor = 0xffffff;
|
||||
|
||||
int chromeHorMargin = CSSToDevPixels(2, sCSSToDevPixelScaling);
|
||||
int verticalOffset = sMaximized ? sNonClientVerticalMargins : 0;
|
||||
int horizontalOffset =
|
||||
sNonClientHorizontalMargins - (sMaximized ? 0 : chromeHorMargin);
|
||||
int dpi = sGetDpiForWindow(hWnd);
|
||||
int verticalOffset = sGetSystemMetricsForDpi(SM_CYBORDER, dpi);
|
||||
int nonClientHorMargins = sGetSystemMetricsForDpi(SM_CXFRAME, dpi) +
|
||||
sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||
int horizontalOffset = nonClientHorMargins - 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 =
|
||||
(sMaximized ? 0 : CSSToDevPixels(40, sCSSToDevPixelScaling)) +
|
||||
horizontalOffset;
|
||||
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);
|
||||
@ -230,18 +190,11 @@ 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 = topBorder.height;
|
||||
tabBar.y = 0;
|
||||
tabBar.width = sWindowWidth;
|
||||
tabBar.height = tabBarHeight;
|
||||
|
||||
@ -249,21 +202,21 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
|
||||
ColorRect tabLine = {};
|
||||
tabLine.color = tabLineColor;
|
||||
tabLine.x = titlebarSpacerWidth;
|
||||
tabLine.y = topBorder.height;
|
||||
tabLine.y = 0;
|
||||
tabLine.width = selectedTabWidth;
|
||||
tabLine.height = tabLineHeight;
|
||||
|
||||
// The initial selected tab
|
||||
ColorRect selectedTab = {};
|
||||
selectedTab.color = sBackgroundColor;
|
||||
selectedTab.color = backgroundColor;
|
||||
selectedTab.x = titlebarSpacerWidth;
|
||||
selectedTab.y = tabLine.y + tabLineHeight;
|
||||
selectedTab.y = tabLineHeight;
|
||||
selectedTab.width = selectedTabWidth;
|
||||
selectedTab.height = tabBar.y + tabBar.height - selectedTab.y;
|
||||
selectedTab.height = tabBarHeight;
|
||||
|
||||
// A placeholder rect representing text that will fill the selected tab title
|
||||
ColorRect tabTextPlaceholder = {};
|
||||
tabTextPlaceholder.color = sToolbarForegroundColor;
|
||||
tabTextPlaceholder.color = toolbarForegroundColor;
|
||||
tabTextPlaceholder.x = selectedTab.x + tabPlaceholderBarMarginLeft;
|
||||
tabTextPlaceholder.y = selectedTab.y + tabPlaceholderBarMarginTop;
|
||||
tabTextPlaceholder.width = tabPlaceholderBarWidth;
|
||||
@ -271,16 +224,16 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
|
||||
|
||||
// The toolbar background
|
||||
ColorRect toolbar = {};
|
||||
toolbar.color = sBackgroundColor;
|
||||
toolbar.color = backgroundColor;
|
||||
toolbar.x = 0;
|
||||
toolbar.y = tabBar.y + tabBarHeight;
|
||||
toolbar.y = tabBarHeight;
|
||||
toolbar.width = sWindowWidth;
|
||||
toolbar.height = toolbarHeight;
|
||||
|
||||
// A placeholder rect representing UI elements that will fill the left part
|
||||
// of the toolbar
|
||||
ColorRect leftToolbarPlaceholder = {};
|
||||
leftToolbarPlaceholder.color = sToolbarForegroundColor;
|
||||
leftToolbarPlaceholder.color = toolbarForegroundColor;
|
||||
leftToolbarPlaceholder.x =
|
||||
toolbar.x + toolbarPlaceholderMarginLeft + horizontalOffset;
|
||||
leftToolbarPlaceholder.y = toolbar.y + toolbarPlaceholderMarginTop;
|
||||
@ -290,7 +243,7 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
|
||||
// A placeholder rect representing UI elements that will fill the right part
|
||||
// of the toolbar
|
||||
ColorRect rightToolbarPlaceholder = {};
|
||||
rightToolbarPlaceholder.color = sToolbarForegroundColor;
|
||||
rightToolbarPlaceholder.color = toolbarForegroundColor;
|
||||
rightToolbarPlaceholder.x = sWindowWidth - horizontalOffset -
|
||||
toolbarPlaceholderMarginRight -
|
||||
toolbarPlaceholderWidth;
|
||||
@ -311,14 +264,14 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
|
||||
urlbar.color = urlbarColor;
|
||||
urlbar.x = CSSToDevPixels(urlbarHorizontalOffsetCSS, sCSSToDevPixelScaling) +
|
||||
horizontalOffset;
|
||||
urlbar.y = tabBar.y + tabBarHeight + urlbarTopOffset;
|
||||
urlbar.y = CSSToDevPixels(39, sCSSToDevPixelScaling);
|
||||
urlbar.width = CSSToDevPixels(urlbarWidthCSS, sCSSToDevPixelScaling);
|
||||
urlbar.height = urlbarHeight;
|
||||
urlbar.height = CSSToDevPixels(30, sCSSToDevPixelScaling);
|
||||
|
||||
// The urlbar placeholder rect representating text that will fill the urlbar
|
||||
// The placeholder rects should all be y-aligned.
|
||||
ColorRect urlbarTextPlaceholder = {};
|
||||
urlbarTextPlaceholder.color = sToolbarForegroundColor;
|
||||
urlbarTextPlaceholder.color = toolbarForegroundColor;
|
||||
urlbarTextPlaceholder.x = urlbar.x + urlbarTextPlaceholderMarginLeft;
|
||||
// This is equivalent to rightToolbarPlaceholder.y and
|
||||
// leftToolbarPlaceholder.y
|
||||
@ -327,7 +280,6 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
|
||||
urlbarTextPlaceholder.height = urlbarTextPlaceholderHeight;
|
||||
|
||||
ColorRect rects[] = {
|
||||
topBorder,
|
||||
tabBar,
|
||||
tabLine,
|
||||
selectedTab,
|
||||
@ -340,29 +292,17 @@ 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;
|
||||
}
|
||||
int totalChromeHeight = chromeContentDivider.y + chromeContentDivider.height;
|
||||
|
||||
if (!sAnimatedRects->append(tabTextPlaceholder) ||
|
||||
!sAnimatedRects->append(leftToolbarPlaceholder) ||
|
||||
!sAnimatedRects->append(rightToolbarPlaceholder) ||
|
||||
!sAnimatedRects->append(urlbarTextPlaceholder)) {
|
||||
sAnimatedRects = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
sPixelBuffer =
|
||||
(uint32_t*)calloc(sWindowWidth * sTotalChromeHeight, sizeof(uint32_t));
|
||||
uint32_t* pixelBuffer =
|
||||
(uint32_t*)calloc(sWindowWidth * totalChromeHeight, sizeof(uint32_t));
|
||||
|
||||
for (int i = 0; i < sizeof(rects) / sizeof(rects[0]); ++i) {
|
||||
ColorRect rect = rects[i];
|
||||
for (int y = rect.y; y < rect.y + rect.height; ++y) {
|
||||
uint32_t* lineStart = &sPixelBuffer[y * sWindowWidth];
|
||||
uint32_t* lineStart = &pixelBuffer[y * sWindowWidth];
|
||||
uint32_t* dataStart = lineStart + rect.x;
|
||||
std::fill_n(dataStart, rect.width, rect.color);
|
||||
std::fill(dataStart, dataStart + rect.width, rect.color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,226 +311,34 @@ void DrawSkeletonUI(HWND hWnd, double urlbarHorizontalOffsetCSS,
|
||||
BITMAPINFO chromeBMI = {};
|
||||
chromeBMI.bmiHeader.biSize = sizeof(chromeBMI.bmiHeader);
|
||||
chromeBMI.bmiHeader.biWidth = sWindowWidth;
|
||||
chromeBMI.bmiHeader.biHeight = -sTotalChromeHeight;
|
||||
chromeBMI.bmiHeader.biHeight = -totalChromeHeight;
|
||||
chromeBMI.bmiHeader.biPlanes = 1;
|
||||
chromeBMI.bmiHeader.biBitCount = 32;
|
||||
chromeBMI.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
// First, we just paint the chrome area with our pixel buffer
|
||||
sStretchDIBits(hdc, 0, 0, sWindowWidth, sTotalChromeHeight, 0, 0,
|
||||
sWindowWidth, sTotalChromeHeight, sPixelBuffer, &chromeBMI,
|
||||
DIB_RGB_COLORS, SRCCOPY);
|
||||
sStretchDIBits(hdc, 0, 0, sWindowWidth, totalChromeHeight, 0, 0, sWindowWidth,
|
||||
totalChromeHeight, pixelBuffer, &chromeBMI, DIB_RGB_COLORS,
|
||||
SRCCOPY);
|
||||
|
||||
// Then, we just fill the rest with FillRect
|
||||
RECT rect = {0, sTotalChromeHeight, (LONG)sWindowWidth, (LONG)sWindowHeight};
|
||||
HBRUSH brush = sCreateSolidBrush(sBackgroundColor);
|
||||
RECT rect = {0, totalChromeHeight, (LONG)sWindowWidth, (LONG)sWindowHeight};
|
||||
HBRUSH brush = sCreateSolidBrush(backgroundColor);
|
||||
sFillRect(hdc, &rect, brush);
|
||||
|
||||
sReleaseDC(hWnd, hdc);
|
||||
|
||||
free(pixelBuffer);
|
||||
|
||||
sDeleteObject(brush);
|
||||
}
|
||||
|
||||
DWORD WINAPI AnimateSkeletonUI(void* aUnused) {
|
||||
if (!sPixelBuffer || sAnimatedRects->empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// On each of the animated rects (which happen to all be placeholder UI
|
||||
// rects sharing the same color), we want to animate a gradient moving across
|
||||
// the screen from left to right. The gradient starts as the rect's color on,
|
||||
// the left side, changes to the background color of the window by the middle
|
||||
// of the gradient, and then goes back down to the rect's color. To make this
|
||||
// faster than interpolating between the two colors for each pixel for each
|
||||
// frame, we simply create a lookup buffer in which we can look up the color
|
||||
// for a particular offset into the gradient.
|
||||
//
|
||||
// To do this we just interpolate between the two values, and to give the
|
||||
// gradient a smoother transition between colors, we transform the linear
|
||||
// blend amount via the cubic smooth step function (SmoothStep3) to produce
|
||||
// a smooth start and stop for the gradient. We do this for the first half
|
||||
// of the gradient, and then simply copy that backwards for the second half.
|
||||
//
|
||||
// The CSS width of 80 chosen here is effectively is just to match the size
|
||||
// of the animation provided in the design mockup. We define it in CSS pixels
|
||||
// simply because the rest of our UI is based off of CSS scalings.
|
||||
int animationWidth = CSSToDevPixels(80, sCSSToDevPixelScaling);
|
||||
UniquePtr<uint32_t[]> animationLookup =
|
||||
MakeUnique<uint32_t[]>(animationWidth);
|
||||
uint32_t animationColor = sBackgroundColor;
|
||||
NormalizedRGB rgbBlend = UintToRGB(animationColor);
|
||||
|
||||
// Build the first half of the lookup table
|
||||
for (int i = 0; i < animationWidth / 2; ++i) {
|
||||
uint32_t baseColor = sToolbarForegroundColor;
|
||||
double blendAmountLinear =
|
||||
static_cast<double>(i) / (static_cast<double>(animationWidth / 2));
|
||||
double blendAmount = SmoothStep3(blendAmountLinear);
|
||||
|
||||
NormalizedRGB rgbBase = UintToRGB(baseColor);
|
||||
NormalizedRGB rgb = Lerp(rgbBase, rgbBlend, blendAmount);
|
||||
animationLookup[i] = RGBToUint(rgb);
|
||||
}
|
||||
|
||||
// Copy the first half of the lookup table into the second half backwards
|
||||
for (int i = animationWidth / 2; i < animationWidth; ++i) {
|
||||
int j = animationWidth - 1 - i;
|
||||
if (j == animationWidth / 2) {
|
||||
// If animationWidth is odd, we'll be left with one pixel at the center.
|
||||
// Just color that as the animation color.
|
||||
animationLookup[i] = animationColor;
|
||||
} else {
|
||||
animationLookup[i] = animationLookup[j];
|
||||
}
|
||||
}
|
||||
|
||||
// The bitmap info remains unchanged throughout the animation - this just
|
||||
// effectively describes the contents of sPixelBuffer
|
||||
BITMAPINFO chromeBMI = {};
|
||||
chromeBMI.bmiHeader.biSize = sizeof(chromeBMI.bmiHeader);
|
||||
chromeBMI.bmiHeader.biWidth = sWindowWidth;
|
||||
chromeBMI.bmiHeader.biHeight = -sTotalChromeHeight;
|
||||
chromeBMI.bmiHeader.biPlanes = 1;
|
||||
chromeBMI.bmiHeader.biBitCount = 32;
|
||||
chromeBMI.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
uint32_t animationIteration = 0;
|
||||
|
||||
int devPixelsPerFrame =
|
||||
CSSToDevPixels(kAnimationCSSPixelsPerFrame, sCSSToDevPixelScaling);
|
||||
int devPixelsExtraWindowSize =
|
||||
CSSToDevPixels(kAnimationCSSExtraWindowSize, sCSSToDevPixelScaling);
|
||||
|
||||
if (::InterlockedCompareExchange(&sAnimationControlFlag, 0, 0)) {
|
||||
// The window got consumed before we were able to draw anything.
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// The gradient will move across the screen at devPixelsPerFrame at
|
||||
// 60fps, and then loop back to the beginning. However, we add a buffer of
|
||||
// devPixelsExtraWindowSize around the edges so it doesn't immediately
|
||||
// jump back, giving it a more pulsing feel.
|
||||
int animationMin = ((animationIteration * devPixelsPerFrame) %
|
||||
(sWindowWidth + devPixelsExtraWindowSize)) -
|
||||
devPixelsExtraWindowSize / 2;
|
||||
int animationMax = animationMin + animationWidth;
|
||||
// The priorAnimationMin is the beginning of the previous frame's animation.
|
||||
// Since we only want to draw the bits of the image that we updated, we need
|
||||
// to overwrite the left bit of the animation we drew last frame with the
|
||||
// default color.
|
||||
int priorAnimationMin = animationMin - devPixelsPerFrame;
|
||||
animationMin = std::max(0, animationMin);
|
||||
priorAnimationMin = std::max(0, priorAnimationMin);
|
||||
animationMax = std::min((int)sWindowWidth, animationMax);
|
||||
|
||||
// The gradient only affects the specific rects that we put into
|
||||
// sAnimatedRects. So we simply update those rects, and maintain a flag
|
||||
// to avoid drawing when we don't need to.
|
||||
bool updatedAnything = false;
|
||||
for (ColorRect rect : *sAnimatedRects) {
|
||||
int rectMin = rect.x;
|
||||
int rectMax = rect.x + rect.width;
|
||||
bool animationWindowOverlaps =
|
||||
rectMax >= priorAnimationMin && rectMin < animationMax;
|
||||
|
||||
int priorUpdateAreaMin = std::max(rectMin, priorAnimationMin);
|
||||
int currentUpdateAreaMin = std::max(rectMin, animationMin);
|
||||
int priorUpdateAreaMax = std::min(rectMax, animationMin);
|
||||
int currentUpdateAreaMax = std::min(rectMax, animationMax);
|
||||
|
||||
if (animationWindowOverlaps) {
|
||||
updatedAnything = true;
|
||||
for (int y = rect.y; y < rect.y + rect.height; ++y) {
|
||||
uint32_t* lineStart = &sPixelBuffer[y * sWindowWidth];
|
||||
// Overwrite the tail end of last frame's animation with the rect's
|
||||
// normal, unanimated color.
|
||||
for (int x = priorUpdateAreaMin; x < priorUpdateAreaMax; ++x) {
|
||||
lineStart[x] = rect.color;
|
||||
}
|
||||
// Then apply the animated color
|
||||
for (int x = currentUpdateAreaMin; x < currentUpdateAreaMax; ++x) {
|
||||
lineStart[x] = animationLookup[x - animationMin];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updatedAnything) {
|
||||
HDC hdc = sGetWindowDC(sPreXULSkeletonUIWindow);
|
||||
|
||||
sStretchDIBits(hdc, priorAnimationMin, 0,
|
||||
animationMax - priorAnimationMin, sTotalChromeHeight,
|
||||
priorAnimationMin, 0, animationMax - priorAnimationMin,
|
||||
sTotalChromeHeight, sPixelBuffer, &chromeBMI,
|
||||
DIB_RGB_COLORS, SRCCOPY);
|
||||
|
||||
sReleaseDC(sPreXULSkeletonUIWindow, hdc);
|
||||
}
|
||||
|
||||
animationIteration++;
|
||||
|
||||
// We coordinate around our sleep here to ensure that the main thread does
|
||||
// not wait on us if we're sleeping. If we don't get 1 here, it means the
|
||||
// window has been consumed and we don't need to sleep. If in
|
||||
// ConsumePreXULSkeletonUIHandle we get a value other than 1 after
|
||||
// incrementing, it means we're sleeping, and that function can assume that
|
||||
// we will safely exit after the sleep because of the observed value of
|
||||
// sAnimationControlFlag.
|
||||
if (InterlockedIncrement(&sAnimationControlFlag) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Note: Sleep does not guarantee an exact time interval. If the system is
|
||||
// busy, for instance, we could easily end up taking several frames longer,
|
||||
// and really we could be left unscheduled for an arbitrarily long time.
|
||||
// This is fine, and we don't really care. We could track how much time this
|
||||
// actually took and jump the animation forward the appropriate amount, but
|
||||
// its not even clear that that's a better user experience. So we leave this
|
||||
// as simple as we can.
|
||||
::Sleep(16);
|
||||
|
||||
// Here we bring sAnimationControlFlag back down - again, if we don't get a
|
||||
// 0 here it means we consumed the skeleton UI window in the mean time, so
|
||||
// we can simply exit.
|
||||
if (InterlockedDecrement(&sAnimationControlFlag) != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -616,110 +364,6 @@ bool OpenPreXULSkeletonUIRegKey(HKEY& key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoadGdi32AndUser32Procedures() {
|
||||
HMODULE user32Dll = ::LoadLibraryW(L"user32");
|
||||
HMODULE gdi32Dll = ::LoadLibraryW(L"gdi32");
|
||||
|
||||
if (!user32Dll || !gdi32Dll) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto getThreadDpiAwarenessContext =
|
||||
(decltype(GetThreadDpiAwarenessContext)*)::GetProcAddress(
|
||||
user32Dll, "GetThreadDpiAwarenessContext");
|
||||
auto areDpiAwarenessContextsEqual =
|
||||
(decltype(AreDpiAwarenessContextsEqual)*)::GetProcAddress(
|
||||
user32Dll, "AreDpiAwarenessContextsEqual");
|
||||
if (getThreadDpiAwarenessContext && areDpiAwarenessContextsEqual &&
|
||||
areDpiAwarenessContextsEqual(getThreadDpiAwarenessContext(),
|
||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) {
|
||||
// EnableNonClientDpiScaling is optional - we can handle not having it.
|
||||
sEnableNonClientDpiScaling =
|
||||
(EnableNonClientDpiScalingProc)::GetProcAddress(
|
||||
user32Dll, "EnableNonClientDpiScaling");
|
||||
}
|
||||
|
||||
sGetSystemMetricsForDpi = (GetSystemMetricsForDpiProc)::GetProcAddress(
|
||||
user32Dll, "GetSystemMetricsForDpi");
|
||||
if (!sGetSystemMetricsForDpi) {
|
||||
return false;
|
||||
}
|
||||
sGetDpiForWindow =
|
||||
(GetDpiForWindowProc)::GetProcAddress(user32Dll, "GetDpiForWindow");
|
||||
if (!sGetDpiForWindow) {
|
||||
return false;
|
||||
}
|
||||
sRegisterClassW =
|
||||
(RegisterClassWProc)::GetProcAddress(user32Dll, "RegisterClassW");
|
||||
if (!sRegisterClassW) {
|
||||
return false;
|
||||
}
|
||||
sCreateWindowExW =
|
||||
(CreateWindowExWProc)::GetProcAddress(user32Dll, "CreateWindowExW");
|
||||
if (!sCreateWindowExW) {
|
||||
return false;
|
||||
}
|
||||
sShowWindow = (ShowWindowProc)::GetProcAddress(user32Dll, "ShowWindow");
|
||||
if (!sShowWindow) {
|
||||
return false;
|
||||
}
|
||||
sSetWindowPos = (SetWindowPosProc)::GetProcAddress(user32Dll, "SetWindowPos");
|
||||
if (!sSetWindowPos) {
|
||||
return false;
|
||||
}
|
||||
sGetWindowDC = (GetWindowDCProc)::GetProcAddress(user32Dll, "GetWindowDC");
|
||||
if (!sGetWindowDC) {
|
||||
return false;
|
||||
}
|
||||
sFillRect = (FillRectProc)::GetProcAddress(user32Dll, "FillRect");
|
||||
if (!sFillRect) {
|
||||
return false;
|
||||
}
|
||||
sReleaseDC = (ReleaseDCProc)::GetProcAddress(user32Dll, "ReleaseDC");
|
||||
if (!sReleaseDC) {
|
||||
return false;
|
||||
}
|
||||
sLoadIconW = (LoadIconWProc)::GetProcAddress(user32Dll, "LoadIconW");
|
||||
if (!sLoadIconW) {
|
||||
return false;
|
||||
}
|
||||
sLoadCursorW = (LoadCursorWProc)::GetProcAddress(user32Dll, "LoadCursorW");
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
sCreateSolidBrush =
|
||||
(CreateSolidBrushProc)::GetProcAddress(gdi32Dll, "CreateSolidBrush");
|
||||
if (!sCreateSolidBrush) {
|
||||
return false;
|
||||
}
|
||||
sDeleteObject = (DeleteObjectProc)::GetProcAddress(gdi32Dll, "DeleteObject");
|
||||
if (!sDeleteObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance) {
|
||||
HKEY regKey;
|
||||
if (!IsWin10OrLater() || !OpenPreXULSkeletonUIRegKey(regKey)) {
|
||||
@ -737,13 +381,53 @@ void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance) {
|
||||
}
|
||||
sPreXULSkeletonUIEnabled = true;
|
||||
|
||||
MOZ_ASSERT(!sAnimatedRects);
|
||||
sAnimatedRects = new Vector<ColorRect>();
|
||||
// EnableNonClientDpiScaling must be called during the initialization of
|
||||
// the window, so we have to find it and store it before we create our
|
||||
// window in order to run it in our WndProc.
|
||||
HMODULE user32Dll = ::LoadLibraryW(L"user32");
|
||||
HMODULE gdi32Dll = ::LoadLibraryW(L"gdi32");
|
||||
|
||||
if (!LoadGdi32AndUser32Procedures()) {
|
||||
if (!user32Dll || !gdi32Dll) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto getThreadDpiAwarenessContext =
|
||||
(decltype(GetThreadDpiAwarenessContext)*)::GetProcAddress(
|
||||
user32Dll, "GetThreadDpiAwarenessContext");
|
||||
auto areDpiAwarenessContextsEqual =
|
||||
(decltype(AreDpiAwarenessContextsEqual)*)::GetProcAddress(
|
||||
user32Dll, "AreDpiAwarenessContextsEqual");
|
||||
if (getThreadDpiAwarenessContext && areDpiAwarenessContextsEqual &&
|
||||
areDpiAwarenessContextsEqual(getThreadDpiAwarenessContext(),
|
||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) {
|
||||
// Only per-monitor v1 requires these workarounds.
|
||||
sEnableNonClientDpiScaling =
|
||||
(EnableNonClientDpiScalingProc)::GetProcAddress(
|
||||
user32Dll, "EnableNonClientDpiScaling");
|
||||
}
|
||||
|
||||
sGetSystemMetricsForDpi = (GetSystemMetricsForDpiProc)::GetProcAddress(
|
||||
user32Dll, "GetSystemMetricsForDpi");
|
||||
sGetDpiForWindow =
|
||||
(GetDpiForWindowProc)::GetProcAddress(user32Dll, "GetDpiForWindow");
|
||||
sRegisterClassW =
|
||||
(RegisterClassWProc)::GetProcAddress(user32Dll, "RegisterClassW");
|
||||
sCreateWindowExW =
|
||||
(CreateWindowExWProc)::GetProcAddress(user32Dll, "CreateWindowExW");
|
||||
sShowWindow = (ShowWindowProc)::GetProcAddress(user32Dll, "ShowWindow");
|
||||
sSetWindowPos = (SetWindowPosProc)::GetProcAddress(user32Dll, "SetWindowPos");
|
||||
sRedrawWindow = (RedrawWindowProc)::GetProcAddress(user32Dll, "RedrawWindow");
|
||||
sGetWindowDC = (GetWindowDCProc)::GetProcAddress(user32Dll, "GetWindowDC");
|
||||
sFillRect = (FillRectProc)::GetProcAddress(user32Dll, "FillRect");
|
||||
sDeleteObject = (DeleteObjectProc)::GetProcAddress(gdi32Dll, "DeleteObject");
|
||||
sReleaseDC = (ReleaseDCProc)::GetProcAddress(user32Dll, "ReleaseDC");
|
||||
sLoadIconW = (LoadIconWProc)::GetProcAddress(user32Dll, "LoadIconW");
|
||||
sLoadCursorW = (LoadCursorWProc)::GetProcAddress(user32Dll, "LoadCursorW");
|
||||
sStretchDIBits =
|
||||
(StretchDIBitsProc)::GetProcAddress(gdi32Dll, "StretchDIBits");
|
||||
sCreateSolidBrush =
|
||||
(CreateSolidBrushProc)::GetProcAddress(gdi32Dll, "CreateSolidBrush");
|
||||
|
||||
WNDCLASSW wc;
|
||||
wc.style = CS_DBLCLKS;
|
||||
wc.lpfnWndProc = PreXULSkeletonUIProc;
|
||||
@ -779,32 +463,20 @@ void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t windowWidth;
|
||||
result = ::RegGetValueW(regKey, nullptr, L"width", RRF_RT_REG_DWORD, nullptr,
|
||||
reinterpret_cast<PBYTE>(&windowWidth), &dataLen);
|
||||
reinterpret_cast<PBYTE>(&sWindowWidth), &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>(&windowHeight), &dataLen);
|
||||
reinterpret_cast<PBYTE>(&sWindowHeight), &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(
|
||||
@ -833,92 +505,28 @@ void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
sCreateWindowExW(sWindowStyleEx, L"MozillaWindowClass", L"", sWindowStyle,
|
||||
screenX, screenY, sWindowWidth, sWindowHeight, nullptr,
|
||||
nullptr, hInstance, nullptr);
|
||||
|
||||
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);
|
||||
|
||||
if (sAnimatedRects) {
|
||||
sPreXULSKeletonUIAnimationThread = ::CreateThread(
|
||||
nullptr, 256 * 1024, AnimateSkeletonUI, nullptr, 0, nullptr);
|
||||
}
|
||||
sRedrawWindow(sPreXULSkeletonUIWindow, NULL, NULL, RDW_INVALIDATE);
|
||||
}
|
||||
|
||||
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
|
||||
// we don't want to clean everything up right away, because if we have a
|
||||
// blank window up, we want that to stick around and get consumed by nsWindow
|
||||
// as normal, otherwise the window will flicker in and out, which we imagine
|
||||
// is unpleasant.
|
||||
|
||||
// If we don't get 1 here, it means the thread is actually just sleeping, so
|
||||
// we don't need to worry about giving out ownership of the window, because
|
||||
// the thread will simply exit after its sleep. However, if it is 1, we need
|
||||
// to wait for the thread to exit to be safe, as it could be doing anything.
|
||||
if (InterlockedIncrement(&sAnimationControlFlag) == 1) {
|
||||
::WaitForSingleObject(sPreXULSKeletonUIAnimationThread, INFINITE);
|
||||
}
|
||||
::CloseHandle(sPreXULSKeletonUIAnimationThread);
|
||||
sPreXULSKeletonUIAnimationThread = nullptr;
|
||||
HWND result = sPreXULSkeletonUIWindow;
|
||||
sPreXULSkeletonUIWindow = nullptr;
|
||||
free(sPixelBuffer);
|
||||
sPixelBuffer = nullptr;
|
||||
sAnimatedRects = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
void PersistPreXULSkeletonUIValues(int screenX, int screenY, int width,
|
||||
int height, bool maximized,
|
||||
double urlbarHorizontalOffsetCSS,
|
||||
int height, double urlbarHorizontalOffsetCSS,
|
||||
double urlbarWidthCSS,
|
||||
double cssToDevPixelScaling) {
|
||||
if (!sPreXULSkeletonUIEnabled) {
|
||||
@ -960,14 +568,6 @@ 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,20 +12,10 @@
|
||||
|
||||
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, bool maximized,
|
||||
int height,
|
||||
double urlbarHorizontalOffsetCSS,
|
||||
double urlbarWidthCSS,
|
||||
double cssToDevPixelScaling);
|
||||
|
@ -463,9 +463,6 @@ 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;
|
||||
mIsShowingPreXULSkeletonUI = false;
|
||||
mWasPreXulSkeletonUI = false;
|
||||
mResizable = false;
|
||||
mHasTaskbarIconBeenCreated = false;
|
||||
mMouseTransparent = false;
|
||||
@ -896,34 +896,9 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
|
||||
if (aInitData->mWindowType == eWindowType_toplevel && !aParent) {
|
||||
mWnd = ConsumePreXULSkeletonUIHandle();
|
||||
if (mWnd) {
|
||||
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));
|
||||
mWasPreXulSkeletonUI = true;
|
||||
::SetWindowLongPtrW(mWnd, GWL_STYLE, style);
|
||||
::SetWindowLongPtrW(mWnd, GWL_EXSTYLE, extendedStyle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1594,13 +1569,6 @@ 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
|
||||
@ -1949,56 +1917,24 @@ void nsWindow::Move(double aX, double aY) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ClearThemeRegion();
|
||||
|
||||
// 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();
|
||||
}
|
||||
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();
|
||||
@ -2034,36 +1970,24 @@ void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
|
||||
mBounds.SizeTo(width, height);
|
||||
|
||||
if (mWnd) {
|
||||
// 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;
|
||||
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE;
|
||||
|
||||
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();
|
||||
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();
|
||||
}
|
||||
|
||||
if (aRepaint) Invalidate();
|
||||
@ -2100,55 +2024,30 @@ void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
|
||||
mBounds.SetRect(x, y, width, height);
|
||||
|
||||
if (mWnd) {
|
||||
// Refer to the comment above a similar check in nsWindow::Move
|
||||
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 = 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();
|
||||
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();
|
||||
@ -2268,14 +2167,6 @@ 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);
|
||||
@ -5427,8 +5318,6 @@ 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
|
||||
@ -8803,7 +8692,7 @@ bool nsWindow::SynchronouslyRepaintOnResize() {
|
||||
}
|
||||
|
||||
void nsWindow::MaybeDispatchInitialFocusEvent() {
|
||||
if (mIsShowingPreXULSkeletonUI && ::GetActiveWindow() == mWnd) {
|
||||
if (mWasPreXulSkeletonUI && ::GetActiveWindow() == mWnd) {
|
||||
DispatchFocusToTopLevelWindow(true);
|
||||
}
|
||||
}
|
||||
|
@ -606,7 +606,7 @@ class nsWindow final : public nsWindowBase {
|
||||
bool mOpeningAnimationSuppressed;
|
||||
bool mAlwaysOnTop;
|
||||
bool mIsEarlyBlankWindow;
|
||||
bool mIsShowingPreXULSkeletonUI;
|
||||
bool mWasPreXulSkeletonUI;
|
||||
bool mResizable;
|
||||
DWORD_PTR mOldStyle;
|
||||
DWORD_PTR mOldExStyle;
|
||||
|
@ -1835,10 +1835,9 @@ nsresult AppWindow::MaybeSaveEarlyWindowPersistentValues(
|
||||
urlbarWidth -= (double)(2 * (urlbarBreakoutExtend + urlbarMarginInline));
|
||||
}
|
||||
|
||||
PersistPreXULSkeletonUIValues(
|
||||
aRect.X(), aRect.Y(), aRect.Width(), aRect.Height(),
|
||||
mWindow->SizeMode() == nsSizeMode_Maximized, urlbarX, urlbarWidth,
|
||||
mWindow->GetDefaultScale().scale);
|
||||
PersistPreXULSkeletonUIValues(aRect.X(), aRect.Y(), aRect.Width(),
|
||||
aRect.Height(), urlbarX, urlbarWidth,
|
||||
mWindow->GetDefaultScale().scale);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
|
Loading…
Reference in New Issue
Block a user