summaryrefslogtreecommitdiffstats
path: root/chrome/browser/web_contents_view_win.cc
diff options
context:
space:
mode:
authorbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-10 20:34:35 +0000
committerbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-10 20:34:35 +0000
commitc80c563f3f32e49ce0087d899accf6a77de09ba6 (patch)
tree17f56be64796b691c7d323e08120acdac0e43d9f /chrome/browser/web_contents_view_win.cc
parentb5108d1892eeb184b2679ce0658f5fe708e22016 (diff)
downloadchromium_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.cc351
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);
+ }
+}
+