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.ClientSession}
24 this.clientSession_
= 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.ClientSession} clientSession The client session, or null if
108 * there is no connection.
110 remoting
.WindowFrame
.prototype.setClientSession = function(clientSession
) {
111 this.clientSession_
= clientSession
;
112 var windowTitle
= document
.head
.querySelector('title');
113 if (this.clientSession_
) {
114 this.title_
.innerText
= clientSession
.getHostDisplayName();
115 windowTitle
.innerText
= clientSession
.getHostDisplayName() + ' - ' +
116 chrome
.i18n
.getMessage(/*i18n-content*/'PRODUCT_NAME');
118 this.title_
.innerHTML
= ' ';
119 windowTitle
.innerText
=
120 chrome
.i18n
.getMessage(/*i18n-content*/'PRODUCT_NAME');
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;