Bug 909779 - Toolbar Overflow isn't initialized correctly on newly opened windows. r=Gijs,jaws

This commit is contained in:
Jared Wein 2013-10-22 15:07:56 +02:00
parent a2d8e8b929
commit 1117925a69
4 changed files with 85 additions and 23 deletions

View File

@ -13,6 +13,8 @@
<stylesheet src="chrome://global/skin/toolbar.css"/>
</resources>
<implementation implements="nsIAccessibleProvider">
<field name="overflowedDuringConstruction">null</field>
<property name="accessibleType" readonly="true">
<getter>
return Components.interfaces.nsIAccessibleProvider.XULToolbar;
@ -20,6 +22,15 @@
</property>
<constructor><![CDATA[
let scope = {};
Cu.import("resource:///modules/CustomizableUI.jsm", scope);
// Add an early overflow event listener that will mark if the
// toolbar overflowed during construction.
if (scope.CustomizableUI.isAreaOverflowable(this.id)) {
this.addEventListener("overflow", this);
this.addEventListener("underflow", this);
}
if (document.readyState == "complete") {
this._init();
} else {
@ -61,6 +72,21 @@
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.type == "overflow" && aEvent.detail > 0) {
if (this.overflowable && this.overflowable.initialized) {
this.overflowable.onOverflow(aEvent);
} else {
this.overflowedDuringConstruction = aEvent;
}
} else if (aEvent.type == "underflow" && aEvent.detail > 0) {
this.overflowedDuringConstruction = null;
}
]]></body>
</method>
<method name="insertItem">
<parameter name="aId"/>
<parameter name="aBeforeElt"/>

View File

@ -2075,7 +2075,12 @@ this.CustomizableUI = {
},
onWidgetDrag: function(aWidgetId, aArea) {
CustomizableUIInternal.notifyListeners("onWidgetDrag", aWidgetId, aArea);
}
},
isAreaOverflowable: function(aAreaId) {
let area = gAreas.get(aAreaId);
return area ? area.get("type") == this.TYPE_TOOLBAR && area.get("overflowable")
: false;
},
};
Object.freeze(this.CustomizableUI);
@ -2299,13 +2304,12 @@ function OverflowableToolbar(aToolbarNode) {
this._collapsed = new Map();
this._enabled = true;
this._toolbar.customizationTarget.addEventListener("overflow", this);
this._toolbar.setAttribute("overflowable", "true");
Services.obs.addObserver(this, "browser-delayed-startup-finished", false);
}
OverflowableToolbar.prototype = {
_initialized: false,
initialized: false,
_forceOnOverflow: false,
observe: function(aSubject, aTopic, aData) {
@ -2338,19 +2342,21 @@ OverflowableToolbar.prototype = {
CustomizableUI.addListener(this);
this._initialized = true;
// The 'overflow' event may have been fired before init was called.
if (this._forceOnOverflow) {
this._onOverflow();
if (this._toolbar.overflowedDuringConstruction) {
this.onOverflow(this._toolbar.overflowedDuringConstruction);
this._toolbar.overflowedDuringConstruction = null;
}
this.initialized = true;
},
uninit: function() {
this._toolbar.customizationTarget.removeEventListener("overflow", this);
this._toolbar.removeEventListener("overflow", this._toolbar);
this._toolbar.removeEventListener("underflow", this._toolbar);
this._toolbar.removeAttribute("overflowable");
if (!this._initialized) {
if (!this.initialized) {
Services.obs.removeObserver(this, "browser-delayed-startup-finished");
return;
}
@ -2369,16 +2375,6 @@ OverflowableToolbar.prototype = {
handleEvent: function(aEvent) {
switch(aEvent.type) {
case "overflow":
// Ignore vertical overflow:
if (aEvent.detail > 0) {
if (this._initialized) {
this._onOverflow();
} else {
this._forceOnOverflow = true;
}
}
break;
case "resize":
this._onResize(aEvent);
break;
@ -2413,13 +2409,14 @@ OverflowableToolbar.prototype = {
this._chevron.open = false;
},
_onOverflow: function() {
if (!this._enabled)
onOverflow: function(aEvent) {
if (!this._enabled ||
(aEvent && aEvent.target != this._toolbar.customizationTarget))
return;
let child = this._target.lastChild;
while (child && this._target.clientWidth < this._target.scrollWidth) {
while (child && this._target.scrollLeftMax > 0) {
let prevChild = child.previousSibling;
if (child.getAttribute("overflows") != "false") {
@ -2510,7 +2507,7 @@ OverflowableToolbar.prototype = {
_enable: function() {
this._enabled = true;
this._onOverflow();
this.onOverflow();
},
onWidgetBeforeDOMChange: function(aNode, aNextNode, aContainer) {

View File

@ -16,6 +16,7 @@ support-files =
[browser_890262_destroyWidget_after_add_to_panel.js]
[browser_892955_isWidgetRemovable_for_removed_widgets.js]
[browser_892956_destroyWidget_defaultPlacements.js]
[browser_909779_overflow_toolbars_new_window.js]
[browser_913972_currentset_overflow.js]
[browser_914138_widget_API_overflowable_toolbar.js]

View File

@ -0,0 +1,38 @@
/* 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/. */
let gTests = [
{
desc: "Resize to a small window, open a new window, check that new window handles overflow properly",
run: function() {
let originalWindowWidth = window.outerWidth;
let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
let oldChildCount = navbar.customizationTarget.childElementCount;
window.resizeTo(400, window.outerHeight);
yield waitForCondition(() => navbar.hasAttribute("overflowing"));
ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
ok(navbar.customizationTarget.childElementCount < oldChildCount, "Should have fewer children.");
let newWindow = yield openAndLoadWindow();
let otherNavBar = newWindow.document.getElementById(CustomizableUI.AREA_NAVBAR);
yield waitForCondition(() => otherNavBar.hasAttribute("overflowing"));
ok(otherNavBar.hasAttribute("overflowing"), "Other window should have an overflowing toolbar.");
newWindow.close();
window.resizeTo(originalWindowWidth, window.outerHeight);
yield waitForCondition(() => !navbar.hasAttribute("overflowing"));
ok(!navbar.hasAttribute("overflowing"), "Should no longer have an overflowing toolbar.");
}
}
];
function asyncCleanup() {
yield resetCustomization();
}
function test() {
waitForExplicitFinish();
runTests(gTests, asyncCleanup);
}