Bug 659594 - Use MozAfterPaint to redraw thumbnails r=tim

This commit is contained in:
Raymond Lee 2011-11-29 15:10:00 +08:00
Родитель 475c879b48
Коммит 7d24f33b08
8 изменённых файлов: 148 добавлений и 52 удалений

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

@ -74,12 +74,21 @@ let WindowEventHandler = {
// as quick as possible, switch the selected tab and hide the tabview // as quick as possible, switch the selected tab and hide the tabview
// before the modal dialog is shown // before the modal dialog is shown
sendSyncMessage("Panorama:DOMWillOpenModalDialog"); sendSyncMessage("Panorama:DOMWillOpenModalDialog");
},
// ----------
// Function: onMozAfterPaint
// Sends an asynchronous message when the "onMozAfterPaint" event
// is fired.
onMozAfterPaint: function WEH_onMozAfterPaint(event) {
sendAsyncMessage("Panorama:MozAfterPaint");
} }
}; };
// add event listeners // add event listeners
addEventListener("DOMContentLoaded", WindowEventHandler.onDOMContentLoaded, false); addEventListener("DOMContentLoaded", WindowEventHandler.onDOMContentLoaded, false);
addEventListener("DOMWillOpenModalDialog", WindowEventHandler.onDOMWillOpenModalDialog, false); addEventListener("DOMWillOpenModalDialog", WindowEventHandler.onDOMWillOpenModalDialog, false);
addEventListener("MozAfterPaint", WindowEventHandler.onMozAfterPaint, false);
// ---------- // ----------
// WindowMessageHandler // WindowMessageHandler
@ -90,8 +99,8 @@ let WindowMessageHandler = {
// Function: isDocumentLoaded // Function: isDocumentLoaded
// Checks if the currently active document is loaded. // Checks if the currently active document is loaded.
isDocumentLoaded: function WMH_isDocumentLoaded(cx) { isDocumentLoaded: function WMH_isDocumentLoaded(cx) {
let isLoaded = (content.document.readyState == "complete" && let readyState = content.document.readyState;
!webProgress.isLoadingDocument); let isLoaded = (readyState != "uninitalized" && !webProgress.isLoadingDocument);
sendAsyncMessage(cx.name, {isLoaded: isLoaded}); sendAsyncMessage(cx.name, {isLoaded: isLoaded});
} }
@ -187,3 +196,4 @@ let WebProgressListener = {
// add web progress listener // add web progress listener
webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW); webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);

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

