diff --git a/app/static/js/app.js b/app/static/js/app.js index 8109b28e7..72feffe7c 100644 --- a/app/static/js/app.js +++ b/app/static/js/app.js @@ -331,6 +331,18 @@ menuBar.addEventListener("keystroke-history-toggled", () => { menuBar.addEventListener("keyboard-visibility-toggled", () => { onScreenKeyboard.show(!onScreenKeyboard.isShown()); }); +menuBar.addEventListener("dedicated-window-requested", () => { + // Open popup window in standalone view mode (without menu bar or status bar). + window.open("/?viewMode=standalone", undefined, "popup=true"); + + // Redirect the user to a placeholder page. We can’t keep the main window + // open as is, because then we’d have a duplicate video stream (which would + // result in twice the bandwidth consumption), or we’d risk inconsistent view + // state, or ambiguous control flows between the two windows. + // Leaving the main page via an external redirect is a rather pragmatic yet + // effective approach to ensure proper teardown of the main window resources. + window.location = "/dedicated-window-placeholder"; +}); menuBar.addEventListener("shutdown-dialog-requested", () => { document.getElementById("shutdown-overlay").show(); }); diff --git a/app/templates/custom-elements/menu-bar.html b/app/templates/custom-elements/menu-bar.html index 9b706da8b..da662e1f0 100644 --- a/app/templates/custom-elements/menu-bar.html +++ b/app/templates/custom-elements/menu-bar.html @@ -48,6 +48,10 @@ user-select: none; } + :host([logo-only]) ul { + display: none; + } + .logo { position: relative; box-sizing: border-box; @@ -265,6 +269,11 @@ >Full Screen + diff --git a/app/templates/dedicated-window-placeholder.html b/app/templates/dedicated-window-placeholder.html new file mode 100644 index 000000000..64103b077 --- /dev/null +++ b/app/templates/dedicated-window-placeholder.html @@ -0,0 +1,56 @@ + + + + + + + {{ page_title_prefix }}TinyPilot + + + + + + {% include 'custom-elements/menu-bar.html' %} + +
+ + +
+ +

+ The remote screen is displaying in another browser window.
+ To restore the remote screen in this window, please refresh the page. +

+ + + diff --git a/app/views.py b/app/views.py index a0748c36d..9c20c8756 100644 --- a/app/views.py +++ b/app/views.py @@ -34,6 +34,12 @@ def styleguide_get(): return flask.abort(404) +@views_blueprint.route('/dedicated-window-placeholder', methods=['GET']) +def dedicated_window_placeholder_get(): + return flask.render_template('dedicated-window-placeholder.html', + page_title_prefix=_page_title_prefix()) + + # On a real install, nginx redirects the /stream route to uStreamer, so a real # user should never hit this route in production. In development, show a fake # still image to give a better sense of how the TinyPilot UI looks.