Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / remoting / webapp / crd / js / window_frame.js
blobfc5046e7597bfa30f7785d1ab69880a9b0b6e088
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.
5 /**
6  * @fileoverview
7  * Apps v2 custom title bar implementation
8  */
10 'use strict';
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
15 /**
16  * @param {HTMLElement} titleBar The root node of the title-bar DOM hierarchy.
17  * @param {function()} disconnectCallback Callback for disconnecting the
18  *     session.
19  * @constructor
20  */
21 remoting.WindowFrame = function(titleBar, disconnectCallback) {
22   /** @private {remoting.DesktopConnectedView} */
23   this.desktopConnectedView_ = null;
25   /** @private {HTMLElement} */
26   this.titleBar_ = titleBar;
28   /** @private {HTMLElement} */
29   this.title_ = /** @type {HTMLElement} */
30       (titleBar.querySelector('.window-title'));
31   console.assert(this.title_ != null, 'Missing title element.');
33   /** @private {HTMLElement} */
34   this.maximizeRestoreControl_ = /** @type {HTMLElement} */
35       (titleBar.querySelector('.window-maximize-restore'));
36   console.assert(this.maximizeRestoreControl_ != null,
37                  'Missing maximize/restore control.');
39   var optionsButton = titleBar.querySelector('.window-options');
40   console.assert(optionsButton != null, 'Missing options button.');
41   this.optionMenuButton_ = new remoting.MenuButton(
42       optionsButton,
43       this.onShowOptionsMenu_.bind(this),
44       this.onHideOptionsMenu_.bind(this));
46   /** @private {HTMLElement} */
47   this.optionsMenuList_ = /** @type {HTMLElement} */
48       (optionsButton.querySelector('.window-options-menu'));
49   console.assert(this.optionsMenuList_ != null, 'Missing options menu.');
51   /**
52    * @type {Array<{cls:string, fn: function()}>}
53    */
54   var handlers = [
55     { cls: 'window-disconnect', fn: disconnectCallback },
56     { cls: 'window-maximize-restore',
57       fn: this.maximizeOrRestoreWindow_.bind(this) },
58     { cls: 'window-minimize', fn: this.minimizeWindow_.bind(this) },
59     { cls: 'window-close', fn: remoting.app.quit.bind(remoting.app) },
60     { cls: 'window-controls-stub', fn: this.toggleWindowControls_.bind(this) }
61   ];
62   for (var i = 0; i < handlers.length; ++i) {
63     var element = titleBar.querySelector('.' + handlers[i].cls);
64     console.assert(element != null, 'Missing class: ' + handlers[i].cls + '.');
65     element.addEventListener('click', handlers[i].fn, false);
66   }
68   // Ensure that tool-tips are always correct.
69   this.handleWindowStateChange_();
70   chrome.app.window.current().onMaximized.addListener(
71       this.handleWindowStateChange_.bind(this));
72   chrome.app.window.current().onRestored.addListener(
73       this.handleWindowStateChange_.bind(this));
74   chrome.app.window.current().onFullscreened.addListener(
75       this.handleWindowStateChange_.bind(this));
76   chrome.app.window.current().onFullscreened.addListener(
77       this.showWindowControlsPreview_.bind(this));
80 /**
81  * @return {remoting.OptionsMenu}
82  */
83 remoting.WindowFrame.prototype.createOptionsMenu = function() {
84   return new remoting.OptionsMenu(
85       this.titleBar_.querySelector('.menu-send-ctrl-alt-del'),
86       this.titleBar_.querySelector('.menu-send-print-screen'),
87       this.titleBar_.querySelector('.menu-map-right-ctrl-to-meta'),
88       this.titleBar_.querySelector('.menu-resize-to-client'),
89       this.titleBar_.querySelector('.menu-shrink-to-fit'),
90       this.titleBar_.querySelector('.menu-new-window'),
91       this.titleBar_.querySelector('.window-fullscreen'),
92       this.titleBar_.querySelector('.menu-toggle-connection-stats'),
93       this.titleBar_.querySelector('.menu-start-stop-recording'));
96 /**
97  * @param {remoting.DesktopConnectedView} desktopConnectedView The view for the
98  *     current session, or null if there is no connection.
99  */
100 remoting.WindowFrame.prototype.setDesktopConnectedView = function(
101     desktopConnectedView) {
102   this.desktopConnectedView_ = desktopConnectedView;
103   var windowTitle = document.head.querySelector('title');
104   if (this.desktopConnectedView_) {
105     this.title_.innerText = desktopConnectedView.getHostDisplayName();
106     windowTitle.innerText = desktopConnectedView.getHostDisplayName() + ' - ' +
107         remoting.app.getApplicationName();
108   } else {
109     this.title_.innerHTML = '&nbsp;';
110     windowTitle.innerText = remoting.app.getApplicationName();
111   }
112   this.handleWindowStateChange_();
116  * @return {{width: number, height: number}} The size of the window, ignoring
117  *     the title-bar and window borders, if visible.
118  */
119 remoting.WindowFrame.prototype.getClientArea = function() {
120   if (chrome.app.window.current().isFullscreen()) {
121     return { 'height': window.innerHeight, 'width': window.innerWidth };
122   } else {
123     var kBorderWidth = 1;
124     var titleHeight = this.titleBar_.clientHeight;
125     return {
126       'height': window.innerHeight - titleHeight - 2 * kBorderWidth,
127       'width': window.innerWidth - 2 * kBorderWidth
128     };
129   }
133  * @private
134  */
135 remoting.WindowFrame.prototype.maximizeOrRestoreWindow_ = function() {
136   /** @type {boolean} */
137   var restore =
138       chrome.app.window.current().isFullscreen() ||
139       chrome.app.window.current().isMaximized();
140   if (restore) {
141     chrome.app.window.current().restore();
142   } else {
143     chrome.app.window.current().maximize();
144   }
148  * @private
149  */
150 remoting.WindowFrame.prototype.minimizeWindow_ = function() {
151   chrome.app.window.current().minimize();
155  * @private
156  */
157 remoting.WindowFrame.prototype.toggleWindowControls_ = function() {
158   this.titleBar_.classList.toggle('opened');
162  * Update the tool-top for the maximize/full-screen/restore icon to reflect
163  * its current behaviour.
165  * @private
166  */
167 remoting.WindowFrame.prototype.handleWindowStateChange_ = function() {
168   // Set the title for the maximize/restore/full-screen button
169   /** @type {string} */
170   var tag = '';
171   if (chrome.app.window.current().isFullscreen()) {
172     tag = /*i18n-content*/'EXIT_FULL_SCREEN';
173   } else if (chrome.app.window.current().isMaximized()) {
174     tag = /*i18n-content*/'RESTORE_WINDOW';
175   } else {
176     tag = /*i18n-content*/'MAXIMIZE_WINDOW';
177   }
178   this.maximizeRestoreControl_.title = l10n.getTranslationOrError(tag);
180   // Ensure that the options menu aligns correctly for the side of the window
181   // it occupies.
182   if (chrome.app.window.current().isFullscreen()) {
183     this.optionsMenuList_.classList.add('right-align');
184   } else {
185     this.optionsMenuList_.classList.remove('right-align');
186   }
190  * Callback invoked when the options menu is shown.
191  * @private
192  */
193 remoting.WindowFrame.prototype.onShowOptionsMenu_ = function() {
194   remoting.optionsMenu.onShow();
195   this.titleBar_.classList.add('menu-opened');
199  * Callback invoked when the options menu is shown.
200  * @private
201  */
202 remoting.WindowFrame.prototype.onHideOptionsMenu_ = function() {
203   this.titleBar_.classList.remove('menu-opened');
207  * Show the window controls for a few seconds
209  * @private
210  */
211 remoting.WindowFrame.prototype.showWindowControlsPreview_ = function() {
212   /**
213    * @type {HTMLElement}
214    */
215   var target =  this.titleBar_;
216   var kPreviewTimeoutMs = 3000;
217   var hidePreview = function() {
218     target.classList.remove('preview');
219   };
220   target.classList.add('preview');
221   window.setTimeout(hidePreview, kPreviewTimeoutMs);
225 /** @type {remoting.WindowFrame} */
226 remoting.windowFrame = null;