Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/shared/IpcChannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export enum IpcChannel {

App_QuoteToMain = 'app:quote-to-main',
App_SetDisableHardwareAcceleration = 'app:set-disable-hardware-acceleration',
App_SetUseSystemTitleBar = 'app:set-use-system-title-bar',

Notification_Send = 'notification:send',
Notification_OnClick = 'notification:on-click',
Expand Down
3 changes: 3 additions & 0 deletions src/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,9 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
ipcMain.handle(IpcChannel.App_SetDisableHardwareAcceleration, (_, isDisable: boolean) => {
configManager.setDisableHardwareAcceleration(isDisable)
})
ipcMain.handle(IpcChannel.App_SetUseSystemTitleBar, (_, isActive: boolean) => {
configManager.setUseSystemTitleBar(isActive)
})
ipcMain.handle(IpcChannel.TRACE_SAVE_DATA, (_, topicId: string) => saveSpans(topicId))
ipcMain.handle(IpcChannel.TRACE_GET_DATA, (_, topicId: string, traceId: string, modelName?: string) =>
getSpans(topicId, traceId, modelName)
Expand Down
9 changes: 9 additions & 0 deletions src/main/services/ConfigManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export enum ConfigKeys {
SelectionAssistantFilterMode = 'selectionAssistantFilterMode',
SelectionAssistantFilterList = 'selectionAssistantFilterList',
DisableHardwareAcceleration = 'disableHardwareAcceleration',
UseSystemTitleBar = 'useSystemTitleBar',
Proxy = 'proxy',
EnableDeveloperMode = 'enableDeveloperMode',
ClientId = 'clientId',
Expand Down Expand Up @@ -235,6 +236,14 @@ export class ConfigManager {
this.set(ConfigKeys.DisableHardwareAcceleration, value)
}

getUseSystemTitleBar(): boolean {
return this.get<boolean>(ConfigKeys.UseSystemTitleBar, false)
}

setUseSystemTitleBar(value: boolean) {
this.set(ConfigKeys.UseSystemTitleBar, value)
}

setAndNotify(key: string, value: unknown) {
this.set(key, value, true)
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/services/WindowService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ export class WindowService {
trafficLightPosition: { x: 8, y: 13 }
}
: {
frame: false // Frameless window for Windows and Linux
// On Linux, allow using system title bar if setting is enabled
frame: isLinux && configManager.getUseSystemTitleBar() ? true : false
}),
backgroundColor: isMac ? undefined : nativeTheme.shouldUseDarkColors ? '#181818' : '#FFFFFF',
darkTheme: nativeTheme.shouldUseDarkColors,
Expand Down
1 change: 1 addition & 0 deletions src/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ const api = {
quoteToMainWindow: (text: string) => ipcRenderer.invoke(IpcChannel.App_QuoteToMain, text),
setDisableHardwareAcceleration: (isDisable: boolean) =>
ipcRenderer.invoke(IpcChannel.App_SetDisableHardwareAcceleration, isDisable),
setUseSystemTitleBar: (isActive: boolean) => ipcRenderer.invoke(IpcChannel.App_SetUseSystemTitleBar, isActive),
trace: {
saveData: (topicId: string) => ipcRenderer.invoke(IpcChannel.TRACE_SAVE_DATA, topicId),
getData: (topicId: string, traceId: string, modelName?: string) =>
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/components/Tab/TabContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PlusOutlined } from '@ant-design/icons'
import { loggerService } from '@logger'
import { Sortable, useDndReorder } from '@renderer/components/dnd'
import HorizontalScrollContainer from '@renderer/components/HorizontalScrollContainer'
import { isMac } from '@renderer/config/constant'
import { isLinux, isMac, isWin } from '@renderer/config/constant'
import { DEFAULT_MIN_APPS } from '@renderer/config/minapps'
import { useTheme } from '@renderer/context/ThemeProvider'
import { useFullscreen } from '@renderer/hooks/useFullscreen'
Expand Down Expand Up @@ -314,7 +314,7 @@ const TabsBar = styled.div<{ $isFullscreen: boolean }>`
align-items: center;
gap: 5px;
padding-left: ${({ $isFullscreen }) => (!$isFullscreen && isMac ? 'calc(env(titlebar-area-x) + 4px)' : '15px')};
padding-right: ${({ $isFullscreen }) => ($isFullscreen ? '12px' : '0')};
padding-right: ${({ $isFullscreen }) => ($isFullscreen ? '12px' : isWin || isLinux ? '8px' : '0')};
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The paddingRight for TabsBar includes hardcoded values for Linux ('8px') when not in fullscreen mode. This padding should be conditional based on whether the system title bar is being used on Linux. When useSystemTitleBar is true on Linux, the custom window controls won't be displayed (they return null), so the padding calculation might need adjustment. Consider making the padding conditional to match whether WindowControls will actually be rendered.

Suggested change
padding-right: ${({ $isFullscreen }) => ($isFullscreen ? '12px' : isWin || isLinux ? '8px' : '0')};
padding-right: ${({ $isFullscreen }) => ($isFullscreen ? '12px' : isWin ? '8px' : '0')};

Copilot uses AI. Check for mistakes.
height: var(--navbar-height);
min-height: ${({ $isFullscreen }) => (!$isFullscreen && isMac ? 'env(titlebar-area-height)' : '')};
position: relative;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import styled from 'styled-components'

export const WindowControlsContainer = styled.div`
position: fixed;
top: 0;
right: 0;
display: flex;
align-items: center;
height: var(--navbar-height);
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/components/WindowControls/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { isLinux, isWin } from '@renderer/config/constant'
import { useSettings } from '@renderer/hooks/useSettings'
import { Tooltip } from 'antd'
import { Minus, Square, X } from 'lucide-react'
import type { SVGProps } from 'react'
Expand Down Expand Up @@ -49,6 +50,7 @@ const DEFAULT_DELAY = 1
const WindowControls: React.FC = () => {
const [isMaximized, setIsMaximized] = useState(false)
const { t } = useTranslation()
const { useSystemTitleBar } = useSettings()

useEffect(() => {
// Check initial maximized state
Expand All @@ -67,6 +69,11 @@ const WindowControls: React.FC = () => {
return null
}

// Hide on Linux if using system title bar
if (isLinux && useSystemTitleBar) {
return null
}

const handleMinimize = () => {
window.api.windowControls.minimize()
}
Expand Down
10 changes: 4 additions & 6 deletions src/renderer/src/components/app/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@ export const Navbar: FC<Props> = ({ children, ...props }) => {
}

return (
<>
<NavbarContainer {...props} style={{ backgroundColor }} $isFullScreen={isFullscreen}>
{children}
</NavbarContainer>
{!isTopNavbar && !minappShow && <WindowControls />}
</>
<NavbarContainer {...props} style={{ backgroundColor }} $isFullScreen={isFullscreen}>
{children}
{!minappShow && <WindowControls />}
</NavbarContainer>
)
}

Expand Down
5 changes: 5 additions & 0 deletions src/renderer/src/hooks/useSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
setTopicPosition,
setTray as _setTray,
setTrayOnClose,
setUseSystemTitleBar as _setUseSystemTitleBar,
setWindowStyle
} from '@renderer/store/settings'
import type { SidebarIcon, ThemeMode, TranslateLanguageCode } from '@renderer/types'
Expand Down Expand Up @@ -101,6 +102,10 @@ export function useSettings() {
setDisableHardwareAcceleration(disableHardwareAcceleration: boolean) {
dispatch(setDisableHardwareAcceleration(disableHardwareAcceleration))
window.api.setDisableHardwareAcceleration(disableHardwareAcceleration)
},
setUseSystemTitleBar(useSystemTitleBar: boolean) {
dispatch(_setUseSystemTitleBar(useSystemTitleBar))
window.api.setUseSystemTitleBar(useSystemTitleBar)
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/i18n/locales/en-us.json
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@
"show": "Show Tray Icon",
"title": "Tray"
},
"use_system_title_bar": {
"confirm": {
"content": "Changing the title bar style requires restarting the app to take effect. Do you want to restart now?",
"title": "Restart Required"
},
"title": "Use System Title Bar (Linux)"
},
"zoom": {
"reset": "Reset",
"title": "Page Zoom"
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/i18n/locales/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@
"show": "显示托盘图标",
"title": "托盘"
},
"use_system_title_bar": {
"confirm": {
"content": "更改标题栏样式需要重启应用才能生效,是否现在重启?",
"title": "需要重启应用"
},
"title": "使用系统标题栏 (Linux)"
},
"zoom": {
"reset": "重置",
"title": "缩放"
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/i18n/locales/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@
"show": "顯示系統匣圖示",
"title": "系統匣"
},
"use_system_title_bar": {
"confirm": {
"content": "[to be translated]:Changing the title bar style requires restarting the app to take effect. Do you want to restart now?",
"title": "[to be translated]:Restart Required"
},
"title": "[to be translated]:Use System Title Bar (Linux)"
},
"zoom": {
"reset": "重設",
"title": "縮放"
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/i18n/translate/de-de.json
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@
"show": "Tray-Symbol anzeigen",
"title": "Tray"
},
"use_system_title_bar": {
"confirm": {
"content": "[to be translated]:Changing the title bar style requires restarting the app to take effect. Do you want to restart now?",
"title": "[to be translated]:Restart Required"
},
"title": "[to be translated]:Use System Title Bar (Linux)"
},
"zoom": {
"reset": "Zurücksetzen",
"title": "Zoom"
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/i18n/translate/el-gr.json
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@
"show": "Εμφάνιση εικονιδίου συνδρομής",
"title": "Συνδρομή"
},
"use_system_title_bar": {
"confirm": {
"content": "[to be translated]:Changing the title bar style requires restarting the app to take effect. Do you want to restart now?",
"title": "[to be translated]:Restart Required"
},
"title": "[to be translated]:Use System Title Bar (Linux)"
},
"zoom": {
"reset": "Επαναφορά",
"title": "Κλίμακα"
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/i18n/translate/es-es.json
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@
"show": "Mostrar bandera del sistema",
"title": "Bandera"
},
"use_system_title_bar": {
"confirm": {
"content": "[to be translated]:Changing the title bar style requires restarting the app to take effect. Do you want to restart now?",
"title": "[to be translated]:Restart Required"
},
"title": "[to be translated]:Use System Title Bar (Linux)"
},
"zoom": {
"reset": "Restablecer",
"title": "Escala"
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/i18n/translate/fr-fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@
"show": "Afficher l'icône dans la barre d'état système",
"title": "Barre d'état système"
},
"use_system_title_bar": {
"confirm": {
"content": "[to be translated]:Changing the title bar style requires restarting the app to take effect. Do you want to restart now?",
"title": "[to be translated]:Restart Required"
},
"title": "[to be translated]:Use System Title Bar (Linux)"
},
"zoom": {
"reset": "Réinitialiser",
"title": "Zoom"
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/i18n/translate/ja-jp.json
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@
"show": "トレイアイコンを表示",
"title": "トレイ"
},
"use_system_title_bar": {
"confirm": {
"content": "[to be translated]:Changing the title bar style requires restarting the app to take effect. Do you want to restart now?",
"title": "[to be translated]:Restart Required"
},
"title": "[to be translated]:Use System Title Bar (Linux)"
},
"zoom": {
"reset": "リセット",
"title": "ページズーム"
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/i18n/translate/pt-pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@
"show": "Mostrar ícone de bandeja",
"title": "Tray"
},
"use_system_title_bar": {
"confirm": {
"content": "[to be translated]:Changing the title bar style requires restarting the app to take effect. Do you want to restart now?",
"title": "[to be translated]:Restart Required"
},
"title": "[to be translated]:Use System Title Bar (Linux)"
},
"zoom": {
"reset": "Redefinir",
"title": "Escala"
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/i18n/translate/ru-ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@
"show": "Показать значок в трее",
"title": "Трей"
},
"use_system_title_bar": {
"confirm": {
"content": "[to be translated]:Changing the title bar style requires restarting the app to take effect. Do you want to restart now?",
"title": "[to be translated]:Restart Required"
},
"title": "[to be translated]:Use System Title Bar (Linux)"
},
"zoom": {
"reset": "Сбросить",
"title": "Масштаб страницы"
Expand Down
3 changes: 1 addition & 2 deletions src/renderer/src/pages/home/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Navbar, NavbarCenter, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar'
import { HStack } from '@renderer/components/Layout'
import SearchPopup from '@renderer/components/Popups/SearchPopup'
import { isLinux, isWin } from '@renderer/config/constant'
import { modelGenerating } from '@renderer/hooks/useRuntime'
import { useSettings } from '@renderer/hooks/useSettings'
import { useShortcut } from '@renderer/hooks/useShortcuts'
Expand Down Expand Up @@ -123,7 +122,7 @@ const HeaderNavbar: FC<Props> = ({
justifyContent: 'flex-end',
flex: activeTopicOrSession === 'topic' ? 1 : 'none',
position: 'relative',
paddingRight: isWin || isLinux ? '144px' : '15px',
paddingRight: '8px',
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The paddingRight is now hardcoded to '8px' for all platforms, but this might not provide enough space for the WindowControls on Windows and Linux when the system title bar is not being used. Consider making this conditional based on the platform and useSystemTitleBar setting to ensure proper spacing for the window controls.

Suggested change
paddingRight: '8px',
paddingRight:
typeof navigator !== 'undefined' && /Windows|Win32|Linux/i.test(navigator.userAgent)
? '80px'
: '8px',

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

@DeJeune DeJeune Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This issue/comment/review was translated by Claude.

Why was this changed?


Original Content

这里为啥要改

Copy link
Collaborator Author

@beyondkmp beyondkmp Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This comment was translated by Claude.

  1. WindowControls positioning has changed

Previously (main branch):

position: fixed;
top: 0;
right: 0;

The window control buttons were fixed in the top-right corner of the window, so Navbar.tsx needed paddingRight: 144px to prevent content from being obscured.

Currently (feature branch):

/* Removed fixed positioning */
display: flex;

The window control buttons have become flex children, directly placed inside the NavbarContainer.

  1. Navbar structure has also changed

Previously: WindowControls was outside the NavbarContainer, using fixed positioning

Currently: WindowControls is inside the NavbarContainer, naturally arranged as flex children

Conclusion

So paddingRight: '8px' is correct! Because:

  • The window control buttons are now part of the flex layout and will automatically take up space
  • No need to manually reserve 144px of space anymore
  • Both Windows and Linux use the same flex layout approach

However, I've unified it to use 15px as before, which has been corrected.


Original Content
  1. WindowControls 定位方式改变了

之前(main 分支):
position: fixed;
top: 0;
right: 0;
窗口控制按钮是固定定位在窗口右上角的,所以 Navbar.tsx 需要 paddingRight: 144px 来避免内容被遮挡。

现在(feature 分支):
/* 移除了 fixed 定位 */
display: flex;
窗口控制按钮变成了 flex 子元素,直接放在 NavbarContainer 里面。

  1. Navbar 结构也改变了

之前:WindowControls 在 NavbarContainer 外面,使用 fixed 定位
现在:WindowControls 在 NavbarContainer 里面,作为 flex 子元素自然排列

结论

所以 paddingRight: '8px' 是正确的!因为:

  • 窗口控制按钮现在是 flex 布局的一部分,会自动占据空间
  • 不再需要手动预留 144px 的空间
  • Windows 和 Linux 都使用同样的 flex 布局方式

不过还是和之前统一下使用15 px, 已经修正了。

minWidth: activeTopicOrSession === 'topic' ? '' : 'auto'
}}
className="home-navbar-right">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import CodeEditor from '@renderer/components/CodeEditor'
import { ResetIcon } from '@renderer/components/Icons'
import { HStack } from '@renderer/components/Layout'
import TextBadge from '@renderer/components/TextBadge'
import { isMac, THEME_COLOR_PRESETS } from '@renderer/config/constant'
import { isLinux, isMac, THEME_COLOR_PRESETS } from '@renderer/config/constant'
import { DEFAULT_SIDEBAR_ICONS } from '@renderer/config/sidebar'
import { useTheme } from '@renderer/context/ThemeProvider'
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
import { useTimer } from '@renderer/hooks/useTimer'
import useUserTheme from '@renderer/hooks/useUserTheme'
import { useAppDispatch } from '@renderer/store'
import type { AssistantIconType } from '@renderer/store/settings'
Expand Down Expand Up @@ -68,12 +69,15 @@ const DisplaySettings: FC = () => {
sidebarIcons,
setTheme,
assistantIconType,
userTheme
userTheme,
useSystemTitleBar,
setUseSystemTitleBar
} = useSettings()
const { navbarPosition, setNavbarPosition } = useNavbarPosition()
const { theme, settedTheme } = useTheme()
const { t } = useTranslation()
const dispatch = useAppDispatch()
const { setTimeoutTimer } = useTimer()
const [currentZoom, setCurrentZoom] = useState(1.0)
const { setUserTheme } = useUserTheme()

Expand All @@ -88,6 +92,26 @@ const DisplaySettings: FC = () => {
[setWindowStyle]
)

const handleUseSystemTitleBarChange = (checked: boolean) => {
window.modal.confirm({
title: t('settings.use_system_title_bar.confirm.title'),
content: t('settings.use_system_title_bar.confirm.content'),
okText: t('common.confirm'),
cancelText: t('common.cancel'),
centered: true,
onOk() {
setUseSystemTitleBar(checked)
setTimeoutTimer(
'handleUseSystemTitleBarChange',
() => {
window.api.relaunchApp()
},
500
)
}
})
}

const handleColorPrimaryChange = useCallback(
(colorHex: string) => {
setUserTheme({
Expand Down Expand Up @@ -245,6 +269,15 @@ const DisplaySettings: FC = () => {
</SettingRow>
</>
)}
{isLinux && (
<>
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.use_system_title_bar.title')}</SettingRowTitle>
<Switch checked={useSystemTitleBar} onChange={handleUseSystemTitleBarChange} />
</SettingRow>
</>
)}
</SettingGroup>
<SettingGroup theme={theme}>
<SettingTitle style={{ justifyContent: 'flex-start', gap: 5 }}>
Expand Down
Loading