| // Copyright (c) 2010 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_LOGIN_LOGIN_CONTROLLER_H_ |
| #define WINDOW_MANAGER_LOGIN_LOGIN_CONTROLLER_H_ |
| |
| #include <set> |
| #include <tr1/memory> |
| #include <vector> |
| |
| #include <gtest/gtest_prod.h> // for FRIEND_TEST() macro |
| |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "window_manager/event_consumer.h" |
| #include "window_manager/event_consumer_registrar.h" |
| #include "window_manager/event_loop.h" |
| #include "window_manager/login/login_entry.h" |
| |
| namespace window_manager { |
| |
| struct Point; |
| struct Rect; |
| class WindowManager; |
| |
| // LoginController is an EventConsumer responsible for positioning the windows |
| // used during login. LoginController collects all the windows of type |
| // WINDOW_TYPE_LOGIN_XXX and adds them to Entrys. When LoginController sees a |
| // message of type WM_SHOW_LOGIN all the windows are shown. |
| class LoginController : public EventConsumer { |
| public: |
| explicit LoginController(WindowManager* wm); |
| virtual ~LoginController(); |
| |
| // Begin EventConsumer implementation. |
| virtual bool IsInputWindow(XWindow 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); |
| // End EventConsumer implementation. |
| |
| private: |
| friend class LoginControllerTest; // runs InitialShow() manually |
| FRIEND_TEST(LoginControllerTest, AreViewsWindowsReady); |
| FRIEND_TEST(LoginControllerTest, ClientOnOffScreen); |
| FRIEND_TEST(LoginControllerTest, Focus); |
| FRIEND_TEST(LoginControllerTest, KeyBindingsDuringStateChange); |
| FRIEND_TEST(LoginControllerTest, LoginEntryRelativePositions); |
| FRIEND_TEST(LoginControllerTest, RemoveUser); |
| FRIEND_TEST(LoginControllerTest, SelectGuest); |
| FRIEND_TEST(LoginControllerTest, SelectTwice); |
| FRIEND_TEST(LoginControllerTest, ShowEntriesAfterTheyGetPixmaps); |
| FRIEND_TEST(LoginControllerTest, UnhideCursorOnBrowserWindowVisible); |
| FRIEND_TEST(LoginControllerTest, UnhideCursorOnLeave); |
| FRIEND_TEST(LoginControllerTest, HandleWindowMapRequestsWebUILoginWindow); |
| |
| // SelectionChangedManager is used to cleanup after the selection changes. |
| // When the selection changes |Schedule| is invoked on the |
| // SelectionChangedManager. SelectionChangedManager then invokes |
| // ProcessSelectionChangeCompleted back on the LoginController after a delay |
| // to do cleanup. |
| class SelectionChangedManager { |
| public: |
| explicit SelectionChangedManager(LoginController* layout); |
| ~SelectionChangedManager(); |
| |
| // Schedules a selection change for the specified index. If the selection |
| // has changed but not been committed (Run has not been invoked yet), it is |
| // committed. |
| void Schedule(size_t selected_index); |
| |
| // Stops any pending runs. |
| void Stop(); |
| |
| bool is_scheduled() const { |
| return timeout_id_ != EventLoop::kUnsetTimeoutId; |
| } |
| int selected_index() const { return selected_index_; } |
| |
| private: |
| // Callback when the timer fires. Notifies the LoginController. |
| void Run(); |
| |
| LoginController* layout_; |
| |
| // If not EventLoop::kUnsetTimeoutId, indicates there is a pending run. |
| int timeout_id_; |
| |
| // Last index passed to Schedule. |
| size_t selected_index_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SelectionChangedManager); |
| }; |
| |
| typedef std::vector<std::tr1::shared_ptr<LoginEntry> > Entries; |
| |
| // Copies login_xids_ and non_login_xids_ into the passed-in set. |
| void get_all_xids(std::set<XWindow>* xids_out) { |
| DCHECK(xids_out); |
| xids_out->clear(); |
| xids_out->insert(login_xids_.begin(), login_xids_.end()); |
| xids_out->insert(non_login_xids_.begin(), non_login_xids_.end()); |
| } |
| |
| // Invoked to handle the initial show. |
| void InitialShow(); |
| |
| // Set up the background window's position and visibility. |
| void ConfigureBackgroundWindow(); |
| |
| // Stacks the windows. The only stacking we care about is that the |
| // image_window is above the border_window and the controls_window is above |
| // the border window. |
| void StackWindows(); |
| |
| // Selects the entry at the specified index. Does nothing if index is already |
| // selected. This invokes SelectGuest if index corresponds to the guest. |
| void SelectEntryAt(size_t index); |
| |
| // Selects the wizard window. |
| void SelectWizardWindow(); |
| |
| // Sets whether the user can select other entries. |
| void SetEntrySelectionEnabled(bool enable); |
| |
| // Calculate and returns the origin for entries. |
| void CalculateIdealOrigins(std::vector<Point>* bounds); |
| |
| // Returns true if |window| is a a login window. |
| bool IsLoginWindow(Window* window) const; |
| |
| // Returns true if |index| is the index of the guest login window. |
| bool IsGuestEntryIndex(size_t index) const; |
| |
| // Returns the entry for the specified |win| or NULL if |win| doesn't belong |
| // to any entry. This returns an entry based on the index stored in the |
| // window's parameters. If |possibly_insert| is true and Chrome is attempting |
| // to add a new entry, the function will create a new LoginEntry object. |
| LoginEntry* GetEntryForWindow(Window* win, bool possibly_insert); |
| |
| // Returns the entry in |entries_| at the specified index, creating one if |
| // necessary. |
| LoginEntry* GetEntryAt(size_t index); |
| |
| // Invoked when the selection change completes. |last_selected_index| is the |
| // index of the selection before the selection changes. |
| void ProcessSelectionChangeCompleted(size_t last_selected_index); |
| |
| // Have we gotten all the windows we need and are they ready? |
| bool AreViewsWindowsReady(); |
| |
| // Does initial setup for windows if they have already gotten pixmaps. |
| // Invoked when some window gets its pixmap. This may do one of the following: |
| // - If the entry windows are ready, this stacks the windows and starts the |
| // initial animation. |
| // - If the background and guest windows are ready, they are shown. |
| void DoInitialSetupIfWindowsAreReady(); |
| |
| // Returns true if the background window is valid and has painted. |
| bool IsBackgroundWindowReady(); |
| |
| // Returns true if the WebUIBrowser window is valid and has painted. |
| bool IsWebUIWindowReady(); |
| |
| // Focus a window and save it to login_window_to_focus_. |
| void FocusLoginWindow(Window* win); |
| |
| // Stop hiding the mouse cursor if it's hidden and destroy ourselves. |
| // Don't access |this| after calling this method! Invoked when the first |
| // browser window becomes visible. |
| void HandleInitialBrowserWindowVisible(); |
| |
| // Re-show the mouse cursor and destroy |hide_mouse_cursor_xid_|. |
| void ShowMouseCursor(); |
| |
| // Hide all login-related windows and ask the window manager to destroy us. |
| // Called when we see the pixmap for a browser window get loaded. |
| void HideWindowsAndRequestDestruction(); |
| |
| // Send a D-Bus message to the session manager notifying it that the login |
| // windows are visible. |
| void NotifySessionManager(); |
| |
| // Invoke WindowManager::DropStartupBackground(). |
| void HandleDropStartupBackgroundTimeout(); |
| |
| WindowManager* wm_; |
| |
| EventConsumerRegistrar registrar_; |
| |
| // The set of login windows we know about. This is all the windows in |
| // |entries_| along with the guest window and background window. |
| std::set<XWindow> login_xids_; |
| |
| // Other, non-login-specific windows that we're managing when Chrome is |
| // in a not-logged-in state. |
| std::set<XWindow> non_login_xids_; |
| |
| // Current login entries. Each entry consists of 5 windows, each window in |
| // type params has index of the entry it belongs to. Usually the index in |
| // window matches entry index in this array. But it may vary during short |
| // period of time when some entry is removed or inserted. Chrome at first |
| // updates indexes for all entries and then maps or unmaps all windows for |
| // the entry. |
| Entries entries_; |
| |
| // Did we already get all the regular login (i.e. non-wizard, views based) |
| // windows and show them? |
| bool views_windows_are_ready_; |
| |
| // Did we already show the WebUI window? |
| bool webui_window_is_ready_; |
| |
| // Index of the selected entry. |
| size_t selected_entry_index_; |
| |
| // Used when the selection changes. |
| SelectionChangedManager selection_changed_manager_; |
| |
| // One of the OOBE/wizard screens ("Take picture" or "Create account"). |
| // "Guest mode" or "guest user" windows are represented with LoginEntry. |
| Window* wizard_window_; |
| |
| // Window placed in the background. |
| Window* background_window_; |
| |
| // Window that is a WebUI Browser. This is used in WebUI based login. |
| Window* webui_window_; |
| |
| // The controls or guest window that we've most recently focused. We |
| // track this so that if a transient window takes the focus and then gets |
| // closed, we can re-focus the window that had the focus before. |
| Window* login_window_to_focus_; |
| |
| // Are we waiting for a post-login browser window to get mapped and |
| // painted so we can hide the login windows and destroy the login |
| // controller? |
| bool waiting_for_browser_window_; |
| |
| // Has HideWindowsAndRequestDestruction() been called? |
| bool requested_destruction_; |
| |
| // Determines if entry selection is enabled at the moment. |
| bool is_entry_selection_enabled_; |
| |
| // Index of the entry that was inserted or kNoSelection if no such entry. |
| size_t last_inserted_entry_; |
| |
| // ID of an input window created so we can hide the mouse cursor until the |
| // user starts using it. |
| XWindow hide_mouse_cursor_xid_; |
| |
| // Login windows that have been destroyed post-login but that we're |
| // holding on to, so we can continue displaying their actors onscreen |
| // until the browser window has been painted. |
| std::set<std::tr1::shared_ptr<DestroyedWindow> > destroyed_windows_; |
| |
| // XIDs of login windows that we've asked to take ownership of after they're |
| // destroyed (i.e. windows that will eventually end up in |
| // |destroyed_windows_|). We track this so we can avoid double-registering a |
| // window if it's remapped (http://crosbug.com/13093). |
| std::set<XWindow> registered_destroyed_xids_; |
| |
| // Chrome browser windows that we're watching. We wait for one of the |
| // browser windows to get painted and then destroy ourselves. |
| std::set<XWindow> browser_xids_; |
| |
| // ID of timeout for invoking HandleDropStartupBackgroundTimeout(). |
| int drop_startup_background_timeout_id_; |
| |
| DISALLOW_COPY_AND_ASSIGN(LoginController); |
| }; |
| |
| } // namespace window_manager |
| |
| #endif // WINDOW_MANAGER_LOGIN_LOGIN_CONTROLLER_H_ |