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

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

Issue 147074: Merging r18584 into chrome/browser/views/tab_contents/tab_contents_view_win.c... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 6 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
« no previous file with comments | « no previous file | chrome/browser/views/tab_contents/tab_contents_view_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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 "chrome/browser/tab_contents/tab_contents_view_win.h"
6
7 #include <windows.h>
8
9 #include "app/gfx/canvas.h"
10 #include "app/os_exchange_data.h"
11 #include "chrome/browser/bookmarks/bookmark_drag_data.h"
12 #include "chrome/browser/browser.h" // TODO(beng): this dependency is awful.
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/download/download_request_manager.h"
15 #include "chrome/browser/renderer_host/render_process_host.h"
16 #include "chrome/browser/renderer_host/render_view_host.h"
17 #include "chrome/browser/renderer_host/render_view_host_factory.h"
18 #include "chrome/browser/renderer_host/render_widget_host_view_win.h"
19 #include "chrome/browser/tab_contents/render_view_context_menu_win.h"
20 #include "chrome/browser/tab_contents/interstitial_page.h"
21 #include "chrome/browser/tab_contents/tab_contents.h"
22 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
23 #include "chrome/browser/tab_contents/web_drag_source.h"
24 #include "chrome/browser/tab_contents/web_drop_target.h"
25 #include "chrome/browser/views/sad_tab_view.h"
26 #include "chrome/common/url_constants.h"
27 #include "net/base/net_util.h"
28 #include "views/focus/view_storage.h"
29 #include "views/widget/root_view.h"
30 #include "webkit/glue/plugins/webplugin_delegate_impl.h"
31 #include "webkit/glue/webdropdata.h"
32
33 using WebKit::WebInputEvent;
34
35 namespace {
36
37 // Windows callback for OnDestroy to detach the plugin windows.
38 BOOL CALLBACK DetachPluginWindowsCallback(HWND window, LPARAM param) {
39 if (WebPluginDelegateImpl::IsPluginDelegateWindow(window) &&
40 !IsHungAppWindow(window)) {
41 ::ShowWindow(window, SW_HIDE);
42 SetParent(window, NULL);
43 }
44 return TRUE;
45 }
46
47 } // namespace
48
49 // static
50 TabContentsView* TabContentsView::Create(TabContents* tab_contents) {
51 return new TabContentsViewWin(tab_contents);
52 }
53
54 TabContentsViewWin::TabContentsViewWin(TabContents* tab_contents)
55 : TabContentsView(tab_contents),
56 ignore_next_char_event_(false) {
57 last_focused_view_storage_id_ =
58 views::ViewStorage::GetSharedInstance()->CreateStorageID();
59 }
60
61 TabContentsViewWin::~TabContentsViewWin() {
62 // Makes sure to remove any stored view we may still have in the ViewStorage.
63 //
64 // It is possible the view went away before us, so we only do this if the
65 // view is registered.
66 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
67 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
68 view_storage->RemoveView(last_focused_view_storage_id_);
69 }
70
71 void TabContentsViewWin::CreateView() {
72 set_delete_on_destroy(false);
73 // Since we create these windows parented to the desktop window initially, we
74 // don't want to create them initially visible.
75 set_window_style(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
76 WidgetWin::Init(GetDesktopWindow(), gfx::Rect(), false);
77
78 // Remove the root view drop target so we can register our own.
79 RevokeDragDrop(GetNativeView());
80 drop_target_ = new WebDropTarget(GetNativeView(), tab_contents());
81 }
82
83 RenderWidgetHostView* TabContentsViewWin::CreateViewForWidget(
84 RenderWidgetHost* render_widget_host) {
85 if (render_widget_host->view()) {
86 // During testing, the view will already be set up in most cases to the
87 // test view, so we don't want to clobber it with a real one. To verify that
88 // this actually is happening (and somebody isn't accidentally creating the
89 // view twice), we check for the RVH Factory, which will be set when we're
90 // making special ones (which go along with the special views).
91 DCHECK(RenderViewHostFactory::has_factory());
92 return render_widget_host->view();
93 }
94
95 RenderWidgetHostViewWin* view =
96 new RenderWidgetHostViewWin(render_widget_host);
97 view->Create(GetNativeView());
98 view->ShowWindow(SW_SHOW);
99 return view;
100 }
101
102 gfx::NativeView TabContentsViewWin::GetNativeView() const {
103 return WidgetWin::GetNativeView();
104 }
105
106 gfx::NativeView TabContentsViewWin::GetContentNativeView() const {
107 if (!tab_contents()->render_widget_host_view())
108 return NULL;
109 return tab_contents()->render_widget_host_view()->GetNativeView();
110 }
111
112 gfx::NativeWindow TabContentsViewWin::GetTopLevelNativeWindow() const {
113 return ::GetAncestor(GetNativeView(), GA_ROOT);
114 }
115
116 void TabContentsViewWin::GetContainerBounds(gfx::Rect* out) const {
117 GetBounds(out, false);
118 }
119
120 void TabContentsViewWin::StartDragging(const WebDropData& drop_data) {
121 scoped_refptr<OSExchangeData> data(new OSExchangeData);
122
123 // TODO(tc): Generate an appropriate drag image.
124
125 // We set the file contents before the URL because the URL also sets file
126 // contents (to a .URL shortcut). We want to prefer file content data over a
127 // shortcut so we add it first.
128 if (!drop_data.file_contents.empty()) {
129 // Images without ALT text will only have a file extension so we need to
130 // synthesize one from the provided extension and URL.
131 FilePath file_name(drop_data.file_description_filename);
132 file_name = file_name.BaseName().RemoveExtension();
133 if (file_name.value().empty()) {
134 // Retrieve the name from the URL.
135 file_name = FilePath::FromWStringHack(
136 net::GetSuggestedFilename(drop_data.url, "", "", L""));
137 }
138 file_name = file_name.ReplaceExtension(drop_data.file_extension);
139 data->SetFileContents(file_name.value(), drop_data.file_contents);
140 }
141 if (!drop_data.text_html.empty())
142 data->SetHtml(drop_data.text_html, drop_data.html_base_url);
143 if (drop_data.url.is_valid()) {
144 if (drop_data.url.SchemeIs(chrome::kJavaScriptScheme)) {
145 // We don't want to allow javascript URLs to be dragged to the desktop,
146 // but we do want to allow them to be added to the bookmarks bar
147 // (bookmarklets). So we create a fake bookmark entry (BookmarkDragData
148 // object) which explorer.exe cannot handle, and write the entry to data.
149 BookmarkDragData::Element bm_elt;
150 bm_elt.is_url = true;
151 bm_elt.url = drop_data.url;
152 bm_elt.title = drop_data.url_title;
153
154 BookmarkDragData bm_drag_data;
155 bm_drag_data.elements.push_back(bm_elt);
156
157 // Pass in NULL as the profile so that the bookmark always adds the url
158 // rather than trying to move an existing url.
159 bm_drag_data.Write(NULL, data);
160 } else {
161 data->SetURL(drop_data.url, drop_data.url_title);
162 }
163 }
164 if (!drop_data.plain_text.empty())
165 data->SetString(drop_data.plain_text);
166
167 scoped_refptr<WebDragSource> drag_source(
168 new WebDragSource(GetNativeView(), tab_contents()->render_view_host()));
169
170 DWORD effects;
171
172 // We need to enable recursive tasks on the message loop so we can get
173 // updates while in the system DoDragDrop loop.
174 bool old_state = MessageLoop::current()->NestableTasksAllowed();
175 MessageLoop::current()->SetNestableTasksAllowed(true);
176 DoDragDrop(data, drag_source, DROPEFFECT_COPY | DROPEFFECT_LINK, &effects);
177 MessageLoop::current()->SetNestableTasksAllowed(old_state);
178
179 if (tab_contents()->render_view_host())
180 tab_contents()->render_view_host()->DragSourceSystemDragEnded();
181 }
182
183 void TabContentsViewWin::OnContentsDestroy() {
184 // TODO(brettw) this seems like maybe it can be moved into OnDestroy and this
185 // function can be deleted? If you're adding more here, consider whether it
186 // can be moved into OnDestroy which is a Windows message handler as the
187 // window is being torn down.
188
189 // When a tab is closed all its child plugin windows are destroyed
190 // automatically. This happens before plugins get any notification that its
191 // instances are tearing down.
192 //
193 // Plugins like Quicktime assume that their windows will remain valid as long
194 // as they have plugin instances active. Quicktime crashes in this case
195 // because its windowing code cleans up an internal data structure that the
196 // handler for NPP_DestroyStream relies on.
197 //
198 // The fix is to detach plugin windows from web contents when it is going
199 // away. This will prevent the plugin windows from getting destroyed
200 // automatically. The detached plugin windows will get cleaned up in proper
201 // sequence as part of the usual cleanup when the plugin instance goes away.
202 EnumChildWindows(GetNativeView(), DetachPluginWindowsCallback, NULL);
203 }
204
205 void TabContentsViewWin::OnDestroy() {
206 if (drop_target_.get()) {
207 RevokeDragDrop(GetNativeView());
208 drop_target_ = NULL;
209 }
210 }
211
212 void TabContentsViewWin::SetPageTitle(const std::wstring& title) {
213 if (GetNativeView()) {
214 // It's possible to get this after the hwnd has been destroyed.
215 ::SetWindowText(GetNativeView(), title.c_str());
216 // TODO(brettw) this call seems messy the way it reaches into the widget
217 // view, and I'm not sure it's necessary. Maybe we should just remove it.
218 ::SetWindowText(
219 tab_contents()->render_widget_host_view()->GetNativeView(),
220 title.c_str());
221 }
222 }
223
224 void TabContentsViewWin::OnTabCrashed() {
225 // Force an invalidation to render sad tab. We will notice we crashed when we
226 // paint.
227 // Note that it's possible to get this message after the window was destroyed.
228 if (::IsWindow(GetNativeView()))
229 InvalidateRect(GetNativeView(), NULL, FALSE);
230 }
231
232 void TabContentsViewWin::SizeContents(const gfx::Size& size) {
233 // TODO(brettw) this is a hack and should be removed. See tab_contents_view.h.
234 WasSized(size);
235 }
236
237 void TabContentsViewWin::Focus() {
238 HWND container_hwnd = GetNativeView();
239 if (!container_hwnd)
240 return;
241
242 views::FocusManager* focus_manager =
243 views::FocusManager::GetFocusManager(container_hwnd);
244 if (!focus_manager)
245 return; // During testing we have no focus manager.
246 views::View* v = focus_manager->GetViewForWindow(container_hwnd, true);
247 DCHECK(v);
248 if (v)
249 v->RequestFocus();
250 }
251
252 void TabContentsViewWin::SetInitialFocus() {
253 if (tab_contents()->FocusLocationBarByDefault())
254 tab_contents()->delegate()->SetFocusToLocationBar();
255 else
256 ::SetFocus(GetNativeView());
257 }
258
259 void TabContentsViewWin::StoreFocus() {
260 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
261
262 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
263 view_storage->RemoveView(last_focused_view_storage_id_);
264
265 views::FocusManager* focus_manager =
266 views::FocusManager::GetFocusManager(GetNativeView());
267 if (focus_manager) {
268 // |focus_manager| can be NULL if the tab has been detached but still
269 // exists.
270 views::View* focused_view = focus_manager->GetFocusedView();
271 if (focused_view)
272 view_storage->StoreView(last_focused_view_storage_id_, focused_view);
273
274 // If the focus was on the page, explicitly clear the focus so that we
275 // don't end up with the focused HWND not part of the window hierarchy.
276 // TODO(brettw) this should move to the view somehow.
277 HWND container_hwnd = GetNativeView();
278 if (container_hwnd) {
279 views::View* focused_view = focus_manager->GetFocusedView();
280 if (focused_view) {
281 HWND hwnd = focused_view->GetRootView()->GetWidget()->GetNativeView();
282 if (container_hwnd == hwnd || ::IsChild(container_hwnd, hwnd))
283 focus_manager->ClearFocus();
284 }
285 }
286 }
287 }
288
289 void TabContentsViewWin::RestoreFocus() {
290 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
291 views::View* last_focused_view =
292 view_storage->RetrieveView(last_focused_view_storage_id_);
293
294 if (!last_focused_view) {
295 SetInitialFocus();
296 } else {
297 views::FocusManager* focus_manager =
298 views::FocusManager::GetFocusManager(GetNativeView());
299
300 // If you hit this DCHECK, please report it to Jay (jcampan).
301 DCHECK(focus_manager != NULL) << "No focus manager when restoring focus.";
302
303 if (last_focused_view->IsFocusable() && focus_manager &&
304 focus_manager->ContainsView(last_focused_view)) {
305 last_focused_view->RequestFocus();
306 } else {
307 // The focused view may not belong to the same window hierarchy (e.g.
308 // if the location bar was focused and the tab is dragged out), or it may
309 // no longer be focusable (e.g. if the location bar was focused and then
310 // we switched to fullscreen mode). In that case we default to the
311 // default focus.
312 SetInitialFocus();
313 }
314 view_storage->RemoveView(last_focused_view_storage_id_);
315 }
316 }
317
318 void TabContentsViewWin::UpdateDragCursor(bool is_drop_target) {
319 drop_target_->set_is_drop_target(is_drop_target);
320 }
321
322 void TabContentsViewWin::TakeFocus(bool reverse) {
323 if (!tab_contents()->delegate()->TakeFocus(reverse)) {
324 views::FocusManager* focus_manager =
325 views::FocusManager::GetFocusManager(GetNativeView());
326
327 // We may not have a focus manager if the tab has been switched before this
328 // message arrived.
329 if (focus_manager)
330 focus_manager->AdvanceFocus(reverse);
331 }
332 }
333
334 void TabContentsViewWin::HandleKeyboardEvent(
335 const NativeWebKeyboardEvent& event) {
336 // Previous calls to TranslateMessage can generate CHAR events as well as
337 // RAW_KEY_DOWN events, even if the latter triggered an accelerator. In these
338 // cases, we discard the CHAR events.
339 if (event.type == WebInputEvent::Char && ignore_next_char_event_) {
340 ignore_next_char_event_ = false;
341 return;
342 }
343 ignore_next_char_event_ = false;
344
345 // The renderer returned a keyboard event it did not process. This may be
346 // a keyboard shortcut that we have to process.
347 if (event.type == WebInputEvent::RawKeyDown) {
348 views::FocusManager* focus_manager =
349 views::FocusManager::GetFocusManager(GetNativeView());
350 // We may not have a focus_manager at this point (if the tab has been
351 // switched by the time this message returned).
352 if (focus_manager) {
353 views::Accelerator accelerator(event.windowsKeyCode,
354 (event.modifiers & WebInputEvent::ShiftKey) ==
355 WebInputEvent::ShiftKey,
356 (event.modifiers & WebInputEvent::ControlKey) ==
357 WebInputEvent::ControlKey,
358 (event.modifiers & WebInputEvent::AltKey) ==
359 WebInputEvent::AltKey);
360
361 // This is tricky: we want to set ignore_next_char_event_ if
362 // ProcessAccelerator returns true. But ProcessAccelerator might delete
363 // |this| if the accelerator is a "close tab" one. So we speculatively
364 // set the flag and fix it if no event was handled.
365 ignore_next_char_event_ = true;
366 if (focus_manager->ProcessAccelerator(accelerator)) {
367 // DANGER: |this| could be deleted now!
368 return;
369 } else {
370 // ProcessAccelerator didn't handle the accelerator, so we know both
371 // that |this| is still valid, and that we didn't want to set the flag.
372 ignore_next_char_event_ = false;
373 }
374 }
375 }
376
377 // Any unhandled keyboard/character messages should be defproced.
378 // This allows stuff like Alt+F4, etc to work correctly.
379 DefWindowProc(event.os_event.hwnd,
380 event.os_event.message,
381 event.os_event.wParam,
382 event.os_event.lParam);
383 }
384
385 void TabContentsViewWin::ShowContextMenu(const ContextMenuParams& params) {
386 RenderViewContextMenuWin menu(tab_contents(),
387 params,
388 GetNativeView());
389
390 POINT screen_pt = { params.x, params.y };
391 MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_pt, 1);
392
393 // Enable recursive tasks on the message loop so we can get updates while
394 // the context menu is being displayed.
395 bool old_state = MessageLoop::current()->NestableTasksAllowed();
396 MessageLoop::current()->SetNestableTasksAllowed(true);
397 menu.RunMenuAt(screen_pt.x, screen_pt.y);
398 MessageLoop::current()->SetNestableTasksAllowed(old_state);
399 }
400
401 void TabContentsViewWin::OnHScroll(int scroll_type, short position,
402 HWND scrollbar) {
403 ScrollCommon(WM_HSCROLL, scroll_type, position, scrollbar);
404 }
405
406 void TabContentsViewWin::OnMouseLeave() {
407 // Let our delegate know that the mouse moved (useful for resetting status
408 // bubble state).
409 if (tab_contents()->delegate())
410 tab_contents()->delegate()->ContentsMouseEvent(tab_contents(), false);
411 SetMsgHandled(FALSE);
412 }
413
414 LRESULT TabContentsViewWin::OnMouseRange(UINT msg,
415 WPARAM w_param, LPARAM l_param) {
416 switch (msg) {
417 case WM_LBUTTONDOWN:
418 case WM_MBUTTONDOWN:
419 case WM_RBUTTONDOWN: {
420 // Make sure this TabContents is activated when it is clicked on.
421 if (tab_contents()->delegate())
422 tab_contents()->delegate()->ActivateContents(tab_contents());
423 break;
424 }
425 case WM_MOUSEMOVE:
426 // Let our delegate know that the mouse moved (useful for resetting status
427 // bubble state).
428 if (tab_contents()->delegate()) {
429 tab_contents()->delegate()->ContentsMouseEvent(tab_contents(), true);
430 }
431 break;
432 default:
433 break;
434 }
435
436 return 0;
437 }
438
439 void TabContentsViewWin::OnPaint(HDC junk_dc) {
440 if (tab_contents()->render_view_host() &&
441 !tab_contents()->render_view_host()->IsRenderViewLive()) {
442 if (!sad_tab_.get())
443 sad_tab_.reset(new SadTabView);
444 CRect cr;
445 GetClientRect(&cr);
446 sad_tab_->SetBounds(gfx::Rect(cr));
447 gfx::CanvasPaint canvas(GetNativeView(), true);
448 sad_tab_->ProcessPaint(&canvas);
449 return;
450 }
451
452 // We need to do this to validate the dirty area so we don't end up in a
453 // WM_PAINTstorm that causes other mysterious bugs (such as WM_TIMERs not
454 // firing etc). It doesn't matter that we don't have any non-clipped area.
455 CPaintDC dc(GetNativeView());
456 SetMsgHandled(FALSE);
457 }
458
459 // A message is reflected here from view().
460 // Return non-zero to indicate that it is handled here.
461 // Return 0 to allow view() to further process it.
462 LRESULT TabContentsViewWin::OnReflectedMessage(UINT msg, WPARAM w_param,
463 LPARAM l_param) {
464 MSG* message = reinterpret_cast<MSG*>(l_param);
465 switch (message->message) {
466 case WM_MOUSEWHEEL:
467 // This message is reflected from the view() to this window.
468 if (GET_KEYSTATE_WPARAM(message->wParam) & MK_CONTROL) {
469 WheelZoom(GET_WHEEL_DELTA_WPARAM(message->wParam));
470 return 1;
471 }
472 break;
473 case WM_HSCROLL:
474 case WM_VSCROLL:
475 if (ScrollZoom(LOWORD(message->wParam)))
476 return 1;
477 default:
478 break;
479 }
480
481 return 0;
482 }
483
484 void TabContentsViewWin::OnSetFocus(HWND window) {
485 // TODO(jcampan): figure out why removing this prevents tabs opened in the
486 // background from properly taking focus.
487 // We NULL-check the render_view_host_ here because Windows can send us
488 // messages during the destruction process after it has been destroyed.
489 if (tab_contents()->render_widget_host_view()) {
490 HWND inner_hwnd =
491 tab_contents()->render_widget_host_view()->GetNativeView();
492 if (::IsWindow(inner_hwnd))
493 ::SetFocus(inner_hwnd);
494 }
495 }
496
497 void TabContentsViewWin::OnVScroll(int scroll_type, short position,
498 HWND scrollbar) {
499 ScrollCommon(WM_VSCROLL, scroll_type, position, scrollbar);
500 }
501
502 void TabContentsViewWin::OnWindowPosChanged(WINDOWPOS* window_pos) {
503 if (window_pos->flags & SWP_HIDEWINDOW) {
504 WasHidden();
505 } else {
506 // The TabContents was shown by a means other than the user selecting a
507 // Tab, e.g. the window was minimized then restored.
508 if (window_pos->flags & SWP_SHOWWINDOW)
509 WasShown();
510
511 // Unless we were specifically told not to size, cause the renderer to be
512 // sized to the new bounds, which forces a repaint. Not required for the
513 // simple minimize-restore case described above, for example, since the
514 // size hasn't changed.
515 if (!(window_pos->flags & SWP_NOSIZE))
516 WasSized(gfx::Size(window_pos->cx, window_pos->cy));
517 }
518 }
519
520 void TabContentsViewWin::OnSize(UINT param, const CSize& size) {
521 WidgetWin::OnSize(param, size);
522
523 // Hack for thinkpad touchpad driver.
524 // Set fake scrollbars so that we can get scroll messages,
525 SCROLLINFO si = {0};
526 si.cbSize = sizeof(si);
527 si.fMask = SIF_ALL;
528
529 si.nMin = 1;
530 si.nMax = 100;
531 si.nPage = 10;
532 si.nPos = 50;
533
534 ::SetScrollInfo(GetNativeView(), SB_HORZ, &si, FALSE);
535 ::SetScrollInfo(GetNativeView(), SB_VERT, &si, FALSE);
536 }
537
538 LRESULT TabContentsViewWin::OnNCCalcSize(BOOL w_param, LPARAM l_param) {
539 // Hack for thinkpad mouse wheel driver. We have set the fake scroll bars
540 // to receive scroll messages from thinkpad touchpad driver. Suppress
541 // painting of scrollbars by returning 0 size for them.
542 return 0;
543 }
544
545 void TabContentsViewWin::OnNCPaint(HRGN rgn) {
546 // Suppress default WM_NCPAINT handling. We don't need to do anything
547 // here since the view will draw everything correctly.
548 }
549
550 void TabContentsViewWin::ScrollCommon(UINT message, int scroll_type,
551 short position, HWND scrollbar) {
552 // This window can receive scroll events as a result of the ThinkPad's
553 // Trackpad scroll wheel emulation.
554 if (!ScrollZoom(scroll_type)) {
555 // Reflect scroll message to the view() to give it a chance
556 // to process scrolling.
557 SendMessage(GetContentNativeView(), message,
558 MAKELONG(scroll_type, position),
559 reinterpret_cast<LPARAM>(scrollbar));
560 }
561 }
562
563 void TabContentsViewWin::WasHidden() {
564 tab_contents()->HideContents();
565 }
566
567 void TabContentsViewWin::WasShown() {
568 tab_contents()->ShowContents();
569 }
570
571 void TabContentsViewWin::WasSized(const gfx::Size& size) {
572 if (tab_contents()->interstitial_page())
573 tab_contents()->interstitial_page()->SetSize(size);
574 if (tab_contents()->render_widget_host_view())
575 tab_contents()->render_widget_host_view()->SetSize(size);
576
577 // TODO(brettw) this function can probably be moved to this class.
578 tab_contents()->RepositionSupressedPopupsToFit();
579 }
580
581 bool TabContentsViewWin::ScrollZoom(int scroll_type) {
582 // If ctrl is held, zoom the UI. There are three issues with this:
583 // 1) Should the event be eaten or forwarded to content? We eat the event,
584 // which is like Firefox and unlike IE.
585 // 2) Should wheel up zoom in or out? We zoom in (increase font size), which
586 // is like IE and Google maps, but unlike Firefox.
587 // 3) Should the mouse have to be over the content area? We zoom as long as
588 // content has focus, although FF and IE require that the mouse is over
589 // content. This is because all events get forwarded when content has
590 // focus.
591 if (GetAsyncKeyState(VK_CONTROL) & 0x8000) {
592 int distance = 0;
593 switch (scroll_type) {
594 case SB_LINEUP:
595 distance = WHEEL_DELTA;
596 break;
597 case SB_LINEDOWN:
598 distance = -WHEEL_DELTA;
599 break;
600 // TODO(joshia): Handle SB_PAGEUP, SB_PAGEDOWN, SB_THUMBPOSITION,
601 // and SB_THUMBTRACK for completeness
602 default:
603 break;
604 }
605
606 WheelZoom(distance);
607 return true;
608 }
609 return false;
610 }
611
612 void TabContentsViewWin::WheelZoom(int distance) {
613 if (tab_contents()->delegate()) {
614 bool zoom_in = distance > 0;
615 tab_contents()->delegate()->ContentsZoomChange(zoom_in);
616 }
617 }
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/views/tab_contents/tab_contents_view_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698