Chromium Code Reviews| 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..b22dcd88930a1b6d55147eeecbfa8891d62b570d 100644 |
| --- a/remoting/host/desktop_resizer_x11.cc |
| +++ b/remoting/host/desktop_resizer_x11.cc |
| @@ -136,6 +136,13 @@ class DesktopResizerX11 : public DesktopResizer { |
| void RestoreResolution(const ScreenResolution& original) override; |
| private: |
| + // Add a mode matching the specified resolution and switch to it. |
| + void SetResolutionExact(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 SetResolutionRandr(const ScreenResolution& resolution); |
|
rkjnsn
2016/05/20 22:08:40
Are these decent names for these functions?
Jamie
2016/05/20 23:56:19
Since they both use RANDR, maybe SetResolutionNewM
rkjnsn
2016/05/24 00:52:34
Done.
|
| + |
| // 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 +161,9 @@ class DesktopResizerX11 : public DesktopResizer { |
| Window root_; |
| ScreenResources resources_; |
| bool exact_resize_; |
| + int rr_event_base_; |
| + int rr_error_base_; |
|
rkjnsn
2016/05/20 22:08:39
We don't currently use either of these, so it migh
Jamie
2016/05/20 23:56:19
SGTM.
rkjnsn
2016/05/24 00:52:34
Done.
|
| + bool has_randr_; |
| DISALLOW_COPY_AND_ASSIGN(DesktopResizerX11); |
| }; |
| @@ -163,7 +173,11 @@ DesktopResizerX11::DesktopResizerX11() |
| screen_(DefaultScreen(display_)), |
| root_(RootWindow(display_, screen_)), |
| exact_resize_(base::CommandLine::ForCurrentProcess()-> |
| - HasSwitch("server-supports-exact-resize")) { |
| + HasSwitch("server-supports-exact-resize")), |
| + // TODO(rkjnsn): Do we need to handle the case where the display failed to |
| + // open? It doesn't look like we do, elsewhere. |
|
rkjnsn
2016/05/20 22:08:40
It appears we generally assume that XOpenDisplay s
Jamie
2016/05/20 23:56:19
If this is standard elsewhere, then it's okay to d
rkjnsn
2016/05/24 00:52:34
Done.
|
| + has_randr_(XRRQueryExtension(display_, &rr_event_base_, |
| + &rr_error_base_)) { |
| XRRSelectInput(display_, root_, RRScreenChangeNotifyMask); |
| } |
| @@ -172,12 +186,15 @@ DesktopResizerX11::~DesktopResizerX11() { |
| } |
| ScreenResolution DesktopResizerX11::GetCurrentResolution() { |
| - if (!exact_resize_) { |
| - // TODO(jamiewalch): Remove this early return if we decide to support |
| - // non-Xvfb servers. |
| + // TODO(rkjnsn): Don't DisplayWidth and DisplayHeight work even without RandR? |
| + // Would it make sense to return the size here, even when RandR isn't present? |
| + // (Obviously we'd want to skip the XRRUpdateConfiguration loop.) |
|
rkjnsn
2016/05/20 22:08:39
I think we could return something meaningful here
Jamie
2016/05/20 23:56:19
I'll defer to Lambros here, given his TODO
Lambros
2016/05/21 00:57:00
I can't remember why we return an invalid resoluti
rkjnsn
2016/05/24 00:52:34
Done.
|
| + if (!has_randr_) { |
| return ScreenResolution(); |
| } |
| + // TODO(rkjnsn): What's the todo, here? To investigate another approach? To |
| + // revisit if we ever get a central X event loop? |
| // 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 |
| @@ -197,6 +214,7 @@ ScreenResolution DesktopResizerX11::GetCurrentResolution() { |
| webrtc::DesktopSize( |
| DisplayWidth(display_, DefaultScreen(display_)), |
| DisplayHeight(display_, DefaultScreen(display_))), |
| + // TODO(rkjnsn): Do we want to calculate this from the screen dimensions? |
|
rkjnsn
2016/05/20 22:08:39
We seem to assume 96 DPI everywhere. Would it make
Jamie
2016/05/20 23:56:19
I wouldn't worry about it for now, unless it's a r
Sergey Ulanov
2016/05/22 20:00:17
This code is used only with Me2Me where we only su
rkjnsn
2016/05/24 00:52:34
Acknowledged.
|
| webrtc::DesktopVector(kDefaultDPI, kDefaultDPI)); |
| return result; |
| } |
| @@ -220,17 +238,29 @@ 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), |
| + // TODO(rkjnsn): Do we want to calculate this from the screen |
|
Lambros
2016/05/21 00:57:01
nit: Blank line before comment.
|
| + // dimensions? |
| + webrtc::DesktopVector(kDefaultDPI, kDefaultDPI))); |
| + } |
| + |
| + XRRFreeScreenConfigInfo(config); |
|
Jamie
2016/05/20 23:56:19
Use the ScreenResources class to manage the lifeti
Lambros
2016/05/21 00:57:00
I guess you'd need a separate scoper, with a dtor
rkjnsn
2016/05/24 00:52:34
I wouldn't be able to reuse ScreenResources for th
|
| + } |
| } |
| 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 +274,26 @@ void DesktopResizerX11::SetResolution(const ScreenResolution& resolution) { |
| // that the display configuration doesn't change under our feet. |
| ScopedXGrabServer grabber(display_); |
| + if (exact_resize_) { |
| + SetResolutionExact(resolution); |
| + } else { |
| + SetResolutionRandr(resolution); |
| + } |
| +} |
| + |
| +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. |
| + |
| + // TODO(rkjnsn): Previously we only changed the resolution while in curtain |
| + // mode with exact resize support Since we now pick the best resolution |
| + // wherever RandR is supported, presumably we want to actually do the restore |
| + // if and only if RandR is supported and we are not in curtain mode. |
|
Jamie
2016/05/20 23:56:19
Agreed; that makes sense.
rkjnsn
2016/05/24 00:52:34
Per our discussion, this now unconditionally calls
|
| +} |
| + |
| +void DesktopResizerX11::SetResolutionExact(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 +326,25 @@ 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::SetResolutionRandr(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, ¤t_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); |
|
Lambros
2016/05/21 00:57:00
If you do a custom scoper for XRRFreeScreenConfigI
|
| + } |
| } |
| void DesktopResizerX11::CreateMode(const char* name, int width, int height) { |