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

Side by Side Diff: content/browser/tab_contents/tab_contents_view_win.cc

Issue 10031044: TabContents -> WebContentsImpl, part 5. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase (fixed) Created 8 years, 8 months 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
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/browser/tab_contents/tab_contents_view_win.h"
6
7 #include "base/bind.h"
8 #include "content/browser/renderer_host/render_view_host_factory.h"
9 #include "content/browser/renderer_host/render_view_host_impl.h"
10 #include "content/browser/renderer_host/render_widget_host_view_win.h"
11 #include "content/browser/tab_contents/tab_contents.h"
12 #include "content/browser/web_contents/interstitial_page_impl.h"
13 #include "content/browser/web_contents/web_contents_drag_win.h"
14 #include "content/browser/web_contents/web_drag_dest_win.h"
15 #include "content/public/browser/web_contents_delegate.h"
16 #include "content/public/browser/web_contents_view_delegate.h"
17 #include "ui/gfx/screen.h"
18
19 using content::RenderViewHost;
20 using content::RenderWidgetHostView;
21 using content::WebContents;
22 using content::WebContentsViewDelegate;
23
24 namespace {
25
26 // We need to have a parent window for the compositing code to work correctly.
27 //
28 // A tab will not have a parent HWND whenever it is not active in its
29 // host window - for example at creation time and when it's in the
30 // background, so we provide a default widget to host them.
31 //
32 // It may be tempting to use GetDesktopWindow() instead, but this is
33 // problematic as the shell sends messages to children of the desktop
34 // window that interact poorly with us.
35 //
36 // See: http://crbug.com/16476
37 class TempParent : public ui::WindowImpl {
38 public:
39 static TempParent* Get() {
40 static TempParent* g_temp_parent;
41 if (!g_temp_parent) {
42 g_temp_parent = new TempParent();
43
44 g_temp_parent->set_window_style(WS_POPUP);
45 g_temp_parent->set_window_ex_style(WS_EX_TOOLWINDOW);
46 g_temp_parent->Init(GetDesktopWindow(), gfx::Rect());
47 EnableWindow(g_temp_parent->hwnd(), FALSE);
48 }
49 return g_temp_parent;
50 }
51
52 private:
53 // Explicitly do nothing in Close. We do this as some external apps may get a
54 // handle to this window and attempt to close it.
55 void OnClose() {
56 }
57
58 BEGIN_MSG_MAP_EX(TabContentsViewWin)
59 MSG_WM_CLOSE(OnClose)
60 END_MSG_MAP()
61 };
62
63 } // namespace namespace
64
65 TabContentsViewWin::TabContentsViewWin(TabContents* tab_contents,
66 WebContentsViewDelegate* delegate)
67 : tab_contents_(tab_contents),
68 view_(NULL),
69 delegate_(delegate),
70 close_tab_after_drag_ends_(false) {
71 }
72
73 TabContentsViewWin::~TabContentsViewWin() {
74 if (IsWindow(hwnd()))
75 DestroyWindow(hwnd());
76 }
77
78 void TabContentsViewWin::CreateView(const gfx::Size& initial_size) {
79 initial_size_ = initial_size;
80
81 set_window_style(WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
82
83 Init(TempParent::Get()->hwnd(), gfx::Rect(initial_size_));
84
85 // Remove the root view drop target so we can register our own.
86 RevokeDragDrop(GetNativeView());
87 drag_dest_ = new WebDragDest(hwnd(), tab_contents_);
88 if (delegate_.get()) {
89 content::WebDragDestDelegate* delegate = delegate_->GetDragDestDelegate();
90 if (delegate)
91 drag_dest_->set_delegate(delegate);
92 }
93 }
94
95 RenderWidgetHostView* TabContentsViewWin::CreateViewForWidget(
96 content::RenderWidgetHost* render_widget_host) {
97 if (render_widget_host->GetView()) {
98 // During testing, the view will already be set up in most cases to the
99 // test view, so we don't want to clobber it with a real one. To verify that
100 // this actually is happening (and somebody isn't accidentally creating the
101 // view twice), we check for the RVH Factory, which will be set when we're
102 // making special ones (which go along with the special views).
103 DCHECK(RenderViewHostFactory::has_factory());
104 return render_widget_host->GetView();
105 }
106
107 view_ = static_cast<RenderWidgetHostViewWin*>(
108 RenderWidgetHostView::CreateViewForWidget(render_widget_host));
109 view_->CreateWnd(GetNativeView());
110 view_->ShowWindow(SW_SHOW);
111 view_->SetSize(initial_size_);
112 return view_;
113 }
114
115 gfx::NativeView TabContentsViewWin::GetNativeView() const {
116 return hwnd();
117 }
118
119 gfx::NativeView TabContentsViewWin::GetContentNativeView() const {
120 RenderWidgetHostView* rwhv = tab_contents_->GetRenderWidgetHostView();
121 return rwhv ? rwhv->GetNativeView() : NULL;
122 }
123
124 gfx::NativeWindow TabContentsViewWin::GetTopLevelNativeWindow() const {
125 return GetParent(GetNativeView());
126 }
127
128 void TabContentsViewWin::GetContainerBounds(gfx::Rect *out) const {
129 // Copied from NativeWidgetWin::GetClientAreaScreenBounds().
130 RECT r;
131 GetClientRect(hwnd(), &r);
132 POINT point = { r.left, r.top };
133 ClientToScreen(hwnd(), &point);
134 *out = gfx::Rect(point.x, point.y, r.right - r.left, r.bottom - r.top);
135 }
136
137 void TabContentsViewWin::SetPageTitle(const string16& title) {
138 // It's possible to get this after the hwnd has been destroyed.
139 if (GetNativeView())
140 ::SetWindowText(GetNativeView(), title.c_str());
141 }
142
143 void TabContentsViewWin::OnTabCrashed(base::TerminationStatus status,
144 int error_code) {
145 // TODO(avi): No other TCV implementation does anything in this callback. Can
146 // this be moved elsewhere so that |OnTabCrashed| can be removed everywhere?
147 view_ = NULL;
148 }
149
150 void TabContentsViewWin::SizeContents(const gfx::Size& size) {
151 gfx::Rect bounds;
152 GetContainerBounds(&bounds);
153 if (bounds.size() != size) {
154 SetWindowPos(hwnd(), NULL, 0, 0, size.width(), size.height(),
155 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
156 } else {
157 // Our size matches what we want but the renderers size may not match.
158 // Pretend we were resized so that the renderers size is updated too.
159 if (tab_contents_->GetInterstitialPage())
160 tab_contents_->GetInterstitialPage()->SetSize(size);
161 RenderWidgetHostView* rwhv = tab_contents_->GetRenderWidgetHostView();
162 if (rwhv)
163 rwhv->SetSize(size);
164 }
165 }
166
167 void TabContentsViewWin::RenderViewCreated(RenderViewHost* host) {
168 }
169
170 void TabContentsViewWin::Focus() {
171 if (tab_contents_->GetInterstitialPage()) {
172 tab_contents_->GetInterstitialPage()->Focus();
173 return;
174 }
175
176 if (delegate_.get() && delegate_->Focus())
177 return;
178
179 RenderWidgetHostView* rwhv = tab_contents_->GetRenderWidgetHostView();
180 if (rwhv)
181 rwhv->Focus();
182 }
183
184 void TabContentsViewWin::SetInitialFocus() {
185 if (tab_contents_->FocusLocationBarByDefault())
186 tab_contents_->SetFocusToLocationBar(false);
187 else
188 Focus();
189 }
190
191 void TabContentsViewWin::StoreFocus() {
192 if (delegate_.get())
193 delegate_->StoreFocus();
194 }
195
196 void TabContentsViewWin::RestoreFocus() {
197 if (delegate_.get())
198 delegate_->RestoreFocus();
199 }
200
201 bool TabContentsViewWin::IsDoingDrag() const {
202 return drag_handler_.get() != NULL;
203 }
204
205 void TabContentsViewWin::CancelDragAndCloseTab() {
206 DCHECK(IsDoingDrag());
207 // We can't close the tab while we're in the drag and
208 // |drag_handler_->CancelDrag()| is async. Instead, set a flag to cancel
209 // the drag and when the drag nested message loop ends, close the tab.
210 drag_handler_->CancelDrag();
211 close_tab_after_drag_ends_ = true;
212 }
213
214 bool TabContentsViewWin::IsEventTracking() const {
215 return false;
216 }
217
218 void TabContentsViewWin::CloseTabAfterEventTracking() {
219 }
220
221 void TabContentsViewWin::GetViewBounds(gfx::Rect* out) const {
222 RECT r;
223 GetWindowRect(hwnd(), &r);
224 *out = gfx::Rect(r);
225 }
226
227 void TabContentsViewWin::CreateNewWindow(
228 int route_id,
229 const ViewHostMsg_CreateWindow_Params& params) {
230 tab_contents_view_helper_.CreateNewWindow(tab_contents_, route_id, params);
231 }
232
233 void TabContentsViewWin::CreateNewWidget(int route_id,
234 WebKit::WebPopupType popup_type) {
235 tab_contents_view_helper_.CreateNewWidget(tab_contents_,
236 route_id,
237 false,
238 popup_type);
239 }
240
241 void TabContentsViewWin::CreateNewFullscreenWidget(int route_id) {
242 tab_contents_view_helper_.CreateNewWidget(tab_contents_,
243 route_id,
244 true,
245 WebKit::WebPopupTypeNone);
246 }
247
248 void TabContentsViewWin::ShowCreatedWindow(int route_id,
249 WindowOpenDisposition disposition,
250 const gfx::Rect& initial_pos,
251 bool user_gesture) {
252 tab_contents_view_helper_.ShowCreatedWindow(
253 tab_contents_, route_id, disposition, initial_pos, user_gesture);
254 }
255
256 void TabContentsViewWin::ShowCreatedWidget(int route_id,
257 const gfx::Rect& initial_pos) {
258 tab_contents_view_helper_.ShowCreatedWidget(tab_contents_,
259 route_id,
260 false,
261 initial_pos);
262 }
263
264 void TabContentsViewWin::ShowCreatedFullscreenWidget(int route_id) {
265 tab_contents_view_helper_.ShowCreatedWidget(tab_contents_,
266 route_id,
267 true,
268 gfx::Rect());
269 }
270
271 void TabContentsViewWin::ShowContextMenu(
272 const content::ContextMenuParams& params) {
273 // Allow WebContentsDelegates to handle the context menu operation first.
274 if (tab_contents_->GetDelegate() &&
275 tab_contents_->GetDelegate()->HandleContextMenu(params)) {
276 return;
277 }
278
279 if (delegate_.get())
280 delegate_->ShowContextMenu(params);
281 }
282
283 void TabContentsViewWin::ShowPopupMenu(const gfx::Rect& bounds,
284 int item_height,
285 double item_font_size,
286 int selected_item,
287 const std::vector<WebMenuItem>& items,
288 bool right_aligned) {
289 // External popup menus are only used on Mac.
290 NOTIMPLEMENTED();
291 }
292
293 void TabContentsViewWin::StartDragging(const WebDropData& drop_data,
294 WebKit::WebDragOperationsMask operations,
295 const SkBitmap& image,
296 const gfx::Point& image_offset) {
297 drag_handler_ = new WebContentsDragWin(
298 GetNativeView(),
299 tab_contents_,
300 drag_dest_,
301 base::Bind(&TabContentsViewWin::EndDragging, base::Unretained(this)));
302 drag_handler_->StartDragging(drop_data, operations, image, image_offset);
303 }
304
305 void TabContentsViewWin::UpdateDragCursor(WebKit::WebDragOperation operation) {
306 drag_dest_->set_drag_cursor(operation);
307 }
308
309 void TabContentsViewWin::GotFocus() {
310 if (tab_contents_->GetDelegate())
311 tab_contents_->GetDelegate()->WebContentsFocused(tab_contents_);
312 }
313
314 void TabContentsViewWin::TakeFocus(bool reverse) {
315 if (tab_contents_->GetDelegate() &&
316 !tab_contents_->GetDelegate()->TakeFocus(reverse) &&
317 delegate_.get()) {
318 delegate_->TakeFocus(reverse);
319 }
320 }
321
322 void TabContentsViewWin::EndDragging() {
323 drag_handler_ = NULL;
324 if (close_tab_after_drag_ends_) {
325 close_tab_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(0),
326 this, &TabContentsViewWin::CloseTab);
327 }
328 tab_contents_->SystemDragEnded();
329 }
330
331 void TabContentsViewWin::CloseTab() {
332 RenderViewHost* rvh = tab_contents_->GetRenderViewHost();
333 rvh->GetDelegate()->Close(rvh);
334 }
335
336 LRESULT TabContentsViewWin::OnDestroy(
337 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
338 if (drag_dest_.get()) {
339 RevokeDragDrop(GetNativeView());
340 drag_dest_ = NULL;
341 }
342 return 0;
343 }
344
345 LRESULT TabContentsViewWin::OnWindowPosChanged(
346 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
347 WINDOWPOS* window_pos = reinterpret_cast<WINDOWPOS*>(lparam);
348 if (window_pos->flags & SWP_HIDEWINDOW) {
349 tab_contents_->HideContents();
350 return 0;
351 }
352
353 // The TabContents was shown by a means other than the user selecting a
354 // Tab, e.g. the window was minimized then restored.
355 if (window_pos->flags & SWP_SHOWWINDOW)
356 tab_contents_->ShowContents();
357
358 // Unless we were specifically told not to size, cause the renderer to be
359 // sized to the new bounds, which forces a repaint. Not required for the
360 // simple minimize-restore case described above, for example, since the
361 // size hasn't changed.
362 if (window_pos->flags & SWP_NOSIZE)
363 return 0;
364
365 gfx::Size size(window_pos->cx, window_pos->cy);
366 if (tab_contents_->GetInterstitialPage())
367 tab_contents_->GetInterstitialPage()->SetSize(size);
368 RenderWidgetHostView* rwhv = tab_contents_->GetRenderWidgetHostView();
369 if (rwhv)
370 rwhv->SetSize(size);
371
372 if (delegate_.get())
373 delegate_->SizeChanged(size);
374
375 return 0;
376 }
377
378 LRESULT TabContentsViewWin::OnMouseDown(
379 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
380 // Make sure this TabContents is activated when it is clicked on.
381 if (tab_contents_->GetDelegate())
382 tab_contents_->GetDelegate()->ActivateContents(tab_contents_);
383 return 0;
384 }
385
386 LRESULT TabContentsViewWin::OnMouseMove(
387 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
388 // Let our delegate know that the mouse moved (useful for resetting status
389 // bubble state).
390 if (tab_contents_->GetDelegate()) {
391 tab_contents_->GetDelegate()->ContentsMouseEvent(
392 tab_contents_, gfx::Screen::GetCursorScreenPoint(), true);
393 }
394 return 0;
395 }
396
397 LRESULT TabContentsViewWin::OnReflectedMessage(
398 UINT msg, WPARAM wparam, LPARAM lparam, BOOL& handled) {
399 MSG* message = reinterpret_cast<MSG*>(lparam);
400 switch (message->message) {
401 case WM_MOUSEWHEEL:
402 // This message is reflected from the view() to this window.
403 if (GET_KEYSTATE_WPARAM(message->wParam) & MK_CONTROL) {
404 tab_contents_->GetDelegate()->ContentsZoomChange(
405 GET_WHEEL_DELTA_WPARAM(message->wParam) > 0);
406 return 1;
407 }
408 break;
409 }
410 return 0;
411 }
412
413 LRESULT TabContentsViewWin::OnNCCalcSize(
414 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
415 // Hack for ThinkPad mouse wheel driver. We have set the fake scroll bars
416 // to receive scroll messages from ThinkPad touch-pad driver. Suppress
417 // painting of scrollbars by returning 0 size for them.
418 return 0;
419 }
420
421 LRESULT TabContentsViewWin::OnScroll(
422 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
423 int scroll_type = LOWORD(wparam);
424 short position = HIWORD(wparam);
425 HWND scrollbar = reinterpret_cast<HWND>(lparam);
426 // This window can receive scroll events as a result of the ThinkPad's
427 // touch-pad scroll wheel emulation.
428 // If ctrl is held, zoom the UI. There are three issues with this:
429 // 1) Should the event be eaten or forwarded to content? We eat the event,
430 // which is like Firefox and unlike IE.
431 // 2) Should wheel up zoom in or out? We zoom in (increase font size), which
432 // is like IE and Google maps, but unlike Firefox.
433 // 3) Should the mouse have to be over the content area? We zoom as long as
434 // content has focus, although FF and IE require that the mouse is over
435 // content. This is because all events get forwarded when content has
436 // focus.
437 if (GetAsyncKeyState(VK_CONTROL) & 0x8000) {
438 int distance = 0;
439 switch (scroll_type) {
440 case SB_LINEUP:
441 distance = WHEEL_DELTA;
442 break;
443 case SB_LINEDOWN:
444 distance = -WHEEL_DELTA;
445 break;
446 // TODO(joshia): Handle SB_PAGEUP, SB_PAGEDOWN, SB_THUMBPOSITION,
447 // and SB_THUMBTRACK for completeness
448 default:
449 break;
450 }
451
452 tab_contents_->GetDelegate()->ContentsZoomChange(distance > 0);
453 return 0;
454 }
455
456 // Reflect scroll message to the view() to give it a chance
457 // to process scrolling.
458 SendMessage(GetContentNativeView(), message, wparam, lparam);
459 return 0;
460 }
461
462 LRESULT TabContentsViewWin::OnSize(
463 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
464 // NOTE: Because we handle OnWindowPosChanged without calling DefWindowProc,
465 // OnSize is NOT called on window resize. This handler is called only once
466 // when the window is created.
467 // Don't call base class OnSize to avoid useless layout for 0x0 size.
468 // We will get OnWindowPosChanged later and layout root view in WasSized.
469
470 // Hack for ThinkPad touch-pad driver.
471 // Set fake scrollbars so that we can get scroll messages,
472 SCROLLINFO si = {0};
473 si.cbSize = sizeof(si);
474 si.fMask = SIF_ALL;
475
476 si.nMin = 1;
477 si.nMax = 100;
478 si.nPage = 10;
479 si.nPos = 50;
480
481 ::SetScrollInfo(hwnd(), SB_HORZ, &si, FALSE);
482 ::SetScrollInfo(hwnd(), SB_VERT, &si, FALSE);
483
484 return 1;
485 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698