diff --git a/img/window-actions/linux/titlebutton-close-hover.png b/img/window-actions/linux/titlebutton-close-hover.png
new file mode 100755
index 00000000000..73405fc1881
Binary files /dev/null and b/img/window-actions/linux/titlebutton-close-hover.png differ
diff --git a/img/window-actions/linux/titlebutton-close.png b/img/window-actions/linux/titlebutton-close.png
new file mode 100755
index 00000000000..65a9a23c5f8
Binary files /dev/null and b/img/window-actions/linux/titlebutton-close.png differ
diff --git a/img/window-actions/linux/titlebutton-maximize-hover.png b/img/window-actions/linux/titlebutton-maximize-hover.png
new file mode 100755
index 00000000000..2de4e7446c8
Binary files /dev/null and b/img/window-actions/linux/titlebutton-maximize-hover.png differ
diff --git a/img/window-actions/linux/titlebutton-maximize.png b/img/window-actions/linux/titlebutton-maximize.png
new file mode 100755
index 00000000000..9fb27510706
Binary files /dev/null and b/img/window-actions/linux/titlebutton-maximize.png differ
diff --git a/img/window-actions/linux/titlebutton-minimize-hover.png b/img/window-actions/linux/titlebutton-minimize-hover.png
new file mode 100755
index 00000000000..017991834cb
Binary files /dev/null and b/img/window-actions/linux/titlebutton-minimize-hover.png differ
diff --git a/img/window-actions/linux/titlebutton-minimize.png b/img/window-actions/linux/titlebutton-minimize.png
new file mode 100755
index 00000000000..6ced316d820
Binary files /dev/null and b/img/window-actions/linux/titlebutton-minimize.png differ
diff --git a/img/window-actions/windows/10/close-btn-white.svg b/img/window-actions/windows/10/close-btn-white.svg
new file mode 100644
index 00000000000..72e603cbd55
--- /dev/null
+++ b/img/window-actions/windows/10/close-btn-white.svg
@@ -0,0 +1,63 @@
+
+
diff --git a/img/window-actions/windows/10/close-btn.svg b/img/window-actions/windows/10/close-btn.svg
new file mode 100644
index 00000000000..8dc9e16250f
--- /dev/null
+++ b/img/window-actions/windows/10/close-btn.svg
@@ -0,0 +1,62 @@
+
+
diff --git a/img/window-actions/windows/10/max-btn-fullscreen.svg b/img/window-actions/windows/10/max-btn-fullscreen.svg
new file mode 100644
index 00000000000..c534778f540
--- /dev/null
+++ b/img/window-actions/windows/10/max-btn-fullscreen.svg
@@ -0,0 +1,79 @@
+
+
diff --git a/img/window-actions/windows/10/max-btn.svg b/img/window-actions/windows/10/max-btn.svg
new file mode 100644
index 00000000000..c6beccbfddb
--- /dev/null
+++ b/img/window-actions/windows/10/max-btn.svg
@@ -0,0 +1,74 @@
+
+
diff --git a/img/window-actions/windows/10/min-btn.svg b/img/window-actions/windows/10/min-btn.svg
new file mode 100644
index 00000000000..22f67f36884
--- /dev/null
+++ b/img/window-actions/windows/10/min-btn.svg
@@ -0,0 +1,74 @@
+
+
diff --git a/js/components/main.js b/js/components/main.js
index e7a7b9d23d1..0930726664a 100644
--- a/js/components/main.js
+++ b/js/components/main.js
@@ -38,6 +38,7 @@ const ContextMenu = require('./contextMenu')
const PopupWindow = require('./popupWindow')
const NoScriptInfo = require('./noScriptInfo')
const LongPressButton = require('./longPressButton')
+const WindowActionBar = require('./windowActionBar')
// Constants
const config = require('../constants/config')
@@ -584,11 +585,7 @@ class Main extends ImmutableComponent {
if (!e.target.className.includes('navigatorWrapper')) {
return
}
- if (currentWindow.isMaximized()) {
- currentWindow.maximize()
- } else {
- currentWindow.unmaximize()
- }
+ return (!currentWindow.isMaximized()) ? currentWindow.maximize() : currentWindow.unmaximize()
}
onMouseDown (e) {
@@ -866,6 +863,7 @@ class Main extends ImmutableComponent {
braveShieldsDown: !braverySettings.shieldsUp
})}
onClick={this.onBraveMenu} />
+ {process.platform === 'darwin' ? null : }
diff --git a/js/components/windowActionBar.js b/js/components/windowActionBar.js
new file mode 100644
index 00000000000..3a763a06986
--- /dev/null
+++ b/js/components/windowActionBar.js
@@ -0,0 +1,71 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const os = require('os')
+const React = require('react')
+const ImmutableComponent = require('./immutableComponent')
+const currentWindow = require('../../app/renderer/currentWindow')
+
+class WindowActionBar extends ImmutableComponent {
+ constructor () {
+ super()
+ this.onDoubleClick = this.onDoubleClick.bind(this)
+ this.onMinimizeClick = this.onMinimizeClick.bind(this)
+ this.onMaximizeClick = this.onMaximizeClick.bind(this)
+ this.onCloseClick = this.onCloseClick.bind(this)
+ this.osClass = this.getPlatformCssClass()
+ }
+
+ get buttonClass () {
+ return (this.props.windowMaximized ? 'fullscreen' : '')
+ }
+
+ getPlatformCssClass () {
+ switch (os.platform()) {
+ case 'linux':
+ return 'linux'
+ case 'win32':
+ if (/10.0./.test(os.release())) {
+ return 'win-10'
+ } else if (/6.1./.test(os.release())) {
+ return 'win-7'
+ } else {
+ return 'win'
+ }
+ default:
+ return 'hidden'
+ }
+ }
+
+ onMinimizeClick (e) {
+ currentWindow.minimize()
+ }
+
+ onMaximizeClick (e) {
+ return (!currentWindow.isMaximized()) ? currentWindow.maximize() : currentWindow.unmaximize()
+ }
+
+ onCloseClick (e) {
+ currentWindow.close()
+ }
+
+ onDoubleClick (e) {
+ if (!e.target.className.includes('navigatorWrapper')) {
+ return
+ }
+ this.onMaximizeClick(e)
+ }
+
+ render () {
+ return
+ }
+}
+
+module.exports = WindowActionBar
diff --git a/js/stores/appStore.js b/js/stores/appStore.js
index f1ccd7f71d1..d121c33e665 100644
--- a/js/stores/appStore.js
+++ b/js/stores/appStore.js
@@ -134,7 +134,8 @@ const createWindow = (browserOpts, defaults, frameOpts, windowState) => {
titleBarStyle: 'hidden-inset',
autoHideMenuBar: autoHideMenuBarSetting,
title: appConfig.name,
- webPreferences: defaults.webPreferences
+ webPreferences: defaults.webPreferences,
+ frame: (process.platform === 'darwin')
}
if (process.platform === 'linux') {
diff --git a/less/navigationBar.less b/less/navigationBar.less
index 8f2a6f52949..0d0e36a4696 100644
--- a/less/navigationBar.less
+++ b/less/navigationBar.less
@@ -29,6 +29,137 @@
- (@navbarBraveButtonWidth + 2 * @navbarButtonSpacing);
}
+// Window Header
+.window-header {
+ -webkit-user-select: none;
+ -webkit-app-region: drag;
+ height: 18px;
+ padding: 3px 0;
+ margin: 0px;
+ display: flex;
+ line-height: 30px;
+
+ .hidden {
+ display: none;
+ }
+
+ .title-bar-btns {
+ -webkit-app-region: no-drag;
+ }
+
+ .win-7, .win-10 {
+ margin: -13px 3px 0 0;
+
+ button.win-action-btn {
+ outline: 0;
+ cursor: pointer;
+ width: 45px;
+ height: 23px;
+ color: #b1acac;
+ background-size: 12px 12px!important;
+ background-position: center!important;
+ border: 1px solid #e1e1e1;
+ display: inline-block;
+ padding: 12px;
+
+ &.fullscreen {
+ height:21px;
+ padding:6px;
+ }
+
+ &.close-btn {
+ background: url('../img/window-actions/windows/10/close-btn.svg') no-repeat;
+ &:hover {
+ background: url('../img/window-actions/windows/10/close-btn-white.svg') no-repeat;
+ background-color: #e5182c;
+ }
+ &:active {
+ background: url('../img/window-actions/windows/10/close-btn-white.svg') no-repeat;
+ background-color: #ef717c;
+ }
+ }
+
+ &.min-btn {
+ border-right: 0px;
+ border-bottom-left-radius: 5px;
+ background: url('../img/window-actions/windows/10/min-btn.svg') no-repeat;
+ &:hover {
+ background-color: #e5e5e5;
+ }
+ &:active {
+ background-color: #cacacb;
+ }
+ }
+
+ &.max-btn {
+ background: url('../img/window-actions/windows/10/max-btn.svg') no-repeat;
+ border-right: 0px;
+ &:hover {
+ background-color: #e5e5e5;
+ }
+ &:active {
+ background-color: #cacacb;
+ }
+ &.fullscreen {
+ background: url('../img/window-actions/windows/10/max-btn-fullscreen.svg') no-repeat;
+ &:hover {
+ background-color: #e5e5e5;
+ }
+ &:active {
+ background-color: #cacacb;
+ }
+ }
+ }
+ }
+
+ }
+
+ .linux {
+ button {
+ outline: 0;
+ cursor: pointer;
+ width: 14px;
+ height: 14px;
+ color: transparent;
+ background-color: transparent;
+ background-position: center;
+ background-repeat: no-repeat;
+ border-width: 0;
+ border-radius: 50%;
+ display: inline-block;
+ padding: 0px;
+ margin-right: 15px;
+ }
+
+ min-btn:backdrop, .max-btn:backdrop, .close-btn:backdrop {
+ opacity: 1;
+ }
+
+ .close-btn {
+ background: url('../img/window-actions/linux/titlebutton-close.png') 0 0 / contain no-repeat;
+ }
+
+ .min-btn {
+ background: url('../img/window-actions/linux/titlebutton-minimize.png') 0 0 / contain no-repeat;
+ }
+
+ .max-btn {
+ background: url('../img/window-actions/linux/titlebutton-maximize.png') 0 0 / contain no-repeat;
+ }
+
+ .close-btn:hover {
+ background: url('../img/window-actions/linux/titlebutton-close-hover.png') 0 0 / contain no-repeat;
+ }
+
+ .min-btn:hover {
+ background: url('../img/window-actions/linux/titlebutton-minimize-hover.png') 0 0 / contain no-repeat;
+ }
+
+ .max-btn:hover {
+ background: url('../img/window-actions/linux/titlebutton-maximize-hover.png') 0 0 / contain no-repeat;
+ }
+ }
+}
// Here I grouped the rules to keep the layout of the top bar consistent.
// The tricky part is to keep the title in `#navigator` centered when the
diff --git a/less/variables.less b/less/variables.less
index 0ae0af1591e..74d87376aa5 100644
--- a/less/variables.less
+++ b/less/variables.less
@@ -66,7 +66,7 @@
@bookmarksFileIconSize: 13px;
@bookmarksFolderIconSize: 15px;
-@navbarButtonSpacing: 4px;
+@navbarButtonSpacing: 14px;
@navbarButtonWidth: 35px;
@navbarBraveButtonWidth: 23px;
@navbarBraveButtonMarginLeft: 80px;
diff --git a/test/components/windowTest.js b/test/components/windowTest.js
index fb255f5fec2..596322e3355 100644
--- a/test/components/windowTest.js
+++ b/test/components/windowTest.js
@@ -1,7 +1,7 @@
/* global describe, it, before */
const Brave = require('../lib/brave')
-const {activeWebview} = require('../lib/selectors')
+const {activeWebview, minimizeButton, maximizeButton, closeButton} = require('../lib/selectors')
describe('application window', function () {
describe('application launch', function () {
@@ -146,6 +146,56 @@ describe('application window', function () {
})
})
+ if (process.platform !== 'darwin') {
+ describe('window top action buttons', function () {
+ Brave.beforeAll(this)
+
+ before(function * () {
+ yield this.app.client
+ .waitUntilWindowLoaded()
+ .waitForUrl(Brave.newTabUrl)
+ .windowByIndex(0)
+ .resizeWindow(600, 700)
+ .waitUntilWindowLoaded()
+ })
+
+ it('should be maximized when maximize button is clicked', function * () {
+ yield this.app.client
+ .click(maximizeButton)
+ .windowByIndex(0)
+ .getWindowWidth().should.eventually.be.getPrimaryDisplayWidth()
+ .getWindowHeight().should.eventually.be.getPrimaryDisplayHeight()
+ })
+
+ it('should be minimized when minimize button is clicked', function * () {
+ yield this.app.client
+ .click(minimizeButton)
+ .waitUntil(function () {
+ return this.windowByIndex(0).isWindowMinimized()
+ })
+ })
+
+ it('should close the new window when close button is clicked', function * () {
+ yield this.app.client
+ .windowByIndex(0)
+ .newWindowAction()
+ .waitUntil(function () {
+ return this.getWindowCount().then((count) => {
+ return count === 2
+ })
+ })
+ .windowByIndex(1)
+ .waitUntilWindowLoaded()
+ .click(closeButton)
+ .waitUntil(function () {
+ return this.getWindowCount().then((count) => {
+ return count === 1
+ })
+ })
+ })
+ })
+ }
+
describe('windw.open with click', function () {
describe('with features', function () {
Brave.beforeAll(this)
diff --git a/test/lib/selectors.js b/test/lib/selectors.js
index eb8c71de6eb..89a40088166 100644
--- a/test/lib/selectors.js
+++ b/test/lib/selectors.js
@@ -1,4 +1,7 @@
module.exports = {
+ minimizeButton: '.min-btn',
+ maximizeButton: '.max-btn',
+ closeButton: '.close-btn',
urlInput: '#urlInput',
activeWebview: '.frameWrapper.isActive webview',
activeTab: '.tab.active',