Commit 983cb2f7 authored by jamiewalch's avatar jamiewalch Committed by Commit bot

Separate menu & disconnect buttons from the window controls and clean up CSS.

One piece of feedback we've received is that users want an
explicit full-screen control rather than tying it to
maximize. Simply adding a full-screen button means that the
window has six icons of varying crypticness (crypticality?)

This CL prepares the ground for adding a full-screen button
while reducing clutter. It moves the Options and Disconnect
buttons to the left-hand side of the window, while leaving
them adjacent to the window controls in full-screen mode.

There are two main changes to the CSS. The first is that we
no longer use "display: table"; I thought this was needed to
get rid of the implicit spaces between the icons, but
"display: flex" does the job just as well. The second is to
do with how the etched borders are rendered. Previously, a
button was responsible for rending both the light and dark
highlights to the left and bottom. This worked because they
were all right-aligned, but with the new layout, each button
renders all of its borders.

Review URL: https://codereview.chromium.org/498813003

Cr-Commit-Position: refs/heads/master@{#291745}
parent 4739a2c5
...@@ -21,7 +21,7 @@ found in the LICENSE file. ...@@ -21,7 +21,7 @@ found in the LICENSE file.
<title i18n-content="PRODUCT_NAME"></title> <title i18n-content="PRODUCT_NAME"></title>
</head> </head>
<body class="full-height inner-border-for-apps-v2"> <body class="full-height">
<meta-include src="webapp/html/window_frame.html"/> <meta-include src="webapp/html/window_frame.html"/>
......
...@@ -4,54 +4,52 @@ Use of this source code is governed by a BSD-style license that can be ...@@ -4,54 +4,52 @@ Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. found in the LICENSE file.
--> -->
<div id="title-bar" class="title-bar apps-v2-only"> <div id="title-bar" class="title-bar apps-v2-only">
<span class="window-title">&nbsp;</span> <div class="window-controls-and-title">
<span class="window-controls-hover-target"> <span i18n-title="OPTIONS_MENU"
<div class="window-controls"> class="window-control window-options menu-button">
<span i18n-title="OPTIONS_MENU" <span class="menu-button-activator">
class="window-control window-options menu-button"> <img src="icon_options.webp">
<span class="menu-button-activator">
<img src="icon_options.webp">
</span>
<ul class="window-options-menu right-align">
<li class="menu-start-stop-recording"
i18n-content="START_RECORDING"
hidden></li>
<li class="menu-send-ctrl-alt-del"
i18n-content="SEND_CTRL_ALT_DEL"></li>
<li class="menu-send-print-screen"
i18n-content="SEND_PRINT_SCREEN"></li>
<li class="menu-separator"></li>
<li class="menu-resize-to-client"
i18n-content="RESIZE_TO_CLIENT"></li>
<li class="menu-shrink-to-fit"
i18n-content="SHRINK_TO_FIT"></li>
<li class="menu-separator"></li>
<li class="menu-new-connection"
i18n-content="NEW_CONNECTION"></li>
<li class="menu-separator"></li>
<li class="menu-help"
i18n-content="HELP"></li>
<li class="menu-feedback"
i18n-content="ACTIONBAR_FEEDBACK"></li>
</ul>
</span> </span>
<span i18n-title="DISCONNECT_MYSELF_BUTTON" <ul class="window-options-menu right-align">
class="window-control window-disconnect"> <li class="menu-start-stop-recording"
<img src="icon_disconnect.webp"> i18n-content="START_RECORDING"
</span> hidden></li>
<span i18n-title="MINIMIZE_WINDOW" <li class="menu-send-ctrl-alt-del"
class="window-control window-minimize"> i18n-content="SEND_CTRL_ALT_DEL"></li>
<img src="icon_minimize.webp"> <li class="menu-send-print-screen"
</span> i18n-content="SEND_PRINT_SCREEN"></li>
<span i18n-title="MAXIMIZE_WINDOW" <li class="menu-separator"></li>
class="window-control window-maximize-restore"> <li class="menu-resize-to-client"
<img src="icon_maximize_restore.webp"> i18n-content="RESIZE_TO_CLIENT"></li>
</span> <li class="menu-shrink-to-fit"
<span i18n-title="CLOSE_WINDOW" i18n-content="SHRINK_TO_FIT"></li>
class="window-control window-close"> <li class="menu-separator"></li>
<img src="icon_close.webp"> <li class="menu-new-connection"
</span> i18n-content="NEW_CONNECTION"></li>
</div> <li class="menu-separator"></li>
<div class="window-controls-stub">&nbsp;</div> <li class="menu-help"
</span> i18n-content="HELP"></li>
</div> <li class="menu-feedback"
i18n-content="ACTIONBAR_FEEDBACK"></li>
</ul>
</span>
<span i18n-title="DISCONNECT_MYSELF_BUTTON"
class="window-control window-disconnect">
<img src="icon_disconnect.webp">
</span>
<span class="window-title">&nbsp;</span>
<span i18n-title="MINIMIZE_WINDOW"
class="window-control window-minimize">
<img src="icon_minimize.webp">
</span>
<span i18n-title="MAXIMIZE_WINDOW"
class="window-control window-maximize-restore">
<img src="icon_maximize_restore.webp">
</span>
<span i18n-title="CLOSE_WINDOW"
class="window-control window-close">
<img src="icon_close.webp">
</span>
</div>
<div class="window-controls-stub">&nbsp;</div>
</div> <!-- title-bar -->
...@@ -13,17 +13,19 @@ html.apps-v2 body:not(.fullscreen) { ...@@ -13,17 +13,19 @@ html.apps-v2 body:not(.fullscreen) {
border: 1px solid gray; /* This is the window border. */ border: 1px solid gray; /* This is the window border. */
} }
html.apps-v2 .title-bar { .title-bar {
border-bottom: 1px solid gray;
z-index: 100; z-index: 100;
width: 100%;
background-color: #c4c4c4;
} }
.window-title, .window-controls-and-title {
.window-controls-hover-target { display: flex;
height: 32px; }
.window-title {
line-height: 32px; line-height: 32px;
font-size: 14px; font-size: 14px;
background-color: #c4c4c4;
} }
.title-bar .window-title { .title-bar .window-title {
...@@ -31,29 +33,16 @@ html.apps-v2 .title-bar { ...@@ -31,29 +33,16 @@ html.apps-v2 .title-bar {
width: 100%; width: 100%;
display: inline-block; display: inline-block;
-webkit-app-region: drag; -webkit-app-region: drag;
} flex: 1;
.window-controls-hover-target {
-webkit-app-region: no-drag;
position: fixed;
top: 1px;
__MSG_@@bidi_end_edge__: 1px;
}
.window-controls-hover-target {
display: table;
}
.window-controls-hover-target > div:first-child {
display: table-row;
} }
.window-control { .window-control {
height: 32px;
width: 32px; width: 32px;
height: 32px;
padding-top: 9px;
padding-right: 1px;
text-align: center; text-align: center;
display: inline-block; display: inline-block;
border-__MSG_@@bidi_start_edge__: 1px solid rgba(0, 0, 0, 0.2);
} }
.window-control > span.menu-button-activator { .window-control > span.menu-button-activator {
...@@ -76,10 +65,9 @@ html.apps-v2 .title-bar { ...@@ -76,10 +65,9 @@ html.apps-v2 .title-bar {
.window-controls-stub { .window-controls-stub {
display: none; display: none;
-webkit-column-span: all; height: 8px;
line-height: 3px;
background: url("drag.webp"); background: url("drag.webp");
border-top: 1px solid rgba(0, 0, 0, 0.2); background-position: 2px 1px;
} }
#scroller { #scroller {
...@@ -90,30 +78,42 @@ html.apps-v2 .title-bar { ...@@ -90,30 +78,42 @@ html.apps-v2 .title-bar {
} }
html.apps-v2 #scroller { html.apps-v2 #scroller {
height: calc(100% - 32px); /** Allow space for the title-bar */ height: calc(100% - 32px); /* Allow space for the title-bar */
} }
/* Add an etched border to the window controls, title bar and stub */ /* Add an etched border to the window controls, title bar and stub */
.title-bar, .window-title,
.window-control, .window-control,
.window-controls-stub { .window-controls-stub {
position: relative; position: relative;
} }
.title-bar:after, .window-title::after,
.window-control:after, .window-control::after,
.window-controls-stub:after { .window-controls-stub::after {
content: ""; content: "";
width: 100%; width: 100%;
height: 100%; height: 100%;
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
border-left: 1px solid rgba(255, 255, 255, 0.2); border-right: 1px solid rgba(0, 0, 0, 0.2);
border-top: 1px solid rgba(255, 255, 255, 0.2); border-top: 1px solid rgba(255, 255, 255, 0.2);
border-bottom: 1px solid rgba(0, 0, 0, 0.3); /* darken bottom slightly */
border-left: 1px solid rgba(255, 255, 255, 0.2);
pointer-events: none; pointer-events: none;
box-sizing: border-box;
}
/* Remove dark borders for elements that are adjacent an existing border. */
.window-close::after {
border-right: none;
} }
.window-controls-stub::after {
border-bottom: none;
border-right: none;
}
/* The Disconnect and Options buttons are only displayed when connected. */ /* The Disconnect and Options buttons are only displayed when connected. */
body:not(.connected) .window-disconnect, body:not(.connected) .window-disconnect,
...@@ -127,7 +127,7 @@ body:not(.connected) .window-options { ...@@ -127,7 +127,7 @@ body:not(.connected) .window-options {
* - The scroll-bars are removed. * - The scroll-bars are removed.
* - The window controls have a border (so the left-border of the first button * - The window controls have a border (so the left-border of the first button
* is not needed). * is not needed).
* - The title-bar (and its bottom border) are not displayed. * - The window title is not displayed.
* - The stub is visible. * - The stub is visible.
* - The window controls gain transition effects for position and opacity and * - The window controls gain transition effects for position and opacity and
* auto-hide behind the top edge of the screen. * auto-hide behind the top edge of the screen.
...@@ -141,27 +141,28 @@ html.apps-v2 body.fullscreen #scroller { ...@@ -141,27 +141,28 @@ html.apps-v2 body.fullscreen #scroller {
overflow: hidden; overflow: hidden;
} }
body.fullscreen .window-controls-hover-target { body.fullscreen .title-bar {
border: 1px solid #a6a6a6; border: 1px solid #a6a6a6;
} }
body.fullscreen .window-control:first-child {
border-__MSG_@@bidi_start_edge__: none;
}
body.fullscreen .window-title { body.fullscreen .window-title {
display: none; display: none;
} }
body.fullscreen .title-bar { body.fullscreen .title-bar {
border-bottom: none; position: fixed;
width: initial; /* Override the 100% width when windowed. */
}
body.fullscreen .window-controls-and-title {
display: inline-flex;
} }
body.fullscreen .window-controls-stub { body.fullscreen .window-controls-stub {
display: table-cell; display: block;
} }
body.fullscreen .window-controls-hover-target { body.fullscreen .title-bar {
transition-property: opacity, box-shadow, top; transition-property: opacity, box-shadow, top;
transition-duration: 0.3s; transition-duration: 0.3s;
opacity: 0.7; opacity: 0.7;
...@@ -169,15 +170,15 @@ body.fullscreen .window-controls-hover-target { ...@@ -169,15 +170,15 @@ body.fullscreen .window-controls-hover-target {
__MSG_@@bidi_end_edge__: 8px; __MSG_@@bidi_end_edge__: 8px;
} }
body.fullscreen .window-controls-hover-target:hover, body.fullscreen .title-bar:hover,
body.fullscreen .window-controls-hover-target.menu-opened, body.fullscreen .title-bar.menu-opened,
body.fullscreen .window-controls-hover-target.opened, body.fullscreen .title-bar.opened,
body.fullscreen .window-controls-hover-target.preview { body.fullscreen .title-bar.preview {
top: -4px; top: -4px;
opacity: 1.0; opacity: 1.0;
box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.5); box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.5);
} }
.fullscreen .window-controls-hover-target.opened .window-controls-stub { .fullscreen .title-bar.opened .window-controls-stub {
background-color: #a6a6a6; background-color: #a6a6a6;
} }
...@@ -29,14 +29,6 @@ remoting.WindowFrame = function(titleBar) { ...@@ -29,14 +29,6 @@ remoting.WindowFrame = function(titleBar) {
*/ */
this.titleBar_ = titleBar; this.titleBar_ = titleBar;
/**
* @type {HTMLElement}
* @private
*/
this.hoverTarget_ = /** @type {HTMLElement} */
(titleBar.querySelector('.window-controls-hover-target'));
base.debug.assert(this.hoverTarget_ != null);
/** /**
* @type {remoting.OptionsMenu} * @type {remoting.OptionsMenu}
* @private * @private
...@@ -73,6 +65,14 @@ remoting.WindowFrame = function(titleBar) { ...@@ -73,6 +65,14 @@ remoting.WindowFrame = function(titleBar) {
this.onShowOptionsMenu_.bind(this), this.onShowOptionsMenu_.bind(this),
this.onHideOptionsMenu_.bind(this)); this.onHideOptionsMenu_.bind(this));
/**
* @type {HTMLElement}
* @private
*/
this.optionsMenuList_ = /** @type {HTMLElement} */
(optionsButton.querySelector('.window-options-menu'));
base.debug.assert(this.optionsMenu_ != null);
/** /**
* @type {Array.<{cls:string, fn: function()}>} * @type {Array.<{cls:string, fn: function()}>}
*/ */
...@@ -91,13 +91,13 @@ remoting.WindowFrame = function(titleBar) { ...@@ -91,13 +91,13 @@ remoting.WindowFrame = function(titleBar) {
} }
// Ensure that tool-tips are always correct. // Ensure that tool-tips are always correct.
this.updateMaximizeOrRestoreIconTitle_(); this.handleWindowStateChange_();
chrome.app.window.current().onMaximized.addListener( chrome.app.window.current().onMaximized.addListener(
this.updateMaximizeOrRestoreIconTitle_.bind(this)); this.handleWindowStateChange_.bind(this));
chrome.app.window.current().onRestored.addListener( chrome.app.window.current().onRestored.addListener(
this.updateMaximizeOrRestoreIconTitle_.bind(this)); this.handleWindowStateChange_.bind(this));
chrome.app.window.current().onFullscreened.addListener( chrome.app.window.current().onFullscreened.addListener(
this.updateMaximizeOrRestoreIconTitle_.bind(this)); this.handleWindowStateChange_.bind(this));
chrome.app.window.current().onFullscreened.addListener( chrome.app.window.current().onFullscreened.addListener(
this.showWindowControlsPreview_.bind(this)); this.showWindowControlsPreview_.bind(this));
}; };
...@@ -119,7 +119,7 @@ remoting.WindowFrame.prototype.setClientSession = function(clientSession) { ...@@ -119,7 +119,7 @@ remoting.WindowFrame.prototype.setClientSession = function(clientSession) {
windowTitle.innerText = windowTitle.innerText =
chrome.i18n.getMessage(/*i18n-content*/'PRODUCT_NAME'); chrome.i18n.getMessage(/*i18n-content*/'PRODUCT_NAME');
} }
this.updateMaximizeOrRestoreIconTitle_(); this.handleWindowStateChange_();
}; };
/** /**
...@@ -185,7 +185,7 @@ remoting.WindowFrame.prototype.minimizeWindow_ = function() { ...@@ -185,7 +185,7 @@ remoting.WindowFrame.prototype.minimizeWindow_ = function() {
* @private * @private
*/ */
remoting.WindowFrame.prototype.toggleWindowControls_ = function() { remoting.WindowFrame.prototype.toggleWindowControls_ = function() {
this.hoverTarget_.classList.toggle('opened'); this.titleBar_.classList.toggle('opened');
}; };
/** /**
...@@ -194,7 +194,8 @@ remoting.WindowFrame.prototype.toggleWindowControls_ = function() { ...@@ -194,7 +194,8 @@ remoting.WindowFrame.prototype.toggleWindowControls_ = function() {
* *
* @private * @private
*/ */
remoting.WindowFrame.prototype.updateMaximizeOrRestoreIconTitle_ = function() { remoting.WindowFrame.prototype.handleWindowStateChange_ = function() {
// Set the title for the maximize/restore/full-screen button
/** @type {string} */ /** @type {string} */
var tag = ''; var tag = '';
if (chrome.app.window.current().isFullscreen()) { if (chrome.app.window.current().isFullscreen()) {
...@@ -207,6 +208,14 @@ remoting.WindowFrame.prototype.updateMaximizeOrRestoreIconTitle_ = function() { ...@@ -207,6 +208,14 @@ remoting.WindowFrame.prototype.updateMaximizeOrRestoreIconTitle_ = function() {
tag = /*i18n-content*/'MAXIMIZE_WINDOW'; tag = /*i18n-content*/'MAXIMIZE_WINDOW';
} }
this.maximizeRestoreControl_.title = l10n.getTranslationOrError(tag); this.maximizeRestoreControl_.title = l10n.getTranslationOrError(tag);
// Ensure that the options menu aligns correctly for the side of the window
// it occupies.
if (chrome.app.window.current().isFullscreen()) {
this.optionsMenuList_.classList.add('right-align');
} else {
this.optionsMenuList_.classList.remove('right-align');
}
}; };
/** /**
...@@ -215,7 +224,7 @@ remoting.WindowFrame.prototype.updateMaximizeOrRestoreIconTitle_ = function() { ...@@ -215,7 +224,7 @@ remoting.WindowFrame.prototype.updateMaximizeOrRestoreIconTitle_ = function() {
*/ */
remoting.WindowFrame.prototype.onShowOptionsMenu_ = function() { remoting.WindowFrame.prototype.onShowOptionsMenu_ = function() {
this.optionsMenu_.onShow(); this.optionsMenu_.onShow();
this.hoverTarget_.classList.add('menu-opened'); this.titleBar_.classList.add('menu-opened');
}; };
/** /**
...@@ -223,7 +232,7 @@ remoting.WindowFrame.prototype.onShowOptionsMenu_ = function() { ...@@ -223,7 +232,7 @@ remoting.WindowFrame.prototype.onShowOptionsMenu_ = function() {
* @private * @private
*/ */
remoting.WindowFrame.prototype.onHideOptionsMenu_ = function() { remoting.WindowFrame.prototype.onHideOptionsMenu_ = function() {
this.hoverTarget_.classList.remove('menu-opened'); this.titleBar_.classList.remove('menu-opened');
}; };
/** /**
...@@ -235,7 +244,7 @@ remoting.WindowFrame.prototype.showWindowControlsPreview_ = function() { ...@@ -235,7 +244,7 @@ remoting.WindowFrame.prototype.showWindowControlsPreview_ = function() {
/** /**
* @type {HTMLElement} * @type {HTMLElement}
*/ */
var target = this.hoverTarget_; var target = this.titleBar_;
var kPreviewTimeoutMs = 3000; var kPreviewTimeoutMs = 3000;
var hidePreview = function() { var hidePreview = function() {
target.classList.remove('preview'); target.classList.remove('preview');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment