#include "ui/linux/display_server_utils.h"
#include <optional>
#include <string>
#include "base/command_line.h"
#include "base/environment.h"
#include "base/logging.h"
#include "ui/base/ozone_buildflags.h"
#include "ui/ozone/public/ozone_switches.h"
#if BUILDFLAG(IS_OZONE_WAYLAND)
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/nix/xdg_util.h"
#include "ui/base/ui_base_features.h"
#endif
namespace ui {
namespace {
#if BUILDFLAG(IS_OZONE_X11)
constexpr char kPlatformX11[] = "x11";
#endif
#if BUILDFLAG(IS_OZONE_WAYLAND)
constexpr char kPlatformWayland[] = "wayland";
bool InspectWaylandDisplay(base::Environment& env) {
std::optional<std::string> wayland_display = env.GetVar("WAYLAND_DISPLAY");
if (wayland_display.has_value()) {
return true;
}
std::optional<std::string> xdg_runtime_dir = env.GetVar("XDG_RUNTIME_DIR");
if (xdg_runtime_dir.has_value()) {
constexpr char kDefaultWaylandSocketName[] = "wayland-0";
const auto wayland_socket_path =
base::FilePath(*xdg_runtime_dir).Append(kDefaultWaylandSocketName);
if (base::PathExists(wayland_socket_path)) {
env.SetVar("WAYLAND_DISPLAY", kDefaultWaylandSocketName);
return true;
}
}
return false;
}
#endif
std::string MaybeFixPlatformName(const std::string& platform_hint) {
#if BUILDFLAG(IS_OZONE_WAYLAND)
if (platform_hint == kPlatformWayland || platform_hint == "auto") {
auto env = base::Environment::Create();
std::optional<std::string> xdg_session_type =
env->GetVar(base::nix::kXdgSessionTypeEnvVar);
if ((xdg_session_type.has_value() && *xdg_session_type == "wayland") ||
(platform_hint == kPlatformWayland && HasWaylandDisplay(*env))) {
return kPlatformWayland;
}
}
#endif
#if BUILDFLAG(IS_OZONE_X11)
if (platform_hint == kPlatformX11) {
return kPlatformX11;
}
#if BUILDFLAG(IS_OZONE_WAYLAND)
if (platform_hint == kPlatformWayland || platform_hint == "auto") {
if (platform_hint == kPlatformWayland) {
LOG(WARNING) << "No Wayland server is available. Falling back to X11.";
} else {
LOG(WARNING) << "This is not a Wayland session. Falling back to X11. "
"If you need to run Chrome on Wayland using some "
"embedded compositor, e.g. Weston, please specify "
"Wayland as your preferred Ozone platform, or use "
"--ozone-platform=wayland.";
}
return kPlatformX11;
}
#endif
#endif
return platform_hint;
}
void MaybeOverrideDefaultAsAuto(base::CommandLine& command_line) {
#if BUILDFLAG(IS_OZONE_WAYLAND)
const auto ozone_platform_hint =
command_line.GetSwitchValueASCII(switches::kOzonePlatformHint);
if (!ozone_platform_hint.empty() ||
!base::FeatureList::IsEnabled(
features::kOverrideDefaultOzonePlatformHintToAuto)) {
return;
}
command_line.AppendSwitchASCII(switches::kOzonePlatformHint, "auto");
#endif
}
}
void SetOzonePlatformForLinuxIfNeeded(base::CommandLine& command_line) {
if (!command_line.HasSwitch(switches::kOzonePlatform)) {
MaybeOverrideDefaultAsAuto(command_line);
const auto ozone_platform_hint =
command_line.GetSwitchValueASCII(switches::kOzonePlatformHint);
if (!ozone_platform_hint.empty()) {
command_line.AppendSwitchASCII(switches::kOzonePlatform,
MaybeFixPlatformName(ozone_platform_hint));
}
}
}
bool HasWaylandDisplay(base::Environment& env) {
#if !BUILDFLAG(IS_OZONE_WAYLAND)
return false;
#else
static bool has_wayland_display = InspectWaylandDisplay(env);
return has_wayland_display;
#endif
}
bool HasX11Display(base::Environment& env) {
#if !BUILDFLAG(IS_OZONE_X11)
return false;
#else
return env.GetVar("DISPLAY").has_value();
#endif
}
}