GTK: Implement BlockedPopupContainerView for linux.

This doesn't have:
- rounded corners
- gradient background
- animating in or out.
- graphical polish

but it is fucntionally complete.

http://crbug.com/12843

Review URL: http://codereview.chromium.org/118480

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18113 0039d316-1c4b-4281-b951-d872f2087c98
Esse commit está contido em:
erg@google.com
2009-06-10 23:54:20 +00:00
commit d700cffde0
13 arquivos alterados com 390 adições e 29 exclusões
+4
Ver Arquivo
@@ -1061,6 +1061,10 @@ std::wstring UintToWString(unsigned int value) {
return IntToStringT<std::wstring, unsigned int, unsigned int, false>::
IntToString(value);
}
string16 UintToString16(unsigned int value) {
return IntToStringT<string16, unsigned int, unsigned int, false>::
IntToString(value);
}
std::string Int64ToString(int64 value) {
return IntToStringT<std::string, int64, uint64, true>::
IntToString(value);
+1
Ver Arquivo
@@ -410,6 +410,7 @@ std::wstring IntToWString(int value);
string16 IntToString16(int value);
std::string UintToString(unsigned int value);
std::wstring UintToWString(unsigned int value);
string16 UintToString16(unsigned int value);
std::string Int64ToString(int64 value);
std::wstring Int64ToWString(int64 value);
std::string Uint64ToString(uint64 value);
+4 -4
Ver Arquivo
@@ -17,9 +17,9 @@ BlockedPopupContainer* BlockedPopupContainer::Create(
BlockedPopupContainer* container =
new BlockedPopupContainer(owner, profile->GetPrefs());
// TODO(erg): Add different defined(OS_??) as they get subclasses of
// BlockedPopupContainerView.
#if defined(OS_WIN)
// TODO(port): This ifdef goes away once Mac peeps write a Cocoa
// implementation of BlockedPopupContainerView.
#if defined(OS_WIN) || defined(OS_LINUX)
BlockedPopupContainerView* view =
BlockedPopupContainerView::Create(container);
container->set_view(view);
@@ -180,7 +180,7 @@ void BlockedPopupContainer::RepositionBlockedPopupContainer() {
view_->SetPosition();
}
TabContents* BlockedPopupContainer::GetTabContentsAt(size_t index) {
TabContents* BlockedPopupContainer::GetTabContentsAt(size_t index) const {
return blocked_popups_[index].tab_contents;
}
+1 -1
Ver Arquivo
@@ -119,7 +119,7 @@ class BlockedPopupContainer : public TabContentsDelegate,
void RepositionBlockedPopupContainer();
// Returns the TabContents for the blocked popup |index|.
TabContents* GetTabContentsAt(size_t index);
TabContents* GetTabContentsAt(size_t index) const;
// Returns the names of hosts showing popups.
std::vector<std::string> GetHosts() const;
+1 -3
Ver Arquivo
@@ -6,6 +6,7 @@
#include "chrome/browser/autofill_manager.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/blocked_popup_container.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/dom_ui/new_tab_ui.h"
@@ -25,7 +26,6 @@
#if defined(OS_WIN) // TODO(port): whittle this down as we port
#include "chrome/browser/task_manager.h"
#include "chrome/browser/views/blocked_popup_container_view_win.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/views/keyword_editor_view.h"
#include "chrome/browser/views/page_info_window.h"
@@ -63,9 +63,7 @@ void RegisterAllPrefs(PrefService* user_prefs, PrefService* local_state) {
TabContents::RegisterUserPrefs(user_prefs);
TemplateURLPrepopulateData::RegisterUserPrefs(user_prefs);
NewTabUI::RegisterUserPrefs(user_prefs);
#if defined(OS_WIN) // TODO(port): whittle this down as we port
BlockedPopupContainer::RegisterUserPrefs(user_prefs);
#endif
}
} // namespace browser
@@ -0,0 +1,186 @@
// 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/blocked_popup_container_view_gtk.h"
#include "app/l10n_util.h"
#include "base/gfx/gtk_util.h"
#include "base/string_util.h"
#include "chrome/browser/gtk/custom_button.h"
#include "chrome/browser/gtk/gtk_chrome_button.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view_gtk.h"
#include "chrome/common/gtk_util.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
namespace {
// Inner padding between the border and the text label.
const int kInternalTopBottomPadding = 1;
const int kInternalLeftRightPadding = 2;
// Size of the border painted in kBorderColor
const int kBorderPadding = 1;
// Color of the border.
const GdkColor kFrameBorderColor = GDK_COLOR_RGB(190, 205, 223);
// TODO(erg): The windows signal has a gradient on the background. I don't know
// how to do that so we just fill with the bottom color.
const GdkColor kBackgroundColorBottom = GDK_COLOR_RGB(219, 235, 255);
} // namespace
// static
BlockedPopupContainerView* BlockedPopupContainerView::Create(
BlockedPopupContainer* container) {
return new BlockedPopupContainerViewGtk(container);
}
BlockedPopupContainerViewGtk::~BlockedPopupContainerViewGtk() {
container_.Destroy();
}
TabContentsViewGtk* BlockedPopupContainerViewGtk::ContainingView() {
return static_cast<TabContentsViewGtk*>(
model_->GetConstrainingContents(NULL)->view());
}
void BlockedPopupContainerViewGtk::GetURLAndTitleForPopup(
size_t index, string16* url, string16* title) const {
DCHECK(url);
DCHECK(title);
TabContents* tab_contents = model_->GetTabContentsAt(index);
const GURL& tab_contents_url = tab_contents->GetURL().GetOrigin();
*url = UTF8ToUTF16(tab_contents_url.possibly_invalid_spec());
*title = tab_contents->GetTitle();
}
// Overridden from BlockedPopupContainerView:
void BlockedPopupContainerViewGtk::SetPosition() {
// No-op. Not required with the GTK version.
}
void BlockedPopupContainerViewGtk::ShowView() {
// TODO(erg): Animate in.
gtk_widget_show_all(container_.get());
}
void BlockedPopupContainerViewGtk::UpdateLabel() {
size_t blocked_popups = model_->GetBlockedPopupCount();
gtk_button_set_label(
GTK_BUTTON(menu_button_),
(blocked_popups > 0) ?
l10n_util::GetStringFUTF8(IDS_POPUPS_BLOCKED_COUNT,
UintToString16(blocked_popups)).c_str() :
l10n_util::GetStringUTF8(IDS_POPUPS_UNBLOCKED).c_str());
}
void BlockedPopupContainerViewGtk::HideView() {
// TODO(erg): Animate out.
gtk_widget_hide(container_.get());
}
void BlockedPopupContainerViewGtk::Destroy() {
ContainingView()->RemoveBlockedPopupView(this);
delete this;
}
bool BlockedPopupContainerViewGtk::IsCommandEnabled(int command_id) const {
return true;
}
bool BlockedPopupContainerViewGtk::IsItemChecked(int id) const {
DCHECK_GT(id, 0);
size_t id_size_t = static_cast<size_t>(id);
if (id_size_t > BlockedPopupContainer::kImpossibleNumberOfPopups) {
return model_->IsHostWhitelisted(
id_size_t - BlockedPopupContainer::kImpossibleNumberOfPopups - 1);
}
return false;
}
void BlockedPopupContainerViewGtk::ExecuteCommand(int id) {
DCHECK_GT(id, 0);
size_t id_size_t = static_cast<size_t>(id);
if (id_size_t > BlockedPopupContainer::kImpossibleNumberOfPopups) {
// Decrement id since all index based commands have 1 added to them. (See
// ButtonPressed() for detail).
model_->ToggleWhitelistingForHost(
id_size_t - BlockedPopupContainer::kImpossibleNumberOfPopups - 1);
} else {
model_->LaunchPopupAtIndex(id_size_t - 1);
}
}
BlockedPopupContainerViewGtk::BlockedPopupContainerViewGtk(
BlockedPopupContainer* container)
: model_(container),
close_button_(CustomDrawButton::CloseButton()) {
Init();
}
void BlockedPopupContainerViewGtk::Init() {
menu_button_ = gtk_chrome_button_new();
UpdateLabel();
g_signal_connect(menu_button_, "clicked",
G_CALLBACK(OnMenuButtonClicked), this);
GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), menu_button_, FALSE, FALSE, 0);
gtk_util::CenterWidgetInHBox(hbox, close_button_->widget(), true, 0);
g_signal_connect(close_button_->widget(), "clicked",
G_CALLBACK(OnCloseButtonClicked), this);
GtkWidget* padding = gtk_util::CreateGtkBorderBin(
hbox, &kBackgroundColorBottom,
kInternalTopBottomPadding, kInternalTopBottomPadding,
kInternalLeftRightPadding, kInternalLeftRightPadding);
container_.Own(gtk_util::CreateGtkBorderBin(padding, &kFrameBorderColor,
kBorderPadding, kBorderPadding, kBorderPadding, kBorderPadding));
ContainingView()->AttachBlockedPopupView(this);
}
void BlockedPopupContainerViewGtk::OnMenuButtonClicked(
GtkButton *button, BlockedPopupContainerViewGtk* container) {
container->launch_menu_.reset(new MenuGtk(container, false));
// Set items 1 .. popup_count as individual popups.
size_t popup_count = container->model_->GetBlockedPopupCount();
for (size_t i = 0; i < popup_count; ++i) {
string16 url, title;
container->GetURLAndTitleForPopup(i, &url, &title);
// We can't just use the index into container_ here because Menu reserves
// the value 0 as the nop command.
container->launch_menu_->AppendMenuItemWithLabel(i + 1,
l10n_util::GetStringFUTF8(IDS_POPUP_TITLE_FORMAT, url, title));
}
// Set items (kImpossibleNumberOfPopups + 1) ..
// (kImpossibleNumberOfPopups + 1 + hosts.size()) as hosts.
std::vector<std::string> hosts(container->model_->GetHosts());
if (!hosts.empty() && (popup_count > 0))
container->launch_menu_->AppendSeparator();
for (size_t i = 0; i < hosts.size(); ++i) {
container->launch_menu_->AppendCheckMenuItemWithLabel(
BlockedPopupContainer::kImpossibleNumberOfPopups + i + 1,
l10n_util::GetStringFUTF8(IDS_POPUP_HOST_FORMAT,
UTF8ToUTF16(hosts[i])));
}
container->launch_menu_->PopupAsContext(gtk_get_current_event_time());
}
void BlockedPopupContainerViewGtk::OnCloseButtonClicked(
GtkButton *button, BlockedPopupContainerViewGtk* container) {
container->model_->set_dismissed();
container->model_->CloseAll();
}
@@ -0,0 +1,101 @@
// 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_BLOCKED_POPUP_CONTAINER_VIEW_GTK_H_
#define CHROME_BROWSER_GTK_BLOCKED_POPUP_CONTAINER_VIEW_GTK_H_
#include <gtk/gtk.h>
#include <set>
#include <utility>
#include <vector>
#include "app/slide_animation.h"
#include "base/basictypes.h"
#include "base/gfx/native_widget_types.h"
#include "base/gfx/rect.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "chrome/browser/blocked_popup_container.h"
#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/common/owned_widget_gtk.h"
class BlockedPopupContainerInternalView;
class CustomDrawButton;
class MenuGtk;
class PrefService;
class Profile;
class TabContents;
class TabContentsViewGtk;
class TextButton;
namespace views {
class ImageButton;
}
// The GTK blocked popup container notification.
class BlockedPopupContainerViewGtk : public BlockedPopupContainerView,
public MenuGtk::Delegate {
public:
virtual ~BlockedPopupContainerViewGtk();
// Returns the Gtk view that currently owns us.
TabContentsViewGtk* ContainingView();
// Returns the URL and title for popup |index|, used to construct a string for
// display.
void GetURLAndTitleForPopup(size_t index,
string16* url,
string16* title) const;
GtkWidget* widget() { return container_.get(); }
// Overridden from BlockedPopupContainerView:
virtual void SetPosition();
virtual void ShowView();
virtual void UpdateLabel();
virtual void HideView();
virtual void Destroy();
// Overridden from MenuGtk::Delegate:
virtual bool IsCommandEnabled(int command_id) const;
virtual bool IsItemChecked(int command_id) const;
virtual void ExecuteCommand(int command_id);
private:
// For the static constructor BlockedPopupContainerView::Create().
friend class BlockedPopupContainerView;
// Creates a container for a certain TabContents.
explicit BlockedPopupContainerViewGtk(BlockedPopupContainer* container);
// Builds all the messy GTK stuff.
void Init();
// Callbacks for the two buttons in the notification
static void OnMenuButtonClicked(GtkButton *button,
BlockedPopupContainerViewGtk* container);
static void OnCloseButtonClicked(GtkButton *button,
BlockedPopupContainerViewGtk* container);
// Our model; calling the shots.
BlockedPopupContainer* model_;
// The top level of our local GTK hierarchy.
OwnedWidgetGtk container_;
// The "Blocked Popups: XXX" button.
GtkWidget* menu_button_;
// Closes the container.
scoped_ptr<CustomDrawButton> close_button_;
// The popup menu with options to launch blocked popups.
scoped_ptr<MenuGtk> launch_menu_;
DISALLOW_COPY_AND_ASSIGN(BlockedPopupContainerViewGtk);
};
#endif // CHROME_BROWSER_GTK_BLOCKED_POPUP_CONTAINER_VIEW_GTK_H_
+2 -3
Ver Arquivo
@@ -769,8 +769,7 @@ void TabContents::AddNewContents(TabContents* new_contents,
if (!delegate_)
return;
#if defined(OS_WIN)
bool constrain_popup = false;
#if defined(OS_WIN) || defined(OS_LINUX)
if ((disposition == NEW_POPUP) && !user_gesture &&
!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisablePopupBlocking)) {
@@ -1072,7 +1071,7 @@ void TabContents::SetIsLoading(bool is_loading,
det);
}
#if defined(OS_WIN)
#if defined(OS_WIN) || defined(OS_LINUX)
void TabContents::CreateBlockedPopupContainerIfNecessary() {
if (blocked_popups_)
return;
@@ -13,7 +13,9 @@
#include "base/gfx/size.h"
#include "build/build_config.h"
#include "chrome/browser/download/download_shelf.h"
#include "chrome/browser/gtk/blocked_popup_container_view_gtk.h"
#include "chrome/browser/gtk/browser_window_gtk.h"
#include "chrome/browser/gtk/gtk_floating_container.h"
#include "chrome/browser/gtk/sad_tab_gtk.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_view_host_factory.h"
@@ -28,6 +30,10 @@
namespace {
// TODO(erg): I have no idea how to progromatically figure out how wide the
// vertical scrollbar is. Hack it with a hardcoded value for now.
const int kScrollbarWidthHack = 25;
// Called when the content view gtk widget is tabbed to, or after the call to
// gtk_widget_child_focus() in TakeFocus(). We return true
// and grab focus if we don't have it. The call to
@@ -99,16 +105,38 @@ TabContentsView* TabContentsView::Create(TabContents* tab_contents) {
TabContentsViewGtk::TabContentsViewGtk(TabContents* tab_contents)
: TabContentsView(tab_contents),
fixed_(gtk_fixed_new()) {
g_signal_connect(fixed_.get(), "size-allocate",
floating_(gtk_floating_container_new()),
fixed_(gtk_fixed_new()),
popup_view_(NULL) {
g_signal_connect(fixed_, "size-allocate",
G_CALLBACK(OnSizeAllocate), this);
gtk_widget_show(fixed_.get());
g_signal_connect(floating_.get(), "set-floating-position",
G_CALLBACK(OnSetFloatingPosition), this);
gtk_container_add(GTK_CONTAINER(floating_.get()), fixed_);
gtk_widget_show(fixed_);
gtk_widget_show(floating_.get());
registrar_.Add(this, NotificationType::TAB_CONTENTS_CONNECTED,
Source<TabContents>(tab_contents));
}
TabContentsViewGtk::~TabContentsViewGtk() {
fixed_.Destroy();
floating_.Destroy();
}
void TabContentsViewGtk::AttachBlockedPopupView(
BlockedPopupContainerViewGtk* popup_view) {
DCHECK(popup_view_ == NULL);
popup_view_ = popup_view;
gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(floating_.get()),
popup_view->widget());
}
void TabContentsViewGtk::RemoveBlockedPopupView(
BlockedPopupContainerViewGtk* popup_view) {
DCHECK(popup_view_ == popup_view);
gtk_container_remove(GTK_CONTAINER(floating_.get()), popup_view->widget());
popup_view_ = NULL;
}
void TabContentsViewGtk::CreateView() {
@@ -150,7 +178,7 @@ RenderWidgetHostView* TabContentsViewGtk::CreateViewForWidget(
}
gfx::NativeView TabContentsViewGtk::GetNativeView() const {
return fixed_.get();
return floating_.get();
}
gfx::NativeView TabContentsViewGtk::GetContentNativeView() const {
@@ -172,10 +200,10 @@ void TabContentsViewGtk::GetContainerBounds(gfx::Rect* out) const {
// animation.
int x = 0;
int y = 0;
if (fixed_.get()->window)
gdk_window_get_origin(fixed_.get()->window, &x, &y);
out->SetRect(x + fixed_.get()->allocation.x, y + fixed_.get()->allocation.y,
fixed_.get()->allocation.width, fixed_.get()->allocation.height);
if (fixed_->window)
gdk_window_get_origin(fixed_->window, &x, &y);
out->SetRect(x + fixed_->allocation.x, y + fixed_->allocation.y,
fixed_->allocation.width, fixed_->allocation.height);
}
void TabContentsViewGtk::OnContentsDestroy() {
@@ -299,7 +327,7 @@ void TabContentsViewGtk::StartDragging(const WebDropData& drop_data) {
}
void TabContentsViewGtk::InsertIntoContentArea(GtkWidget* widget) {
gtk_fixed_put(GTK_FIXED(fixed_.get()), widget, 0, 0);
gtk_fixed_put(GTK_FIXED(fixed_), widget, 0, 0);
}
gboolean TabContentsViewGtk::OnMouseDown(GtkWidget* widget,
@@ -321,3 +349,34 @@ gboolean TabContentsViewGtk::OnSizeAllocate(GtkWidget* widget,
return FALSE;
}
// static
void TabContentsViewGtk::OnSetFloatingPosition(
GtkFloatingContainer* floating_container, GtkAllocation* allocation,
TabContentsViewGtk* tab_contents_view) {
if (tab_contents_view->popup_view_) {
GtkWidget* widget = tab_contents_view->popup_view_->widget();
// Look at the size request of the status bubble and tell the
// GtkFloatingContainer where we want it positioned.
GtkRequisition requisition;
gtk_widget_size_request(widget, &requisition);
GValue value = { 0, };
g_value_init(&value, G_TYPE_INT);
int child_x = std::max(
allocation->x + allocation->width - requisition.width -
kScrollbarWidthHack, 0);
g_value_set_int(&value, child_x);
gtk_container_child_set_property(GTK_CONTAINER(floating_container),
widget, "x", &value);
int child_y = std::max(
allocation->y + allocation->height - requisition.height, 0);
g_value_set_int(&value, child_y);
gtk_container_child_set_property(GTK_CONTAINER(floating_container),
widget, "y", &value);
g_value_unset(&value);
}
}
@@ -14,8 +14,10 @@
#include "chrome/common/notification_registrar.h"
#include "chrome/common/owned_widget_gtk.h"
class BlockedPopupContainerViewGtk;
class RenderViewContextMenuGtk;
class SadTabGtk;
typedef struct _GtkFloatingContainer GtkFloatingContainer;
class TabContentsViewGtk : public TabContentsView,
public NotificationObserver {
@@ -26,6 +28,11 @@ class TabContentsViewGtk : public TabContentsView,
explicit TabContentsViewGtk(TabContents* tab_contents);
virtual ~TabContentsViewGtk();
// Unlike Windows, the BlockedPopupContainerView needs to collaborate with
// the TabContentsViewGtk to position the notification.
void AttachBlockedPopupView(BlockedPopupContainerViewGtk* popup_view);
void RemoveBlockedPopupView(BlockedPopupContainerViewGtk* popup_view);
// TabContentsView implementation --------------------------------------------
virtual void CreateView();
@@ -74,9 +81,17 @@ class TabContentsViewGtk : public TabContentsView,
GtkAllocation* config,
TabContentsViewGtk* view);
static void OnSetFloatingPosition(
GtkFloatingContainer* floating_container, GtkAllocation* allocation,
TabContentsViewGtk* tab_contents_view);
// Contains |fixed_| as its GtkBin member and a possible floating widget from
// |popup_view_|.
OwnedWidgetGtk floating_;
// This container holds the tab's web page views. It is a GtkFixed so that we
// can control the size of the web pages.
OwnedWidgetGtk fixed_;
GtkWidget* fixed_;
// The context menu is reset every time we show it, but we keep a pointer to
// between uses so that it won't go out of scope before we're done with it.
@@ -93,6 +108,8 @@ class TabContentsViewGtk : public TabContentsView,
FocusStoreGtk focus_store_;
BlockedPopupContainerViewGtk* popup_view_;
DISALLOW_COPY_AND_ASSIGN(TabContentsViewGtk);
};
@@ -344,9 +344,6 @@ void BlockedPopupContainerViewWin::SetPosition() {
gfx::Size size = container_view_->GetPreferredSize();
int base_x = anchor_point.x() - size.width();
int base_y = anchor_point.y() - size.height();
// The bounds we report through the automation system are the real bounds;
// the animation is short lived...
bounds_ = gfx::Rect(gfx::Point(base_x, base_y), size);
int real_height =
static_cast<int>(size.height() * slide_animation_->GetCurrentValue());
@@ -67,6 +67,7 @@ class BlockedPopupContainerViewWin : public BlockedPopupContainerView,
virtual void Destroy();
private:
// For the static constructor BlockedPopupContainerView::Create().
friend class BlockedPopupContainerView;
// Creates a container for a certain TabContents.
@@ -86,10 +87,6 @@ class BlockedPopupContainerViewWin : public BlockedPopupContainerView,
// The animation that slides us up and down.
scoped_ptr<SlideAnimation> slide_animation_;
// The bounds to report to the automation system (may not equal our actual
// bounds while animating in or out).
gfx::Rect bounds_;
DISALLOW_COPY_AND_ASSIGN(BlockedPopupContainerViewWin);
};
+2
Ver Arquivo
@@ -903,6 +903,8 @@
'browser/gtk/back_forward_button_gtk.h',
'browser/gtk/back_forward_menu_model_gtk.cc',
'browser/gtk/back_forward_menu_model_gtk.h',
'browser/gtk/blocked_popup_container_view_gtk.cc',
'browser/gtk/blocked_popup_container_view_gtk.h',
'browser/gtk/bookmark_bar_gtk.cc',
'browser/gtk/bookmark_bar_gtk.h',
'browser/gtk/bookmark_bubble_gtk.cc',