@ -794,6 +794,7 @@ let TabItems = {
tempCanvas: null, tempCanvas: null,
_reconnectingPaused: false, _reconnectingPaused: false,
tabItemPadding: {}, tabItemPadding: {},
_mozAfterPaintHandler: null,
// ---------- // ----------
// Function: toString // Function: toString
@ -825,6 +826,10 @@ let TabItems = {
this.tempCanvas.width = 150; this.tempCanvas.width = 150;
this.tempCanvas.height = 112; this.tempCanvas.height = 112;
let mm = gWindow.messageManager;
this._mozAfterPaintHandler = this.onMozAfterPaint.bind(this);
mm.addMessageListener("Panorama:MozAfterPaint", this._mozAfterPaintHandler);
// When a tab is opened, create the TabItem // When a tab is opened, create the TabItem
this._eventListeners.open = function (event) { this._eventListeners.open = function (event) {
let tab = event.target; let tab = event.target;
@ -874,6 +879,9 @@ let TabItems = {
// ---------- // ----------
// Function: uninit // Function: uninit
uninit: function TabItems_uninit() { uninit: function TabItems_uninit() {
let mm = gWindow.messageManager;
mm.removeMessageListener("Panorama:MozAfterPaint", this._mozAfterPaintHandler);
for (let name in this._eventListeners) { for (let name in this._eventListeners) {
AllTabs.unregister(name, this._eventListeners[name]); AllTabs.unregister(name, this._eventListeners[name]);
} }
@ -912,20 +920,33 @@ let TabItems = {
return this._fragment; return this._fragment;
}, },
// ---------- // Function: _isComplete
// Function: isComplete // Checks whether the xul:tab has fully loaded and calls a callback with a
// Return whether the xul:tab has fully loaded. // boolean indicates whether the tab is loaded or not.
isComplete: function TabItems_isComplete(tab) { _isComplete: function TabItems__isComplete(tab, callback) {
// If our readyState is complete, but we're showing about:blank,
// and we're not loading about:blank, it means we haven't really
// started loading. This can happen to the first few tabs in a
// page.
Utils.assertThrow(tab, "tab"); Utils.assertThrow(tab, "tab");
return (
tab.linkedBrowser.contentDocument.readyState == 'complete' && let mm = tab.linkedBrowser.messageManager;
!(tab.linkedBrowser.contentDocument.URL == 'about:blank' && let message = "Panorama:isDocumentLoaded";
tab._tabViewTabItem.url != 'about:blank')
); mm.addMessageListener(message, function onMessage(cx) {
mm.removeMessageListener(cx.name, onMessage);
callback(cx.json.isLoaded);
});
mm.sendAsyncMessage(message);
},
// ----------
// Function: _onMozAfterPaint
// Called when a web page is painted.
onMozAfterPaint: function TabItems_onMozAfterPaint(cx) {
let index = gBrowser.browsers.indexOf(cx.target);
if (index == -1)
return;
let tab = gBrowser.tabs[index];
if (!tab.pinned)
this.update(tab);
}, },
// ---------- // ----------
@ -1009,12 +1030,8 @@ let TabItems = {
} }
// ___ Make sure the tab is complete and ready for updating. // ___ Make sure the tab is complete and ready for updating.
if (!this.isComplete(tab) && (!options || !options.force)) { let self = this;
// If it's incomplete, stick it on the end of the queue let updateCanvas = function TabItems__update_updateCanvas(tabItem) {
this._tabsWaitingForUpdate.push(tab);
return;
}
// ___ thumbnail // ___ thumbnail
let $canvas = tabItem.$canvas; let $canvas = tabItem.$canvas;
if (!tabItem.canvasSizeForced) { if (!tabItem.canvasSizeForced) {
@ -1026,8 +1043,8 @@ let TabItems = {
} }
} }
this._lastUpdateTime = Date.now(); self._lastUpdateTime = Date.now();
tabItem._lastTabUpdateTime = this._lastUpdateTime; tabItem._lastTabUpdateTime = self._lastUpdateTime;
tabItem.tabCanvas.paint(); tabItem.tabCanvas.paint();
tabItem.saveThumbnail(); tabItem.saveThumbnail();
@ -1038,6 +1055,16 @@ let TabItems = {
// ___ notify subscribers that a full update has completed. // ___ notify subscribers that a full update has completed.
tabItem._sendToSubscribers("updated"); tabItem._sendToSubscribers("updated");
};
if (options && options.force)
updateCanvas(tabItem);
else
this._isComplete(tab, function TabItems__update_isComplete(isComplete) {
if (isComplete)
updateCanvas(tabItem);
else
self._tabsWaitingForUpdate.push(tab);
});
} catch(e) { } catch(e) {
Utils.log(e); Utils.log(e);
} }

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

@ -151,6 +151,7 @@ _BROWSER_FILES = \
browser_tabview_bug655269.js \ browser_tabview_bug655269.js \
browser_tabview_bug656778.js \ browser_tabview_bug656778.js \
browser_tabview_bug656913.js \ browser_tabview_bug656913.js \
browser_tabview_bug659594.js \
browser_tabview_bug662266.js \ browser_tabview_bug662266.js \
browser_tabview_bug663421.js \ browser_tabview_bug663421.js \
browser_tabview_bug665502.js \ browser_tabview_bug665502.js \

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

@ -54,10 +54,17 @@ function test() {
let test = tests.shift(); let test = tests.shift();
let tab = win.gBrowser.tabs[0]; let tab = win.gBrowser.tabs[0];
tab.linkedBrowser.addEventListener('load', function onLoad() { let mm = tab.linkedBrowser.messageManager;
tab.linkedBrowser.removeEventListener('load', onLoad, true);
mm.addMessageListener("Panorama:DOMContentLoaded", function onLoad(cx) {
mm.removeMessageListener(cx.name, onLoad);
let tabItem = tab._tabViewTabItem;
tabItem.addSubscriber("updated", function onUpdated() {
tabItem.removeSubscriber("updated", onUpdated);
checkUrl(test); checkUrl(test);
}, true); });
});
tab.linkedBrowser.loadURI(test.url); tab.linkedBrowser.loadURI(test.url);
} }

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

@ -134,11 +134,14 @@ function updateAndCheck() {
let tabItems = contentWindow.TabItems.getItems(); let tabItems = contentWindow.TabItems.getItems();
tabItems.forEach(function(tabItem) { tabItems.forEach(function(tabItem) {
contentWindow.TabItems._update(tabItem.tab); tabItem.addSubscriber("updated", function onUpdated() {
tabItem.removeSubscriber("updated", onUpdated);
ok(!tabItem.isShowingCachedData(), ok(!tabItem.isShowingCachedData(),
"Tab item is not showing cached data anymore. " + "Tab item is not showing cached data anymore. " +
tabItem.tab.linkedBrowser.currentURI.spec); tabItem.tab.linkedBrowser.currentURI.spec);
}); });
contentWindow.TabItems.update(tabItem.tab);
});
// clean up and finish // clean up and finish
restoredWin.close(); restoredWin.close();

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

@ -0,0 +1,39 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
newWindowWithTabView(function(win) {
let numTabsToUpdate = 2;
showTabView(function() {
let contentWindow = win.TabView.getContentWindow();
let groupItem = contentWindow.GroupItems.groupItems[0];
groupItem.getChildren().forEach(function(tabItem) {
tabItem.addSubscriber("updated", function onUpdated() {
tabItem.removeSubscriber("updated", onUpdated);
if (--numTabsToUpdate == 0)
finish();
});
contentWindow.TabItems.update(tabItem.tab);
});
}, win);
}, function(win) {
BrowserOffline.toggleOfflineStatus();
ok(Services.io.offline, "It is now offline");
let originalTab = win.gBrowser.tabs[0];
originalTab.linkedBrowser.loadURI("http://www.example.com/foo");
win.gBrowser.addTab("http://www.example.com/bar");
registerCleanupFunction(function () {
if (Services.io.offline)
BrowserOffline.toggleOfflineStatus();
win.close();
});
});
}

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

@ -26,14 +26,13 @@ function onTabViewWindowLoaded(win) {
// procreate! // procreate!
contentWindow.UI.setActive(group); contentWindow.UI.setActive(group);
for (var i=0; i<7; i++) { for (var i=0; i<7; i++) {
win.gBrowser.loadOneTab('about:blank#' + i, {inBackground: true}); win.gBrowser.loadOneTab('http://example.com#' + i, {inBackground: true});
} }
let children = group.getChildren(); let children = group.getChildren();
// Wait until they all update because, once updated, they will notice that they // Wait until they all update because, once updated, they will notice that they
// don't have favicons and this will change their styling at some unknown time. // don't have favicons and this will change their styling at some unknown time.
afterAllTabItemsUpdated(function() { afterAllTabItemsUpdated(function() {
ok(!group.shouldStack(group._children.length), "The group should not stack."); ok(!group.shouldStack(group._children.length), "The group should not stack.");
is(expander[0].style.display, "none", "The expander is hidden."); is(expander[0].style.display, "none", "The expander is hidden.");

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

@ -69,12 +69,22 @@ function closeGroupItem(groupItem, callback) {
function afterAllTabItemsUpdated(callback, win) { function afterAllTabItemsUpdated(callback, win) {
win = win || window; win = win || window;
let tabItems = win.document.getElementById("tab-view").contentWindow.TabItems; let tabItems = win.document.getElementById("tab-view").contentWindow.TabItems;
let counter = 0;
for (let a = 0; a < win.gBrowser.tabs.length; a++) { for (let a = 0; a < win.gBrowser.tabs.length; a++) {
let tabItem = win.gBrowser.tabs[a]._tabViewTabItem; let tabItem = win.gBrowser.tabs[a]._tabViewTabItem;
if (tabItem) if (tabItem) {
tabItems._update(win.gBrowser.tabs[a]); let tab = win.gBrowser.tabs[a];
counter++;
tabItem.addSubscriber("updated", function onUpdated() {
tabItem.removeSubscriber("updated", onUpdated);
if (--counter == 0)
callback();
});
tabItems.update(tab);
} }
}
if (counter == 0)
callback(); callback();
} }