Index: remoting/host/win/rdp_client_window.cc |
diff --git a/remoting/host/win/rdp_client_window.cc b/remoting/host/win/rdp_client_window.cc |
index 47a50b30f92e66fc9ea7fc82ee70d079286b58e1..aab871de4248ce205c10eb16666276d01c7253c4 100644 |
--- a/remoting/host/win/rdp_client_window.cc |
+++ b/remoting/host/win/rdp_client_window.cc |
@@ -8,7 +8,9 @@ |
#include <list> |
+#include "base/bind.h" |
#include "base/lazy_instance.h" |
+#include "base/location.h" |
#include "base/logging.h" |
#include "base/macros.h" |
#include "base/strings/string16.h" |
@@ -36,6 +38,12 @@ constexpr BYTE kKeyPressedFlag = 0x80; |
constexpr int kKeyboardStateLength = 256; |
+constexpr base::TimeDelta kReapplyResolutionPeriod = |
+ base::TimeDelta::FromMilliseconds(250); |
+ |
+// We want to try to reapply resolution changes for ~5 seconds (20 * 250ms). |
+constexpr int kMaxResolutionReapplyAttempts = 20; |
+ |
// The RDP control creates 'IHWindowClass' window to handle keyboard input. |
constexpr wchar_t kRdpInputWindowClass[] = L"IHWindowClass"; |
@@ -215,8 +223,14 @@ void RdpClientWindow::InjectSas() { |
} |
void RdpClientWindow::ChangeResolution(const ScreenResolution& resolution) { |
+ // Stop any pending resolution changes. |
+ apply_resolution_timer_.Stop(); |
screen_resolution_ = resolution; |
- UpdateDesktopResolution(); |
+ HRESULT result = UpdateDesktopResolution(); |
+ if (FAILED(result)) { |
+ LOG(ERROR) << "UpdateSessionDisplaySettings() failed: 0x" << std::hex |
+ << result << std::dec; |
Sergey Ulanov
2016/12/27 21:16:13
I don't think you need std::dec here. Each LOG() c
joedow
2017/01/04 15:47:44
Done.
|
+ } |
} |
void RdpClientWindow::OnClose() { |
@@ -390,6 +404,7 @@ void RdpClientWindow::OnDestroy() { |
client_.Release(); |
client_9_.Release(); |
client_settings_.Release(); |
+ apply_resolution_timer_.Stop(); |
} |
HRESULT RdpClientWindow::OnAuthenticationWarningDisplayed() { |
@@ -421,8 +436,14 @@ HRESULT RdpClientWindow::OnLoginComplete() { |
user_logged_in_ = true; |
- // Apply pending screen size changes to the desktop. |
- UpdateDesktopResolution(); |
+ // Set up a timer to apply pending screen size changes to the desktop after a |
+ // brief timeout. Attempting to set the resolution now seems to fail |
+ // consistently, but succeeds after a brief timeout. |
+ if (client_9_) { |
+ apply_resolution_timer_.Start(FROM_HERE, |
+ kReapplyResolutionPeriod, |
+ base::Bind(&RdpClientWindow::ReapplyDesktopResolution, this, 0)); |
+ } |
return S_OK; |
} |
@@ -502,9 +523,9 @@ void RdpClientWindow::NotifyDisconnected() { |
} |
} |
-void RdpClientWindow::UpdateDesktopResolution() { |
+HRESULT RdpClientWindow::UpdateDesktopResolution() { |
if (!client_9_ || !user_logged_in_) { |
- return; |
+ return S_FALSE; |
} |
// UpdateSessionDisplaySettings() is poorly documented in MSDN and has a few |
@@ -512,8 +533,7 @@ void RdpClientWindow::UpdateDesktopResolution() { |
// 1.) This method will only work when the user is logged into their session. |
// 2.) The method may return E_UNEXPECTED until some amount of time (seconds) |
// have elapsed after logging in to the user's session. |
- // TODO(joedow): Investigate adding retry logic for applying the settings. |
- HRESULT result = client_9_->UpdateSessionDisplaySettings( |
+ return client_9_->UpdateSessionDisplaySettings( |
screen_resolution_.dimensions().width(), |
screen_resolution_.dimensions().height(), |
screen_resolution_.dimensions().width(), |
@@ -521,9 +541,27 @@ void RdpClientWindow::UpdateDesktopResolution() { |
/*ulOrientation=*/0, |
screen_resolution_.dpi().x(), |
screen_resolution_.dpi().y()); |
+} |
+ |
+void RdpClientWindow::ReapplyDesktopResolution(int attempt_count) { |
+ if (attempt_count > kMaxResolutionReapplyAttempts) { |
Sergey Ulanov
2016/12/27 21:16:13
Maybe just don't post the task after kMaxResolutio
joedow
2017/01/04 15:47:44
Done.
|
+ LOG(WARNING) << "Unable to apply desktop resolution changes."; |
+ return; |
+ } |
+ |
+ HRESULT result = UpdateDesktopResolution(); |
if (FAILED(result)) { |
- LOG(ERROR) << "UpdateSessionDisplaySettings() failed: 0x" << std::hex |
- << result << std::dec; |
+ // Only log errors on the last attempt to reduce log spam since a few errors |
+ // can be expected and don't signal an actual failure. |
+ if (attempt_count == kMaxResolutionReapplyAttempts) { |
+ LOG(ERROR) << "UpdateSessionDisplaySettings() failed: 0x" << std::hex |
+ << result << std::dec; |
+ } |
+ |
+ apply_resolution_timer_.Start(FROM_HERE, |
Sergey Ulanov
2016/12/27 21:16:13
It may be easier to start a repeating timer and th
joedow
2017/01/04 15:47:44
I think that's a good call. I've updated it to us
|
+ kReapplyResolutionPeriod, |
+ base::Bind(&RdpClientWindow::ReapplyDesktopResolution, this, |
+ attempt_count + 1)); |
} |
} |