| // Copyright (c) 2011 The Chromium OS 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 WINDOW_MANAGER_LAYOUT2_LAYOUT_MANAGER2_H_ |
| #define WINDOW_MANAGER_LAYOUT2_LAYOUT_MANAGER2_H_ |
| |
| #include <gtest/gtest_prod.h> // for FRIEND_TEST() macro |
| |
| #include <map> |
| #include <set> |
| #include <tr1/memory> |
| #include <vector> |
| |
| #include "base/basictypes.h" |
| #include "base/scoped_ptr.h" |
| #include "base/time.h" |
| #include "cros/chromeos_wm_ipc_enums.h" |
| #include "window_manager/compositor/compositor.h" |
| #include "window_manager/event_consumer.h" |
| #include "window_manager/focus_manager.h" |
| #include "window_manager/geometry.h" |
| #include "window_manager/modality_handler.h" |
| #include "window_manager/panels/panel_manager.h" |
| #include "window_manager/wm_ipc.h" |
| #include "window_manager/x11/x_types.h" |
| |
| namespace window_manager { |
| |
| class BrowserWindow; |
| class EventConsumerRegistrar; |
| class KeyBindingsActionRegistrar; |
| class KeyBindingsGroup; |
| class ResizeBox; |
| class Window; |
| class WindowManager; |
| |
| class LayoutManager2 : public EventConsumer, |
| public FocusChangeListener, |
| public ModalityChangeListener, |
| public PanelManagerAreaChangeListener { |
| public: |
| explicit LayoutManager2(WindowManager* wm); |
| virtual ~LayoutManager2(); |
| |
| chromeos::WmIpcLayoutMode layout_mode() const { return layout_mode_; } |
| bool maximized() const { |
| return layout_mode_ == chromeos::WM_IPC_LAYOUT_MAXIMIZED; |
| } |
| int num_browser_windows() const { return browser_windows_.size(); } |
| |
| // EventConsumer implementation. |
| virtual bool IsInputWindow(XWindow xid) { |
| return xid == resize_handle_xid_ || |
| xid == left_edge_input_xid_ || |
| xid == right_edge_input_xid_; |
| } |
| virtual void HandleScreenResize(); |
| virtual void HandleLoggedInStateChange() {} |
| virtual bool HandleWindowMapRequest(Window* win); |
| virtual void HandleWindowMap(Window* win); |
| virtual void HandleWindowUnmap(Window* win); |
| virtual void HandleWindowPixmapFetch(Window* win); |
| virtual void HandleWindowConfigureRequest(Window* win, |
| const Rect& requested_bounds); |
| virtual void HandleButtonPress(XWindow xid, |
| const Point& relative_pos, |
| const Point& absolute_pos, |
| int button, |
| XTime timestamp); |
| virtual void HandleButtonRelease(XWindow xid, |
| const Point& relative_pos, |
| const Point& absolute_pos, |
| int button, |
| XTime timestamp); |
| virtual void HandlePointerEnter(XWindow xid, |
| const Point& relative_pos, |
| const Point& absolute_pos, |
| XTime timestamp); |
| virtual void HandlePointerLeave(XWindow xid, |
| const Point& relative_pos, |
| const Point& absolute_pos, |
| XTime timestamp); |
| virtual void HandlePointerMotion(XWindow xid, |
| const Point& relative_pos, |
| const Point& absolute_pos, |
| XTime timestamp); |
| virtual void HandleChromeMessage(const WmIpc::Message& msg); |
| virtual void HandleClientMessage(XWindow xid, |
| XAtom message_type, |
| const long data[5]); |
| virtual void HandleWindowPropertyChange(XWindow xid, XAtom xatom) {} |
| virtual void OwnDestroyedWindow(DestroyedWindow* destroyed_win, |
| XWindow xid) {} |
| |
| // FocusChangeListener implementation. |
| virtual void HandleFocusChange(); |
| |
| // ModalityChangeListener implementation. |
| virtual void HandleModalityChange(); |
| |
| // PanelManagerAreaChangeListener implementation. |
| virtual void HandlePanelManagerAreaChange(); |
| |
| // Assign the input focus to the fullscreen/active browser if possible. |
| // Returns false if we were unable to take the focus. |
| bool TakeFocus(XTime timestamp); |
| |
| // The PanelManager is typically passed in here, but it's decoupled from the |
| // c'tor so it can be set by tests. |
| void SetPanelAreaNotifier(PanelManagerAreaChangeNotifier* notifier); |
| |
| private: |
| friend class LayoutManager2Test; |
| FRIEND_TEST(LayoutManager2Test, ResizeScreen); |
| FRIEND_TEST(LayoutManager2Test, InitialBrowserWindow); |
| FRIEND_TEST(LayoutManager2Test, MultipleWindowLayout); |
| FRIEND_TEST(LayoutManager2Test, ClickToActivateBrowser); |
| FRIEND_TEST(LayoutManager2Test, AvoidJankOnLayoutModeChange); |
| FRIEND_TEST(LayoutManager2Test, ResizeHandleActor); |
| FRIEND_TEST(LayoutManager2Test, IgnoreScrollwheelButtons); |
| |
| // Specifies ArrangeBrowserWindows()'s behavior with regard to assigning the |
| // input focus. |
| enum ArrangeFocusPolicy { |
| // Assign the focus to the fullscreen or active window if it doesn't have it |
| // already. |
| ASSIGN_FOCUS_DURING_ARRANGE = 0, |
| |
| // Leave the focus alone (e.g. we're rearranging the windows because we've |
| // exited fullscreen mode in response to a panel being mapped and taking the |
| // focus, and we don't want to immediately steal the focus back from the |
| // panel). |
| PRESERVE_FOCUS_DURING_ARRANGE, |
| }; |
| |
| // Specifies the browser windows that ArrangeBrowserWindows() should modify. |
| enum ArrangeSet { |
| // Arrange and restack all browser windows. |
| ARRANGE_ALL_BROWSERS = 0, |
| |
| // Arrange only the active browser. None of the windows are restacked. |
| ARRANGE_ACTIVE_BROWSER, |
| |
| // Arrange all but the active browser. None of the windows are restacked. |
| ARRANGE_INACTIVE_BROWSERS, |
| }; |
| |
| // Width used for new windows (although it may be capped). |
| static const int kWindowInitialWidthPixels; |
| |
| // How many pixels should we leave at the edge of the screen for the next |
| // window to be visible? |
| static const int kEdgeGapPixels; |
| |
| // Brightness for the secondary browser window when in non-maximized mode. |
| static const double kSecondaryBrowserWindowBrightness; |
| |
| // Brightness for browser windows shown at the edges of the screen. |
| static const double kEdgeBrowserWindowBrightness; |
| |
| // Get the currently-active browser window, or NULL if none is active (i.e. |
| // |browser_windows_| is empty). |
| BrowserWindow* GetActiveBrowserWindow() const; |
| |
| // Return the index in |browser_| of the BrowserWindow representing |win|. |
| // Returns -1 if the window isn't present in the vector. |
| int FindBrowserWindowIndexByWindow(const Window& win) const; |
| |
| // Get a browser window's index by X ID, or -1 if none exists with the ID. |
| int FindBrowserWindowIndexByXid(XWindow xid) const; |
| |
| // Get a browser window by X ID, or NULL if none exists with the ID. |
| BrowserWindow* FindBrowserWindowByXid(XWindow xid) const; |
| |
| // Get the browser window owning |win|, or NULL if no browser window owns it. |
| BrowserWindow* FindBrowserWindowOwningTransientWindow( |
| const Window& win) const; |
| |
| // Get |browser|'s index within |browser_windows_|. |
| int GetBrowserWindowIndex(const BrowserWindow& browser) const; |
| |
| // Get the initial, minimum, and maximum widths allowed for an unmaximized |
| // browser window. |
| int GetInitialUnmaximizedWidth() const; |
| int GetMinUnmaximizedWidth() const; |
| int GetMaxUnmaximizedWidth() const; |
| |
| // Constrain a browser window's unmaximized width within the allowed range. |
| int ConstrainUnmaximizedWidth(int reqested_width); |
| |
| // Get the number of milliseconds that we should take to switch from the |
| // currently-active browser to the one at |new_index|. |
| int GetWindowAnimationMs(int new_index) const; |
| |
| // Get the current time (typically to use when assigning the focus). If we're |
| // handling a key binding, returns the time from the event; otherwise, fetches |
| // the current time from the server. |
| XTime GetCurrentXTime(); |
| |
| // Save the area available for layout to |workarea_| and reconfigure browser |
| // windows as needed. |
| void MoveAndResizeForAvailableArea(); |
| |
| // Register all of our key bindings. Called once during initialization. |
| void InitKeyBindings(); |
| |
| // Handle various types of windows being mapped. Called by HandleWindowMap(). |
| void HandleBrowserWindowMap(Window* win); |
| void HandleTransientWindowMap(Window* transient_win, |
| BrowserWindow* owning_browser); |
| |
| // Do additional setup that's needed after we see the first browser window. |
| // Called by HandleBrowserWindowMap(). |
| void HandleFirstBrowserWindowMapped(Window* win); |
| |
| // Fill |bounds| with bounds for the windows in |browser_windows_|. |
| // The indices of the first (possibly only partially-)offscreen windows to |
| // the left and the right are stored in |left_offscreen_index| and |
| // |right_offscreen_index|. The |*_index| parameters may be NULL if unneeded. |
| void ComputeBrowserWindowBounds(std::vector<Rect>* bounds, |
| int* left_offscreen_index, |
| int* right_offscreen_index); |
| |
| // Restack all browser windows. Helper method for ArrangeBrowserWindows(). |
| void RestackBrowserWindows(int secondary_browser_index, |
| int left_offscreen_index, |
| int right_offscreen_index); |
| |
| // Arrange the browser windows described by |arrange_set|. |
| // |timestamp_for_focus| is used to focus the active window; 0 can be passed |
| // if |focus_policy| is PRESERVE_FOCUS_DURING_ARRANGE. |
| void ArrangeBrowserWindows(ArrangeSet arrange_set, |
| ArrangeFocusPolicy focus_policy, |
| XTime timestamp_for_focus, |
| int anim_ms); |
| |
| // Update |active_browser_index_|, along with the new active browser window's |
| // anchor position. ArrangeBrowserWindows() must be called afterwards. |
| void SetActiveBrowserWindowIndex(int browser_index); |
| |
| // Cycle forward or backward through browser windows. |
| // Calls ArrangeBrowserWindows() itself. |
| void CycleActiveBrowserWindow(bool forward); |
| |
| // Activate the browser window at index |browser_index|. -1 activates the |
| // last browser window, -2 the second-to-last, and so on. Effectively, just |
| // here so it can be used as a callback that calls both |
| // SetActiveBrowserWindow() and ArrangeBrowserWindows(). |
| void ActivateBrowserWindowByIndex(int browser_index); |
| |
| // Call SetLayoutMode() to toggle back and forth between the maximized and |
| // overlapping modes. |
| void ToggleMaximized(); |
| |
| // Change the layout mode. |
| void SetLayoutMode(chromeos::WmIpcLayoutMode mode, bool arrange_browsers); |
| |
| // Change the active browser window's stored width to use while unmaximized. |
| // If |maximized_| is currently false, the window is also resized. |
| void ChangeActiveBrowserUnmaximizedWidth(int new_width); |
| |
| // Resize the active browser window one "step". |
| void ResizeActiveBrowserWindowIncrementally(bool to_right); |
| |
| // Configure |resize_handle_xid_| appropriately given the current position of |
| // the active browser window. |
| void ConfigureResizeHandle(); |
| |
| // Configure |left_edge_input_xid_| and |right_edge_input_xid_| to cover the |
| // onscreen portions of the browser windows at |left_offscreen_index| and |
| // |right_offscreen_index|, or to be offscreen if those indices are -1. |
| void ConfigureEdgeInputWindows(int left_offscreen_index, |
| int right_offscreen_index); |
| |
| void HandleResizeDragStart(const Point& pos); |
| void HandleResizeDragMotion(const Point& pos); |
| void HandleResizeDragEnd(const Point& pos); |
| |
| // Handle |win| no longer preventing us from arranging all of the browser |
| // windows (either because we've gotten a new pixmap for it after it's been |
| // resized, or because it's been unmapped). Safe to call even if |win| isn't |
| // in |windows_blocking_arrange_|. |
| void HandleWindowNoLongerBlockingArrange(Window* win); |
| |
| // Call |browser|'s TakeFocus() method, switching to it if it isn't already |
| // focused. This is useful if one of the browser's transient windows has |
| // become modal and we want to make sure that it gets the focus. |
| void FocusBrowserWindow(BrowserWindow* browser); |
| |
| // Make |browser| be fullscreen. If a different browser window is already |
| // fullscreen, it will be restored. NULL can be supplied to exit fullscreen |
| // mode. |
| void SetFullscreenBrowserWindow(BrowserWindow* browser); |
| |
| // Handle EWMH ClientMessage requests sent by clients (_NET_WM_STATE, |
| // _NET_ACTIVE_WINDOW, etc.). |
| void HandleFullscreenRequest(Window* win, bool fullscreen); |
| void HandleModalityRequest(Window* win, bool modal); |
| void HandleActiveWindowRequest(Window* win, XTime timestamp); |
| |
| // Close the currently-focused "browser" window if it doesn't appear to be a |
| // Chrome window. (This provides a way to close cros-term windows.) |
| void CloseFocusedNonChromeWindow(); |
| |
| WindowManager* wm_; // not owned |
| |
| // Typically the PanelManager, although it can be set by tests. |
| // NULL until SetPanelAreaNotifier() is called. |
| PanelManagerAreaChangeNotifier* panel_area_notifier_; // not owned |
| |
| // Area where we lay out browser windows which we intend to be visible. |
| // Note that other browser windows may extend outside of this area. |
| Rect workarea_; |
| |
| scoped_ptr<EventConsumerRegistrar> event_consumer_registrar_; |
| scoped_ptr<KeyBindingsActionRegistrar> key_bindings_actions_; |
| |
| // Key bindings that are always enabled (while a modal dialog isn't open). |
| scoped_ptr<KeyBindingsGroup> key_bindings_group_; |
| |
| // Key bindings that are only enabled when a non-Chrome window is focused. |
| scoped_ptr<KeyBindingsGroup> non_chrome_key_bindings_group_; |
| |
| std::vector<std::tr1::shared_ptr<BrowserWindow> > browser_windows_; |
| |
| // Index in |browsers_| of the active browser window. |
| int active_browser_index_; |
| |
| // The current layout mode (e.g. maximized, overlapping, etc.). |
| chromeos::WmIpcLayoutMode layout_mode_; |
| |
| // The currently-fullscreen browser window, or NULL if none is fullscreen. |
| BrowserWindow* fullscreen_browser_; |
| |
| // Map from transient window IDs to the browsers owning them. |
| std::map<XWindow, BrowserWindow*> transient_xids_to_browsers_; |
| |
| // Windows that we're currently waiting on (either for them to get a new |
| // pixmap or to get unmapped) before we can arrange the browser windows. |
| std::set<Window*> windows_blocking_arrange_; |
| |
| // Duration for arrange animations when ArrangeBrowserWindows() is next called |
| // in response to |windows_blocking_arrange_| becoming empty, in milliseconds. |
| int anim_ms_for_pending_arrange_; |
| |
| // Input window that can be dragged to resize the active browser window. |
| XWindow resize_handle_xid_; |
| |
| // Actor used to emphasize the resize handle while the pointer is over it. |
| scoped_ptr<Compositor::ColoredBoxActor> resize_handle_actor_; |
| bool resize_handle_actor_is_visible_; |
| |
| // Left and right resize cursors used by |resize_handle_xid_|. |
| XID left_cursor_; |
| XID right_cursor_; |
| |
| // Input windows that listen for clicks at the left or right edges of the |
| // screen so we can switch to the browser windows there. We stack these on |
| // top of the browsers so that the browsers won't display hover effects in |
| // response to mouse motion events. |
| XWindow left_edge_input_xid_; |
| XWindow right_edge_input_xid_; |
| |
| // Is the user currently dragging |resize_handle_xid_| to resize the active |
| // browser window? |
| bool in_resize_drag_; |
| |
| // Pointer position and active browser window width when the resize started. |
| Point resize_drag_start_pos_; |
| int resize_width_at_start_; |
| |
| // Box displayed to show the current window dimensions while resizing. |
| scoped_ptr<ResizeBox> resize_box_; |
| |
| // Is |resize_box_| currently snapped to cover the whole workarea? |
| bool resize_box_is_snapped_; |
| |
| // Last bounds used for configuring |resize_box_|. |
| Rect last_resize_box_bounds_; |
| |
| // When the user drags the resize box to cover the whole screen and then drags |
| // it back, time at which we unsnapped the box from the maximized state. |
| base::TimeTicks resize_box_unsnap_time_; |
| |
| // Have we seen a browser window get mapped yet? |
| bool first_browser_window_mapped_; |
| |
| DISALLOW_COPY_AND_ASSIGN(LayoutManager2); |
| }; |
| |
| } // namespace window_manager |
| |
| #endif // WINDOW_MANAGER_LAYOUT2_LAYOUT_MANAGER2_H_ |