1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * Apps v2 custom title bar implementation
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
16 * @param {HTMLElement} titleBar The root node of the title-bar DOM hierarchy.
19 remoting.WindowFrame = function(titleBar) {
21 * @type {remoting.DesktopConnectedView}
24 this.desktopConnectedView_ = null;
30 this.titleBar_ = titleBar;
36 this.title_ = /** @type {HTMLElement} */
37 (titleBar.querySelector('.window-title'));
38 base.debug.assert(this.title_ != null);
44 this.maximizeRestoreControl_ = /** @type {HTMLElement} */
45 (titleBar.querySelector('.window-maximize-restore'));
46 base.debug.assert(this.maximizeRestoreControl_ != null);
48 var optionsButton = titleBar.querySelector('.window-options');
49 base.debug.assert(optionsButton != null);
50 this.optionMenuButton_ = new remoting.MenuButton(
52 this.onShowOptionsMenu_.bind(this),
53 this.onHideOptionsMenu_.bind(this));
59 this.optionsMenuList_ = /** @type {HTMLElement} */
60 (optionsButton.querySelector('.window-options-menu'));
61 base.debug.assert(this.optionsMenuList_ != null);
64 * @type {Array<{cls:string, fn: function()}>}
67 { cls: 'window-disconnect', fn: this.disconnectSession_.bind(this) },
68 { cls: 'window-maximize-restore',
69 fn: this.maximizeOrRestoreWindow_.bind(this) },
70 { cls: 'window-minimize', fn: this.minimizeWindow_.bind(this) },
71 { cls: 'window-close', fn: window.close.bind(window) },
72 { cls: 'window-controls-stub', fn: this.toggleWindowControls_.bind(this) }
74 for (var i = 0; i < handlers.length; ++i) {
75 var element = titleBar.querySelector('.' + handlers[i].cls);
76 base.debug.assert(element != null);
77 element.addEventListener('click', handlers[i].fn, false);
80 // Ensure that tool-tips are always correct.
81 this.handleWindowStateChange_();
82 chrome.app.window.current().onMaximized.addListener(
83 this.handleWindowStateChange_.bind(this));
84 chrome.app.window.current().onRestored.addListener(
85 this.handleWindowStateChange_.bind(this));
86 chrome.app.window.current().onFullscreened.addListener(
87 this.handleWindowStateChange_.bind(this));
88 chrome.app.window.current().onFullscreened.addListener(
89 this.showWindowControlsPreview_.bind(this));
93 * @return {remoting.OptionsMenu}
95 remoting.WindowFrame.prototype.createOptionsMenu = function() {
96 return new remoting.OptionsMenu(
97 this.titleBar_.querySelector('.menu-send-ctrl-alt-del'),
98 this.titleBar_.querySelector('.menu-send-print-screen'),
99 this.titleBar_.querySelector('.menu-resize-to-client'),
100 this.titleBar_.querySelector('.menu-shrink-to-fit'),
101 this.titleBar_.querySelector('.menu-new-connection'),
102 this.titleBar_.querySelector('.window-fullscreen'),
103 this.titleBar_.querySelector('.menu-start-stop-recording'));
107 * @param {remoting.DesktopConnectedView} desktopConnectedView The view for the
108 * current session, or null if there is no connection.
110 remoting.WindowFrame.prototype.setDesktopConnectedView = function(
111 desktopConnectedView) {
112 this.desktopConnectedView_ = desktopConnectedView;
113 var windowTitle = document.head.querySelector('title');
114 if (this.desktopConnectedView_) {
115 this.title_.innerText = desktopConnectedView.getHostDisplayName();
116 windowTitle.innerText = desktopConnectedView.getHostDisplayName() + ' - ' +
117 remoting.app.getApplicationName();
119 this.title_.innerHTML = ' ';
120 windowTitle.innerText = remoting.app.getApplicationName();
122 this.handleWindowStateChange_();
126 * @return {{width: number, height: number}} The size of the window, ignoring
127 * the title-bar and window borders, if visible.
129 remoting.WindowFrame.prototype.getClientArea = function() {
130 if (chrome.app.window.current().isFullscreen()) {
131 return { 'height': window.innerHeight, 'width': window.innerWidth };
133 var kBorderWidth = 1;
134 var titleHeight = this.titleBar_.clientHeight;
136 'height': window.innerHeight - titleHeight - 2 * kBorderWidth,
137 'width': window.innerWidth - 2 * kBorderWidth
145 remoting.WindowFrame.prototype.disconnectSession_ = function() {
146 // When the user disconnects, exit full-screen mode. This should not be
147 // necessary, as we do the same thing in client_session.js when the plugin
148 // is removed. However, there seems to be a bug in chrome.AppWindow.restore
149 // that causes it to get stuck in full-screen mode without this.
150 if (chrome.app.window.current().isFullscreen()) {
151 chrome.app.window.current().restore();
153 remoting.disconnect();
159 remoting.WindowFrame.prototype.maximizeOrRestoreWindow_ = function() {
160 /** @type {boolean} */
162 chrome.app.window.current().isFullscreen() ||
163 chrome.app.window.current().isMaximized();
165 chrome.app.window.current().restore();
167 chrome.app.window.current().maximize();
174 remoting.WindowFrame.prototype.minimizeWindow_ = function() {
175 chrome.app.window.current().minimize();
181 remoting.WindowFrame.prototype.toggleWindowControls_ = function() {
182 this.titleBar_.classList.toggle('opened');
186 * Update the tool-top for the maximize/full-screen/restore icon to reflect
187 * its current behaviour.
191 remoting.WindowFrame.prototype.handleWindowStateChange_ = function() {
192 // Set the title for the maximize/restore/full-screen button
193 /** @type {string} */
195 if (chrome.app.window.current().isFullscreen()) {
196 tag = /*i18n-content*/'EXIT_FULL_SCREEN';
197 } else if (chrome.app.window.current().isMaximized()) {
198 tag = /*i18n-content*/'RESTORE_WINDOW';
200 tag = /*i18n-content*/'MAXIMIZE_WINDOW';
202 this.maximizeRestoreControl_.title = l10n.getTranslationOrError(tag);
204 // Ensure that the options menu aligns correctly for the side of the window
206 if (chrome.app.window.current().isFullscreen()) {
207 this.optionsMenuList_.classList.add('right-align');
209 this.optionsMenuList_.classList.remove('right-align');
214 * Callback invoked when the options menu is shown.
217 remoting.WindowFrame.prototype.onShowOptionsMenu_ = function() {
218 remoting.optionsMenu.onShow();
219 this.titleBar_.classList.add('menu-opened');
223 * Callback invoked when the options menu is shown.
226 remoting.WindowFrame.prototype.onHideOptionsMenu_ = function() {
227 this.titleBar_.classList.remove('menu-opened');
231 * Show the window controls for a few seconds
235 remoting.WindowFrame.prototype.showWindowControlsPreview_ = function() {
237 * @type {HTMLElement}
239 var target = this.titleBar_;
240 var kPreviewTimeoutMs = 3000;
241 var hidePreview = function() {
242 target.classList.remove('preview');
244 target.classList.add('preview');
245 window.setTimeout(hidePreview, kPreviewTimeoutMs);
249 /** @type {remoting.WindowFrame} */
250 remoting.windowFrame = null;