mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-12 06:52:25 +00:00
Bug 1130646 - Find non-hacky way to make back button dismiss reader mode popup, r=bnicholson
This commit is contained in:
parent
670995286a
commit
466a9d607e
@ -33,6 +33,7 @@ import org.mozilla.gecko.util.ActivityUtils;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.FileUtils;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.GeckoRequest;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
@ -2344,31 +2345,57 @@ public abstract class GeckoApp
|
||||
return;
|
||||
}
|
||||
|
||||
Tabs tabs = Tabs.getInstance();
|
||||
Tab tab = tabs.getSelectedTab();
|
||||
final Tabs tabs = Tabs.getInstance();
|
||||
final Tab tab = tabs.getSelectedTab();
|
||||
if (tab == null) {
|
||||
moveTaskToBack(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tab.doBack())
|
||||
return;
|
||||
// Give Gecko a chance to handle the back press first, then fallback to the Java UI.
|
||||
GeckoAppShell.sendRequestToGecko(new GeckoRequest("Browser:OnBackPressed", null) {
|
||||
@Override
|
||||
public void onResponse(NativeJSObject nativeJSObject) {
|
||||
if (!nativeJSObject.getBoolean("handled")) {
|
||||
// Default behavior is Gecko didn't prevent.
|
||||
onDefault();
|
||||
}
|
||||
}
|
||||
|
||||
if (tab.isExternal()) {
|
||||
moveTaskToBack(true);
|
||||
tabs.closeTab(tab);
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void onError(NativeJSObject error) {
|
||||
// Default behavior is Gecko didn't prevent, via failure.
|
||||
onDefault();
|
||||
}
|
||||
|
||||
int parentId = tab.getParentId();
|
||||
Tab parent = tabs.getTab(parentId);
|
||||
if (parent != null) {
|
||||
// The back button should always return to the parent (not a sibling).
|
||||
tabs.closeTab(tab, parent);
|
||||
return;
|
||||
}
|
||||
// Return from Gecko thread, then back-press through the Java UI.
|
||||
private void onDefault() {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (tab.doBack()) {
|
||||
return;
|
||||
}
|
||||
|
||||
moveTaskToBack(true);
|
||||
if (tab.isExternal()) {
|
||||
moveTaskToBack(true);
|
||||
tabs.closeTab(tab);
|
||||
return;
|
||||
}
|
||||
|
||||
final int parentId = tab.getParentId();
|
||||
final Tab parent = tabs.getTab(parentId);
|
||||
if (parent != null) {
|
||||
// The back button should always return to the parent (not a sibling).
|
||||
tabs.closeTab(tab, parent);
|
||||
return;
|
||||
}
|
||||
|
||||
moveTaskToBack(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -20,6 +20,39 @@ var Reader = {
|
||||
return this._hasUsedToolbar = Services.prefs.getBoolPref("reader.has_used_toolbar");
|
||||
},
|
||||
|
||||
/**
|
||||
* BackPressListener (listeners / ReaderView Ids).
|
||||
*/
|
||||
_backPressListeners: [],
|
||||
_backPressViewIds: [],
|
||||
|
||||
/**
|
||||
* Set a backPressListener for this tabId / ReaderView Id pair.
|
||||
*/
|
||||
_addBackPressListener: function(tabId, viewId, listener) {
|
||||
this._backPressListeners[tabId] = listener;
|
||||
this._backPressViewIds[viewId] = tabId;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a backPressListener for this ReaderView Id.
|
||||
*/
|
||||
_removeBackPressListener: function(viewId) {
|
||||
let tabId = this._backPressViewIds[viewId];
|
||||
if (tabId != undefined) {
|
||||
this._backPressListeners[tabId] = null;
|
||||
delete this._backPressViewIds[viewId];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* If the requested tab has a backPress listener, return its results, else false.
|
||||
*/
|
||||
onBackPress: function(tabId) {
|
||||
let listener = this._backPressListeners[tabId];
|
||||
return { handled: (listener ? listener() : false) };
|
||||
},
|
||||
|
||||
observe: function Reader_observe(aMessage, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "Reader:FetchContent": {
|
||||
@ -66,6 +99,29 @@ var Reader = {
|
||||
});
|
||||
break;
|
||||
|
||||
// On DropdownClosed in ReaderView, we cleanup / clear existing BackPressListener.
|
||||
case "Reader:DropdownClosed": {
|
||||
this._removeBackPressListener(message.data);
|
||||
break;
|
||||
}
|
||||
|
||||
// On DropdownOpened in ReaderView, we add BackPressListener to handle a subsequent BACK request.
|
||||
case "Reader:DropdownOpened": {
|
||||
let tabId = BrowserApp.selectedTab.id;
|
||||
this._addBackPressListener(tabId, message.data, () => {
|
||||
// User hit BACK key while ReaderView has the banner font-dropdown opened.
|
||||
// Close it and return prevent-default.
|
||||
if (message.target.messageManager) {
|
||||
message.target.messageManager.sendAsyncMessage("Reader:CloseDropdown");
|
||||
return true;
|
||||
}
|
||||
// We can assume ReaderView banner's font-dropdown doesn't need to be closed.
|
||||
return false;
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "Reader:FaviconRequest": {
|
||||
Messaging.sendRequestForResult({
|
||||
type: "Reader:FaviconRequest",
|
||||
|
@ -193,6 +193,8 @@ lazilyLoadedObserverScripts.forEach(function (aScript) {
|
||||
["Reader", [
|
||||
["Reader:AddToList", false],
|
||||
["Reader:ArticleGet", false],
|
||||
["Reader:DropdownClosed", true], // 'true' allows us to survive mid-air cycle-collection.
|
||||
["Reader:DropdownOpened", false],
|
||||
["Reader:FaviconRequest", false],
|
||||
["Reader:ListStatusRequest", false],
|
||||
["Reader:RemoveFromList", false],
|
||||
@ -4747,6 +4749,11 @@ var BrowserEventHandler = {
|
||||
|
||||
InitLater(() => BrowserApp.deck.addEventListener("click", InputWidgetHelper, true));
|
||||
InitLater(() => BrowserApp.deck.addEventListener("click", SelectHelper, true));
|
||||
|
||||
// ReaderViews support backPress listeners.
|
||||
Messaging.addListener(() => {
|
||||
return Reader.onBackPress(BrowserApp.selectedTab.id);
|
||||
}, "Browser:OnBackPressed");
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
|
@ -38,6 +38,7 @@ var AboutReader = function(mm, win, articlePromise) {
|
||||
this._mm.addMessageListener("Reader:Removed", this);
|
||||
this._mm.addMessageListener("Sidebar:VisibilityChange", this);
|
||||
this._mm.addMessageListener("ReadingList:VisibilityStatus", this);
|
||||
this._mm.addMessageListener("Reader:CloseDropdown", this);
|
||||
|
||||
this._docRef = Cu.getWeakReference(doc);
|
||||
this._winRef = Cu.getWeakReference(win);
|
||||
@ -178,6 +179,15 @@ AboutReader.prototype = {
|
||||
return this._toolbarVertical = Services.prefs.getBoolPref("reader.toolbar.vertical");
|
||||
},
|
||||
|
||||
// Provides unique view Id.
|
||||
get viewId() {
|
||||
let _viewId = Cc["@mozilla.org/uuid-generator;1"].
|
||||
getService(Ci.nsIUUIDGenerator).generateUUID().toString();
|
||||
Object.defineProperty(this, "viewId", { value: _viewId });
|
||||
|
||||
return _viewId;
|
||||
},
|
||||
|
||||
receiveMessage: function (message) {
|
||||
switch (message.name) {
|
||||
case "Reader:Added": {
|
||||
@ -190,6 +200,14 @@ AboutReader.prototype = {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Triggered by Android user pressing BACK while the banner font-dropdown is open.
|
||||
case "Reader:CloseDropdown": {
|
||||
// Just close it.
|
||||
this._closeDropdown();
|
||||
break;
|
||||
}
|
||||
|
||||
case "Reader:Removed": {
|
||||
if (message.data.url == this._article.url) {
|
||||
if (this._isReadingListItem != 0) {
|
||||
@ -246,10 +264,14 @@ AboutReader.prototype = {
|
||||
break;
|
||||
|
||||
case "unload":
|
||||
// Close the Banners Font-dropdown, cleanup Android BackPressListener.
|
||||
this._closeDropdown();
|
||||
|
||||
this._mm.removeMessageListener("Reader:Added", this);
|
||||
this._mm.removeMessageListener("Reader:Removed", this);
|
||||
this._mm.removeMessageListener("Sidebar:VisibilityChange", this);
|
||||
this._mm.removeMessageListener("ReadingList:VisibilityStatus", this);
|
||||
this._mm.removeMessageListener("Reader:CloseDropdown", this);
|
||||
this._windowUnloaded = true;
|
||||
break;
|
||||
}
|
||||
@ -584,8 +606,7 @@ AboutReader.prototype = {
|
||||
},
|
||||
|
||||
_setToolbarVisibility: function(visible) {
|
||||
let dropdown = this._doc.getElementById("style-dropdown");
|
||||
dropdown.classList.remove("open");
|
||||
this._closeDropdown();
|
||||
|
||||
if (this._getToolbarVisibility() === visible) {
|
||||
return;
|
||||
@ -943,13 +964,41 @@ AboutReader.prototype = {
|
||||
event.stopPropagation();
|
||||
|
||||
if (dropdown.classList.contains("open")) {
|
||||
dropdown.classList.remove("open");
|
||||
this._closeDropdown();
|
||||
} else {
|
||||
dropdown.classList.add("open");
|
||||
this._openDropdown();
|
||||
if (this._isToolbarVertical) {
|
||||
updatePopupPosition();
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
},
|
||||
|
||||
/*
|
||||
* If the ReaderView banner font-dropdown is closed, open it.
|
||||
*/
|
||||
_openDropdown: function() {
|
||||
let dropdown = this._doc.getElementById("style-dropdown");
|
||||
if (dropdown.classList.contains("open")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger BackPressListener initialization in Android.
|
||||
dropdown.classList.add("open");
|
||||
this._mm.sendAsyncMessage("Reader:DropdownOpened", this.viewId);
|
||||
},
|
||||
|
||||
/*
|
||||
* If the ReaderView banner font-dropdown is opened, close it.
|
||||
*/
|
||||
_closeDropdown: function() {
|
||||
let dropdown = this._doc.getElementById("style-dropdown");
|
||||
if (!dropdown.classList.contains("open")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger BackPressListener cleanup in Android.
|
||||
dropdown.classList.remove("open");
|
||||
this._mm.sendAsyncMessage("Reader:DropdownClosed", this.viewId);
|
||||
},
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user