Skip to content

Commit

Permalink
[XProto] Remove usage of XRRUpdateConfiguration and XRandR
Browse files Browse the repository at this point in the history
Since we never initialize the libxrandr (by calling XRRQueryVersion),
Xlib cannot decode the incoming randr notify events.  This causes a
crash in XRRUpdateConfiguration.

This CL solves the issue by removing all calls to
XRRUpdateConfiguration, which updates the XDisplay screen dimensions.
This data is only used in the following APIs:

XDisplayWidth
XDisplayHeight
XDisplayCells
XDisplayWidthMM
XDisplayHeightMM
XWidthOfScreen
XHeightOfScreen
XWidthMMOfScreen
XHeightMMOfScreen
DisplayWidth
DisplayHeight
DisplayCells
DisplayWidthMM
DisplayHeightMM
WidthOfScreen
HeightOfScreen
WidthMMOfScreen
HeightMMOfScreen

Therefore, this CL also adds a PRESUBMIT check to ensure they aren't
being used.

Since this is the last usage of libxrandr, the build config for it is
removed.

R=nickdiego,sky

Bug: 1102059
Change-Id: Ib60811259ae23ffa8af9c50e0bb3d4ac2158e5af
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2285068
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: Nick Yamane <nickdiego@igalia.com>
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Lambros Lambrou <lambroslambrou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#786148}
  • Loading branch information
