diff options
7 files changed, 99 insertions, 47 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index a8b7ad4..03251ec 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -945,14 +945,10 @@ void RenderViewHost::OnMsgDidRedirectProvisionalLoad(int32 page_id, void RenderViewHost::OnMsgDidStartLoading(int32 page_id) { delegate_->DidStartLoading(this, page_id); - if (view()) - view()->UpdateCursorIfOverSelf(); } void RenderViewHost::OnMsgDidStopLoading(int32 page_id) { delegate_->DidStopLoading(this, page_id); - if (view()) - view()->UpdateCursorIfOverSelf(); } void RenderViewHost::OnMsgDidLoadResourceFromMemoryCache( diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h index 0779e5f..7d24eec 100644 --- a/chrome/browser/renderer_host/render_widget_host_view.h +++ b/chrome/browser/renderer_host/render_widget_host_view.h @@ -84,9 +84,6 @@ class RenderWidgetHostView { // Sets the cursor to the one associated with the specified cursor_type virtual void UpdateCursor(const WebCursor& cursor) = 0; - // Updates the displayed cursor to the current one. - virtual void UpdateCursorIfOverSelf() = 0; - // Indicates whether the page has finished loading. virtual void SetIsLoading(bool is_loading) = 0; diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc index ff9c68f..8f18af1 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -18,6 +18,8 @@ namespace { +#include "webkit/glue/webcursor_gtk_data.h" + // This class is a simple convenience wrapper for Gtk functions. It has only // static methods. class RenderWidgetHostViewGtkWidget { @@ -147,7 +149,8 @@ RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host) parent_host_view_(NULL), parent_(NULL), popup_signal_id_(0), - activatable_(true) { + activatable_(true), + is_loading_(false) { host_->set_view(this); } @@ -241,46 +244,22 @@ gfx::Rect RenderWidgetHostViewGtk::GetViewBounds() const { } void RenderWidgetHostViewGtk::UpdateCursor(const WebCursor& cursor) { - // TODO(port): some of this logic may need moving to UpdateCursorIfOverSelf at - // some point. - GdkCursorType current_cursor_type = current_cursor_.GetCursorType(); - GdkCursorType new_cursor_type = cursor.GetCursorType(); - current_cursor_ = cursor; - GdkCursor* gdk_cursor; - if (new_cursor_type == GDK_CURSOR_IS_PIXMAP) { - // TODO(port): WebKit bug https://bugs.webkit.org/show_bug.cgi?id=16388 is - // that calling gdk_window_set_cursor repeatedly is expensive. We should - // avoid it here where possible. - gdk_cursor = current_cursor_.GetCustomCursor(); - } else { - // Optimize the common case, where the cursor hasn't changed. - // However, we can switch between different pixmaps, so only on the - // non-pixmap branch. - if (new_cursor_type == current_cursor_type) - return; - if (new_cursor_type == GDK_LAST_CURSOR) - gdk_cursor = NULL; - else - gdk_cursor = gdk_cursor_new(new_cursor_type); - } - gdk_window_set_cursor(view_.get()->window, gdk_cursor); - // The window now owns the cursor. - if (gdk_cursor) - gdk_cursor_unref(gdk_cursor); -} + // Optimize the common case, where the cursor hasn't changed. + // However, we can switch between different pixmaps, so only on the + // non-pixmap branch. + if (current_cursor_.GetCursorType() != GDK_CURSOR_IS_PIXMAP && + current_cursor_.GetCursorType() == cursor.GetCursorType()) + return; -void RenderWidgetHostViewGtk::UpdateCursorIfOverSelf() { - // Windows uses this to show the resizer arrow if the mouse is over the - // bottom-right corner, which doesn't make sense for us. - // It also uses it to show the "loading" cursor, which we ought to do. - // That is bug 9385: - // http://code.google.com/p/chromium/issues/detail?id=9385 + current_cursor_ = cursor; + ShowCurrentCursor(); } void RenderWidgetHostViewGtk::SetIsLoading(bool is_loading) { - // Windows tracks loading whether it's loading to switch the cursor - // out for the arrow+hourglass one. - // http://code.google.com/p/chromium/issues/detail?id=9385 + is_loading_ = is_loading; + // Only call ShowCurrentCursor() when it will actually change the cursor. + if (current_cursor_.GetCursorType() == GDK_LAST_CURSOR) + ShowCurrentCursor(); } void RenderWidgetHostViewGtk::IMEUpdateStatus(int control, @@ -357,3 +336,40 @@ void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) { NOTIMPLEMENTED(); } } + +void RenderWidgetHostViewGtk::ShowCurrentCursor() { + GdkCursor* gdk_cursor; + switch(current_cursor_.GetCursorType()) { + case GDK_CURSOR_IS_PIXMAP: + // TODO(port): WebKit bug https://bugs.webkit.org/show_bug.cgi?id=16388 is + // that calling gdk_window_set_cursor repeatedly is expensive. We should + // avoid it here where possible. + gdk_cursor = current_cursor_.GetCustomCursor(); + break; + + case GDK_LAST_CURSOR: + if (is_loading_) { + // Use MOZ_CURSOR_SPINNING if we are showing the default cursor and + // the page is loading. + static const GdkColor fg = { 0, 0, 0, 0 }; + static const GdkColor bg = { 65535, 65535, 65535, 65535 }; + GdkPixmap* source = + gdk_bitmap_create_from_data(NULL, moz_spinning_bits, 32, 32); + GdkPixmap* mask = + gdk_bitmap_create_from_data(NULL, moz_spinning_mask_bits, 32, 32); + gdk_cursor = gdk_cursor_new_from_pixmap(source, mask, &fg, &bg, 2, 2); + g_object_unref(source); + g_object_unref(mask); + } else { + gdk_cursor = NULL; + } + break; + + default: + gdk_cursor = gdk_cursor_new(current_cursor_.GetCursorType()); + } + gdk_window_set_cursor(view_.get()->window, gdk_cursor); + // The window now owns the cursor. + if (gdk_cursor) + gdk_cursor_unref(gdk_cursor); +} diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h index 61edf67..6a7a792 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h @@ -48,7 +48,6 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView { void Hide(); gfx::Rect GetViewBounds() const; void UpdateCursor(const WebCursor& cursor); - void UpdateCursorIfOverSelf(); void SetIsLoading(bool is_loading); void IMEUpdateStatus(int control, const gfx::Rect& caret_rect); void DidPaintRect(const gfx::Rect& rect); @@ -65,6 +64,9 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView { void Paint(const gfx::Rect&); private: + // Update the display cursor for the render view. + void ShowCurrentCursor(); + // The model object. RenderWidgetHost *const host_; // The native UI widget. @@ -85,6 +87,9 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView { // form autocomplete. bool activatable_; + // Whether we are currently loading. + bool is_loading_; + // The cursor for the page. This is passed up from the renderer. WebCursor current_cursor_; }; diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h index 0a0dd3d..ffa0a5d 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -78,7 +78,6 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { virtual void Hide(); virtual gfx::Rect GetViewBounds() const; virtual void UpdateCursor(const WebCursor& cursor); - virtual void UpdateCursorIfOverSelf(); virtual void SetIsLoading(bool is_loading); virtual void IMEUpdateStatus(int control, const gfx::Rect& caret_rect); virtual void DidPaintRect(const gfx::Rect& rect); @@ -91,6 +90,10 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { void KillSelf(); private: + // Updates the display cursor to the current cursor if the cursor is over this + // render view. + void UpdateCursorIfOverSelf(); + // Shuts down the render_widget_host_. This is a separate function so we can // invoke it from the message loop. void ShutdownHost(); 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 0a93555..274b2ec 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -122,7 +122,6 @@ class RenderWidgetHostViewWin : virtual void Hide(); virtual gfx::Rect GetViewBounds() const; virtual void UpdateCursor(const WebCursor& cursor); - virtual void UpdateCursorIfOverSelf(); virtual void SetIsLoading(bool is_loading); virtual void IMEUpdateStatus(int control, const gfx::Rect& caret_rect); virtual void DidPaintRect(const gfx::Rect& rect); @@ -174,6 +173,10 @@ class RenderWidgetHostViewWin : void OnFinalMessage(HWND window); private: + // Updates the display cursor to the current cursor if the cursor is over this + // render view. + void UpdateCursorIfOverSelf(); + // Tells Windows that we want to hear about mouse exit messages. void TrackMouseLeave(bool start_tracking); diff --git a/webkit/glue/webcursor_gtk_data.h b/webkit/glue/webcursor_gtk_data.h index 8fb52f7..8bffcb7 100644 --- a/webkit/glue/webcursor_gtk_data.h +++ b/webkit/glue/webcursor_gtk_data.h @@ -219,3 +219,35 @@ static const CustomCursor CustomCursors[] = { { "zoom-out", moz_zoom_out_bits, moz_zoom_out_mask_bits, 6, 6 }, { "vertical-text", moz_vertical_text_bits, moz_vertical_text_mask_bits, 8, 4 }, }; + +// This cursor intentionally left out of above structs. It is only used by +// RenderWidgetHostViewGtk. For an explanation see +// http://vektor-sigma.livejournal.com/1137.html (where it is referred +// to as left_ptr_watch). + +/* MOZ_CURSOR_SPINNING */ +static const char moz_spinning_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, + 0xfc, 0x3b, 0x00, 0x00, 0x7c, 0x38, 0x00, 0x00, 0x6c, 0x54, 0x00, 0x00, + 0xc4, 0xdc, 0x00, 0x00, 0xc0, 0x44, 0x00, 0x00, 0x80, 0x39, 0x00, 0x00, + 0x80, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const char moz_spinning_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0xfe, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x3b, 0x00, 0x00, + 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, + 0xee, 0xff, 0x01, 0x00, 0xe4, 0xff, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, + 0xc0, 0x7f, 0x00, 0x00, 0x80, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |