mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 1603321 - Replace Touch Bar "Search or enter address" button with an "Exit Fullscreen" button while in fullscreen. r=mikedeboer,fluent-reviewers,flod
Differential Revision: https://phabricator.services.mozilla.com/D57350 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
f362f78bca
commit
4cde91dd0c
@ -1687,14 +1687,8 @@ var BookmarkingUI = {
|
||||
}
|
||||
if (starred) {
|
||||
element.setAttribute("starred", "true");
|
||||
Services.obs.notifyObservers(null, "bookmark-icon-updated", "starred");
|
||||
} else {
|
||||
element.removeAttribute("starred");
|
||||
Services.obs.notifyObservers(
|
||||
null,
|
||||
"bookmark-icon-updated",
|
||||
"unstarred"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1708,6 +1702,12 @@ var BookmarkingUI = {
|
||||
starred ? this._starredTooltip : this._unstarredTooltip
|
||||
);
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(
|
||||
null,
|
||||
"bookmark-icon-updated",
|
||||
starred ? "starred" : "unstarred"
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -87,7 +87,7 @@ const kInputTypes = {
|
||||
/**
|
||||
* An object containing all implemented TouchBarInput objects.
|
||||
*/
|
||||
const kBuiltInInputs = {
|
||||
var gBuiltInInputs = {
|
||||
Back: {
|
||||
title: "back",
|
||||
image: "chrome://browser/skin/back.svg",
|
||||
@ -164,6 +164,7 @@ const kBuiltInInputs = {
|
||||
disabled: true, // Updated when the page is found to be Reader View-able.
|
||||
},
|
||||
OpenLocation: {
|
||||
key: "open-location",
|
||||
title: "open-location",
|
||||
image: "chrome://browser/skin/search-glass.svg",
|
||||
type: kInputTypes.MAIN_BUTTON,
|
||||
@ -244,6 +245,7 @@ var localizedStrings = {};
|
||||
|
||||
const kHelperObservers = new Set([
|
||||
"bookmark-icon-updated",
|
||||
"fullscreen-painted",
|
||||
"reader-mode-available",
|
||||
"touchbar-location-change",
|
||||
"quit-application",
|
||||
@ -265,11 +267,7 @@ class TouchBarHelper {
|
||||
// created/destroyed for the urlbar-focus/blur events.
|
||||
this._searchPopover = this.getTouchBarInput("SearchPopover");
|
||||
|
||||
// The test machines do not have Touch Bars, so _inputsNotUpdated is never
|
||||
// initialized. This causes problems in the tests.
|
||||
if (Cu.isInAutomation) {
|
||||
this._inputsNotUpdated = new Set();
|
||||
}
|
||||
this._inputsNotUpdated = new Set();
|
||||
}
|
||||
|
||||
destructor() {
|
||||
@ -296,19 +294,20 @@ class TouchBarHelper {
|
||||
Ci.nsIMutableArray
|
||||
);
|
||||
|
||||
for (let inputName of Object.keys(kBuiltInInputs)) {
|
||||
// Every input must be updated at least once so that all assets (titles,
|
||||
// icons) are loaded. We keep track of which inputs haven't updated and
|
||||
// run an update on them ASAP.
|
||||
this._inputsNotUpdated.clear();
|
||||
|
||||
for (let inputName of Object.keys(gBuiltInInputs)) {
|
||||
let input = this.getTouchBarInput(inputName);
|
||||
if (!input) {
|
||||
continue;
|
||||
}
|
||||
this._inputsNotUpdated.add(inputName);
|
||||
layoutItems.appendElement(input);
|
||||
}
|
||||
|
||||
// Every input must be updated at least once so that all assets (titles,
|
||||
// icons) are loaded. We keep track of which inputs haven't updated and
|
||||
// run an update on them after the first location change.
|
||||
this._inputsNotUpdated = new Set(Object.keys(kBuiltInInputs));
|
||||
|
||||
return layoutItems;
|
||||
}
|
||||
|
||||
@ -343,11 +342,11 @@ class TouchBarHelper {
|
||||
return this._searchPopover;
|
||||
}
|
||||
|
||||
if (!inputName || !kBuiltInInputs.hasOwnProperty(inputName)) {
|
||||
if (!inputName || !gBuiltInInputs.hasOwnProperty(inputName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let inputData = kBuiltInInputs[inputName];
|
||||
let inputData = gBuiltInInputs[inputName];
|
||||
|
||||
let item = new TouchBarInput(inputData);
|
||||
|
||||
@ -361,7 +360,7 @@ class TouchBarHelper {
|
||||
}
|
||||
|
||||
// Async l10n fills in the localized input labels after the initial load.
|
||||
this._l10n.formatValue(item.key).then(result => {
|
||||
this._l10n.formatValue(inputData.title).then(result => {
|
||||
item.title = result;
|
||||
localizedStrings[inputData.title] = result; // Cache result.
|
||||
// Checking TouchBarHelper.window since this callback can fire after all windows are closed.
|
||||
@ -381,7 +380,7 @@ class TouchBarHelper {
|
||||
/**
|
||||
* Fetches a specific Touch Bar Input by name and updates it on the Touch Bar.
|
||||
* @param {...*} inputNames
|
||||
* A key/keys to a value/values in the kBuiltInInputs object in this file.
|
||||
* A key/keys to a value/values in the gBuiltInInputs object in this file.
|
||||
*/
|
||||
_updateTouchBarInputs(...inputNames) {
|
||||
if (!TouchBarHelper.window || !inputNames.length) {
|
||||
@ -389,14 +388,13 @@ class TouchBarHelper {
|
||||
}
|
||||
|
||||
let inputs = [];
|
||||
for (let inputName of new Set(inputNames)) {
|
||||
for (let inputName of new Set([...inputNames, ...this._inputsNotUpdated])) {
|
||||
let input = this.getTouchBarInput(inputName);
|
||||
if (!input) {
|
||||
continue;
|
||||
}
|
||||
if (this._inputsNotUpdated) {
|
||||
this._inputsNotUpdated.delete(inputName);
|
||||
}
|
||||
|
||||
this._inputsNotUpdated.delete(inputName);
|
||||
inputs.push(input);
|
||||
}
|
||||
|
||||
@ -433,28 +431,43 @@ class TouchBarHelper {
|
||||
this.activeUrl = data;
|
||||
// ReaderView button is disabled on every location change since
|
||||
// Reader View must determine if the new page can be Reader Viewed.
|
||||
kBuiltInInputs.ReaderView.disabled = !data.startsWith("about:reader");
|
||||
kBuiltInInputs.Back.disabled = !TouchBarHelper.window.gBrowser
|
||||
gBuiltInInputs.ReaderView.disabled = !data.startsWith("about:reader");
|
||||
gBuiltInInputs.Back.disabled = !TouchBarHelper.window.gBrowser
|
||||
.canGoBack;
|
||||
kBuiltInInputs.Forward.disabled = !TouchBarHelper.window.gBrowser
|
||||
gBuiltInInputs.Forward.disabled = !TouchBarHelper.window.gBrowser
|
||||
.canGoForward;
|
||||
this._updateTouchBarInputs(
|
||||
"ReaderView",
|
||||
"Back",
|
||||
"Forward",
|
||||
...this._inputsNotUpdated
|
||||
);
|
||||
this._updateTouchBarInputs("ReaderView", "Back", "Forward");
|
||||
break;
|
||||
case "fullscreen-painted":
|
||||
if (TouchBarHelper.window.document.fullscreenElement) {
|
||||
gBuiltInInputs.OpenLocation.title = "touchbar-fullscreen-exit";
|
||||
gBuiltInInputs.OpenLocation.image =
|
||||
"chrome://browser/skin/fullscreen-exit.svg";
|
||||
gBuiltInInputs.OpenLocation.callback = () => {
|
||||
TouchBarHelper.window.windowUtils.exitFullscreen();
|
||||
let telemetry = Services.telemetry.getHistogramById(
|
||||
"TOUCHBAR_BUTTON_PRESSES"
|
||||
);
|
||||
telemetry.add("OpenLocation");
|
||||
};
|
||||
} else {
|
||||
gBuiltInInputs.OpenLocation.title = "open-location";
|
||||
gBuiltInInputs.OpenLocation.image =
|
||||
"chrome://browser/skin/search-glass.svg";
|
||||
gBuiltInInputs.OpenLocation.callback = () =>
|
||||
execCommand("Browser:OpenLocation", "OpenLocation");
|
||||
}
|
||||
this._updateTouchBarInputs("OpenLocation");
|
||||
break;
|
||||
case "bookmark-icon-updated":
|
||||
data == "starred"
|
||||
? (kBuiltInInputs.AddBookmark.image =
|
||||
"chrome://browser/skin/bookmark.svg")
|
||||
: (kBuiltInInputs.AddBookmark.image =
|
||||
"chrome://browser/skin/bookmark-hollow.svg");
|
||||
gBuiltInInputs.AddBookmark.image =
|
||||
data == "starred"
|
||||
? "chrome://browser/skin/bookmark.svg"
|
||||
: "chrome://browser/skin/bookmark-hollow.svg";
|
||||
this._updateTouchBarInputs("AddBookmark");
|
||||
break;
|
||||
case "reader-mode-available":
|
||||
kBuiltInInputs.ReaderView.disabled = false;
|
||||
gBuiltInInputs.ReaderView.disabled = false;
|
||||
this._updateTouchBarInputs("ReaderView");
|
||||
break;
|
||||
case "urlbar-focus":
|
||||
@ -487,7 +500,7 @@ class TouchBarHelper {
|
||||
this._l10n = new Localization(["browser/touchbar/touchbar.ftl"]);
|
||||
helperProto._l10n = this._l10n;
|
||||
|
||||
this._updateTouchBarInputs(...Object.keys(kBuiltInInputs));
|
||||
this._updateTouchBarInputs(...Object.keys(gBuiltInInputs));
|
||||
break;
|
||||
case "quit-application":
|
||||
this.destructor();
|
||||
|
@ -53,8 +53,8 @@ JavaScript API
|
||||
|
||||
``browser/components/touchbar/MacTouchBar.js`` defines what specific inputs are
|
||||
available to the user, what icon they will have, what action they will perform,
|
||||
and so on. Inputs are defined in the ``kBuiltInInputs`` object `in that file`_.
|
||||
When creating a new object in ``kBuiltInInputs``, the available properties are
|
||||
and so on. Inputs are defined in the ``gBuiltInInputs`` object `in that file`_.
|
||||
When creating a new object in ``gBuiltInInputs``, the available properties are
|
||||
documented in the JSDoc for ``TouchBarInput``:
|
||||
|
||||
.. highlight:: JavaScript
|
||||
@ -95,7 +95,7 @@ Clarification on some of these properties is warranted.
|
||||
second string, "Back", records an interaction with the back button in
|
||||
Telemetry.
|
||||
* ``children`` is an array of objects with the same properties as members of
|
||||
``kBuiltInInputs``. When used with an input of type
|
||||
``gBuiltInInputs``. When used with an input of type
|
||||
``kInputTypes.SCROLLVIEW``, ``children`` can only contain inputs of type
|
||||
``kInputTypes.BUTTON``. When used with an input of type
|
||||
``kInputTypes.POPOVER``, any input type except another ``kInputTypes.POPOVER``
|
||||
@ -159,7 +159,7 @@ Scroll View
|
||||
|
||||
Examples
|
||||
--------
|
||||
Some examples of ``kBuiltInInputs`` objects follow.
|
||||
Some examples of ``gBuiltInInputs`` objects follow.
|
||||
|
||||
A simple button
|
||||
.. highlight:: JavaScript
|
||||
@ -246,13 +246,13 @@ The search popover
|
||||
|
||||
Adding a new input
|
||||
------------------
|
||||
Adding a new input is easy: just add a new object to ``kBuiltInInputs``. This
|
||||
Adding a new input is easy: just add a new object to ``gBuiltInInputs``. This
|
||||
will make the input available in the Touch Bar customization window (accessible
|
||||
from the Firefox menu bar item).
|
||||
|
||||
If you want to to add your new input to the default set, add its identifier
|
||||
here_, where ``type`` is a value from ``kAllowedInputTypes`` in that
|
||||
file and ``key`` is the value you set for ``title`` in ``kBuiltInInputs``.
|
||||
file and ``key`` is the value you set for ``title`` in ``gBuiltInInputs``.
|
||||
You should request approval from UX before changing the default set of inputs.
|
||||
|
||||
.. _here: https://searchfox.org/mozilla-central/rev/ebe492edacc75bb122a2b380e4cafcca3470864c/widget/cocoa/nsTouchBar.mm#100
|
||||
@ -323,7 +323,7 @@ If you need to generate an identifier, use the convenience method
|
||||
will be erased.
|
||||
|
||||
Each identifier is tied to a ``TouchBarInput``. ``TouchBarInput`` is a class
|
||||
that holds the properties specified for each input in ``kBuiltInInputs``.
|
||||
that holds the properties specified for each input in ``gBuiltInInputs``.
|
||||
``nsTouchBar`` uses them to create instances of ``NSTouchBarItem``
|
||||
which are the actual objects used by Apple's Touch Bar API and displayed in the
|
||||
Touch Bar. It is important to understand the difference between
|
||||
|
@ -1,6 +1,8 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
readerModeArticle.html
|
||||
test-video.mp4
|
||||
video_test.html
|
||||
|
||||
[browser_touchbar_searchrestrictions.js]
|
||||
[browser_touchbar_tests.js]
|
||||
|
@ -19,6 +19,11 @@ XPCOMUtils.defineLazyServiceGetter(
|
||||
"nsITouchBarInput"
|
||||
);
|
||||
|
||||
const TEST_PATH = getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
);
|
||||
|
||||
function is_element_visible(aElement, aMsg) {
|
||||
isnot(aElement, null, "Element should not be null when checking visibility");
|
||||
ok(!BrowserTestUtils.is_hidden(aElement), aMsg);
|
||||
@ -74,10 +79,6 @@ add_task(async function updateReaderView() {
|
||||
"ReaderView Touch Bar button should be disabled by default."
|
||||
);
|
||||
|
||||
const TEST_PATH = getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
);
|
||||
let url = TEST_PATH + "readerModeArticle.html";
|
||||
await BrowserTestUtils.withNewTab(url, async function() {
|
||||
await BrowserTestUtils.waitForCondition(() => !readerButton.hidden);
|
||||
@ -89,3 +90,59 @@ add_task(async function updateReaderView() {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function updateMainButtonInFullscreen() {
|
||||
Assert.equal(
|
||||
TouchBarHelper.getTouchBarInput("OpenLocation").image.spec,
|
||||
"chrome://browser/skin/search-glass.svg",
|
||||
"OpenLocation should be displaying the search glass icon."
|
||||
);
|
||||
await BrowserTestUtils.loadURI(
|
||||
gBrowser.selectedBrowser,
|
||||
TEST_PATH + "video_test.html"
|
||||
);
|
||||
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
let entered = waitForFullScreenState(gBrowser.selectedBrowser, true);
|
||||
// Fullscreen video must be triggered from a user input handler so the video
|
||||
// page contains a script to enter fullscreen on Enter instead of us calling
|
||||
// requestFullscreen directly here.
|
||||
EventUtils.synthesizeKey("KEY_Enter");
|
||||
await entered;
|
||||
Assert.equal(
|
||||
TouchBarHelper.getTouchBarInput("OpenLocation").image.spec,
|
||||
"chrome://browser/skin/fullscreen-exit.svg",
|
||||
"OpenLocation should be displaying the exit fullscreen icon."
|
||||
);
|
||||
let exited = waitForFullScreenState(gBrowser.selectedBrowser, false);
|
||||
EventUtils.synthesizeKey("KEY_Enter");
|
||||
await exited;
|
||||
Assert.equal(
|
||||
TouchBarHelper.getTouchBarInput("OpenLocation").image.spec,
|
||||
"chrome://browser/skin/search-glass.svg",
|
||||
"OpenLocation should be displaying the search glass icon."
|
||||
);
|
||||
});
|
||||
|
||||
function waitForFullScreenState(browser, state) {
|
||||
info("inside waitforfullscreenstate");
|
||||
return new Promise(resolve => {
|
||||
let eventReceived = false;
|
||||
|
||||
let observe = (subject, topic, data) => {
|
||||
if (!eventReceived) {
|
||||
return;
|
||||
}
|
||||
Services.obs.removeObserver(observe, "fullscreen-painted");
|
||||
resolve();
|
||||
};
|
||||
Services.obs.addObserver(observe, "fullscreen-painted");
|
||||
|
||||
window.addEventListener(
|
||||
`MozDOMFullscreen:${state ? "Entered" : "Exited"}`,
|
||||
() => {
|
||||
eventReceived = true;
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
BIN
browser/components/touchbar/tests/browser/test-video.mp4
Normal file
BIN
browser/components/touchbar/tests/browser/test-video.mp4
Normal file
Binary file not shown.
32
browser/components/touchbar/tests/browser/video_test.html
Normal file
32
browser/components/touchbar/tests/browser/video_test.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Touch Bar Fullscreen Video Test</title>
|
||||
</head>
|
||||
<style>
|
||||
video {
|
||||
display: block;
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<video id="test-video" src="test-video.mp4" controls loop="true"></video>
|
||||
</body>
|
||||
<script>
|
||||
let video = document.getElementById("test-video");
|
||||
|
||||
function toggleFullScreen() {
|
||||
if (!document.fullscreenElement) {
|
||||
document.documentElement.requestFullscreen();
|
||||
} else if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
}
|
||||
document.addEventListener("keydown", function(e) {
|
||||
if (e.keyCode == 13) {
|
||||
toggleFullScreen();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</html>
|
@ -9,6 +9,7 @@ forward = Forward
|
||||
reload = Reload
|
||||
home = Home
|
||||
fullscreen = Fullscreen
|
||||
touchbar-fullscreen-exit = Exit Fullscreen
|
||||
find = Find
|
||||
new-tab = New tab
|
||||
add-bookmark = Add bookmark
|
||||
|
Loading…
Reference in New Issue
Block a user