Backed out 5 changesets (bug 1930292, bug 1932600) for causing chrome failures at test_maximized_persist.xhtml on a CLOSED TREE
Backed out changeset 2418bfee53f1 (bug 1932600) Backed out changeset 3297e990715a (bug 1932600) Backed out changeset 24a670dea977 (bug 1930292) Backed out changeset 7dd9f48216dd (bug 1930292) Backed out changeset 15a85ec739dd (bug 1930292)
This commit is contained in:
@@ -120,8 +120,8 @@ addAccessibleTask(
|
||||
info("Showing title bar");
|
||||
let titleBarChanged = BrowserTestUtils.waitForMutationCondition(
|
||||
document.documentElement,
|
||||
{ attributes: true, attributeFilter: ["customtitlebar"] },
|
||||
() => !document.documentElement.hasAttribute("customtitlebar")
|
||||
{ attributes: true, attributeFilter: ["tabsintitlebar"] },
|
||||
() => !document.documentElement.hasAttribute("tabsintitlebar")
|
||||
);
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.tabs.inTitlebar", false]],
|
||||
|
||||
@@ -102,13 +102,12 @@ var gBrowserInit = {
|
||||
toolbarMenubar.setAttribute("data-l10n-attrs", "toolbarname");
|
||||
}
|
||||
|
||||
// Run menubar initialization first, to avoid CustomTitlebar code picking
|
||||
// Run menubar initialization first, to avoid TabsInTitlebar code picking
|
||||
// up mutations from it and causing a reflow.
|
||||
AutoHideMenubar.init();
|
||||
// Update the customtitlebar attribute so the window can be sized
|
||||
// correctly.
|
||||
// Update the chromemargin attribute so the window can be sized correctly.
|
||||
window.TabBarVisibility.update();
|
||||
CustomTitlebar.init();
|
||||
TabsInTitlebar.init();
|
||||
|
||||
new LightweightThemeConsumer(document);
|
||||
|
||||
@@ -1025,7 +1024,7 @@ var gBrowserInit = {
|
||||
onUnload() {
|
||||
gUIDensity.uninit();
|
||||
|
||||
CustomTitlebar.uninit();
|
||||
TabsInTitlebar.uninit();
|
||||
|
||||
ToolbarIconColor.uninit();
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var CustomTitlebar = {
|
||||
var TabsInTitlebar = {
|
||||
init() {
|
||||
this._readPref();
|
||||
Services.prefs.addObserver(this._prefName, this);
|
||||
@@ -40,7 +40,7 @@ var CustomTitlebar = {
|
||||
},
|
||||
|
||||
get enabled() {
|
||||
return document.documentElement.hasAttribute("customtitlebar");
|
||||
return document.documentElement.getAttribute("tabsintitlebar") == "true";
|
||||
},
|
||||
|
||||
observe(subject, topic) {
|
||||
@@ -67,13 +67,23 @@ var CustomTitlebar = {
|
||||
this.systemSupported &&
|
||||
!window.fullScreen &&
|
||||
!Object.keys(this._disallowed).length;
|
||||
|
||||
document.documentElement.toggleAttribute("customtitlebar", allowed);
|
||||
if (AppConstants.platform == "macosx") {
|
||||
document.documentElement.toggleAttribute("drawtitle", !allowed);
|
||||
if (allowed) {
|
||||
document.documentElement.setAttribute("tabsintitlebar", "true");
|
||||
if (AppConstants.platform == "macosx") {
|
||||
document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
|
||||
document.documentElement.removeAttribute("drawtitle");
|
||||
} else {
|
||||
document.documentElement.setAttribute("chromemargin", "0,2,2,2");
|
||||
}
|
||||
} else {
|
||||
document.documentElement.removeAttribute("tabsintitlebar");
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
if (AppConstants.platform == "macosx") {
|
||||
document.documentElement.setAttribute("drawtitle", "true");
|
||||
}
|
||||
}
|
||||
|
||||
ToolbarIconColor.inferFromText("customtitlebar", allowed);
|
||||
ToolbarIconColor.inferFromText("tabsintitlebar", allowed);
|
||||
TabBarVisibility.update(true);
|
||||
},
|
||||
|
||||
@@ -6642,7 +6642,7 @@ var ToolbarIconColor = {
|
||||
_windowState: {
|
||||
active: false,
|
||||
fullscreen: false,
|
||||
customtitlebar: false,
|
||||
tabsintitlebar: false,
|
||||
},
|
||||
init() {
|
||||
this._initialized = true;
|
||||
@@ -6709,8 +6709,8 @@ var ToolbarIconColor = {
|
||||
case "toolbarvisibilitychange":
|
||||
// toolbar changes dont require reset of the cached color values
|
||||
break;
|
||||
case "customtitlebar":
|
||||
this._windowState.customtitlebar = reasonValue;
|
||||
case "tabsintitlebar":
|
||||
this._windowState.tabsintitlebar = reasonValue;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,12 @@
|
||||
#endif
|
||||
data-l10n-args="{"content-title":"CONTENTTITLE"}"
|
||||
data-l10n-attrs="data-content-title-default, data-content-title-private, data-title-default, data-title-private"
|
||||
customtitlebar="true"
|
||||
#ifdef XP_WIN
|
||||
chromemargin="0,2,2,2"
|
||||
#else
|
||||
chromemargin="0,-1,-1,-1"
|
||||
#endif
|
||||
tabsintitlebar="true"
|
||||
windowtype="navigator:browser"
|
||||
macanimationtype="document"
|
||||
macnativefullscreen="true"
|
||||
@@ -113,7 +118,7 @@
|
||||
}
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/browser-pageActions.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/sidebar/browser-sidebar.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/browser-customtitlebar.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/browser-tabsintitlebar.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/browser-unified-extensions.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser/tab.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser/tabbrowser.js", this);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
windowtype="Browser:page-info"
|
||||
#ifdef XP_MACOSX
|
||||
drawtitle="true"
|
||||
customtitlebar="true"
|
||||
chromemargin="0,0,0,0"
|
||||
#endif
|
||||
onload="onLoadPageInfo()"
|
||||
align="stretch"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="webrtcIndicator"
|
||||
windowtype="Browser:WebRTCGlobalIndicator"
|
||||
customtitlebar="true"
|
||||
chromemargin="0,0,0,0"
|
||||
>
|
||||
<head>
|
||||
<link rel="stylesheet" href="chrome://global/skin/global.css" />
|
||||
|
||||
@@ -59,7 +59,7 @@ browser.jar:
|
||||
content/browser/browser-sitePermissionPanel.js (content/browser-sitePermissionPanel.js)
|
||||
content/browser/browser-siteProtections.js (content/browser-siteProtections.js)
|
||||
content/browser/browser-sync.js (content/browser-sync.js)
|
||||
content/browser/browser-customtitlebar.js (content/browser-customtitlebar.js)
|
||||
content/browser/browser-tabsintitlebar.js (content/browser-tabsintitlebar.js)
|
||||
content/browser/browser-toolbarKeyNav.js (content/browser-toolbarKeyNav.js)
|
||||
content/browser/browser-thumbnails.js (content/browser-thumbnails.js)
|
||||
content/browser/browser-unified-extensions.js (content/browser-unified-extensions.js)
|
||||
|
||||
@@ -1822,7 +1822,7 @@ BrowserGlue.prototype = {
|
||||
// Hide the titlebar if the actual browser window will draw in it.
|
||||
let hiddenTitlebar = Services.appinfo.drawInTitlebar;
|
||||
if (hiddenTitlebar) {
|
||||
win.windowUtils.setCustomTitlebar(true);
|
||||
win.windowUtils.setChromeMargin(0, 2, 2, 2);
|
||||
}
|
||||
|
||||
let docElt = win.document.documentElement;
|
||||
|
||||
@@ -1674,7 +1674,7 @@ CustomizeMode.prototype = {
|
||||
},
|
||||
|
||||
_canDrawInTitlebar() {
|
||||
return this.window.CustomTitlebar.systemSupported;
|
||||
return this.window.TabsInTitlebar.systemSupported;
|
||||
},
|
||||
|
||||
_ensureCustomizationPanels() {
|
||||
|
||||
@@ -143,9 +143,9 @@ add_task(async function () {
|
||||
// Bug 971626 - Restore Defaults should collapse the Title Bar
|
||||
add_task(async function () {
|
||||
{
|
||||
const supported = CustomTitlebar.systemSupported;
|
||||
const supported = TabsInTitlebar.systemSupported;
|
||||
is(typeof supported, "boolean");
|
||||
info("CustomTitlebar support: " + supported);
|
||||
info("TabsInTitlebar support: " + supported);
|
||||
if (!supported) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ add_task(async function tabstrip_context() {
|
||||
// Right-click on the title bar spacer before the tabstrip should show a
|
||||
// context menu without options to move it and no tab-specific options.
|
||||
add_task(async function titlebar_spacer_context() {
|
||||
if (!CustomTitlebar.enabled) {
|
||||
if (!TabsInTitlebar.enabled) {
|
||||
info("Skipping test that requires tabs in the title bar.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
screenX="10" screenY="10"
|
||||
#ifdef XP_MACOSX
|
||||
drawtitle="true"
|
||||
customtitlebar="true"
|
||||
chromemargin="0,0,0,0"
|
||||
#endif
|
||||
toggletoolbar="true"
|
||||
persist="width height screenX screenY sizemode">
|
||||
|
||||
@@ -46,13 +46,13 @@ function getExpectedElements(win, tabstripOrientation = "horizontal") {
|
||||
const sizeMode = win.document.documentElement.getAttribute("sizemode");
|
||||
let selectors;
|
||||
|
||||
// NOTE: CustomTitlebar behaviour isn't under test here. We just want to assert on
|
||||
// NOTE: TabsInTitlebar behaviour isn't under test here. We just want to assert on
|
||||
// the right stuff being visible whatever the case for the given window.
|
||||
|
||||
if (tabstripOrientation == "horizontal") {
|
||||
selectors = ["#TabsToolbar"];
|
||||
|
||||
if (win.CustomTitlebar.enabled) {
|
||||
if (win.TabsInTitlebar.enabled) {
|
||||
selectors.push("#TabsToolbar .titlebar-buttonbox-container");
|
||||
if (sizeMode == "normal") {
|
||||
selectors.push("#TabsToolbar .titlebar-spacer");
|
||||
@@ -62,7 +62,7 @@ function getExpectedElements(win, tabstripOrientation = "horizontal") {
|
||||
}
|
||||
|
||||
selectors = ["#vertical-tabs"];
|
||||
if (win.CustomTitlebar.enabled) {
|
||||
if (win.TabsInTitlebar.enabled) {
|
||||
selectors.push("#nav-bar .titlebar-buttonbox-container");
|
||||
if (sizeMode == "normal") {
|
||||
selectors.push("#nav-bar .titlebar-spacer[type='post-tabs']");
|
||||
@@ -89,7 +89,7 @@ add_task(async function test_toggle_vertical_tabs() {
|
||||
);
|
||||
info(`sizemode: ${document.documentElement.getAttribute("sizemode")}`);
|
||||
info(
|
||||
`customtitlebar: ${document.documentElement.getAttribute("customtitlebar")}`
|
||||
`tabsintitlebar: ${document.documentElement.getAttribute("tabsintitlebar")}`
|
||||
);
|
||||
|
||||
const expectedElementsWhenHorizontal = getExpectedElements(
|
||||
|
||||
@@ -8089,28 +8089,28 @@ var TabBarVisibility = {
|
||||
}
|
||||
|
||||
if (nonPopupWithVerticalTabs) {
|
||||
// CustomTitlebar decides if we can draw within the titlebar area.
|
||||
// TabsInTitlebar decides if we can draw within the titlebar area.
|
||||
// In vertical tabs mode, the toolbar with the horizontal tabstrip gets hidden
|
||||
// and the navbar becomes a titlebar. This makes CustomTitlebar a bit of a misnomer.
|
||||
// and the navbar becomes a titlebar. This makes TabsInTitlebar a bit of a misnomer.
|
||||
// We'll fix this in Bug 1921034.
|
||||
hideTabstrip = true;
|
||||
CustomTitlebar.allowedBy("tabs-visible", true);
|
||||
TabsInTitlebar.allowedBy("tabs-visible", true);
|
||||
} else {
|
||||
CustomTitlebar.allowedBy("tabs-visible", !hideTabstrip);
|
||||
TabsInTitlebar.allowedBy("tabs-visible", !hideTabstrip);
|
||||
}
|
||||
|
||||
gNavToolbox.toggleAttribute("tabs-hidden", hideTabstrip);
|
||||
// Should the nav-bar look and function like a titlebar?
|
||||
navbar.classList.toggle(
|
||||
"browser-titlebar",
|
||||
CustomTitlebar.enabled && hideTabstrip
|
||||
TabsInTitlebar.enabled && hideTabstrip
|
||||
);
|
||||
|
||||
document
|
||||
.getElementById("browser")
|
||||
.classList.toggle(
|
||||
"browser-toolbox-background",
|
||||
CustomTitlebar.enabled && nonPopupWithVerticalTabs
|
||||
TabsInTitlebar.enabled && nonPopupWithVerticalTabs
|
||||
);
|
||||
|
||||
if (
|
||||
|
||||
@@ -344,7 +344,7 @@
|
||||
// When the tabbar has an unified appearance with the titlebar
|
||||
// and menubar, a double-click in it should have the same behavior
|
||||
// as double-clicking the titlebar
|
||||
if (CustomTitlebar.enabled && !this.verticalMode) {
|
||||
if (TabsInTitlebar.enabled && !this.verticalMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
* (in X11) or the compositor (in Wayland) does draw the shadow corners
|
||||
* already.
|
||||
*/
|
||||
:root[customtitlebar] {
|
||||
:root[tabsintitlebar] {
|
||||
background-color: transparent;
|
||||
|
||||
&[sizemode="normal"]:not([gtktiledwindow="true"]) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
--toolbox-bgcolor-inactive: -moz-headerbarinactive;
|
||||
--toolbox-textcolor-inactive: -moz-headerbarinactivetext;
|
||||
|
||||
&:where([customtitlebar]) {
|
||||
&:where([tabsintitlebar]) {
|
||||
--toolbox-bgcolor: ActiveCaption;
|
||||
--toolbox-textcolor: CaptionText;
|
||||
--toolbox-bgcolor-inactive: InactiveCaption;
|
||||
@@ -111,7 +111,7 @@
|
||||
--toolbox-textcolor: light-dark(rgb(21, 20, 26), rgb(251, 251, 254));
|
||||
--toolbox-bgcolor-inactive: var(--toolbox-bgcolor);
|
||||
--toolbox-textcolor-inactive: var(--toolbox-textcolor);
|
||||
&:where([customtitlebar]) {
|
||||
&:where([tabsintitlebar]) {
|
||||
--toolbox-bgcolor-inactive: light-dark(rgb(235, 235, 239), rgb(31, 30, 37));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ body {
|
||||
@media (-moz-platform: macos) and (-moz-bool-pref: "browser.theme.native-theme") {
|
||||
/* Don't make the toolbox vibrant when in full-screen. macOS fullscreen has a
|
||||
* native titlebar outside of the window (revealed on hover) anyways. */
|
||||
:root[customtitlebar]:not([lwtheme], [macOSNativeFullscreen]) & {
|
||||
:root[tabsintitlebar]:not([lwtheme], [macOSNativeFullscreen]) & {
|
||||
background-color: transparent;
|
||||
|
||||
/* This is conceptually a background, but putting this on a
|
||||
@@ -233,8 +233,8 @@ body {
|
||||
.browser-titlebar {
|
||||
-moz-window-dragging: drag;
|
||||
|
||||
:root[customtitlebar] &,
|
||||
:root[customtitlebar] & #urlbar:popover-open {
|
||||
:root[tabsintitlebar] &,
|
||||
:root[tabsintitlebar] & #urlbar:popover-open {
|
||||
will-change: opacity;
|
||||
transition: opacity var(--inactive-window-transition);
|
||||
|
||||
@@ -263,14 +263,14 @@ body {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
:root:not([customtitlebar], [inFullscreen]) & {
|
||||
:root:not([chromemargin], [inFullscreen]) & {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.titlebar-spacer {
|
||||
:root[inFullscreen] &,
|
||||
:root:not([customtitlebar]) & {
|
||||
:root:not([tabsintitlebar]) & {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ body {
|
||||
-moz-default-appearance: -moz-window-button-box;
|
||||
position: relative;
|
||||
|
||||
:root:not([customtitlebar], [sizemode=fullscreen]) & {
|
||||
:root:not([tabsintitlebar], [sizemode=fullscreen]) & {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -332,12 +332,12 @@ body {
|
||||
as tall as the tab toolbar such that the window controls don't appear to move up.
|
||||
For MacOS, autohide is never true on the menubar.
|
||||
*/
|
||||
:root[customtitlebar] #navigator-toolbox:not([tabs-hidden]) > & {
|
||||
:root[tabsintitlebar] #navigator-toolbox:not([tabs-hidden]) > & {
|
||||
min-height: var(--tabstrip-min-height);
|
||||
}
|
||||
/* adjust the height of the auto-hiding toolbar menubar when the tabstrip is
|
||||
hidden and we need to match the height of the nav-bar. */
|
||||
:root[customtitlebar] #navigator-toolbox[tabs-hidden] > & {
|
||||
:root[tabsintitlebar] #navigator-toolbox[tabs-hidden] > & {
|
||||
min-height: calc(var(--urlbar-min-height) + 2 * var(--urlbar-padding-block));
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
|
||||
@media (-moz-windows-accent-color-in-titlebar) or (-moz-windows-mica) {
|
||||
:root[customtitlebar] {
|
||||
:root[tabsintitlebar] {
|
||||
@media (-moz-windows-mica) {
|
||||
&:not([lwtheme]) {
|
||||
background-color: transparent;
|
||||
|
||||
@@ -368,7 +368,7 @@ export var TestRunner = {
|
||||
|
||||
this.mochitestScope.info("called " + config.name);
|
||||
// Add a default timeout of 700ms to avoid conflicts when configurations
|
||||
// try to apply at the same time. e.g WindowSize and CustomTitlebar
|
||||
// try to apply at the same time. e.g WindowSize and TabsInTitlebar
|
||||
return Promise.race([applyPromise, timeoutPromise]).then(result => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => resolve(result), 700);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
const PREF_TABS_IN_TITLEBAR = "browser.tabs.inTitlebar";
|
||||
|
||||
export var CustomTitlebar = {
|
||||
export var TabsInTitlebar = {
|
||||
init() {},
|
||||
|
||||
configurations: {
|
||||
@@ -24,12 +24,12 @@ FINAL_TARGET_FILES.resources.configurations += [
|
||||
"configurations/Buttons.sys.mjs",
|
||||
"configurations/ControlCenter.sys.mjs",
|
||||
"configurations/CustomizeMode.sys.mjs",
|
||||
"configurations/CustomTitlebar.sys.mjs",
|
||||
"configurations/DevTools.sys.mjs",
|
||||
"configurations/LightweightThemes.sys.mjs",
|
||||
"configurations/PermissionPrompts.sys.mjs",
|
||||
"configurations/Preferences.sys.mjs",
|
||||
"configurations/Tabs.sys.mjs",
|
||||
"configurations/TabsInTitlebar.sys.mjs",
|
||||
"configurations/Toolbars.sys.mjs",
|
||||
"configurations/UIDensities.sys.mjs",
|
||||
"configurations/WindowSize.sys.mjs",
|
||||
|
||||
@@ -12,7 +12,7 @@ add_task(async function capture() {
|
||||
}
|
||||
|
||||
let sets = [
|
||||
"CustomTitlebar",
|
||||
"TabsInTitlebar",
|
||||
"Tabs",
|
||||
"WindowSize",
|
||||
"Toolbars",
|
||||
|
||||
@@ -1819,6 +1819,50 @@ bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) {
|
||||
nsGkAtoms::ul, nsGkAtoms::xmp);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool nsContentUtils::ParseIntMarginValue(const nsAString& aString,
|
||||
nsIntMargin& result) {
|
||||
nsAutoString marginStr(aString);
|
||||
marginStr.CompressWhitespace(true, true);
|
||||
if (marginStr.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t start = 0, end = 0;
|
||||
for (int count = 0; count < 4; count++) {
|
||||
if ((uint32_t)end >= marginStr.Length()) return false;
|
||||
|
||||
// top, right, bottom, left
|
||||
if (count < 3)
|
||||
end = Substring(marginStr, start).FindChar(',');
|
||||
else
|
||||
end = Substring(marginStr, start).Length();
|
||||
|
||||
if (end <= 0) return false;
|
||||
|
||||
nsresult ec;
|
||||
int32_t val = nsString(Substring(marginStr, start, end)).ToInteger(&ec);
|
||||
if (NS_FAILED(ec)) return false;
|
||||
|
||||
switch (count) {
|
||||
case 0:
|
||||
result.top = val;
|
||||
break;
|
||||
case 1:
|
||||
result.right = val;
|
||||
break;
|
||||
case 2:
|
||||
result.bottom = val;
|
||||
break;
|
||||
case 3:
|
||||
result.left = val;
|
||||
break;
|
||||
}
|
||||
start += end + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) {
|
||||
nsAString::const_iterator iter, end;
|
||||
|
||||
@@ -874,6 +874,17 @@ class nsContentUtils {
|
||||
ParseHTMLIntegerResultFlags* aResult);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Parse a margin string of format 'top, right, bottom, left' into
|
||||
* an nsIntMargin.
|
||||
*
|
||||
* @param aString the string to parse
|
||||
* @param aResult the resulting integer
|
||||
* @return whether the value could be parsed
|
||||
*/
|
||||
static bool ParseIntMarginValue(const nsAString& aString,
|
||||
nsIntMargin& aResult);
|
||||
|
||||
/**
|
||||
* Parse the value of the <font size=""> attribute according to the HTML5
|
||||
* spec as of April 16, 2012.
|
||||
|
||||
@@ -4192,27 +4192,32 @@ nsDOMWindowUtils::PostRestyleSelfEvent(Element* aElement) {
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetCustomTitlebar(bool aCustomTitlebar) {
|
||||
// TODO(emilio): Can't we use nsDOMWindowUtils::GetWidget()?
|
||||
if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow)) {
|
||||
if (nsCOMPtr<nsIBaseWindow> baseWindow =
|
||||
do_QueryInterface(window->GetDocShell())) {
|
||||
nsDOMWindowUtils::SetChromeMargin(int32_t aTop, int32_t aRight, int32_t aBottom,
|
||||
int32_t aLeft) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
|
||||
if (window) {
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow =
|
||||
do_QueryInterface(window->GetDocShell());
|
||||
if (baseWindow) {
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
baseWindow->GetMainWidget(getter_AddRefs(widget));
|
||||
if (widget) {
|
||||
widget->SetCustomTitlebar(aCustomTitlebar);
|
||||
LayoutDeviceIntMargin margins(aTop, aRight, aBottom, aLeft);
|
||||
return widget->SetNonClientMargins(margins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetResizeMargin(int32_t aResizeMargin) {
|
||||
// TODO(emilio): Can't we use nsDOMWindowUtils::GetWidget()?
|
||||
if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow)) {
|
||||
if (nsCOMPtr<nsIBaseWindow> baseWindow =
|
||||
do_QueryInterface(window->GetDocShell())) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
|
||||
if (window) {
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow =
|
||||
do_QueryInterface(window->GetDocShell());
|
||||
if (baseWindow) {
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
baseWindow->GetMainWidget(getter_AddRefs(widget));
|
||||
if (widget) {
|
||||
|
||||
@@ -2053,11 +2053,14 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
readonly attribute boolean refreshDriverHasPendingTick;
|
||||
|
||||
/**
|
||||
* Controls whether we paint to the titlebar of the window.
|
||||
* Works like the customtitlebar xul:window attribute.
|
||||
* Controls the amount of chrome that should be visible on each side of
|
||||
* the window. Works like the chromemargin xul:window attribute.
|
||||
* This should only be used with non-XUL windows.
|
||||
*/
|
||||
void setCustomTitlebar(in boolean aCustomTitlebar);
|
||||
void setChromeMargin(in int32_t aTop,
|
||||
in int32_t aRight,
|
||||
in int32_t aBottom,
|
||||
in int32_t aLeft);
|
||||
|
||||
/**
|
||||
* Controls the amount of space on each edge of the window that can be
|
||||
|
||||
@@ -39,8 +39,8 @@ void ChromeObserver::Init() {
|
||||
for (uint32_t i = 0; i < attributeCount; i++) {
|
||||
BorrowedAttrInfo info = rootElement->GetAttrInfoAt(i);
|
||||
const nsAttrName* name = info.mName;
|
||||
if (name->LocalName() == nsGkAtoms::customtitlebar) {
|
||||
// Some linux windows managers have an issue when the customtitlebar is
|
||||
if (name->LocalName() == nsGkAtoms::chromemargin) {
|
||||
// Some linux windows managers have an issue when the chrome margin is
|
||||
// applied while the browser is loading (bug 1598848). For now, skip
|
||||
// applying this attribute when initializing.
|
||||
continue;
|
||||
@@ -73,6 +73,43 @@ void ChromeObserver::SetDrawsTitle(bool aState) {
|
||||
}
|
||||
}
|
||||
|
||||
class MarginSetter : public Runnable {
|
||||
public:
|
||||
explicit MarginSetter(nsIWidget* aWidget)
|
||||
: mozilla::Runnable("MarginSetter"),
|
||||
mWidget(aWidget),
|
||||
mMargin(-1, -1, -1, -1) {}
|
||||
MarginSetter(nsIWidget* aWidget, const LayoutDeviceIntMargin& aMargin)
|
||||
: mozilla::Runnable("MarginSetter"), mWidget(aWidget), mMargin(aMargin) {}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
// SetNonClientMargins can dispatch native events, hence doing
|
||||
// it off a script runner.
|
||||
mWidget->SetNonClientMargins(mMargin);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
LayoutDeviceIntMargin mMargin;
|
||||
};
|
||||
|
||||
void ChromeObserver::SetChromeMargins(const nsAttrValue* aValue) {
|
||||
if (!aValue) return;
|
||||
|
||||
nsIWidget* mainWidget = GetWindowWidget();
|
||||
if (!mainWidget) return;
|
||||
|
||||
// top, right, bottom, left - see nsAttrValue
|
||||
nsAutoString tmp;
|
||||
aValue->ToString(tmp);
|
||||
nsIntMargin margins;
|
||||
if (nsContentUtils::ParseIntMarginValue(tmp, margins)) {
|
||||
nsContentUtils::AddScriptRunner(new MarginSetter(
|
||||
mainWidget, LayoutDeviceIntMargin::FromUnknownMargin(margins)));
|
||||
}
|
||||
}
|
||||
|
||||
void ChromeObserver::AttributeChanged(dom::Element* aElement,
|
||||
int32_t aNamespaceID, nsAtom* aName,
|
||||
int32_t aModType,
|
||||
@@ -82,25 +119,37 @@ void ChromeObserver::AttributeChanged(dom::Element* aElement,
|
||||
return;
|
||||
}
|
||||
|
||||
if (aModType == dom::MutationEvent_Binding::ADDITION ||
|
||||
aModType == dom::MutationEvent_Binding::REMOVAL) {
|
||||
const bool added = aModType == dom::MutationEvent_Binding::ADDITION;
|
||||
const nsAttrValue* value = aElement->GetParsedAttr(aName, aNamespaceID);
|
||||
if (value) {
|
||||
// Hide chrome if needed
|
||||
if (aName == nsGkAtoms::hidechrome) {
|
||||
HideWindowChrome(added);
|
||||
} else if (aName == nsGkAtoms::customtitlebar) {
|
||||
SetCustomTitlebar(added);
|
||||
} else if (aName == nsGkAtoms::drawtitle) {
|
||||
SetDrawsTitle(added);
|
||||
HideWindowChrome(value->Equals(u"true"_ns, eCaseMatters));
|
||||
} else if (aName == nsGkAtoms::chromemargin) {
|
||||
SetChromeMargins(value);
|
||||
}
|
||||
// title and drawintitlebar are settable on
|
||||
// any root node (windows, dialogs, etc)
|
||||
else if (aName == nsGkAtoms::title) {
|
||||
mDocument->NotifyPossibleTitleChange(false);
|
||||
} else if (aName == nsGkAtoms::drawtitle) {
|
||||
SetDrawsTitle(value->Equals(u"true"_ns, eCaseMatters));
|
||||
} else if (aName == nsGkAtoms::localedir) {
|
||||
// if the localedir changed on the root element, reset the document
|
||||
// direction
|
||||
mDocument->ResetDocumentDirection();
|
||||
}
|
||||
} else {
|
||||
if (aName == nsGkAtoms::hidechrome) {
|
||||
HideWindowChrome(false);
|
||||
} else if (aName == nsGkAtoms::chromemargin) {
|
||||
ResetChromeMargins();
|
||||
} else if (aName == nsGkAtoms::localedir) {
|
||||
// if the localedir changed on the root element, reset the document
|
||||
// direction
|
||||
mDocument->ResetDocumentDirection();
|
||||
} else if (aName == nsGkAtoms::drawtitle) {
|
||||
SetDrawsTitle(false);
|
||||
}
|
||||
}
|
||||
if (aName == nsGkAtoms::localedir) {
|
||||
// if the localedir changed on the root element, reset the document
|
||||
// direction
|
||||
mDocument->ResetDocumentDirection();
|
||||
}
|
||||
if (aName == nsGkAtoms::title &&
|
||||
aModType != dom::MutationEvent_Binding::REMOVAL) {
|
||||
mDocument->NotifyPossibleTitleChange(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,14 +157,11 @@ void ChromeObserver::NodeWillBeDestroyed(nsINode* aNode) {
|
||||
mDocument = nullptr;
|
||||
}
|
||||
|
||||
void ChromeObserver::SetCustomTitlebar(bool aCustomTitlebar) {
|
||||
if (nsIWidget* mainWidget = GetWindowWidget()) {
|
||||
// SetCustomTitlebar can dispatch native events, hence doing it off a
|
||||
// script runner
|
||||
nsContentUtils::AddScriptRunner(NewRunnableMethod<bool>(
|
||||
"SetCustomTitlebar", mainWidget, &nsIWidget::SetCustomTitlebar,
|
||||
aCustomTitlebar));
|
||||
}
|
||||
void ChromeObserver::ResetChromeMargins() {
|
||||
nsIWidget* mainWidget = GetWindowWidget();
|
||||
if (!mainWidget) return;
|
||||
// See nsIWidget
|
||||
nsContentUtils::AddScriptRunner(new MarginSetter(mainWidget));
|
||||
}
|
||||
|
||||
nsresult ChromeObserver::HideWindowChrome(bool aShouldHide) {
|
||||
|
||||
@@ -27,8 +27,11 @@ class ChromeObserver final : public nsStubMutationObserver {
|
||||
protected:
|
||||
nsIWidget* GetWindowWidget();
|
||||
void SetDrawsTitle(bool aState);
|
||||
void SetChromeMargins(const nsAttrValue* aValue);
|
||||
nsresult HideWindowChrome(bool aShouldHide);
|
||||
void SetCustomTitlebar(bool);
|
||||
|
||||
private:
|
||||
void ResetChromeMargins();
|
||||
~ChromeObserver();
|
||||
// A weak pointer cleared when the element will be destroyed.
|
||||
Document* MOZ_NON_OWNING_REF mDocument;
|
||||
|
||||
@@ -131,7 +131,7 @@ static int sVerticalResizeMargin = 0;
|
||||
|
||||
// See nsWindow::NonClientSizeMargin()
|
||||
static Margin NonClientSizeMargin() {
|
||||
return Margin{sCaptionHeight + sVerticalResizeMargin - sNonClientOffset.top,
|
||||
return Margin{sCaptionHeight - sNonClientOffset.top,
|
||||
sHorizontalResizeMargin - sNonClientOffset.right,
|
||||
sVerticalResizeMargin - sNonClientOffset.bottom,
|
||||
sHorizontalResizeMargin - sNonClientOffset.left};
|
||||
@@ -1365,7 +1365,7 @@ ThemeColors GetTheme(ThemeMode themeId) {
|
||||
theme.tabColor = 0xf9f9fb;
|
||||
theme.toolbarForegroundColor = 0xdddde1;
|
||||
theme.tabOutlineColor = 0xdddde1;
|
||||
// found in browser-aero.css ":root[customtitlebar]:not(:-moz-lwtheme)"
|
||||
// found in browser-aero.css ":root[tabsintitlebar]:not(:-moz-lwtheme)"
|
||||
// (set to "hsl(235,33%,19%)")
|
||||
theme.titlebarColor = 0xf0f0f4;
|
||||
// --chrome-content-separator-color in browser.css
|
||||
@@ -1992,15 +1992,25 @@ static Result<Ok, PreXULSkeletonUIError> CreateAndStorePreXULSkeletonUIImpl(
|
||||
sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, sDpi);
|
||||
sVerticalResizeMargin = sGetSystemMetricsForDpi(SM_CYFRAME, sDpi) +
|
||||
sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, sDpi);
|
||||
sCaptionHeight = sGetSystemMetricsForDpi(SM_CYCAPTION, sDpi);
|
||||
sCaptionHeight =
|
||||
sVerticalResizeMargin + sGetSystemMetricsForDpi(SM_CYCAPTION, sDpi);
|
||||
|
||||
// These match the margins set in browser-tabsintitlebar.js with default prefs
|
||||
// on Windows. We don't use the skeleton ui if tabsInTitlebar is disabled, see
|
||||
// bug 1673092.
|
||||
const Margin nonClientMargin{0, 2, 2, 2};
|
||||
|
||||
// These match the offsets that we get with default prefs. We don't use the
|
||||
// skeleton ui if tabsInTitlebar is disabled, see bug 1673092.
|
||||
if (sMaximized) {
|
||||
sNonClientOffset = Margin{sCaptionHeight, 0, 0, 0};
|
||||
sNonClientOffset.top = sCaptionHeight - sVerticalResizeMargin;
|
||||
} else {
|
||||
// See nsWindow::NormalWindowNonClientOffset()
|
||||
sNonClientOffset = Margin{sCaptionHeight + sVerticalResizeMargin, 0, 0, 0};
|
||||
sNonClientOffset.top = sCaptionHeight;
|
||||
sNonClientOffset.bottom =
|
||||
std::min(sVerticalResizeMargin, nonClientMargin.bottom);
|
||||
sNonClientOffset.left =
|
||||
std::min(sHorizontalResizeMargin, nonClientMargin.left);
|
||||
sNonClientOffset.right =
|
||||
std::min(sHorizontalResizeMargin, nonClientMargin.right);
|
||||
}
|
||||
|
||||
if (sMaximized) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
windowtype="Toolkit:PictureInPicture"
|
||||
macnativefullscreen="true"
|
||||
customtitlebar="true"
|
||||
chromemargin="0,0,0,0"
|
||||
scrolling="false"
|
||||
>
|
||||
<head>
|
||||
|
||||
@@ -197,9 +197,8 @@ add_task(async function test_found_resize() {
|
||||
info(`values: ${JSON.stringify(values)}`);
|
||||
info(`resizedValues: ${JSON.stringify(resizedValues)}`);
|
||||
isfuzzy(resizedValues[0], values[0], 2, "first value");
|
||||
const kSlop = 50;
|
||||
Assert.greaterOrEqual(resizedValues[1] - kSlop, values[1], "second value");
|
||||
Assert.greaterOrEqual(resizedValues[2] - kSlop, values[2], "third value");
|
||||
Assert.greater(resizedValues[1] - 50, values[1], "second value");
|
||||
Assert.greater(resizedValues[2] - 50, values[2], "third value");
|
||||
|
||||
endFn();
|
||||
|
||||
|
||||
@@ -143,6 +143,10 @@ skip-if = [
|
||||
|
||||
["test_button.xhtml"]
|
||||
|
||||
["test_chromemargin.xhtml"]
|
||||
support-files = "window_chromemargin.xhtml"
|
||||
skip-if = ["apple_catalina"]
|
||||
|
||||
["test_closemenu_attribute.xhtml"]
|
||||
|
||||
["test_contextmenu_list.xhtml"]
|
||||
|
||||
35
toolkit/content/tests/chrome/test_chromemargin.xhtml
Normal file
35
toolkit/content/tests/chrome/test_chromemargin.xhtml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
|
||||
<window title="Custom chrome margin tests"
|
||||
onload="setTimeout(runTest, 0);"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<script>
|
||||
|
||||
// Tests parsing of the chrome margin attrib on a window.
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
function runTest()
|
||||
{
|
||||
window.openDialog("window_chromemargin.xhtml", "_blank", "chrome,width=600,height=600,noopener", window);
|
||||
}
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display">
|
||||
</p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
</window>
|
||||
73
toolkit/content/tests/chrome/window_chromemargin.xhtml
Normal file
73
toolkit/content/tests/chrome/window_chromemargin.xhtml
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
|
||||
<window id="window" title="Subframe Origin Tests"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
|
||||
chrome margins rock!
|
||||
<script>
|
||||
|
||||
// Tests parsing of the chrome margin attrib on a window.
|
||||
|
||||
function ok(condition, message) {
|
||||
window.arguments[0].SimpleTest.ok(condition, message);
|
||||
}
|
||||
|
||||
function is(a, b, message) {
|
||||
window.arguments[0].SimpleTest.is(a, b, message);
|
||||
}
|
||||
|
||||
function doSingleTest(param)
|
||||
{
|
||||
var exception = null;
|
||||
try {
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
document.documentElement.setAttribute("chromemargin", param);
|
||||
is(document.
|
||||
documentElement.
|
||||
getAttribute("chromemargin"), param, "couldn't set/get chromemargin?");
|
||||
} catch (ex) {
|
||||
exception = ex;
|
||||
}
|
||||
ok(!exception, "failed for param:'" + param + "'");
|
||||
return true;
|
||||
}
|
||||
|
||||
function runTests()
|
||||
{
|
||||
var doc = document.documentElement;
|
||||
|
||||
// make sure we can set and get
|
||||
doc.setAttribute("chromemargin", "0,0,0,0");
|
||||
ok(doc.getAttribute("chromemargin") == "0,0,0,0", "couldn't set/get chromemargin?");
|
||||
doc.setAttribute("chromemargin", "-1,-1,-1,-1");
|
||||
ok(doc.getAttribute("chromemargin") == "-1,-1,-1,-1", "couldn't set/get chromemargin?");
|
||||
|
||||
// test remove
|
||||
doc.removeAttribute("chromemargin");
|
||||
is(doc.getAttribute("chromemargin"), null, "couldn't remove chromemargin?");
|
||||
|
||||
// we already test these really well in a c++ test in widget
|
||||
doSingleTest("1,2,3,4");
|
||||
doSingleTest("-2,-2,-2,-2");
|
||||
doSingleTest("1,1,1,1");
|
||||
doSingleTest("");
|
||||
doSingleTest("12123123");
|
||||
doSingleTest("0,-1,-1,-1");
|
||||
doSingleTest("-1,0,-1,-1");
|
||||
doSingleTest("-1,-1,0,-1");
|
||||
doSingleTest("-1,-1,-1,0");
|
||||
doSingleTest("1234567890,1234567890,1234567890,1234567890");
|
||||
doSingleTest("-1,-1,-1,-1");
|
||||
|
||||
window.arguments[0].SimpleTest.finish();
|
||||
window.close();
|
||||
}
|
||||
|
||||
window.arguments[0].SimpleTest.waitForFocus(runTests, window);
|
||||
|
||||
</script>
|
||||
</window>
|
||||
@@ -5,7 +5,7 @@
|
||||
height="300"
|
||||
width="300"
|
||||
sizemode="normal"
|
||||
customtitlebar="true"
|
||||
chromemargin="0,2,2,2"
|
||||
id="window"
|
||||
persist="height width sizemode">
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
@@ -283,7 +283,8 @@ class nsCocoaWindow final : public nsBaseWidget {
|
||||
void SetSupportsNativeFullscreen(bool aShow) override;
|
||||
void SetWindowAnimationType(WindowAnimationType aType) override;
|
||||
void SetDrawsTitle(bool aDrawTitle) override;
|
||||
void SetCustomTitlebar(bool) override;
|
||||
nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override;
|
||||
void SetDrawsInTitlebar(bool aState);
|
||||
void UpdateThemeGeometries(
|
||||
const nsTArray<ThemeGeometry>& aThemeGeometries) override;
|
||||
nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
|
||||
|
||||
@@ -2464,7 +2464,18 @@ void nsCocoaWindow::SetDrawsTitle(bool aDrawTitle) {
|
||||
NS_OBJC_END_TRY_IGNORE_BLOCK;
|
||||
}
|
||||
|
||||
void nsCocoaWindow::SetCustomTitlebar(bool aState) {
|
||||
nsresult nsCocoaWindow::SetNonClientMargins(
|
||||
const LayoutDeviceIntMargin& margins) {
|
||||
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
|
||||
|
||||
SetDrawsInTitlebar(margins.top == 0);
|
||||
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
void nsCocoaWindow::SetDrawsInTitlebar(bool aState) {
|
||||
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
|
||||
|
||||
if (mWindow) {
|
||||
|
||||
@@ -8774,6 +8774,11 @@ void nsWindow::SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) {
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsWindow::SetNonClientMargins(const LayoutDeviceIntMargin& aMargins) {
|
||||
SetDrawsInTitlebar(aMargins.top == 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsWindow::IsAlwaysUndecoratedWindow() const {
|
||||
if (mIsPIPWindow || gKioskMode) {
|
||||
return true;
|
||||
@@ -8788,8 +8793,8 @@ bool nsWindow::IsAlwaysUndecoratedWindow() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void nsWindow::SetCustomTitlebar(bool aState) {
|
||||
LOG("nsWindow::SetCustomTitlebar() State %d mGtkWindowDecoration %d\n",
|
||||
void nsWindow::SetDrawsInTitlebar(bool aState) {
|
||||
LOG("nsWindow::SetDrawsInTitlebar() State %d mGtkWindowDecoration %d\n",
|
||||
aState, (int)mGtkWindowDecoration);
|
||||
|
||||
if (mGtkWindowDecoration == GTK_DECORATION_NONE ||
|
||||
|
||||
@@ -373,7 +373,8 @@ class nsWindow final : public nsBaseWidget {
|
||||
void GetCompositorWidgetInitData(
|
||||
mozilla::widget::CompositorWidgetInitData* aInitData) override;
|
||||
|
||||
void SetCustomTitlebar(bool) override;
|
||||
nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override;
|
||||
void SetDrawsInTitlebar(bool aState);
|
||||
mozilla::LayoutDeviceIntCoord GetTitlebarRadius();
|
||||
void UpdateWindowDraggingRegion(
|
||||
const LayoutDeviceIntRegion& aRegion) override;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace mozilla {
|
||||
enum class NativeKeyBindingsType : uint8_t;
|
||||
namespace widget {
|
||||
|
||||
class HeadlessWidget final : public nsBaseWidget {
|
||||
class HeadlessWidget : public nsBaseWidget {
|
||||
public:
|
||||
HeadlessWidget();
|
||||
|
||||
@@ -77,6 +77,10 @@ class HeadlessWidget final : public nsBaseWidget {
|
||||
// Headless widgets have no title, so just ignore it.
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult SetNonClientMargins(const LayoutDeviceIntMargin& margins) override {
|
||||
// Headless widgets have no chrome margins, so just ignore the call.
|
||||
return NS_OK;
|
||||
}
|
||||
LayoutDeviceIntPoint WidgetToScreenOffset() override;
|
||||
void SetInputContext(const InputContext& aContext,
|
||||
const InputContextAction& aAction) override {
|
||||
|
||||
@@ -1747,6 +1747,12 @@ LayoutDeviceIntPoint nsBaseWidget::GetClientOffset() {
|
||||
return LayoutDeviceIntPoint(0, 0);
|
||||
}
|
||||
|
||||
nsresult nsBaseWidget::SetNonClientMargins(const LayoutDeviceIntMargin&) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void nsBaseWidget::SetResizeMargin(LayoutDeviceIntCoord aResizeMargin) {}
|
||||
|
||||
uint32_t nsBaseWidget::GetMaxTouchPoints() const { return 0; }
|
||||
|
||||
bool nsBaseWidget::HasPendingInputEvent() { return false; }
|
||||
|
||||
@@ -252,9 +252,11 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
|
||||
LayoutDeviceIntRect GetClientBounds() override;
|
||||
LayoutDeviceIntRect GetScreenBounds() override;
|
||||
[[nodiscard]] nsresult GetRestoredBounds(LayoutDeviceIntRect& aRect) override;
|
||||
nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override;
|
||||
LayoutDeviceIntPoint GetClientOffset() override;
|
||||
void EnableDragDrop(bool aEnable) override {};
|
||||
nsresult AsyncEnableDragDrop(bool aEnable) override;
|
||||
void SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) override;
|
||||
[[nodiscard]] nsresult GetAttention(int32_t aCycleCount) override {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -870,15 +870,24 @@ class nsIWidget : public nsISupports {
|
||||
*/
|
||||
virtual LayoutDeviceIntRect GetClientBounds() = 0;
|
||||
|
||||
/** Whether to extend the client area into the titlebar. */
|
||||
virtual void SetCustomTitlebar(bool) {}
|
||||
/**
|
||||
* Sets the non-client area dimensions of the window. Pass -1 to restore
|
||||
* the system default frame size for that border. Pass zero to remove
|
||||
* a border, or pass a specific value adjust a border. Units are in
|
||||
* pixels. (DPI dependent)
|
||||
*
|
||||
* Platform notes:
|
||||
* Windows: shrinking top non-client height will remove application
|
||||
* icon and window title text. Glass desktops will refuse to set
|
||||
* dimensions between zero and size < system default.
|
||||
*/
|
||||
virtual nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) = 0;
|
||||
|
||||
/**
|
||||
* Sets the region around the edges of the window that can be dragged to
|
||||
* resize the window. All four sides of the window will get the same margin.
|
||||
*/
|
||||
virtual void SetResizeMargin(mozilla::LayoutDeviceIntCoord) {}
|
||||
|
||||
virtual void SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) = 0;
|
||||
/**
|
||||
* Get the client offset from the window origin.
|
||||
*
|
||||
|
||||
130
widget/tests/TestChromeMargin.cpp
Normal file
130
widget/tests/TestChromeMargin.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* This tests the margin parsing functionality in nsAttrValue.cpp, which
|
||||
* is accessible via nsContentUtils, and is used in setting chromemargins
|
||||
* to widget windows. It's located here due to linking issues in the
|
||||
* content directory.
|
||||
*/
|
||||
|
||||
/* This test no longer compiles now that we've removed nsIContentUtils (bug
|
||||
* 647273). We need to be internal code in order to include nsContentUtils.h,
|
||||
* but defining MOZILLA_INTERNAL_API is not enough to make us internal.
|
||||
*/
|
||||
|
||||
#include "TestHarness.h"
|
||||
|
||||
#ifndef MOZILLA_INTERNAL_API
|
||||
# error This test needs MOZILLA_INTERNAL_API (see bug 652123)
|
||||
#endif
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsString.h"
|
||||
|
||||
struct DATA {
|
||||
bool shouldfail;
|
||||
const char* margins;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
int left;
|
||||
};
|
||||
|
||||
const bool SHOULD_FAIL = true;
|
||||
const int SHOULD_PASS = false;
|
||||
|
||||
const DATA Data[] = {
|
||||
{SHOULD_FAIL, "", 1, 2, 3, 4},
|
||||
{SHOULD_FAIL, "1,0,0,0", 1, 2, 3, 4},
|
||||
{SHOULD_FAIL, "1,2,0,0", 1, 2, 3, 4},
|
||||
{SHOULD_FAIL, "1,2,3,0", 1, 2, 3, 4},
|
||||
{SHOULD_FAIL, "4,3,2,1", 1, 2, 3, 4},
|
||||
{SHOULD_FAIL, "azsasdasd", 0, 0, 0, 0},
|
||||
{SHOULD_FAIL, ",azsasdasd", 0, 0, 0, 0},
|
||||
{SHOULD_FAIL, " ", 1, 2, 3, 4},
|
||||
{SHOULD_FAIL,
|
||||
"azsdfsdfsdfsdfsdfsasdasd,asdasdasdasdasdasd,asdadasdasd,asdasdasdasd", 0,
|
||||
0, 0, 0},
|
||||
{SHOULD_FAIL, "as,as,as,as", 0, 0, 0, 0},
|
||||
{SHOULD_FAIL, "0,0,0", 0, 0, 0, 0},
|
||||
{SHOULD_FAIL, "0,0", 0, 0, 0, 0},
|
||||
{SHOULD_FAIL, "4.6,1,1,1", 0, 0, 0, 0},
|
||||
{SHOULD_FAIL, ",,,,", 0, 0, 0, 0},
|
||||
{SHOULD_FAIL, "1, , , ,", 0, 0, 0, 0},
|
||||
{SHOULD_FAIL, "1, , ,", 0, 0, 0, 0},
|
||||
{SHOULD_FAIL, "@!@%^&^*()", 1, 2, 3, 4},
|
||||
{SHOULD_PASS, "4,3,2,1", 4, 3, 2, 1},
|
||||
{SHOULD_PASS, "-4,-3,-2,-1", -4, -3, -2, -1},
|
||||
{SHOULD_PASS, "10000,3,2,1", 10000, 3, 2, 1},
|
||||
{SHOULD_PASS, "4 , 3 , 2 , 1", 4, 3, 2, 1},
|
||||
{SHOULD_PASS, "4, 3 ,2,1", 4, 3, 2, 1},
|
||||
{SHOULD_FAIL, "4,3,2,10000000000000 --", 4, 3, 2, 10000000000000},
|
||||
{SHOULD_PASS, "4,3,2,1000", 4, 3, 2, 1000},
|
||||
{SHOULD_PASS, "2147483647,3,2,1000", 2147483647, 3, 2, 1000},
|
||||
{SHOULD_PASS, "2147483647,2147483647,2147483647,2147483647", 2147483647,
|
||||
2147483647, 2147483647, 2147483647},
|
||||
{SHOULD_PASS, "-2147483647,3,2,1000", -2147483647, 3, 2, 1000},
|
||||
{SHOULD_FAIL, "2147483648,3,2,1000", 1, 3, 2, 1000},
|
||||
{0, nullptr, 0, 0, 0, 0}};
|
||||
|
||||
void DoAttrValueTest() {
|
||||
int idx = -1;
|
||||
bool didFail = false;
|
||||
while (Data[++idx].margins) {
|
||||
nsAutoString str;
|
||||
str.AssignLiteral(Data[idx].margins);
|
||||
nsIntMargin values(99, 99, 99, 99);
|
||||
bool result = nsContentUtils::ParseIntMarginValue(str, values);
|
||||
|
||||
// if the parse fails
|
||||
if (!result) {
|
||||
if (Data[idx].shouldfail) continue;
|
||||
fail(Data[idx].margins);
|
||||
didFail = true;
|
||||
printf("*1\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Data[idx].shouldfail) {
|
||||
if (Data[idx].top == values.top && Data[idx].right == values.right &&
|
||||
Data[idx].bottom == values.bottom && Data[idx].left == values.left) {
|
||||
// not likely
|
||||
fail(Data[idx].margins);
|
||||
didFail = true;
|
||||
printf("*2\n");
|
||||
continue;
|
||||
}
|
||||
// good failure, parse failed and that's what we expected.
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
printf("%d==%d %d==%d %d==%d %d==%d\n",
|
||||
Data[idx].top, values.top,
|
||||
Data[idx].right, values.right,
|
||||
Data[idx].bottom, values.bottom,
|
||||
Data[idx].left, values.left);
|
||||
#endif
|
||||
if (Data[idx].top == values.top && Data[idx].right == values.right &&
|
||||
Data[idx].bottom == values.bottom && Data[idx].left == values.left) {
|
||||
// good parse results
|
||||
continue;
|
||||
} else {
|
||||
fail(Data[idx].margins);
|
||||
didFail = true;
|
||||
printf("*3\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!didFail) passed("nsAttrValue margin parsing tests passed.");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
ScopedXPCOM xpcom("");
|
||||
if (xpcom.failed()) return 1;
|
||||
DoAttrValueTest();
|
||||
return 0;
|
||||
}
|
||||
@@ -16,6 +16,9 @@ with Files("unit/*macwebapputils*"):
|
||||
with Files("unit/*taskbar_jumplistitems*"):
|
||||
BUG_COMPONENT = ("Core", "Widget: Win32")
|
||||
|
||||
with Files("TestChromeMargin.cpp"):
|
||||
BUG_COMPONENT = ("Core", "Widget: Win32")
|
||||
|
||||
with Files("*413277*"):
|
||||
BUG_COMPONENT = ("Core", "Widget: Cocoa")
|
||||
|
||||
@@ -114,3 +117,9 @@ XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell.toml"]
|
||||
MOCHITEST_MANIFESTS += ["mochitest.toml"]
|
||||
MOCHITEST_CHROME_MANIFESTS += ["chrome.toml"]
|
||||
BROWSER_CHROME_MANIFESTS += ["browser/browser.toml"]
|
||||
|
||||
# if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
#
|
||||
# Test disabled because it requires the internal API. Re-enabling this test
|
||||
# is bug 652123.
|
||||
# CPP_UNIT_TESTS += ['TestChromeMargin']
|
||||
|
||||
@@ -43,13 +43,13 @@ async function start() {
|
||||
await waitForEvent(window, "focus");
|
||||
var oldOuterWidth = window.outerWidth, oldOuterHeight = window.outerHeight;
|
||||
var oldInnerWidth = window.innerWidth, oldInnerHeight = window.innerHeight;
|
||||
document.documentElement.setAttribute("customtitlebar", "true");
|
||||
document.documentElement.setAttribute("chromemargin", "0,0,0,0");
|
||||
|
||||
await executeSoon();
|
||||
is(window.outerWidth, oldOuterWidth, "customtitlebar shouldn't change the window's outerWidth");
|
||||
is(window.outerHeight, oldOuterHeight, "customtitlebar shouldn't change the window's outerHeight");
|
||||
is(window.innerWidth, oldOuterWidth, "if customtitlebar is set, innerWidth and outerWidth should be the same");
|
||||
is(window.innerHeight, oldOuterHeight, "if customtitlebar is set, innerHeight and outerHeight should be the same");
|
||||
is(window.outerWidth, oldOuterWidth, "chromemargin shouldn't change the window's outerWidth");
|
||||
is(window.outerHeight, oldOuterHeight, "chromemargin shouldn't change the window's outerHeight");
|
||||
is(window.innerWidth, oldOuterWidth, "if chromemargin is set, innerWidth and outerWidth should be the same");
|
||||
is(window.innerHeight, oldOuterHeight, "if chromemargin is set, innerHeight and outerHeight should be the same");
|
||||
|
||||
// Wait for going full screen and back.
|
||||
let sizemodeChange = waitForEvent(window, "sizemodechange");
|
||||
@@ -62,13 +62,13 @@ async function start() {
|
||||
is(window.outerHeight, oldOuterHeight, "wrong outerHeight after fullscreen mode");
|
||||
is(window.innerWidth, oldOuterWidth, "wrong innerWidth after fullscreen mode");
|
||||
is(window.innerHeight, oldOuterHeight, "wrong innerHeight after fullscreen mode");
|
||||
document.documentElement.removeAttribute("customtitlebar");
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
|
||||
await executeSoon();
|
||||
is(window.outerWidth, oldOuterWidth, "wrong outerWidth after removing customtitlebar");
|
||||
is(window.outerHeight, oldOuterHeight, "wrong outerHeight after removing customtitlebar");
|
||||
is(window.innerWidth, oldInnerWidth, "wrong innerWidth after removing customtitlebar");
|
||||
is(window.innerHeight, oldInnerHeight, "wrong innerHeight after removing customtitlebar");
|
||||
is(window.outerWidth, oldOuterWidth, "wrong outerWidth after removing chromemargin");
|
||||
is(window.outerHeight, oldOuterHeight, "wrong outerHeight after removing chromemargin");
|
||||
is(window.innerWidth, oldInnerWidth, "wrong innerWidth after removing chromemargin");
|
||||
is(window.innerHeight, oldInnerHeight, "wrong innerHeight after removing chromemargin");
|
||||
window.arguments[0].SimpleTest.finish();
|
||||
window.close();
|
||||
}
|
||||
|
||||
@@ -940,8 +940,10 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect,
|
||||
DesktopIntRect::Round(LayoutDeviceRect(GetBounds()) / scale)
|
||||
.ToUnknownRect());
|
||||
|
||||
// Skeleton ui is disabled when custom titlebar is off, see bug 1673092.
|
||||
SetCustomTitlebar(true);
|
||||
// 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.
|
||||
SetNonClientMargins(LayoutDeviceIntMargin(0, 2, 2, 2));
|
||||
// The skeleton UI already painted over the NC area, so there's no need
|
||||
// to do that again; the effective non-client margins haven't changed.
|
||||
mNeedsNCAreaClear = false;
|
||||
@@ -2335,7 +2337,7 @@ void nsWindow::SetFocus(Raise aRaise, mozilla::dom::CallerType aCallerType) {
|
||||
* SECTION: Bounds
|
||||
*
|
||||
* GetBounds, GetClientBounds, GetScreenBounds,
|
||||
* GetRestoredBounds, GetClientOffset, SetCustomTitlebar
|
||||
* GetRestoredBounds, GetClientOffset, SetNonClientMargins
|
||||
*
|
||||
* Bound calculations.
|
||||
*
|
||||
@@ -2521,17 +2523,49 @@ void nsWindow::SetColorScheme(const Maybe<ColorScheme>& aScheme) {
|
||||
}
|
||||
|
||||
LayoutDeviceIntMargin nsWindow::NormalWindowNonClientOffset() const {
|
||||
MOZ_ASSERT(mCustomNonClient);
|
||||
LayoutDeviceIntMargin nonClientOffset;
|
||||
|
||||
// We're dealing with a "normal" window (not maximized, minimized, or
|
||||
// fullscreen), so set `mNonClientOffset` accordingly.
|
||||
// fullscreen), so process `mNonClientMargins` and set `mNonClientOffset`
|
||||
// accordingly.
|
||||
//
|
||||
// Setting `mNonClientOffset` to 0 has the effect of leaving the default
|
||||
// frame intact. Setting it to a value greater than 0 reduces the frame
|
||||
// size by that amount.
|
||||
//
|
||||
// When using custom titlebar, we hide the titlebar and leave the default
|
||||
// frame on the other sides.
|
||||
return LayoutDeviceIntMargin(mCaptionHeight + mVertResizeMargin, 0, 0, 0);
|
||||
|
||||
if (mNonClientMargins.top > 0) {
|
||||
nonClientOffset.top = std::min(mCaptionHeight, mNonClientMargins.top);
|
||||
} else if (mNonClientMargins.top == 0) {
|
||||
nonClientOffset.top = mCaptionHeight;
|
||||
} else {
|
||||
nonClientOffset.top = 0;
|
||||
}
|
||||
|
||||
if (mNonClientMargins.bottom > 0) {
|
||||
nonClientOffset.bottom =
|
||||
std::min(mVertResizeMargin, mNonClientMargins.bottom);
|
||||
} else if (mNonClientMargins.bottom == 0) {
|
||||
nonClientOffset.bottom = mVertResizeMargin;
|
||||
} else {
|
||||
nonClientOffset.bottom = 0;
|
||||
}
|
||||
|
||||
if (mNonClientMargins.left > 0) {
|
||||
nonClientOffset.left = std::min(mHorResizeMargin, mNonClientMargins.left);
|
||||
} else if (mNonClientMargins.left == 0) {
|
||||
nonClientOffset.left = mHorResizeMargin;
|
||||
} else {
|
||||
nonClientOffset.left = 0;
|
||||
}
|
||||
|
||||
if (mNonClientMargins.right > 0) {
|
||||
nonClientOffset.right = std::min(mHorResizeMargin, mNonClientMargins.right);
|
||||
} else if (mNonClientMargins.right == 0) {
|
||||
nonClientOffset.right = mHorResizeMargin;
|
||||
} else {
|
||||
nonClientOffset.right = 0;
|
||||
}
|
||||
return nonClientOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2540,14 +2574,24 @@ LayoutDeviceIntMargin nsWindow::NormalWindowNonClientOffset() const {
|
||||
* margins and fires off a frame changed event, which triggers an nc calc
|
||||
* size windows event, kicking the changes in.
|
||||
*
|
||||
* The offsets calculated here are based on the value of `mNonClientMargins`
|
||||
* which is specified in the "chromemargins" attribute of the window. For
|
||||
* each margin, the value specified has the following meaning:
|
||||
* -1 - leave the default frame in place
|
||||
* 0 - remove the frame
|
||||
* >0 - frame size equals min(0, (default frame size - margin value))
|
||||
*
|
||||
* This function calculates and populates `mNonClientOffset`.
|
||||
* In our processing of `WM_NCCALCSIZE`, the frame size will be calculated
|
||||
* as (default frame size - offset). For example, if the left frame should
|
||||
* be 1 pixel narrower than the default frame size, `mNonClientOffset.left`
|
||||
* will equal 1.
|
||||
*
|
||||
* For maximized, fullscreen, and minimized windows special processing takes
|
||||
* place.
|
||||
* For maximized, fullscreen, and minimized windows, the values stored in
|
||||
* `mNonClientMargins` are ignored, and special processing takes place.
|
||||
*
|
||||
* For non-glass windows, we only allow frames to be their default size
|
||||
* or removed entirely.
|
||||
*/
|
||||
bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
|
||||
if (!mCustomNonClient) {
|
||||
@@ -2556,44 +2600,56 @@ bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
|
||||
|
||||
const nsSizeMode sizeMode = mFrameState->GetSizeMode();
|
||||
|
||||
const bool hasCaption =
|
||||
bool hasCaption =
|
||||
bool(mBorderStyle & (BorderStyle::All | BorderStyle::Title |
|
||||
BorderStyle::Menu | BorderStyle::Default));
|
||||
|
||||
float dpi = GetDPI();
|
||||
|
||||
// mHorResizeMargin is the size of the default NC areas on the
|
||||
// left and right sides of our window. It is calculated as
|
||||
// the sum of:
|
||||
// SM_CXFRAME - The thickness of the sizing border
|
||||
// mCaptionHeight is the default size of the NC area at
|
||||
// the top of the window. If the window has a caption,
|
||||
// the size is calculated as the sum of:
|
||||
// SM_CYFRAME - The thickness of the sizing border
|
||||
// around a resizable window
|
||||
// SM_CXPADDEDBORDER - The amount of border padding
|
||||
// for captioned windows
|
||||
// SM_CYCAPTION - The height of the caption area
|
||||
//
|
||||
// If the window does not have a caption, mHorResizeMargin will be equal to
|
||||
// `WinUtils::GetSystemMetricsForDpi(SM_CXFRAME, dpi)`
|
||||
mHorResizeMargin =
|
||||
WinUtils::GetSystemMetricsForDpi(SM_CXFRAME, dpi) +
|
||||
(hasCaption ? WinUtils::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)
|
||||
: 0);
|
||||
|
||||
// mVertResizeMargin is the size of the default NC area at the
|
||||
// bottom of the window. It is calculated as the sum of:
|
||||
// SM_CYFRAME - The thickness of the sizing border
|
||||
// SM_CXPADDEDBORDER - The amount of border padding
|
||||
// for captioned windows.
|
||||
//
|
||||
// If the window does not have a caption, mVertResizeMargin will be equal to
|
||||
// If the window does not have a caption, mCaptionHeight will be equal to
|
||||
// `WinUtils::GetSystemMetricsForDpi(SM_CYFRAME, dpi)`
|
||||
mVertResizeMargin =
|
||||
WinUtils::GetSystemMetricsForDpi(SM_CYFRAME, dpi) +
|
||||
(hasCaption ? WinUtils::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)
|
||||
: 0);
|
||||
|
||||
// mCaptionHeight is the default size of the caption. You need to include
|
||||
// mVertResizeMargin if you want the whole size of the default NC area at the
|
||||
// top of the window.
|
||||
mCaptionHeight =
|
||||
hasCaption ? WinUtils::GetSystemMetricsForDpi(SM_CYCAPTION, dpi) : 0;
|
||||
WinUtils::GetSystemMetricsForDpi(SM_CYFRAME, dpi) +
|
||||
(hasCaption ? WinUtils::GetSystemMetricsForDpi(SM_CYCAPTION, dpi) +
|
||||
WinUtils::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)
|
||||
: 0);
|
||||
if (!mUseResizeMarginOverrides) {
|
||||
// mHorResizeMargin is the size of the default NC areas on the
|
||||
// left and right sides of our window. It is calculated as
|
||||
// the sum of:
|
||||
// SM_CXFRAME - The thickness of the sizing border
|
||||
// SM_CXPADDEDBORDER - The amount of border padding
|
||||
// for captioned windows
|
||||
//
|
||||
// If the window does not have a caption, mHorResizeMargin will be equal to
|
||||
// `WinUtils::GetSystemMetricsForDpi(SM_CXFRAME, dpi)`
|
||||
mHorResizeMargin =
|
||||
WinUtils::GetSystemMetricsForDpi(SM_CXFRAME, dpi) +
|
||||
(hasCaption ? WinUtils::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)
|
||||
: 0);
|
||||
|
||||
// mVertResizeMargin is the size of the default NC area at the
|
||||
// bottom of the window. It is calculated as the sum of:
|
||||
// SM_CYFRAME - The thickness of the sizing border
|
||||
// SM_CXPADDEDBORDER - The amount of border padding
|
||||
// for captioned windows.
|
||||
//
|
||||
// If the window does not have a caption, mVertResizeMargin will be equal to
|
||||
// `WinUtils::GetSystemMetricsForDpi(SM_CYFRAME, dpi)`
|
||||
mVertResizeMargin =
|
||||
WinUtils::GetSystemMetricsForDpi(SM_CYFRAME, dpi) +
|
||||
(hasCaption ? WinUtils::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)
|
||||
: 0);
|
||||
}
|
||||
|
||||
if (sizeMode == nsSizeMode_Minimized) {
|
||||
// Use default frame size for minimized windows
|
||||
@@ -2606,13 +2662,7 @@ bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
|
||||
// makes the whole caption part of our client area, allowing us to draw
|
||||
// in the whole caption area. Additionally remove the default frame from
|
||||
// the left, right, and bottom.
|
||||
//
|
||||
// NOTE(emilio): Fullscreen windows have completely different window styles
|
||||
// because of HideWindowChrome(), so we actually need to apply the offsets
|
||||
// and extend into the frame. It might be worth investigating if we can
|
||||
// make fullscreen work without messing with window styles (like
|
||||
// maximized windows work).
|
||||
mNonClientOffset.top = mVertResizeMargin + mCaptionHeight;
|
||||
mNonClientOffset.top = mCaptionHeight;
|
||||
mNonClientOffset.bottom = mVertResizeMargin;
|
||||
mNonClientOffset.left = mHorResizeMargin;
|
||||
mNonClientOffset.right = mHorResizeMargin;
|
||||
@@ -2620,7 +2670,12 @@ bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
|
||||
// We make the entire frame part of the client area. We leave the default
|
||||
// frame sizes for left, right and bottom since Windows will automagically
|
||||
// position the edges "offscreen" for maximized windows.
|
||||
mNonClientOffset.top = mCaptionHeight;
|
||||
int verticalResize =
|
||||
WinUtils::GetSystemMetricsForDpi(SM_CYFRAME, dpi) +
|
||||
(hasCaption ? WinUtils::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)
|
||||
: 0);
|
||||
|
||||
mNonClientOffset.top = mCaptionHeight - verticalResize;
|
||||
mNonClientOffset.bottom = 0;
|
||||
mNonClientOffset.left = 0;
|
||||
mNonClientOffset.right = 0;
|
||||
@@ -2653,23 +2708,26 @@ bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void nsWindow::SetCustomTitlebar(bool aCustomTitlebar) {
|
||||
nsresult nsWindow::SetNonClientMargins(const LayoutDeviceIntMargin& margins) {
|
||||
if (!IsTopLevelWidget() || mBorderStyle == BorderStyle::None) {
|
||||
return;
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (mCustomNonClient == aCustomTitlebar) {
|
||||
return;
|
||||
if (mNonClientMargins == margins) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mHideChrome) {
|
||||
mCustomTitlebarOnceChromeShows = Some(aCustomTitlebar);
|
||||
return;
|
||||
mFutureMarginsOnceChromeShows = margins;
|
||||
mFutureMarginsToUse = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mCustomTitlebarOnceChromeShows.reset();
|
||||
mFutureMarginsToUse = false;
|
||||
|
||||
mCustomNonClient = aCustomTitlebar;
|
||||
// -1 margins request a reset
|
||||
mCustomNonClient = margins != LayoutDeviceIntMargin(-1, -1, -1, -1);
|
||||
mNonClientMargins = margins;
|
||||
|
||||
// Force a reflow of content based on the new client dimensions.
|
||||
if (mCustomNonClient) {
|
||||
@@ -2677,10 +2735,15 @@ void nsWindow::SetCustomTitlebar(bool aCustomTitlebar) {
|
||||
} else {
|
||||
ResetLayout();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsWindow::SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) {
|
||||
mCustomResizeMargin = aResizeMargin;
|
||||
mUseResizeMarginOverrides = true;
|
||||
mHorResizeMargin = aResizeMargin;
|
||||
mVertResizeMargin = aResizeMargin;
|
||||
UpdateNonClientMargins();
|
||||
}
|
||||
|
||||
nsAutoRegion nsWindow::ComputeNonClientHRGN() {
|
||||
@@ -2705,7 +2768,7 @@ nsAutoRegion nsWindow::ComputeNonClientHRGN() {
|
||||
// windows non-client chrome and app non-client chrome
|
||||
// in winRgn.
|
||||
::GetWindowRect(mWnd, &rect);
|
||||
rect.top += mCaptionHeight + mVertResizeMargin;
|
||||
rect.top += mCaptionHeight;
|
||||
rect.right -= mHorResizeMargin;
|
||||
rect.bottom -= mVertResizeMargin;
|
||||
rect.left += mHorResizeMargin;
|
||||
@@ -2975,9 +3038,8 @@ void nsWindow::HideWindowChrome(bool aShouldHide) {
|
||||
// if there's nothing to "restore" it to, just use what's there now
|
||||
oldChrome = mOldStyles.refOr(currentChrome);
|
||||
newChrome = oldChrome;
|
||||
if (mCustomTitlebarOnceChromeShows) {
|
||||
SetCustomTitlebar(mCustomTitlebarOnceChromeShows.extract());
|
||||
MOZ_ASSERT(!mCustomTitlebarOnceChromeShows);
|
||||
if (mFutureMarginsToUse) {
|
||||
SetNonClientMargins(mFutureMarginsOnceChromeShows);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4922,9 +4984,8 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
* sending the message with an updated title
|
||||
*/
|
||||
|
||||
if (mSendingSetText || !mCustomNonClient) {
|
||||
if (mSendingSetText || !mCustomNonClient || mNonClientMargins.top == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
// From msdn, the way around this is to disable the visible state
|
||||
@@ -5867,11 +5928,10 @@ void nsWindow::FinishLiveResizing(ResizeState aNewState) {
|
||||
|
||||
LayoutDeviceIntMargin nsWindow::NonClientSizeMargin(
|
||||
const LayoutDeviceIntMargin& aNonClientOffset) const {
|
||||
return LayoutDeviceIntMargin(
|
||||
mCaptionHeight + mVertResizeMargin - aNonClientOffset.top,
|
||||
mHorResizeMargin - aNonClientOffset.right,
|
||||
mVertResizeMargin - aNonClientOffset.bottom,
|
||||
mHorResizeMargin - aNonClientOffset.left);
|
||||
return LayoutDeviceIntMargin(mCaptionHeight - aNonClientOffset.top,
|
||||
mHorResizeMargin - aNonClientOffset.right,
|
||||
mVertResizeMargin - aNonClientOffset.bottom,
|
||||
mHorResizeMargin - aNonClientOffset.left);
|
||||
}
|
||||
|
||||
int32_t nsWindow::ClientMarginHitTestPoint(int32_t aX, int32_t aY) {
|
||||
@@ -5924,12 +5984,6 @@ int32_t nsWindow::ClientMarginHitTestPoint(int32_t aX, int32_t aY) {
|
||||
borderSize.EnsureAtLeast(
|
||||
LayoutDeviceIntMargin(mVertResizeMargin, mHorResizeMargin,
|
||||
mVertResizeMargin, mHorResizeMargin));
|
||||
// If we have a custom resize margin, check for it too.
|
||||
if (mCustomResizeMargin) {
|
||||
borderSize.EnsureAtLeast(
|
||||
LayoutDeviceIntMargin(mCustomResizeMargin, mCustomResizeMargin,
|
||||
mCustomResizeMargin, mCustomResizeMargin));
|
||||
}
|
||||
|
||||
bool top = false;
|
||||
bool bottom = false;
|
||||
|
||||
@@ -293,7 +293,7 @@ class nsWindow final : public nsBaseWidget {
|
||||
TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override;
|
||||
void SetTransparencyMode(TransparencyMode aMode) override;
|
||||
TransparencyMode GetTransparencyMode() override;
|
||||
void SetCustomTitlebar(bool) override;
|
||||
nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override;
|
||||
void SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) override;
|
||||
void UpdateWindowDraggingRegion(
|
||||
const LayoutDeviceIntRegion& aRegion) override;
|
||||
@@ -802,20 +802,23 @@ class nsWindow final : public nsBaseWidget {
|
||||
// Non-client margin settings
|
||||
// Pre-calculated outward offset applied to default frames
|
||||
LayoutDeviceIntMargin mNonClientOffset;
|
||||
// Margins set by the owner
|
||||
LayoutDeviceIntMargin mNonClientMargins{-1, -1, -1, -1};
|
||||
// Margins we'd like to set once chrome is reshown:
|
||||
LayoutDeviceIntMargin mFutureMarginsOnceChromeShows;
|
||||
// Indicates we need to apply margins once toggling chrome into showing:
|
||||
bool mFutureMarginsToUse = false;
|
||||
|
||||
// Indicates the custom titlebar is enabled.
|
||||
// Indicates custom frames are enabled
|
||||
bool mCustomNonClient = false;
|
||||
// Whether we want to draw to the titlebar once the chrome shows. (Always
|
||||
// Nothing if mHideChrome is false).
|
||||
mozilla::Maybe<bool> mCustomTitlebarOnceChromeShows;
|
||||
// Indicates custom resize margins are in effect
|
||||
bool mUseResizeMarginOverrides = false;
|
||||
// Width of the left and right portions of the resize region
|
||||
mozilla::LayoutDeviceIntCoord mHorResizeMargin;
|
||||
// Height of the top and bottom portions of the resize region
|
||||
mozilla::LayoutDeviceIntCoord mVertResizeMargin;
|
||||
// Height of the caption plus border
|
||||
mozilla::LayoutDeviceIntCoord mCaptionHeight;
|
||||
// Custom extra resize margin width.
|
||||
mozilla::LayoutDeviceIntCoord mCustomResizeMargin{0};
|
||||
|
||||
// not yet set, will be calculated on first use
|
||||
double mDefaultScale = -1.0;
|
||||
|
||||
@@ -235,7 +235,7 @@ STATIC_ATOMS = [
|
||||
Atom("childList", "childList"),
|
||||
Atom("child_item_count", "child-item-count"),
|
||||
Atom("choose", "choose"),
|
||||
Atom("customtitlebar", "customtitlebar"),
|
||||
Atom("chromemargin", "chromemargin"),
|
||||
Atom("exposeToUntrustedContent", "exposeToUntrustedContent"),
|
||||
Atom("circ", "circ"),
|
||||
Atom("circle", "circle"),
|
||||
|
||||
@@ -1501,7 +1501,7 @@ void AppWindow::SyncAttributesToWidget() {
|
||||
|
||||
nsAutoString attr;
|
||||
|
||||
// Some attributes can change the client size (e.g. customtitlebar on Windows
|
||||
// Some attributes can change the client size (e.g. chromemargin on Windows
|
||||
// and MacOS). But we might want to keep it.
|
||||
const LayoutDeviceIntSize oldClientSize = mWindow->GetClientSize();
|
||||
// We have to check now whether we want to restore the client size, as any
|
||||
@@ -1509,16 +1509,19 @@ void AppWindow::SyncAttributesToWidget() {
|
||||
bool maintainClientSize = mDominantClientSize;
|
||||
|
||||
// "hidechrome" attribute
|
||||
mWindow->HideWindowChrome(windowElement->GetBoolAttr(nsGkAtoms::hidechrome));
|
||||
if (windowElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidechrome,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
mWindow->HideWindowChrome(true);
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE_VOID(mWindow);
|
||||
|
||||
// "customtitlebar" attribute
|
||||
// FIXME(emilio): This should arguably be
|
||||
// SetCustomTitlebar(windowElement->GetBoolAttr(...)), but that breaks with
|
||||
// the early blank window which sets the custom titlebar via
|
||||
// nsIDOMWindowUtils...
|
||||
if (windowElement->GetBoolAttr(nsGkAtoms::customtitlebar)) {
|
||||
mWindow->SetCustomTitlebar(true);
|
||||
// "chromemargin" attribute
|
||||
nsIntMargin margins;
|
||||
windowElement->GetAttribute(u"chromemargin"_ns, attr);
|
||||
if (nsContentUtils::ParseIntMarginValue(attr, margins)) {
|
||||
mWindow->SetNonClientMargins(
|
||||
LayoutDeviceIntMargin::FromUnknownMargin(margins));
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE_VOID(mWindow);
|
||||
@@ -1547,17 +1550,18 @@ void AppWindow::SyncAttributesToWidget() {
|
||||
}
|
||||
|
||||
// "drawtitle" attribute
|
||||
mWindow->SetDrawsTitle(windowElement->GetBoolAttr(nsGkAtoms::drawtitle));
|
||||
windowElement->GetAttribute(u"drawtitle"_ns, attr);
|
||||
mWindow->SetDrawsTitle(attr.LowerCaseEqualsLiteral("true"));
|
||||
NS_ENSURE_TRUE_VOID(mWindow);
|
||||
|
||||
// "toggletoolbar" attribute
|
||||
mWindow->SetShowsToolbarButton(
|
||||
windowElement->HasAttribute(u"toggletoolbar"_ns));
|
||||
windowElement->GetAttribute(u"toggletoolbar"_ns, attr);
|
||||
mWindow->SetShowsToolbarButton(attr.LowerCaseEqualsLiteral("true"));
|
||||
NS_ENSURE_TRUE_VOID(mWindow);
|
||||
|
||||
// "macnativefullscreen" attribute
|
||||
mWindow->SetSupportsNativeFullscreen(
|
||||
windowElement->HasAttribute(u"macnativefullscreen"_ns));
|
||||
windowElement->GetAttribute(u"macnativefullscreen"_ns, attr);
|
||||
mWindow->SetSupportsNativeFullscreen(attr.LowerCaseEqualsLiteral("true"));
|
||||
NS_ENSURE_TRUE_VOID(mWindow);
|
||||
|
||||
// "macanimationtype" attribute
|
||||
@@ -2342,7 +2346,7 @@ NS_IMETHODIMP
|
||||
AppWindow::BeforeStartLayout() {
|
||||
ApplyChromeFlags();
|
||||
// Ordering here is important, loading width/height values in
|
||||
// LoadPersistentWindowState() depends on the customtitlebar attribute (since
|
||||
// LoadPersistentWindowState() depends on the chromemargin attribute (since
|
||||
// we need to translate outer to inner sizes).
|
||||
SyncAttributesToWidget();
|
||||
LoadPersistentWindowState();
|
||||
|
||||
Reference in New Issue
Block a user