From 539f854dbfa054cd075ff77887fb8dee6e5107fc Mon Sep 17 00:00:00 2001
From: H3CoF6 <1707889225@qq.com>
Date: Sat, 21 Mar 2026 02:53:03 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0wayland=E6=A3=80?=
=?UTF-8?q?=E6=9F=A5=E5=92=8C=E6=B6=88=E6=81=AF=E5=BC=B9=E7=AA=97=E4=BD=8D?=
=?UTF-8?q?=E7=BD=AE=E5=A4=B1=E6=95=88=E8=AF=B4=E6=98=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
electron/main.ts | 7 +++
electron/preload.ts | 3 +-
electron/services/keyServiceLinux.ts | 3 +-
src/App.tsx | 67 ++++++++++++++++++++++++++++
src/types/electron.d.ts | 1 +
5 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/electron/main.ts b/electron/main.ts
index a60c898..3a5dab3 100644
--- a/electron/main.ts
+++ b/electron/main.ts
@@ -1043,6 +1043,13 @@ function registerIpcHandlers() {
return app.getVersion()
})
+ ipcMain.handle('app:checkWayland', async () => {
+ if (process.platform !== 'linux') return false;
+
+ const sessionType = process.env.XDG_SESSION_TYPE?.toLowerCase();
+ return Boolean(process.env.WAYLAND_DISPLAY || sessionType === 'wayland');
+ })
+
ipcMain.handle('log:getPath', async () => {
return join(app.getPath('userData'), 'logs', 'wcdb.log')
})
diff --git a/electron/preload.ts b/electron/preload.ts
index f12a272..b1c9c30 100644
--- a/electron/preload.ts
+++ b/electron/preload.ts
@@ -63,7 +63,8 @@ contextBridge.exposeInMainWorld('electronAPI', {
onUpdateAvailable: (callback: (info: { version: string; releaseNotes: string }) => void) => {
ipcRenderer.on('app:updateAvailable', (_, info) => callback(info))
return () => ipcRenderer.removeAllListeners('app:updateAvailable')
- }
+ },
+ checkWayland: () => ipcRenderer.invoke('app:checkWayland'),
},
// 日志
diff --git a/electron/services/keyServiceLinux.ts b/electron/services/keyServiceLinux.ts
index 8fe2cc4..7364f83 100644
--- a/electron/services/keyServiceLinux.ts
+++ b/electron/services/keyServiceLinux.ts
@@ -1,10 +1,9 @@
import { app } from 'electron'
import { join } from 'path'
import { existsSync, readdirSync, statSync, readFileSync } from 'fs'
-import { execFile, exec } from 'child_process'
+import { execFile, exec, spawn } from 'child_process'
import { promisify } from 'util'
import { createRequire } from 'module';
-import { spawn } from 'child_process'
const require = createRequire(import.meta.url);
const execFileAsync = promisify(execFile)
diff --git a/src/App.tsx b/src/App.tsx
index eb8cd5c..e09f7ef 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -104,6 +104,44 @@ function App() {
// 数据收集同意状态
const [showAnalyticsConsent, setShowAnalyticsConsent] = useState(false)
+ const [showWaylandWarning, setShowWaylandWarning] = useState(false)
+
+ useEffect(() => {
+ const checkWaylandStatus = async () => {
+ try {
+ // 防止在非客户端环境报错,先检查 API 是否存在
+ if (!window.electronAPI?.app?.checkWayland) return
+
+ // 通过 configService 检查是否已经弹过窗
+ const hasWarned = await window.electronAPI.config.get('waylandWarningShown')
+
+ if (!hasWarned) {
+ const isWayland = await window.electronAPI.app.checkWayland()
+ if (isWayland) {
+ setShowWaylandWarning(true)
+ }
+ }
+ } catch (e) {
+ console.error('检查 Wayland 状态失败:', e)
+ }
+ }
+
+ // 只有在协议同意之后并且已经进入主应用流程才检查
+ if (!isAgreementWindow && !isOnboardingWindow && !agreementLoading) {
+ checkWaylandStatus()
+ }
+ }, [isAgreementWindow, isOnboardingWindow, agreementLoading])
+
+ const handleDismissWaylandWarning = async () => {
+ try {
+ // 记录到本地配置中,下次不再提示
+ await window.electronAPI.config.set('waylandWarningShown', true)
+ } catch (e) {
+ console.error('保存 Wayland 提示状态失败:', e)
+ }
+ setShowWaylandWarning(false)
+ }
+
useEffect(() => {
if (location.pathname !== '/settings') {
settingsBackgroundRef.current = location
@@ -432,6 +470,8 @@ function App() {
checkLock()
}, [isAgreementWindow, isOnboardingWindow, isVideoPlayerWindow])
+
+
// 独立协议窗口
if (isAgreementWindow) {
return
检测到您当前正在使用 Wayland 显示服务器。
+在 Wayland 环境下,出于系统级的安全与设计机制,应用程序无法直接控制新弹出窗口的位置。
+这可能导致某些独立窗口(如消息通知、图片查看器等)出现位置随机、或不受控制的情况。这是底层机制导致的,对此我们无能为力。
+如果您觉得窗口位置异常严重影响了使用体验,建议尝试:
+1. 在系统登录界面,将会话切换回 X11 (Xorg) 模式。
+2. 修改您的桌面管理器 (WM/DE) 配置,强制指定该应用程序的窗口规则。
+