tanderson-google authored and Commit Bot committed Jul 8, 2020
1 parent def0fa3 commit 74d064b
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 43 deletions.
8 changes: 8 additions & 0 deletions PRESUBMIT.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,14 @@
r"^ui[\\/]base[\\/]x[\\/]xwmstartupcheck[\\/]xwmstartupcheck\.cc$",
),
),
(
r'/\WX?(((Width|Height)(MM)?OfScreen)|(Display(Width|Height)))\(',
(
'Use the corresponding fields in x11::Screen instead.',
),
True,
(),
),
(
r'/XInternAtom|xcb_intern_atom',
(
Expand Down
4 changes: 0 additions & 4 deletions build/config/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ config("xext") {
libs = [ "Xext" ]
}

config("xrandr") {
libs = [ "Xrandr" ]
}

config("xfixes") {
libs = [ "Xfixes" ]
}
Expand Down
39 changes: 18 additions & 21 deletions remoting/host/desktop_resizer_x11.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ class ScreenResources {
std::unique_ptr<x11::RandR::GetScreenResourcesCurrentReply> resources_;
};

class DesktopResizerX11 : public DesktopResizer {
class DesktopResizerX11 : public DesktopResizer,
public x11::Connection::Delegate {
public:
DesktopResizerX11();
~DesktopResizerX11() override;
Expand All @@ -124,6 +125,10 @@ class DesktopResizerX11 : public DesktopResizer {
void RestoreResolution(const ScreenResolution& original) override;

private:
// x11::Connection::Delegate:
bool ShouldContinueStream() const override;
void DispatchXEvent(x11::Event* event) override;

// Add a mode matching the specified resolution and switch to it.
void SetResolutionNewMode(const ScreenResolution& resolution);

Expand Down Expand Up @@ -174,28 +179,14 @@ DesktopResizerX11::DesktopResizerX11()
DesktopResizerX11::~DesktopResizerX11() = default;

ScreenResolution DesktopResizerX11::GetCurrentResolution() {
// Xrandr requires that we process RRScreenChangeNotify events, otherwise
// DisplayWidth and DisplayHeight do not return the current values. Normally,
// this would be done via a central X event loop, but we don't have one, hence
// this horrible hack.
//
// Note that the WatchFileDescriptor approach taken in XServerClipboard
// doesn't work here because resize events have already been read from the
// X server socket by the time the resize function returns, hence the
// file descriptor is never seen as readable.
if (has_randr_) {
while (XEventsQueued(connection_.display(), QueuedAlready)) {
XEvent event;
XNextEvent(connection_.display(), &event);
XRRUpdateConfiguration(&event);
}
}
// Process pending events so that the connection setup data is updated
// with the correct display metrics.
if (has_randr_)
connection_.Dispatch(this);

ScreenResolution result(
webrtc::DesktopSize(DisplayWidth(connection_.display(),
DefaultScreen(connection_.display())),
DisplayHeight(connection_.display(),
DefaultScreen(connection_.display()))),
webrtc::DesktopSize(connection_.default_screen().width_in_pixels,
connection_.default_screen().height_in_pixels),
webrtc::DesktopVector(kDefaultDPI, kDefaultDPI));
return result;
}
Expand Down Expand Up @@ -257,6 +248,12 @@ void DesktopResizerX11::RestoreResolution(const ScreenResolution& original) {
SetResolution(original);
}

bool DesktopResizerX11::ShouldContinueStream() const {
return true;
}

void DesktopResizerX11::DispatchXEvent(x11::Event* event) {}

void DesktopResizerX11::SetResolutionNewMode(
const ScreenResolution& resolution) {
// The name of the mode representing the current client view resolution and
Expand Down
2 changes: 0 additions & 2 deletions ui/base/x/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ jumbo_component("x") {
]
}

public_configs = [ "//build/config/linux:xrandr" ]

defines = [ "IS_UI_BASE_X_IMPL" ]

deps = [
Expand Down
6 changes: 0 additions & 6 deletions ui/base/x/x11_display_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,6 @@ void XDisplayManager::RemoveObserver(display::DisplayObserver* observer) {

bool XDisplayManager::ProcessEvent(x11::Event* xev) {
DCHECK(xev);
if (xev->As<x11::RandR::ScreenChangeNotifyEvent>()) {
// TODO(https://crbug.com/1102059): Remove this since the Xlib even is
// nullptr since we don't initialize the extension, which causes a crash.
XRRUpdateConfiguration(&xev->xlib_event());
return true;
}
auto* prop = xev->As<x11::PropertyNotifyEvent>();
if (xev->As<x11::RandR::NotifyEvent>() ||
(prop && prop->atom == gfx::GetAtom("_NET_WORKAREA"))) {
Expand Down
15 changes: 6 additions & 9 deletions ui/base/x/x11_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1266,15 +1266,12 @@ bool IsX11WindowFullScreen(x11::Window window) {
if (!ui::GetOuterWindowBounds(window, &window_rect))
return false;

// We can't use display::Screen here because we don't have an aura::Window. So
// instead just look at the size of the default display.
//
// TODO(erg): Actually doing this correctly would require pulling out xrandr,
// which we don't even do in the desktop screen yet.
::XDisplay* display = gfx::GetXDisplay();
::Screen* screen = DefaultScreenOfDisplay(display);
int width = WidthOfScreen(screen);
int height = HeightOfScreen(screen);
// TODO(thomasanderson): We should use
// display::Screen::GetDisplayNearestWindow() instead of using the
// connection screen size, which encompasses all displays.
auto* connection = x11::Connection::Get();
int width = connection->default_screen().width_in_pixels;
int height = connection->default_screen().height_in_pixels;
return window_rect.size() == gfx::Size(width, height);
}

Expand Down
38 changes: 38 additions & 0 deletions ui/gfx/x/connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "base/memory/scoped_refptr.h"
#include "ui/gfx/x/bigreq.h"
#include "ui/gfx/x/event.h"
#include "ui/gfx/x/randr.h"
#include "ui/gfx/x/x11_switches.h"
#include "ui/gfx/x/xproto_internal.h"
#include "ui/gfx/x/xproto_types.h"
Expand Down Expand Up @@ -171,6 +172,7 @@ void Connection::Dispatch(Delegate* delegate) {

Event event = std::move(events_.front());
events_.pop_front();
PreDispatchEvent(event);
delegate->DispatchXEvent(&event);
};

Expand Down Expand Up @@ -213,4 +215,40 @@ void Connection::AddRequest(unsigned int sequence,
requests_.emplace(sequence, std::move(callback));
}

void Connection::PreDispatchEvent(const Event& event) {
// This is adapted from XRRUpdateConfiguration.
if (auto* configure = event.As<x11::ConfigureNotifyEvent>()) {
int index = ScreenIndexFromRootWindow(configure->window);
if (index != -1) {
setup_.roots[index].width_in_pixels = configure->width;
setup_.roots[index].height_in_pixels = configure->height;
}
} else if (auto* screen = event.As<x11::RandR::ScreenChangeNotifyEvent>()) {
int index = ScreenIndexFromRootWindow(configure->window);
DCHECK_GE(index, 0);
bool portrait = static_cast<bool>(
screen->rotation &
(x11::RandR::Rotation::Rotate_90 | x11::RandR::Rotation::Rotate_270));
if (portrait) {
setup_.roots[index].width_in_pixels = screen->height;
setup_.roots[index].height_in_pixels = screen->width;
setup_.roots[index].width_in_millimeters = screen->mheight;
setup_.roots[index].height_in_millimeters = screen->mwidth;
} else {
setup_.roots[index].width_in_pixels = screen->width;
setup_.roots[index].height_in_pixels = screen->height;
setup_.roots[index].width_in_millimeters = screen->mwidth;
setup_.roots[index].height_in_millimeters = screen->mheight;
}
}
}

int Connection::ScreenIndexFromRootWindow(x11::Window root) const {
for (size_t i = 0; i < setup_.roots.size(); i++) {
if (setup_.roots[i].root == root)
return i;
}
return -1;
}

} // namespace x11
4 changes: 4 additions & 0 deletions ui/gfx/x/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,

bool HasNextResponse() const;

void PreDispatchEvent(const Event& event);

int ScreenIndexFromRootWindow(x11::Window root) const;

XDisplay* const display_;

uint32_t extended_max_request_length_ = 0;
Expand Down
1 change: 0 additions & 1 deletion ui/gfx/x/x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ extern "C" {
#include <X11/extensions/XShm.h>
#include <X11/extensions/XTest.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/record.h>
#include <X11/extensions/sync.h>
Expand Down

0 comments on commit 74d064b

Please sign in to comment.