diff options
author | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-10 20:34:35 +0000 |
---|---|---|
committer | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-10 20:34:35 +0000 |
commit | c80c563f3f32e49ce0087d899accf6a77de09ba6 (patch) | |
tree | 17f56be64796b691c7d323e08120acdac0e43d9f /chrome/browser/web_contents_view_win.cc | |
parent | b5108d1892eeb184b2679ce0658f5fe708e22016 (diff) | |
download | chromium_src-c80c563f3f32e49ce0087d899accf6a77de09ba6.zip chromium_src-c80c563f3f32e49ce0087d899accf6a77de09ba6.tar.gz chromium_src-c80c563f3f32e49ce0087d899accf6a77de09ba6.tar.bz2 |
Start splitting out view-related stuff from WebContents into a new class WebContentsViewWin, accessed through an abstract interface WebContentsView. This is incomplete but is a good start. There are still a bunch of pass-throughs required for the TabContents overrides. These won't be able to be cleaned up until we kill TabContents.
Review URL: http://codereview.chromium.org/7205
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3243 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/web_contents_view_win.cc')
-rw-r--r-- | chrome/browser/web_contents_view_win.cc | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/chrome/browser/web_contents_view_win.cc b/chrome/browser/web_contents_view_win.cc new file mode 100644 index 0000000..6078b94 --- /dev/null +++ b/chrome/browser/web_contents_view_win.cc @@ -0,0 +1,351 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_contents_view_win.h" + +#include <windows.h> + +#include "chrome/browser/find_in_page_controller.h" +#include "chrome/browser/render_view_host.h" +#include "chrome/browser/render_widget_host_hwnd.h" +#include "chrome/browser/tab_contents_delegate.h" +#include "chrome/browser/views/sad_tab_view.h" +#include "chrome/browser/web_contents.h" +#include "chrome/browser/web_drag_source.h" +#include "chrome/browser/web_drop_target.h" +#include "chrome/common/gfx/chrome_canvas.h" +#include "chrome/common/os_exchange_data.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" + +namespace { + +// Windows callback for DetachPluginWindows. +BOOL CALLBACK EnumPluginWindowsCallback(HWND window, LPARAM param) { + if (WebPluginDelegateImpl::IsPluginDelegateWindow(window)) { + ::ShowWindow(window, SW_HIDE); + SetParent(window, NULL); + } + return TRUE; +} + +} // namespace + +WebContentsViewWin::WebContentsViewWin(WebContents* web_contents) + : web_contents_(web_contents), + info_bar_visible_(false) { +} + +WebContentsViewWin::~WebContentsViewWin() { +} + +void WebContentsViewWin::CreateView(HWND parent_hwnd, + const gfx::Rect& initial_bounds) { + set_delete_on_destroy(false); + HWNDViewContainer::Init(parent_hwnd, initial_bounds, false); + + // Remove the root view drop target so we can register our own. + RevokeDragDrop(GetHWND()); + drop_target_ = new WebDropTarget(GetHWND(), web_contents_); +} + +RenderWidgetHostHWND* WebContentsViewWin::CreatePageView( + RenderViewHost* render_view_host) { + // Create the View as well. Its lifetime matches the child process'. + DCHECK(!render_view_host->view()); + RenderWidgetHostHWND* view = new RenderWidgetHostHWND(render_view_host); + render_view_host->set_view(view); + view->Create(GetHWND()); + view->ShowWindow(SW_SHOW); + return view; +} + +HWND WebContentsViewWin::GetContainerHWND() const { + return GetHWND(); +} + +HWND WebContentsViewWin::GetContentHWND() const { + if (!web_contents_->view()) + return NULL; + return web_contents_->view()->GetPluginHWND(); +} + +void WebContentsViewWin::GetContainerBounds(gfx::Rect *out) const { + CRect r; + GetBounds(&r, false); + *out = r; +} + +void WebContentsViewWin::StartDragging(const WebDropData& drop_data) { + scoped_refptr<OSExchangeData> data(new OSExchangeData); + + // TODO(tc): Generate an appropriate drag image. + + // We set the file contents before the URL because the URL also sets file + // contents (to a .URL shortcut). We want to prefer file content data over a + // shortcut. + if (!drop_data.file_contents.empty()) { + data->SetFileContents(drop_data.file_description_filename, + drop_data.file_contents); + } + if (!drop_data.cf_html.empty()) + data->SetCFHtml(drop_data.cf_html); + if (drop_data.url.is_valid()) + data->SetURL(drop_data.url, drop_data.url_title); + if (!drop_data.plain_text.empty()) + data->SetString(drop_data.plain_text); + + scoped_refptr<WebDragSource> drag_source( + new WebDragSource(GetHWND(), web_contents_->render_view_host())); + + DWORD effects; + + // We need to enable recursive tasks on the message loop so we can get + // updates while in the system DoDragDrop loop. + bool old_state = MessageLoop::current()->NestableTasksAllowed(); + MessageLoop::current()->SetNestableTasksAllowed(true); + DoDragDrop(data, drag_source, DROPEFFECT_COPY | DROPEFFECT_LINK, &effects); + MessageLoop::current()->SetNestableTasksAllowed(old_state); + + if (web_contents_->render_view_host()) + web_contents_->render_view_host()->DragSourceSystemDragEnded(); +} + +void WebContentsViewWin::DetachPluginWindows() { + EnumChildWindows(GetHWND(), EnumPluginWindowsCallback, NULL); +} + +void WebContentsViewWin::OnDestroy() { + if (drop_target_.get()) { + RevokeDragDrop(GetHWND()); + drop_target_ = NULL; + } +} + +void WebContentsViewWin::SetInfoBarVisible(bool visible) { + if (info_bar_visible_ != visible) { + info_bar_visible_ = visible; + if (info_bar_visible_) { + // Invoke GetInfoBarView to force the info bar to be created. + GetInfoBarView(); + } + web_contents_->ToolbarSizeChanged(false); + } +} + +bool WebContentsViewWin::IsInfoBarVisible() const { + return info_bar_visible_; +} + +InfoBarView* WebContentsViewWin::GetInfoBarView() { + if (info_bar_view_.get() == NULL) { + info_bar_view_.reset(new InfoBarView(web_contents_)); + // The WebContents owns the info-bar. + info_bar_view_->SetParentOwned(false); + } + return info_bar_view_.get(); +} + +void WebContentsViewWin::UpdateDragCursor(bool is_drop_target) { + drop_target_->set_is_drop_target(is_drop_target); +} + +void WebContentsViewWin::OnHScroll(int scroll_type, short position, HWND scrollbar) { + ScrollCommon(WM_HSCROLL, scroll_type, position, scrollbar); +} + +void WebContentsViewWin::OnMouseLeave() { + // Let our delegate know that the mouse moved (useful for resetting status + // bubble state). + if (web_contents_->delegate()) + web_contents_->delegate()->ContentsMouseEvent(web_contents_, WM_MOUSELEAVE); + SetMsgHandled(FALSE); +} + +LRESULT WebContentsViewWin::OnMouseRange(UINT msg, WPARAM w_param, LPARAM l_param) { + switch (msg) { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + // Make sure this TabContents is activated when it is clicked on. + if (web_contents_->delegate()) + web_contents_->delegate()->ActivateContents(web_contents_); + break; + case WM_MOUSEMOVE: + // Let our delegate know that the mouse moved (useful for resetting status + // bubble state). + if (web_contents_->delegate()) + web_contents_->delegate()->ContentsMouseEvent(web_contents_, WM_MOUSEMOVE); + break; + default: + break; + } + + return 0; +} + +void WebContentsViewWin::OnPaint(HDC junk_dc) { + if (web_contents_->render_view_host() && + !web_contents_->render_view_host()->IsRenderViewLive()) { + if (!web_contents_->sad_tab_.get()) + web_contents_->sad_tab_.reset(new SadTabView); + CRect cr; + GetClientRect(&cr); + web_contents_->sad_tab_->SetBounds(cr); + ChromeCanvasPaint canvas(GetHWND(), true); + web_contents_->sad_tab_->ProcessPaint(&canvas); + return; + } + + // We need to do this to validate the dirty area so we don't end up in a + // WM_PAINTstorm that causes other mysterious bugs (such as WM_TIMERs not + // firing etc). It doesn't matter that we don't have any non-clipped area. + CPaintDC dc(GetHWND()); + SetMsgHandled(FALSE); +} + +// A message is reflected here from view(). +// Return non-zero to indicate that it is handled here. +// Return 0 to allow view() to further process it. +LRESULT WebContentsViewWin::OnReflectedMessage(UINT msg, WPARAM w_param, + LPARAM l_param) { + MSG* message = reinterpret_cast<MSG*>(l_param); + switch (message->message) { + case WM_MOUSEWHEEL: + // This message is reflected from the view() to this window. + if (GET_KEYSTATE_WPARAM(message->wParam) & MK_CONTROL) { + WheelZoom(GET_WHEEL_DELTA_WPARAM(message->wParam)); + return 1; + } + break; + case WM_HSCROLL: + case WM_VSCROLL: + if (ScrollZoom(LOWORD(message->wParam))) + return 1; + default: + break; + } + + return 0; +} + +void WebContentsViewWin::OnSetFocus(HWND window) { + // TODO(jcampan): figure out why removing this prevents tabs opened in the + // background from properly taking focus. + // We NULL-check the render_view_host_ here because Windows can send us + // messages during the destruction process after it has been destroyed. + if (web_contents_->view()) { + HWND inner_hwnd = web_contents_->view()->GetPluginHWND(); + if (::IsWindow(inner_hwnd)) + ::SetFocus(inner_hwnd); + } +} + +void WebContentsViewWin::OnVScroll(int scroll_type, short position, HWND scrollbar) { + ScrollCommon(WM_VSCROLL, scroll_type, position, scrollbar); +} + +void WebContentsViewWin::OnWindowPosChanged(WINDOWPOS* window_pos) { + if (window_pos->flags & SWP_HIDEWINDOW) { + web_contents_->HideContents(); + } else { + // The WebContents was shown by a means other than the user selecting a + // Tab, e.g. the window was minimized then restored. + if (window_pos->flags & SWP_SHOWWINDOW) + web_contents_->ShowContents(); + // Unless we were specifically told not to size, cause the renderer to be + // sized to the new bounds, which forces a repaint. Not required for the + // simple minimize-restore case described above, for example, since the + // size hasn't changed. + if (!(window_pos->flags & SWP_NOSIZE)) { + gfx::Size size(window_pos->cx, window_pos->cy); + web_contents_->SizeContents(size); // FIXME(brettw) should this be on this class? + } + + // If we have a FindInPage dialog, notify it that the window changed. + if (web_contents_->find_in_page_controller_.get() && + web_contents_->find_in_page_controller_->IsVisible()) + web_contents_->find_in_page_controller_->MoveWindowIfNecessary(gfx::Rect()); + } +} + +void WebContentsViewWin::OnSize(UINT param, const CSize& size) { + HWNDViewContainer::OnSize(param, size); + + // Hack for thinkpad touchpad driver. + // Set fake scrollbars so that we can get scroll messages, + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + + si.nMin = 1; + si.nMax = 100; + si.nPage = 10; + si.nTrackPos = 50; + + ::SetScrollInfo(GetHWND(), SB_HORZ, &si, FALSE); + ::SetScrollInfo(GetHWND(), SB_VERT, &si, FALSE); +} + +LRESULT WebContentsViewWin::OnNCCalcSize(BOOL w_param, LPARAM l_param) { + // Hack for thinkpad mouse wheel driver. We have set the fake scroll bars + // to receive scroll messages from thinkpad touchpad driver. Suppress + // painting of scrollbars by returning 0 size for them. + return 0; +} + +void WebContentsViewWin::OnNCPaint(HRGN rgn) { + // Suppress default WM_NCPAINT handling. We don't need to do anything + // here since the view will draw everything correctly. +} + +void WebContentsViewWin::ScrollCommon(UINT message, int scroll_type, short position, + HWND scrollbar) { + // This window can receive scroll events as a result of the ThinkPad's + // Trackpad scroll wheel emulation. + if (!ScrollZoom(scroll_type)) { + // Reflect scroll message to the view() to give it a chance + // to process scrolling. + SendMessage(GetContentHWND(), message, MAKELONG(scroll_type, position), + (LPARAM) scrollbar); + } +} + +bool WebContentsViewWin::ScrollZoom(int scroll_type) { + // If ctrl is held, zoom the UI. There are three issues with this: + // 1) Should the event be eaten or forwarded to content? We eat the event, + // which is like Firefox and unlike IE. + // 2) Should wheel up zoom in or out? We zoom in (increase font size), which + // is like IE and Google maps, but unlike Firefox. + // 3) Should the mouse have to be over the content area? We zoom as long as + // content has focus, although FF and IE require that the mouse is over + // content. This is because all events get forwarded when content has + // focus. + if (GetAsyncKeyState(VK_CONTROL) & 0x8000) { + int distance = 0; + switch (scroll_type) { + case SB_LINEUP: + distance = WHEEL_DELTA; + break; + case SB_LINEDOWN: + distance = -WHEEL_DELTA; + break; + // TODO(joshia): Handle SB_PAGEUP, SB_PAGEDOWN, SB_THUMBPOSITION, + // and SB_THUMBTRACK for completeness + default: + break; + } + + WheelZoom(distance); + return true; + } + return false; +} + +void WebContentsViewWin::WheelZoom(int distance) { + if (web_contents_->delegate()) { + bool zoom_in = distance > 0; + web_contents_->delegate()->ContentsZoomChange(zoom_in); + } +} + |