15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 9a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/memory.h" 105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_gdi_object.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_hdc.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_select_object.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/host/client_session_control.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/host/host_window.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/win/core_resource.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace remoting { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int DISCONNECT_HOTKEY_ID = 1000; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum length of "Your desktop is shared with ..." message in UTF-16 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// characters. 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kMaxSharingWithTextLength = 100; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kShellTrayWindowName[] = L"Shell_TrayWnd"; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kWindowBorderRadius = 14; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Margin between dialog controls (in dialog units). 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst int kWindowTextMargin = 8; 347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DisconnectWindowWin : public HostWindow { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DisconnectWindowWin(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~DisconnectWindowWin(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // HostWindow overrides. 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void Start( 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::WeakPtr<ClientSessionControl>& client_session_control) 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OVERRIDE; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wparam, 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LPARAM lparam); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL OnDialogMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Creates the dialog window and registers the disconnect hot key. 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool BeginDialog(); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Closes the dialog, unregisters the hot key and invokes the disconnect 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // callback, if set. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void EndDialog(); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Returns |control| rectangle in the dialog coordinates. 597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool GetControlRect(HWND control, RECT* rect); 607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Trys to position the dialog window above the taskbar. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetDialogPosition(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Applies localization string and resizes the dialog. 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool SetStrings(); 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Used to disconnect the client session. 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WeakPtr<ClientSessionControl> client_session_control_; 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Specifies the remote user name. 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string username_; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND hwnd_; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_hotkey_; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedGDIObject<HPEN> border_pen_; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DisconnectWindowWin); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Returns the text for the given dialog control window. 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GetControlText(HWND control, base::string16* text) { 827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // GetWindowText truncates the text if it is longer than can fit into 837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // the buffer. 847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch WCHAR buffer[256]; 857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int result = GetWindowText(control, buffer, arraysize(buffer)); 867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!result) 877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch text->assign(buffer); 907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return true; 917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Returns width |text| rendered in |control| window. 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GetControlTextWidth(HWND control, 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& text, 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LONG* width) { 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RECT rect = {0, 0, 0, 0}; 987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::win::ScopedGetDC dc(control); 997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::win::ScopedSelectObject font( 1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch dc, (HFONT)SendMessage(control, WM_GETFONT, 0, 0)); 1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!DrawText(dc, text.c_str(), -1, &rect, DT_CALCRECT | DT_SINGLELINE)) 1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *width = rect.right; 1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return true; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DisconnectWindowWin::DisconnectWindowWin() 109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) : hwnd_(NULL), 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_hotkey_(false), 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) border_pen_(CreatePen(PS_SOLID, 5, 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RGB(0.13 * 255, 0.69 * 255, 0.11 * 255))) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DisconnectWindowWin::~DisconnectWindowWin() { 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EndDialog(); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DisconnectWindowWin::Start( 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::WeakPtr<ClientSessionControl>& client_session_control) { 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!client_session_control_); 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(client_session_control); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) client_session_control_ = client_session_control; 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string client_jid = client_session_control_->client_jid(); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) username_ = client_jid.substr(0, client_jid.find('/')); 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!BeginDialog()) 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EndDialog(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)INT_PTR CALLBACK DisconnectWindowWin::DialogProc(HWND hwnd, 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UINT message, 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WPARAM wparam, 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LPARAM lparam) { 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LONG_PTR self = NULL; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (message == WM_INITDIALOG) { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self = lparam; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Store |this| to the window's user data. 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetLastError(ERROR_SUCCESS); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LONG_PTR result = SetWindowLongPtr(hwnd, DWLP_USER, self); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result == 0 && GetLastError() != ERROR_SUCCESS) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<DisconnectWindowWin*>(self)->EndDialog(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self = GetWindowLongPtr(hwnd, DWLP_USER); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (self) { 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return reinterpret_cast<DisconnectWindowWin*>(self)->OnDialogMessage( 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hwnd, message, wparam, lparam); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)BOOL DisconnectWindowWin::OnDialogMessage(HWND hwnd, 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UINT message, 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WPARAM wparam, 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LPARAM lparam) { 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (message) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore close messages. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_CLOSE: 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle the Disconnect button. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_COMMAND: 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (LOWORD(wparam)) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDC_DISCONNECT: 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndDialog(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure we don't try to use the HWND anymore. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_DESTROY: 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hwnd_ = NULL; 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Ensure that the disconnect callback is invoked even if somehow our 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // window gets destroyed. 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EndDialog(); 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure the dialog stays visible if the work area dimensions change. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_SETTINGCHANGE: 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (wparam == SPI_SETWORKAREA) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetDialogPosition(); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure the dialog stays visible if the display dimensions change. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_DISPLAYCHANGE: 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetDialogPosition(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle the disconnect hot-key. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_HOTKEY: 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndDialog(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let the window be draggable by its client area by responding 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the entire window is the title bar. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_NCHITTEST: 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetWindowLongPtr(hwnd, DWLP_MSGRESULT, HTCAPTION); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_PAINT: { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PAINTSTRUCT ps; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HDC hdc = BeginPaint(hwnd_, &ps); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RECT rect; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetClientRect(hwnd_, &rect); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedSelectObject border(hdc, border_pen_); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedSelectObject brush(hdc, GetStockObject(NULL_BRUSH)); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RoundRect(hdc, rect.left, rect.top, rect.right - 1, rect.bottom - 1, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kWindowBorderRadius, kWindowBorderRadius); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndPaint(hwnd_, &ps); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DisconnectWindowWin::BeginDialog() { 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!hwnd_); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HMODULE module = base::GetModuleFromAddress(&DialogProc); 232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) hwnd_ = CreateDialogParam(module, MAKEINTRESOURCE(IDD_DISCONNECT), NULL, 233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DialogProc, reinterpret_cast<LPARAM>(this)); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!hwnd_) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set up handler for Ctrl-Alt-Esc shortcut. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_hotkey_ && RegisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOD_ALT | MOD_CONTROL, VK_ESCAPE)) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_hotkey_ = true; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!SetStrings()) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetDialogPosition(); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShowWindow(hwnd_, SW_SHOW); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return IsWindowVisible(hwnd_) != FALSE; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisconnectWindowWin::EndDialog() { 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (has_hotkey_) { 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UnregisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) has_hotkey_ = false; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (hwnd_) { 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DestroyWindow(hwnd_); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hwnd_ = NULL; 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (client_session_control_) 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) client_session_control_->DisconnectSession(); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Returns |control| rectangle in the dialog coordinates. 2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool DisconnectWindowWin::GetControlRect(HWND control, RECT* rect) { 2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!GetWindowRect(control, rect)) 2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SetLastError(ERROR_SUCCESS); 2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int result = MapWindowPoints(HWND_DESKTOP, hwnd_, 2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch reinterpret_cast<LPPOINT>(rect), 2); 2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!result && GetLastError() != ERROR_SUCCESS) 2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return true; 2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisconnectWindowWin::SetDialogPosition() { 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to center the window above the task-bar. If that fails, use the 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // primary monitor. If that fails (very unlikely), use the default position. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND taskbar = FindWindow(kShellTrayWindowName, NULL); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMONITOR monitor = MonitorFromWindow(taskbar, MONITOR_DEFAULTTOPRIMARY); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MONITORINFO monitor_info = {sizeof(monitor_info)}; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RECT window_rect; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetMonitorInfo(monitor, &monitor_info) && 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWindowRect(hwnd_, &window_rect)) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int window_width = window_rect.right - window_rect.left; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int window_height = window_rect.bottom - window_rect.top; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int top = monitor_info.rcWork.bottom - window_height; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int left = (monitor_info.rcWork.right + monitor_info.rcWork.left - 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_width) / 2; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowPos(hwnd_, NULL, left, top, 0, 0, SWP_NOSIZE | SWP_NOZORDER); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DisconnectWindowWin::SetStrings() { 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Localize the disconnect button text and measure length of the old and new 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // labels. 3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch HWND hwnd_button = GetDlgItem(hwnd_, IDC_DISCONNECT); 3077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch HWND hwnd_message = GetDlgItem(hwnd_, IDC_DISCONNECT_SHARINGWITH); 3087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!hwnd_button || !hwnd_message) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 button_text; 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 message_text; 3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!GetControlText(hwnd_button, &button_text) || 3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch !GetControlText(hwnd_message, &message_text)) { 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Format and truncate "Your desktop is shared with ..." message. 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_text = ReplaceStringPlaceholders(message_text, 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(username_), 3217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch NULL); 3227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (message_text.length() > kMaxSharingWithTextLength) 3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch message_text.erase(kMaxSharingWithTextLength); 3247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!SetWindowText(hwnd_message, message_text.c_str())) 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Calculate the margin between controls in pixels. 3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RECT rect = {0}; 3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch rect.right = kWindowTextMargin; 3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!MapDialogRect(hwnd_, &rect)) 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int margin = rect.right; 3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Resize |hwnd_message| so that the text is not clipped. 3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RECT message_rect; 3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!GetControlRect(hwnd_message, &message_rect)) 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch LONG control_width; 3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!GetControlTextWidth(hwnd_message, message_text, &control_width)) 3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch message_rect.right = message_rect.left + control_width + margin; 3447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!SetWindowPos(hwnd_message, NULL, 3467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch message_rect.left, message_rect.top, 3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch message_rect.right - message_rect.left, 3487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch message_rect.bottom - message_rect.top, 3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SWP_NOZORDER)) { 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Reposition and resize |hwnd_button| as well. 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RECT button_rect; 3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!GetControlRect(hwnd_button, &button_rect)) 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!GetControlTextWidth(hwnd_button, button_text, &control_width)) 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch button_rect.left = message_rect.right; 3627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch button_rect.right = button_rect.left + control_width + margin * 2; 3637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!SetWindowPos(hwnd_button, NULL, 3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch button_rect.left, button_rect.top, 3657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch button_rect.right - button_rect.left, 3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch button_rect.bottom - button_rect.top, 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SWP_NOZORDER)) { 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Resize the whole window to fit the resized controls. 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RECT window_rect; 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetWindowRect(hwnd_, &window_rect)) 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int width = button_rect.right + margin; 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int height = window_rect.bottom - window_rect.top; 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!SetWindowPos(hwnd_, NULL, 0, 0, width, height, 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SWP_NOMOVE | SWP_NOZORDER)) { 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make the corners of the disconnect window rounded. 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRGN rgn = CreateRoundRectRgn(0, 0, width, height, kWindowBorderRadius, 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kWindowBorderRadius); 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!rgn) 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!SetWindowRgn(hwnd_, rgn, TRUE)) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)scoped_ptr<HostWindow> HostWindow::CreateDisconnectWindow() { 397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return scoped_ptr<HostWindow>(new DisconnectWindowWin()); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 401