Add extra pixel to titlebar on Windows 11
This commit is contained in:
parent
4b8cb9f040
commit
8b32811440
26 changed files with 139 additions and 53 deletions
|
@ -30,5 +30,8 @@
|
|||
},
|
||||
waitForChange: () => {},
|
||||
},
|
||||
OS: {
|
||||
isWindows11: () => false,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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'),
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
30
stylesheets/_titlebar.scss
Normal file
30
stylesheets/_titlebar.scss
Normal 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));
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
@import 'variables';
|
||||
@import 'mixins';
|
||||
@import 'global';
|
||||
@import 'titlebar';
|
||||
|
||||
// Old style: components
|
||||
@import 'progress';
|
||||
|
|
|
@ -6,3 +6,4 @@
|
|||
@import 'variables';
|
||||
@import 'mixins';
|
||||
@import 'modules';
|
||||
@import 'titlebar';
|
||||
|
|
4
ts/OS.ts
4
ts/OS.ts
|
@ -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');
|
||||
};
|
||||
|
|
|
@ -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}
|
||||
>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -27,6 +27,7 @@ const createProps = (): PropsType => ({
|
|||
},
|
||||
executeMenuRole: action('executeMenuRole'),
|
||||
platform: 'win32',
|
||||
isWindows11: false,
|
||||
});
|
||||
|
||||
export default {
|
||||
|
|
|
@ -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}
|
||||
>
|
||||
|
|
|
@ -159,6 +159,7 @@ const createProps = (): PropsType => ({
|
|||
|
||||
executeMenuRole: action('executeMenuRole'),
|
||||
platform: 'win32',
|
||||
isWindows11: false,
|
||||
});
|
||||
|
||||
export default {
|
||||
|
|
|
@ -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}
|
||||
>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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 />
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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) =>
|
||||
|
|
|
@ -339,6 +339,7 @@ const renderPreferences = async () => {
|
|||
i18n: SignalContext.i18n,
|
||||
|
||||
platform: process.platform,
|
||||
isWindows11: SignalContext.OS.isWindows11(),
|
||||
executeMenuRole: SignalContext.executeMenuRole,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue