fix(linux): enable floating window frame by default on GNOME

This commit is contained in:
Cristian
2026-10-18 12:04:04 +08:00
committed by GitHub
parent ed8852f62a
commit 6e3afd19fd
3 changed files with 52 additions and 20 deletions
+3 -3
View File
@@ -35,15 +35,15 @@ description: DBX 常见问题:连接数据保存在哪里、如何备份、如
## Linux 窗口闪烁或内容消失
Linux 主窗口默认使用不透明背景,避免部分 KDE、显卡驱动与 WebKitGTK 的透明窗口合成兼容问题。不会因此关闭 GPU 加速或改变 Wayland/X11 后端。
在 GNOME 且系统已开启窗口合成时,Linux 主窗口会绘制带圆角、阴影的浮动边框;在其他桌面(KDE、XFCE、Cinnamon 等)默认使用不透明背景,避免部分显卡驱动与 WebKitGTK 的透明窗口合成兼容问题。两种模式都不会关闭 GPU 加速或改变 Wayland/X11 后端。
如果确认当前环境支持透明窗口,可以显式启用带圆角、阴影的浮动边框:
可以通过环境变量覆盖默认行为。在其他桌面强制启用浮动边框:
```bash
DBX_LINUX_FLOATING_FRAME=1 dbx
```
只有环境变量值为 `1` 且系统已开启窗口合成时才启用。若启用后出现闪烁、内容消失或必须缩放窗口才能重绘,请完全退出 DBX(包括托盘),移除该环境变量或使用 `DBX_LINUX_FLOATING_FRAME=0 dbx` 重新启动。AppImage 用户请将 `dbx` 替换为实际的 AppImage 文件路径。
若在 GNOME 上出现闪烁、内容消失或必须缩放窗口才能重绘,请完全退出 DBX(包括托盘),并使用 `DBX_LINUX_FLOATING_FRAME=0 dbx` 重新启动以强制使用不透明窗口。没有窗口合成时始终不启用浮动边框。AppImage 用户请将 `dbx` 替换为实际的 AppImage 文件路径。
如果默认的不透明窗口仍有问题,请在反馈中提供 DBX 版本、安装方式、KDE/Plasma 版本、Wayland/X11 会话类型、显卡及驱动信息,以及系统 WebKitGTK 版本。
+3 -3
View File
@@ -35,15 +35,15 @@ description: Frequently asked questions about DBX, including where connection da
## Linux Window Flickering or Missing Content
The Linux main window uses an opaque background by default to avoid transparent-window compositing compatibility problems with some KDE, graphics driver and WebKitGTK combinations. This does not disable GPU acceleration or change the Wayland/X11 backend.
The Linux main window draws a rounded, shadowed floating frame on GNOME when a compositing manager is running. On other desktops (KDE, XFCE, Cinnamon, ...) it uses an opaque background by default to avoid transparent-window compositing problems with some graphics driver and WebKitGTK combinations. Neither mode disables GPU acceleration or changes the Wayland/X11 backend.
If your environment supports transparent windows, you can explicitly enable the floating frame with rounded corners and a shadow:
The default can be overridden with an environment variable. To force the floating frame on another desktop:
```bash
DBX_LINUX_FLOATING_FRAME=1 dbx
```
The frame is enabled only when the variable is exactly `1` and a compositing manager is available. If enabling it causes flickering, missing content or redraws only after resizing, quit DBX completely, including its tray process, and remove the variable or restart with `DBX_LINUX_FLOATING_FRAME=0 dbx`. For AppImage installations, replace `dbx` with the actual AppImage path.
To force the opaque window on GNOME, for example if you see flickering, missing content or redraws only after resizing, quit DBX completely, including its tray process, and restart with `DBX_LINUX_FLOATING_FRAME=0 dbx`. The frame is never used without a compositing manager. For AppImage installations, replace `dbx` with the actual AppImage path.
If the default opaque window still has problems, include the DBX version, installation format, KDE/Plasma version, Wayland/X11 session type, graphics hardware and driver details, and system WebKitGTK version in your report.
+46 -14
View File
@@ -176,21 +176,45 @@ pub(crate) fn linux_compositing_available() -> bool {
gtk::gdk::Screen::default().is_some_and(|screen| screen.is_composited())
}
/// Desktops where the transparent floating frame is known to render correctly. Others (notably
/// KDE, which shows flickering or missing content with some driver/WebKitGTK combinations) keep
/// the opaque window unless the user forces the frame on.
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
fn should_enable_linux_floating_frame(compositing: bool, opt_in: Option<&std::ffi::OsStr>) -> bool {
compositing && opt_in == Some(std::ffi::OsStr::new("1"))
fn linux_desktop_supports_floating_frame(current_desktop: Option<&std::ffi::OsStr>) -> bool {
current_desktop
.map(|value| value.to_string_lossy().split(':').any(|name| name.eq_ignore_ascii_case("GNOME")))
.unwrap_or(false)
}
/// `DBX_LINUX_FLOATING_FRAME=1|0` is an optional override; without it the desktop decides.
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
fn should_enable_linux_floating_frame(
compositing: bool,
override_value: Option<&std::ffi::OsStr>,
current_desktop: Option<&std::ffi::OsStr>,
) -> bool {
if !compositing {
return false;
}
match override_value.and_then(|value| value.to_str()) {
Some("1") => true,
Some("0") => false,
_ => linux_desktop_supports_floating_frame(current_desktop),
}
}
/// The Linux config declares the main window with `create: false` so its transparency can
/// be explicitly opted into at runtime when a compositor is available.
/// depend at runtime on the desktop and on whether a compositor is available.
#[cfg(target_os = "linux")]
fn create_linux_main_window(app: &tauri::App) -> tauri::Result<()> {
let Some(config) = app.config().app.windows.iter().find(|window| window.label == "main").cloned() else {
return Ok(());
};
let compositing = linux_compositing_available();
let opt_in = std::env::var_os("DBX_LINUX_FLOATING_FRAME");
let floating_frame = should_enable_linux_floating_frame(compositing, opt_in.as_deref());
let override_value = std::env::var_os("DBX_LINUX_FLOATING_FRAME");
let current_desktop = std::env::var_os("XDG_CURRENT_DESKTOP");
let floating_frame =
should_enable_linux_floating_frame(compositing, override_value.as_deref(), current_desktop.as_deref());
log::info!("[WINDOW] Linux main window compositing={compositing}; floating_frame={floating_frame}");
let mut builder = tauri::WebviewWindowBuilder::from_config(app.handle(), &config)?.transparent(floating_frame);
if floating_frame {
@@ -1205,22 +1229,30 @@ mod tests {
}
#[test]
fn linux_floating_frame_is_disabled_by_default() {
assert!(!should_enable_linux_floating_frame(true, None));
assert!(!should_enable_linux_floating_frame(false, None));
fn linux_floating_frame_is_enabled_by_default_on_gnome_only() {
for desktop in ["GNOME", "ubuntu:GNOME", "gnome", "GNOME-Classic:GNOME"] {
assert!(should_enable_linux_floating_frame(true, None, Some(OsStr::new(desktop))), "{desktop}");
}
for desktop in ["KDE", "XFCE", "X-Cinnamon", "sway", "", "GNOMEISH"] {
assert!(!should_enable_linux_floating_frame(true, None, Some(OsStr::new(desktop))), "{desktop}");
}
assert!(!should_enable_linux_floating_frame(true, None, None));
}
#[test]
fn linux_floating_frame_requires_explicit_opt_in() {
assert!(should_enable_linux_floating_frame(true, Some(OsStr::new("1"))));
for value in ["", "0", "false", "true", "auto", "yes", "01"] {
assert!(!should_enable_linux_floating_frame(true, Some(OsStr::new(value))));
fn linux_floating_frame_override_wins_over_desktop() {
assert!(should_enable_linux_floating_frame(true, Some(OsStr::new("1")), Some(OsStr::new("KDE"))));
assert!(!should_enable_linux_floating_frame(true, Some(OsStr::new("0")), Some(OsStr::new("GNOME"))));
for value in ["", "true", "auto", "01"] {
assert!(should_enable_linux_floating_frame(true, Some(OsStr::new(value)), Some(OsStr::new("GNOME"))));
assert!(!should_enable_linux_floating_frame(true, Some(OsStr::new(value)), Some(OsStr::new("KDE"))));
}
}
#[test]
fn linux_floating_frame_requires_compositing_even_when_opted_in() {
assert!(!should_enable_linux_floating_frame(false, Some(OsStr::new("1"))));
fn linux_floating_frame_requires_compositing() {
assert!(!should_enable_linux_floating_frame(false, Some(OsStr::new("1")), Some(OsStr::new("GNOME"))));
assert!(!should_enable_linux_floating_frame(false, None, Some(OsStr::new("GNOME"))));
}
#[test]