summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/gtk/bookmark_bubble_gtk.cc26
-rw-r--r--chrome/browser/gtk/bookmark_bubble_gtk.h26
-rw-r--r--chrome/browser/gtk/browser_window_gtk.cc2
-rw-r--r--chrome/browser/gtk/info_bubble_gtk.cc208
-rw-r--r--chrome/browser/gtk/info_bubble_gtk.h72
-rw-r--r--chrome/browser/gtk/toolbar_star_toggle_gtk.cc18
-rw-r--r--chrome/chrome.gyp8
7 files changed, 357 insertions, 3 deletions
diff --git a/chrome/browser/gtk/bookmark_bubble_gtk.cc b/chrome/browser/gtk/bookmark_bubble_gtk.cc
new file mode 100644
index 0000000..3ea2197
--- /dev/null
+++ b/chrome/browser/gtk/bookmark_bubble_gtk.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2009 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/gtk/bookmark_bubble_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "chrome/browser/gtk/info_bubble_gtk.h"
+
+// static
+void BookmarkBubbleGtk::Show(const gfx::Rect& rect,
+ Profile* profile,
+ const GURL& url,
+ bool newly_bookmarked) {
+ // TODO(deanm): Implement the real bookmark bubble. For now we just have
+ // a placeholder for testing that input and focus works correctly.
+ GtkWidget* content = gtk_vbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(content), gtk_label_new("Hej!"), TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(content), gtk_entry_new(), TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(content), gtk_entry_new(), TRUE, TRUE, 0);
+ InfoBubbleGtk* bubble = InfoBubbleGtk::Show(rect, content);
+ DCHECK(bubble);
+}
diff --git a/chrome/browser/gtk/bookmark_bubble_gtk.h b/chrome/browser/gtk/bookmark_bubble_gtk.h
new file mode 100644
index 0000000..f456ba1
--- /dev/null
+++ b/chrome/browser/gtk/bookmark_bubble_gtk.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2009 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.
+
+#ifndef CHROME_BROWSER_GTK_BOOKMARK_BUBBLE_GTK_H_
+#define CHROME_BROWSER_GTK_BOOKMARK_BUBBLE_GTK_H_
+
+#include "base/basictypes.h"
+#include "googleurl/src/gurl.h"
+
+typedef struct _GtkWidget GtkWidget;
+
+class Profile;
+namespace gfx {
+class Rect;
+}
+
+class BookmarkBubbleGtk {
+ public:
+ static void Show(const gfx::Rect& rect,
+ Profile* profile,
+ const GURL& url,
+ bool newly_bookmarked);
+};
+
+#endif // CHROME_BROWSER_GTK_BOOKMARK_BUBBLE_GTK_H_
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
index 8500a17..ee1d1e1 100644
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ b/chrome/browser/gtk/browser_window_gtk.cc
@@ -487,7 +487,7 @@ void BrowserWindowGtk::ShowBookmarkManager() {
void BrowserWindowGtk::ShowBookmarkBubble(const GURL& url,
bool already_bookmarked) {
- NOTIMPLEMENTED();
+ toolbar_->star()->ShowStarBubble(url, !already_bookmarked);
}
void BrowserWindowGtk::ShowReportBugDialog() {
diff --git a/chrome/browser/gtk/info_bubble_gtk.cc b/chrome/browser/gtk/info_bubble_gtk.cc
new file mode 100644
index 0000000..3758cd2
--- /dev/null
+++ b/chrome/browser/gtk/info_bubble_gtk.cc
@@ -0,0 +1,208 @@
+// Copyright (c) 2009 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/gtk/info_bubble_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/gfx/gtk_util.h"
+#include "base/gfx/rect.h"
+#include "base/logging.h"
+#include "chrome/common/gfx/path.h"
+
+namespace {
+
+// The height of the arrow, and the width will be about twice the height.
+const int kArrowSize = 5;
+// Number of pixels to the start of the arrow from the edge of the window.
+const int kArrowX = 13;
+// Number of pixels between the tip of the arrow and the region we're
+// pointing to.
+const int kArrowToContentPadding = -6;
+// We draw flat diagonal corners, each corner is an NxN square.
+const int kCornerSize = 3;
+// Margins around the content.
+const int kTopMargin = kArrowSize + kCornerSize + 6;
+const int kBottomMargin = kCornerSize + 6;
+const int kLeftMargin = kCornerSize + 6;
+const int kRightMargin = kCornerSize + 6;
+
+const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff);
+const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63);
+
+// A small convenience since GdkPoint is a POD without a constructor.
+GdkPoint MakeGdkPoint(gint x, gint y) {
+ GdkPoint point = {x, y};
+ return point;
+}
+
+enum FrameType {
+ FRAME_MASK,
+ FRAME_STROKE,
+};
+
+// Make the points for our polygon frame, either for fill (the mask), or for
+// when we stroke the border. NOTE: This seems a bit overcomplicated, but it
+// requires a bunch of careful fudging to get the pixels rasterized exactly
+// where we want them, the arrow to have a 1 pixel point, etc.
+// TODO(deanm): Windows draws with Skia and uses some PNG images for the
+// corners. This is a lot more work, but they get anti-aliasing.
+std::vector<GdkPoint> MakeFramePolygonPoints(int width,
+ int height,
+ FrameType type) {
+ std::vector<GdkPoint> points;
+
+ // If we have a stroke, we have to offset some of our points by 1 pixel.
+ int off = (type == FRAME_MASK) ? 0 : 1;
+
+ // Top left corner.
+ points.push_back(MakeGdkPoint(0, kArrowSize + kCornerSize - 1));
+ points.push_back(MakeGdkPoint(kCornerSize - 1, kArrowSize));
+
+ // The arrow.
+ points.push_back(MakeGdkPoint(kArrowX - kArrowSize, kArrowSize));
+ points.push_back(MakeGdkPoint(kArrowX, 0));
+ points.push_back(MakeGdkPoint(kArrowX + 1 - off, 0));
+ points.push_back(MakeGdkPoint(kArrowX + kArrowSize + 1 - off, kArrowSize));
+
+ // Top right corner.
+ points.push_back(MakeGdkPoint(width - kCornerSize + 1 - off, kArrowSize));
+ points.push_back(MakeGdkPoint(width - off, kArrowSize + kCornerSize - 1));
+
+ // Bottom right corner.
+ points.push_back(MakeGdkPoint(width - off, height - kCornerSize));
+ points.push_back(MakeGdkPoint(width - kCornerSize, height - off));
+
+ // Bottom left corner.
+ points.push_back(MakeGdkPoint(kCornerSize - off, height - off));
+ points.push_back(MakeGdkPoint(0, height - kCornerSize));
+
+ return points;
+}
+
+// When our size is initially allocated or changed, we need to recompute
+// and apply our shape mask region.
+void HandleSizeAllocate(GtkWidget* widget,
+ GtkAllocation* allocation,
+ gpointer unused) {
+ DCHECK(allocation->x == 0 && allocation->y == 0);
+ std::vector<GdkPoint> points = MakeFramePolygonPoints(
+ allocation->width, allocation->height, FRAME_MASK);
+ GdkRegion* mask_region = gdk_region_polygon(&points[0],
+ points.size(),
+ GDK_EVEN_ODD_RULE);
+ gdk_window_shape_combine_region(widget->window, mask_region, 0, 0);
+ gdk_region_destroy(mask_region);
+}
+
+gboolean HandleExpose(GtkWidget* widget,
+ GdkEventExpose* event,
+ gpointer unused) {
+ GdkDrawable* drawable = GDK_DRAWABLE(event->window);
+ GdkGC* gc = gdk_gc_new(drawable);
+ gdk_gc_set_rgb_fg_color(gc, &kFrameColor);
+
+ // Stroke the frame border.
+ std::vector<GdkPoint> points = MakeFramePolygonPoints(
+ widget->allocation.width, widget->allocation.height, FRAME_STROKE);
+ gdk_draw_polygon(drawable, gc, FALSE, &points[0], points.size());
+
+ g_object_unref(gc);
+ return FALSE; // Propagate so our children paint, etc.
+}
+
+} // namespace
+
+// static
+InfoBubbleGtk* InfoBubbleGtk::Show(const gfx::Rect& rect, GtkWidget* content) {
+ InfoBubbleGtk* bubble = new InfoBubbleGtk();
+ bubble->Init(rect, content);
+ return bubble;
+}
+
+InfoBubbleGtk::InfoBubbleGtk()
+ : window_(NULL),
+ screen_x_(0),
+ screen_y_(0),
+ closed_(false) {
+}
+
+InfoBubbleGtk::~InfoBubbleGtk() {
+}
+
+void InfoBubbleGtk::Init(const gfx::Rect& rect, GtkWidget* content) {
+ DCHECK(!window_);
+ screen_x_ = rect.x() + (rect.width() / 2) - kArrowX;
+ screen_y_ = rect.y() + rect.height() + kArrowToContentPadding;
+
+ window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_decorated(GTK_WINDOW(window_), TRUE);
+ gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
+ gtk_widget_set_app_paintable(window_, TRUE);
+ // Have GTK double buffer around the expose signal.
+ gtk_widget_set_double_buffered(window_, TRUE);
+ // Set the background color, so we don't need to paint it manually.
+ gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &kBackgroundColor);
+ // Make sure that our window can be focused.
+ GTK_WIDGET_SET_FLAGS(window_, GTK_CAN_FOCUS);
+
+ GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
+ kTopMargin, kBottomMargin,
+ kLeftMargin, kRightMargin);
+
+ gtk_container_add(GTK_CONTAINER(alignment), content);
+ gtk_container_add(GTK_CONTAINER(window_), alignment);
+
+ // GtkWidget only exposes the bitmap mask interface. Use GDK to more
+ // efficently mask a GdkRegion. Make sure the window is realized during
+ // HandleSizeAllocate, so the mask can be applied to the GdkWindow.
+ gtk_widget_realize(window_);
+ gtk_window_move(GTK_WINDOW(window_), screen_x_, screen_y_);
+
+ gtk_widget_add_events(window_, GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK);
+
+ g_signal_connect(window_, "size-allocate",
+ G_CALLBACK(HandleSizeAllocate), NULL);
+ g_signal_connect(window_, "expose-event",
+ G_CALLBACK(HandleExpose), NULL);
+ g_signal_connect(window_, "configure-event",
+ G_CALLBACK(&HandleConfigureThunk), this);
+ g_signal_connect(window_, "button-press-event",
+ G_CALLBACK(&HandleButtonPressThunk), this);
+
+ gtk_widget_show_all(window_);
+ gtk_window_present(GTK_WINDOW(window_));
+ gtk_grab_add(window_);
+}
+
+void InfoBubbleGtk::Close() {
+ DCHECK(!closed_);
+ DCHECK(window_);
+ gtk_widget_destroy(window_);
+ window_ = NULL;
+ closed_ = true;
+}
+
+gboolean InfoBubbleGtk::HandleConfigure(GdkEventConfigure* event) {
+ // If the window is moved someplace besides where we want it, move it back.
+ // TODO(deanm): In the end, I will probably remove this code and just let
+ // the user move around the bubble like a normal dialog. I want to try
+ // this for now and see if it causes problems when any window managers.
+ if (event->x != screen_x_ || event->y != screen_y_)
+ gtk_window_move(GTK_WINDOW(window_), screen_x_, screen_y_);
+ return FALSE;
+}
+
+gboolean InfoBubbleGtk::HandleButtonPress(GdkEventButton* event) {
+ // If we got a click in our own window, that's ok.
+ if (event->window == window_->window)
+ return FALSE; // Propagate.
+
+ // Otherwise we had a click outside of our window, close ourself.
+ Close();
+ return TRUE;
+}
diff --git a/chrome/browser/gtk/info_bubble_gtk.h b/chrome/browser/gtk/info_bubble_gtk.h
new file mode 100644
index 0000000..d5a3b7b
--- /dev/null
+++ b/chrome/browser/gtk/info_bubble_gtk.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2009 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.
+
+#ifndef CHROME_BROWSER_GTK_INFO_BUBBLE_GTK_H_
+#define CHROME_BROWSER_GTK_INFO_BUBBLE_GTK_H_
+
+#include "base/basictypes.h"
+
+#include <gtk/gtk.h>
+
+namespace gfx {
+class Rect;
+}
+
+class InfoBubbleGtk {
+ public:
+ // Show an InfoBubble, pointing at the area |rect| (in screen coordinates).
+ // An infobubble will try to fit on the screen, so it can point to any edge
+ // of |rect|. The bubble will host |widget| as the content.
+ static InfoBubbleGtk* Show(const gfx::Rect& rect, GtkWidget* content);
+
+ InfoBubbleGtk();
+ virtual ~InfoBubbleGtk();
+
+ void Close();
+
+ private:
+ // Creates the InfoBubble.
+ void Init(const gfx::Rect& rect, GtkWidget* content);
+
+ // Closes the window notifying the delegate. |closed_by_escape| is true if
+ // the close is the result of pressing escape.
+ void Close(bool closed_by_escape);
+
+ static gboolean HandleConfigureThunk(GtkWidget* widget,
+ GdkEventConfigure* event,
+ gpointer user_data) {
+ return reinterpret_cast<InfoBubbleGtk*>(user_data)->HandleConfigure(event);
+ }
+ gboolean HandleConfigure(GdkEventConfigure* event);
+
+ static gboolean HandleButtonPressThunk(GtkWidget* widget,
+ GdkEventButton* event,
+ gpointer userdata) {
+ return reinterpret_cast<InfoBubbleGtk*>(userdata)->
+ HandleButtonPress(event);
+ }
+ gboolean HandleButtonPress(GdkEventButton* event);
+
+ static gboolean HandleButtonReleaseThunk(GtkWidget* widget,
+ GdkEventButton* event,
+ gpointer userdata) {
+ return reinterpret_cast<InfoBubbleGtk*>(userdata)->
+ HandleButtonRelease(event);
+ }
+ gboolean HandleButtonRelease(GdkEventButton* event);
+
+ // Our GtkWindow popup window.
+ GtkWidget* window_;
+
+ // Where we want our window to be positioned on the screen.
+ int screen_x_;
+ int screen_y_;
+
+ // Have we been closed?
+ bool closed_;
+
+ DISALLOW_COPY_AND_ASSIGN(InfoBubbleGtk);
+};
+
+#endif // CHROME_BROWSER_GTK_INFO_BUBBLE_GTK_H_
diff --git a/chrome/browser/gtk/toolbar_star_toggle_gtk.cc b/chrome/browser/gtk/toolbar_star_toggle_gtk.cc
index e6edf24..92cfc16 100644
--- a/chrome/browser/gtk/toolbar_star_toggle_gtk.cc
+++ b/chrome/browser/gtk/toolbar_star_toggle_gtk.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/gtk/toolbar_star_toggle_gtk.h"
+#include "base/gfx/rect.h"
+#include "chrome/browser/gtk/bookmark_bubble_gtk.h"
#include "chrome/common/resource_bundle.h"
#include "grit/theme_resources.h"
@@ -27,6 +29,22 @@ ToolbarStarToggleGtk::~ToolbarStarToggleGtk() {
widget_.Destroy();
}
+void ToolbarStarToggleGtk::ShowStarBubble(const GURL& url,
+ bool newly_bookmarked) {
+ GtkWidget* widget = widget_.get();
+ gint x, y;
+ gdk_window_get_origin(widget->window, &x, &y);
+ x += widget->allocation.x;
+ y += widget->allocation.y;
+ gint width = widget->allocation.width;
+ gint height = widget->allocation.height;
+
+ BookmarkBubbleGtk::Show(gfx::Rect(x, y, width, height),
+ NULL,
+ url,
+ newly_bookmarked);
+}
+
void ToolbarStarToggleGtk::SetStarred(bool starred) {
is_starred_ = starred;
gtk_widget_queue_draw(widget_.get());
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 3d845d5..de92c3e 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -728,6 +728,8 @@
'browser/gtk/back_forward_menu_model_gtk.h',
'browser/gtk/bookmark_bar_gtk.cc',
'browser/gtk/bookmark_bar_gtk.h',
+ 'browser/gtk/bookmark_bubble_gtk.cc',
+ 'browser/gtk/bookmark_bubble_gtk.h',
'browser/gtk/bookmark_editor_gtk.cc',
'browser/gtk/bookmark_editor_gtk.h',
'browser/gtk/browser_toolbar_gtk.cc',
@@ -746,10 +748,12 @@
'browser/gtk/go_button_gtk.h',
'browser/gtk/gtk_chrome_button.cc',
'browser/gtk/gtk_chrome_button.h',
- 'browser/gtk/infobar_gtk.cc',
- 'browser/gtk/infobar_gtk.h',
+ 'browser/gtk/info_bubble_gtk.cc',
+ 'browser/gtk/info_bubble_gtk.h',
'browser/gtk/infobar_container_gtk.cc',
'browser/gtk/infobar_container_gtk.h',
+ 'browser/gtk/infobar_gtk.cc',
+ 'browser/gtk/infobar_gtk.h',
'browser/gtk/find_bar_gtk.cc',
'browser/gtk/find_bar_gtk.h',
'browser/gtk/link_button_gtk.cc',