diff options
author | mad@chromium.org <mad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-09 20:10:17 +0000 |
---|---|---|
committer | mad@chromium.org <mad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-09 20:10:17 +0000 |
commit | c3826037cbcb22fe784a10589061eaf084818727 (patch) | |
tree | 58da3c893c97e0fd5fee5df93f3dc30db7b93a40 /chrome/browser/renderer_host | |
parent | b595ba77947ee0881ae8ce16ee92b47d1c48f10a (diff) | |
download | chromium_src-c3826037cbcb22fe784a10589061eaf084818727.zip chromium_src-c3826037cbcb22fe784a10589061eaf084818727.tar.gz chromium_src-c3826037cbcb22fe784a10589061eaf084818727.tar.bz2 |
Add a new resizer corner.
To display a resize bitmap and handle the mouse interactions as requested in
http://code.google.com/p/chromium/issues/detail?id=458.
BUG=458
There are unfortunately two cases to handle and they must be handled separately.
The first one is when there are no bottom shelf like the download bar,
and the case where there is one.
For the case without, we must draw on top of what we receive from WebKit,
so we intercept the bitmap in RenderWidgetHostViewWin::OnPaint() so that we
can draw the resize corner bitmap on top of it (taking into account whether
we are in a right to left language or not).
For the case where we have a bottom shelf, we use a dedicated view that we
properly layout on top of the bottom shelf view (which takes care of handling
the RTL language case for us).
Same split for the mouse interactions. Without the bottom shelf, we must deal
with it in RenderWidgetHostViewWin::OnMouseEvent() by sending the root window
a WM_NCLBUTTONDOWN message with either HTBOTTOMRIGHT or HTBOTTOMLEFT (based on
the RTL setting) and let the OS take care of the resizing. IF we have a bottom
shelf, we must deal with the mouse interaction in
BrowserView::NonClientHitTest()
to either return HTBOTTOMRIGHT or HTBOTTOMLEFT (again, based on the RTL setting)
and, again, let the OS take care of the resizing.
More details here:
http://code.google.com/p/chromium/wiki/BrowserViewResizer
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9408 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/renderer_host')
9 files changed, 113 insertions, 37 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index e244c83..cf9be2d 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -150,7 +150,8 @@ bool RenderViewHost::CreateRenderView() { SYNCHRONIZE, FALSE, 0); - DCHECK(result) << "Couldn't duplicate the modal dialog handle for the renderer."; + DCHECK(result) << + "Couldn't duplicate the modal dialog handle for the renderer."; #endif DCHECK(view()); @@ -308,7 +309,7 @@ void RenderViewHost::ClosePage(int new_render_process_host_id, } } -void RenderViewHost::SetHasPendingCrossSiteRequest(bool has_pending_request, +void RenderViewHost::SetHasPendingCrossSiteRequest(bool has_pending_request, int request_id) { Singleton<CrossSiteRequestManager>()->SetHasPendingCrossSiteRequest( process()->host_id(), routing_id(), has_pending_request); @@ -382,7 +383,8 @@ void RenderViewHost::DragTargetDragEnter(const WebDropData& drop_data, // Grant the renderer the ability to load the drop_data. RendererSecurityPolicy* policy = RendererSecurityPolicy::GetInstance(); policy->GrantRequestURL(process()->host_id(), drop_data.url); - for (std::vector<std::wstring>::const_iterator iter(drop_data.filenames.begin()); + for (std::vector<std::wstring>::const_iterator + iter(drop_data.filenames.begin()); iter != drop_data.filenames.end(); ++iter) { policy->GrantRequestURL(process()->host_id(), net::FilePathToFileURL(*iter)); @@ -515,7 +517,8 @@ void RenderViewHost::JavaScriptMessageBoxClosed(IPC::Message* reply_msg, if (--modal_dialog_count_ == 0) modal_dialog_event_->Reset(); - ViewHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg, success, prompt); + ViewHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg, + success, prompt); Send(reply_msg); } @@ -572,7 +575,8 @@ void RenderViewHost::AllowDomAutomationBindings() { void RenderViewHost::AllowDOMUIBindings() { DCHECK(!renderer_initialized_); enable_dom_ui_bindings_ = true; - RendererSecurityPolicy::GetInstance()->GrantDOMUIBindings(process()->host_id()); + RendererSecurityPolicy::GetInstance()->GrantDOMUIBindings( + process()->host_id()); } void RenderViewHost::AllowExternalHostBindings() { @@ -936,7 +940,8 @@ void RenderViewHost::OnMsgDidStartProvisionalLoadForFrame(bool is_main_frame, FilterURL(RendererSecurityPolicy::GetInstance(), process()->host_id(), &validated_url); - delegate_->DidStartProvisionalLoadForFrame(this, is_main_frame, validated_url); + delegate_->DidStartProvisionalLoadForFrame(this, is_main_frame, + validated_url); } void RenderViewHost::OnMsgDidFailProvisionalLoadWithError( @@ -1273,6 +1278,10 @@ void RenderViewHost::NotifyRendererResponsive() { delegate_->RendererResponsive(this); } +gfx::Rect RenderViewHost::GetRootWindowResizerRect() const { + return delegate_->GetRootWindowResizerRect(); +} + void RenderViewHost::OnDebugDisconnect() { if (debugger_attached_) { debugger_attached_ = false; diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 2cd9d29..9d0bb37 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -410,6 +410,7 @@ class RenderViewHost : public RenderWidgetHost { virtual bool IsRenderView() { return true; } virtual void OnMessageReceived(const IPC::Message& msg); virtual bool CanBlur() const; + virtual gfx::Rect GetRootWindowResizerRect() const; protected: // RenderWidgetHost protected overrides. diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index f048dc2..b701b21 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/file_path.h" +#include "base/gfx/rect.h" #include "base/logging.h" #include "net/base/load_states.h" #include "webkit/glue/password_form.h" @@ -38,10 +39,6 @@ namespace IPC { class Message; } -namespace gfx { -class Rect; -} - namespace webkit_glue { struct WebApplicationInfo; } @@ -301,13 +298,13 @@ class RenderViewHostDelegate { // Forms fillable by autofill have been detected in the page. virtual void AutofillFormSubmitted(const AutofillForm& form) { } - // Called to retrieve a list of suggestions from the web database given + // Called to retrieve a list of suggestions from the web database given // the name of the field |field_name| and what the user has already typed in // the field |user_text|. Appeals to the database thead to perform the query. // When the database thread is finished, the autofill manager retrieves the // calling RenderViewHost and then passes the vector of suggestions to // RenderViewHost::AutofillSuggestionsReturned. - virtual void GetAutofillSuggestions(const std::wstring& field_name, + virtual void GetAutofillSuggestions(const std::wstring& field_name, const std::wstring& user_text, int64 node_id, int request_id) { } @@ -372,9 +369,13 @@ class RenderViewHostDelegate { // blurred. virtual bool CanBlur() const { return true; } + // Return the rect where to display the resize corner, if any, otherwise + // an empty rect. + virtual gfx::Rect GetRootWindowResizerRect() const { return gfx::Rect(); } + // Notification that the renderer has become unresponsive. The // delegate can use this notification to show a warning to the user. - virtual void RendererUnresponsive(RenderViewHost* render_view_host, + virtual void RendererUnresponsive(RenderViewHost* render_view_host, bool is_during_unload) { } // Notification that a previously unresponsive renderer has become diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index a6d289b..e196a00 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -164,7 +164,8 @@ void RenderWidgetHost::WasResized() { if (!new_size.IsEmpty()) resize_ack_pending_ = true; - if (!Send(new ViewMsg_Resize(routing_id_, new_size))) + if (!Send(new ViewMsg_Resize(routing_id_, new_size, + GetRootWindowResizerRect()))) resize_ack_pending_ = false; } @@ -330,6 +331,10 @@ void RenderWidgetHost::RendererExited() { BackingStoreManager::RemoveBackingStore(this); } +gfx::Rect RenderWidgetHost::GetRootWindowResizerRect() const { + return gfx::Rect(); +} + void RenderWidgetHost::Destroy() { NotificationService::current()->Notify( NotificationType::RENDER_WIDGET_HOST_DESTROYED, diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h index 4bd1849..48fc912 100644 --- a/chrome/browser/renderer_host/render_widget_host.h +++ b/chrome/browser/renderer_host/render_widget_host.h @@ -205,6 +205,10 @@ class RenderWidgetHost : public IPC::Channel::Listener { void ForwardKeyboardEvent(const WebKeyboardEvent& key_event); void ForwardInputEvent(const WebInputEvent& input_event, int event_size); + // This is for derived classes to give us access to the resizer rect. + // And to also expose it to the RenderWidgetHostView. + virtual gfx::Rect GetRootWindowResizerRect() const; + protected: // Called when we receive a notification indicating that the renderer // process has gone. This will reset our state so that our state will be diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc index b499669..65a3921 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -20,12 +20,15 @@ #include "chrome/common/l10n_util.h" #include "chrome/common/plugin_messages.h" #include "chrome/common/render_messages.h" +#include "chrome/common/resource_bundle.h" #include "chrome/common/win_util.h" // Included for views::kReflectedMessage - TODO(beng): move this to win_util.h! #include "chrome/views/widget_win.h" #include "webkit/glue/plugins/plugin_constants_win.h" #include "webkit/glue/plugins/webplugin_delegate_impl.h" #include "webkit/glue/webcursor.h" +#include "webkit_resources.h" + using base::TimeDelta; using base::TimeTicks; @@ -243,28 +246,40 @@ void RenderWidgetHostViewWin::UpdateCursor(const WebCursor& cursor) { } void RenderWidgetHostViewWin::UpdateCursorIfOverSelf() { + static HCURSOR kCursorResizeRight = LoadCursor(NULL, IDC_SIZENWSE); + static HCURSOR kCursorResizeLeft = LoadCursor(NULL, IDC_SIZENESW); static HCURSOR kCursorArrow = LoadCursor(NULL, IDC_ARROW); static HCURSOR kCursorAppStarting = LoadCursor(NULL, IDC_APPSTARTING); static HINSTANCE module_handle = GetModuleHandle(chrome::kBrowserResourcesDll); - // We cannot pass in NULL as the module handle as this would only work for - // standard win32 cursors. We can also receive cursor types which are defined - // as webkit resources. We need to specify the module handle of chrome.dll - // while loading these cursors. - HCURSOR display_cursor = current_cursor_.GetCursor(module_handle); - - // If a page is in the loading state, we want to show the Arrow+Hourglass - // cursor only when the current cursor is the ARROW cursor. In all other - // cases we should continue to display the current cursor. - if (is_loading_ && display_cursor == kCursorArrow) - display_cursor = kCursorAppStarting; - // If the mouse is over our HWND, then update the cursor state immediately. CPoint pt; GetCursorPos(&pt); - if (WindowFromPoint(pt) == m_hWnd) - SetCursor(display_cursor); + if (WindowFromPoint(pt) == m_hWnd) { + BOOL result = ::ScreenToClient(m_hWnd, &pt); + DCHECK(result); + if (render_widget_host_->GetRootWindowResizerRect().Contains(pt.x, pt.y)) { + if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) + SetCursor(kCursorResizeLeft); + else + SetCursor(kCursorResizeRight); + } else { + // We cannot pass in NULL as the module handle as this would only work for + // standard win32 cursors. We can also receive cursor types which are + // defined as webkit resources. We need to specify the module handle of + // chrome.dll while loading these cursors. + HCURSOR display_cursor = current_cursor_.GetCursor(module_handle); + + // If a page is in the loading state, we want to show the Arrow+Hourglass + // cursor only when the current cursor is the ARROW cursor. In all other + // cases we should continue to display the current cursor. + if (is_loading_ && display_cursor == kCursorArrow) + display_cursor = kCursorAppStarting; + + SetCursor(display_cursor); + } + } } void RenderWidgetHostViewWin::SetIsLoading(bool is_loading) { @@ -322,6 +337,37 @@ void RenderWidgetHostViewWin::Redraw(const gfx::Rect& rect) { EnumChildWindows(m_hWnd, EnumChildProc, lparam); } +void RenderWidgetHostViewWin::DrawResizeCorner(const gfx::Rect& paint_rect, + HDC dc) { + gfx::Rect resize_corner_rect = + render_widget_host_->GetRootWindowResizerRect(); + if (!paint_rect.Intersect(resize_corner_rect).IsEmpty()) { + SkBitmap* bitmap = ResourceBundle::GetSharedInstance(). + GetBitmapNamed(IDR_TEXTAREA_RESIZER); + ChromeCanvas canvas(bitmap->width(), bitmap->height(), false); + // TODO(jcampan): This const_cast should not be necessary once the + // SKIA API has been changed to return a non-const bitmap. + const_cast<SkBitmap&>(canvas.getDevice()->accessBitmap(true)). + eraseARGB(0, 0, 0, 0); + int x = resize_corner_rect.x() + resize_corner_rect.width() - + bitmap->width(); + bool rtl_dir = (l10n_util::GetTextDirection() == + l10n_util::RIGHT_TO_LEFT); + if (rtl_dir) { + canvas.TranslateInt(bitmap->width(), 0); + canvas.ScaleInt(-1, 1); + canvas.save(); + x = 0; + } + canvas.DrawBitmapInt(*bitmap, 0, 0); + canvas.getTopPlatformDevice().drawToHDC(dc, x, + resize_corner_rect.y() + resize_corner_rect.height() - + bitmap->height(), NULL); + if (rtl_dir) + canvas.restore(); + } +} + void RenderWidgetHostViewWin::DidPaintRect(const gfx::Rect& rect) { if (is_hidden_) return; @@ -434,6 +480,7 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) { gfx::Rect paint_rect = bitmap_rect.Intersect(damaged_rect); if (!paint_rect.IsEmpty()) { + DrawResizeCorner(paint_rect, backing_store->hdc()); BitBlt(paint_dc.m_hDC, paint_rect.x(), paint_rect.y(), @@ -722,6 +769,20 @@ LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam, // call). So the WebContents window would have to be specified to the // RenderViewHostHWND as there is no way to retrieve it from the HWND. if (!close_on_deactivate_) { // Don't forward if the container is a popup. + if (message == WM_LBUTTONDOWN) { + // If we get clicked on, where the resize corner is drawn, we delegate the + // message to the root window, with the proper HTBOTTOMXXX wparam so that + // Windows can take care of the resizing for us. + if (render_widget_host_->GetRootWindowResizerRect(). + Contains(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam))) { + WPARAM wparam = HTBOTTOMRIGHT; + if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) + wparam = HTBOTTOMLEFT; + HWND root_hwnd = ::GetAncestor(m_hWnd, GA_ROOT); + if (SendMessage(root_hwnd, WM_NCLBUTTONDOWN, wparam, lparam) == 0) + return 0; + } + } switch (message) { case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h index ec1547a..167f529 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -213,6 +213,10 @@ class RenderWidgetHostViewWin : // asynchronously. void Redraw(const gfx::Rect& invalid_rect); + // Draw the resize corner bitmap on top of the given HDC, if it intersects the + // given paint rect. + void DrawResizeCorner(const gfx::Rect& paint_rect, HDC dc); + // The associated Model. RenderWidgetHost* render_widget_host_; diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 2db7124..51c4875 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -205,8 +205,6 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { #if defined(OS_WIN) IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowRect, OnGetWindowRect) IPC_MESSAGE_HANDLER(ViewHostMsg_GetRootWindowRect, OnGetRootWindowRect) - IPC_MESSAGE_HANDLER(ViewHostMsg_GetRootWindowResizerRect, - OnGetRootWindowResizerRect) #endif IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromExtension, OnGetMimeTypeFromExtension) @@ -541,12 +539,6 @@ void ResourceMessageFilter::OnGetRootWindowRect(gfx::NativeViewId window_id, *rect = window_rect; } -void ResourceMessageFilter::OnGetRootWindowResizerRect(gfx::NativeViewId window, - gfx::Rect* rect) { - RECT window_rect = {0}; - *rect = window_rect; -} - #endif // OS_WIN void ResourceMessageFilter::OnGetMimeTypeFromExtension( diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index c4d75e3..7bb8090 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -150,7 +150,6 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, #if defined(OS_WIN) void OnGetWindowRect(gfx::NativeViewId window, gfx::Rect *rect); void OnGetRootWindowRect(gfx::NativeViewId window, gfx::Rect *rect); - void OnGetRootWindowResizerRect(gfx::NativeViewId window, gfx::Rect *rect); #endif void OnGetMimeTypeFromExtension(const std::wstring& ext, std::string* mime_type); |