Add extra pixel to titlebar on Windows 11

This commit is contained in:
Fedor Indutny 2022-06-15 11:21:03 -07:00 committed by GitHub
parent 4b8cb9f040
commit 8b32811440
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 139 additions and 53 deletions

View File

@ -30,5 +30,8 @@
},
waitForChange: () => {},
},
OS: {
isWindows11: () => false,
},
};
</script>

View File

@ -626,7 +626,7 @@ async function getTitleBarOverlay(): Promise<TitleBarOverlayOptions | false> {
// Should match stylesheets/components/TitleBarContainer.scss minus the
// border
height: 28 - 1,
height: (OS.isWindows11() ? 29 : 28) - 1,
};
}
@ -1261,7 +1261,8 @@ async function showStickerCreator() {
const { x = 0, y = 0 } = windowConfig || {};
// TODO: DESKTOP-3670
const titleBarOverlay = await getTitleBarOverlay();
const options = {
x: x + 100,
y: y + 100,
@ -1269,6 +1270,8 @@ async function showStickerCreator() {
minWidth: 800,
height: 650,
title: getLocale().i18n('signalDesktopStickerCreator'),
titleBarStyle: nonMainTitleBarStyle,
titleBarOverlay,
autoHideMenuBar: true,
backgroundColor: await getBackgroundColor(),
show: false,
@ -1286,7 +1289,7 @@ async function showStickerCreator() {
stickerCreatorWindow = new BrowserWindow(options);
setupSpellChecker(stickerCreatorWindow, getLocale());
handleCommonWindowEvents(stickerCreatorWindow);
handleCommonWindowEvents(stickerCreatorWindow, titleBarOverlay);
const appUrl = process.env.SIGNAL_ENABLE_HTTP
? prepareUrl(

View File

@ -80,6 +80,6 @@ esbuild.build({
esbuild.build({
...bundleDefaults,
mainFields: ['browser', 'main'],
entryPoints: [path.join(ROOT_DIR, 'ts/windows/main/preload.ts')],
entryPoints: [path.join(ROOT_DIR, 'ts', 'windows', 'main', 'preload.ts')],
outfile: path.join(ROOT_DIR, 'preload.bundle.js'),
});

View File

@ -6,8 +6,8 @@
.container {
display: grid;
height: 100vh;
grid-template-rows: 47px calc(100vh - 47px - 68px) 68px;
height: var(--window-height);
grid-template-rows: 47px calc(var(--window-height) - 47px - 68px) 68px;
@include light-theme() {
background-color: $color-white;

View File

@ -11,31 +11,53 @@ import { ShareStage } from './stages/ShareStage';
import * as styles from './index.scss';
import { PageHeader } from '../elements/PageHeader';
import { useI18n } from '../util/i18n';
import { TitleBarContainer } from '../../ts/components/TitleBarContainer';
import type { ExecuteMenuRoleType } from '../../ts/components/TitleBarContainer';
import { useTheme } from '../../ts/hooks/useTheme';
export const App: React.ComponentType = () => {
export type AppPropsType = Readonly<{
platform: string;
executeMenuRole: ExecuteMenuRoleType;
isWindows11: boolean;
}>;
export const App = ({
platform,
executeMenuRole,
isWindows11,
}: AppPropsType): JSX.Element => {
const i18n = useI18n();
const theme = useTheme();
return (
<div className={styles.container}>
<PageHeader>{i18n('StickerCreator--title')}</PageHeader>
<Switch>
<Route path="/drop">
<DropStage />
</Route>
<Route path="/add-emojis">
<EmojiStage />
</Route>
<Route path="/add-meta">
<MetaStage />
</Route>
<Route path="/upload">
<UploadStage />
</Route>
<Route path="/share">
<ShareStage />
</Route>
<Redirect to="/drop" />
</Switch>
</div>
<TitleBarContainer
iconSrc="../../images/icon_32.png"
platform={platform}
isWindows11={isWindows11}
theme={theme}
executeMenuRole={executeMenuRole}
>
<div className={styles.container}>
<PageHeader>{i18n('StickerCreator--title')}</PageHeader>
<Switch>
<Route path="/drop">
<DropStage />
</Route>
<Route path="/add-emojis">
<EmojiStage />
</Route>
<Route path="/add-meta">
<MetaStage />
</Route>
<Route path="/upload">
<UploadStage />
</Route>
<Route path="/share">
<ShareStage />
</Route>
<Redirect to="/drop" />
</Switch>
</div>
</TitleBarContainer>
);
};

View File

@ -4,7 +4,7 @@
.facade {
background: rgba(0, 0, 0, 0.33);
width: 100vw;
height: 100vh;
height: var(--window-height);
display: flex;
justify-content: center;
align-items: center;

View File

@ -5,7 +5,7 @@
<html>
<head>
<link
href="../../node_modules/@indutny/frameless-titlebar/src/title-bar/style.css"
href="../../node_modules/@indutny/frameless-titlebar/dist/styles.css"
rel="stylesheet"
type="text/css"
/>
@ -14,6 +14,7 @@
<body>
<div id="root"></div>
<script type="text/javascript" src="../../js/components.js"></script>
<script type="text/javascript" src="../../ts/set_os_class.js"></script>
<script
type="text/javascript"
src="../../ts/backbone/backbonejQuery.js"

View File

@ -16,7 +16,11 @@ const ColdRoot = () => (
<ReduxProvider store={store}>
<Router history={history}>
<I18n messages={localeMessages} locale={SignalContext.config.locale}>
<App />
<App
executeMenuRole={SignalContext.executeMenuRole}
platform={SignalContext.OS.platform}
isWindows11={SignalContext.OS.isWindows11()}
/>
</I18n>
</Router>
</ReduxProvider>

View File

@ -16,25 +16,6 @@ body {
@include font-body-1;
// These should match the logic in `ts/types/Settings.ts`'s `getTitleBarVisibility`.
//
// It'd be great if we could use the `:fullscreen` selector here, but that does not seem
// to work with Electron, at least on macOS.
--title-bar-drag-area-height: 0px; // Needs to have a unit to work with `calc()`.
--draggable-app-region: initial;
&.os-macos:not(.full-screen) {
--title-bar-drag-area-height: 28px;
--draggable-app-region: drag;
}
--window-height: 100vh;
--titlebar-height: 0px;
&.os-windows:not(.full-screen) {
--titlebar-height: 28px;
--window-height: calc(100vh - var(--titlebar-height));
}
&.light-theme {
background-color: $color-white;
color: $color-gray-90;

View File

@ -0,0 +1,30 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
body {
// These should match the logic in `ts/types/Settings.ts`'s `getTitleBarVisibility`.
//
// It'd be great if we could use the `:fullscreen` selector here, but that does not seem
// to work with Electron, at least on macOS.
--title-bar-drag-area-height: 0px; // Needs to have a unit to work with `calc()`.
--draggable-app-region: initial;
&.os-macos:not(.full-screen) {
--title-bar-drag-area-height: 28px;
--draggable-app-region: drag;
}
--window-height: 100vh;
--titlebar-height: 0px;
&.os-windows:not(.full-screen) {
--titlebar-height: 28px;
// Account for border eating one pixel out of the titlebar and making it
// look unbalanced
&.os-windows-11 {
--titlebar-height: calc(28px + 1px);
}
--window-height: calc(100vh - var(--titlebar-height));
}
}

View File

@ -6,6 +6,7 @@
@import 'variables';
@import 'mixins';
@import 'global';
@import 'titlebar';
// Old style: components
@import 'progress';

View File

@ -6,3 +6,4 @@
@import 'variables';
@import 'mixins';
@import 'modules';
@import 'titlebar';

View File

@ -16,3 +16,7 @@ export const isWindows = (minVersion?: string): boolean => {
return is.undefined(minVersion) ? true : semver.gte(osRelease, minVersion);
};
export const isWindows11 = (): boolean => {
// See https://docs.microsoft.com/en-us/answers/questions/586619/windows-11-build-ver-is-still-10022000194.html
return isWindows('10.0.22000');
};

View File

@ -15,6 +15,7 @@ export type PropsType = {
i18n: LocalizerType;
version: string;
platform: string;
isWindows11: boolean;
executeMenuRole: ExecuteMenuRoleType;
};
@ -24,6 +25,7 @@ export const About = ({
environment,
version,
platform,
isWindows11,
executeMenuRole,
}: PropsType): JSX.Element => {
useEscapeHandling(closeAbout);
@ -33,6 +35,7 @@ export const About = ({
return (
<TitleBarContainer
platform={platform}
isWindows11={isWindows11}
theme={theme}
executeMenuRole={executeMenuRole}
>

View File

@ -37,6 +37,7 @@ type PropsType = {
isFullScreen: boolean;
menuOptions: MenuOptionsType;
platform: string;
isWindows11: boolean;
executeMenuRole: ExecuteMenuRoleType;
executeMenuAction: (action: MenuActionType) => void;
@ -54,6 +55,7 @@ export const App = ({
isShowingStoriesView,
isMaximized,
isFullScreen,
isWindows11,
menuOptions,
platform,
localeMessages,
@ -139,6 +141,7 @@ export const App = ({
isMaximized={isMaximized}
isFullScreen={isFullScreen}
platform={platform}
isWindows11={isWindows11}
hasMenu
localeMessages={localeMessages}
menuOptions={menuOptions}

View File

@ -27,6 +27,7 @@ const createProps = (): PropsType => ({
},
executeMenuRole: action('executeMenuRole'),
platform: 'win32',
isWindows11: false,
});
export default {

View File

@ -32,6 +32,7 @@ export type PropsType = {
fetchLogs: () => Promise<string>;
uploadLogs: (logs: string) => Promise<string>;
platform: string;
isWindows11: boolean;
executeMenuRole: ExecuteMenuRoleType;
};
@ -48,6 +49,7 @@ export const DebugLogWindow = ({
fetchLogs,
uploadLogs,
platform,
isWindows11,
executeMenuRole,
}: PropsType): JSX.Element => {
const [loadState, setLoadState] = useState<LoadState>(LoadState.NotStarted);
@ -146,6 +148,7 @@ export const DebugLogWindow = ({
return (
<TitleBarContainer
platform={platform}
isWindows11={isWindows11}
theme={theme}
executeMenuRole={executeMenuRole}
>
@ -189,6 +192,7 @@ export const DebugLogWindow = ({
return (
<TitleBarContainer
platform={platform}
isWindows11={isWindows11}
theme={theme}
executeMenuRole={executeMenuRole}
>

View File

@ -159,6 +159,7 @@ const createProps = (): PropsType => ({
executeMenuRole: action('executeMenuRole'),
platform: 'win32',
isWindows11: false,
});
export default {

View File

@ -103,6 +103,7 @@ export type PropsType = {
}
) => unknown;
platform: string;
isWindows11: boolean;
executeMenuRole: ExecuteMenuRoleType;
// Limited support features
@ -229,6 +230,7 @@ export const Preferences = ({
isNotificationAttentionSupported,
isSyncSupported,
isSystemTraySupported,
isWindows11,
lastSyncTime,
makeSyncRequest,
notificationContent,
@ -1027,6 +1029,7 @@ export const Preferences = ({
return (
<TitleBarContainer
platform={platform}
isWindows11={isWindows11}
theme={theme}
executeMenuRole={executeMenuRole}
>

View File

@ -27,13 +27,19 @@ export type PropsType = Readonly<{
theme: ThemeType;
isMaximized?: boolean;
isFullScreen?: boolean;
isWindows11: boolean;
platform: string;
executeMenuRole: ExecuteMenuRoleType;
titleBarDoubleClick?: () => void;
children: ReactNode;
// Needs to be overriden in sticker-creator
iconSrc?: string;
}> &
(MenuPropsType | { hasMenu?: false });
const TITLEBAR_HEIGHT = 28;
// Windows only
const ROLE_TO_ACCELERATOR = new Map<
MenuItemConstructorOptions['role'],
@ -108,11 +114,13 @@ export const TitleBarContainer = (props: PropsType): JSX.Element => {
theme,
isMaximized,
isFullScreen,
isWindows11,
executeMenuRole,
titleBarDoubleClick,
children,
platform,
hasMenu,
platform,
iconSrc = 'images/icon_32.png',
} = props;
if (platform !== 'win32' || isFullScreen) {
@ -151,6 +159,8 @@ export const TitleBarContainer = (props: PropsType): JSX.Element => {
const titleBarTheme = {
bar: {
// See stylesheets/_global.scss
height: isWindows11 ? TITLEBAR_HEIGHT + 1 : TITLEBAR_HEIGHT,
palette:
theme === ThemeType.light ? ('light' as const) : ('dark' as const),
},
@ -168,7 +178,7 @@ export const TitleBarContainer = (props: PropsType): JSX.Element => {
<TitleBar
className="TitleBarContainer__title"
platform={platform}
iconSrc="images/icon_32.png"
iconSrc={iconSrc}
theme={titleBarTheme}
maximized={isMaximized}
menu={maybeMenu}

View File

@ -5,6 +5,9 @@
let className: string;
if (window.SignalContext.OS.isWindows()) {
className = 'os-windows';
if (window.SignalContext.OS.isWindows11()) {
document.body.classList.add('os-windows-11');
}
} else if (window.SignalContext.OS.isMacOS()) {
className = 'os-macos';
} else if (window.SignalContext.OS.isLinux()) {

View File

@ -41,6 +41,7 @@ const mapStateToProps = (state: StateType) => {
isFullScreen: getIsMainWindowFullScreen(state),
menuOptions: getMenuOptions(state),
platform: getPlatform(state),
isWindows11: window.SignalContext.OS.isWindows11(),
renderCallManager: () => <SmartCallManager />,
renderCustomizingPreferredReactionsModal: () => (
<SmartCustomizingPreferredReactionsModal />

View File

@ -34,6 +34,7 @@ contextBridge.exposeInMainWorld('SignalContext', {
i18n: SignalContext.i18n,
version: SignalContext.getVersion(),
platform: process.platform,
isWindows11: SignalContext.OS.isWindows11(),
executeMenuRole: SignalContext.executeMenuRole,
}),
document.getElementById('app')

View File

@ -28,7 +28,7 @@ import { createSetting } from '../util/preload';
import { initialize as initializeLogging } from '../logging/set_up_renderer_logging';
import { waitForSettingsChange } from './waitForSettingsChange';
import { createNativeThemeListener } from '../context/createNativeThemeListener';
import { isWindows, isLinux, isMacOS } from '../OS';
import { isWindows, isWindows11, isLinux, isMacOS } from '../OS';
const params = new URLSearchParams(document.location.search);
const configParam = params.get('config');
@ -63,7 +63,9 @@ export type SignalContextType = {
waitForChange: () => Promise<void>;
};
OS: {
platform: string;
isWindows: typeof isWindows;
isWindows11: typeof isWindows11;
isLinux: typeof isLinux;
isMacOS: typeof isMacOS;
};
@ -89,7 +91,9 @@ export const SignalContext: SignalContextType = {
waitForChange: waitForSettingsChange,
},
OS: {
platform: process.platform,
isWindows,
isWindows11,
isLinux,
isMacOS,
},

View File

@ -24,6 +24,7 @@ contextBridge.exposeInMainWorld('SignalContext', {
ReactDOM.render(
React.createElement(DebugLogWindow, {
platform: process.platform,
isWindows11: SignalContext.OS.isWindows11(),
executeMenuRole: SignalContext.executeMenuRole,
closeWindow: () => SignalContext.executeMenuRole('close'),
downloadLog: (logText: string) =>

View File

@ -339,6 +339,7 @@ const renderPreferences = async () => {
i18n: SignalContext.i18n,
platform: process.platform,
isWindows11: SignalContext.OS.isWindows11(),
executeMenuRole: SignalContext.executeMenuRole,
};