diff --git a/Cargo.lock b/Cargo.lock index bc91e9f..2a28b31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1599,6 +1599,7 @@ dependencies = [ "clap-verbosity-flag", "dns-lookup", "env_logger", + "gtk", "log", "log-reload", "md5", diff --git a/crates/gpapi/Cargo.toml b/crates/gpapi/Cargo.toml index c82ce00..6fb217d 100644 --- a/crates/gpapi/Cargo.toml +++ b/crates/gpapi/Cargo.toml @@ -39,6 +39,9 @@ clap-verbosity-flag = { workspace = true, optional = true } env_logger = { workspace = true, optional = true } log-reload = { version = "0.1", optional = true } +[target.'cfg(not(any(target_os="macos", target_os="windows")))'.dependencies] +gtk = "0.18" + [features] tauri = ["dep:tauri"] clap = ["dep:clap", "dep:clap-verbosity-flag"] diff --git a/crates/gpapi/src/utils/env_utils.rs b/crates/gpapi/src/utils/env_utils.rs index 11ce633..a056e03 100644 --- a/crates/gpapi/src/utils/env_utils.rs +++ b/crates/gpapi/src/utils/env_utils.rs @@ -41,12 +41,6 @@ pub fn patch_gui_runtime_env(hidpi: bool) { // This is to avoid blank screen on some systems std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1"); - // Workaround for https://github.com/tauri-apps/tao/issues/929 - let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland"; - if is_wayland { - env::set_var("GDK_BACKEND", "x11"); - } - if hidpi { info!("Setting GDK_SCALE=2 and GDK_DPI_SCALE=0.5"); std::env::set_var("GDK_SCALE", "2"); diff --git a/crates/gpapi/src/utils/window.rs b/crates/gpapi/src/utils/window.rs index b0b3ac3..36246ab 100644 --- a/crates/gpapi/src/utils/window.rs +++ b/crates/gpapi/src/utils/window.rs @@ -1,73 +1,97 @@ -use std::{process::ExitStatus, time::Duration}; - -use anyhow::bail; -use log::info; use tauri::WebviewWindow; -use tokio::process::Command; pub trait WindowExt { fn raise(&self) -> anyhow::Result<()>; } impl WindowExt for WebviewWindow { + #[cfg(any(target_os = "macos", target_os = "windows"))] fn raise(&self) -> anyhow::Result<()> { - raise_window(self) + self.show()?; + Ok(()) + } + + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + fn raise(&self) -> anyhow::Result<()> { + unix::raise_window(self) } } -pub fn raise_window(win: &WebviewWindow) -> anyhow::Result<()> { - let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland"; +#[cfg(not(any(target_os = "macos", target_os = "windows")))] +mod unix { + use std::{process::ExitStatus, time::Duration}; - if is_wayland { - win.hide()?; - win.show()?; - } else { - if !win.is_visible()? { - win.show()?; - } - let title = win.title()?; - tokio::spawn(async move { - if let Err(err) = wmctrl_raise_window(&title).await { - info!("Window not raised: {}", err); + use anyhow::bail; + use gtk::{ + glib::Cast, + traits::{EventBoxExt, GtkWindowExt, WidgetExt}, + EventBox, + }; + use log::info; + use tauri::WebviewWindow; + use tokio::process::Command; + + pub fn raise_window(win: &WebviewWindow) -> anyhow::Result<()> { + let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland"; + + if is_wayland { + let gtk_win = win.gtk_window()?; + if let Some(header) = gtk_win.titlebar() { + let _ = header.downcast::().map(|event_box| { + event_box.set_above_child(false); + }); } - }); - } - // Calling window.show() on Windows will cause the menu to be shown. - // We need to hide it again. - win.hide_menu()?; - - Ok(()) -} - -async fn wmctrl_raise_window(title: &str) -> anyhow::Result<()> { - let mut counter = 0; - - loop { - if let Ok(exit_status) = wmctrl_try_raise_window(title).await { - if exit_status.success() { - info!("Window raised after {} attempts", counter + 1); - return Ok(()); + gtk_win.hide(); + gtk_win.show_all(); + } else { + if !win.is_visible()? { + win.show()?; } + let title = win.title()?; + tokio::spawn(async move { + if let Err(err) = wmctrl_raise_window(&title).await { + info!("Window not raised: {}", err); + } + }); } - if counter >= 10 { - bail!("Failed to raise window: {}", title) - } + // Calling window.show() on window object will cause the menu to be shown. + // We need to hide it again. + win.hide_menu()?; - counter += 1; - tokio::time::sleep(Duration::from_millis(100)).await; + Ok(()) + } + + async fn wmctrl_raise_window(title: &str) -> anyhow::Result<()> { + let mut counter = 0; + + loop { + if let Ok(exit_status) = wmctrl_try_raise_window(title).await { + if exit_status.success() { + info!("Window raised after {} attempts", counter + 1); + return Ok(()); + } + } + + if counter >= 10 { + bail!("Failed to raise window: {}", title) + } + + counter += 1; + tokio::time::sleep(Duration::from_millis(100)).await; + } + } + + async fn wmctrl_try_raise_window(title: &str) -> anyhow::Result { + let exit_status = Command::new("wmctrl") + .arg("-F") + .arg("-a") + .arg(title) + .spawn()? + .wait() + .await?; + + Ok(exit_status) } } - -async fn wmctrl_try_raise_window(title: &str) -> anyhow::Result { - let exit_status = Command::new("wmctrl") - .arg("-F") - .arg("-a") - .arg(title) - .spawn()? - .wait() - .await?; - - Ok(exit_status) -}