| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <algorithm> | |
| 6 | |
| 7 #include "app/theme_provider.h" | |
| 8 #include "chrome/app/chrome_dll_resource.h" | |
| 9 #include "chrome/browser/chromeos/compact_location_bar.h" | |
| 10 #include "chrome/browser/chromeos/compact_navigation_bar.h" | |
| 11 #include "chrome/browser/chromeos/main_menu.h" | |
| 12 #include "chrome/browser/chromeos/status_area_view.h" | |
| 13 #include "chrome/browser/chromeos/panel_controller.h" | |
| 14 #include "chrome/browser/views/frame/browser_extender.h" | |
| 15 #include "chrome/browser/views/frame/browser_frame_gtk.h" | |
| 16 #include "chrome/browser/views/frame/browser_view.h" | |
| 17 #include "chrome/browser/views/tabs/tab_overview_types.h" | |
| 18 #include "chrome/browser/views/tabs/tab_strip.h" | |
| 19 #include "chrome/browser/views/tabs/tab_strip_wrapper.h" | |
| 20 #include "chrome/browser/views/toolbar_view.h" | |
| 21 #include "grit/generated_resources.h" | |
| 22 #include "grit/theme_resources.h" | |
| 23 #include "views/controls/button/button.h" | |
| 24 #include "views/controls/button/image_button.h" | |
| 25 #include "views/controls/menu/simple_menu_model.h" | |
| 26 #include "views/window/window.h" | |
| 27 | |
| 28 namespace { | |
| 29 | |
| 30 // NormalExtender adds ChromeOS specific controls and menus to a BrowserView | |
| 31 // created with Browser::TYPE_NORMAL. This extender adds controls to | |
| 32 // the title bar as follows: | |
| 33 // ____ __ __ | |
| 34 // [MainMenu] / \ \ \ [StatusArea] | |
| 35 // | |
| 36 // and adds the system context menu to the remaining arae of the titlebar. | |
| 37 // | |
| 38 // For Browser::TYPE_POPUP type of BrowserView, see PopupExtender class below. | |
| 39 class NormalExtender : public BrowserExtender, | |
| 40 public views::ButtonListener, | |
| 41 public views::ContextMenuController { | |
| 42 public: | |
| 43 explicit NormalExtender(BrowserView* browser_view) | |
| 44 : BrowserExtender(browser_view), | |
| 45 main_menu_(NULL), | |
| 46 status_area_(NULL), | |
| 47 compact_navigation_bar_(NULL), | |
| 48 // CompactNavigationBar is disabled by default. | |
| 49 // TODO(oshima): Get this info from preference. | |
| 50 compact_navigation_bar_enabled_(false) { | |
| 51 } | |
| 52 virtual ~NormalExtender() {} | |
| 53 | |
| 54 protected: | |
| 55 // BrowserExtender overrides. | |
| 56 virtual void Init() { | |
| 57 main_menu_ = new views::ImageButton(this); | |
| 58 ThemeProvider* theme_provider = | |
| 59 browser_view()->frame()->GetThemeProviderForFrame(); | |
| 60 SkBitmap* image = theme_provider->GetBitmapNamed(IDR_MAIN_MENU_BUTTON); | |
| 61 main_menu_->SetImage(views::CustomButton::BS_NORMAL, image); | |
| 62 main_menu_->SetImage(views::CustomButton::BS_HOT, image); | |
| 63 main_menu_->SetImage(views::CustomButton::BS_PUSHED, image); | |
| 64 browser_view()->AddChildView(main_menu_); | |
| 65 | |
| 66 compact_location_bar_.reset(new CompactLocationBar(browser_view())); | |
| 67 compact_navigation_bar_ = | |
| 68 new CompactNavigationBar(browser_view()->browser()); | |
| 69 browser_view()->AddChildView(compact_navigation_bar_); | |
| 70 compact_navigation_bar_->Init(); | |
| 71 status_area_ = new StatusAreaView( | |
| 72 browser_view()->browser(), | |
| 73 browser_view()->GetWindow()->GetNativeWindow()); | |
| 74 browser_view()->AddChildView(status_area_); | |
| 75 status_area_->Init(); | |
| 76 | |
| 77 InitSystemMenu(); | |
| 78 MainMenu::ScheduleCreation(); | |
| 79 | |
| 80 // The ContextMenuController has to be set to a NonClientView but | |
| 81 // not to a NonClientFrameView because a TabStrip is not a child of | |
| 82 // a NonClientFrameView even though visually a TabStrip is over a | |
| 83 // NonClientFrameView. | |
| 84 BrowserFrameGtk* gtk_frame = | |
| 85 static_cast<BrowserFrameGtk*>(browser_view()->frame()); | |
| 86 gtk_frame->GetNonClientView()->SetContextMenuController(this); | |
| 87 } | |
| 88 | |
| 89 virtual gfx::Rect Layout(const gfx::Rect& bounds) { | |
| 90 // Skip if there is no space to layout, or if the browser is in | |
| 91 // fullscreen mode. | |
| 92 if (bounds.IsEmpty() || browser_view()->IsFullscreen()) { | |
| 93 main_menu_->SetVisible(false); | |
| 94 compact_navigation_bar_->SetVisible(false); | |
| 95 status_area_->SetVisible(false); | |
| 96 return bounds; | |
| 97 } else { | |
| 98 main_menu_->SetVisible(true); | |
| 99 compact_navigation_bar_->SetVisible(compact_navigation_bar_enabled_); | |
| 100 status_area_->SetVisible(true); | |
| 101 } | |
| 102 | |
| 103 if (compact_navigation_bar_->IsVisible()) { | |
| 104 // Update the size and location of the compact location bar. | |
| 105 compact_location_bar_->UpdateBounds( | |
| 106 browser_view()->tabstrip()->AsTabStrip()->GetSelectedTab()); | |
| 107 } | |
| 108 | |
| 109 // Layout main menu before tab strip. | |
| 110 gfx::Size main_menu_size = main_menu_->GetPreferredSize(); | |
| 111 main_menu_->SetBounds(bounds.x(), bounds.y(), | |
| 112 main_menu_size.width(), bounds.height()); | |
| 113 | |
| 114 // Layout status area after tab strip. | |
| 115 gfx::Size status_size = status_area_->GetPreferredSize(); | |
| 116 status_area_->SetBounds(bounds.x() + bounds.width() - status_size.width(), | |
| 117 bounds.y(), status_size.width(), | |
| 118 status_size.height()); | |
| 119 int curx = bounds.x() + main_menu_size.width(); | |
| 120 int width = bounds.width() - main_menu_size.width() - status_size.width(); | |
| 121 | |
| 122 if (compact_navigation_bar_->IsVisible()) { | |
| 123 gfx::Size cnb_bounds = compact_navigation_bar_->GetPreferredSize(); | |
| 124 compact_navigation_bar_->SetBounds(curx, bounds.y(), | |
| 125 cnb_bounds.width(), bounds.height()); | |
| 126 curx += cnb_bounds.width(); | |
| 127 width -= cnb_bounds.width(); | |
| 128 } | |
| 129 width = std::max(0, width); // In case there is no space left. | |
| 130 return gfx::Rect(curx, bounds.y(), width, bounds.height()); | |
| 131 } | |
| 132 | |
| 133 virtual bool NonClientHitTest(const gfx::Point& point) { | |
| 134 gfx::Point point_in_main_menu_coords(point); | |
| 135 views::View::ConvertPointToView(browser_view(), main_menu_, | |
| 136 &point_in_main_menu_coords); | |
| 137 if (main_menu_->HitTest(point_in_main_menu_coords)) | |
| 138 return true; | |
| 139 | |
| 140 gfx::Point point_in_status_area_coords(point); | |
| 141 views::View::ConvertPointToView(browser_view(), status_area_, | |
| 142 &point_in_status_area_coords); | |
| 143 if (status_area_->HitTest(point_in_status_area_coords)) | |
| 144 return true; | |
| 145 | |
| 146 if (compact_navigation_bar_->IsVisible()) { | |
| 147 gfx::Point point_in_cnb_coords(point); | |
| 148 views::View::ConvertPointToView(browser_view(), | |
| 149 compact_navigation_bar_, | |
| 150 &point_in_cnb_coords); | |
| 151 return compact_navigation_bar_->HitTest(point_in_cnb_coords); | |
| 152 } | |
| 153 return false; | |
| 154 } | |
| 155 | |
| 156 virtual void UpdateTitleBar() {} | |
| 157 | |
| 158 virtual void Show() { | |
| 159 TabOverviewTypes::instance()->SetWindowType( | |
| 160 GTK_WIDGET(GetBrowserWindow()->GetNativeWindow()), | |
| 161 TabOverviewTypes::WINDOW_TYPE_CHROME_TOPLEVEL, | |
| 162 NULL); | |
| 163 } | |
| 164 | |
| 165 virtual void Close() {} | |
| 166 | |
| 167 virtual void ActivationChanged() {} | |
| 168 | |
| 169 virtual bool ShouldForceHideToolbar() { | |
| 170 return compact_navigation_bar_enabled_; | |
| 171 } | |
| 172 | |
| 173 virtual void ToggleCompactNavigationBar() { | |
| 174 compact_navigation_bar_enabled_ = !compact_navigation_bar_enabled_; | |
| 175 } | |
| 176 | |
| 177 virtual void OnMouseEnteredToTab(Tab* tab) { | |
| 178 ShowCompactLocationBarUnderSelectedTab(); | |
| 179 } | |
| 180 | |
| 181 virtual void OnMouseMovedOnTab(Tab* tab) { | |
| 182 ShowCompactLocationBarUnderSelectedTab(); | |
| 183 } | |
| 184 | |
| 185 virtual void OnMouseExitedFromTab(Tab* tab) { | |
| 186 compact_location_bar_->StartPopupTimer(); | |
| 187 } | |
| 188 | |
| 189 private: | |
| 190 // Shows the compact location bar under the selected tab. | |
| 191 void ShowCompactLocationBarUnderSelectedTab() { | |
| 192 if (!compact_navigation_bar_enabled_) | |
| 193 return; | |
| 194 compact_location_bar_->Update( | |
| 195 browser_view()->tabstrip()->AsTabStrip()->GetSelectedTab(), | |
| 196 browser_view()->browser()->GetSelectedTabContents()); | |
| 197 } | |
| 198 | |
| 199 // Creates system menu. | |
| 200 void InitSystemMenu() { | |
| 201 system_menu_contents_.reset(new views::SimpleMenuModel(browser_view())); | |
| 202 system_menu_contents_->AddItemWithStringId(IDC_RESTORE_TAB, | |
| 203 IDS_RESTORE_TAB); | |
| 204 system_menu_contents_->AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB); | |
| 205 system_menu_contents_->AddSeparator(); | |
| 206 system_menu_contents_->AddItemWithStringId(IDC_TASK_MANAGER, | |
| 207 IDS_TASK_MANAGER); | |
| 208 system_menu_menu_.reset(new views::Menu2(system_menu_contents_.get())); | |
| 209 } | |
| 210 | |
| 211 // views::ButtonListener overrides. | |
| 212 virtual void ButtonPressed(views::Button* sender, const views::Event& event) { | |
| 213 MainMenu::Show(browser_view()->browser()); | |
| 214 } | |
| 215 | |
| 216 // views::ContextMenuController overrides. | |
| 217 virtual void ShowContextMenu(views::View* source, | |
| 218 int x, | |
| 219 int y, | |
| 220 bool is_mouse_gesture) { | |
| 221 system_menu_menu_->RunMenuAt(gfx::Point(x, y), views::Menu2::ALIGN_TOPLEFT); | |
| 222 } | |
| 223 | |
| 224 // Main menu button. | |
| 225 views::ImageButton* main_menu_; | |
| 226 | |
| 227 // Status Area view. | |
| 228 StatusAreaView* status_area_; | |
| 229 | |
| 230 // System menus. | |
| 231 scoped_ptr<views::SimpleMenuModel> system_menu_contents_; | |
| 232 scoped_ptr<views::Menu2> system_menu_menu_; | |
| 233 | |
| 234 // CompactNavigationBar view. | |
| 235 CompactNavigationBar* compact_navigation_bar_; | |
| 236 | |
| 237 // A toggle flag to show/hide the compact navigation bar. | |
| 238 bool compact_navigation_bar_enabled_; | |
| 239 | |
| 240 // CompactLocationBar view. | |
| 241 scoped_ptr<CompactLocationBar> compact_location_bar_; | |
| 242 | |
| 243 DISALLOW_COPY_AND_ASSIGN(NormalExtender); | |
| 244 }; | |
| 245 | |
| 246 // PopupExtender class creates dedicated title window for popup window. | |
| 247 // The size and location of the created title window is controlled by | |
| 248 // by window manager. | |
| 249 class PopupExtender : public BrowserExtender { | |
| 250 public: | |
| 251 explicit PopupExtender(BrowserView* browser_view) | |
| 252 : BrowserExtender(browser_view) { | |
| 253 } | |
| 254 virtual ~PopupExtender() {} | |
| 255 | |
| 256 private: | |
| 257 // BrowserExtender overrides. | |
| 258 virtual void Init() { | |
| 259 // The visibility of toolbar is controlled in | |
| 260 // the BrowserView::IsToolbarVisible method. | |
| 261 | |
| 262 views::Window* window = GetBrowserWindow(); | |
| 263 gfx::NativeWindow native_window = window->GetNativeWindow(); | |
| 264 // The window manager needs the min size for popups. | |
| 265 gfx::Rect bounds = window->GetBounds(); | |
| 266 gtk_widget_set_size_request( | |
| 267 GTK_WIDGET(native_window), bounds.width(), bounds.height()); | |
| 268 // If we don't explicitly resize here there is a race condition between | |
| 269 // the X Server and the window manager. Windows will appear with a default | |
| 270 // size of 200x200 if this happens. | |
| 271 gtk_window_resize(native_window, bounds.width(), bounds.height()); | |
| 272 } | |
| 273 | |
| 274 virtual gfx::Rect Layout(const gfx::Rect& bounds) { | |
| 275 return bounds; | |
| 276 } | |
| 277 | |
| 278 virtual bool NonClientHitTest(const gfx::Point& point) { | |
| 279 return false; | |
| 280 } | |
| 281 | |
| 282 virtual void Show() { | |
| 283 panel_controller_.reset(new PanelController(browser_view())); | |
| 284 } | |
| 285 | |
| 286 virtual void Close() { | |
| 287 if (panel_controller_.get()) | |
| 288 panel_controller_->Close(); | |
| 289 } | |
| 290 | |
| 291 virtual void UpdateTitleBar() { | |
| 292 if (panel_controller_.get()) | |
| 293 panel_controller_->UpdateTitleBar(); | |
| 294 } | |
| 295 | |
| 296 virtual void ActivationChanged() { | |
| 297 if (panel_controller_.get()) { | |
| 298 if (GetBrowserWindow()->IsActive()) | |
| 299 panel_controller_->OnFocusIn(); | |
| 300 else | |
| 301 panel_controller_->OnFocusOut(); | |
| 302 } | |
| 303 } | |
| 304 | |
| 305 virtual bool ShouldForceHideToolbar() { | |
| 306 // Always hide toolbar for popups. | |
| 307 return true; | |
| 308 } | |
| 309 | |
| 310 virtual void ToggleCompactNavigationBar() {} | |
| 311 | |
| 312 virtual void OnMouseEnteredToTab(Tab* tab) {} | |
| 313 | |
| 314 virtual void OnMouseMovedOnTab(Tab* tab) {} | |
| 315 | |
| 316 virtual void OnMouseExitedFromTab(Tab* tab) {} | |
| 317 | |
| 318 // Controls interactions with the window manager for popup panels. | |
| 319 scoped_ptr<PanelController> panel_controller_; | |
| 320 | |
| 321 DISALLOW_COPY_AND_ASSIGN(PopupExtender); | |
| 322 }; | |
| 323 | |
| 324 } // namespace | |
| 325 | |
| 326 //////////////////////////////////////////////////////////////////////////////// | |
| 327 // BrowserExtender, public: | |
| 328 | |
| 329 // static | |
| 330 BrowserExtender* BrowserExtender::Create(BrowserView* browser_view) { | |
| 331 BrowserExtender* extender; | |
| 332 if (browser_view->browser()->type() & Browser::TYPE_POPUP) | |
| 333 extender = new PopupExtender(browser_view); | |
| 334 else | |
| 335 extender = new NormalExtender(browser_view); | |
| 336 extender->Init(); | |
| 337 return extender; | |
| 338 } | |
| OLD | NEW |