Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: remoting/host/disconnect_window_win.cc

Issue 8356032: Initial prototype minus drop-shadow. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | remoting/host/plugin/host_plugin.rc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/disconnect_window.h" 5 #include "remoting/host/disconnect_window.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "base/win/scoped_gdi_object.h"
14 #include "base/win/scoped_hdc.h"
15 #include "base/win/scoped_select_object.h"
13 #include "remoting/host/chromoting_host.h" 16 #include "remoting/host/chromoting_host.h"
14 // TODO(wez): The DisconnectWindow isn't plugin-specific, so shouldn't have 17 // TODO(wez): The DisconnectWindow isn't plugin-specific, so shouldn't have
15 // a dependency on the plugin's resource header. 18 // a dependency on the plugin's resource header.
16 #include "remoting/host/plugin/host_plugin_resource.h" 19 #include "remoting/host/plugin/host_plugin_resource.h"
17 #include "remoting/host/ui_strings.h" 20 #include "remoting/host/ui_strings.h"
18 21
19 // TODO(garykac): Lots of duplicated code in this file and 22 // TODO(garykac): Lots of duplicated code in this file and
20 // continue_window_win.cc. These global floating windows are temporary so 23 // continue_window_win.cc. These global floating windows are temporary so
21 // they should be deleted soon. If we need to expand this then we should 24 // they should be deleted soon. If we need to expand this then we should
22 // create a class with the shared code. 25 // create a class with the shared code.
23 26
24 // HMODULE from DllMain/WinMain. This is needed to find our dialog resource. 27 // HMODULE from DllMain/WinMain. This is needed to find our dialog resource.
25 // This is defined in: 28 // This is defined in:
26 // Plugin: host_plugin.cc 29 // Plugin: host_plugin.cc
27 // SimpleHost: simple_host_process.cc 30 // SimpleHost: simple_host_process.cc
28 extern HMODULE g_hModule; 31 extern HMODULE g_hModule;
29 32
30 const int DISCONNECT_HOTKEY_ID = 1000; 33 const int DISCONNECT_HOTKEY_ID = 1000;
34 const int kWindowBorderRadius = 14;
31 35
32 namespace remoting { 36 namespace remoting {
33 37
34 class DisconnectWindowWin : public DisconnectWindow { 38 class DisconnectWindowWin : public DisconnectWindow {
35 public: 39 public:
36 DisconnectWindowWin(); 40 DisconnectWindowWin();
37 virtual ~DisconnectWindowWin(); 41 virtual ~DisconnectWindowWin();
38 42
39 virtual void Show(remoting::ChromotingHost* host, 43 virtual void Show(remoting::ChromotingHost* host,
40 const std::string& username) OVERRIDE; 44 const std::string& username) OVERRIDE;
41 virtual void Hide() OVERRIDE; 45 virtual void Hide() OVERRIDE;
42 46
43 private: 47 private:
44 static BOOL CALLBACK DialogProc(HWND hwmd, UINT msg, WPARAM wParam, 48 static BOOL CALLBACK DialogProc(HWND hwmd, UINT msg, WPARAM wParam,
45 LPARAM lParam); 49 LPARAM lParam);
46 50
47 BOOL OnDialogMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 51 BOOL OnDialogMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
48 52
49 void ShutdownHost(); 53 void ShutdownHost();
50 void EndDialog(int result); 54 void EndDialog(int result);
51 void SetStrings(const UiStrings& strings, const std::string& username); 55 void SetStrings(const UiStrings& strings, const std::string& username);
52 56
53 remoting::ChromotingHost* host_; 57 remoting::ChromotingHost* host_;
54 HWND hwnd_; 58 HWND hwnd_;
55 bool has_hotkey_; 59 bool has_hotkey_;
60 base::win::ScopedGDIObject<HPEN> border_pen_;
56 61
57 DISALLOW_COPY_AND_ASSIGN(DisconnectWindowWin); 62 DISALLOW_COPY_AND_ASSIGN(DisconnectWindowWin);
58 }; 63 };
59 64
60 DisconnectWindowWin::DisconnectWindowWin() 65 DisconnectWindowWin::DisconnectWindowWin()
61 : host_(NULL), 66 : host_(NULL),
62 hwnd_(NULL), 67 hwnd_(NULL),
63 has_hotkey_(false) { 68 has_hotkey_(false),
69 border_pen_(CreatePen(PS_SOLID, 5,
70 RGB(0.13 * 255, 0.69 * 255, 0.11 * 255))) {
64 } 71 }
65 72
66 DisconnectWindowWin::~DisconnectWindowWin() { 73 DisconnectWindowWin::~DisconnectWindowWin() {
67 EndDialog(0); 74 EndDialog(0);
68 } 75 }
69 76
70 BOOL CALLBACK DisconnectWindowWin::DialogProc(HWND hwnd, UINT msg, 77 BOOL CALLBACK DisconnectWindowWin::DialogProc(HWND hwnd, UINT msg,
71 WPARAM wParam, LPARAM lParam) { 78 WPARAM wParam, LPARAM lParam) {
72 DisconnectWindowWin* win = NULL; 79 DisconnectWindowWin* win = NULL;
73 if (msg == WM_INITDIALOG) { 80 if (msg == WM_INITDIALOG) {
74 win = reinterpret_cast<DisconnectWindowWin*>(lParam); 81 win = reinterpret_cast<DisconnectWindowWin*>(lParam);
75 CHECK(win); 82 CHECK(win);
76 SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)win); 83 SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)win);
77 } else { 84 } else {
78 LONG_PTR lp = GetWindowLongPtr(hwnd, DWLP_USER); 85 LONG_PTR lp = GetWindowLongPtr(hwnd, DWLP_USER);
79 win = reinterpret_cast<DisconnectWindowWin*>(lp); 86 win = reinterpret_cast<DisconnectWindowWin*>(lp);
80 } 87 }
81 if (win == NULL) 88 if (win == NULL)
82 return FALSE; 89 return FALSE;
83 return win->OnDialogMessage(hwnd, msg, wParam, lParam); 90 return win->OnDialogMessage(hwnd, msg, wParam, lParam);
84 } 91 }
85 92
86 BOOL DisconnectWindowWin::OnDialogMessage(HWND hwnd, UINT msg, 93 BOOL DisconnectWindowWin::OnDialogMessage(HWND hwnd, UINT msg,
87 WPARAM wParam, LPARAM lParam) { 94 WPARAM wParam, LPARAM lParam) {
88 switch (msg) { 95 switch (msg) {
89 case WM_HOTKEY: 96 // Ignore close messages.
90 ShutdownHost(); 97 case WM_CLOSE:
91 EndDialog(0);
92 return TRUE; 98 return TRUE;
93 case WM_CLOSE: 99
94 // Ignore close messages. 100 // Handle the Disconnect button.
95 return TRUE;
96 case WM_DESTROY:
97 // Ensure we don't try to use the HWND anymore.
98 hwnd_ = NULL;
99 return TRUE;
100 case WM_COMMAND: 101 case WM_COMMAND:
101 switch (LOWORD(wParam)) { 102 switch (LOWORD(wParam)) {
102 case IDC_DISCONNECT: 103 case IDC_DISCONNECT:
103 ShutdownHost(); 104 ShutdownHost();
104 EndDialog(LOWORD(wParam)); 105 EndDialog(LOWORD(wParam));
105 return TRUE; 106 return TRUE;
106 } 107 }
108 return FALSE;
109
110 // Ensure we don't try to use the HWND anymore.
111 case WM_DESTROY:
112 hwnd_ = NULL;
113 return TRUE;
114
115 // Handle the disconnect hot-key.
116 case WM_HOTKEY:
117 ShutdownHost();
118 EndDialog(0);
119 return TRUE;
120
121 // Let the window be draggable by its client area by responding
122 // that the entire window is the title bar.
123 case WM_NCHITTEST:
124 SetWindowLong(hwnd, DWL_MSGRESULT, HTCAPTION);
125 return TRUE;
126
127 case WM_PAINT:
128 {
129 PAINTSTRUCT ps;
130 HDC hdc = BeginPaint(hwnd_, &ps);
131 RECT rect;
132 GetClientRect(hwnd_, &rect);
133 {
134 base::win::ScopedSelectObject border(hdc, border_pen_);
135 base::win::ScopedSelectObject brush(hdc, GetStockObject(NULL_BRUSH));
136 RoundRect(hdc, rect.left, rect.top, rect.right - 1, rect.bottom - 1,
137 kWindowBorderRadius, kWindowBorderRadius);
138 }
139 EndPaint(hwnd_, &ps);
140 return TRUE;
141 }
107 } 142 }
108 return FALSE; 143 return FALSE;
109 } 144 }
110 145
111 void DisconnectWindowWin::Show(ChromotingHost* host, 146 void DisconnectWindowWin::Show(ChromotingHost* host,
112 const std::string& username) { 147 const std::string& username) {
148 CHECK(!hwnd_);
113 host_ = host; 149 host_ = host;
114 150
115 CHECK(!hwnd_); 151 // Load the dialog resource so that we can modify the RTL flags if necessary.
116 hwnd_ = CreateDialogParam(g_hModule, MAKEINTRESOURCE(IDD_DISCONNECT), NULL, 152 // This is taken from chrome/default_plugin/install_dialog.cc
117 (DLGPROC)DialogProc, (LPARAM)this); 153 HRSRC dialog_resource =
118 if (!hwnd_) { 154 FindResource(g_hModule, MAKEINTRESOURCE(IDD_DISCONNECT), RT_DIALOG);
119 LOG(ERROR) << "Unable to create Disconnect dialog for remoting."; 155 CHECK(dialog_resource);
120 return; 156 HGLOBAL dialog_template = LoadResource(g_hModule, dialog_resource);
157 CHECK(dialog_template);
158 DLGTEMPLATE* dialog_pointer =
159 reinterpret_cast<DLGTEMPLATE*>(LockResource(dialog_template));
160 CHECK(dialog_pointer);
161
162 // The actual resource type is DLGTEMPLATEEX, but this is not defined in any
163 // standard headers, so we treat it as a generic pointer and manipulate the
164 // correct offsets explicitly.
165 scoped_ptr<unsigned char> rtl_dialog_template;
166 if (host->ui_strings().direction == UiStrings::RTL) {
167 unsigned long dialog_template_size =
168 SizeofResource(g_hModule, dialog_resource);
169 rtl_dialog_template.reset(new unsigned char[dialog_template_size]);
170 memcpy(rtl_dialog_template.get(), dialog_pointer, dialog_template_size);
171 DWORD* rtl_dwords = reinterpret_cast<DWORD*>(rtl_dialog_template.get());
172 rtl_dwords[2] |= (WS_EX_LAYOUTRTL | WS_EX_RTLREADING);
173 dialog_pointer = reinterpret_cast<DLGTEMPLATE*>(rtl_dwords);
121 } 174 }
122 175
176 hwnd_ = CreateDialogIndirectParam(g_hModule, dialog_pointer, NULL,
177 (DLGPROC)DialogProc, (LPARAM)this);
178 CHECK(hwnd_);
179
123 // Set up handler for Ctrl-Alt-Esc shortcut. 180 // Set up handler for Ctrl-Alt-Esc shortcut.
124 if (!has_hotkey_ && RegisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID, 181 if (!has_hotkey_ && RegisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID,
125 MOD_ALT | MOD_CONTROL, VK_ESCAPE)) { 182 MOD_ALT | MOD_CONTROL, VK_ESCAPE)) {
126 has_hotkey_ = true; 183 has_hotkey_ = true;
127 } 184 }
128 185
129 SetStrings(host->ui_strings(), username); 186 SetStrings(host->ui_strings(), username);
130 ShowWindow(hwnd_, SW_SHOW); 187 ShowWindow(hwnd_, SW_SHOW);
131 } 188 }
132 189
133 void DisconnectWindowWin::ShutdownHost() { 190 void DisconnectWindowWin::ShutdownHost() {
134 CHECK(host_); 191 CHECK(host_);
135 host_->Shutdown(NULL); 192 host_->Shutdown(NULL);
136 } 193 }
137 194
195 static int GetControlTextWidth(HWND control) {
196 RECT rect = {0, 0, 0, 0};
197 WCHAR text[256];
198 int result = GetWindowText(control, text, arraysize(text));
199 if (result) {
200 base::win::ScopedGetDC dc(control);
201 base::win::ScopedSelectObject font(
202 dc, (HFONT)SendMessage(control, WM_GETFONT, 0, 0));
203 DrawText(dc, text, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
204 }
205 return rect.right;
206 }
207
138 void DisconnectWindowWin::SetStrings(const UiStrings& strings, 208 void DisconnectWindowWin::SetStrings(const UiStrings& strings,
139 const std::string& username) { 209 const std::string& username) {
140 SetWindowText(hwnd_, strings.product_name.c_str()); 210 SetWindowText(hwnd_, strings.product_name.c_str());
141 211
142 HWND hwndButton = GetDlgItem(hwnd_, IDC_DISCONNECT); 212 HWND hwndButton = GetDlgItem(hwnd_, IDC_DISCONNECT);
143 CHECK(hwndButton); 213 CHECK(hwndButton);
144 const WCHAR* label = 214 const WCHAR* label =
145 has_hotkey_ ? strings.disconnect_button_text_plus_shortcut.c_str() 215 has_hotkey_ ? strings.disconnect_button_text_plus_shortcut.c_str()
146 : strings.disconnect_button_text.c_str(); 216 : strings.disconnect_button_text.c_str();
217 int button_old_required_width = GetControlTextWidth(hwndButton);
147 SetWindowText(hwndButton, label); 218 SetWindowText(hwndButton, label);
219 int button_new_required_width = GetControlTextWidth(hwndButton);
148 220
149 HWND hwndSharingWith = GetDlgItem(hwnd_, IDC_DISCONNECT_SHARINGWITH); 221 HWND hwndSharingWith = GetDlgItem(hwnd_, IDC_DISCONNECT_SHARINGWITH);
150 CHECK(hwndSharingWith); 222 CHECK(hwndSharingWith);
151 string16 text = ReplaceStringPlaceholders( 223 string16 text = ReplaceStringPlaceholders(
152 strings.disconnect_message, UTF8ToUTF16(username), NULL); 224 strings.disconnect_message, UTF8ToUTF16(username), NULL);
225 int label_old_required_width = GetControlTextWidth(hwndSharingWith);
153 SetWindowText(hwndSharingWith, text.c_str()); 226 SetWindowText(hwndSharingWith, text.c_str());
227 int label_new_required_width = GetControlTextWidth(hwndSharingWith);
228
229 int label_width_delta = label_new_required_width - label_old_required_width;
230 int button_width_delta =
231 button_new_required_width - button_old_required_width;
232
233 // Reposition the controls such that the label lies to the left of the
234 // disconnect button (assuming LTR layout). The dialog template determines
235 // the controls' spacing; update their size to fit the localized content.
236 RECT label_rect;
237 GetClientRect(hwndSharingWith, &label_rect);
238 SetWindowPos(hwndSharingWith, NULL, 0, 0,
239 label_rect.right + label_width_delta, label_rect.bottom,
240 SWP_NOMOVE|SWP_NOZORDER);
241
242 RECT button_rect;
243 GetWindowRect(hwndButton, &button_rect);
244 int button_width = button_rect.right - button_rect.left;
245 int button_height = button_rect.bottom - button_rect.top;
246 MapWindowPoints(NULL, hwnd_, reinterpret_cast<LPPOINT>(&button_rect), 2);
247 SetWindowPos(hwndButton, NULL,
248 button_rect.left + label_width_delta, button_rect.top,
249 button_width + button_width_delta, button_height, SWP_NOZORDER);
250
251 RECT window_rect;
252 GetWindowRect(hwnd_, &window_rect);
253 int width = (window_rect.right - window_rect.left) +
254 button_width_delta + label_width_delta;
255 int height = window_rect.bottom - window_rect.top;
256 SetWindowPos(hwnd_, NULL, 0, 0, width, height, SWP_NOMOVE|SWP_NOZORDER);
257 HRGN rgn = CreateRoundRectRgn(0, 0, width, height, kWindowBorderRadius,
258 kWindowBorderRadius);
259 SetWindowRgn(hwnd_, rgn, TRUE);
154 } 260 }
155 261
156 void DisconnectWindowWin::Hide() { 262 void DisconnectWindowWin::Hide() {
157 EndDialog(0); 263 EndDialog(0);
158 } 264 }
159 265
160 void DisconnectWindowWin::EndDialog(int result) { 266 void DisconnectWindowWin::EndDialog(int result) {
161 if (has_hotkey_) { 267 if (has_hotkey_) {
162 UnregisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID); 268 UnregisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID);
163 has_hotkey_ = false; 269 has_hotkey_ = false;
164 } 270 }
165 271
166 if (hwnd_) { 272 if (hwnd_) {
167 ::EndDialog(hwnd_, result); 273 ::EndDialog(hwnd_, result);
168 hwnd_ = NULL; 274 hwnd_ = NULL;
169 } 275 }
170 } 276 }
171 277
172 DisconnectWindow* DisconnectWindow::Create() { 278 DisconnectWindow* DisconnectWindow::Create() {
173 return new DisconnectWindowWin; 279 return new DisconnectWindowWin;
174 } 280 }
175 281
176 } // namespace remoting 282 } // namespace remoting
OLDNEW
« no previous file with comments | « no previous file | remoting/host/plugin/host_plugin.rc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698