1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_UI_PANELS_PANEL_H_ 6 #define CHROME_BROWSER_UI_PANELS_PANEL_H_ 7 8 #include <string> 9 10 #include "base/gtest_prod_util.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/weak_ptr.h" 13 #include "base/strings/string16.h" 14 #include "chrome/browser/command_updater.h" 15 #include "chrome/browser/command_updater_delegate.h" 16 #include "chrome/browser/ui/panels/panel_constants.h" 17 #include "components/sessions/session_id.h" 18 #include "content/public/browser/notification_observer.h" 19 #include "content/public/browser/notification_registrar.h" 20 #include "extensions/browser/extension_registry_observer.h" 21 #include "ui/base/base_window.h" 22 #include "ui/gfx/image/image.h" 23 #include "ui/gfx/rect.h" 24 25 class GURL; 26 class NativePanel; 27 class PanelCollection; 28 class PanelHost; 29 class PanelManager; 30 class Profile; 31 class StackedPanelCollection; 32 33 namespace content { 34 class WebContents; 35 struct NativeWebKeyboardEvent; 36 } 37 38 namespace extensions { 39 class Extension; 40 class ExtensionRegistry; 41 class WindowController; 42 } 43 44 // A platform independent implementation of ui::BaseWindow for Panels. 45 // This class gets the first crack at all the ui::BaseWindow calls for Panels 46 // and does one or more of the following: 47 // - Do nothing. The function is not relevant to Panels. 48 // - Do Panel specific platform independent processing and then invoke the 49 // function on the platform specific member. For example, restrict panel 50 // size to certain limits. 51 // - Invoke an appropriate PanelManager function to do stuff that might affect 52 // other Panels. For example deleting a panel would rearrange other panels. 53 class Panel : public ui::BaseWindow, 54 public CommandUpdaterDelegate, 55 public content::NotificationObserver, 56 public extensions::ExtensionRegistryObserver { 57 public: 58 enum ExpansionState { 59 // The panel is fully expanded with both title-bar and the client-area. 60 EXPANDED, 61 // The panel is shown with the title-bar only. 62 TITLE_ONLY, 63 // The panel is shown with 3-pixel line. 64 MINIMIZED 65 }; 66 67 // Controls how the attention should be drawn. 68 enum AttentionMode { 69 // Uses the panel attention. The panel's titlebar would be painted 70 // differently to attract the user's attention. This is the default mode. 71 USE_PANEL_ATTENTION = 0x01, 72 // Uses the system attention. On Windows or Linux (depending on Window 73 // Manager), the app icon on taskbar will be flashed. On MacOS, the dock 74 // icon will jump once. 75 USE_SYSTEM_ATTENTION = 0x02 76 }; 77 78 virtual ~Panel(); 79 80 // Returns the PanelManager associated with this panel. 81 PanelManager* manager() const; 82 app_name()83 const std::string& app_name() const { return app_name_; } app_icon()84 const gfx::Image& app_icon() const { return app_icon_; } session_id()85 const SessionID& session_id() const { return session_id_; } extension_window_controller()86 extensions::WindowController* extension_window_controller() const { 87 return extension_window_controller_.get(); 88 } 89 const std::string extension_id() const; 90 91 CommandUpdater* command_updater(); 92 Profile* profile() const; 93 94 const extensions::Extension* GetExtension() const; 95 96 // Returns web contents of the panel, if any. There may be none if web 97 // contents have not been added to the panel yet. 98 content::WebContents* GetWebContents() const; 99 100 void SetExpansionState(ExpansionState new_expansion_state); 101 102 bool IsDrawingAttention() const; 103 104 // This function will only get called by PanelManager when full screen mode 105 // changes i.e it gets called when an app goes into full screen mode or when 106 // an app exits full screen mode. Panel should respond by making sure 107 // a) it does not go on top when some app enters full screen mode. 108 // b) it remains on top when an app exits full screen mode. 109 void FullScreenModeChanged(bool is_full_screen); 110 111 int TitleOnlyHeight() const; 112 113 // Returns true if the panel can show minimize or restore button in its 114 // titlebar, depending on its state. 115 bool CanShowMinimizeButton() const; 116 bool CanShowRestoreButton() const; 117 118 // ui::BaseWindow overrides. 119 virtual bool IsActive() const OVERRIDE; 120 virtual bool IsMaximized() const OVERRIDE; 121 virtual bool IsMinimized() const OVERRIDE; 122 virtual bool IsFullscreen() const OVERRIDE; 123 virtual gfx::NativeWindow GetNativeWindow() OVERRIDE; 124 virtual gfx::Rect GetRestoredBounds() const OVERRIDE; 125 virtual ui::WindowShowState GetRestoredState() const OVERRIDE; 126 virtual gfx::Rect GetBounds() const OVERRIDE; 127 virtual void Show() OVERRIDE; 128 virtual void Hide() OVERRIDE; 129 virtual void ShowInactive() OVERRIDE; 130 virtual void Close() OVERRIDE; 131 virtual void Activate() OVERRIDE; 132 virtual void Deactivate() OVERRIDE; 133 virtual void Maximize() OVERRIDE; 134 virtual void Minimize() OVERRIDE; 135 virtual void Restore() OVERRIDE; 136 virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE; 137 virtual void FlashFrame(bool flash) OVERRIDE; 138 virtual bool IsAlwaysOnTop() const OVERRIDE; 139 virtual void SetAlwaysOnTop(bool on_top) OVERRIDE; 140 141 // Overridden from CommandUpdaterDelegate: 142 virtual void ExecuteCommandWithDisposition( 143 int id, 144 WindowOpenDisposition disposition) OVERRIDE; 145 146 // content::NotificationObserver overrides. 147 virtual void Observe(int type, 148 const content::NotificationSource& source, 149 const content::NotificationDetails& details) OVERRIDE; 150 151 // extensions::ExtensionRegistryObserver. 152 virtual void OnExtensionUnloaded( 153 content::BrowserContext* browser_context, 154 const extensions::Extension* extension, 155 extensions::UnloadedExtensionInfo::Reason reason) OVERRIDE; 156 157 // Construct a native panel implementation. 158 static NativePanel* CreateNativePanel(Panel* panel, 159 const gfx::Rect& bounds, 160 bool always_on_top); 161 native_panel()162 NativePanel* native_panel() const { return native_panel_; } 163 164 // Invoked when the native panel has detected a mouse click on the 165 // panel's titlebar, minimize or restore buttons. Behavior of the 166 // click may be modified as indicated by |modifier|. 167 void OnTitlebarClicked(panel::ClickModifier modifier); 168 void OnMinimizeButtonClicked(panel::ClickModifier modifier); 169 void OnRestoreButtonClicked(panel::ClickModifier modifier); 170 171 // Used on platforms where the panel cannot determine its window size 172 // until the window has been created. (e.g. GTK) 173 void OnWindowSizeAvailable(); 174 175 // Asynchronous completion of panel close request. 176 void OnNativePanelClosed(); 177 178 // May be NULL if: 179 // * panel is newly created and has not been positioned yet. 180 // * panel is being closed asynchronously. 181 // Please use it with caution. collection()182 PanelCollection* collection() const { return collection_; } 183 184 // Sets the current panel collection that contains this panel. set_collection(PanelCollection * new_collection)185 void set_collection(PanelCollection* new_collection) { 186 collection_ = new_collection; 187 } 188 189 StackedPanelCollection* stack() const; 190 expansion_state()191 ExpansionState expansion_state() const { return expansion_state_; } min_size()192 const gfx::Size& min_size() const { return min_size_; } max_size()193 const gfx::Size& max_size() const { return max_size_; } auto_resizable()194 bool auto_resizable() const { return auto_resizable_; } 195 in_preview_mode()196 bool in_preview_mode() const { return in_preview_mode_; } 197 198 panel::Resizability CanResizeByMouse() const; 199 attention_mode()200 AttentionMode attention_mode() const { return attention_mode_; } set_attention_mode(AttentionMode attention_mode)201 void set_attention_mode(AttentionMode attention_mode) { 202 attention_mode_ = attention_mode; 203 } 204 205 // The full size is the size of the panel when it is detached or expanded 206 // in the docked collection and squeezing mode is not on. full_size()207 gfx::Size full_size() const { return full_size_; } set_full_size(const gfx::Size & size)208 void set_full_size(const gfx::Size& size) { full_size_ = size; } 209 210 // Panel must be initialized to be "fully created" and ready for use. 211 // Only called by PanelManager. initialized()212 bool initialized() const { return initialized_; } 213 void Initialize(const GURL& url, const gfx::Rect& bounds, bool always_on_top); 214 215 // This is different from BaseWindow::SetBounds(): 216 // * SetPanelBounds() is only called by PanelManager to manage its position. 217 // * SetBounds() is called by the API to try to change the bounds, which may 218 // only change the size for Panel. 219 void SetPanelBounds(const gfx::Rect& bounds); 220 221 // Updates the panel bounds instantly without any animation. 222 void SetPanelBoundsInstantly(const gfx::Rect& bounds); 223 224 // Ensures that the panel's size does not exceed the work area by updating 225 // maximum and full size of the panel. This is called each time when display 226 // settings are changed. Note that bounds are not updated here and the call 227 // of setting bounds or refreshing layout should be called after this. 228 void LimitSizeToWorkArea(const gfx::Rect& work_area); 229 230 // Sets whether the panel will auto resize according to its content. 231 void SetAutoResizable(bool resizable); 232 233 // Configures the web contents for auto resize, including configurations 234 // on the renderer and detecting renderer changes. 235 void EnableWebContentsAutoResize(content::WebContents* web_contents); 236 237 // Invoked when the preferred window size of the given panel might need to 238 // get changed due to the contents being auto-resized. 239 void OnContentsAutoResized(const gfx::Size& new_content_size); 240 241 // Resizes the panel and sets the origin. Invoked when the panel is resized 242 // via the mouse. 243 void OnWindowResizedByMouse(const gfx::Rect& new_bounds); 244 245 // Sets minimum and maximum size for the panel. 246 void SetSizeRange(const gfx::Size& min_size, const gfx::Size& max_size); 247 248 // Updates the maximum size of the panel so that it's never smaller than the 249 // panel's desired size. Note that even if the user resizes the panel smaller 250 // later, the increased maximum size will still be in effect. Since it's not 251 // possible currently to switch the panel back to autosizing from 252 // user-resizable, it should not be a problem. 253 void IncreaseMaxSize(const gfx::Size& desired_panel_size); 254 255 // Handles keyboard events coming back from the renderer. 256 void HandleKeyboardEvent(const content::NativeWebKeyboardEvent& event); 257 258 // Sets whether the panel is shown in preview mode. When the panel is 259 // being dragged, it is in preview mode. 260 void SetPreviewMode(bool in_preview_mode); 261 262 // Sets whether the minimize or restore button, if any, are visible. 263 void UpdateMinimizeRestoreButtonVisibility(); 264 265 // Changes the preferred size to acceptable based on min_size() and max_size() 266 gfx::Size ClampSize(const gfx::Size& size) const; 267 268 // Called when the panel's active state changes. 269 // |active| is true if panel became active. 270 void OnActiveStateChanged(bool active); 271 272 // Called when the panel starts/ends the user resizing. 273 void OnPanelStartUserResizing(); 274 void OnPanelEndUserResizing(); 275 276 // Gives beforeunload handlers the chance to cancel the close. 277 bool ShouldCloseWindow(); 278 279 // Invoked when the window containing us is closing. Performs the necessary 280 // cleanup. 281 void OnWindowClosing(); 282 283 // Executes a command if it's enabled. 284 // Returns true if the command is executed. 285 bool ExecuteCommandIfEnabled(int id); 286 287 // Gets the title of the window from the web contents. 288 base::string16 GetWindowTitle() const; 289 290 // Gets the Favicon of the web contents. 291 gfx::Image GetCurrentPageIcon() const; 292 293 // Updates the title bar to display the current title and icon. 294 void UpdateTitleBar(); 295 296 // Updates UI to reflect change in loading state. 297 void LoadingStateChanged(bool is_loading); 298 299 // Updates UI to reflect that the web cotents receives the focus. 300 void WebContentsFocused(content::WebContents* contents); 301 302 // Moves the panel by delta instantly. 303 void MoveByInstantly(const gfx::Vector2d& delta_origin); 304 305 // Applies |corner_style| to the panel window. 306 void SetWindowCornerStyle(panel::CornerStyle corner_style); 307 308 // Performs the system minimize for the panel, i.e. becoming iconic. 309 void MinimizeBySystem(); 310 311 bool IsMinimizedBySystem() const; 312 313 // Returns true if the panel is shown in the active desktop. The user could 314 // create or use multiple desktops or workspaces. 315 bool IsShownOnActiveDesktop() const; 316 317 // Turns on/off the shadow effect around the window shape. 318 void ShowShadow(bool show); 319 320 protected: 321 // Panel can only be created using PanelManager::CreatePanel() or subclass. 322 // |app_name| is the default title for Panels when the page content does not 323 // provide a title. For extensions, this is usually the application name 324 // generated from the extension id. 325 Panel(Profile* profile, const std::string& app_name, 326 const gfx::Size& min_size, const gfx::Size& max_size); 327 328 private: 329 friend class PanelManager; 330 friend class PanelBrowserTest; 331 332 enum MaxSizePolicy { 333 // Default maximum size is proportional to the work area. 334 DEFAULT_MAX_SIZE, 335 // Custom maximum size is used when the panel is resized by the user. 336 CUSTOM_MAX_SIZE 337 }; 338 339 void OnImageLoaded(const gfx::Image& image); 340 341 // Initialize state for all supported commands. 342 void InitCommandState(); 343 344 // Configures the renderer for auto resize (if auto resize is enabled). 345 void ConfigureAutoResize(content::WebContents* web_contents); 346 347 // Load the app's image, firing a load state change when loaded. 348 void UpdateAppIcon(); 349 350 // Prepares a title string for display (removes embedded newlines, etc). 351 static void FormatTitleForDisplay(base::string16* title); 352 353 // The application name that is also the name of the window when the 354 // page content does not provide a title. 355 // This name should be set when the panel is created. 356 const std::string app_name_; 357 358 Profile* profile_; 359 360 // Current collection of panels to which this panel belongs. This determines 361 // the panel's screen layout. 362 PanelCollection* collection_; // Owned by PanelManager. 363 364 bool initialized_; 365 366 // Stores the full size of the panel so we can restore it after it's 367 // been minimized or squeezed due to lack of space in the collection. 368 gfx::Size full_size_; 369 370 // This is the minimum size that the panel can shrink to. 371 gfx::Size min_size_; 372 373 // This is the size beyond which the panel is not going to grow to accomodate 374 // the growing content and WebKit would add the scrollbars in such case. 375 gfx::Size max_size_; 376 377 MaxSizePolicy max_size_policy_; 378 379 // True if this panel auto resizes based on content. 380 bool auto_resizable_; 381 382 // True if this panel is in preview mode. When in preview mode, panel bounds 383 // should not be affected by layout refresh. This is currently used by drag 384 // controller to add a panel to the collection without causing its bounds to 385 // change. 386 bool in_preview_mode_; 387 388 // Platform specifc implementation for panels. It'd be one of 389 // PanelGtk/PanelView/PanelCocoa. 390 NativePanel* native_panel_; // Weak, owns us. 391 392 AttentionMode attention_mode_; 393 394 ExpansionState expansion_state_; 395 396 // The CommandUpdater manages the window commands. 397 CommandUpdater command_updater_; 398 399 content::NotificationRegistrar registrar_; 400 extensions::ExtensionRegistry* extension_registry_; 401 const SessionID session_id_; 402 scoped_ptr<extensions::WindowController> extension_window_controller_; 403 scoped_ptr<PanelHost> panel_host_; 404 405 // Icon showed in the task bar. 406 gfx::Image app_icon_; 407 408 base::WeakPtrFactory<Panel> image_loader_ptr_factory_; 409 410 DISALLOW_COPY_AND_ASSIGN(Panel); 411 }; 412 413 #endif // CHROME_BROWSER_UI_PANELS_PANEL_H_ 414