Skip to content

Commit

Permalink
[embedlite-components] Send content orientation changed message to ch…
Browse files Browse the repository at this point in the history
…rome. 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.
  • Loading branch information
rainemak committed Jun 17, 2016
1 parent 483da40 commit 5502b1e
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 0 deletions.
5 changes: 5 additions & 0 deletions jscomps/EmbedLiteJSComponents.manifest
Expand Up @@ -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}
Expand Down
63 changes: 63 additions & 0 deletions jscomps/EmbedLiteOrientationChangeHandler.js
@@ -0,0 +1,63 @@
/* 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]);
1 change: 1 addition & 0 deletions jscomps/Makefile.am
Expand Up @@ -9,6 +9,7 @@ jscomps_manifest_DATA = \
ContentPermissionPrompt.js \
EmbedLiteGlobalHelper.js \
EmbedLiteConsoleListener.js \
EmbedLiteOrientationChangeHandler.js \
EmbedLiteSyncService.js \
EmbedLiteFaviconService.js \
EmbedLiteSearchEngine.js \
Expand Down
1 change: 1 addition & 0 deletions jsscripts/Makefile.am
Expand Up @@ -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 \
Expand Down
128 changes: 128 additions & 0 deletions jsscripts/OrientationChangeHandler.jsm
@@ -0,0 +1,128 @@
/* 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])
};
2 changes: 2 additions & 0 deletions link_to_system.sh
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 5502b1e

Please sign in to comment.