fix: linux titlebar (#6483)

This commit is contained in:
naman-bruno
2025-12-23 16:54:30 +05:30
committed by GitHub
parent f1961a8988
commit 49ffdd1b8f
4 changed files with 30 additions and 15 deletions

View File

@@ -201,6 +201,15 @@ const Wrapper = styled.div`
margin-left: 6px;
}
&.os-linux .titlebar-content {
padding-right: 0px;
padding-left: 0px;
}
&.os-linux .titlebar-left {
margin-left: 6px;
}
/* Custom window control buttons for Windows - always interactive, above modal overlay */
.window-controls {
display: flex;

View File

@@ -20,11 +20,12 @@ import IconBottombarToggle from 'components/Icons/IconBottombarToggle/index';
import StyledWrapper from './StyledWrapper';
import { toTitleCase } from 'utils/common/index';
import ResponseLayoutToggle from 'components/ResponsePane/ResponseLayoutToggle';
import { isMacOS, isWindowsOS } from 'utils/common/platform';
import { isMacOS, isWindowsOS, isLinuxOS } from 'utils/common/platform';
const getOsClass = () => {
if (isMacOS()) return 'os-mac';
if (isWindowsOS()) return 'os-windows';
if (isLinuxOS()) return 'os-linux';
return 'os-other';
};
@@ -34,6 +35,8 @@ const AppTitleBar = () => {
const [isMaximized, setIsMaximized] = useState(false);
const osClass = getOsClass();
const isWindows = osClass === 'os-windows';
const isLinux = osClass === 'os-linux';
const showWindowControls = isWindows || isLinux;
// Listen for fullscreen changes
useEffect(() => {
@@ -54,13 +57,11 @@ const AppTitleBar = () => {
};
}, []);
// Check initial maximized state and listen for changes (Windows only)
useEffect(() => {
if (!isWindows) return;
if (!showWindowControls) return;
const { ipcRenderer } = window;
if (!ipcRenderer) return;
// Get initial state
ipcRenderer.invoke('renderer:window-is-maximized')
.then((maximized) => {
setIsMaximized(maximized);
@@ -69,7 +70,6 @@ const AppTitleBar = () => {
console.error('Error getting initial maximized state:', error);
});
// Listen for maximize/unmaximize events from main process
const removeMaximizedListener = ipcRenderer.on('main:window-maximized', () => {
setIsMaximized(true);
});
@@ -82,9 +82,8 @@ const AppTitleBar = () => {
removeMaximizedListener();
removeUnmaximizedListener();
};
}, [isWindows]);
}, [showWindowControls]);
// Window control handlers (Windows only) - these always work, even with modals open
const handleMinimize = useCallback(() => {
window.ipcRenderer?.send('renderer:window-minimize');
}, []);
@@ -300,7 +299,7 @@ const AppTitleBar = () => {
<ResponseLayoutToggle />
</div>
{isWindows && (
{showWindowControls && (
<div className="window-controls">
<button
className="window-control-btn minimize"

View File

@@ -33,6 +33,13 @@ export const isMacOS = () => {
return osFamily.includes('os x');
};
export const isLinuxOS = () => {
const os = platform.os;
const osFamily = os.family.toLowerCase();
return osFamily.includes('linux') || osFamily.includes('ubuntu') || osFamily.includes('debian') || osFamily.includes('fedora') || osFamily.includes('centos') || osFamily.includes('arch');
};
export const getAppInstallDate = () => {
let dateString = localStorage.getItem('bruno.installedOn');

View File

@@ -85,6 +85,7 @@ setContentSecurityPolicy(contentSecurityPolicy.join(';') + ';');
const menu = Menu.buildFromTemplate(menuTemplate);
const isMac = process.platform === 'darwin';
const isWindows = process.platform === 'win32';
const isLinux = process.platform === 'linux';
let mainWindow;
let appProtocolUrl;
@@ -155,8 +156,8 @@ app.on('ready', async () => {
},
title: 'Bruno',
icon: path.join(__dirname, 'about/256x256.png'),
// Custom title bar ensure React titlebar occupies the window chrome on all OSes
titleBarStyle: isMac ? 'hiddenInset' : isWindows ? 'hidden' : 'default',
titleBarStyle: isMac ? 'hiddenInset' : isWindows ? 'hidden' : undefined,
frame: isLinux ? false : true,
trafficLightPosition: isMac ? { x: 12, y: 10 } : undefined
// we will bring this back
// see https://github.com/usebruno/bruno/issues/440
@@ -167,14 +168,13 @@ app.on('ready', async () => {
mainWindow.maximize();
}
// Window control IPC handlers (Windows custom titlebar)
ipcMain.on('renderer:window-minimize', () => {
if (!isWindows) return;
if (!isWindows && !isLinux) return;
mainWindow.minimize();
});
ipcMain.on('renderer:window-maximize', () => {
if (!isWindows) return;
if (!isWindows && !isLinux) return;
if (mainWindow.isMaximized()) {
mainWindow.unmaximize();
} else {
@@ -183,12 +183,12 @@ app.on('ready', async () => {
});
ipcMain.on('renderer:window-close', () => {
if (!isWindows) return;
if (!isWindows && !isLinux) return;
mainWindow.close();
});
ipcMain.handle('renderer:window-is-maximized', () => {
if (!isWindows) return false;
if (!isWindows && !isLinux) return false;
return mainWindow.isMaximized();
});