Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(425)

Unified Diff: remoting/host/desktop_resizer_x11.cc

Issue 2004613002: Add support for inexact resize on X11 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address further comments Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/desktop_resizer_x11.cc
diff --git a/remoting/host/desktop_resizer_x11.cc b/remoting/host/desktop_resizer_x11.cc
index e59fa2c10f104023600bfe51e82fd6097f9fb62f..90110fca0ba9429111dfe27eaaf11a5094ca643a 100644
--- a/remoting/host/desktop_resizer_x11.cc
+++ b/remoting/host/desktop_resizer_x11.cc
@@ -14,13 +14,12 @@
#include "remoting/base/logging.h"
#include "remoting/host/linux/x11_util.h"
-// On Linux, we use the xrandr extension to change the desktop resolution. For
-// now, we only support resize-to-client for Xvfb-based servers that can match
-// the client resolution exactly. To support best-resolution matching, it would
-// be necessary to implement |GetSupportedResolutions|, but it's not considered
-// a priority now.
+// On Linux, we use the xrandr extension to change the desktop resolution. In
+// curtain mode, we do exact resize where supported (currently only using a
+// patched Xvfb server). Otherwise, we try to pick the best resolution from the
+// existing modes.
//
-// Xrandr has a number of restrictions that make this code more complex:
+// Xrandr has a number of restrictions that make exact resize more complex:
//
// 1. It's not possible to change the resolution of an existing mode. Instead,
// the mode must be deleted and recreated.
@@ -136,6 +135,13 @@ class DesktopResizerX11 : public DesktopResizer {
void RestoreResolution(const ScreenResolution& original) override;
private:
+ // Add a mode matching the specified resolution and switch to it.
+ void SetResolutionNewMode(const ScreenResolution& resolution);
+
+ // Attempt to switch to an existing mode matching the specified resolution
+ // using RandR, if such a resolution exists. Otherwise, do nothing.
+ void SetResolutionExistingMode(const ScreenResolution& resolution);
+
// Create a mode, and attach it to the primary output. If the mode already
// exists, it is left unchanged.
void CreateMode(const char* name, int width, int height);
@@ -154,6 +160,7 @@ class DesktopResizerX11 : public DesktopResizer {
Window root_;
ScreenResources resources_;
bool exact_resize_;
+ bool has_randr_;
DISALLOW_COPY_AND_ASSIGN(DesktopResizerX11);
};
@@ -164,6 +171,11 @@ DesktopResizerX11::DesktopResizerX11()
root_(RootWindow(display_, screen_)),
exact_resize_(base::CommandLine::ForCurrentProcess()->
HasSwitch("server-supports-exact-resize")) {
+ int rr_event_base;
+ int rr_error_base;
+
+ has_randr_ = XRRQueryExtension(display_, &rr_event_base, &rr_error_base);
+
XRRSelectInput(display_, root_, RRScreenChangeNotifyMask);
}
@@ -172,31 +184,27 @@ DesktopResizerX11::~DesktopResizerX11() {
}
ScreenResolution DesktopResizerX11::GetCurrentResolution() {
- if (!exact_resize_) {
- // TODO(jamiewalch): Remove this early return if we decide to support
- // non-Xvfb servers.
- return ScreenResolution();
- }
-
- // TODO(lambroslambrou): 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.
+ // 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.
- while (XEventsQueued(display_, QueuedAlready)) {
- XEvent event;
- XNextEvent(display_, &event);
- XRRUpdateConfiguration(&event);
+ if (has_randr_) {
+ while (XEventsQueued(display_, QueuedAlready)) {
+ XEvent event;
+ XNextEvent(display_, &event);
+ XRRUpdateConfiguration(&event);
+ }
}
ScreenResolution result(
webrtc::DesktopSize(
- DisplayWidth(display_, DefaultScreen(display_)),
- DisplayHeight(display_, DefaultScreen(display_))),
+ DisplayWidth(display_, screen_),
+ DisplayHeight(display_, screen_)),
webrtc::DesktopVector(kDefaultDPI, kDefaultDPI));
return result;
}
@@ -220,17 +228,27 @@ std::list<ScreenResolution> DesktopResizerX11::GetSupportedResolutions(
webrtc::DesktopSize(std::max(640, width), std::max(480, height)),
webrtc::DesktopVector(kDefaultDPI, kDefaultDPI));
result.push_back(actual);
- } else {
- // TODO(jamiewalch): Return the list of supported resolutions if we can't
- // support exact-size matching.
+ } else if (has_randr_) {
+ // Retrieve supported resolutions with RandR
+ XRRScreenConfiguration *config = XRRGetScreenInfo(display_, root_);
+ if (config) {
+ int num_sizes = 0;
+ XRRScreenSize *sizes = XRRConfigSizes(config, &num_sizes);
+
+ for (int i = 0; i < num_sizes; ++i) {
+ result.push_back(ScreenResolution(
+ webrtc::DesktopSize(sizes[i].width, sizes[i].height),
+ webrtc::DesktopVector(kDefaultDPI, kDefaultDPI)));
+ }
+
+ XRRFreeScreenConfigInfo(config);
+ }
}
return result;
}
void DesktopResizerX11::SetResolution(const ScreenResolution& resolution) {
- if (!exact_resize_) {
- // TODO(jamiewalch): Remove this early return if we decide to support
- // non-Xvfb servers.
+ if (!has_randr_) {
return;
}
@@ -244,6 +262,19 @@ void DesktopResizerX11::SetResolution(const ScreenResolution& resolution) {
// that the display configuration doesn't change under our feet.
ScopedXGrabServer grabber(display_);
+ if (exact_resize_) {
+ SetResolutionNewMode(resolution);
+ } else {
+ SetResolutionExistingMode(resolution);
+ }
+}
+
+void DesktopResizerX11::RestoreResolution(const ScreenResolution& original) {
+ SetResolution(original);
+}
+
+void DesktopResizerX11::SetResolutionNewMode(
+ const ScreenResolution& resolution) {
// The name of the mode representing the current client view resolution and
// the temporary mode used for the reasons described at the top of this file.
// The former should be localized if it's user-visible; the latter only
@@ -276,11 +307,26 @@ void DesktopResizerX11::SetResolution(const ScreenResolution& resolution) {
DeleteMode(kTempModeName);
}
-void DesktopResizerX11::RestoreResolution(const ScreenResolution& original) {
- // Since the desktop is only visible via a remote connection, the original
- // resolution of the desktop will never been seen and there's no point
- // restoring it; if we did, we'd just risk messing up the user's window
- // layout.
+void DesktopResizerX11::SetResolutionExistingMode(
+ const ScreenResolution& resolution) {
+ XRRScreenConfiguration *config = XRRGetScreenInfo(display_, root_);
+ if (config) {
+ int num_sizes = 0;
+ XRRScreenSize *sizes = XRRConfigSizes(config, &num_sizes);
+ Rotation current_rotation = 0;
+ XRRConfigCurrentConfiguration(config, &current_rotation);
+
+ for (int i = 0; i < num_sizes; ++i) {
+ if (sizes[i].width == resolution.dimensions().width()
+ && sizes[i].height == resolution.dimensions().height()) {
+ XRRSetScreenConfig(display_, config, root_, i, current_rotation,
+ CurrentTime);
+ break;
+ }
+ }
+
+ XRRFreeScreenConfigInfo(config);
+ }
}
void DesktopResizerX11::CreateMode(const char* name, int width, int height) {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698