0

Add more robust XRandR environment checking in VirtualDisplayUtilLinux.

Removes base::nix::GetSessionType(...) in favor of connecting to X
server to check XRandR availability and output compatibility.

Bug: 40257169
Change-Id: I47008dcf3509614385be6d67ded61fee2cadc6f7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5646526
Reviewed-by: Ahmed Fakhry <afakhry@chromium.org>
Reviewed-by: Mike Wasserman <msw@chromium.org>
Commit-Queue: Brad Triebwasser <btriebw@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1319358}
This commit is contained in:
Brad Triebwasser
2024-06-25 20:12:48 +00:00
committed by Chromium LUCI CQ
parent 6e5d5e9bc4
commit dba244f23f
2 changed files with 37 additions and 7 deletions

@ -263,6 +263,7 @@ static_library("test_support") {
deps += [
"//remoting/host:display_layout",
"//remoting/host:x11_display_utils",
"//ui/gfx/x:x",
]
}

@ -18,6 +18,7 @@
#include "ui/display/types/display_constants.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/x/randr.h"
namespace {
@ -65,13 +66,41 @@ VirtualDisplayUtilLinux::~VirtualDisplayUtilLinux() {
// static
bool VirtualDisplayUtilLinux::IsAPIAvailable() {
// Wayland is currently unimplemented. Note that this detection uses
// XDG_SESSION_TYPE environment variable. When running in a pure SSH / virtual
// X server, it may be necessary to manually set XDG_SESSION_TYPE=x11 in the
// command.
static base::nix::SessionType session_type =
base::nix::GetSessionType(*base::Environment::Create());
return session_type == base::nix::SessionType::kX11;
// Check if XRandR is running with a sufficient number of connected outputs.
// Skip base::nix::GetSessionType(...), which may return kTty instead of kX11
// in SSH sessions with virtualized X11 environments.
constexpr auto kConnected = static_cast<x11::RandR::RandRConnection>(0);
constexpr auto kDisabled = static_cast<x11::RandR::Crtc>(0);
x11::Connection* x11_connection = x11::Connection::Get();
if (!x11_connection) {
LOG(ERROR) << "X11 is not present.";
return false;
}
x11::RandR& xrandr = x11_connection->randr();
if (!xrandr.present()) {
LOG(ERROR) << "XRandR is not present.";
return false;
}
x11::Response<x11::RandR::GetScreenResourcesCurrentReply> screen_resources =
xrandr.GetScreenResourcesCurrent({x11_connection->default_screen().root})
.Sync();
if (!screen_resources.reply) {
LOG(ERROR) << "GetScreenResourcesCurrent failed.";
return false;
}
int connected_and_disabled_outputs = 0;
for (const auto& output : screen_resources.reply->outputs) {
std::unique_ptr<x11::RandR::GetOutputInfoReply> output_reply =
xrandr.GetOutputInfo(output, screen_resources.reply->config_timestamp)
.Sync()
.reply;
if (output_reply && output_reply->connection == kConnected &&
output_reply->crtc == kDisabled) {
connected_and_disabled_outputs++;
}
}
return connected_and_disabled_outputs >= kMaxDisplays;
}
int64_t VirtualDisplayUtilLinux::AddDisplay(