Commit 01951df1 authored by Raine Makelainen's avatar Raine Makelainen Committed by chriadam

[embedlite-components] Send content orientation changed message to chrome. Fixes JB#35447

Send "embed:contentOrientationChanged" message to chrome after
content has been resized after orientation change. Changing orientation
between mirrored orientations (primary to secondary or other way
round) is cheap and does not trigger reflow. Thus, those can
be send back to chrome immediately.

There is a 200ms fallback timer that guarantees that we send the
orientation change eventually. Noticed for instance that full
screen video playback orientation change did not always trigger
resizing while it should have been triggered.

This is inspited by B2G's OrientationChangeHandler.jsm.
parent b326edeb
......@@ -46,6 +46,11 @@ component {c48047b0-9e6d-11e2-a162-bb9036ce396c} EmbedLiteFaviconService.js
contract @mozilla.org/embedlite-favicon-component;1 {c48047b0-9e6d-11e2-a162-bb9036ce396c}
category app-startup EmbedLiteFaviconService service,@mozilla.org/embedlite-favicon-component;1
# EmbedLiteOrientationChangeHandler.js
component {39c15bb1-0a5c-42ff-979a-f2cfd966743c} EmbedLiteOrientationChangeHandler.js
contract @mozilla.org/embedlite-orientationhandler-component;1 {39c15bb1-0a5c-42ff-979a-f2cfd966743c}
category app-startup EmbedLiteOrientationChangeHandler service,@mozilla.org/embedlite-orientationhandler-component;1
# EmbedLiteSearchEngine.js
component {924fe7ba-afa1-11e2-9d4f-533572064b73} EmbedLiteSearchEngine.js
contract @mozilla.org/embedlite-search-component;1 {924fe7ba-afa1-11e2-9d4f-533572064b73}
......
/* 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/. */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("chrome://embedlite/content/OrientationChangeHandler.jsm")
XPCOMUtils.defineLazyServiceGetter(Services, "embedlite",
"@mozilla.org/embedlite-app-service;1",
"nsIEmbedAppService");
function EmbedLiteOrientationChangeHandler()
{
}
EmbedLiteOrientationChangeHandler.prototype = {
classID: Components.ID("{39c15bb1-0a5c-42ff-979a-f2cfd966743c}"),
_orientationListeners: {},
_initialize: function() {
Services.obs.addObserver(this, "embedliteviewcreated", true);
Services.obs.addObserver(this, "domwindowclosed", true);
},
observe: function(aSubject, aTopic, aData) {
let self = this;
switch (aTopic) {
case "app-startup": {
self._initialize();
break;
}
case "embedliteviewcreated": {
self.onWindowOpen(aSubject);
break;
}
case "domwindowclosed": {
self.onWindowClosed(aSubject);
break;
}
}
},
onWindowOpen: function(aWindow) {
this._orientationListeners[aWindow] = new OrientationChangeHandler(aWindow);
Services.embedlite.chromeEventHandler(aWindow).addEventListener("DOMContentLoaded", this._orientationListeners[aWindow], false);
},
onWindowClosed: function(aWindow) {
Services.embedlite.chromeEventHandler(aWindow).addEventListener("DOMContentLoaded", this._orientationListeners[aWindow], false);
delete this._orientationListeners[aWindow];
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference])
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([EmbedLiteOrientationChangeHandler]);
......@@ -9,6 +9,7 @@ jscomps_manifest_DATA = \
ContentPermissionPrompt.js \
EmbedLiteGlobalHelper.js \
EmbedLiteConsoleListener.js \
EmbedLiteOrientationChangeHandler.js \
EmbedLiteSyncService.js \
EmbedLiteFaviconService.js \
EmbedLiteSearchEngine.js \
......
......@@ -2,6 +2,7 @@ jsscripts_manifestdir=$(libdir)/mozembedlite/chrome/embedlite/content
jsscripts_manifest_DATA = \
TelURIParser.jsm \
embedhelper.js \
OrientationChangeHandler.jsm \
SelectHelper.js \
SelectAsyncHelper.js \
SelectionHandler.js \
......
/* 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/. */
"use strict";
this.EXPORTED_SYMBOLS = ["OrientationChangeHandler"];
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyServiceGetter(Services, "embedlite",
"@mozilla.org/embedlite-app-service;1",
"nsIEmbedAppService");
this.OrientationChangeHandler = function OrientationChangeHandler(window) {
this._winID = Services.embedlite.getIDByWindow(window);
this._targetWindow = Services.embedlite.getContentWindowByID(this._winID);
// "DomContentLoaded" event listener registered in EmbedLiteOrientationChangeHandler.js
}
OrientationChangeHandler.prototype = {
_targetWindow: null,
_winID: -1,
lastOrientation: "portrait-primary",
isRegistered: false,
handleOrientationChange: function(evt) {
let that = this;
let newOrientation = that._targetWindow.screen.mozOrientation;
let fullSwitch = (newOrientation.split("-")[0] ==
that.lastOrientation.split("-")[0]);
let changeSent = false;
that.lastOrientation = newOrientation;
function sendOrientationChanged() {
if (changeSent) {
return;
}
try {
Services.embedlite.sendAsyncMessage(that._winID, "embed:contentOrientationChanged",
JSON.stringify({
"orientation": newOrientation
}));
changeSent = true;
} catch (e) {
dump("EmbedLiteOrientationChangeHandler: Failed to report orientation change " + e + "\n")
}
}
// 180deg rotation, no resize
if (fullSwitch) {
that._targetWindow.setTimeout(sendOrientationChanged);
return;
}
that._targetWindow.addEventListener("resize", resizeThrottler, false);
let resizeTimeout;
function resizeThrottler() {
// ignore resize events as long as an actualResizeHandler execution is in the queue
if (!resizeTimeout) {
resizeTimeout = that._targetWindow.setTimeout(function() {
resizeTimeout = null;
that._targetWindow.removeEventListener("resize", resizeThrottler, false);
sendOrientationChanged();
// The sendOrientationChanged will execute at a rate of 15fps
// Noise should be small as we're only listening resizing after
// orientation has changed.
}, 66);
}
}
// Fallback timeout 200ms.
// When fullscreen video playback is running, noticed that
// resizing doesn't take always place. This guarantees that
// we will send the message back to chrome after 200ms. Normally
// we go always through the resizeThrottler.
that._targetWindow.setTimeout(sendOrientationChanged, 200);
},
handleEvent: function(evt) {
let window = this._targetWindow;
switch (evt.type) {
case "DOMContentLoaded":
let target = evt.originalTarget;
// ignore on frames and other documents
if (target != window.document) {
return;
}
if (!this.isRegistered) {
window.screen.addEventListener("mozorientationchange", this, true);
// This will take care of navigation between pages.
window.addEventListener("beforeunload", this, true);
this.isRegistered = true;
}
// Confirm initial orientation
try {
this.lastOrientation = this._targetWindow.screen.mozOrientation;
Services.embedlite.sendAsyncMessage(this._winID, "embed:contentOrientationChanged",
JSON.stringify({
"orientation": this.lastOrientation
}));
} catch (e) {
dump("EmbedLiteOrientationChangeHandler: Report initial orientation " + e + "\n")
}
break;
case "mozorientationchange":
this.handleOrientationChange(evt);
break;
case "beforeunload":
if (window && window.screen) {
window.screen.removeEventListener("mozorientationchange", this, true);
}
this.isRegistered = false;
break;
}
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener, Ci.nsISupportsWeakReference])
};
......@@ -35,6 +35,7 @@ jscomps/EmbedLiteGlobalHelper.js
jscomps/EmbedLiteConsoleListener.js
jscomps/EmbedLiteSyncService.js
jscomps/EmbedLiteFaviconService.js
jscomps/EmbedLiteOrientationChangeHandler.js
jscomps/EmbedLiteSearchEngine.js
jscomps/EmbedLiteErrorPageHandler.js
jscomps/UserAgentOverrideHelper.js
......@@ -62,6 +63,7 @@ ln -s $(pwd)/jsscripts/EmbedLiteJSScripts.manifest $TARGET_DIR/chrome/EmbedLiteJ
rm -rf $TARGET_DIR/chrome/embedlite;
mkdir -p $TARGET_DIR/chrome/embedlite/content/sync;
ln -s $(pwd)/jsscripts/embedhelper.js $TARGET_DIR/chrome/embedlite/content/embedhelper.js;
ln -s $(pwd)/jsscripts/OrientationChangeHandler.jsm $TARGET_DIR/chrome/embedlite/content/OrientationChangeHandler.jsm;
ln -s $(pwd)/jsscripts/TelURIParser.jsm $TARGET_DIR/chrome/embedlite/content/TelURIParser.jsm;
ln -s $(pwd)/jsscripts/SelectHelper.js $TARGET_DIR/chrome/embedlite/content/SelectHelper.js;
ln -s $(pwd)/jsscripts/SelectAsyncHelper.js $TARGET_DIR/chrome/embedlite/content/SelectAsyncHelper.js;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment