Bug 893446 - Try to avoid moving the page contents when the find bar appears. r=dao

This commit is contained in:
Markus Stange 2013-07-16 11:57:20 +02:00
parent f2bdc0900c
commit e366563d7b
6 changed files with 125 additions and 54 deletions

View File

@ -62,6 +62,7 @@ toolkit.jar:
content/global/bindings/expander.xml (widgets/expander.xml)
* content/global/bindings/filefield.xml (widgets/filefield.xml)
*+ content/global/bindings/findbar.xml (widgets/findbar.xml)
content/global/bindings/findbar.css (widgets/findbar.css)
content/global/bindings/general.xml (widgets/general.xml)
content/global/bindings/groupbox.xml (widgets/groupbox.xml)
*+ content/global/bindings/listbox.xml (widgets/listbox.xml)

View File

@ -0,0 +1,41 @@
/* 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/. */
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
findbar {
transition-property: transform, opacity, visibility;
transition-duration: 120ms, 120ms, 0s;
transition-timing-function: ease-in-out, ease-in-out, linear;
/* The following positioning properties only take an effect during findbar
* transitions. The findbar binding sets position:absolute during that time
* on the findbar.
*/
left: 0;
right: 0;
bottom: 0;
}
findbar[position="top"] {
top: 0;
bottom: auto;
}
findbar > hbox {
width: 100%;
}
findbar[hidden] {
/* Override display:none to make the transition work. */
display: -moz-box;
visibility: collapse;
opacity: 0;
transition-delay: 0s, 0s, 120ms;
transform: translateY(2em);
}
findbar[position="top"][hidden] {
transform: translateY(-2em);
}

View File

@ -173,6 +173,7 @@
<binding id="findbar"
extends="chrome://global/content/bindings/toolbar.xml#toolbar">
<resources>
<stylesheet src="chrome://global/content/bindings/findbar.css"/>
<stylesheet src="chrome://global/skin/findBar.css"/>
</resources>
@ -241,6 +242,8 @@
<field name="_flashFindBar">0</field>
<field name="_initialFlashFindBarCount">6</field>
<field name="_contentScrollOffset">0</field>
<property name="_foundLink"
onget="return this._foundLinkRef.get();"
onset="this._foundLinkRef = Components.utils.getWeakReference(val); return val;"/>
@ -1134,8 +1137,30 @@
this._updateFindUI();
if (this.hidden) {
// Use position:absolute during the transition.
this.style.position = "absolute";
this.parentNode.style.position = "relative";
// Apparently a flush is necessary after setting position:relative
// on our parentNode, otherwise setting hidden to false won't
// animate the transform change.
this.getBoundingClientRect();
this.hidden = false;
// Set a height on the findbar that's at least as much as the
// current height, but guaranteed to be an integer number of
// screen pixels.
// This way, reapplying position:static on the findbar after the
// fade in animation won't cause the browser contents to wiggle.
let [chromeOffset, contentScrollOffset] = this._findOffsets();
this.style.height = chromeOffset + "px";
this._contentScrollOffset = contentScrollOffset;
// Wait for the findbar appearance animation to end before
// changing the browser size.
this.addEventListener("transitionend", this);
this._updateStatusUI(this.nsITypeAheadFind.FIND_FOUND);
let event = document.createEvent("Events");
@ -1178,6 +1203,16 @@
}
this.hidden = true;
this.addEventListener("transitionend", this);
// Revert browser scroll shift + findbar static positioning.
if (this.getAttribute("position") == "top" &&
this.style.position != "absolute") {
this._browser.contentWindow.scrollBy(0, -this._contentScrollOffset);
}
this.style.position = "absolute";
var fastFind = this.browser.fastFind;
fastFind.setSelectionModeAndRepaint
(this.nsISelectionController.SELECTION_ON);
@ -1479,10 +1514,58 @@
case "keypress":
this._onBrowserKeypress(aEvent);
break;
case "transitionend":
if (aEvent.target == this &&
aEvent.propertyName == "transform") {
this.removeEventListener("transitionend", this);
// Change the browser size in such a way that the region that's
// overlapped by the findbar can be scrolled to, but try to
// avoid a visual shift of the browser contents.
this.style.removeProperty("position");
if (this.getAttribute("position") == "top" &&
!this.hidden) {
this._browser.contentWindow.scrollBy(0, this._contentScrollOffset);
}
// We'd like to remove position:relative from this.parentNode,
// but that unfortunately causes unnecessary repainting.
}
break;
}
]]></body>
</method>
<method name="_screenPixelsPerCSSPixel">
<parameter name="aWindow"/>
<body><![CDATA[
return aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.screenPixelsPerCSSPixel;
]]></body>
</method>
<!--
- Find two numbers, one in chrome CSS pixels and one in integer
- content CSS pixels, that are about the same as (but not less than)
- the height of the findbar. These two numbers hopefully map to the
- same number of integer screen pixels.
- We want to avoid shifting of the page even when chrome and content
- have different zoom factors, and scrollBy() only accepts integers.
-->
<method name="_findOffsets">
<body><![CDATA[
let chromeFactor = this._screenPixelsPerCSSPixel(window);
let contentFactor = this._screenPixelsPerCSSPixel(this._browser.contentWindow);
let findbarHeightScreen = this.getBoundingClientRect().height * chromeFactor;
let contentScrollOffset = Math.ceil(findbarHeightScreen / contentFactor);
let estimatedScrollOffsetInScreenPixels = Math.round(contentScrollOffset * contentFactor);
let chromeOffset = estimatedScrollOffsetInScreenPixels / chromeFactor;
return [chromeOffset, contentScrollOffset];
]]></body>
</method>
<method name="_enableFindButtons">
<parameter name="aEnable"/>
<body><![CDATA[

View File

@ -9,29 +9,11 @@ findbar {
border-top: 2px solid;
-moz-border-top-colors: ThreeDShadow ThreeDHighlight;
min-width: 1px;
transition-property: margin-bottom, opacity, visibility;
transition-duration: 150ms, 150ms, 0s;
transition-timing-function: ease-in-out, ease-in-out, linear;
}
findbar[position="top"] {
border-top-style: none;
border-bottom: 1px solid ThreeDShadow;
transition-property: margin-top, opacity, visibility;
}
findbar[hidden] {
/* Override display:none to make the transition work. */
display: -moz-box;
visibility: collapse;
margin-bottom: -1em;
opacity: 0;
transition-delay: 0s, 0s, 150ms;
}
findbar[position="top"][hidden] {
margin-bottom: auto;
margin-top: -1em;
}
.findbar-closebutton {

View File

@ -10,29 +10,11 @@ findbar {
border-top: @scopeBarSeparatorBorder@;
min-width: 1px;
padding: 4px 2px;
transition-property: margin-bottom, opacity, visibility;
transition-duration: 150ms, 150ms, 0s;
transition-timing-function: ease-in-out, ease-in-out, linear;
}
findbar[position="top"] {
border-top: none;
border-bottom: @scopeBarSeparatorBorder@;
transition-property: margin-top, opacity, visibility;
}
findbar[hidden] {
/* Override display:none to make the transition work. */
display: -moz-box;
visibility: collapse;
margin-bottom: -1em;
opacity: 0;
transition-delay: 0s, 0s, 150ms;
}
findbar[position="top"][hidden] {
margin-bottom: auto;
margin-top: -1em;
}
findbar:-moz-lwtheme {

View File

@ -11,29 +11,11 @@ findbar {
background-size: 100% 2px;
background-repeat: no-repeat;
min-width: 1px;
transition-property: margin-bottom, opacity, visibility;
transition-duration: 150ms, 150ms, 0s;
transition-timing-function: ease-in-out, ease-in-out, linear;
}
findbar[position="top"] {
background-image: none;
box-shadow: 0 -1px 0 rgba(0,0,0,.1) inset;
transition-property: margin-top, opacity, visibility;
}
findbar[hidden] {
/* Override display:none to make the transition work. */
display: -moz-box;
visibility: collapse;
margin-bottom: -1em;
opacity: 0;
transition-delay: 0s, 0s, 150ms;
}
findbar[position="top"][hidden] {
margin-bottom: auto;
margin-top: -1em;
}
.findbar-closebutton {