fix(linux): Can't change Chinese IMEs on Debian (#582)
Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Haze <hazeone@users.noreply.github.com>
This commit is contained in:
@@ -113,6 +113,8 @@ function getAppIcon(): Electron.NativeImage | undefined {
|
|||||||
*/
|
*/
|
||||||
function createWindow(): BrowserWindow {
|
function createWindow(): BrowserWindow {
|
||||||
const isMac = process.platform === 'darwin';
|
const isMac = process.platform === 'darwin';
|
||||||
|
const isWindows = process.platform === 'win32';
|
||||||
|
const useCustomTitleBar = isWindows;
|
||||||
|
|
||||||
const win = new BrowserWindow({
|
const win = new BrowserWindow({
|
||||||
width: 1280,
|
width: 1280,
|
||||||
@@ -127,9 +129,9 @@ function createWindow(): BrowserWindow {
|
|||||||
sandbox: false,
|
sandbox: false,
|
||||||
webviewTag: true, // Enable <webview> for embedding OpenClaw Control UI
|
webviewTag: true, // Enable <webview> for embedding OpenClaw Control UI
|
||||||
},
|
},
|
||||||
titleBarStyle: isMac ? 'hiddenInset' : 'hidden',
|
titleBarStyle: isMac ? 'hiddenInset' : useCustomTitleBar ? 'hidden' : 'default',
|
||||||
trafficLightPosition: isMac ? { x: 16, y: 16 } : undefined,
|
trafficLightPosition: isMac ? { x: 16, y: 16 } : undefined,
|
||||||
frame: isMac,
|
frame: isMac || !useCustomTitleBar,
|
||||||
show: false,
|
show: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2194,7 +2194,7 @@ function registerUsageHandlers(): void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Window control handlers (for custom title bar on Windows/Linux)
|
* Window control handlers (for custom title bar on Windows)
|
||||||
*/
|
*/
|
||||||
function registerWindowHandlers(mainWindow: BrowserWindow): void {
|
function registerWindowHandlers(mainWindow: BrowserWindow): void {
|
||||||
ipcMain.handle('window:minimize', () => {
|
ipcMain.handle('window:minimize', () => {
|
||||||
|
|||||||
@@ -1,20 +1,26 @@
|
|||||||
/**
|
/**
|
||||||
* TitleBar Component
|
* TitleBar Component
|
||||||
* macOS: empty drag region (native traffic lights handled by hiddenInset).
|
* macOS: empty drag region (native traffic lights handled by hiddenInset).
|
||||||
* Windows/Linux: drag region on left, minimize/maximize/close on right.
|
* Windows: drag region with custom minimize/maximize/close controls.
|
||||||
|
* Linux: use native window chrome (no custom title bar).
|
||||||
*/
|
*/
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Minus, Square, X, Copy } from 'lucide-react';
|
import { Minus, Square, X, Copy } from 'lucide-react';
|
||||||
import { invokeIpc } from '@/lib/api-client';
|
import { invokeIpc } from '@/lib/api-client';
|
||||||
|
|
||||||
const isMac = window.electron?.platform === 'darwin';
|
|
||||||
|
|
||||||
export function TitleBar() {
|
export function TitleBar() {
|
||||||
if (isMac) {
|
const platform = window.electron?.platform;
|
||||||
|
|
||||||
|
if (platform === 'darwin') {
|
||||||
// macOS: just a drag region, traffic lights are native
|
// macOS: just a drag region, traffic lights are native
|
||||||
return <div className="drag-region h-10 shrink-0 border-b bg-background" />;
|
return <div className="drag-region h-10 shrink-0 border-b bg-background" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Linux keeps the native frame/title bar for better IME compatibility.
|
||||||
|
if (platform !== 'win32') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return <WindowsTitleBar />;
|
return <WindowsTitleBar />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
50
tests/unit/title-bar.test.tsx
Normal file
50
tests/unit/title-bar.test.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
import { render, screen, waitFor } from '@testing-library/react';
|
||||||
|
import { TitleBar } from '@/components/layout/TitleBar';
|
||||||
|
|
||||||
|
const invokeIpcMock = vi.hoisted(() => vi.fn());
|
||||||
|
|
||||||
|
vi.mock('@/lib/api-client', () => ({
|
||||||
|
invokeIpc: (...args: unknown[]) => invokeIpcMock(...args),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('TitleBar platform behavior', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
invokeIpcMock.mockReset();
|
||||||
|
invokeIpcMock.mockResolvedValue(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders macOS drag region', () => {
|
||||||
|
window.electron.platform = 'darwin';
|
||||||
|
|
||||||
|
const { container } = render(<TitleBar />);
|
||||||
|
|
||||||
|
expect(container.querySelector('.drag-region')).toBeInTheDocument();
|
||||||
|
expect(screen.queryByTitle('Minimize')).not.toBeInTheDocument();
|
||||||
|
expect(invokeIpcMock).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders custom controls on Windows', async () => {
|
||||||
|
window.electron.platform = 'win32';
|
||||||
|
|
||||||
|
render(<TitleBar />);
|
||||||
|
|
||||||
|
expect(screen.getByTitle('Minimize')).toBeInTheDocument();
|
||||||
|
expect(screen.getByTitle('Maximize')).toBeInTheDocument();
|
||||||
|
expect(screen.getByTitle('Close')).toBeInTheDocument();
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(invokeIpcMock).toHaveBeenCalledWith('window:isMaximized');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders no custom title bar on Linux', () => {
|
||||||
|
window.electron.platform = 'linux';
|
||||||
|
|
||||||
|
const { container } = render(<TitleBar />);
|
||||||
|
|
||||||
|
expect(container.firstChild).toBeNull();
|
||||||
|
expect(screen.queryByTitle('Minimize')).not.toBeInTheDocument();
|
||||||
|
expect(invokeIpcMock).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user