зеркало из https://github.com/mozilla/gecko-dev.git
Bug 732564 - Move the display port trimming to Java so that we always have a copy of the display port being used. r=Cwiiis
This commit is contained in:
Родитель
9fe09db32f
Коммит
a8b4dca61a
|
@ -381,7 +381,7 @@ public class GeckoEvent {
|
|||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createViewportEvent(ViewportMetrics viewport, Rect displayPortMargins) {
|
||||
public static GeckoEvent createViewportEvent(ViewportMetrics viewport, RectF displayPort) {
|
||||
GeckoEvent event = new GeckoEvent(VIEWPORT);
|
||||
event.mCharacters = "Viewport:Change";
|
||||
PointF origin = viewport.getOrigin();
|
||||
|
@ -389,7 +389,7 @@ public class GeckoEvent {
|
|||
sb.append("{ \"x\" : ").append(origin.x)
|
||||
.append(", \"y\" : ").append(origin.y)
|
||||
.append(", \"zoom\" : ").append(viewport.getZoomFactor())
|
||||
.append(", \"displayPortMargins\" :").append(RectUtils.toJSON(displayPortMargins))
|
||||
.append(", \"displayPort\" :").append(RectUtils.toJSON(displayPort))
|
||||
.append('}');
|
||||
event.mCharactersExtra = sb.toString();
|
||||
return event;
|
||||
|
|
|
@ -69,7 +69,7 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
private IntSize mScreenSize;
|
||||
private IntSize mWindowSize;
|
||||
private IntSize mBufferSize;
|
||||
private Rect mDisplayPortMargins;
|
||||
private RectF mDisplayPort;
|
||||
|
||||
private VirtualLayer mRootLayer;
|
||||
|
||||
|
@ -87,14 +87,11 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
private ViewTransform mCurrentViewTransform;
|
||||
|
||||
public GeckoLayerClient(Context context) {
|
||||
// we can fill these in with dummy values because they are always written
|
||||
// to before being read
|
||||
mScreenSize = new IntSize(0, 0);
|
||||
mBufferSize = new IntSize(0, 0);
|
||||
mDisplayPortMargins = new Rect(DEFAULT_DISPLAY_PORT_MARGIN,
|
||||
DEFAULT_DISPLAY_PORT_MARGIN,
|
||||
DEFAULT_DISPLAY_PORT_MARGIN,
|
||||
DEFAULT_DISPLAY_PORT_MARGIN);
|
||||
// we can fill this in with dummy values because it is always written
|
||||
// to before being read
|
||||
mDisplayPort = new RectF();
|
||||
mCurrentViewTransform = new ViewTransform(0, 0, 1);
|
||||
}
|
||||
|
||||
|
@ -155,12 +152,7 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
}
|
||||
|
||||
RectF getDisplayPort() {
|
||||
RectF displayPort = new RectF(mRootLayer.getPosition());
|
||||
displayPort.left -= mDisplayPortMargins.left;
|
||||
displayPort.top -= mDisplayPortMargins.top;
|
||||
displayPort.right += mDisplayPortMargins.right;
|
||||
displayPort.bottom += mDisplayPortMargins.bottom;
|
||||
return displayPort;
|
||||
return mDisplayPort;
|
||||
}
|
||||
|
||||
/* Informs Gecko that the screen size has changed. */
|
||||
|
@ -221,13 +213,78 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
mViewportSizeChanged = true;
|
||||
}
|
||||
|
||||
private void updateDisplayPort() {
|
||||
float desiredXMargins = 2 * DEFAULT_DISPLAY_PORT_MARGIN;
|
||||
float desiredYMargins = 2 * DEFAULT_DISPLAY_PORT_MARGIN;
|
||||
|
||||
ImmutableViewportMetrics metrics = mLayerController.getViewportMetrics();
|
||||
|
||||
// we need to avoid having a display port that is larger than the page, or we will end up
|
||||
// painting things outside the page bounds (bug 729169). we simultaneously need to make
|
||||
// the display port as large as possible so that we redraw less.
|
||||
|
||||
// figure out how much of the desired buffer amount we can actually use on the horizontal axis
|
||||
float xBufferAmount = Math.min(desiredXMargins, Math.max(0, metrics.pageSizeWidth - metrics.getWidth()));
|
||||
// if we reduced the buffer amount on the horizontal axis, we should take that saved memory and
|
||||
// use it on the vertical axis
|
||||
float savedPixels = (desiredXMargins - xBufferAmount) * (metrics.getHeight() + desiredYMargins);
|
||||
float extraYAmount = (float)Math.floor(savedPixels / (metrics.getWidth() + xBufferAmount));
|
||||
float yBufferAmount = Math.min(desiredYMargins + extraYAmount, Math.max(0, metrics.pageSizeHeight - metrics.getHeight()));
|
||||
// and the reverse - if we shrunk the buffer on the vertical axis we can add it to the horizontal
|
||||
if (xBufferAmount == desiredXMargins && yBufferAmount < desiredYMargins) {
|
||||
savedPixels = (desiredYMargins - yBufferAmount) * (metrics.getWidth() + xBufferAmount);
|
||||
float extraXAmount = (float)Math.floor(savedPixels / (metrics.getHeight() + yBufferAmount));
|
||||
xBufferAmount = Math.min(xBufferAmount + extraXAmount, Math.max(0, metrics.pageSizeWidth - metrics.getWidth()));
|
||||
}
|
||||
|
||||
// and now calculate the display port margins based on how much buffer we've decided to use and
|
||||
// the page bounds, ensuring we use all of the available buffer amounts on one side or the other
|
||||
// on any given axis. (i.e. if we're scrolled to the top of the page, the vertical buffer is
|
||||
// entirely below the visible viewport, but if we're halfway down the page, the vertical buffer
|
||||
// is split).
|
||||
float leftMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, Math.max(0, metrics.viewportRectLeft));
|
||||
float rightMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, Math.max(0, metrics.pageSizeWidth - (metrics.viewportRectLeft + metrics.getWidth())));
|
||||
if (leftMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
|
||||
rightMargin = xBufferAmount - leftMargin;
|
||||
} else if (rightMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
|
||||
leftMargin = xBufferAmount - rightMargin;
|
||||
} else if (!FloatUtils.fuzzyEquals(leftMargin + rightMargin, xBufferAmount)) {
|
||||
float delta = xBufferAmount - leftMargin - rightMargin;
|
||||
leftMargin += delta / 2;
|
||||
rightMargin += delta / 2;
|
||||
}
|
||||
|
||||
float topMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, Math.max(0, metrics.viewportRectTop));
|
||||
float bottomMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, Math.max(0, metrics.pageSizeHeight - (metrics.viewportRectTop + metrics.getHeight())));
|
||||
if (topMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
|
||||
bottomMargin = yBufferAmount - topMargin;
|
||||
} else if (bottomMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
|
||||
topMargin = yBufferAmount - bottomMargin;
|
||||
} else if (!FloatUtils.fuzzyEquals(topMargin + bottomMargin, yBufferAmount)) {
|
||||
float delta = yBufferAmount - topMargin - bottomMargin;
|
||||
topMargin += delta / 2;
|
||||
bottomMargin += delta / 2;
|
||||
}
|
||||
|
||||
// note that unless the viewport size changes, or the page dimensions change (either because of
|
||||
// content changes or zooming), the size of the display port should remain constant. this
|
||||
// is intentional to avoid re-creating textures and all sorts of other reallocations in the
|
||||
// draw and composition code.
|
||||
|
||||
mDisplayPort.left = metrics.viewportRectLeft - leftMargin;
|
||||
mDisplayPort.top = metrics.viewportRectTop - topMargin;
|
||||
mDisplayPort.right = metrics.viewportRectRight + rightMargin;
|
||||
mDisplayPort.bottom = metrics.viewportRectBottom + bottomMargin;
|
||||
}
|
||||
|
||||
private void adjustViewport() {
|
||||
ViewportMetrics viewportMetrics =
|
||||
new ViewportMetrics(mLayerController.getViewportMetrics());
|
||||
|
||||
viewportMetrics.setViewport(viewportMetrics.getClampedViewport());
|
||||
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createViewportEvent(viewportMetrics, mDisplayPortMargins));
|
||||
updateDisplayPort();
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createViewportEvent(viewportMetrics, mDisplayPort));
|
||||
if (mViewportSizeChanged) {
|
||||
mViewportSizeChanged = false;
|
||||
GeckoAppShell.viewSizeChanged();
|
||||
|
@ -254,11 +311,12 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
|
||||
/** Implementation of GeckoEventResponder. */
|
||||
public String getResponse() {
|
||||
// We are responding to the events handled in handleMessage() above with
|
||||
// the display port margins we want. Note that all messages we are currently
|
||||
// handling (Viewport:Update) require this response, so we can just return
|
||||
// this indiscriminately.
|
||||
return RectUtils.toJSON(mDisplayPortMargins);
|
||||
// We are responding to the events handled in handleMessage() above with the
|
||||
// display port we want. Note that all messages we are currently handling
|
||||
// (just Viewport:Update) require this response, so we can just return this
|
||||
// indiscriminately.
|
||||
updateDisplayPort();
|
||||
return RectUtils.toJSON(mDisplayPort);
|
||||
}
|
||||
|
||||
void geometryChanged() {
|
||||
|
|
|
@ -41,6 +41,14 @@ public class ImmutableViewportMetrics {
|
|||
allowZoom = m.getAllowZoom();
|
||||
}
|
||||
|
||||
public float getWidth() {
|
||||
return viewportRectRight - viewportRectLeft;
|
||||
}
|
||||
|
||||
public float getHeight() {
|
||||
return viewportRectBottom - viewportRectTop;
|
||||
}
|
||||
|
||||
// some helpers to make ImmutableViewportMetrics act more like ViewportMetrics
|
||||
|
||||
public PointF getOrigin() {
|
||||
|
|
|
@ -58,7 +58,7 @@ public final class RectUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static String toJSON(Rect rect) {
|
||||
public static String toJSON(RectF rect) {
|
||||
StringBuffer sb = new StringBuffer(256);
|
||||
sb.append("{ \"left\": ").append(rect.left)
|
||||
.append(", \"top\": ").append(rect.top)
|
||||
|
|
|
@ -1589,94 +1589,35 @@ Tab.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
refreshDisplayPort: function(aDisplayPortMargins) {
|
||||
if (this._zoom <= 0)
|
||||
return;
|
||||
if (!this.browser.contentDocument.documentElement)
|
||||
setDisplayPort: function(aViewportX, aViewportY, aDisplayPortRect) {
|
||||
let zoom = this._zoom;
|
||||
if (zoom <= 0)
|
||||
return;
|
||||
|
||||
let viewport = this.getViewport();
|
||||
let element = this.browser.contentDocument.documentElement;
|
||||
if (!element)
|
||||
return;
|
||||
|
||||
// we need to avoid having a display port that is larger than the page, or we will end up
|
||||
// painting things outside the page bounds (bug 729169)
|
||||
|
||||
let requestedXAmount = Math.max(0, aDisplayPortMargins.left + aDisplayPortMargins.right);
|
||||
let requestedYAmount = Math.max(0, aDisplayPortMargins.top + aDisplayPortMargins.bottom);
|
||||
|
||||
// figure out how much of the specified buffer amount we can actually use on the horizontal axis
|
||||
let xBufferAmount = Math.min(requestedXAmount, Math.max(0, viewport.pageWidth - viewport.width));
|
||||
// if we reduced the buffer amount on the horizontal axis, we should take that saved memory and
|
||||
// use it on the vertical axis
|
||||
let savedPixels = (requestedXAmount - xBufferAmount) * (viewport.height + requestedYAmount);
|
||||
let extraYAmount = Math.floor(savedPixels / (viewport.width + xBufferAmount));
|
||||
let yBufferAmount = Math.min(requestedYAmount + extraYAmount, Math.max(0, viewport.pageHeight - viewport.height));
|
||||
// and the reverse - if we shrunk the buffer on the vertical axis we can add it to the horizontal
|
||||
if (xBufferAmount == requestedXAmount && yBufferAmount < requestedYAmount) {
|
||||
savedPixels = (requestedYAmount - yBufferAmount) * (viewport.width + xBufferAmount);
|
||||
let extraXAmount = Math.floor(savedPixels / (viewport.height + yBufferAmount));
|
||||
xBufferAmount = Math.min(xBufferAmount + extraXAmount, Math.max(0, viewport.pageWidth - viewport.width));
|
||||
}
|
||||
|
||||
// and now calculate the display port margins based on how much buffer we've decided to use and
|
||||
// the page bounds, ensuring we use all of the available buffer amounts on one side or the other
|
||||
// on any given axis. (i.e. if we're scrolled to the top of the page, the vertical buffer is
|
||||
// entirely below the visible viewport, but if we're halfway down the page, the vertical buffer
|
||||
// is split as specified in the aDisplayPortMargins parameter).
|
||||
let leftMargin = Math.min(aDisplayPortMargins.left, Math.max(0, viewport.x));
|
||||
let rightMargin = Math.min(aDisplayPortMargins.right, Math.max(0, viewport.pageWidth - (viewport.x + viewport.width)));
|
||||
if (leftMargin < aDisplayPortMargins.left) {
|
||||
rightMargin = xBufferAmount - leftMargin;
|
||||
} else if (rightMargin < aDisplayPortMargins.right) {
|
||||
leftMargin = xBufferAmount - rightMargin;
|
||||
} else if (Math.abs(leftMargin + rightMargin - xBufferAmount) >= 1e-6) {
|
||||
let delta = xBufferAmount - leftMargin - rightMargin;
|
||||
leftMargin += delta / 2;
|
||||
rightMargin += delta / 2;
|
||||
}
|
||||
|
||||
let topMargin = Math.min(aDisplayPortMargins.top, Math.max(0, viewport.y));
|
||||
let bottomMargin = Math.min(aDisplayPortMargins.bottom, Math.max(0, viewport.pageHeight - (viewport.y + viewport.height)));
|
||||
if (topMargin < aDisplayPortMargins.top) {
|
||||
bottomMargin = yBufferAmount - topMargin;
|
||||
} else if (bottomMargin < aDisplayPortMargins.bottom) {
|
||||
topMargin = yBufferAmount - bottomMargin;
|
||||
} else if (Math.abs(topMargin + bottomMargin - yBufferAmount) >= 1e-6) {
|
||||
let delta = yBufferAmount - topMargin - bottomMargin;
|
||||
topMargin += delta / 2;
|
||||
bottomMargin += delta / 2;
|
||||
}
|
||||
|
||||
dump("### displayport margins=(" + leftMargin + ", " + topMargin + ", " + rightMargin + ", " + bottomMargin + ") at zoom=" + viewport.zoom
|
||||
+ " and buffer amounts=(" + xBufferAmount + ", " + yBufferAmount + ")");
|
||||
|
||||
// note that unless the viewport size changes, or the page dimensions change (either because of
|
||||
// content changes or zooming), the size of the display port should remain constant. this
|
||||
// is intentional to avoid re-creating textures and all sorts of other reallocations in the
|
||||
// draw and composition code.
|
||||
|
||||
let cwu = window.top.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
cwu.setDisplayPortForElement(-leftMargin / viewport.zoom,
|
||||
-topMargin / viewport.zoom,
|
||||
(leftMargin + viewport.width + rightMargin) / viewport.zoom,
|
||||
(topMargin + viewport.height + bottomMargin) / viewport.zoom,
|
||||
this.browser.contentDocument.documentElement);
|
||||
let cwu = window.top.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
cwu.setDisplayPortForElement((aDisplayPortRect.left - aViewportX) / zoom,
|
||||
(aDisplayPortRect.top - aViewportY) / zoom,
|
||||
(aDisplayPortRect.right - aDisplayPortRect.left) / zoom,
|
||||
(aDisplayPortRect.bottom - aDisplayPortRect.top) / zoom,
|
||||
element);
|
||||
},
|
||||
|
||||
setViewport: function(aViewport) {
|
||||
// Transform coordinates based on zoom
|
||||
aViewport.x /= aViewport.zoom;
|
||||
aViewport.y /= aViewport.zoom;
|
||||
let x = aViewport.x / aViewport.zoom;
|
||||
let y = aViewport.y / aViewport.zoom;
|
||||
|
||||
// Set scroll position
|
||||
let win = this.browser.contentWindow;
|
||||
win.scrollTo(aViewport.x, aViewport.y);
|
||||
win.scrollTo(x, y);
|
||||
this.userScrollPos.x = win.scrollX;
|
||||
this.userScrollPos.y = win.scrollY;
|
||||
this.setResolution(aViewport.zoom, false);
|
||||
|
||||
// always refresh display port when we scroll so that we can clip it to page bounds
|
||||
this.refreshDisplayPort(aViewport.displayPortMargins);
|
||||
this.setDisplayPort(aViewport.x, aViewport.y, aViewport.displayPort);
|
||||
},
|
||||
|
||||
setResolution: function(aZoom, aForce) {
|
||||
|
@ -1752,9 +1693,9 @@ Tab.prototype = {
|
|||
return;
|
||||
let message = this.getViewport();
|
||||
message.type = "Viewport:Update";
|
||||
let displayPortMargins = sendMessageToJava({ gecko: message });
|
||||
if (displayPortMargins != null)
|
||||
this.refreshDisplayPort(JSON.parse(displayPortMargins));
|
||||
let displayPort = sendMessageToJava({ gecko: message });
|
||||
if (displayPort != null)
|
||||
this.setDisplayPort(message.x, message.y, JSON.parse(displayPort));
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
|
@ -2017,7 +1958,7 @@ Tab.prototype = {
|
|||
// XXX This code assumes that this is the earliest hook we have at which
|
||||
// browser.contentDocument is changed to the new document we're loading
|
||||
this.contentDocumentIsDisplayed = false;
|
||||
this.refreshDisplayPort({left: 0, top: 0, right: 0, bottom: 0 });
|
||||
this.setDisplayPort(0, 0, {left: 0, top: 0, right: gScreenWidth, bottom: gScreenHeight });
|
||||
} else {
|
||||
this.sendViewportUpdate();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче