Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / remoting / webapp / window_frame.js
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.
4
5 /**
6  * @fileoverview
7  * Apps v2 custom title bar implementation
8  */
9
10 'use strict';
11
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
14
15 /**
16  * @param {HTMLElement} titleBar The root node of the title-bar DOM hierarchy.
17  * @constructor
18  */
19 remoting.WindowFrame = function(titleBar) {
20   /**
21    * @type {remoting.ClientSession}
22    * @private
23    */
24   this.clientSession_ = null;
25
26   /**
27    * @type {HTMLElement}
28    * @private
29    */
30   this.titleBar_ = titleBar;
31
32   /**
33    * @type {HTMLElement}
34    * @private
35    */
36   this.title_ = /** @type {HTMLElement} */
37       (titleBar.querySelector('.window-title'));
38   base.debug.assert(this.title_ != null);
39
40   /**
41    * @type {HTMLElement}
42    * @private
43    */
44   this.maximizeRestoreControl_ = /** @type {HTMLElement} */
45       (titleBar.querySelector('.window-maximize-restore'));
46   base.debug.assert(this.maximizeRestoreControl_ != null);
47
48   var optionsButton = titleBar.querySelector('.window-options');
49   base.debug.assert(optionsButton != null);
50   this.optionMenuButton_ = new remoting.MenuButton(
51       optionsButton,
52       this.onShowOptionsMenu_.bind(this),
53       this.onHideOptionsMenu_.bind(this));
54
55   /**
56    * @type {HTMLElement}
57    * @private
58    */
59   this.optionsMenuList_ = /** @type {HTMLElement} */
60       (optionsButton.querySelector('.window-options-menu'));
61   base.debug.assert(this.optionsMenuList_ != null);
62
63   /**
64    * @type {Array.<{cls:string, fn: function()}>}
65    */
66   var handlers = [
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) }
73   ];
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);
78   }
79
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));
90 };
91
92 /**
93  * @return {remoting.OptionsMenu}
94  */
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'));
104 };
105
106 /**
107  * @param {remoting.ClientSession} clientSession The client session, or null if
108  *     there is no connection.
109  */
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');
117   } else {
118     this.title_.innerHTML = '&nbsp;';
119     windowTitle.innerText =
120         chrome.i18n.getMessage(/*i18n-content*/'PRODUCT_NAME');
121   }
122   this.handleWindowStateChange_();
123 };
124
125 /**
126  * @return {{width: number, height: number}} The size of the window, ignoring
127  *     the title-bar and window borders, if visible.
128  */
129 remoting.WindowFrame.prototype.getClientArea = function() {
130   if (chrome.app.window.current().isFullscreen()) {
131     return { 'height': window.innerHeight, 'width': window.innerWidth };
132   } else {
133     var kBorderWidth = 1;
134     var titleHeight = this.titleBar_.clientHeight;
135     return {
136       'height': window.innerHeight - titleHeight - 2 * kBorderWidth,
137       'width': window.innerWidth - 2 * kBorderWidth
138     };
139   }
140 };
141
142 /**
143  * @private
144  */
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();
152   }
153   remoting.disconnect();
154 };
155
156 /**
157  * @private
158  */
159 remoting.WindowFrame.prototype.maximizeOrRestoreWindow_ = function() {
160   /** @type {boolean} */
161   var restore =
162       chrome.app.window.current().isFullscreen() ||
163       chrome.app.window.current().isMaximized();
164   if (restore) {
165     chrome.app.window.current().restore();
166   } else {
167     chrome.app.window.current().maximize();
168   }
169 };
170
171 /**
172  * @private
173  */
174 remoting.WindowFrame.prototype.minimizeWindow_ = function() {
175   chrome.app.window.current().minimize();
176 };
177
178 /**
179  * @private
180  */
181 remoting.WindowFrame.prototype.toggleWindowControls_ = function() {
182   this.titleBar_.classList.toggle('opened');
183 };
184
185 /**
186  * Update the tool-top for the maximize/full-screen/restore icon to reflect
187  * its current behaviour.
188  *
189  * @private
190  */
191 remoting.WindowFrame.prototype.handleWindowStateChange_ = function() {
192   // Set the title for the maximize/restore/full-screen button
193   /** @type {string} */
194   var tag = '';
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';
199   } else {
200     tag = /*i18n-content*/'MAXIMIZE_WINDOW';
201   }
202   this.maximizeRestoreControl_.title = l10n.getTranslationOrError(tag);
203
204   // Ensure that the options menu aligns correctly for the side of the window
205   // it occupies.
206   if (chrome.app.window.current().isFullscreen()) {
207     this.optionsMenuList_.classList.add('right-align');
208   } else {
209     this.optionsMenuList_.classList.remove('right-align');
210   }
211 };
212
213 /**
214  * Callback invoked when the options menu is shown.
215  * @private
216  */
217 remoting.WindowFrame.prototype.onShowOptionsMenu_ = function() {
218   remoting.optionsMenu.onShow();
219   this.titleBar_.classList.add('menu-opened');
220 };
221
222 /**
223  * Callback invoked when the options menu is shown.
224  * @private
225  */
226 remoting.WindowFrame.prototype.onHideOptionsMenu_ = function() {
227   this.titleBar_.classList.remove('menu-opened');
228 };
229
230 /**
231  * Show the window controls for a few seconds
232  *
233  * @private
234  */
235 remoting.WindowFrame.prototype.showWindowControlsPreview_ = function() {
236   /**
237    * @type {HTMLElement}
238    */
239   var target =  this.titleBar_;
240   var kPreviewTimeoutMs = 3000;
241   var hidePreview = function() {
242     target.classList.remove('preview');
243   };
244   target.classList.add('preview');
245   window.setTimeout(hidePreview, kPreviewTimeoutMs);
246 };
247
248
249 /** @type {remoting.WindowFrame} */
250 remoting.windowFrame = null;