| Index: remoting/host/disconnect_window_win.cc
|
| diff --git a/remoting/host/disconnect_window_win.cc b/remoting/host/disconnect_window_win.cc
|
| index abe739a34b8b7c6204959171d242babf90443542..e81ed6580504ceb28e19e34eeb217ebab794312f 100644
|
| --- a/remoting/host/disconnect_window_win.cc
|
| +++ b/remoting/host/disconnect_window_win.cc
|
| @@ -10,6 +10,9 @@
|
| #include "base/logging.h"
|
| #include "base/string_util.h"
|
| #include "base/utf_string_conversions.h"
|
| +#include "base/win/scoped_gdi_object.h"
|
| +#include "base/win/scoped_hdc.h"
|
| +#include "base/win/scoped_select_object.h"
|
| #include "remoting/host/chromoting_host.h"
|
| // TODO(wez): The DisconnectWindow isn't plugin-specific, so shouldn't have
|
| // a dependency on the plugin's resource header.
|
| @@ -28,6 +31,7 @@
|
| extern HMODULE g_hModule;
|
|
|
| const int DISCONNECT_HOTKEY_ID = 1000;
|
| +const int kWindowBorderRadius = 14;
|
|
|
| namespace remoting {
|
|
|
| @@ -53,6 +57,7 @@ private:
|
| remoting::ChromotingHost* host_;
|
| HWND hwnd_;
|
| bool has_hotkey_;
|
| + base::win::ScopedGDIObject<HPEN> border_pen_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(DisconnectWindowWin);
|
| };
|
| @@ -60,7 +65,9 @@ private:
|
| DisconnectWindowWin::DisconnectWindowWin()
|
| : host_(NULL),
|
| hwnd_(NULL),
|
| - has_hotkey_(false) {
|
| + has_hotkey_(false),
|
| + border_pen_(CreatePen(PS_SOLID, 5,
|
| + RGB(0.13 * 255, 0.69 * 255, 0.11 * 255))) {
|
| }
|
|
|
| DisconnectWindowWin::~DisconnectWindowWin() {
|
| @@ -86,17 +93,11 @@ BOOL CALLBACK DisconnectWindowWin::DialogProc(HWND hwnd, UINT msg,
|
| BOOL DisconnectWindowWin::OnDialogMessage(HWND hwnd, UINT msg,
|
| WPARAM wParam, LPARAM lParam) {
|
| switch (msg) {
|
| - case WM_HOTKEY:
|
| - ShutdownHost();
|
| - EndDialog(0);
|
| - return TRUE;
|
| + // Ignore close messages.
|
| case WM_CLOSE:
|
| - // Ignore close messages.
|
| - return TRUE;
|
| - case WM_DESTROY:
|
| - // Ensure we don't try to use the HWND anymore.
|
| - hwnd_ = NULL;
|
| return TRUE;
|
| +
|
| + // Handle the Disconnect button.
|
| case WM_COMMAND:
|
| switch (LOWORD(wParam)) {
|
| case IDC_DISCONNECT:
|
| @@ -104,21 +105,77 @@ BOOL DisconnectWindowWin::OnDialogMessage(HWND hwnd, UINT msg,
|
| EndDialog(LOWORD(wParam));
|
| return TRUE;
|
| }
|
| + return FALSE;
|
| +
|
| + // Ensure we don't try to use the HWND anymore.
|
| + case WM_DESTROY:
|
| + hwnd_ = NULL;
|
| + return TRUE;
|
| +
|
| + // Handle the disconnect hot-key.
|
| + case WM_HOTKEY:
|
| + ShutdownHost();
|
| + EndDialog(0);
|
| + return TRUE;
|
| +
|
| + // Let the window be draggable by its client area by responding
|
| + // that the entire window is the title bar.
|
| + case WM_NCHITTEST:
|
| + SetWindowLong(hwnd, DWL_MSGRESULT, HTCAPTION);
|
| + return TRUE;
|
| +
|
| + case WM_PAINT:
|
| + {
|
| + PAINTSTRUCT ps;
|
| + HDC hdc = BeginPaint(hwnd_, &ps);
|
| + RECT rect;
|
| + GetClientRect(hwnd_, &rect);
|
| + {
|
| + base::win::ScopedSelectObject border(hdc, border_pen_);
|
| + base::win::ScopedSelectObject brush(hdc, GetStockObject(NULL_BRUSH));
|
| + RoundRect(hdc, rect.left, rect.top, rect.right - 1, rect.bottom - 1,
|
| + kWindowBorderRadius, kWindowBorderRadius);
|
| + }
|
| + EndPaint(hwnd_, &ps);
|
| + return TRUE;
|
| + }
|
| }
|
| return FALSE;
|
| }
|
|
|
| void DisconnectWindowWin::Show(ChromotingHost* host,
|
| const std::string& username) {
|
| + CHECK(!hwnd_);
|
| host_ = host;
|
|
|
| - CHECK(!hwnd_);
|
| - hwnd_ = CreateDialogParam(g_hModule, MAKEINTRESOURCE(IDD_DISCONNECT), NULL,
|
| - (DLGPROC)DialogProc, (LPARAM)this);
|
| - if (!hwnd_) {
|
| - LOG(ERROR) << "Unable to create Disconnect dialog for remoting.";
|
| - return;
|
| - }
|
| + // Load the dialog resource so that we can modify the RTL flags if necessary.
|
| + // This is taken from chrome/default_plugin/install_dialog.cc
|
| + HRSRC dialog_resource =
|
| + FindResource(g_hModule, MAKEINTRESOURCE(IDD_DISCONNECT), RT_DIALOG);
|
| + CHECK(dialog_resource);
|
| + HGLOBAL dialog_template = LoadResource(g_hModule, dialog_resource);
|
| + CHECK(dialog_template);
|
| + DLGTEMPLATE* dialog_pointer =
|
| + reinterpret_cast<DLGTEMPLATE*>(LockResource(dialog_template));
|
| + CHECK(dialog_pointer);
|
| +
|
| + // The actual resource type is DLGTEMPLATEEX, but this is not defined in any
|
| + // standard headers, so we treat it as a generic pointer and manipulate the
|
| + // correct offsets explicitly.
|
| + scoped_ptr<unsigned char> rtl_dialog_template;
|
| + if (host->ui_strings().direction == UiStrings::RTL) {
|
| + unsigned long dialog_template_size =
|
| + SizeofResource(g_hModule, dialog_resource);
|
| + rtl_dialog_template.reset(new unsigned char[dialog_template_size]);
|
| + memcpy(rtl_dialog_template.get(), dialog_pointer, dialog_template_size);
|
| + DWORD* rtl_dwords = reinterpret_cast<DWORD*>(rtl_dialog_template.get());
|
| + rtl_dwords[2] |= (WS_EX_LAYOUTRTL | WS_EX_RTLREADING);
|
| + dialog_pointer = reinterpret_cast<DLGTEMPLATE*>(rtl_dwords);
|
| + }
|
| +
|
| + hwnd_ = CreateDialogIndirectParam(g_hModule, dialog_pointer, NULL,
|
| + (DLGPROC)DialogProc, (LPARAM)this);
|
| + CHECK(hwnd_);
|
|
|
| // Set up handler for Ctrl-Alt-Esc shortcut.
|
| if (!has_hotkey_ && RegisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID,
|
| @@ -135,8 +192,21 @@ void DisconnectWindowWin::ShutdownHost() {
|
| host_->Shutdown(NULL);
|
| }
|
|
|
| +static int GetControlTextWidth(HWND control) {
|
| + RECT rect = {0, 0, 0, 0};
|
| + WCHAR text[256];
|
| + int result = GetWindowText(control, text, arraysize(text));
|
| + if (result) {
|
| + base::win::ScopedGetDC dc(control);
|
| + base::win::ScopedSelectObject font(
|
| + dc, (HFONT)SendMessage(control, WM_GETFONT, 0, 0));
|
| + DrawText(dc, text, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
|
| + }
|
| + return rect.right;
|
| +}
|
| +
|
| void DisconnectWindowWin::SetStrings(const UiStrings& strings,
|
| - const std::string& username) {
|
| + const std::string& username) {
|
| SetWindowText(hwnd_, strings.product_name.c_str());
|
|
|
| HWND hwndButton = GetDlgItem(hwnd_, IDC_DISCONNECT);
|
| @@ -144,13 +214,49 @@ void DisconnectWindowWin::SetStrings(const UiStrings& strings,
|
| const WCHAR* label =
|
| has_hotkey_ ? strings.disconnect_button_text_plus_shortcut.c_str()
|
| : strings.disconnect_button_text.c_str();
|
| + int button_old_required_width = GetControlTextWidth(hwndButton);
|
| SetWindowText(hwndButton, label);
|
| + int button_new_required_width = GetControlTextWidth(hwndButton);
|
|
|
| HWND hwndSharingWith = GetDlgItem(hwnd_, IDC_DISCONNECT_SHARINGWITH);
|
| CHECK(hwndSharingWith);
|
| string16 text = ReplaceStringPlaceholders(
|
| strings.disconnect_message, UTF8ToUTF16(username), NULL);
|
| + int label_old_required_width = GetControlTextWidth(hwndSharingWith);
|
| SetWindowText(hwndSharingWith, text.c_str());
|
| + int label_new_required_width = GetControlTextWidth(hwndSharingWith);
|
| +
|
| + int label_width_delta = label_new_required_width - label_old_required_width;
|
| + int button_width_delta =
|
| + button_new_required_width - button_old_required_width;
|
| +
|
| + // Reposition the controls such that the label lies to the left of the
|
| + // disconnect button (assuming LTR layout). The dialog template determines
|
| + // the controls' spacing; update their size to fit the localized content.
|
| + RECT label_rect;
|
| + GetClientRect(hwndSharingWith, &label_rect);
|
| + SetWindowPos(hwndSharingWith, NULL, 0, 0,
|
| + label_rect.right + label_width_delta, label_rect.bottom,
|
| + SWP_NOMOVE|SWP_NOZORDER);
|
| +
|
| + RECT button_rect;
|
| + GetWindowRect(hwndButton, &button_rect);
|
| + int button_width = button_rect.right - button_rect.left;
|
| + int button_height = button_rect.bottom - button_rect.top;
|
| + MapWindowPoints(NULL, hwnd_, reinterpret_cast<LPPOINT>(&button_rect), 2);
|
| + SetWindowPos(hwndButton, NULL,
|
| + button_rect.left + label_width_delta, button_rect.top,
|
| + button_width + button_width_delta, button_height, SWP_NOZORDER);
|
| +
|
| + RECT window_rect;
|
| + GetWindowRect(hwnd_, &window_rect);
|
| + int width = (window_rect.right - window_rect.left) +
|
| + button_width_delta + label_width_delta;
|
| + int height = window_rect.bottom - window_rect.top;
|
| + SetWindowPos(hwnd_, NULL, 0, 0, width, height, SWP_NOMOVE|SWP_NOZORDER);
|
| + HRGN rgn = CreateRoundRectRgn(0, 0, width, height, kWindowBorderRadius,
|
| + kWindowBorderRadius);
|
| + SetWindowRgn(hwnd_, rgn, TRUE);
|
| }
|
|
|
| void DisconnectWindowWin::Hide() {
|
|
|