1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/shell/browser/shell.h" 6 7#include <windows.h> 8#include <commctrl.h> 9#include <fcntl.h> 10#include <io.h> 11 12#include "base/strings/utf_string_conversions.h" 13#include "base/win/wrapped_window_proc.h" 14#include "content/public/browser/web_contents.h" 15#include "content/public/browser/web_contents_view.h" 16#include "content/shell/app/resource.h" 17#include "ui/gfx/win/hwnd_util.h" 18 19namespace { 20 21const wchar_t kWindowTitle[] = L"Content Shell"; 22const wchar_t kWindowClass[] = L"CONTENT_SHELL"; 23 24const int kButtonWidth = 72; 25const int kURLBarHeight = 24; 26 27const int kMaxURLLength = 1024; 28 29} // namespace 30 31namespace content { 32 33HINSTANCE Shell::instance_handle_; 34 35void Shell::PlatformInitialize(const gfx::Size& default_window_size) { 36 _setmode(_fileno(stdout), _O_BINARY); 37 _setmode(_fileno(stderr), _O_BINARY); 38 INITCOMMONCONTROLSEX InitCtrlEx; 39 InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); 40 InitCtrlEx.dwICC = ICC_STANDARD_CLASSES; 41 InitCommonControlsEx(&InitCtrlEx); 42 RegisterWindowClass(); 43} 44 45void Shell::PlatformExit() { 46 std::vector<Shell*> windows = windows_; 47 for (std::vector<Shell*>::iterator it = windows.begin(); 48 it != windows.end(); ++it) 49 DestroyWindow((*it)->window_); 50} 51 52void Shell::PlatformCleanUp() { 53 // When the window is destroyed, tell the Edit field to forget about us, 54 // otherwise we will crash. 55 gfx::SetWindowProc(url_edit_view_, default_edit_wnd_proc_); 56 gfx::SetWindowUserData(url_edit_view_, NULL); 57} 58 59void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) { 60 int id; 61 switch (control) { 62 case BACK_BUTTON: 63 id = IDC_NAV_BACK; 64 break; 65 case FORWARD_BUTTON: 66 id = IDC_NAV_FORWARD; 67 break; 68 case STOP_BUTTON: 69 id = IDC_NAV_STOP; 70 break; 71 default: 72 NOTREACHED() << "Unknown UI control"; 73 return; 74 } 75 EnableWindow(GetDlgItem(window_, id), is_enabled); 76} 77 78void Shell::PlatformSetAddressBarURL(const GURL& url) { 79 std::wstring url_string = UTF8ToWide(url.spec()); 80 SendMessage(url_edit_view_, WM_SETTEXT, 0, 81 reinterpret_cast<LPARAM>(url_string.c_str())); 82} 83 84void Shell::PlatformSetIsLoading(bool loading) { 85} 86 87void Shell::PlatformCreateWindow(int width, int height) { 88 window_ = CreateWindow(kWindowClass, kWindowTitle, 89 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 90 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 91 NULL, NULL, instance_handle_, NULL); 92 gfx::SetWindowUserData(window_, this); 93 94 HWND hwnd; 95 int x = 0; 96 97 hwnd = CreateWindow(L"BUTTON", L"Back", 98 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 99 x, 0, kButtonWidth, kURLBarHeight, 100 window_, (HMENU) IDC_NAV_BACK, instance_handle_, 0); 101 x += kButtonWidth; 102 103 hwnd = CreateWindow(L"BUTTON", L"Forward", 104 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 105 x, 0, kButtonWidth, kURLBarHeight, 106 window_, (HMENU) IDC_NAV_FORWARD, instance_handle_, 0); 107 x += kButtonWidth; 108 109 hwnd = CreateWindow(L"BUTTON", L"Reload", 110 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 111 x, 0, kButtonWidth, kURLBarHeight, 112 window_, (HMENU) IDC_NAV_RELOAD, instance_handle_, 0); 113 x += kButtonWidth; 114 115 hwnd = CreateWindow(L"BUTTON", L"Stop", 116 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 117 x, 0, kButtonWidth, kURLBarHeight, 118 window_, (HMENU) IDC_NAV_STOP, instance_handle_, 0); 119 x += kButtonWidth; 120 121 // This control is positioned by PlatformResizeSubViews. 122 url_edit_view_ = CreateWindow(L"EDIT", 0, 123 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | 124 ES_AUTOVSCROLL | ES_AUTOHSCROLL, 125 x, 0, 0, 0, window_, 0, instance_handle_, 0); 126 127 default_edit_wnd_proc_ = gfx::SetWindowProc(url_edit_view_, 128 Shell::EditWndProc); 129 gfx::SetWindowUserData(url_edit_view_, this); 130 131 ShowWindow(window_, SW_SHOW); 132 133 SizeTo(gfx::Size(width, height)); 134} 135 136void Shell::PlatformSetContents() { 137 SetParent(web_contents_->GetView()->GetNativeView(), window_); 138} 139 140void Shell::SizeTo(const gfx::Size& size) { 141 RECT rc, rw; 142 GetClientRect(window_, &rc); 143 GetWindowRect(window_, &rw); 144 145 int client_width = rc.right - rc.left; 146 int window_width = rw.right - rw.left; 147 window_width = (window_width - client_width) + size.width(); 148 149 int client_height = rc.bottom - rc.top; 150 int window_height = rw.bottom - rw.top; 151 window_height = (window_height - client_height) + size.height(); 152 153 // Add space for the url bar. 154 window_height += kURLBarHeight; 155 156 SetWindowPos(window_, NULL, 0, 0, window_width, window_height, 157 SWP_NOMOVE | SWP_NOZORDER); 158} 159 160void Shell::PlatformResizeSubViews() { 161 RECT rc; 162 GetClientRect(window_, &rc); 163 164 int x = kButtonWidth * 4; 165 MoveWindow(url_edit_view_, x, 0, rc.right - x, kURLBarHeight, TRUE); 166 167 MoveWindow(GetContentView(), 0, kURLBarHeight, rc.right, 168 rc.bottom - kURLBarHeight, TRUE); 169} 170 171void Shell::Close() { 172 DestroyWindow(window_); 173} 174 175ATOM Shell::RegisterWindowClass() { 176 WNDCLASSEX window_class; 177 base::win::InitializeWindowClass( 178 kWindowClass, 179 &Shell::WndProc, 180 CS_HREDRAW | CS_VREDRAW, 181 0, 182 0, 183 LoadCursor(NULL, IDC_ARROW), 184 NULL, 185 MAKEINTRESOURCE(IDC_CONTENTSHELL), 186 NULL, 187 NULL, 188 &window_class); 189 instance_handle_ = window_class.hInstance; 190 return RegisterClassEx(&window_class); 191} 192 193LRESULT CALLBACK Shell::WndProc(HWND hwnd, UINT message, WPARAM wParam, 194 LPARAM lParam) { 195 Shell* shell = static_cast<Shell*>(gfx::GetWindowUserData(hwnd)); 196 197 switch (message) { 198 case WM_COMMAND: { 199 int id = LOWORD(wParam); 200 switch (id) { 201 case IDM_NEW_WINDOW: 202 CreateNewWindow( 203 shell->web_contents()->GetBrowserContext(), 204 GURL(), NULL, MSG_ROUTING_NONE, gfx::Size()); 205 break; 206 case IDM_CLOSE_WINDOW: 207 DestroyWindow(hwnd); 208 break; 209 case IDM_EXIT: 210 PlatformExit(); 211 break; 212 case IDM_SHOW_DEVELOPER_TOOLS: 213 shell->ShowDevTools(); 214 break; 215 case IDC_NAV_BACK: 216 shell->GoBackOrForward(-1); 217 break; 218 case IDC_NAV_FORWARD: 219 shell->GoBackOrForward(1); 220 break; 221 case IDC_NAV_RELOAD: 222 shell->Reload(); 223 break; 224 case IDC_NAV_STOP: 225 shell->Stop(); 226 break; 227 } 228 break; 229 } 230 case WM_DESTROY: { 231 delete shell; 232 return 0; 233 } 234 235 case WM_SIZE: { 236 if (shell->GetContentView()) 237 shell->PlatformResizeSubViews(); 238 return 0; 239 } 240 241 case WM_WINDOWPOSCHANGED: { 242 // Notify the content view that the window position of its parent window 243 // has been changed by sending window message 244 gfx::NativeView native_view = shell->GetContentView(); 245 if (native_view) { 246 SendMessage(native_view, message, wParam, lParam); 247 } 248 break; 249 } 250 } 251 252 return DefWindowProc(hwnd, message, wParam, lParam); 253} 254 255LRESULT CALLBACK Shell::EditWndProc(HWND hwnd, UINT message, 256 WPARAM wParam, LPARAM lParam) { 257 Shell* shell = static_cast<Shell*>(gfx::GetWindowUserData(hwnd)); 258 259 switch (message) { 260 case WM_CHAR: 261 if (wParam == VK_RETURN) { 262 wchar_t str[kMaxURLLength + 1]; // Leave room for adding a NULL; 263 *(str) = kMaxURLLength; 264 LRESULT str_len = SendMessage(hwnd, EM_GETLINE, 0, (LPARAM)str); 265 if (str_len > 0) { 266 str[str_len] = 0; // EM_GETLINE doesn't NULL terminate. 267 GURL url(str); 268 if (!url.has_scheme()) 269 url = GURL(std::wstring(L"http://") + std::wstring(str)); 270 shell->LoadURL(url); 271 } 272 273 return 0; 274 } 275 } 276 277 return CallWindowProc(shell->default_edit_wnd_proc_, hwnd, message, wParam, 278 lParam); 279} 280 281void Shell::PlatformSetTitle(const base::string16& text) { 282 ::SetWindowText(window_, text.c_str()); 283} 284 285} // namespace content 286