diff options
author | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-07 00:41:04 +0000 |
---|---|---|
committer | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-07 00:41:04 +0000 |
commit | d904bc88427330a9cf4a32f3129c2353736be5ab (patch) | |
tree | fc4a3bd31be8bbc7ae8ed77dc1e2431963aa0bf2 /chrome/browser | |
parent | 3c78ae92e0c9a8c1e3e33c68df8e8a8af7d76a6c (diff) | |
download | chromium_src-d904bc88427330a9cf4a32f3129c2353736be5ab.zip chromium_src-d904bc88427330a9cf4a32f3129c2353736be5ab.tar.gz chromium_src-d904bc88427330a9cf4a32f3129c2353736be5ab.tar.bz2 |
Popup changes
Review URL: http://codereview.chromium.org/155075
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20001 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/browser.cc | 8 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.cc | 45 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.h | 9 | ||||
-rwxr-xr-x | chrome/browser/gtk/tabs/tab_strip_gtk.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/panel_controller.cc | 237 | ||||
-rw-r--r-- | chrome/browser/views/panel_controller.h | 104 |
6 files changed, 394 insertions, 11 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index ea81a21..b1d5f72 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -444,16 +444,16 @@ std::wstring Browser::GetCurrentPageTitle() const { if (title.empty()) title = l10n_util::GetString(IDS_TAB_UNTITLED_TITLE); -#if defined(OS_WIN) || defined(OS_LINUX) +#if defined(OS_MACOSX) || defined(LINUX2) + // On Mac, we don't want to suffix the page title with the application name. + return title; +#elif defined(OS_WIN) || defined(OS_LINUX) int string_id = IDS_BROWSER_WINDOW_TITLE_FORMAT; // Don't append the app name to window titles when we're not displaying a // distributor logo for the frame. if (!ShouldShowDistributorLogo()) string_id = IDS_BROWSER_WINDOW_TITLE_FORMAT_NO_LOGO; return l10n_util::GetStringF(string_id, title); -#elif defined(OS_MACOSX) - // On Mac, we don't want to suffix the page title with the application name. - return title; #endif } diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index 5416814..44274b1 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -56,6 +56,7 @@ #include "grit/theme_resources.h" #if defined(LINUX2) +#include "chrome/browser/views/panel_controller.h" #include "chrome/browser/views/tabs/tab_overview_types.h" #endif @@ -359,6 +360,7 @@ BrowserWindowGtk::BrowserWindowGtk(Browser* browser) full_screen_(false), #if defined(LINUX2) drag_active_(false), + panel_controller_(NULL), #endif frame_cursor_(NULL) { use_custom_frame_.Init(prefs::kUseCustomChromeFrame, @@ -456,8 +458,6 @@ gboolean BrowserWindowGtk::OnCustomFrameExpose(GtkWidget* widget, } void BrowserWindowGtk::Show() { - gtk_widget_show(GTK_WIDGET(window_)); - // The Browser associated with this browser window must become the active // browser at the time Show() is called. This is the natural behaviour under // Windows, but gtk_widget_show won't show the widget (and therefore won't @@ -467,10 +467,17 @@ void BrowserWindowGtk::Show() { BrowserList::SetLastActive(browser()); #if defined(LINUX2) - TabOverviewTypes::instance()->SetWindowType( - GTK_WIDGET(window_), TabOverviewTypes::WINDOW_TYPE_CHROME_TOPLEVEL, - NULL); + if (browser_->type() == Browser::TYPE_POPUP) { + panel_controller_ = new PanelController(this); + } else { + TabOverviewTypes::instance()->SetWindowType( + GTK_WIDGET(window_), + TabOverviewTypes::WINDOW_TYPE_CHROME_TOPLEVEL, + NULL); + } #endif + + gtk_widget_show(GTK_WIDGET(window_)); } void BrowserWindowGtk::SetBounds(const gfx::Rect& bounds) { @@ -498,6 +505,12 @@ void BrowserWindowGtk::Close() { // destruction, set window_ to NULL before any handlers will run. window_ = NULL; gtk_widget_destroy(window); + +#if defined(LINUX2) + if (panel_controller_) { + panel_controller_->Close(); + } +#endif } void BrowserWindowGtk::Activate() { @@ -533,6 +546,11 @@ void BrowserWindowGtk::SelectedTabToolbarSizeChanged(bool is_animating) { } void BrowserWindowGtk::UpdateTitleBar() { +#if defined(LINUX2) + if (panel_controller_) + panel_controller_->UpdateTitleBar(); +#endif + std::wstring title = browser_->GetCurrentPageTitle(); gtk_window_set_title(window_, WideToUTF8(title).c_str()); if (ShouldShowWindowIcon()) { @@ -1003,7 +1021,14 @@ void BrowserWindowGtk::InitWidgets() { toolbar_.reset(new BrowserToolbarGtk(browser_.get(), this)); toolbar_->Init(browser_->profile(), window_); - toolbar_->AddToolbarToBox(content_vbox_); + bool hide_tools = false; +#if defined(LINUX2) + if (browser_->type() == Browser::TYPE_POPUP) + hide_tools = true; +#endif + + if (!hide_tools) + toolbar_->AddToolbarToBox(content_vbox_); bookmark_bar_.reset(new BookmarkBarGtk(browser_->profile(), browser_.get(), this)); @@ -1026,6 +1051,14 @@ void BrowserWindowGtk::InitWidgets() { contents_container_->AddContainerToBox(render_area_vbox_); gtk_widget_show_all(render_area_vbox_); +#if defined(LINUX2) + if (browser_->type() == Browser::TYPE_POPUP) { + // The window manager needs the min size for popups + gtk_widget_set_size_request( + GTK_WIDGET(window_), bounds_.width(), bounds_.height()); + } +#endif + // We have to realize the window before we try to apply a window shape mask. gtk_widget_realize(GTK_WIDGET(window_)); state_ = gdk_window_get_state(GTK_WIDGET(window_)->window); diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index 64d4449..3045236 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -12,6 +12,7 @@ #include "base/gfx/rect.h" #include "base/scoped_ptr.h" #include "base/timer.h" +#include "build/build_config.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/common/notification_registrar.h" @@ -31,6 +32,10 @@ class StatusBubbleGtk; class TabContentsContainerGtk; class TabStripGtk; +#ifdef LINUX2 +class PanelController; +#endif + // An implementation of BrowserWindow for GTK. // Cross-platform code will interact with this object when // it needs to manipulate the window. @@ -149,6 +154,8 @@ class BrowserWindowGtk : public BrowserWindow, return browser_.get(); } + GtkWindow* window() { return window_; } + protected: virtual void DestroyBrowser(); // Top level window. @@ -292,6 +299,8 @@ class BrowserWindowGtk : public BrowserWindow, #if defined(LINUX2) // True if a drag is active. See description above setter for details. bool drag_active_; + // Controls interactions with the window manager for popup panels. + PanelController* panel_controller_; #endif // A map which translates an X Window ID into its respective GtkWindow. diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc index bb32927..7565815 100755 --- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc @@ -1584,7 +1584,7 @@ CustomDrawButton* TabStripGtk::MakeNewTabButton() { #if defined(LINUX2) CustomDrawButton* TabStripGtk::MakeTabOverviewButton() { CustomDrawButton* button = - new CustomDrawButton(IDR_TAB_OVERVIEW_BUTTON_ICON, 0, 0, 0); + new CustomDrawButton(IDR_TAB_OVERVIEW_BUTTON_ICON, 0, 0, 0, NULL); g_signal_connect(G_OBJECT(button->widget()), "clicked", G_CALLBACK(OnTabOverviewButtonClicked), this); diff --git a/chrome/browser/views/panel_controller.cc b/chrome/browser/views/panel_controller.cc new file mode 100644 index 0000000..c86aacd --- /dev/null +++ b/chrome/browser/views/panel_controller.cc @@ -0,0 +1,237 @@ +// 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/views/panel_controller.h" + +#include <gdk/gdkx.h> +extern "C" { +#include <X11/Xlib.h> +} + +#include "app/resource_bundle.h" +#include "base/logging.h" +#include "base/singleton.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/gtk/browser_window_gtk.h" +#include "chrome/browser/views/tabs/tab_overview_types.h" +#include "chrome/common/x11_util.h" +#include "grit/app_resources.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "views/controls/button/image_button.h" +#include "views/controls/label.h" +#include "views/event.h" +#include "views/view.h" +#include "views/widget/widget_gtk.h" + +static int close_button_width; +static int close_button_height; +static SkBitmap* close_button_n; +static SkBitmap* close_button_h; +static SkBitmap* close_button_p; +static gfx::Font* title_font = NULL; + +namespace { + +const int kTitleWidth = 200; +const int kTitleHeight = 24; +const int kTitlePad = 8; +const int kButtonPad = 8; + +static bool resources_initialized; +static void InitializeResources() { + if (resources_initialized) { + return; + } + + resources_initialized = true; + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + title_font = new gfx::Font(rb.GetFont(ResourceBundle::BaseFont)); + close_button_n = rb.GetBitmapNamed(IDR_TAB_CLOSE); + close_button_h = rb.GetBitmapNamed(IDR_TAB_CLOSE_H); + close_button_p = rb.GetBitmapNamed(IDR_TAB_CLOSE_P); + close_button_width = close_button_n->width(); + close_button_height = close_button_n->height(); +} + +} // namespace + +PanelController::PanelController(BrowserWindowGtk* browser_window) + : browser_window_(browser_window), + panel_(browser_window->window()), + panel_xid_(x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(panel_))), + expanded_(true), + mouse_down_(false), + dragging_(false) { + title_window_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW); + gfx::Rect title_bounds( + 0, 0, browser_window->GetNormalBounds().width(), kTitleHeight); + title_window_->Init(NULL, title_bounds); + title_ = title_window_->GetNativeView(); + title_xid_ = x11_util::GetX11WindowFromGtkWidget(title_); + + TabOverviewTypes* tab_overview = TabOverviewTypes::instance(); + tab_overview->SetWindowType( + title_, + TabOverviewTypes::WINDOW_TYPE_CHROME_PANEL_TITLEBAR, + NULL); + std::vector<int> type_params; + type_params.push_back(title_xid_); + type_params.push_back(expanded_ ? 1 : 0); + tab_overview->SetWindowType( + GTK_WIDGET(panel_), + TabOverviewTypes::WINDOW_TYPE_CHROME_PANEL, + &type_params); + + g_signal_connect( + panel_, "client-event", G_CALLBACK(OnPanelClientEvent), this); + + title_content_ = new TitleContentView(this); + title_window_->SetContentsView(title_content_); + title_window_->Show(); +} + +void PanelController::UpdateTitleBar() { + title_content_->title_label()->SetText( + browser_window_->browser()->GetCurrentPageTitle()); +} + +bool PanelController::TitleMousePressed(const views::MouseEvent& event) { + if (!event.IsOnlyLeftMouseButton()) { + return false; + } + gfx::Point abs_location = event.location(); + views::View::ConvertPointToScreen(title_content_, &abs_location); + mouse_down_ = true; + mouse_down_abs_x_ = abs_location.x(); + mouse_down_abs_y_ = abs_location.y(); + mouse_down_offset_x_ = event.x(); + mouse_down_offset_y_ = event.y(); + dragging_ = false; + return true; +} + +void PanelController::TitleMouseReleased( + const views::MouseEvent& event, bool canceled) { + if (!event.IsOnlyLeftMouseButton()) { + return; + } + // Only handle clicks that started in our window. + if (!mouse_down_) { + return; + } + + mouse_down_ = false; + if (!dragging_) { + TabOverviewTypes::Message msg( + TabOverviewTypes::Message::WM_SET_PANEL_STATE); + msg.set_param(0, panel_xid_); + msg.set_param(1, expanded_ ? 0 : 1); + TabOverviewTypes::instance()->SendMessage(msg); + } else { + TabOverviewTypes::Message msg( + TabOverviewTypes::Message::WM_NOTIFY_PANEL_DRAG_COMPLETE); + msg.set_param(0, panel_xid_); + TabOverviewTypes::instance()->SendMessage(msg); + dragging_ = false; + } +} + +bool PanelController::TitleMouseDragged(const views::MouseEvent& event) { + if (!mouse_down_) { + return false; + } + + gfx::Point abs_location = event.location(); + views::View::ConvertPointToScreen(title_content_, &abs_location); + if (!dragging_) { + if (views::View::ExceededDragThreshold( + abs_location.x() - mouse_down_abs_x_, + abs_location.y() - mouse_down_abs_y_)) { + dragging_ = true; + } + } + if (dragging_) { + TabOverviewTypes::Message msg(TabOverviewTypes::Message::WM_MOVE_PANEL); + msg.set_param(0, panel_xid_); + msg.set_param(1, abs_location.x() - mouse_down_offset_x_); + msg.set_param(2, abs_location.y() - mouse_down_offset_y_); + TabOverviewTypes::instance()->SendMessage(msg); + } + return true; +} + +// static +bool PanelController::OnPanelClientEvent( + GtkWidget* widget, + GdkEventClient* event, + PanelController* panel_controller) { + return panel_controller->PanelClientEvent(event); +} + +bool PanelController::PanelClientEvent(GdkEventClient* event) { + TabOverviewTypes::Message msg; + TabOverviewTypes::instance()->DecodeMessage(*event, &msg); + if (msg.type() == TabOverviewTypes::Message::CHROME_NOTIFY_PANEL_STATE) { + expanded_ = msg.param(0); + } + return true; +} + +void PanelController::Close() { + title_window_->Close(); +} + +void PanelController::ButtonPressed(views::Button* sender) { + if (sender == title_content_->close_button()) { + browser_window_->Close(); + } +} + +PanelController::TitleContentView::TitleContentView( + PanelController* panel_controller) + : panel_controller_(panel_controller) { + InitializeResources(); + close_button_ = new views::ImageButton(panel_controller_); + close_button_->SetImage(views::CustomButton::BS_NORMAL, close_button_n); + close_button_->SetImage(views::CustomButton::BS_HOT, close_button_h); + close_button_->SetImage(views::CustomButton::BS_PUSHED, close_button_p); + AddChildView(close_button_); + + title_label_ = new views::Label(std::wstring(), *title_font); + title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + AddChildView(title_label_); + + set_background(views::Background::CreateSolidBackground(0xdd, 0xdd, 0xdd, 1)); +} + +void PanelController::TitleContentView::Layout() { + close_button_->SetBounds( + bounds().width() - (close_button_width + kButtonPad), + (bounds().height() - close_button_height) / 2, + close_button_width, + close_button_height); + title_label_->SetBounds( + kTitlePad, + 0, + bounds().width() - (kTitlePad + close_button_width + 2 * kButtonPad), + bounds().height()); +} + +bool PanelController::TitleContentView::OnMousePressed( + const views::MouseEvent& event) { + return panel_controller_->TitleMousePressed(event); +} + +void PanelController::TitleContentView::OnMouseReleased( + const views::MouseEvent& event, bool canceled) { + return panel_controller_->TitleMouseReleased(event, canceled); +} + +bool PanelController::TitleContentView::OnMouseDragged( + const views::MouseEvent& event) { + return panel_controller_->TitleMouseDragged(event); +} + diff --git a/chrome/browser/views/panel_controller.h b/chrome/browser/views/panel_controller.h new file mode 100644 index 0000000..3bb88a6 --- /dev/null +++ b/chrome/browser/views/panel_controller.h @@ -0,0 +1,104 @@ +// 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_VIEWS_PANEL_CONTROLLER_H_ +#define CHROME_BROWSER_VIEWS_PANEL_CONTROLLER_H_ + +#include <gtk/gtk.h> + +#include "views/controls/button/button.h" + +class BrowserWindowGtk; +typedef unsigned long XID; + +namespace views { +class ImageButton; +class Label; +class MouseEvent; +class WidgetGtk; +} + +// Controls interactions with the WM for popups / panels. +class PanelController : public views::ButtonListener { + public: + explicit PanelController(BrowserWindowGtk* browser_window); + virtual ~PanelController() {} + + bool TitleMousePressed(const views::MouseEvent& event); + void TitleMouseReleased(const views::MouseEvent& event, bool canceled); + bool TitleMouseDragged(const views::MouseEvent& event); + bool PanelClientEvent(GdkEventClient* event); + + void UpdateTitleBar(); + void Close(); + // ButtonListener methods. + virtual void ButtonPressed(views::Button* sender); + + private: + class TitleContentView : public views::View { + public: + explicit TitleContentView(PanelController* panelController); + virtual ~TitleContentView() {} + virtual void Layout(); + virtual bool OnMousePressed(const views::MouseEvent& event); + virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled); + virtual bool OnMouseDragged(const views::MouseEvent& event); + + views::Label* title_label() { return title_label_; } + views::ImageButton* close_button() { return close_button_; } + + private: + views::Label* title_label_; + views::ImageButton* close_button_; + PanelController* panel_controller_; + DISALLOW_COPY_AND_ASSIGN(TitleContentView); + }; + + // Dispatches client events to PanelController instances + static bool OnPanelClientEvent( + GtkWidget* widget, + GdkEventClient* event, + PanelController* panel_controller); + + // Browser window containing content. + BrowserWindowGtk* browser_window_; + // Gtk object for content. + GtkWindow* panel_; + // X id for content. + XID panel_xid_; + + // Views object representing title. + views::WidgetGtk* title_window_; + // Gtk object representing title. + GtkWidget* title_; + // X id representing title. + XID title_xid_; + + // Views object, holds title and close button. + TitleContentView* title_content_; + + // Is the panel expanded or collapsed? + bool expanded_; + + // Is the mouse button currently down? + bool mouse_down_; + + // Cursor's absolute position when the mouse button was pressed. + int mouse_down_abs_x_; + int mouse_down_abs_y_; + + // Cursor's offset from the upper-left corner of the titlebar when the + // mouse button was pressed. + int mouse_down_offset_x_; + int mouse_down_offset_y_; + + // Is the titlebar currently being dragged? That is, has the cursor + // moved more than kDragThreshold away from its starting position? + bool dragging_; + + DISALLOW_COPY_AND_ASSIGN(PanelController); +}; + +#endif // CHROME_BROWSER_PANEL_CONTROLLER_H_ + |