diff options
7 files changed, 95 insertions, 48 deletions
diff --git a/chrome/browser/chromeos/login/background_view.cc b/chrome/browser/chromeos/login/background_view.cc index 32ad3e4..987e5f1 100644 --- a/chrome/browser/chromeos/login/background_view.cc +++ b/chrome/browser/chromeos/login/background_view.cc @@ -32,12 +32,11 @@ using views::WidgetGtk; namespace chromeos { -BackgroundView::BackgroundView(bool for_screen_locker) +BackgroundView::BackgroundView() : status_area_(NULL), os_version_label_(NULL), boot_times_label_(NULL), - did_paint_(false), - for_screen_locker_(for_screen_locker) { + did_paint_(false) { views::Painter* painter = CreateBackgroundPainter(); set_background(views::Background::CreateBackgroundPainter(true, painter)); InitStatusArea(); @@ -63,7 +62,7 @@ views::Widget* BackgroundView::CreateWindowContainingView( WidgetGtk* window = new WidgetGtk(WidgetGtk::TYPE_WINDOW); window->Init(NULL, bounds); - *view = new BackgroundView(false /* for_screen_locker */); + *view = new BackgroundView(); window->SetContentsView(*view); (*view)->UpdateWindowType(); @@ -150,7 +149,7 @@ bool BackgroundView::IsBrowserMode() const { } bool BackgroundView::IsScreenLockerMode() const { - return for_screen_locker_; + return false; } void BackgroundView::LocaleChanged() { diff --git a/chrome/browser/chromeos/login/background_view.h b/chrome/browser/chromeos/login/background_view.h index fafbe05..f5c4540 100644 --- a/chrome/browser/chromeos/login/background_view.h +++ b/chrome/browser/chromeos/login/background_view.h @@ -26,7 +26,7 @@ class StatusAreaView; // StatusAreaView. class BackgroundView : public views::View, public StatusAreaHost { public: - explicit BackgroundView(bool for_screen_locker); + BackgroundView(); // Creates a window containing an instance of WizardContentsView as the root // view. The caller is responsible for showing (and closing) the returned @@ -90,9 +90,6 @@ private: // TODO(sky): nuke this when the wm knows when chrome has painted. bool did_paint_; - // true if the background view is for the screen locker. - const bool for_screen_locker_; - DISALLOW_COPY_AND_ASSIGN(BackgroundView); }; diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc index be138b0..cce18f4 100644 --- a/chrome/browser/chromeos/login/screen_locker.cc +++ b/chrome/browser/chromeos/login/screen_locker.cc @@ -191,7 +191,6 @@ class LockWindow : public views::WidgetGtk { }; // A child widget that grabs both keyboard and pointer input. -// TODO(oshima): catch grab-broke event and quit if it ever happenes. class GrabWidget : public views::WidgetGtk { public: explicit GrabWidget(chromeos::ScreenLocker* screen_locker) @@ -288,6 +287,36 @@ void GrabWidget::TryGrabAllInputs() { } } +// BackgroundView for ScreenLocker, which layouts a lock widget in +// addition to other background components. +class ScreenLockerBackgroundView : public chromeos::BackgroundView { + public: + ScreenLockerBackgroundView(views::WidgetGtk* lock_widget) + : lock_widget_(lock_widget) { + } + + virtual bool IsScreenLockerMode() const { + return true; + } + + virtual void Layout() { + chromeos::BackgroundView::Layout(); + gfx::Rect screen = bounds(); + gfx::Rect size; + lock_widget_->GetBounds(&size, false); + lock_widget_->SetBounds( + gfx::Rect((screen.width() - size.width()) / 2, + (screen.height() - size.height()) / 2, + size.width(), + size.height())); + } + + private: + views::WidgetGtk* lock_widget_; + + DISALLOW_COPY_AND_ASSIGN(ScreenLockerBackgroundView); +}; + } // namespace namespace chromeos { @@ -389,7 +418,7 @@ ScreenLocker::ScreenLocker(const UserManager::User& user) screen_lock_view_(NULL), user_(user), error_info_(NULL), - mapped_(false), + drawn_(false), input_grabbed_(false), // TODO(oshima): support auto login mode (this is not implemented yet) // http://crosbug.com/1881 @@ -398,28 +427,21 @@ ScreenLocker::ScreenLocker(const UserManager::User& user) screen_locker_ = this; } -void ScreenLocker::Init(const gfx::Rect& bounds) { - // TODO(oshima): Figure out which UI to keep and remove in the background. - views::View* screen = new BackgroundView(true /* for_screen_locker */); +void ScreenLocker::Init() { + authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); + + gfx::Point left_top(1, 1); + gfx::Rect init_bounds(views::Screen::GetMonitorAreaNearestPoint(left_top)); + LockWindow* lock_window = new LockWindow(); lock_window_ = lock_window; - lock_window_->Init(NULL, bounds); - g_signal_connect(lock_window_->GetNativeView(), - "map-event", - G_CALLBACK(&OnMapThunk), - this); - DCHECK(GTK_WIDGET_REALIZED(lock_window_->GetNativeView())); - WmIpc::instance()->SetWindowType( - lock_window_->GetNativeView(), - WM_IPC_WINDOW_CHROME_SCREEN_LOCKER, - NULL); - lock_window_->SetContentsView(screen); - lock_window_->Show(); - authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); + lock_window_->Init(NULL, init_bounds); + + g_signal_connect(lock_window_->GetNativeView(), "client-event", + G_CALLBACK(OnClientEventThunk), this); // GTK does not like zero width/height. gfx::Size size(1, 1); - if (!unlock_on_input_) { screen_lock_view_ = new ScreenLockView(this); screen_lock_view_->Init(); @@ -431,16 +453,22 @@ void ScreenLocker::Init(const gfx::Rect& bounds) { lock_widget_ = new GrabWidget(this); lock_widget_->MakeTransparent(); - lock_widget_->InitWithWidget(lock_window_, - gfx::Rect((bounds.width() - size.width()) / 2, - (bounds.height() - size.height()) / 2, - size.width(), - size.height())); + lock_widget_->InitWithWidget(lock_window_, gfx::Rect(size)); if (screen_lock_view_) lock_widget_->SetContentsView(screen_lock_view_); lock_widget_->GetRootView()->SetVisible(false); lock_widget_->Show(); + views::View* screen = new ScreenLockerBackgroundView(lock_widget_); + + DCHECK(GTK_WIDGET_REALIZED(lock_window_->GetNativeView())); + WmIpc::instance()->SetWindowType( + lock_window_->GetNativeView(), + WM_IPC_WINDOW_CHROME_SCREEN_LOCKER, + NULL); + lock_window_->SetContentsView(screen); + lock_window_->Show(); + // Don't let X draw default background, which was causing flash on // resume. gdk_window_set_back_pixmap(lock_window_->GetNativeView()->window, @@ -545,7 +573,7 @@ void ScreenLocker::Signout() { void ScreenLocker::OnGrabInputs() { DLOG(INFO) << "OnGrabInputs"; input_grabbed_ = true; - if (mapped_) + if (drawn_) ScreenLockReady(); } @@ -557,10 +585,9 @@ void ScreenLocker::Show() { // enable this again if it's possible. // DCHECK(!screen_locker_); if (!screen_locker_) { - gfx::Rect bounds(views::Screen::GetMonitorWorkAreaNearestWindow(NULL)); ScreenLocker* locker = new ScreenLocker(UserManager::Get()->logged_in_user()); - locker->Init(bounds); + locker->Init(); } else { LOG(INFO) << "Show(): screen locker already exists. ignoring"; } @@ -637,9 +664,17 @@ void ScreenLocker::ScreenLockReady() { CrosLibrary::Get()->GetScreenLockLibrary()->NotifyScreenLockCompleted(); } -void ScreenLocker::OnMap(GtkWidget* widget, GdkEvent* event) { - DLOG(INFO) << "OnMap"; - mapped_ = true; +void ScreenLocker::OnClientEvent(GtkWidget* widge, GdkEventClient* event) { + WmIpc::Message msg; + WmIpc::instance()->DecodeMessage(*event, &msg); + if (msg.type() == WM_IPC_MESSAGE_CHROME_NOTIFY_SCREEN_REDRAWN_FOR_LOCK) { + OnWindowManagerReady(); + } +} + +void ScreenLocker::OnWindowManagerReady() { + DLOG(INFO) << "OnClientEvent: drawn for lock"; + drawn_ = true; if (input_grabbed_) ScreenLockReady(); } diff --git a/chrome/browser/chromeos/login/screen_locker.h b/chrome/browser/chromeos/login/screen_locker.h index 89047ec..f2681b7 100644 --- a/chrome/browser/chromeos/login/screen_locker.h +++ b/chrome/browser/chromeos/login/screen_locker.h @@ -40,8 +40,8 @@ class ScreenLocker : public LoginStatusConsumer, public: explicit ScreenLocker(const UserManager::User& user); - // Initialize and show the screen locker with given |bounds|. - void Init(const gfx::Rect& bounds); + // Initialize and show the screen locker. + void Init(); // LoginStatusConsumer implements: virtual void OnLoginFailure(const std::string& error); @@ -103,8 +103,11 @@ class ScreenLocker : public LoginStatusConsumer, // Called when the screen lock is ready. void ScreenLockReady(); - // Event handler for map-event. - CHROMEGTK_CALLBACK_1(ScreenLocker, void, OnMap, GdkEvent*); + // Called when the window manager is ready to handle locked state. + void OnWindowManagerReady(); + + // Event handler for client-event. + CHROMEGTK_CALLBACK_1(ScreenLocker, void, OnClientEvent, GdkEventClient*); // The screen locker window. views::WidgetGtk* lock_window_; @@ -134,8 +137,8 @@ class ScreenLocker : public LoginStatusConsumer, // An info bubble to display login failure message. MessageBubble* error_info_; - // True if the screen locker's window is mapped. - bool mapped_; + // True if the screen locker's window has been drawn. + bool drawn_; // True if both mouse input and keyboard input are grabbed. bool input_grabbed_; diff --git a/chrome/browser/chromeos/login/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/screen_locker_browsertest.cc index e30446a..48a8ff8 100644 --- a/chrome/browser/chromeos/login/screen_locker_browsertest.cc +++ b/chrome/browser/chromeos/login/screen_locker_browsertest.cc @@ -15,6 +15,7 @@ #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/views/browser_dialogs.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/notification_type.h" #include "chrome/test/ui_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,9 +34,10 @@ class ScreenLockerTest : public CrosInProcessBrowserTest { void TestNoPassword(void (unlock)(views::Widget*)) { UserManager::Get()->OffTheRecordUserLoggedIn(); ScreenLocker::Show(); - ui_test_utils::RunAllPendingInMessageLoop(); - scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester()); + tester->EmulateWindowManagerReady(); + ui_test_utils::WaitForNotification( + NotificationType::SCREEN_LOCK_STATE_CHANGED); EXPECT_TRUE(tester->IsOpen()); tester->InjectMockAuthenticator("", ""); @@ -87,8 +89,11 @@ IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestBasic) { .RetiresOnSaturation(); UserManager::Get()->UserLoggedIn("user"); ScreenLocker::Show(); - ui_test_utils::RunAllPendingInMessageLoop(); scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester()); + tester->EmulateWindowManagerReady(); + ui_test_utils::WaitForNotification( + NotificationType::SCREEN_LOCK_STATE_CHANGED); + tester->InjectMockAuthenticator("user", "pass"); EXPECT_TRUE(tester->IsOpen()); tester->EnterPassword("fail"); diff --git a/chrome/browser/chromeos/login/screen_locker_tester.cc b/chrome/browser/chromeos/login/screen_locker_tester.cc index 08b62c9..b399baa 100644 --- a/chrome/browser/chromeos/login/screen_locker_tester.cc +++ b/chrome/browser/chromeos/login/screen_locker_tester.cc @@ -48,6 +48,11 @@ void ScreenLockerTester::EnterPassword(const char* password) { gdk_event_free(event); } +void ScreenLockerTester::EmulateWindowManagerReady() { + DCHECK(ScreenLocker::screen_locker_); + ScreenLocker::screen_locker_->OnWindowManagerReady(); +} + views::Textfield* ScreenLockerTester::GetPasswordField() { DCHECK(ScreenLocker::screen_locker_); return ScreenLocker::screen_locker_->screen_lock_view_->password_field_; diff --git a/chrome/browser/chromeos/login/screen_locker_tester.h b/chrome/browser/chromeos/login/screen_locker_tester.h index da2887a..acf5f5d 100644 --- a/chrome/browser/chromeos/login/screen_locker_tester.h +++ b/chrome/browser/chromeos/login/screen_locker_tester.h @@ -32,6 +32,9 @@ class ScreenLockerTester { // Emulates entring a password. void EnterPassword(const char* password); + // Emulates the ready message from window manager. + void EmulateWindowManagerReady(); + // Returns the widget for screen locker window. views::Widget* GetWidget(); |