blob: 05a26ba972a961bf153f9be0c51e08f5dc38f67f [file] [log] [blame]
// 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_