зеркало из https://github.com/mozilla/pjs.git
Bug 594958 - Tab thumbnails sometimes have gray (now black) bars at the bottom [r=ian, a=blocking2.0:final+]
This commit is contained in:
Родитель
bfbd3de5cb
Коммит
700d4ee717
|
@ -808,7 +808,7 @@ let TabItems = {
|
||||||
// 150 pixels is an empirical size, below which FF's drawWindow()
|
// 150 pixels is an empirical size, below which FF's drawWindow()
|
||||||
// algorithm breaks down
|
// algorithm breaks down
|
||||||
this.tempCanvas.width = 150;
|
this.tempCanvas.width = 150;
|
||||||
this.tempCanvas.height = 150;
|
this.tempCanvas.height = 112;
|
||||||
|
|
||||||
this.tabsProgressListener = {
|
this.tabsProgressListener = {
|
||||||
onStateChange: function(browser, webProgress, request, stateFlags, status) {
|
onStateChange: function(browser, webProgress, request, stateFlags, status) {
|
||||||
|
@ -1281,69 +1281,101 @@ TabCanvas.prototype = {
|
||||||
if (!w || !h)
|
if (!w || !h)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let fromWin = this.tab.linkedBrowser.contentWindow;
|
if (!this.tab.linkedBrowser.contentWindow) {
|
||||||
if (fromWin == null) {
|
Utils.log('no tab.linkedBrowser.contentWindow in TabCanvas.paint()');
|
||||||
Utils.log('null fromWin in paint');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ctx = this.canvas.getContext("2d");
|
||||||
let tempCanvas = TabItems.tempCanvas;
|
let tempCanvas = TabItems.tempCanvas;
|
||||||
|
let bgColor = '#fff';
|
||||||
|
|
||||||
if (w < tempCanvas.width) {
|
if (w < tempCanvas.width) {
|
||||||
// Small draw case where nearest-neighbor algorithm breaks down in Windows
|
// Small draw case where nearest-neighbor algorithm breaks down in Windows
|
||||||
// First draw to a larger canvas (150px wide), and then draw that image
|
// First draw to a larger canvas (150px wide), and then draw that image
|
||||||
// to the destination canvas.
|
// to the destination canvas.
|
||||||
|
let tempCtx = tempCanvas.getContext("2d");
|
||||||
var tempCtx = tempCanvas.getContext("2d");
|
this._drawWindow(tempCtx, tempCanvas.width, tempCanvas.height, bgColor);
|
||||||
|
|
||||||
let canvW = tempCanvas.width;
|
// Now copy to tabitem canvas.
|
||||||
let canvH = (h/w) * canvW;
|
try {
|
||||||
|
this._fillCanvasBackground(ctx, w, h, bgColor);
|
||||||
var scaler = canvW/fromWin.innerWidth;
|
ctx.drawImage(tempCanvas, 0, 0, w, h);
|
||||||
|
} catch (e) {
|
||||||
tempCtx.save();
|
|
||||||
tempCtx.clearRect(0,0,tempCanvas.width,tempCanvas.height);
|
|
||||||
tempCtx.scale(scaler, scaler);
|
|
||||||
try{
|
|
||||||
tempCtx.drawWindow(fromWin, fromWin.scrollX, fromWin.scrollY,
|
|
||||||
canvW/scaler, canvH/scaler, "#fff");
|
|
||||||
} catch(e) {
|
|
||||||
Utils.error('paint', e);
|
Utils.error('paint', e);
|
||||||
}
|
}
|
||||||
tempCtx.restore();
|
|
||||||
|
|
||||||
// Now copy to tabitem canvas. No save/restore necessary.
|
|
||||||
var destCtx = this.canvas.getContext("2d");
|
|
||||||
try{
|
|
||||||
// the tempcanvas is square, so draw it as a square.
|
|
||||||
destCtx.drawImage(tempCanvas, 0, 0, w, w);
|
|
||||||
} catch(e) {
|
|
||||||
Utils.error('paint', e);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// General case where nearest neighbor algorithm looks good
|
// General case where nearest neighbor algorithm looks good
|
||||||
// Draw directly to the destination canvas
|
// Draw directly to the destination canvas
|
||||||
|
this._drawWindow(ctx, w, h, bgColor);
|
||||||
var ctx = this.canvas.getContext("2d");
|
|
||||||
|
|
||||||
var scaler = w/fromWin.innerWidth;
|
|
||||||
|
|
||||||
// TODO: Potentially only redraw the dirty rect? (Is it worth it?)
|
|
||||||
|
|
||||||
ctx.save();
|
|
||||||
ctx.scale(scaler, scaler);
|
|
||||||
try{
|
|
||||||
ctx.drawWindow(fromWin, fromWin.scrollX, fromWin.scrollY,
|
|
||||||
w/scaler, h/scaler, "#fff",
|
|
||||||
Ci.nsIDOMCanvasRenderingContext2D.DRAWWINDOW_DO_NOT_FLUSH);
|
|
||||||
} catch(e) {
|
|
||||||
Utils.error('paint', e);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.restore();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
// Function: _fillCanvasBackground
|
||||||
|
// Draws a rectangle of <width>x<height> with color <bgColor> to the given
|
||||||
|
// canvas context.
|
||||||
|
_fillCanvasBackground: function TabCanvas__fillCanvasBackground(ctx, width, height, bgColor) {
|
||||||
|
ctx.fillStyle = bgColor;
|
||||||
|
ctx.fillRect(0, 0, width, height);
|
||||||
|
},
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
// Function: _drawWindow
|
||||||
|
// Draws contents of the tabs' browser window to the given canvas context.
|
||||||
|
_drawWindow: function TabCanvas__drawWindow(ctx, width, height, bgColor) {
|
||||||
|
this._fillCanvasBackground(ctx, width, height, bgColor);
|
||||||
|
|
||||||
|
let rect = this._calculateClippingRect(width, height);
|
||||||
|
let scaler = width / rect.width;
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.scale(scaler, scaler);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let win = this.tab.linkedBrowser.contentWindow;
|
||||||
|
ctx.drawWindow(win, rect.left, rect.top, rect.width, rect.height,
|
||||||
|
bgColor, ctx.DRAWWINDOW_DO_NOT_FLUSH);
|
||||||
|
} catch (e) {
|
||||||
|
Utils.error('paint', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.restore();
|
||||||
|
},
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
// Function: _calculateClippingRect
|
||||||
|
// Calculate the clipping rect that will be projected to the tab's
|
||||||
|
// thumbnail canvas.
|
||||||
|
_calculateClippingRect: function TabCanvas__calculateClippingRect(origWidth, origHeight) {
|
||||||
|
let win = this.tab.linkedBrowser.contentWindow;
|
||||||
|
let body = win.document.body;
|
||||||
|
|
||||||
|
let maxWidth = win.innerWidth - 25;
|
||||||
|
let maxHeight = win.innerHeight;
|
||||||
|
|
||||||
|
if (body) {
|
||||||
|
maxWidth = Math.max(maxWidth, body.scrollWidth - win.scrollX);
|
||||||
|
maxHeight = Math.max(maxHeight, body.scrollHeight - win.scrollY);
|
||||||
|
}
|
||||||
|
|
||||||
|
let height = Math.min(maxHeight, Math.floor(origHeight * maxWidth / origWidth));
|
||||||
|
let width = Math.floor(origWidth * height / origHeight);
|
||||||
|
|
||||||
|
// very short pages in combination with a very wide browser window force us
|
||||||
|
// to extend the clipping rect and add some empty space around the thumb
|
||||||
|
let factor = 0.7;
|
||||||
|
if (width < maxWidth * factor) {
|
||||||
|
width = maxWidth * factor;
|
||||||
|
height = Math.floor(origHeight * width / origWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
let left = win.scrollX + Math.max(0, Math.round((maxWidth - width) / 2));
|
||||||
|
let top = win.scrollY;
|
||||||
|
|
||||||
|
return new Rect(left, top, width, height);
|
||||||
|
},
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
// Function: toImageData
|
// Function: toImageData
|
||||||
toImageData: function TabCanvas_toImageData() {
|
toImageData: function TabCanvas_toImageData() {
|
||||||
|
|
|
@ -57,6 +57,7 @@ _BROWSER_FILES = \
|
||||||
browser_tabview_bug589324.js \
|
browser_tabview_bug589324.js \
|
||||||
browser_tabview_bug590606.js \
|
browser_tabview_bug590606.js \
|
||||||
browser_tabview_bug591706.js \
|
browser_tabview_bug591706.js \
|
||||||
|
browser_tabview_bug594958.js \
|
||||||
browser_tabview_bug595191.js \
|
browser_tabview_bug595191.js \
|
||||||
browser_tabview_bug595436.js \
|
browser_tabview_bug595436.js \
|
||||||
browser_tabview_bug595518.js \
|
browser_tabview_bug595518.js \
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
let win;
|
||||||
|
let cw;
|
||||||
|
|
||||||
|
let getGroupItem = function (index) {
|
||||||
|
return cw.GroupItems.groupItems[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
let newWindow = function (callback) {
|
||||||
|
newWindowWithTabView(function (tvwin) {
|
||||||
|
registerCleanupFunction(function () {
|
||||||
|
if (!tvwin.closed)
|
||||||
|
tvwin.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
win = tvwin;
|
||||||
|
cw = win.TabView.getContentWindow();
|
||||||
|
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let finishTest = function () {
|
||||||
|
win.close();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
// very long page that produces black bars at the right
|
||||||
|
let html1 = '<html><body style="background-color: #00f;">' +
|
||||||
|
'<div style="background: #fff; width: 95%; height: 10000px; ' +
|
||||||
|
' margin: 0 auto;"></div></body></html>';
|
||||||
|
|
||||||
|
// very short page that produces black bars at the bottom
|
||||||
|
let html2 = '<html><body style="background-color: #00f;"></body></html>';
|
||||||
|
|
||||||
|
let tests = [{
|
||||||
|
url: 'data:text/html,' + html1,
|
||||||
|
colors: [
|
||||||
|
{right: [0, 0, 255], bottom: [255, 255, 255]},
|
||||||
|
{right: [0, 0, 255], bottom: [255, 255, 255]},
|
||||||
|
{right: [0, 0, 255], bottom: [255, 255, 255]}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
url: 'about:blank',
|
||||||
|
colors: [
|
||||||
|
{right: [255, 255, 255], bottom: [255, 255, 255]},
|
||||||
|
{right: [255, 255, 255], bottom: [255, 255, 255]},
|
||||||
|
{right: [255, 255, 255], bottom: [255, 255, 255]}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
url: 'data:text/html,' + html2,
|
||||||
|
colors: [
|
||||||
|
{right: [0, 0, 255], bottom: [0, 0, 255]},
|
||||||
|
{right: [0, 0, 255], bottom: [255, 255, 255]},
|
||||||
|
{right: [0, 0, 255], bottom: [0, 0, 255]}
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
|
||||||
|
let next = function () {
|
||||||
|
if (!tests.length) {
|
||||||
|
finishTest();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let test = tests.shift();
|
||||||
|
let tab = win.gBrowser.tabs[0];
|
||||||
|
|
||||||
|
tab.linkedBrowser.addEventListener('load', function onLoad() {
|
||||||
|
tab.linkedBrowser.removeEventListener('load', onLoad, true);
|
||||||
|
checkUrl(test);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
tab.linkedBrowser.loadURI(test.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
let checkUrl = function (test) {
|
||||||
|
let sizes = [[-400, 0], [800, -200], [-400, 200]];
|
||||||
|
|
||||||
|
let nextSize = function () {
|
||||||
|
if (!sizes.length) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = sizes.shift();
|
||||||
|
let colors = test.colors.shift();
|
||||||
|
let groupItem = getGroupItem(0);
|
||||||
|
|
||||||
|
let checkWithSmallItemSize = function () {
|
||||||
|
groupItem.setSize(150, 150, true);
|
||||||
|
groupItem.setUserSize();
|
||||||
|
|
||||||
|
afterAllTabItemsUpdated(function () {
|
||||||
|
checkPixelColors(test.url, colors, nextSize);
|
||||||
|
}, win);
|
||||||
|
}
|
||||||
|
|
||||||
|
let checkWithNormalItemSize = function () {
|
||||||
|
groupItem.setSize(300, 300, true);
|
||||||
|
groupItem.setUserSize();
|
||||||
|
|
||||||
|
afterAllTabItemsUpdated(function () {
|
||||||
|
checkPixelColors(test.url, colors, checkWithSmallItemSize);
|
||||||
|
}, win);
|
||||||
|
}
|
||||||
|
|
||||||
|
win.resizeBy.apply(win, size);
|
||||||
|
checkWithNormalItemSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
nextSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
let checkPixelColors = function (url, colors, callback) {
|
||||||
|
let tab = win.gBrowser.tabs[0];
|
||||||
|
let $canvas = tab._tabViewTabItem.$canvas;
|
||||||
|
let width = $canvas.width();
|
||||||
|
let height = $canvas.height();
|
||||||
|
let ctx = $canvas[0].getContext("2d");
|
||||||
|
|
||||||
|
afterAllTabItemsUpdated(function () {
|
||||||
|
checkPixelColor(ctx, url, colors.bottom, Math.floor(width / 4), height - 1, 'bottom');
|
||||||
|
checkPixelColor(ctx, url, colors.right, width - 1, Math.floor(height / 4), 'right');
|
||||||
|
callback();
|
||||||
|
}, win);
|
||||||
|
}
|
||||||
|
|
||||||
|
let checkPixelColor = function (ctx, url, color, x, y, edge) {
|
||||||
|
let data = ctx.getImageData(x, y, 1, 1).data;
|
||||||
|
let check = (data[0] == color[0] && data[1] == color[1] && data[2] == color[2]);
|
||||||
|
ok(check, url + ': ' + edge + ' edge color matches pixel value');
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForExplicitFinish();
|
||||||
|
newWindow(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------
|
||||||
|
function newWindowWithTabView(callback) {
|
||||||
|
let win = window.openDialog(getBrowserURL(), "_blank",
|
||||||
|
"chrome,all,dialog=no,height=600,width=800");
|
||||||
|
win.addEventListener("load", function onLoad() {
|
||||||
|
win.removeEventListener("load", onLoad, false);
|
||||||
|
showTabView(function () callback(win), win);
|
||||||
|
}, false);
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче