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:
Cristina Horotan
2024-11-28 06:57:35 +02:00
parent 7a0203174c
commit bb08cc9f1d
52 changed files with 710 additions and 224 deletions

View File

@@ -120,8 +120,8 @@ addAccessibleTask(
info("Showing title bar"); info("Showing title bar");
let titleBarChanged = BrowserTestUtils.waitForMutationCondition( let titleBarChanged = BrowserTestUtils.waitForMutationCondition(
document.documentElement, document.documentElement,
{ attributes: true, attributeFilter: ["customtitlebar"] }, { attributes: true, attributeFilter: ["tabsintitlebar"] },
() => !document.documentElement.hasAttribute("customtitlebar") () => !document.documentElement.hasAttribute("tabsintitlebar")
); );
await SpecialPowers.pushPrefEnv({ await SpecialPowers.pushPrefEnv({
set: [["browser.tabs.inTitlebar", false]], set: [["browser.tabs.inTitlebar", false]],

View File

@@ -102,13 +102,12 @@ var gBrowserInit = {
toolbarMenubar.setAttribute("data-l10n-attrs", "toolbarname"); 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. // up mutations from it and causing a reflow.
AutoHideMenubar.init(); AutoHideMenubar.init();
// Update the customtitlebar attribute so the window can be sized // Update the chromemargin attribute so the window can be sized correctly.
// correctly.
window.TabBarVisibility.update(); window.TabBarVisibility.update();
CustomTitlebar.init(); TabsInTitlebar.init();
new LightweightThemeConsumer(document); new LightweightThemeConsumer(document);
@@ -1025,7 +1024,7 @@ var gBrowserInit = {
onUnload() { onUnload() {
gUIDensity.uninit(); gUIDensity.uninit();
CustomTitlebar.uninit(); TabsInTitlebar.uninit();
ToolbarIconColor.uninit(); ToolbarIconColor.uninit();

View File

@@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var CustomTitlebar = { var TabsInTitlebar = {
init() { init() {
this._readPref(); this._readPref();
Services.prefs.addObserver(this._prefName, this); Services.prefs.addObserver(this._prefName, this);
@@ -40,7 +40,7 @@ var CustomTitlebar = {
}, },
get enabled() { get enabled() {
return document.documentElement.hasAttribute("customtitlebar"); return document.documentElement.getAttribute("tabsintitlebar") == "true";
}, },
observe(subject, topic) { observe(subject, topic) {
@@ -67,13 +67,23 @@ var CustomTitlebar = {
this.systemSupported && this.systemSupported &&
!window.fullScreen && !window.fullScreen &&
!Object.keys(this._disallowed).length; !Object.keys(this._disallowed).length;
if (allowed) {
document.documentElement.toggleAttribute("customtitlebar", allowed); document.documentElement.setAttribute("tabsintitlebar", "true");
if (AppConstants.platform == "macosx") { if (AppConstants.platform == "macosx") {
document.documentElement.toggleAttribute("drawtitle", !allowed); 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); TabBarVisibility.update(true);
}, },

View File

@@ -6642,7 +6642,7 @@ var ToolbarIconColor = {
_windowState: { _windowState: {
active: false, active: false,
fullscreen: false, fullscreen: false,
customtitlebar: false, tabsintitlebar: false,
}, },
init() { init() {
this._initialized = true; this._initialized = true;
@@ -6709,8 +6709,8 @@ var ToolbarIconColor = {
case "toolbarvisibilitychange": case "toolbarvisibilitychange":
// toolbar changes dont require reset of the cached color values // toolbar changes dont require reset of the cached color values
break; break;
case "customtitlebar": case "tabsintitlebar":
this._windowState.customtitlebar = reasonValue; this._windowState.tabsintitlebar = reasonValue;
break; break;
} }

View File

@@ -17,7 +17,12 @@
#endif #endif
data-l10n-args="{"content-title":"CONTENTTITLE"}" data-l10n-args="{"content-title":"CONTENTTITLE"}"
data-l10n-attrs="data-content-title-default, data-content-title-private, data-title-default, data-title-private" 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" windowtype="navigator:browser"
macanimationtype="document" macanimationtype="document"
macnativefullscreen="true" macnativefullscreen="true"
@@ -113,7 +118,7 @@
} }
Services.scriptloader.loadSubScript("chrome://browser/content/browser-pageActions.js", this); 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/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/browser-unified-extensions.js", this);
Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser/tab.js", this); Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser/tab.js", this);
Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser/tabbrowser.js", this); Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser/tabbrowser.js", this);

View File

@@ -12,7 +12,7 @@
windowtype="Browser:page-info" windowtype="Browser:page-info"
#ifdef XP_MACOSX #ifdef XP_MACOSX
drawtitle="true" drawtitle="true"
customtitlebar="true" chromemargin="0,0,0,0"
#endif #endif
onload="onLoadPageInfo()" onload="onLoadPageInfo()"
align="stretch" align="stretch"

View File

@@ -10,7 +10,7 @@
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="webrtcIndicator" id="webrtcIndicator"
windowtype="Browser:WebRTCGlobalIndicator" windowtype="Browser:WebRTCGlobalIndicator"
customtitlebar="true" chromemargin="0,0,0,0"
> >
<head> <head>
<link rel="stylesheet" href="chrome://global/skin/global.css" /> <link rel="stylesheet" href="chrome://global/skin/global.css" />

View File

@@ -59,7 +59,7 @@ browser.jar:
content/browser/browser-sitePermissionPanel.js (content/browser-sitePermissionPanel.js) content/browser/browser-sitePermissionPanel.js (content/browser-sitePermissionPanel.js)
content/browser/browser-siteProtections.js (content/browser-siteProtections.js) content/browser/browser-siteProtections.js (content/browser-siteProtections.js)
content/browser/browser-sync.js (content/browser-sync.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-toolbarKeyNav.js (content/browser-toolbarKeyNav.js)
content/browser/browser-thumbnails.js (content/browser-thumbnails.js) content/browser/browser-thumbnails.js (content/browser-thumbnails.js)
content/browser/browser-unified-extensions.js (content/browser-unified-extensions.js) content/browser/browser-unified-extensions.js (content/browser-unified-extensions.js)

View File

@@ -1822,7 +1822,7 @@ BrowserGlue.prototype = {
// Hide the titlebar if the actual browser window will draw in it. // Hide the titlebar if the actual browser window will draw in it.
let hiddenTitlebar = Services.appinfo.drawInTitlebar; let hiddenTitlebar = Services.appinfo.drawInTitlebar;
if (hiddenTitlebar) { if (hiddenTitlebar) {
win.windowUtils.setCustomTitlebar(true); win.windowUtils.setChromeMargin(0, 2, 2, 2);
} }
let docElt = win.document.documentElement; let docElt = win.document.documentElement;

View File

@@ -1674,7 +1674,7 @@ CustomizeMode.prototype = {
}, },
_canDrawInTitlebar() { _canDrawInTitlebar() {
return this.window.CustomTitlebar.systemSupported; return this.window.TabsInTitlebar.systemSupported;
}, },
_ensureCustomizationPanels() { _ensureCustomizationPanels() {

View File

@@ -143,9 +143,9 @@ add_task(async function () {
// Bug 971626 - Restore Defaults should collapse the Title Bar // Bug 971626 - Restore Defaults should collapse the Title Bar
add_task(async function () { add_task(async function () {
{ {
const supported = CustomTitlebar.systemSupported; const supported = TabsInTitlebar.systemSupported;
is(typeof supported, "boolean"); is(typeof supported, "boolean");
info("CustomTitlebar support: " + supported); info("TabsInTitlebar support: " + supported);
if (!supported) { if (!supported) {
return; return;
} }

View File

@@ -92,7 +92,7 @@ add_task(async function tabstrip_context() {
// Right-click on the title bar spacer before the tabstrip should show a // 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. // context menu without options to move it and no tab-specific options.
add_task(async function titlebar_spacer_context() { add_task(async function titlebar_spacer_context() {
if (!CustomTitlebar.enabled) { if (!TabsInTitlebar.enabled) {
info("Skipping test that requires tabs in the title bar."); info("Skipping test that requires tabs in the title bar.");
return; return;
} }

View File

@@ -17,7 +17,7 @@
screenX="10" screenY="10" screenX="10" screenY="10"
#ifdef XP_MACOSX #ifdef XP_MACOSX
drawtitle="true" drawtitle="true"
customtitlebar="true" chromemargin="0,0,0,0"
#endif #endif
toggletoolbar="true" toggletoolbar="true"
persist="width height screenX screenY sizemode"> persist="width height screenX screenY sizemode">

View File

@@ -46,13 +46,13 @@ function getExpectedElements(win, tabstripOrientation = "horizontal") {
const sizeMode = win.document.documentElement.getAttribute("sizemode"); const sizeMode = win.document.documentElement.getAttribute("sizemode");
let selectors; 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. // the right stuff being visible whatever the case for the given window.
if (tabstripOrientation == "horizontal") { if (tabstripOrientation == "horizontal") {
selectors = ["#TabsToolbar"]; selectors = ["#TabsToolbar"];
if (win.CustomTitlebar.enabled) { if (win.TabsInTitlebar.enabled) {
selectors.push("#TabsToolbar .titlebar-buttonbox-container"); selectors.push("#TabsToolbar .titlebar-buttonbox-container");
if (sizeMode == "normal") { if (sizeMode == "normal") {
selectors.push("#TabsToolbar .titlebar-spacer"); selectors.push("#TabsToolbar .titlebar-spacer");
@@ -62,7 +62,7 @@ function getExpectedElements(win, tabstripOrientation = "horizontal") {
} }
selectors = ["#vertical-tabs"]; selectors = ["#vertical-tabs"];
if (win.CustomTitlebar.enabled) { if (win.TabsInTitlebar.enabled) {
selectors.push("#nav-bar .titlebar-buttonbox-container"); selectors.push("#nav-bar .titlebar-buttonbox-container");
if (sizeMode == "normal") { if (sizeMode == "normal") {
selectors.push("#nav-bar .titlebar-spacer[type='post-tabs']"); 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(`sizemode: ${document.documentElement.getAttribute("sizemode")}`);
info( info(
`customtitlebar: ${document.documentElement.getAttribute("customtitlebar")}` `tabsintitlebar: ${document.documentElement.getAttribute("tabsintitlebar")}`
); );
const expectedElementsWhenHorizontal = getExpectedElements( const expectedElementsWhenHorizontal = getExpectedElements(

View File

@@ -8089,28 +8089,28 @@ var TabBarVisibility = {
} }
if (nonPopupWithVerticalTabs) { 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 // 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. // We'll fix this in Bug 1921034.
hideTabstrip = true; hideTabstrip = true;
CustomTitlebar.allowedBy("tabs-visible", true); TabsInTitlebar.allowedBy("tabs-visible", true);
} else { } else {
CustomTitlebar.allowedBy("tabs-visible", !hideTabstrip); TabsInTitlebar.allowedBy("tabs-visible", !hideTabstrip);
} }
gNavToolbox.toggleAttribute("tabs-hidden", hideTabstrip); gNavToolbox.toggleAttribute("tabs-hidden", hideTabstrip);
// Should the nav-bar look and function like a titlebar? // Should the nav-bar look and function like a titlebar?
navbar.classList.toggle( navbar.classList.toggle(
"browser-titlebar", "browser-titlebar",
CustomTitlebar.enabled && hideTabstrip TabsInTitlebar.enabled && hideTabstrip
); );
document document
.getElementById("browser") .getElementById("browser")
.classList.toggle( .classList.toggle(
"browser-toolbox-background", "browser-toolbox-background",
CustomTitlebar.enabled && nonPopupWithVerticalTabs TabsInTitlebar.enabled && nonPopupWithVerticalTabs
); );
if ( if (

View File

@@ -344,7 +344,7 @@
// When the tabbar has an unified appearance with the titlebar // When the tabbar has an unified appearance with the titlebar
// and menubar, a double-click in it should have the same behavior // and menubar, a double-click in it should have the same behavior
// as double-clicking the titlebar // as double-clicking the titlebar
if (CustomTitlebar.enabled && !this.verticalMode) { if (TabsInTitlebar.enabled && !this.verticalMode) {
return; return;
} }

View File

@@ -34,7 +34,7 @@
* (in X11) or the compositor (in Wayland) does draw the shadow corners * (in X11) or the compositor (in Wayland) does draw the shadow corners
* already. * already.
*/ */
:root[customtitlebar] { :root[tabsintitlebar] {
background-color: transparent; background-color: transparent;
&[sizemode="normal"]:not([gtktiledwindow="true"]) { &[sizemode="normal"]:not([gtktiledwindow="true"]) {

View File

@@ -8,7 +8,7 @@
--toolbox-bgcolor-inactive: -moz-headerbarinactive; --toolbox-bgcolor-inactive: -moz-headerbarinactive;
--toolbox-textcolor-inactive: -moz-headerbarinactivetext; --toolbox-textcolor-inactive: -moz-headerbarinactivetext;
&:where([customtitlebar]) { &:where([tabsintitlebar]) {
--toolbox-bgcolor: ActiveCaption; --toolbox-bgcolor: ActiveCaption;
--toolbox-textcolor: CaptionText; --toolbox-textcolor: CaptionText;
--toolbox-bgcolor-inactive: InactiveCaption; --toolbox-bgcolor-inactive: InactiveCaption;
@@ -111,7 +111,7 @@
--toolbox-textcolor: light-dark(rgb(21, 20, 26), rgb(251, 251, 254)); --toolbox-textcolor: light-dark(rgb(21, 20, 26), rgb(251, 251, 254));
--toolbox-bgcolor-inactive: var(--toolbox-bgcolor); --toolbox-bgcolor-inactive: var(--toolbox-bgcolor);
--toolbox-textcolor-inactive: var(--toolbox-textcolor); --toolbox-textcolor-inactive: var(--toolbox-textcolor);
&:where([customtitlebar]) { &:where([tabsintitlebar]) {
--toolbox-bgcolor-inactive: light-dark(rgb(235, 235, 239), rgb(31, 30, 37)); --toolbox-bgcolor-inactive: light-dark(rgb(235, 235, 239), rgb(31, 30, 37));
} }
} }

View File

@@ -193,7 +193,7 @@ body {
@media (-moz-platform: macos) and (-moz-bool-pref: "browser.theme.native-theme") { @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 /* Don't make the toolbox vibrant when in full-screen. macOS fullscreen has a
* native titlebar outside of the window (revealed on hover) anyways. */ * native titlebar outside of the window (revealed on hover) anyways. */
:root[customtitlebar]:not([lwtheme], [macOSNativeFullscreen]) & { :root[tabsintitlebar]:not([lwtheme], [macOSNativeFullscreen]) & {
background-color: transparent; background-color: transparent;
/* This is conceptually a background, but putting this on a /* This is conceptually a background, but putting this on a
@@ -233,8 +233,8 @@ body {
.browser-titlebar { .browser-titlebar {
-moz-window-dragging: drag; -moz-window-dragging: drag;
:root[customtitlebar] &, :root[tabsintitlebar] &,
:root[customtitlebar] & #urlbar:popover-open { :root[tabsintitlebar] & #urlbar:popover-open {
will-change: opacity; will-change: opacity;
transition: opacity var(--inactive-window-transition); transition: opacity var(--inactive-window-transition);
@@ -263,14 +263,14 @@ body {
visibility: hidden; visibility: hidden;
} }
:root:not([customtitlebar], [inFullscreen]) & { :root:not([chromemargin], [inFullscreen]) & {
display: none; display: none;
} }
} }
.titlebar-spacer { .titlebar-spacer {
:root[inFullscreen] &, :root[inFullscreen] &,
:root:not([customtitlebar]) & { :root:not([tabsintitlebar]) & {
display: none; display: none;
} }
@@ -317,7 +317,7 @@ body {
-moz-default-appearance: -moz-window-button-box; -moz-default-appearance: -moz-window-button-box;
position: relative; position: relative;
:root:not([customtitlebar], [sizemode=fullscreen]) & { :root:not([tabsintitlebar], [sizemode=fullscreen]) & {
display: none; display: none;
} }
} }
@@ -332,12 +332,12 @@ body {
as tall as the tab toolbar such that the window controls don't appear to move up. 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. 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); min-height: var(--tabstrip-min-height);
} }
/* adjust the height of the auto-hiding toolbar menubar when the tabstrip is /* 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. */ 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)); min-height: calc(var(--urlbar-min-height) + 2 * var(--urlbar-padding-block));
} }

View File

@@ -26,7 +26,7 @@
} }
@media (-moz-windows-accent-color-in-titlebar) or (-moz-windows-mica) { @media (-moz-windows-accent-color-in-titlebar) or (-moz-windows-mica) {
:root[customtitlebar] { :root[tabsintitlebar] {
@media (-moz-windows-mica) { @media (-moz-windows-mica) {
&:not([lwtheme]) { &:not([lwtheme]) {
background-color: transparent; background-color: transparent;

View File

@@ -368,7 +368,7 @@ export var TestRunner = {
this.mochitestScope.info("called " + config.name); this.mochitestScope.info("called " + config.name);
// Add a default timeout of 700ms to avoid conflicts when configurations // 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 Promise.race([applyPromise, timeoutPromise]).then(result => {
return new Promise(resolve => { return new Promise(resolve => {
setTimeout(() => resolve(result), 700); setTimeout(() => resolve(result), 700);

View File

@@ -4,7 +4,7 @@
const PREF_TABS_IN_TITLEBAR = "browser.tabs.inTitlebar"; const PREF_TABS_IN_TITLEBAR = "browser.tabs.inTitlebar";
export var CustomTitlebar = { export var TabsInTitlebar = {
init() {}, init() {},
configurations: { configurations: {

View File

@@ -24,12 +24,12 @@ FINAL_TARGET_FILES.resources.configurations += [
"configurations/Buttons.sys.mjs", "configurations/Buttons.sys.mjs",
"configurations/ControlCenter.sys.mjs", "configurations/ControlCenter.sys.mjs",
"configurations/CustomizeMode.sys.mjs", "configurations/CustomizeMode.sys.mjs",
"configurations/CustomTitlebar.sys.mjs",
"configurations/DevTools.sys.mjs", "configurations/DevTools.sys.mjs",
"configurations/LightweightThemes.sys.mjs", "configurations/LightweightThemes.sys.mjs",
"configurations/PermissionPrompts.sys.mjs", "configurations/PermissionPrompts.sys.mjs",
"configurations/Preferences.sys.mjs", "configurations/Preferences.sys.mjs",
"configurations/Tabs.sys.mjs", "configurations/Tabs.sys.mjs",
"configurations/TabsInTitlebar.sys.mjs",
"configurations/Toolbars.sys.mjs", "configurations/Toolbars.sys.mjs",
"configurations/UIDensities.sys.mjs", "configurations/UIDensities.sys.mjs",
"configurations/WindowSize.sys.mjs", "configurations/WindowSize.sys.mjs",

View File

@@ -12,7 +12,7 @@ add_task(async function capture() {
} }
let sets = [ let sets = [
"CustomTitlebar", "TabsInTitlebar",
"Tabs", "Tabs",
"WindowSize", "WindowSize",
"Toolbars", "Toolbars",

View File

@@ -1819,6 +1819,50 @@ bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) {
nsGkAtoms::ul, nsGkAtoms::xmp); 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 // static
int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) { int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) {
nsAString::const_iterator iter, end; nsAString::const_iterator iter, end;

View File

@@ -874,6 +874,17 @@ class nsContentUtils {
ParseHTMLIntegerResultFlags* aResult); ParseHTMLIntegerResultFlags* aResult);
public: 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 * Parse the value of the <font size=""> attribute according to the HTML5
* spec as of April 16, 2012. * spec as of April 16, 2012.

View File

@@ -4192,27 +4192,32 @@ nsDOMWindowUtils::PostRestyleSelfEvent(Element* aElement) {
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDOMWindowUtils::SetCustomTitlebar(bool aCustomTitlebar) { nsDOMWindowUtils::SetChromeMargin(int32_t aTop, int32_t aRight, int32_t aBottom,
// TODO(emilio): Can't we use nsDOMWindowUtils::GetWidget()? int32_t aLeft) {
if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow)) { nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
if (nsCOMPtr<nsIBaseWindow> baseWindow = if (window) {
do_QueryInterface(window->GetDocShell())) { nsCOMPtr<nsIBaseWindow> baseWindow =
do_QueryInterface(window->GetDocShell());
if (baseWindow) {
nsCOMPtr<nsIWidget> widget; nsCOMPtr<nsIWidget> widget;
baseWindow->GetMainWidget(getter_AddRefs(widget)); baseWindow->GetMainWidget(getter_AddRefs(widget));
if (widget) { if (widget) {
widget->SetCustomTitlebar(aCustomTitlebar); LayoutDeviceIntMargin margins(aTop, aRight, aBottom, aLeft);
return widget->SetNonClientMargins(margins);
} }
} }
} }
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDOMWindowUtils::SetResizeMargin(int32_t aResizeMargin) { nsDOMWindowUtils::SetResizeMargin(int32_t aResizeMargin) {
// TODO(emilio): Can't we use nsDOMWindowUtils::GetWidget()? nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow)) { if (window) {
if (nsCOMPtr<nsIBaseWindow> baseWindow = nsCOMPtr<nsIBaseWindow> baseWindow =
do_QueryInterface(window->GetDocShell())) { do_QueryInterface(window->GetDocShell());
if (baseWindow) {
nsCOMPtr<nsIWidget> widget; nsCOMPtr<nsIWidget> widget;
baseWindow->GetMainWidget(getter_AddRefs(widget)); baseWindow->GetMainWidget(getter_AddRefs(widget));
if (widget) { if (widget) {

View File

@@ -2053,11 +2053,14 @@ interface nsIDOMWindowUtils : nsISupports {
readonly attribute boolean refreshDriverHasPendingTick; readonly attribute boolean refreshDriverHasPendingTick;
/** /**
* Controls whether we paint to the titlebar of the window. * Controls the amount of chrome that should be visible on each side of
* Works like the customtitlebar xul:window attribute. * the window. Works like the chromemargin xul:window attribute.
* This should only be used with non-XUL windows. * 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 * Controls the amount of space on each edge of the window that can be

View File

@@ -39,8 +39,8 @@ void ChromeObserver::Init() {
for (uint32_t i = 0; i < attributeCount; i++) { for (uint32_t i = 0; i < attributeCount; i++) {
BorrowedAttrInfo info = rootElement->GetAttrInfoAt(i); BorrowedAttrInfo info = rootElement->GetAttrInfoAt(i);
const nsAttrName* name = info.mName; const nsAttrName* name = info.mName;
if (name->LocalName() == nsGkAtoms::customtitlebar) { if (name->LocalName() == nsGkAtoms::chromemargin) {
// Some linux windows managers have an issue when the customtitlebar is // Some linux windows managers have an issue when the chrome margin is
// applied while the browser is loading (bug 1598848). For now, skip // applied while the browser is loading (bug 1598848). For now, skip
// applying this attribute when initializing. // applying this attribute when initializing.
continue; 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, void ChromeObserver::AttributeChanged(dom::Element* aElement,
int32_t aNamespaceID, nsAtom* aName, int32_t aNamespaceID, nsAtom* aName,
int32_t aModType, int32_t aModType,
@@ -82,25 +119,37 @@ void ChromeObserver::AttributeChanged(dom::Element* aElement,
return; return;
} }
if (aModType == dom::MutationEvent_Binding::ADDITION || const nsAttrValue* value = aElement->GetParsedAttr(aName, aNamespaceID);
aModType == dom::MutationEvent_Binding::REMOVAL) { if (value) {
const bool added = aModType == dom::MutationEvent_Binding::ADDITION; // Hide chrome if needed
if (aName == nsGkAtoms::hidechrome) { if (aName == nsGkAtoms::hidechrome) {
HideWindowChrome(added); HideWindowChrome(value->Equals(u"true"_ns, eCaseMatters));
} else if (aName == nsGkAtoms::customtitlebar) { } else if (aName == nsGkAtoms::chromemargin) {
SetCustomTitlebar(added); 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) { } else if (aName == nsGkAtoms::drawtitle) {
SetDrawsTitle(added); SetDrawsTitle(value->Equals(u"true"_ns, eCaseMatters));
} } else if (aName == nsGkAtoms::localedir) {
}
if (aName == nsGkAtoms::localedir) {
// if the localedir changed on the root element, reset the document // if the localedir changed on the root element, reset the document
// direction // direction
mDocument->ResetDocumentDirection(); mDocument->ResetDocumentDirection();
} }
if (aName == nsGkAtoms::title && } else {
aModType != dom::MutationEvent_Binding::REMOVAL) { if (aName == nsGkAtoms::hidechrome) {
mDocument->NotifyPossibleTitleChange(false); 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);
}
} }
} }
@@ -108,14 +157,11 @@ void ChromeObserver::NodeWillBeDestroyed(nsINode* aNode) {
mDocument = nullptr; mDocument = nullptr;
} }
void ChromeObserver::SetCustomTitlebar(bool aCustomTitlebar) { void ChromeObserver::ResetChromeMargins() {
if (nsIWidget* mainWidget = GetWindowWidget()) { nsIWidget* mainWidget = GetWindowWidget();
// SetCustomTitlebar can dispatch native events, hence doing it off a if (!mainWidget) return;
// script runner // See nsIWidget
nsContentUtils::AddScriptRunner(NewRunnableMethod<bool>( nsContentUtils::AddScriptRunner(new MarginSetter(mainWidget));
"SetCustomTitlebar", mainWidget, &nsIWidget::SetCustomTitlebar,
aCustomTitlebar));
}
} }
nsresult ChromeObserver::HideWindowChrome(bool aShouldHide) { nsresult ChromeObserver::HideWindowChrome(bool aShouldHide) {

View File

@@ -27,8 +27,11 @@ class ChromeObserver final : public nsStubMutationObserver {
protected: protected:
nsIWidget* GetWindowWidget(); nsIWidget* GetWindowWidget();
void SetDrawsTitle(bool aState); void SetDrawsTitle(bool aState);
void SetChromeMargins(const nsAttrValue* aValue);
nsresult HideWindowChrome(bool aShouldHide); nsresult HideWindowChrome(bool aShouldHide);
void SetCustomTitlebar(bool);
private:
void ResetChromeMargins();
~ChromeObserver(); ~ChromeObserver();
// A weak pointer cleared when the element will be destroyed. // A weak pointer cleared when the element will be destroyed.
Document* MOZ_NON_OWNING_REF mDocument; Document* MOZ_NON_OWNING_REF mDocument;

View File

@@ -131,7 +131,7 @@ static int sVerticalResizeMargin = 0;
// See nsWindow::NonClientSizeMargin() // See nsWindow::NonClientSizeMargin()
static Margin NonClientSizeMargin() { static Margin NonClientSizeMargin() {
return Margin{sCaptionHeight + sVerticalResizeMargin - sNonClientOffset.top, return Margin{sCaptionHeight - sNonClientOffset.top,
sHorizontalResizeMargin - sNonClientOffset.right, sHorizontalResizeMargin - sNonClientOffset.right,
sVerticalResizeMargin - sNonClientOffset.bottom, sVerticalResizeMargin - sNonClientOffset.bottom,
sHorizontalResizeMargin - sNonClientOffset.left}; sHorizontalResizeMargin - sNonClientOffset.left};
@@ -1365,7 +1365,7 @@ ThemeColors GetTheme(ThemeMode themeId) {
theme.tabColor = 0xf9f9fb; theme.tabColor = 0xf9f9fb;
theme.toolbarForegroundColor = 0xdddde1; theme.toolbarForegroundColor = 0xdddde1;
theme.tabOutlineColor = 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%)") // (set to "hsl(235,33%,19%)")
theme.titlebarColor = 0xf0f0f4; theme.titlebarColor = 0xf0f0f4;
// --chrome-content-separator-color in browser.css // --chrome-content-separator-color in browser.css
@@ -1992,15 +1992,25 @@ static Result<Ok, PreXULSkeletonUIError> CreateAndStorePreXULSkeletonUIImpl(
sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, sDpi); sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, sDpi);
sVerticalResizeMargin = sGetSystemMetricsForDpi(SM_CYFRAME, sDpi) + sVerticalResizeMargin = sGetSystemMetricsForDpi(SM_CYFRAME, sDpi) +
sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, 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) { if (sMaximized) {
sNonClientOffset = Margin{sCaptionHeight, 0, 0, 0}; sNonClientOffset.top = sCaptionHeight - sVerticalResizeMargin;
} else { } else {
// See nsWindow::NormalWindowNonClientOffset() // 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) { if (sMaximized) {

View File

@@ -7,7 +7,7 @@
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
windowtype="Toolkit:PictureInPicture" windowtype="Toolkit:PictureInPicture"
macnativefullscreen="true" macnativefullscreen="true"
customtitlebar="true" chromemargin="0,0,0,0"
scrolling="false" scrolling="false"
> >
<head> <head>

View File

@@ -197,9 +197,8 @@ add_task(async function test_found_resize() {
info(`values: ${JSON.stringify(values)}`); info(`values: ${JSON.stringify(values)}`);
info(`resizedValues: ${JSON.stringify(resizedValues)}`); info(`resizedValues: ${JSON.stringify(resizedValues)}`);
isfuzzy(resizedValues[0], values[0], 2, "first value"); isfuzzy(resizedValues[0], values[0], 2, "first value");
const kSlop = 50; Assert.greater(resizedValues[1] - 50, values[1], "second value");
Assert.greaterOrEqual(resizedValues[1] - kSlop, values[1], "second value"); Assert.greater(resizedValues[2] - 50, values[2], "third value");
Assert.greaterOrEqual(resizedValues[2] - kSlop, values[2], "third value");
endFn(); endFn();

View File

@@ -143,6 +143,10 @@ skip-if = [
["test_button.xhtml"] ["test_button.xhtml"]
["test_chromemargin.xhtml"]
support-files = "window_chromemargin.xhtml"
skip-if = ["apple_catalina"]
["test_closemenu_attribute.xhtml"] ["test_closemenu_attribute.xhtml"]
["test_contextmenu_list.xhtml"] ["test_contextmenu_list.xhtml"]

View 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>

View 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>

View File

@@ -5,7 +5,7 @@
height="300" height="300"
width="300" width="300"
sizemode="normal" sizemode="normal"
customtitlebar="true" chromemargin="0,2,2,2"
id="window" id="window"
persist="height width sizemode"> persist="height width sizemode">
<script type="application/javascript"><![CDATA[ <script type="application/javascript"><![CDATA[

View File

@@ -283,7 +283,8 @@ class nsCocoaWindow final : public nsBaseWidget {
void SetSupportsNativeFullscreen(bool aShow) override; void SetSupportsNativeFullscreen(bool aShow) override;
void SetWindowAnimationType(WindowAnimationType aType) override; void SetWindowAnimationType(WindowAnimationType aType) override;
void SetDrawsTitle(bool aDrawTitle) override; void SetDrawsTitle(bool aDrawTitle) override;
void SetCustomTitlebar(bool) override; nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override;
void SetDrawsInTitlebar(bool aState);
void UpdateThemeGeometries( void UpdateThemeGeometries(
const nsTArray<ThemeGeometry>& aThemeGeometries) override; const nsTArray<ThemeGeometry>& aThemeGeometries) override;
nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,

View File

@@ -2464,7 +2464,18 @@ void nsCocoaWindow::SetDrawsTitle(bool aDrawTitle) {
NS_OBJC_END_TRY_IGNORE_BLOCK; 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; NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
if (mWindow) { if (mWindow) {

View File

@@ -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 { bool nsWindow::IsAlwaysUndecoratedWindow() const {
if (mIsPIPWindow || gKioskMode) { if (mIsPIPWindow || gKioskMode) {
return true; return true;
@@ -8788,8 +8793,8 @@ bool nsWindow::IsAlwaysUndecoratedWindow() const {
return false; return false;
} }
void nsWindow::SetCustomTitlebar(bool aState) { void nsWindow::SetDrawsInTitlebar(bool aState) {
LOG("nsWindow::SetCustomTitlebar() State %d mGtkWindowDecoration %d\n", LOG("nsWindow::SetDrawsInTitlebar() State %d mGtkWindowDecoration %d\n",
aState, (int)mGtkWindowDecoration); aState, (int)mGtkWindowDecoration);
if (mGtkWindowDecoration == GTK_DECORATION_NONE || if (mGtkWindowDecoration == GTK_DECORATION_NONE ||

View File

@@ -373,7 +373,8 @@ class nsWindow final : public nsBaseWidget {
void GetCompositorWidgetInitData( void GetCompositorWidgetInitData(
mozilla::widget::CompositorWidgetInitData* aInitData) override; mozilla::widget::CompositorWidgetInitData* aInitData) override;
void SetCustomTitlebar(bool) override; nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override;
void SetDrawsInTitlebar(bool aState);
mozilla::LayoutDeviceIntCoord GetTitlebarRadius(); mozilla::LayoutDeviceIntCoord GetTitlebarRadius();
void UpdateWindowDraggingRegion( void UpdateWindowDraggingRegion(
const LayoutDeviceIntRegion& aRegion) override; const LayoutDeviceIntRegion& aRegion) override;

View File

@@ -39,7 +39,7 @@ namespace mozilla {
enum class NativeKeyBindingsType : uint8_t; enum class NativeKeyBindingsType : uint8_t;
namespace widget { namespace widget {
class HeadlessWidget final : public nsBaseWidget { class HeadlessWidget : public nsBaseWidget {
public: public:
HeadlessWidget(); HeadlessWidget();
@@ -77,6 +77,10 @@ class HeadlessWidget final : public nsBaseWidget {
// Headless widgets have no title, so just ignore it. // Headless widgets have no title, so just ignore it.
return NS_OK; 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; LayoutDeviceIntPoint WidgetToScreenOffset() override;
void SetInputContext(const InputContext& aContext, void SetInputContext(const InputContext& aContext,
const InputContextAction& aAction) override { const InputContextAction& aAction) override {

View File

@@ -1747,6 +1747,12 @@ LayoutDeviceIntPoint nsBaseWidget::GetClientOffset() {
return LayoutDeviceIntPoint(0, 0); 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; } uint32_t nsBaseWidget::GetMaxTouchPoints() const { return 0; }
bool nsBaseWidget::HasPendingInputEvent() { return false; } bool nsBaseWidget::HasPendingInputEvent() { return false; }

View File

@@ -252,9 +252,11 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
LayoutDeviceIntRect GetClientBounds() override; LayoutDeviceIntRect GetClientBounds() override;
LayoutDeviceIntRect GetScreenBounds() override; LayoutDeviceIntRect GetScreenBounds() override;
[[nodiscard]] nsresult GetRestoredBounds(LayoutDeviceIntRect& aRect) override; [[nodiscard]] nsresult GetRestoredBounds(LayoutDeviceIntRect& aRect) override;
nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override;
LayoutDeviceIntPoint GetClientOffset() override; LayoutDeviceIntPoint GetClientOffset() override;
void EnableDragDrop(bool aEnable) override {}; void EnableDragDrop(bool aEnable) override {};
nsresult AsyncEnableDragDrop(bool aEnable) override; nsresult AsyncEnableDragDrop(bool aEnable) override;
void SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) override;
[[nodiscard]] nsresult GetAttention(int32_t aCycleCount) override { [[nodiscard]] nsresult GetAttention(int32_t aCycleCount) override {
return NS_OK; return NS_OK;
} }

View File

@@ -870,15 +870,24 @@ class nsIWidget : public nsISupports {
*/ */
virtual LayoutDeviceIntRect GetClientBounds() = 0; 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 * 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. * 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. * Get the client offset from the window origin.
* *

View 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;
}

View File

@@ -16,6 +16,9 @@ with Files("unit/*macwebapputils*"):
with Files("unit/*taskbar_jumplistitems*"): with Files("unit/*taskbar_jumplistitems*"):
BUG_COMPONENT = ("Core", "Widget: Win32") BUG_COMPONENT = ("Core", "Widget: Win32")
with Files("TestChromeMargin.cpp"):
BUG_COMPONENT = ("Core", "Widget: Win32")
with Files("*413277*"): with Files("*413277*"):
BUG_COMPONENT = ("Core", "Widget: Cocoa") BUG_COMPONENT = ("Core", "Widget: Cocoa")
@@ -114,3 +117,9 @@ XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell.toml"]
MOCHITEST_MANIFESTS += ["mochitest.toml"] MOCHITEST_MANIFESTS += ["mochitest.toml"]
MOCHITEST_CHROME_MANIFESTS += ["chrome.toml"] MOCHITEST_CHROME_MANIFESTS += ["chrome.toml"]
BROWSER_CHROME_MANIFESTS += ["browser/browser.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']

View File

@@ -43,13 +43,13 @@ async function start() {
await waitForEvent(window, "focus"); await waitForEvent(window, "focus");
var oldOuterWidth = window.outerWidth, oldOuterHeight = window.outerHeight; var oldOuterWidth = window.outerWidth, oldOuterHeight = window.outerHeight;
var oldInnerWidth = window.innerWidth, oldInnerHeight = window.innerHeight; var oldInnerWidth = window.innerWidth, oldInnerHeight = window.innerHeight;
document.documentElement.setAttribute("customtitlebar", "true"); document.documentElement.setAttribute("chromemargin", "0,0,0,0");
await executeSoon(); await executeSoon();
is(window.outerWidth, oldOuterWidth, "customtitlebar shouldn't change the window's outerWidth"); is(window.outerWidth, oldOuterWidth, "chromemargin shouldn't change the window's outerWidth");
is(window.outerHeight, oldOuterHeight, "customtitlebar shouldn't change the window's outerHeight"); is(window.outerHeight, oldOuterHeight, "chromemargin shouldn't change the window's outerHeight");
is(window.innerWidth, oldOuterWidth, "if customtitlebar is set, innerWidth and outerWidth should be the same"); is(window.innerWidth, oldOuterWidth, "if chromemargin 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.innerHeight, oldOuterHeight, "if chromemargin is set, innerHeight and outerHeight should be the same");
// Wait for going full screen and back. // Wait for going full screen and back.
let sizemodeChange = waitForEvent(window, "sizemodechange"); let sizemodeChange = waitForEvent(window, "sizemodechange");
@@ -62,13 +62,13 @@ async function start() {
is(window.outerHeight, oldOuterHeight, "wrong outerHeight after fullscreen mode"); is(window.outerHeight, oldOuterHeight, "wrong outerHeight after fullscreen mode");
is(window.innerWidth, oldOuterWidth, "wrong innerWidth after fullscreen mode"); is(window.innerWidth, oldOuterWidth, "wrong innerWidth after fullscreen mode");
is(window.innerHeight, oldOuterHeight, "wrong innerHeight after fullscreen mode"); is(window.innerHeight, oldOuterHeight, "wrong innerHeight after fullscreen mode");
document.documentElement.removeAttribute("customtitlebar"); document.documentElement.removeAttribute("chromemargin");
await executeSoon(); await executeSoon();
is(window.outerWidth, oldOuterWidth, "wrong outerWidth after removing customtitlebar"); is(window.outerWidth, oldOuterWidth, "wrong outerWidth after removing chromemargin");
is(window.outerHeight, oldOuterHeight, "wrong outerHeight after removing customtitlebar"); is(window.outerHeight, oldOuterHeight, "wrong outerHeight after removing chromemargin");
is(window.innerWidth, oldInnerWidth, "wrong innerWidth after removing customtitlebar"); is(window.innerWidth, oldInnerWidth, "wrong innerWidth after removing chromemargin");
is(window.innerHeight, oldInnerHeight, "wrong innerHeight after removing customtitlebar"); is(window.innerHeight, oldInnerHeight, "wrong innerHeight after removing chromemargin");
window.arguments[0].SimpleTest.finish(); window.arguments[0].SimpleTest.finish();
window.close(); window.close();
} }

View File

@@ -940,8 +940,10 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect,
DesktopIntRect::Round(LayoutDeviceRect(GetBounds()) / scale) DesktopIntRect::Round(LayoutDeviceRect(GetBounds()) / scale)
.ToUnknownRect()); .ToUnknownRect());
// Skeleton ui is disabled when custom titlebar is off, see bug 1673092. // These match the margins set in browser-tabsintitlebar.js with
SetCustomTitlebar(true); // 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 // 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. // to do that again; the effective non-client margins haven't changed.
mNeedsNCAreaClear = false; mNeedsNCAreaClear = false;
@@ -2335,7 +2337,7 @@ void nsWindow::SetFocus(Raise aRaise, mozilla::dom::CallerType aCallerType) {
* SECTION: Bounds * SECTION: Bounds
* *
* GetBounds, GetClientBounds, GetScreenBounds, * GetBounds, GetClientBounds, GetScreenBounds,
* GetRestoredBounds, GetClientOffset, SetCustomTitlebar * GetRestoredBounds, GetClientOffset, SetNonClientMargins
* *
* Bound calculations. * Bound calculations.
* *
@@ -2521,17 +2523,49 @@ void nsWindow::SetColorScheme(const Maybe<ColorScheme>& aScheme) {
} }
LayoutDeviceIntMargin nsWindow::NormalWindowNonClientOffset() const { LayoutDeviceIntMargin nsWindow::NormalWindowNonClientOffset() const {
MOZ_ASSERT(mCustomNonClient); LayoutDeviceIntMargin nonClientOffset;
// We're dealing with a "normal" window (not maximized, minimized, or // 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 // Setting `mNonClientOffset` to 0 has the effect of leaving the default
// frame intact. Setting it to a value greater than 0 reduces the frame // frame intact. Setting it to a value greater than 0 reduces the frame
// size by that amount. // size by that amount.
//
// When using custom titlebar, we hide the titlebar and leave the default if (mNonClientMargins.top > 0) {
// frame on the other sides. nonClientOffset.top = std::min(mCaptionHeight, mNonClientMargins.top);
return LayoutDeviceIntMargin(mCaptionHeight + mVertResizeMargin, 0, 0, 0); } 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 * margins and fires off a frame changed event, which triggers an nc calc
* size windows event, kicking the changes in. * 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`. * This function calculates and populates `mNonClientOffset`.
* In our processing of `WM_NCCALCSIZE`, the frame size will be calculated * In our processing of `WM_NCCALCSIZE`, the frame size will be calculated
* as (default frame size - offset). For example, if the left frame should * as (default frame size - offset). For example, if the left frame should
* be 1 pixel narrower than the default frame size, `mNonClientOffset.left` * be 1 pixel narrower than the default frame size, `mNonClientOffset.left`
* will equal 1. * will equal 1.
* *
* For maximized, fullscreen, and minimized windows special processing takes * For maximized, fullscreen, and minimized windows, the values stored in
* place. * `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) { bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
if (!mCustomNonClient) { if (!mCustomNonClient) {
@@ -2556,12 +2600,29 @@ bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
const nsSizeMode sizeMode = mFrameState->GetSizeMode(); const nsSizeMode sizeMode = mFrameState->GetSizeMode();
const bool hasCaption = bool hasCaption =
bool(mBorderStyle & (BorderStyle::All | BorderStyle::Title | bool(mBorderStyle & (BorderStyle::All | BorderStyle::Title |
BorderStyle::Menu | BorderStyle::Default)); BorderStyle::Menu | BorderStyle::Default));
float dpi = GetDPI(); float dpi = GetDPI();
// 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, mCaptionHeight will be equal to
// `WinUtils::GetSystemMetricsForDpi(SM_CYFRAME, dpi)`
mCaptionHeight =
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 // mHorResizeMargin is the size of the default NC areas on the
// left and right sides of our window. It is calculated as // left and right sides of our window. It is calculated as
// the sum of: // the sum of:
@@ -2588,12 +2649,7 @@ bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
WinUtils::GetSystemMetricsForDpi(SM_CYFRAME, dpi) + WinUtils::GetSystemMetricsForDpi(SM_CYFRAME, dpi) +
(hasCaption ? WinUtils::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi) (hasCaption ? WinUtils::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)
: 0); : 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;
if (sizeMode == nsSizeMode_Minimized) { if (sizeMode == nsSizeMode_Minimized) {
// Use default frame size for minimized windows // 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 // makes the whole caption part of our client area, allowing us to draw
// in the whole caption area. Additionally remove the default frame from // in the whole caption area. Additionally remove the default frame from
// the left, right, and bottom. // the left, right, and bottom.
// mNonClientOffset.top = mCaptionHeight;
// 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.bottom = mVertResizeMargin; mNonClientOffset.bottom = mVertResizeMargin;
mNonClientOffset.left = mHorResizeMargin; mNonClientOffset.left = mHorResizeMargin;
mNonClientOffset.right = 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 // 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 // frame sizes for left, right and bottom since Windows will automagically
// position the edges "offscreen" for maximized windows. // 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.bottom = 0;
mNonClientOffset.left = 0; mNonClientOffset.left = 0;
mNonClientOffset.right = 0; mNonClientOffset.right = 0;
@@ -2653,23 +2708,26 @@ bool nsWindow::UpdateNonClientMargins(bool aReflowWindow) {
return true; return true;
} }
void nsWindow::SetCustomTitlebar(bool aCustomTitlebar) { nsresult nsWindow::SetNonClientMargins(const LayoutDeviceIntMargin& margins) {
if (!IsTopLevelWidget() || mBorderStyle == BorderStyle::None) { if (!IsTopLevelWidget() || mBorderStyle == BorderStyle::None) {
return; return NS_ERROR_INVALID_ARG;
} }
if (mCustomNonClient == aCustomTitlebar) { if (mNonClientMargins == margins) {
return; return NS_OK;
} }
if (mHideChrome) { if (mHideChrome) {
mCustomTitlebarOnceChromeShows = Some(aCustomTitlebar); mFutureMarginsOnceChromeShows = margins;
return; 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. // Force a reflow of content based on the new client dimensions.
if (mCustomNonClient) { if (mCustomNonClient) {
@@ -2677,10 +2735,15 @@ void nsWindow::SetCustomTitlebar(bool aCustomTitlebar) {
} else { } else {
ResetLayout(); ResetLayout();
} }
return NS_OK;
} }
void nsWindow::SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) { void nsWindow::SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) {
mCustomResizeMargin = aResizeMargin; mUseResizeMarginOverrides = true;
mHorResizeMargin = aResizeMargin;
mVertResizeMargin = aResizeMargin;
UpdateNonClientMargins();
} }
nsAutoRegion nsWindow::ComputeNonClientHRGN() { nsAutoRegion nsWindow::ComputeNonClientHRGN() {
@@ -2705,7 +2768,7 @@ nsAutoRegion nsWindow::ComputeNonClientHRGN() {
// windows non-client chrome and app non-client chrome // windows non-client chrome and app non-client chrome
// in winRgn. // in winRgn.
::GetWindowRect(mWnd, &rect); ::GetWindowRect(mWnd, &rect);
rect.top += mCaptionHeight + mVertResizeMargin; rect.top += mCaptionHeight;
rect.right -= mHorResizeMargin; rect.right -= mHorResizeMargin;
rect.bottom -= mVertResizeMargin; rect.bottom -= mVertResizeMargin;
rect.left += mHorResizeMargin; 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 // if there's nothing to "restore" it to, just use what's there now
oldChrome = mOldStyles.refOr(currentChrome); oldChrome = mOldStyles.refOr(currentChrome);
newChrome = oldChrome; newChrome = oldChrome;
if (mCustomTitlebarOnceChromeShows) { if (mFutureMarginsToUse) {
SetCustomTitlebar(mCustomTitlebarOnceChromeShows.extract()); SetNonClientMargins(mFutureMarginsOnceChromeShows);
MOZ_ASSERT(!mCustomTitlebarOnceChromeShows);
} }
} }
@@ -4922,9 +4984,8 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
* sending the message with an updated title * sending the message with an updated title
*/ */
if (mSendingSetText || !mCustomNonClient) { if (mSendingSetText || !mCustomNonClient || mNonClientMargins.top == -1)
break; break;
}
{ {
// From msdn, the way around this is to disable the visible state // From msdn, the way around this is to disable the visible state
@@ -5867,8 +5928,7 @@ void nsWindow::FinishLiveResizing(ResizeState aNewState) {
LayoutDeviceIntMargin nsWindow::NonClientSizeMargin( LayoutDeviceIntMargin nsWindow::NonClientSizeMargin(
const LayoutDeviceIntMargin& aNonClientOffset) const { const LayoutDeviceIntMargin& aNonClientOffset) const {
return LayoutDeviceIntMargin( return LayoutDeviceIntMargin(mCaptionHeight - aNonClientOffset.top,
mCaptionHeight + mVertResizeMargin - aNonClientOffset.top,
mHorResizeMargin - aNonClientOffset.right, mHorResizeMargin - aNonClientOffset.right,
mVertResizeMargin - aNonClientOffset.bottom, mVertResizeMargin - aNonClientOffset.bottom,
mHorResizeMargin - aNonClientOffset.left); mHorResizeMargin - aNonClientOffset.left);
@@ -5924,12 +5984,6 @@ int32_t nsWindow::ClientMarginHitTestPoint(int32_t aX, int32_t aY) {
borderSize.EnsureAtLeast( borderSize.EnsureAtLeast(
LayoutDeviceIntMargin(mVertResizeMargin, mHorResizeMargin, LayoutDeviceIntMargin(mVertResizeMargin, mHorResizeMargin,
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 top = false;
bool bottom = false; bool bottom = false;

View File

@@ -293,7 +293,7 @@ class nsWindow final : public nsBaseWidget {
TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override; TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override;
void SetTransparencyMode(TransparencyMode aMode) override; void SetTransparencyMode(TransparencyMode aMode) override;
TransparencyMode GetTransparencyMode() override; TransparencyMode GetTransparencyMode() override;
void SetCustomTitlebar(bool) override; nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override;
void SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) override; void SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) override;
void UpdateWindowDraggingRegion( void UpdateWindowDraggingRegion(
const LayoutDeviceIntRegion& aRegion) override; const LayoutDeviceIntRegion& aRegion) override;
@@ -802,20 +802,23 @@ class nsWindow final : public nsBaseWidget {
// Non-client margin settings // Non-client margin settings
// Pre-calculated outward offset applied to default frames // Pre-calculated outward offset applied to default frames
LayoutDeviceIntMargin mNonClientOffset; 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; bool mCustomNonClient = false;
// Whether we want to draw to the titlebar once the chrome shows. (Always // Indicates custom resize margins are in effect
// Nothing if mHideChrome is false). bool mUseResizeMarginOverrides = false;
mozilla::Maybe<bool> mCustomTitlebarOnceChromeShows;
// Width of the left and right portions of the resize region // Width of the left and right portions of the resize region
mozilla::LayoutDeviceIntCoord mHorResizeMargin; mozilla::LayoutDeviceIntCoord mHorResizeMargin;
// Height of the top and bottom portions of the resize region // Height of the top and bottom portions of the resize region
mozilla::LayoutDeviceIntCoord mVertResizeMargin; mozilla::LayoutDeviceIntCoord mVertResizeMargin;
// Height of the caption plus border // Height of the caption plus border
mozilla::LayoutDeviceIntCoord mCaptionHeight; mozilla::LayoutDeviceIntCoord mCaptionHeight;
// Custom extra resize margin width.
mozilla::LayoutDeviceIntCoord mCustomResizeMargin{0};
// not yet set, will be calculated on first use // not yet set, will be calculated on first use
double mDefaultScale = -1.0; double mDefaultScale = -1.0;

View File

@@ -235,7 +235,7 @@ STATIC_ATOMS = [
Atom("childList", "childList"), Atom("childList", "childList"),
Atom("child_item_count", "child-item-count"), Atom("child_item_count", "child-item-count"),
Atom("choose", "choose"), Atom("choose", "choose"),
Atom("customtitlebar", "customtitlebar"), Atom("chromemargin", "chromemargin"),
Atom("exposeToUntrustedContent", "exposeToUntrustedContent"), Atom("exposeToUntrustedContent", "exposeToUntrustedContent"),
Atom("circ", "circ"), Atom("circ", "circ"),
Atom("circle", "circle"), Atom("circle", "circle"),

View File

@@ -1501,7 +1501,7 @@ void AppWindow::SyncAttributesToWidget() {
nsAutoString attr; 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. // and MacOS). But we might want to keep it.
const LayoutDeviceIntSize oldClientSize = mWindow->GetClientSize(); const LayoutDeviceIntSize oldClientSize = mWindow->GetClientSize();
// We have to check now whether we want to restore the client size, as any // 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; bool maintainClientSize = mDominantClientSize;
// "hidechrome" attribute // "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); NS_ENSURE_TRUE_VOID(mWindow);
// "customtitlebar" attribute // "chromemargin" attribute
// FIXME(emilio): This should arguably be nsIntMargin margins;
// SetCustomTitlebar(windowElement->GetBoolAttr(...)), but that breaks with windowElement->GetAttribute(u"chromemargin"_ns, attr);
// the early blank window which sets the custom titlebar via if (nsContentUtils::ParseIntMarginValue(attr, margins)) {
// nsIDOMWindowUtils... mWindow->SetNonClientMargins(
if (windowElement->GetBoolAttr(nsGkAtoms::customtitlebar)) { LayoutDeviceIntMargin::FromUnknownMargin(margins));
mWindow->SetCustomTitlebar(true);
} }
NS_ENSURE_TRUE_VOID(mWindow); NS_ENSURE_TRUE_VOID(mWindow);
@@ -1547,17 +1550,18 @@ void AppWindow::SyncAttributesToWidget() {
} }
// "drawtitle" attribute // "drawtitle" attribute
mWindow->SetDrawsTitle(windowElement->GetBoolAttr(nsGkAtoms::drawtitle)); windowElement->GetAttribute(u"drawtitle"_ns, attr);
mWindow->SetDrawsTitle(attr.LowerCaseEqualsLiteral("true"));
NS_ENSURE_TRUE_VOID(mWindow); NS_ENSURE_TRUE_VOID(mWindow);
// "toggletoolbar" attribute // "toggletoolbar" attribute
mWindow->SetShowsToolbarButton( windowElement->GetAttribute(u"toggletoolbar"_ns, attr);
windowElement->HasAttribute(u"toggletoolbar"_ns)); mWindow->SetShowsToolbarButton(attr.LowerCaseEqualsLiteral("true"));
NS_ENSURE_TRUE_VOID(mWindow); NS_ENSURE_TRUE_VOID(mWindow);
// "macnativefullscreen" attribute // "macnativefullscreen" attribute
mWindow->SetSupportsNativeFullscreen( windowElement->GetAttribute(u"macnativefullscreen"_ns, attr);
windowElement->HasAttribute(u"macnativefullscreen"_ns)); mWindow->SetSupportsNativeFullscreen(attr.LowerCaseEqualsLiteral("true"));
NS_ENSURE_TRUE_VOID(mWindow); NS_ENSURE_TRUE_VOID(mWindow);
// "macanimationtype" attribute // "macanimationtype" attribute
@@ -2342,7 +2346,7 @@ NS_IMETHODIMP
AppWindow::BeforeStartLayout() { AppWindow::BeforeStartLayout() {
ApplyChromeFlags(); ApplyChromeFlags();
// Ordering here is important, loading width/height values in // 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). // we need to translate outer to inner sizes).
SyncAttributesToWidget(); SyncAttributesToWidget();
LoadPersistentWindowState(); LoadPersistentWindowState();