diff --git a/CHANGELOG.md b/CHANGELOG.md index bcfc7ba0..c0a4a868 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Changed + +- Yabridge now preemptively unsets the `WAYLAND_DISPLAY` environment variable + when launching Wine. Upstream Wine currently does not yet have a Wayland + driver, but future versions may. When that happens yabridge's X11 window + embedding would otherwise suddenly start breaking spectacularly. This change + makes sure that Wine will keep using X11 even if Wayland support becomes + available at some point. + ## [5.0.4] - 2023-02-23 ### Fixed diff --git a/src/common/process.cpp b/src/common/process.cpp index 5c84ed0c..7d028130 100644 --- a/src/common/process.cpp +++ b/src/common/process.cpp @@ -174,6 +174,13 @@ void ProcessEnvironment::insert(const std::string& key, variables_.push_back(key + "=" + value); } +size_t ProcessEnvironment::erase(const std::string& key) { + return std::erase_if(variables_, [&key](const std::string& variable) { + return variable.starts_with(key) && variable.size() > key.size() && + variable[key.size()] == '='; + }); +} + char* const* ProcessEnvironment::make_environ() const { recreated_environ_.clear(); diff --git a/src/common/process.h b/src/common/process.h index e74d0873..805f43b8 100644 --- a/src/common/process.h +++ b/src/common/process.h @@ -101,6 +101,14 @@ class ProcessEnvironment { */ void insert(const std::string& key, const std::string& value); + /** + * Remove an environment variable from the environment. Returns the number + * of elements erased (to stay consistent with the STL map interface). This + * can be higher than 1 if the map contains duplicate or overwritten + * environment variables. + */ + size_t erase(const std::string& key); + /** * Create an environ-like object from the updated environment that can be * passed to the `exec*e()` functions. These pointers will be invalidated diff --git a/src/plugin/utils.cpp b/src/plugin/utils.cpp index 8d6236ad..4a52b6c1 100644 --- a/src/plugin/utils.cpp +++ b/src/plugin/utils.cpp @@ -70,6 +70,14 @@ ProcessEnvironment PluginInfo::create_host_env() const { }, wine_prefix_); + // As of writing upstream Wine does not yet have a Wayland driver, but one + // is in the process of being merged. If this ever becomes enabled by + // default on distros, Wine could suddenly start using using Wayland instead + // of X11. This would break yabridge's embedding and drag-and-drop handling. + // So we'll preemptively avoid this by unsetting the `WAYLAND_DISPLAY` + // environment variable. + env.erase("WAYLAND_DISPLAY"); + return env; } diff --git a/src/plugin/utils.h b/src/plugin/utils.h index 9c85933b..53ecc1aa 100644 --- a/src/plugin/utils.h +++ b/src/plugin/utils.h @@ -79,6 +79,9 @@ struct PluginInfo { * `WINEPREFIX` was already set then nothing will be changed. Otherwise * we'll set `WINEPREFIX` to the detected Wine prefix, or it will be left * unset if we could not detect a prefix. + * + * This also unsets `WAYLAND_DISPLAY` so if Wine has been compiled with + * Wayland support, it won't suddenly start using that over X11. */ ProcessEnvironment create_host_env() const; diff --git a/tools/yabridgectl/src/util.rs b/tools/yabridgectl/src/util.rs index 83d04db2..1ea87cec 100644 --- a/tools/yabridgectl/src/util.rs +++ b/tools/yabridgectl/src/util.rs @@ -356,6 +356,10 @@ pub fn verify_wine_setup(config: &mut Config) -> Result<()> { let wine_binary = env::var("WINELOADER").unwrap_or_else(|_| String::from("wine")); let wine_version_output = Command::new(&wine_binary) .arg("--version") + // NOTE: This mimics the setup used in `PluginInfo::create_host_env()`. The X11 window + // embedding will break when future Wine versions start defaulting to a native Wayland + // driver, so we'll prevent that from happening. + .env_remove("WAYLAND_DISPLAY") .output() .with_context(|| { format!(