@theia/core 1.18.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/lib/browser/about-dialog.d.ts.map +1 -1
- package/lib/browser/about-dialog.js +1 -1
- package/lib/browser/about-dialog.js.map +1 -1
- package/lib/browser/authentication-service.d.ts.map +1 -1
- package/lib/browser/authentication-service.js +1 -1
- package/lib/browser/authentication-service.js.map +1 -1
- package/lib/browser/common-frontend-contribution.d.ts +6 -0
- package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/common-frontend-contribution.js +122 -118
- package/lib/browser/common-frontend-contribution.js.map +1 -1
- package/lib/browser/core-preferences.d.ts +1 -0
- package/lib/browser/core-preferences.d.ts.map +1 -1
- package/lib/browser/core-preferences.js +25 -18
- package/lib/browser/core-preferences.js.map +1 -1
- package/lib/browser/dialogs.d.ts +6 -0
- package/lib/browser/dialogs.d.ts.map +1 -1
- package/lib/browser/dialogs.js +10 -3
- package/lib/browser/dialogs.js.map +1 -1
- package/lib/browser/frontend-application-module.d.ts.map +1 -1
- package/lib/browser/frontend-application-module.js +3 -0
- package/lib/browser/frontend-application-module.js.map +1 -1
- package/lib/browser/frontend-application.d.ts +6 -0
- package/lib/browser/frontend-application.d.ts.map +1 -1
- package/lib/browser/frontend-application.js +13 -0
- package/lib/browser/frontend-application.js.map +1 -1
- package/lib/browser/index.d.ts +1 -0
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +1 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/keyboard/browser-keyboard-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/keyboard/browser-keyboard-frontend-contribution.js +16 -11
- package/lib/browser/keyboard/browser-keyboard-frontend-contribution.js.map +1 -1
- package/lib/browser/menu/browser-context-menu-renderer.d.ts +1 -1
- package/lib/browser/menu/browser-context-menu-renderer.d.ts.map +1 -1
- package/lib/browser/menu/browser-menu-plugin.d.ts +3 -0
- package/lib/browser/menu/browser-menu-plugin.d.ts.map +1 -1
- package/lib/browser/menu/browser-menu-plugin.js +24 -4
- package/lib/browser/menu/browser-menu-plugin.js.map +1 -1
- package/lib/browser/nls-loader.d.ts +17 -0
- package/lib/browser/nls-loader.d.ts.map +1 -0
- package/lib/browser/nls-loader.js +29 -0
- package/lib/browser/nls-loader.js.map +1 -0
- package/lib/browser/progress-status-bar-item.d.ts +1 -2
- package/lib/browser/progress-status-bar-item.d.ts.map +1 -1
- package/lib/browser/progress-status-bar-item.js.map +1 -1
- package/lib/browser/quick-input/quick-command-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/quick-input/quick-command-frontend-contribution.js +2 -1
- package/lib/browser/quick-input/quick-command-frontend-contribution.js.map +1 -1
- package/lib/browser/quick-input/quick-command-service.d.ts.map +1 -1
- package/lib/browser/quick-input/quick-command-service.js +2 -2
- package/lib/browser/quick-input/quick-command-service.js.map +1 -1
- package/lib/browser/quick-input/quick-view-service.d.ts +1 -2
- package/lib/browser/quick-input/quick-view-service.d.ts.map +1 -1
- package/lib/browser/quick-input/quick-view-service.js.map +1 -1
- package/lib/browser/shell/application-shell.d.ts +3 -1
- package/lib/browser/shell/application-shell.d.ts.map +1 -1
- package/lib/browser/shell/application-shell.js +1 -2
- package/lib/browser/shell/application-shell.js.map +1 -1
- package/lib/browser/shell/shell-layout-restorer.d.ts.map +1 -1
- package/lib/browser/shell/shell-layout-restorer.js +5 -3
- package/lib/browser/shell/shell-layout-restorer.js.map +1 -1
- package/lib/browser/shell/tab-bar-decorator.d.ts +1 -1
- package/lib/browser/shell/tab-bar-decorator.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-decorator.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar.js +2 -1
- package/lib/browser/shell/tab-bar-toolbar.js.map +1 -1
- package/lib/browser/shell/tab-bars.d.ts +14 -1
- package/lib/browser/shell/tab-bars.d.ts.map +1 -1
- package/lib/browser/shell/tab-bars.js +99 -7
- package/lib/browser/shell/tab-bars.js.map +1 -1
- package/lib/browser/tooltip-service.d.ts +52 -0
- package/lib/browser/tooltip-service.d.ts.map +1 -0
- package/lib/browser/tooltip-service.js +89 -0
- package/lib/browser/tooltip-service.js.map +1 -0
- package/lib/browser/tree/tree-model.d.ts.map +1 -1
- package/lib/browser/view-container.d.ts +55 -14
- package/lib/browser/view-container.d.ts.map +1 -1
- package/lib/browser/view-container.js +284 -66
- package/lib/browser/view-container.js.map +1 -1
- package/lib/browser/window/default-window-service.js +2 -2
- package/lib/browser/window/default-window-service.js.map +1 -1
- package/lib/browser/window/window-service.d.ts +1 -7
- package/lib/browser/window/window-service.d.ts.map +1 -1
- package/lib/browser/window/window-service.js +1 -5
- package/lib/browser/window/window-service.js.map +1 -1
- package/lib/browser/window-contribution.d.ts.map +1 -1
- package/lib/browser/window-contribution.js +2 -2
- package/lib/browser/window-contribution.js.map +1 -1
- package/lib/common/command.d.ts.map +1 -1
- package/lib/common/command.js +1 -2
- package/lib/common/command.js.map +1 -1
- package/lib/common/i18n/localization.d.ts +5 -0
- package/lib/common/i18n/localization.d.ts.map +1 -1
- package/lib/common/i18n/localization.js +43 -1
- package/lib/common/i18n/localization.js.map +1 -1
- package/lib/common/index.d.ts +1 -0
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +1 -0
- package/lib/common/index.js.map +1 -1
- package/lib/{browser → common}/nls.d.ts +3 -2
- package/lib/common/nls.d.ts.map +1 -0
- package/lib/common/nls.js +29 -0
- package/lib/common/nls.js.map +1 -0
- package/lib/common/window.d.ts +29 -0
- package/lib/common/window.d.ts.map +1 -0
- package/lib/common/window.js +23 -0
- package/lib/common/window.js.map +1 -0
- package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts +9 -5
- package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-context-menu-renderer.js +40 -15
- package/lib/electron-browser/menu/electron-context-menu-renderer.js.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts +5 -8
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.js +10 -17
- package/lib/electron-browser/menu/electron-main-menu-factory.js.map +1 -1
- package/lib/electron-browser/menu/electron-menu-contribution.d.ts +15 -7
- package/lib/electron-browser/menu/electron-menu-contribution.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-menu-contribution.js +112 -42
- package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
- package/lib/electron-browser/window/electron-window-preferences.d.ts +1 -0
- package/lib/electron-browser/window/electron-window-preferences.d.ts.map +1 -1
- package/lib/electron-browser/window/electron-window-preferences.js +12 -1
- package/lib/electron-browser/window/electron-window-preferences.js.map +1 -1
- package/lib/electron-browser/window/electron-window-service.d.ts +1 -1
- package/lib/electron-browser/window/electron-window-service.d.ts.map +1 -1
- package/lib/electron-common/electron-main-window-service.d.ts +1 -1
- package/lib/electron-common/electron-main-window-service.d.ts.map +1 -1
- package/lib/electron-common/electron-main-window-service.js.map +1 -1
- package/lib/electron-common/messaging/electron-messages.d.ts +20 -0
- package/lib/electron-common/messaging/electron-messages.d.ts.map +1 -0
- package/lib/electron-common/messaging/electron-messages.js +23 -0
- package/lib/electron-common/messaging/electron-messages.js.map +1 -0
- package/lib/electron-main/electron-main-application.d.ts +6 -0
- package/lib/electron-main/electron-main-application.d.ts.map +1 -1
- package/lib/electron-main/electron-main-application.js +80 -24
- package/lib/electron-main/electron-main-application.js.map +1 -1
- package/lib/electron-main/electron-main-window-service-impl.d.ts +1 -1
- package/lib/electron-main/electron-main-window-service-impl.d.ts.map +1 -1
- package/lib/electron-main/electron-main-window-service-impl.js.map +1 -1
- package/lib/electron-main/messaging/electron-messaging-contribution.d.ts +1 -1
- package/lib/electron-main/messaging/electron-messaging-contribution.d.ts.map +1 -1
- package/lib/electron-main/messaging/electron-messaging-contribution.js +1 -2
- package/lib/electron-main/messaging/electron-messaging-contribution.js.map +1 -1
- package/package.json +6 -4
- package/shared/@theia/application-package/lib/api.d.ts +1 -0
- package/shared/@theia/application-package/lib/api.js +1 -0
- package/src/browser/about-dialog.tsx +2 -2
- package/src/browser/authentication-service.ts +1 -2
- package/src/browser/common-frontend-contribution.ts +99 -95
- package/src/browser/core-preferences.ts +28 -18
- package/src/browser/dialogs.ts +10 -3
- package/src/browser/frontend-application-module.ts +4 -0
- package/src/browser/frontend-application.ts +13 -0
- package/src/browser/index.ts +1 -0
- package/src/browser/keyboard/browser-keyboard-frontend-contribution.ts +16 -11
- package/src/browser/menu/browser-context-menu-renderer.ts +1 -1
- package/src/browser/menu/browser-menu-plugin.ts +25 -5
- package/src/browser/nls-loader.ts +26 -0
- package/src/browser/progress-status-bar-item.ts +1 -2
- package/src/browser/quick-input/quick-command-frontend-contribution.ts +2 -2
- package/src/browser/quick-input/quick-command-service.ts +2 -2
- package/src/browser/quick-input/quick-view-service.ts +1 -2
- package/src/browser/shell/application-shell.ts +4 -3
- package/src/browser/shell/shell-layout-restorer.ts +4 -3
- package/src/browser/shell/tab-bar-decorator.ts +1 -1
- package/src/browser/shell/tab-bar-toolbar.tsx +3 -1
- package/src/browser/shell/tab-bars.ts +103 -8
- package/src/browser/style/index.css +5 -0
- package/src/browser/style/sidepanel.css +8 -2
- package/src/browser/style/tabs.css +30 -0
- package/src/browser/style/tooltip.css +28 -0
- package/src/browser/style/view-container.css +9 -9
- package/src/browser/tooltip-service.tsx +98 -0
- package/src/browser/tree/tree-model.ts +1 -1
- package/src/browser/view-container.ts +312 -80
- package/src/browser/window/default-window-service.ts +1 -1
- package/src/browser/window/window-service.ts +1 -9
- package/src/browser/window-contribution.ts +2 -2
- package/src/common/command.ts +1 -2
- package/src/common/i18n/localization.ts +44 -0
- package/src/common/index.ts +1 -0
- package/src/common/nls.ts +30 -0
- package/src/common/window.ts +30 -0
- package/src/electron-browser/menu/electron-context-menu-renderer.ts +38 -16
- package/src/electron-browser/menu/electron-main-menu-factory.ts +10 -15
- package/src/electron-browser/menu/electron-menu-contribution.ts +129 -39
- package/src/electron-browser/menu/electron-menu-style.css +84 -0
- package/src/electron-browser/window/electron-window-preferences.ts +13 -1
- package/src/electron-browser/window/electron-window-service.ts +1 -1
- package/src/electron-common/electron-main-window-service.ts +1 -2
- package/src/electron-common/messaging/electron-messages.ts +20 -0
- package/src/electron-main/electron-main-application.ts +85 -21
- package/src/electron-main/electron-main-window-service-impl.ts +1 -2
- package/src/electron-main/messaging/electron-messaging-contribution.ts +1 -2
- package/lib/browser/nls.d.ts.map +0 -1
- package/lib/browser/nls.js +0 -64
- package/lib/browser/nls.js.map +0 -1
- package/src/browser/nls.ts +0 -65
|
@@ -23,10 +23,10 @@ import { CommonMenus } from '../browser/common-frontend-contribution';
|
|
|
23
23
|
|
|
24
24
|
export namespace WindowCommands {
|
|
25
25
|
|
|
26
|
-
export const NEW_WINDOW
|
|
26
|
+
export const NEW_WINDOW = Command.toLocalizedCommand({
|
|
27
27
|
id: 'workbench.action.newWindow',
|
|
28
28
|
label: 'New Window'
|
|
29
|
-
};
|
|
29
|
+
}, 'vscode/windowActions/newWindow');
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
@injectable()
|
package/src/common/command.ts
CHANGED
|
@@ -18,8 +18,7 @@ import { injectable, inject, named } from 'inversify';
|
|
|
18
18
|
import { Event, Emitter, WaitUntilEvent } from './event';
|
|
19
19
|
import { Disposable, DisposableCollection } from './disposable';
|
|
20
20
|
import { ContributionProvider } from './contribution-provider';
|
|
21
|
-
|
|
22
|
-
import { nls } from '../browser/nls';
|
|
21
|
+
import { nls } from './nls';
|
|
23
22
|
|
|
24
23
|
/**
|
|
25
24
|
* A command is a unique identifier of a function
|
|
@@ -31,3 +31,47 @@ export interface Localization {
|
|
|
31
31
|
localizedLanguageName?: string;
|
|
32
32
|
translations: { [key: string]: string };
|
|
33
33
|
}
|
|
34
|
+
|
|
35
|
+
export type FormatType = string | number | boolean | undefined;
|
|
36
|
+
|
|
37
|
+
export namespace Localization {
|
|
38
|
+
|
|
39
|
+
function format(message: string, args: FormatType[]): string {
|
|
40
|
+
let result = message;
|
|
41
|
+
if (args.length > 0) {
|
|
42
|
+
result = message.replace(/\{(\d+)\}/g, (match, rest) => {
|
|
43
|
+
const index = rest[0];
|
|
44
|
+
const arg = args[index];
|
|
45
|
+
let replacement = match;
|
|
46
|
+
if (typeof arg === 'string') {
|
|
47
|
+
replacement = arg;
|
|
48
|
+
} else if (typeof arg === 'number' || typeof arg === 'boolean' || !arg) {
|
|
49
|
+
replacement = String(arg);
|
|
50
|
+
}
|
|
51
|
+
return replacement;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function localize(localization: Localization | undefined, key: string, defaultValue: string, ...args: FormatType[]): string {
|
|
58
|
+
let value = defaultValue;
|
|
59
|
+
if (localization) {
|
|
60
|
+
const translation = localization.translations[key];
|
|
61
|
+
if (translation) {
|
|
62
|
+
// vscode's localizations often contain additional '&&' symbols, which we simply ignore
|
|
63
|
+
value = translation.replace(/&&/g, '');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return format(value, args);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function transformKey(key: string): string {
|
|
70
|
+
let nlsKey = key;
|
|
71
|
+
const keySlashIndex = key.lastIndexOf('/');
|
|
72
|
+
if (keySlashIndex >= 0) {
|
|
73
|
+
nlsKey = key.substring(keySlashIndex + 1);
|
|
74
|
+
}
|
|
75
|
+
return nlsKey;
|
|
76
|
+
}
|
|
77
|
+
}
|
package/src/common/index.ts
CHANGED
|
@@ -38,6 +38,7 @@ export * from './strings';
|
|
|
38
38
|
export * from './application-error';
|
|
39
39
|
export * from './lsp-types';
|
|
40
40
|
export * from './contribution-filter';
|
|
41
|
+
export * from './nls';
|
|
41
42
|
|
|
42
43
|
import { environment } from '@theia/application-package/lib/environment';
|
|
43
44
|
export { environment };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (C) 2021 TypeFox and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
* http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
*
|
|
8
|
+
* This Source Code may also be made available under the following Secondary
|
|
9
|
+
* Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
* with the GNU Classpath Exception which is available at
|
|
12
|
+
* https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
*
|
|
14
|
+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
+
********************************************************************************/
|
|
16
|
+
|
|
17
|
+
import { FormatType, Localization } from './i18n/localization';
|
|
18
|
+
|
|
19
|
+
export namespace nls {
|
|
20
|
+
|
|
21
|
+
export let localization: Localization | undefined;
|
|
22
|
+
|
|
23
|
+
export const localeId = 'localeId';
|
|
24
|
+
|
|
25
|
+
export const locale = typeof window === 'object' && window && window.localStorage.getItem(localeId) || undefined;
|
|
26
|
+
|
|
27
|
+
export function localize(key: string, defaultValue: string, ...args: FormatType[]): string {
|
|
28
|
+
return Localization.localize(localization, key, defaultValue, ...args);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (C) 2021 Ericsson and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
* http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
*
|
|
8
|
+
* This Source Code may also be made available under the following Secondary
|
|
9
|
+
* Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
* with the GNU Classpath Exception which is available at
|
|
12
|
+
* https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
*
|
|
14
|
+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
+
********************************************************************************/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The window hash value that is used to spawn a new default window.
|
|
19
|
+
*/
|
|
20
|
+
export const DEFAULT_WINDOW_HASH: string = '!empty';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The options for opening new windows.
|
|
24
|
+
*/
|
|
25
|
+
export interface NewWindowOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Controls whether the window should be opened externally.
|
|
28
|
+
*/
|
|
29
|
+
readonly external?: boolean;
|
|
30
|
+
}
|
|
@@ -17,11 +17,15 @@
|
|
|
17
17
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
18
18
|
|
|
19
19
|
import * as electron from '../../../shared/electron';
|
|
20
|
-
import { inject, injectable } from 'inversify';
|
|
21
|
-
import {
|
|
20
|
+
import { inject, injectable, postConstruct } from 'inversify';
|
|
21
|
+
import {
|
|
22
|
+
ContextMenuRenderer, RenderContextMenuOptions, ContextMenuAccess, FrontendApplicationContribution, CommonCommands, coordinateFromAnchor, PreferenceService
|
|
23
|
+
} from '../../browser';
|
|
22
24
|
import { ElectronMainMenuFactory } from './electron-main-menu-factory';
|
|
23
25
|
import { ContextMenuContext } from '../../browser/menu/context-menu-context';
|
|
24
26
|
import { MenuPath, MenuContribution, MenuModelRegistry } from '../../common';
|
|
27
|
+
import { BrowserContextMenuRenderer } from '../../browser/menu/browser-context-menu-renderer';
|
|
28
|
+
import { RequestTitleBarStyle, TitleBarStyleAtStartup } from '../../electron-common/messaging/electron-messages';
|
|
25
29
|
|
|
26
30
|
export class ElectronContextMenuAccess extends ContextMenuAccess {
|
|
27
31
|
constructor(readonly menu: electron.Menu) {
|
|
@@ -73,27 +77,45 @@ export class ElectronTextInputContextMenuContribution implements FrontendApplica
|
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
@injectable()
|
|
76
|
-
export class ElectronContextMenuRenderer extends
|
|
80
|
+
export class ElectronContextMenuRenderer extends BrowserContextMenuRenderer {
|
|
77
81
|
|
|
78
82
|
@inject(ContextMenuContext)
|
|
79
83
|
protected readonly context: ContextMenuContext;
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
@inject(PreferenceService)
|
|
86
|
+
protected readonly preferenceService: PreferenceService;
|
|
87
|
+
|
|
88
|
+
protected useNativeStyle: boolean = true;
|
|
89
|
+
|
|
90
|
+
constructor(@inject(ElectronMainMenuFactory) private electronMenuFactory: ElectronMainMenuFactory) {
|
|
91
|
+
super(electronMenuFactory);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@postConstruct()
|
|
95
|
+
protected async init(): Promise<void> {
|
|
96
|
+
electron.ipcRenderer.on(TitleBarStyleAtStartup, (_event, style: string) => {
|
|
97
|
+
this.useNativeStyle = style === 'native';
|
|
98
|
+
});
|
|
99
|
+
electron.ipcRenderer.send(RequestTitleBarStyle);
|
|
83
100
|
}
|
|
84
101
|
|
|
85
|
-
protected doRender(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
102
|
+
protected doRender(options: RenderContextMenuOptions): ContextMenuAccess {
|
|
103
|
+
if (this.useNativeStyle) {
|
|
104
|
+
const { menuPath, anchor, args, onHide } = options;
|
|
105
|
+
const menu = this.electronMenuFactory.createElectronContextMenu(menuPath, args);
|
|
106
|
+
const { x, y } = coordinateFromAnchor(anchor);
|
|
107
|
+
const zoom = electron.webFrame.getZoomFactor();
|
|
108
|
+
// x and y values must be Ints or else there is a conversion error
|
|
109
|
+
menu.popup({ x: Math.round(x * zoom), y: Math.round(y * zoom) });
|
|
110
|
+
// native context menu stops the event loop, so there is no keyboard events
|
|
111
|
+
this.context.resetAltPressed();
|
|
112
|
+
if (onHide) {
|
|
113
|
+
menu.once('menu-will-close', () => onHide());
|
|
114
|
+
}
|
|
115
|
+
return new ElectronContextMenuAccess(menu);
|
|
116
|
+
} else {
|
|
117
|
+
return super.doRender(options);
|
|
95
118
|
}
|
|
96
|
-
return new ElectronContextMenuAccess(menu);
|
|
97
119
|
}
|
|
98
120
|
|
|
99
121
|
}
|
|
@@ -24,10 +24,9 @@ import {
|
|
|
24
24
|
} from '../../common';
|
|
25
25
|
import { Keybinding } from '../../common/keybinding';
|
|
26
26
|
import { PreferenceService, KeybindingRegistry, CommonCommands } from '../../browser';
|
|
27
|
-
import { ContextKeyService } from '../../browser/context-key-service';
|
|
28
27
|
import debounce = require('lodash.debounce');
|
|
29
|
-
import { ContextMenuContext } from '../../browser/menu/context-menu-context';
|
|
30
28
|
import { MAXIMIZED_CLASS } from '../../browser/shell/theia-dock-panel';
|
|
29
|
+
import { BrowserMainMenuFactory } from '../../browser/menu/browser-menu-plugin';
|
|
31
30
|
|
|
32
31
|
/**
|
|
33
32
|
* Representation of possible electron menu options.
|
|
@@ -55,23 +54,18 @@ export type ElectronMenuItemRole = ('undo' | 'redo' | 'cut' | 'copy' | 'paste' |
|
|
|
55
54
|
'moveTabToNewWindow' | 'windowMenu');
|
|
56
55
|
|
|
57
56
|
@injectable()
|
|
58
|
-
export class ElectronMainMenuFactory {
|
|
57
|
+
export class ElectronMainMenuFactory extends BrowserMainMenuFactory {
|
|
59
58
|
|
|
60
59
|
protected _menu: Electron.Menu | undefined;
|
|
61
60
|
protected _toggledCommands: Set<string> = new Set();
|
|
62
61
|
|
|
63
|
-
@inject(ContextKeyService)
|
|
64
|
-
protected readonly contextKeyService: ContextKeyService;
|
|
65
|
-
|
|
66
|
-
@inject(ContextMenuContext)
|
|
67
|
-
protected readonly context: ContextMenuContext;
|
|
68
|
-
|
|
69
62
|
constructor(
|
|
70
63
|
@inject(CommandRegistry) protected readonly commandRegistry: CommandRegistry,
|
|
71
64
|
@inject(PreferenceService) protected readonly preferencesService: PreferenceService,
|
|
72
65
|
@inject(MenuModelRegistry) protected readonly menuProvider: MenuModelRegistry,
|
|
73
66
|
@inject(KeybindingRegistry) protected readonly keybindingRegistry: KeybindingRegistry
|
|
74
67
|
) {
|
|
68
|
+
super();
|
|
75
69
|
preferencesService.onPreferenceChanged(
|
|
76
70
|
debounce(e => {
|
|
77
71
|
if (e.preferenceName === 'window.menuBarVisibility') {
|
|
@@ -92,15 +86,16 @@ export class ElectronMainMenuFactory {
|
|
|
92
86
|
|
|
93
87
|
async setMenuBar(): Promise<void> {
|
|
94
88
|
await this.preferencesService.ready;
|
|
95
|
-
const createdMenuBar = this.createMenuBar();
|
|
96
89
|
if (isOSX) {
|
|
90
|
+
const createdMenuBar = this.createElectronMenuBar();
|
|
97
91
|
electron.remote.Menu.setApplicationMenu(createdMenuBar);
|
|
98
|
-
} else {
|
|
92
|
+
} else if (this.preferencesService.get('window.titleBarStyle') === 'native') {
|
|
93
|
+
const createdMenuBar = this.createElectronMenuBar();
|
|
99
94
|
electron.remote.getCurrentWindow().setMenu(createdMenuBar);
|
|
100
95
|
}
|
|
101
96
|
}
|
|
102
97
|
|
|
103
|
-
|
|
98
|
+
createElectronMenuBar(): Electron.Menu | null {
|
|
104
99
|
const preference = this.preferencesService.get<string>('window.menuBarVisibility') || 'classic';
|
|
105
100
|
const maxWidget = document.getElementsByClassName(MAXIMIZED_CLASS);
|
|
106
101
|
if (preference === 'visible' || (preference === 'classic' && maxWidget.length === 0)) {
|
|
@@ -118,7 +113,7 @@ export class ElectronMainMenuFactory {
|
|
|
118
113
|
return null;
|
|
119
114
|
}
|
|
120
115
|
|
|
121
|
-
|
|
116
|
+
createElectronContextMenu(menuPath: MenuPath, args?: any[]): Electron.Menu {
|
|
122
117
|
const menuModel = this.menuProvider.getMenu(menuPath);
|
|
123
118
|
const template = this.fillMenuTemplate([], menuModel, args, { showDisabled: false });
|
|
124
119
|
return electron.remote.Menu.buildFromTemplate(template);
|
|
@@ -221,13 +216,13 @@ export class ElectronMainMenuFactory {
|
|
|
221
216
|
this._toggledCommands.add(commandId);
|
|
222
217
|
}
|
|
223
218
|
} else {
|
|
224
|
-
items.push(...this.
|
|
219
|
+
items.push(...this.handleElectronDefault(menu, args, options));
|
|
225
220
|
}
|
|
226
221
|
}
|
|
227
222
|
return items;
|
|
228
223
|
}
|
|
229
224
|
|
|
230
|
-
protected
|
|
225
|
+
protected handleElectronDefault(menuNode: MenuNode, args: any[] = [], options?: ElectronMenuOptions): Electron.MenuItemConstructorOptions[] {
|
|
231
226
|
return [];
|
|
232
227
|
}
|
|
233
228
|
|
|
@@ -18,44 +18,51 @@ import * as electron from '../../../shared/electron';
|
|
|
18
18
|
import { inject, injectable } from 'inversify';
|
|
19
19
|
import {
|
|
20
20
|
Command, CommandContribution, CommandRegistry,
|
|
21
|
-
isOSX, isWindows, MenuModelRegistry, MenuContribution, Disposable
|
|
21
|
+
isOSX, isWindows, MenuModelRegistry, MenuContribution, Disposable, nls
|
|
22
22
|
} from '../../common';
|
|
23
|
-
import {
|
|
24
|
-
|
|
23
|
+
import {
|
|
24
|
+
ApplicationShell, codicon, ConfirmDialog, KeybindingContribution, KeybindingRegistry,
|
|
25
|
+
PreferenceScope, Widget, FrontendApplication, FrontendApplicationContribution, CommonMenus, CommonCommands, Dialog
|
|
26
|
+
} from '../../browser';
|
|
25
27
|
import { ElectronMainMenuFactory } from './electron-main-menu-factory';
|
|
26
28
|
import { FrontendApplicationStateService, FrontendApplicationState } from '../../browser/frontend-application-state';
|
|
29
|
+
import { FrontendApplicationConfigProvider } from '../../browser/frontend-application-config-provider';
|
|
30
|
+
import { RequestTitleBarStyle, Restart, TitleBarStyleAtStartup, TitleBarStyleChanged } from '../../electron-common/messaging/electron-messages';
|
|
27
31
|
import { ZoomLevel } from '../window/electron-window-preferences';
|
|
32
|
+
import { BrowserMenuBarContribution } from '../../browser/menu/browser-menu-plugin';
|
|
33
|
+
|
|
34
|
+
import '../../../src/electron-browser/menu/electron-menu-style.css';
|
|
28
35
|
|
|
29
36
|
export namespace ElectronCommands {
|
|
30
|
-
export const TOGGLE_DEVELOPER_TOOLS
|
|
37
|
+
export const TOGGLE_DEVELOPER_TOOLS = Command.toLocalizedCommand({
|
|
31
38
|
id: 'theia.toggleDevTools',
|
|
32
39
|
label: 'Toggle Developer Tools'
|
|
33
|
-
};
|
|
34
|
-
export const RELOAD
|
|
40
|
+
}, 'vscode/developerActions/toggleDevTools');
|
|
41
|
+
export const RELOAD = Command.toLocalizedCommand({
|
|
35
42
|
id: 'view.reload',
|
|
36
43
|
label: 'Reload Window'
|
|
37
|
-
};
|
|
38
|
-
export const ZOOM_IN
|
|
44
|
+
}, 'vscode/windowActions/reloadWindow');
|
|
45
|
+
export const ZOOM_IN = Command.toLocalizedCommand({
|
|
39
46
|
id: 'view.zoomIn',
|
|
40
47
|
label: 'Zoom In'
|
|
41
|
-
};
|
|
42
|
-
export const ZOOM_OUT
|
|
48
|
+
}, 'vscode/windowActions/zoomIn');
|
|
49
|
+
export const ZOOM_OUT = Command.toLocalizedCommand({
|
|
43
50
|
id: 'view.zoomOut',
|
|
44
51
|
label: 'Zoom Out'
|
|
45
|
-
};
|
|
46
|
-
export const RESET_ZOOM
|
|
52
|
+
}, 'vscode/windowActions/zoomOut');
|
|
53
|
+
export const RESET_ZOOM = Command.toLocalizedCommand({
|
|
47
54
|
id: 'view.resetZoom',
|
|
48
55
|
label: 'Reset Zoom'
|
|
49
|
-
};
|
|
50
|
-
export const CLOSE_WINDOW
|
|
56
|
+
}, 'vscode/windowActions/zoomReset');
|
|
57
|
+
export const CLOSE_WINDOW = Command.toLocalizedCommand({
|
|
51
58
|
id: 'close.window',
|
|
52
59
|
label: 'Close Window'
|
|
53
|
-
};
|
|
54
|
-
export const TOGGLE_FULL_SCREEN
|
|
60
|
+
}, 'vscode/windowActions/close');
|
|
61
|
+
export const TOGGLE_FULL_SCREEN = Command.toLocalizedCommand({
|
|
55
62
|
id: 'workbench.action.toggleFullScreen',
|
|
56
|
-
category:
|
|
63
|
+
category: CommonCommands.VIEW_CATEGORY,
|
|
57
64
|
label: 'Toggle Full Screen'
|
|
58
|
-
};
|
|
65
|
+
}, 'vscode/windowActions/toggleFullScreen', CommonCommands.VIEW_CATEGORY_KEY);
|
|
59
66
|
}
|
|
60
67
|
|
|
61
68
|
export namespace ElectronMenus {
|
|
@@ -72,38 +79,33 @@ export namespace ElectronMenus {
|
|
|
72
79
|
}
|
|
73
80
|
|
|
74
81
|
@injectable()
|
|
75
|
-
export class ElectronMenuContribution implements FrontendApplicationContribution, CommandContribution, MenuContribution, KeybindingContribution {
|
|
82
|
+
export class ElectronMenuContribution extends BrowserMenuBarContribution implements FrontendApplicationContribution, CommandContribution, MenuContribution, KeybindingContribution {
|
|
76
83
|
|
|
77
84
|
@inject(FrontendApplicationStateService)
|
|
78
85
|
protected readonly stateService: FrontendApplicationStateService;
|
|
79
86
|
|
|
80
|
-
|
|
81
|
-
protected
|
|
87
|
+
protected titleBarStyleChangeFlag = false;
|
|
88
|
+
protected titleBarStyle?: string;
|
|
82
89
|
|
|
83
90
|
constructor(
|
|
84
91
|
@inject(ElectronMainMenuFactory) protected readonly factory: ElectronMainMenuFactory,
|
|
85
92
|
@inject(ApplicationShell) protected shell: ApplicationShell
|
|
86
|
-
) {
|
|
93
|
+
) {
|
|
94
|
+
super(factory);
|
|
95
|
+
}
|
|
87
96
|
|
|
88
97
|
onStart(app: FrontendApplication): void {
|
|
89
|
-
this.
|
|
90
|
-
this.preferenceService.ready.then(() => {
|
|
91
|
-
this.setMenu();
|
|
92
|
-
electron.remote.getCurrentWindow().setMenuBarVisibility(true);
|
|
93
|
-
});
|
|
98
|
+
this.handleTitleBarStyling(app);
|
|
94
99
|
if (isOSX) {
|
|
95
100
|
// OSX: Recreate the menus when changing windows.
|
|
96
101
|
// OSX only has one menu bar for all windows, so we need to swap
|
|
97
102
|
// between them as the user switches windows.
|
|
98
|
-
electron.remote.getCurrentWindow().on('focus', () => this.setMenu());
|
|
103
|
+
electron.remote.getCurrentWindow().on('focus', () => this.setMenu(app));
|
|
99
104
|
}
|
|
100
105
|
// Make sure the application menu is complete, once the frontend application is ready.
|
|
101
106
|
// https://github.com/theia-ide/theia/issues/5100
|
|
102
107
|
let onStateChange: Disposable | undefined = undefined;
|
|
103
108
|
const stateServiceListener = (state: FrontendApplicationState) => {
|
|
104
|
-
if (state === 'ready') {
|
|
105
|
-
this.setMenu();
|
|
106
|
-
}
|
|
107
109
|
if (state === 'closing_window') {
|
|
108
110
|
if (!!onStateChange) {
|
|
109
111
|
onStateChange.dispose();
|
|
@@ -119,6 +121,30 @@ export class ElectronMenuContribution implements FrontendApplicationContribution
|
|
|
119
121
|
});
|
|
120
122
|
}
|
|
121
123
|
|
|
124
|
+
handleTitleBarStyling(app: FrontendApplication): void {
|
|
125
|
+
this.hideTopPanel(app);
|
|
126
|
+
electron.ipcRenderer.on(TitleBarStyleAtStartup, (_event, style: string) => {
|
|
127
|
+
this.titleBarStyle = style;
|
|
128
|
+
this.preferenceService.ready.then(() => {
|
|
129
|
+
this.preferenceService.set('window.titleBarStyle', this.titleBarStyle, PreferenceScope.User);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
electron.ipcRenderer.send(RequestTitleBarStyle);
|
|
133
|
+
this.preferenceService.ready.then(() => {
|
|
134
|
+
this.setMenu(app);
|
|
135
|
+
electron.remote.getCurrentWindow().setMenuBarVisibility(['classic', 'visible'].includes(this.preferenceService.get('window.menuBarVisibility', 'classic')));
|
|
136
|
+
});
|
|
137
|
+
this.preferenceService.onPreferenceChanged(change => {
|
|
138
|
+
if (change.preferenceName === 'window.titleBarStyle') {
|
|
139
|
+
if (this.titleBarStyleChangeFlag && this.titleBarStyle !== change.newValue && electron.remote.getCurrentWindow().isFocused()) {
|
|
140
|
+
electron.ipcRenderer.send(TitleBarStyleChanged, change.newValue);
|
|
141
|
+
this.handleRequiredRestart();
|
|
142
|
+
}
|
|
143
|
+
this.titleBarStyleChangeFlag = true;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
122
148
|
handleToggleMaximized(): void {
|
|
123
149
|
const preference = this.preferenceService.get('window.menuBarVisibility');
|
|
124
150
|
if (preference === 'classic') {
|
|
@@ -127,31 +153,95 @@ export class ElectronMenuContribution implements FrontendApplicationContribution
|
|
|
127
153
|
}
|
|
128
154
|
|
|
129
155
|
/**
|
|
130
|
-
*
|
|
156
|
+
* Hides the `theia-top-panel` depending on the selected `titleBarStyle`.
|
|
131
157
|
* The `theia-top-panel` is used as the container of the main, application menu-bar for the
|
|
132
|
-
* browser. Electron has it's own.
|
|
158
|
+
* browser. Native Electron has it's own.
|
|
133
159
|
* By default, this method is called on application `onStart`.
|
|
134
160
|
*/
|
|
135
161
|
protected hideTopPanel(app: FrontendApplication): void {
|
|
136
162
|
const itr = app.shell.children();
|
|
137
163
|
let child = itr.next();
|
|
138
164
|
while (child) {
|
|
139
|
-
// Top panel for the menu contribution is not required for Electron.
|
|
165
|
+
// Top panel for the menu contribution is not required for native Electron title bar.
|
|
140
166
|
if (child.id === 'theia-top-panel') {
|
|
141
|
-
child.setHidden(
|
|
142
|
-
|
|
167
|
+
child.setHidden(this.titleBarStyle !== 'custom');
|
|
168
|
+
break;
|
|
143
169
|
} else {
|
|
144
170
|
child = itr.next();
|
|
145
171
|
}
|
|
146
172
|
}
|
|
147
173
|
}
|
|
148
174
|
|
|
149
|
-
|
|
175
|
+
protected setMenu(app: FrontendApplication, electronMenu: electron.Menu | null = this.factory.createElectronMenuBar(),
|
|
176
|
+
electronWindow: electron.BrowserWindow = electron.remote.getCurrentWindow()): void {
|
|
150
177
|
if (isOSX) {
|
|
151
|
-
electron.remote.Menu.setApplicationMenu(
|
|
178
|
+
electron.remote.Menu.setApplicationMenu(electronMenu);
|
|
152
179
|
} else {
|
|
180
|
+
this.hideTopPanel(app);
|
|
181
|
+
if (this.titleBarStyle === 'custom' && !this.menuBar) {
|
|
182
|
+
this.createCustomTitleBar(app, electronWindow);
|
|
183
|
+
}
|
|
153
184
|
// Unix/Windows: Set the per-window menus
|
|
154
|
-
electronWindow.setMenu(
|
|
185
|
+
electronWindow.setMenu(electronMenu);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
protected createCustomTitleBar(app: FrontendApplication, electronWindow: electron.BrowserWindow): void {
|
|
190
|
+
const dragPanel = new Widget();
|
|
191
|
+
dragPanel.id = 'theia-drag-panel';
|
|
192
|
+
app.shell.addWidget(dragPanel, { area: 'top' });
|
|
193
|
+
this.appendMenu(app.shell);
|
|
194
|
+
const controls = document.createElement('div');
|
|
195
|
+
controls.id = 'window-controls';
|
|
196
|
+
controls.append(
|
|
197
|
+
this.createControlButton('minimize', () => electronWindow.minimize()),
|
|
198
|
+
this.createControlButton('maximize', () => electronWindow.maximize()),
|
|
199
|
+
this.createControlButton('restore', () => electronWindow.unmaximize()),
|
|
200
|
+
this.createControlButton('close', () => electronWindow.close())
|
|
201
|
+
);
|
|
202
|
+
app.shell.topPanel.node.append(controls);
|
|
203
|
+
this.handleWindowControls(electronWindow);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
protected handleWindowControls(electronWindow: electron.BrowserWindow): void {
|
|
207
|
+
toggleControlButtons();
|
|
208
|
+
electronWindow.on('maximize', toggleControlButtons);
|
|
209
|
+
electronWindow.on('unmaximize', toggleControlButtons);
|
|
210
|
+
|
|
211
|
+
function toggleControlButtons(): void {
|
|
212
|
+
if (electronWindow.isMaximized()) {
|
|
213
|
+
document.body.classList.add('maximized');
|
|
214
|
+
} else {
|
|
215
|
+
document.body.classList.remove('maximized');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
protected createControlButton(id: string, handler: () => void): HTMLElement {
|
|
221
|
+
const button = document.createElement('div');
|
|
222
|
+
button.id = `${id}-button`;
|
|
223
|
+
button.className = `control-button ${codicon(`chrome-${id}`)}`;
|
|
224
|
+
button.addEventListener('click', handler);
|
|
225
|
+
return button;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
protected async handleRequiredRestart(): Promise<void> {
|
|
229
|
+
const msgNode = document.createElement('div');
|
|
230
|
+
const message = document.createElement('p');
|
|
231
|
+
message.textContent = nls.localize('vscode/relauncher.contribution/relaunchSettingMessage', 'A setting has changed that requires a restart to take effect');
|
|
232
|
+
const detail = document.createElement('p');
|
|
233
|
+
detail.textContent = nls.localize('vscode/relauncher.contribution/relaunchSettingDetail',
|
|
234
|
+
'Press the restart button to restart {0} and enable the setting.', FrontendApplicationConfigProvider.get().applicationName);
|
|
235
|
+
msgNode.append(message, detail);
|
|
236
|
+
const restart = nls.localize('vscode/relauncher.contribution/restart', 'Restart');
|
|
237
|
+
const dialog = new ConfirmDialog({
|
|
238
|
+
title: restart,
|
|
239
|
+
msg: msgNode,
|
|
240
|
+
ok: restart,
|
|
241
|
+
cancel: Dialog.CANCEL
|
|
242
|
+
});
|
|
243
|
+
if (await dialog.open()) {
|
|
244
|
+
electron.ipcRenderer.send(Restart);
|
|
155
245
|
}
|
|
156
246
|
}
|
|
157
247
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (C) 2021 TypeFox and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
* http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
*
|
|
8
|
+
* This Source Code may also be made available under the following Secondary
|
|
9
|
+
* Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
* with the GNU Classpath Exception which is available at
|
|
12
|
+
* https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
*
|
|
14
|
+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
+
********************************************************************************/
|
|
16
|
+
|
|
17
|
+
#theia-drag-panel {
|
|
18
|
+
position: absolute;
|
|
19
|
+
display: block;
|
|
20
|
+
top: 0;
|
|
21
|
+
left: 0;
|
|
22
|
+
width: 100%;
|
|
23
|
+
height: calc(100% - 4px);
|
|
24
|
+
margin: 4px;
|
|
25
|
+
-webkit-app-region: drag !important;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#theia-top-panel > * {
|
|
29
|
+
-webkit-app-region: no-drag;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#window-controls {
|
|
33
|
+
display: grid;
|
|
34
|
+
grid-template-columns: repeat(3, 48px);
|
|
35
|
+
position: absolute;
|
|
36
|
+
top: 0;
|
|
37
|
+
right: 0;
|
|
38
|
+
height: 100%;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
#window-controls .control-button {
|
|
42
|
+
display: flex;
|
|
43
|
+
line-height: 30px;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
align-items: center;
|
|
46
|
+
width: 100%;
|
|
47
|
+
height: 100%;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#minimize-button {
|
|
51
|
+
grid-column: 1;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
#maximize-button, #restore-button {
|
|
55
|
+
grid-column: 2;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
#close-button {
|
|
59
|
+
grid-column: 3;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#window-controls .control-button {
|
|
63
|
+
user-select: none;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#window-controls .control-button:hover {
|
|
67
|
+
background: rgba(50%, 50%, 50%, 0.2);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#window-controls #close-button:hover {
|
|
71
|
+
background: #E81123;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#window-controls #close-button:hover:before {
|
|
75
|
+
color: white;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
body:not(.maximized) #restore-button {
|
|
79
|
+
display: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
body.maximized #maximize-button {
|
|
83
|
+
display: none;
|
|
84
|
+
}
|