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..53cb776f887db6ad57c4f4721887b95b0b8cff67 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(WARNING) << "UpdateSessionDisplaySettings() failed: 0x" << std::hex |
+ << result; |
+ } |
} |
void RdpClientWindow::OnClose() { |
@@ -230,7 +244,7 @@ void RdpClientWindow::OnClose() { |
HRESULT result = client_->RequestClose(&close_status); |
if (FAILED(result)) { |
LOG(ERROR) << "Failed to request a graceful shutdown of an RDP connection" |
- << ", result=0x" << std::hex << result << std::dec; |
+ << ", result=0x" << std::hex << result; |
NotifyDisconnected(); |
return; |
} |
@@ -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,15 @@ HRESULT RdpClientWindow::OnLoginComplete() { |
user_logged_in_ = true; |
- // Apply pending screen size changes to the desktop. |
- UpdateDesktopResolution(); |
+ // Set up a timer to periodically apply pending screen size changes to the |
+ // desktop. Attempting to set the resolution now seems to fail consistently, |
+ // but succeeds after a brief timeout. |
+ if (client_9_) { |
+ apply_resolution_attempts_ = 0; |
+ apply_resolution_timer_.Start( |
+ FROM_HERE, kReapplyResolutionPeriod, |
+ base::Bind(&RdpClientWindow::ReapplyDesktopResolution, this)); |
+ } |
return S_OK; |
} |
@@ -480,8 +502,7 @@ HRESULT RdpClientWindow::OnConfirmClose(VARIANT_BOOL* allow_close) { |
int RdpClientWindow::LogOnCreateError(HRESULT error) { |
LOG(ERROR) << "RDP: failed to initiate a connection to " |
- << server_endpoint_.ToString() << ": error=" |
- << std::hex << error << std::dec; |
+ << server_endpoint_.ToString() << ": error=" << std::hex << error; |
client_.Release(); |
client_9_.Release(); |
client_settings_.Release(); |
@@ -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,23 @@ void RdpClientWindow::UpdateDesktopResolution() { |
/*ulOrientation=*/0, |
screen_resolution_.dpi().x(), |
screen_resolution_.dpi().y()); |
- if (FAILED(result)) { |
- LOG(ERROR) << "UpdateSessionDisplaySettings() failed: 0x" << std::hex |
- << result << std::dec; |
+} |
+ |
+void RdpClientWindow::ReapplyDesktopResolution() { |
+ DCHECK_LT(apply_resolution_attempts_, kMaxResolutionReapplyAttempts); |
+ |
+ HRESULT result = UpdateDesktopResolution(); |
+ apply_resolution_attempts_++; |
+ |
+ if (SUCCEEDED(result)) { |
+ // Successfully applied the new resolution so stop the retry timer. |
+ apply_resolution_timer_.Stop(); |
+ } else if (apply_resolution_attempts_ == kMaxResolutionReapplyAttempts) { |
+ // Only log an error on the last attempt to reduce log spam since a few |
+ // errors can be expected and don't signal an actual failure. |
+ LOG(WARNING) << "All UpdateSessionDisplaySettings() retries failed: 0x" |
+ << std::hex << result; |
+ apply_resolution_timer_.Stop(); |
} |
} |
@@ -576,7 +610,7 @@ LRESULT CALLBACK RdpClientWindow::WindowHook::CloseWindowOnActivation( |
// Close the window once all pending window messages are processed. |
HWND window = reinterpret_cast<HWND>(wparam); |
- LOG(WARNING) << "RDP: closing a window: " << std::hex << window << std::dec; |
+ LOG(WARNING) << "RDP: closing a window: " << std::hex << window; |
::PostMessage(window, WM_CLOSE, 0, 0); |
return 0; |
} |