• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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} */
13var remoting = remoting || {};
14
15/**
16 * @param {HTMLElement} titleBar The root node of the title-bar DOM hierarchy.
17 * @constructor
18 */
19remoting.WindowFrame = function(titleBar) {
20  /**
21   * @type {boolean}
22   * @private
23   */
24  this.isConnected_ = false;
25
26  /**
27   * @type {HTMLElement}
28   * @private
29   */
30  this.titleBar_ = titleBar;
31
32  /**
33   * @type {HTMLElement}
34   * @private
35   */
36  this.hoverTarget_ = /** @type {HTMLElement} */
37      (titleBar.querySelector('.window-controls-hover-target'));
38  base.debug.assert(this.hoverTarget_ != 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  /**
49   * @type {Array.<{cls:string, fn: function()}>}
50   */
51  var handlers = [
52    { cls: 'window-disconnect', fn: this.disconnectSession_.bind(this) },
53    { cls: 'window-maximize-restore',
54      fn: this.maximizeOrRestoreWindow_.bind(this) },
55    { cls: 'window-minimize', fn: this.minimizeWindow_.bind(this) },
56    { cls: 'window-close', fn: window.close.bind(window) },
57    { cls: 'window-controls-stub', fn: this.toggleWindowControls_.bind(this) }
58  ];
59  for (var i = 0; i < handlers.length; ++i) {
60    var element = titleBar.querySelector('.' + handlers[i].cls);
61    base.debug.assert(element != null);
62    element.addEventListener('click', handlers[i].fn, false);
63  }
64
65  // Ensure that tool-tips are always correct.
66  this.updateMaximizeOrRestoreIconTitle_();
67  chrome.app.window.current().onMaximized.addListener(
68      this.updateMaximizeOrRestoreIconTitle_.bind(this));
69  chrome.app.window.current().onRestored.addListener(
70      this.updateMaximizeOrRestoreIconTitle_.bind(this));
71  chrome.app.window.current().onFullscreened.addListener(
72      this.updateMaximizeOrRestoreIconTitle_.bind(this));
73};
74
75/**
76 * @param {boolean} isConnected True if there is a connection active.
77 */
78remoting.WindowFrame.prototype.setConnected = function(isConnected) {
79  this.isConnected_ = isConnected;
80  if (this.isConnected_) {
81    document.body.classList.add('connected');
82  } else {
83    document.body.classList.remove('connected');
84  }
85  this.updateMaximizeOrRestoreIconTitle_();
86};
87
88/**
89 * @return {{width: number, height: number}} The size of the window, ignoring
90 *     the title-bar and window borders, if visible.
91 */
92remoting.WindowFrame.prototype.getClientArea = function() {
93  if (chrome.app.window.current().isFullscreen()) {
94    return { 'height': window.innerHeight, 'width': window.innerWidth };
95  } else {
96    var kBorderWidth = 1;
97    var titleHeight = this.titleBar_.clientHeight;
98    return {
99      'height': window.innerHeight - titleHeight - 2 * kBorderWidth,
100      'width': window.innerWidth - 2 * kBorderWidth
101    };
102  }
103};
104
105/**
106 * @private
107 */
108remoting.WindowFrame.prototype.disconnectSession_ = function() {
109  // When the user disconnects, exit full-screen mode. This should not be
110  // necessary, as we do the same thing in client_session.js when the plugin
111  // is removed. However, there seems to be a bug in chrome.AppWindow.restore
112  // that causes it to get stuck in full-screen mode without this.
113  if (chrome.app.window.current().isFullscreen()) {
114    chrome.app.window.current().restore();
115  }
116  remoting.disconnect();
117};
118
119/**
120 * @private
121 */
122remoting.WindowFrame.prototype.maximizeOrRestoreWindow_ = function() {
123  /** @type {boolean} */
124  var restore =
125      chrome.app.window.current().isFullscreen() ||
126      chrome.app.window.current().isMaximized();
127  if (restore) {
128    // Restore twice: once to exit full-screen and once to exit maximized.
129    // If the app is not full-screen, or went full-screen without first
130    // being maximized, then the second restore has no effect.
131    chrome.app.window.current().restore();
132  } else if (this.isConnected_) {
133    chrome.app.window.current().fullscreen();
134  } else {
135    chrome.app.window.current().maximize();
136  }
137};
138
139/**
140 * @private
141 */
142remoting.WindowFrame.prototype.minimizeWindow_ = function() {
143  chrome.app.window.current().minimize();
144};
145
146/**
147 * @private
148 */
149remoting.WindowFrame.prototype.toggleWindowControls_ = function() {
150  this.hoverTarget_.classList.toggle('opened');
151};
152
153/**
154 * Update the tool-top for the maximize/full-screen/restore icon to reflect
155 * its current behaviour.
156 *
157 * @private
158 */
159remoting.WindowFrame.prototype.updateMaximizeOrRestoreIconTitle_ = function() {
160  /** @type {string} */
161  var tag = '';
162  if (chrome.app.window.current().isFullscreen()) {
163    tag = /*i18n-content*/'EXIT_FULL_SCREEN';
164  } else if (chrome.app.window.current().isMaximized()) {
165    tag = /*i18n-content*/'RESTORE_WINDOW';
166  } else if (this.isConnected_) {
167    tag = /*i18n-content*/'FULL_SCREEN';
168  } else {
169    tag = /*i18n-content*/'MAXIMIZE_WINDOW';
170  }
171  this.maximizeRestoreControl_.title = l10n.getTranslationOrError(tag);
172};
173
174/** @type {remoting.WindowFrame} */
175remoting.windowFrame = null;
176