| // 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. |
| |
| #include <cmath> |
| #include <vector> |
| |
| #include <gflags/gflags.h> |
| #include <gtest/gtest.h> |
| |
| #include "base/logging.h" |
| #include "cros/chromeos_wm_ipc_enums.h" |
| #include "window_manager/compositor/compositor.h" |
| #include "window_manager/event_loop.h" |
| #include "window_manager/screen_locker_handler.h" |
| #include "window_manager/test_lib.h" |
| #include "window_manager/window.h" |
| #include "window_manager/window_manager.h" |
| #include "window_manager/wm_ipc.h" |
| #include "window_manager/x11/mock_x_connection.h" |
| |
| DEFINE_bool(logtostderr, false, |
| "Print debugging messages to stderr (suppressed otherwise)"); |
| |
| using std::vector; |
| |
| namespace window_manager { |
| |
| class ScreenLockerHandlerTest : public BasicWindowManagerTest { |
| protected: |
| virtual void SetUp() { |
| BasicWindowManagerTest::SetUp(); |
| handler_ = wm_->screen_locker_handler_.get(); |
| } |
| |
| MockCompositor::TexturePixmapActor* GetSnapshotActor() { |
| return dynamic_cast<MockCompositor::TexturePixmapActor*>( |
| handler_->snapshot_actor_.get()); |
| } |
| |
| void TestActorConfiguredForSlowClose( |
| MockCompositor::TexturePixmapActor* actor) { |
| static const float kSizeRatio = ScreenLockerHandler::kSlowCloseSizeRatio; |
| CHECK(actor); |
| EXPECT_TRUE(actor->is_shown()); |
| EXPECT_FLOAT_EQ(round(0.5 * (1.0 - kSizeRatio) * wm_->width()), |
| actor->x()); |
| EXPECT_FLOAT_EQ(round(0.5 * (1.0 - kSizeRatio) * wm_->height()), |
| actor->y()); |
| EXPECT_FLOAT_EQ(kSizeRatio, actor->scale_x()); |
| EXPECT_FLOAT_EQ(kSizeRatio, actor->scale_y()); |
| EXPECT_FLOAT_EQ(1.0, actor->opacity()); |
| } |
| |
| void TestActorConfiguredForUndoSlowClose( |
| MockCompositor::TexturePixmapActor* actor) { |
| CHECK(actor); |
| EXPECT_TRUE(actor->is_shown()); |
| EXPECT_EQ(0, actor->x()); |
| EXPECT_EQ(0, actor->y()); |
| EXPECT_FLOAT_EQ(1.0, actor->scale_x()); |
| EXPECT_FLOAT_EQ(1.0, actor->scale_y()); |
| EXPECT_FLOAT_EQ(1.0, actor->opacity()); |
| } |
| |
| void TestActorConfiguredForFastClose( |
| MockCompositor::TexturePixmapActor* actor) { |
| CHECK(actor); |
| EXPECT_TRUE(actor->is_shown()); |
| EXPECT_EQ(static_cast<int>(round(0.5 * wm_->width())), actor->x()); |
| EXPECT_EQ(static_cast<int>(round(0.5 * wm_->height())), actor->y()); |
| EXPECT_FLOAT_EQ(0.0, actor->scale_x()); |
| EXPECT_FLOAT_EQ(0.0, actor->scale_y()); |
| EXPECT_FLOAT_EQ(0.0, actor->opacity()); |
| } |
| |
| void TestActorConfiguredForFadeout( |
| MockCompositor::TexturePixmapActor* actor) { |
| CHECK(actor); |
| EXPECT_TRUE(actor->is_shown()); |
| EXPECT_EQ(0, actor->x()); |
| EXPECT_EQ(0, actor->y()); |
| EXPECT_FLOAT_EQ(1.0, actor->scale_x()); |
| EXPECT_FLOAT_EQ(1.0, actor->scale_y()); |
| EXPECT_FLOAT_EQ(0.0, actor->opacity()); |
| } |
| |
| bool IsOnlyActiveVisibilityGroup(int group) { |
| if (compositor_->active_visibility_groups().size() != |
| static_cast<size_t>(1)) { |
| return false; |
| } |
| return (*(compositor_->active_visibility_groups().begin()) == group); |
| } |
| |
| ScreenLockerHandler* handler_; |
| }; |
| |
| TEST_F(ScreenLockerHandlerTest, BasicLock) { |
| // Create a regular toplevel window. |
| XWindow toplevel_xid = CreateSimpleWindow(); |
| SendInitialEventsForWindow(toplevel_xid); |
| |
| // The window's actor shouldn't be in any visibility groups, and the |
| // compositor shouldn't be restricting its drawing to a particular group. |
| MockCompositor::TexturePixmapActor* toplevel_actor = |
| GetMockActorForWindow(wm_->GetWindowOrDie(toplevel_xid)); |
| EXPECT_TRUE(toplevel_actor->visibility_groups().empty()); |
| EXPECT_TRUE(compositor_->active_visibility_groups().empty()); |
| |
| // Now create a screen locker window. |
| XWindow screen_locker_xid = |
| CreateBasicWindow(5, 5, wm_->width() - 5, wm_->height() - 5); |
| MockXConnection::WindowInfo* screen_locker_info = |
| xconn_->GetWindowInfoOrDie(screen_locker_xid); |
| wm_->wm_ipc()->SetWindowType( |
| screen_locker_xid, chromeos::WM_IPC_WINDOW_CHROME_SCREEN_LOCKER, NULL); |
| WmIpc::Message msg; |
| EXPECT_FALSE( |
| GetFirstWmIpcMessageOfType( |
| screen_locker_xid, |
| chromeos::WM_IPC_MESSAGE_CHROME_NOTIFY_SCREEN_REDRAWN_FOR_LOCK, |
| &msg)); |
| const int initial_num_draws = compositor_->num_draws(); |
| SendInitialEventsForWindow(screen_locker_xid); |
| Window* screen_locker_win = wm_->GetWindowOrDie(screen_locker_xid); |
| MockCompositor::TexturePixmapActor* screen_locker_actor = |
| GetMockActorForWindow(screen_locker_win); |
| |
| // Check that the window was moved to (0, 0), resized to cover the whole |
| // screen, stacked correctly, and shown. |
| EXPECT_EQ(0, screen_locker_info->bounds.x); |
| EXPECT_EQ(0, screen_locker_info->bounds.y); |
| EXPECT_EQ(wm_->width(), screen_locker_info->bounds.width); |
| EXPECT_EQ(wm_->height(), screen_locker_info->bounds.height); |
| EXPECT_EQ(0, screen_locker_actor->GetX()); |
| EXPECT_EQ(0, screen_locker_actor->GetY()); |
| EXPECT_TRUE(WindowIsInLayer(screen_locker_win, |
| StackingManager::LAYER_SCREEN_LOCKER)); |
| EXPECT_TRUE(screen_locker_actor->is_shown()); |
| |
| // This window's actor *should* be added to a group, and this should now |
| // be the only group that we're drawing. |
| EXPECT_EQ(static_cast<size_t>(1), |
| screen_locker_actor->visibility_groups().size()); |
| EXPECT_TRUE(screen_locker_actor->visibility_groups().count( |
| WindowManager::VISIBILITY_GROUP_SCREEN_LOCKER)); |
| EXPECT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SCREEN_LOCKER)); |
| |
| // We should've redrawn the screen and sent the screen locker window a |
| // message letting it know that we did so. We should also update the |
| // _NET_WM_ACTIVE_WINDOW property so that the window's widgets know that it's |
| // active. |
| EXPECT_GT(compositor_->num_draws(), initial_num_draws); |
| EXPECT_TRUE( |
| GetFirstWmIpcMessageOfType( |
| screen_locker_xid, |
| chromeos::WM_IPC_MESSAGE_CHROME_NOTIFY_SCREEN_REDRAWN_FOR_LOCK, |
| &msg)); |
| EXPECT_EQ(screen_locker_xid, GetActiveWindowProperty()); |
| |
| // We shouldn't animate a snapshot of the screen when we go directly from |
| // the unlocked to locked states (without seeing pre-lock) -- this |
| // probably means that the screen's getting locked because the system is |
| // about to be suspended, so we want to make sure that we're not showing |
| // the unlocked contents onscreen (http;//crosbug.com/8867). (It could |
| // also mean that we're running on a system that doesn't report power |
| // button releases correctly.) |
| EXPECT_TRUE(handler_->snapshot_actor_.get() == NULL); |
| |
| // Now resize the root window and check that the screen locker window is |
| // also resized. |
| const XWindow root_xid = xconn_->GetRootWindow(); |
| MockXConnection::WindowInfo* root_info = xconn_->GetWindowInfoOrDie(root_xid); |
| const int new_width = root_info->bounds.width + 20; |
| const int new_height = root_info->bounds.height + 20; |
| xconn_->ResizeWindow(root_xid, Size(new_width, new_height)); |
| XEvent resize_event; |
| xconn_->InitConfigureNotifyEvent(&resize_event, root_xid); |
| wm_->HandleEvent(&resize_event); |
| EXPECT_EQ(new_width, screen_locker_info->bounds.width); |
| EXPECT_EQ(new_height, screen_locker_info->bounds.height); |
| |
| // Unmap the screen locker window and check that the original toplevel |
| // window would be drawn again. |
| ASSERT_TRUE(xconn_->UnmapWindow(screen_locker_xid)); |
| XEvent event; |
| xconn_->InitUnmapEvent(&event, screen_locker_xid); |
| wm_->HandleEvent(&event); |
| EXPECT_TRUE(compositor_->active_visibility_groups().empty()); |
| } |
| |
| TEST_F(ScreenLockerHandlerTest, AbortedLock) { |
| // Tell the window manager that the user started holding the power button |
| // to lock the screen. |
| WmIpc::Message msg(chromeos::WM_IPC_MESSAGE_WM_NOTIFY_POWER_BUTTON_STATE); |
| msg.set_param(0, chromeos::WM_IPC_POWER_BUTTON_PRE_LOCK); |
| SendWmIpcMessage(msg); |
| |
| // We should have taken a snapshot of the screen. |
| MockCompositor::TexturePixmapActor* actor = GetSnapshotActor(); |
| ASSERT_TRUE(actor != NULL); |
| TestActorConfiguredForSlowClose(actor); |
| EXPECT_NE(-1, handler_->destroy_snapshot_timeout_id_); |
| |
| // The snapshot should be the only actor currently visible. |
| EXPECT_EQ(static_cast<size_t>(2), actor->visibility_groups().size()); |
| EXPECT_TRUE(actor->visibility_groups().count( |
| WindowManager::VISIBILITY_GROUP_SCREEN_LOCKER) != 0); |
| EXPECT_TRUE(actor->visibility_groups().count( |
| WindowManager::VISIBILITY_GROUP_SESSION_ENDING) != 0); |
| EXPECT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SCREEN_LOCKER)); |
| |
| // Now tell the WM that the button was released before being held long |
| // enough to lock. |
| msg.set_param(0, chromeos::WM_IPC_POWER_BUTTON_ABORTED_LOCK); |
| SendWmIpcMessage(msg); |
| |
| // Check that we're still showing the same actor, and that it's being |
| // scaled back to its natural size. |
| ASSERT_EQ(actor, GetSnapshotActor()); |
| TestActorConfiguredForUndoSlowClose(actor); |
| |
| // Check that a timeout was registered to destroy the snapshot, and then |
| // invoke the callback and check that the actor was destroyed and we're |
| // displaying all actors again. |
| ASSERT_NE(-1, handler_->destroy_snapshot_timeout_id_); |
| if (!EventLoop::IsTimerFdSupported()) { |
| LOG(ERROR) << "Aborting test because of missing timerfd support"; |
| return; |
| } |
| event_loop_->RunTimeoutForTesting(handler_->destroy_snapshot_timeout_id_); |
| EXPECT_EQ(-1, handler_->destroy_snapshot_timeout_id_); |
| EXPECT_EQ(static_cast<size_t>(0), |
| compositor_->active_visibility_groups().size()); |
| } |
| |
| TEST_F(ScreenLockerHandlerTest, SuccessfulLock) { |
| // Tell the window manager that we're in the pre-lock state. |
| WmIpc::Message msg(chromeos::WM_IPC_MESSAGE_WM_NOTIFY_POWER_BUTTON_STATE); |
| msg.set_param(0, chromeos::WM_IPC_POWER_BUTTON_PRE_LOCK); |
| SendWmIpcMessage(msg); |
| MockCompositor::TexturePixmapActor* actor = GetSnapshotActor(); |
| ASSERT_TRUE(actor != NULL); |
| TestActorConfiguredForSlowClose(actor); |
| |
| // Map a screen locker window. |
| XWindow screen_locker_xid = CreateSimpleWindow(); |
| wm_->wm_ipc()->SetWindowType( |
| screen_locker_xid, chromeos::WM_IPC_WINDOW_CHROME_SCREEN_LOCKER, NULL); |
| SendInitialEventsForWindow(screen_locker_xid); |
| |
| // We should still be showing the snapshot actor, but it should be |
| // getting scaled down to the center of the screen. |
| ASSERT_EQ(actor, GetSnapshotActor()); |
| TestActorConfiguredForFastClose(actor); |
| |
| // Invoke the timeout to destroy it and check that we're showing only the |
| // screen locker window. |
| ASSERT_NE(-1, handler_->destroy_snapshot_timeout_id_); |
| if (!EventLoop::IsTimerFdSupported()) { |
| LOG(ERROR) << "Aborting test because of missing timerfd support"; |
| return; |
| } |
| event_loop_->RunTimeoutForTesting(handler_->destroy_snapshot_timeout_id_); |
| EXPECT_EQ(-1, handler_->destroy_snapshot_timeout_id_); |
| EXPECT_TRUE(GetSnapshotActor() == NULL); |
| EXPECT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SCREEN_LOCKER)); |
| } |
| |
| TEST_F(ScreenLockerHandlerTest, AbortedShutdown) { |
| // Tell the window manager that the user started holding the power button |
| // to shut down the system. |
| WmIpc::Message msg(chromeos::WM_IPC_MESSAGE_WM_NOTIFY_POWER_BUTTON_STATE); |
| msg.set_param(0, chromeos::WM_IPC_POWER_BUTTON_PRE_SHUTDOWN); |
| SendWmIpcMessage(msg); |
| |
| // We should have taken a snapshot of the screen. |
| MockCompositor::TexturePixmapActor* actor = GetSnapshotActor(); |
| ASSERT_TRUE(actor != NULL); |
| TestActorConfiguredForSlowClose(actor); |
| EXPECT_NE(-1, handler_->destroy_snapshot_timeout_id_); |
| |
| // The snapshot should be the only actor currently visible. |
| EXPECT_TRUE(actor->visibility_groups().count( |
| WindowManager::VISIBILITY_GROUP_SESSION_ENDING) != 0); |
| EXPECT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SESSION_ENDING)); |
| |
| // Now tell the WM that the button was released before being held long |
| // enough to shut down. |
| msg.set_param(0, chromeos::WM_IPC_POWER_BUTTON_ABORTED_SHUTDOWN); |
| SendWmIpcMessage(msg); |
| |
| // Check that we're still showing the same actor, and that it's being |
| // scaled back to its natural size. |
| ASSERT_EQ(actor, GetSnapshotActor()); |
| TestActorConfiguredForUndoSlowClose(actor); |
| |
| // Check that a timeout was registered to destroy the snapshot, and then |
| // invoke the callback and check that the actor was destroyed and we're |
| // displaying all actors again. |
| ASSERT_NE(-1, handler_->destroy_snapshot_timeout_id_); |
| if (!EventLoop::IsTimerFdSupported()) { |
| LOG(ERROR) << "Aborting test because of missing timerfd support"; |
| return; |
| } |
| event_loop_->RunTimeoutForTesting(handler_->destroy_snapshot_timeout_id_); |
| EXPECT_EQ(-1, handler_->destroy_snapshot_timeout_id_); |
| EXPECT_EQ(static_cast<size_t>(0), |
| compositor_->active_visibility_groups().size()); |
| |
| // Now map a screen locker window so we can try the same thing from the |
| // locked state. |
| XWindow screen_locker_xid = CreateSimpleWindow(); |
| wm_->wm_ipc()->SetWindowType( |
| screen_locker_xid, chromeos::WM_IPC_WINDOW_CHROME_SCREEN_LOCKER, NULL); |
| SendInitialEventsForWindow(screen_locker_xid); |
| ASSERT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SCREEN_LOCKER)); |
| |
| // Enter the pre-shutdown state as before. |
| msg.set_param(0, chromeos::WM_IPC_POWER_BUTTON_PRE_SHUTDOWN); |
| SendWmIpcMessage(msg); |
| actor = GetSnapshotActor(); |
| ASSERT_TRUE(actor != NULL); |
| TestActorConfiguredForSlowClose(actor); |
| EXPECT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SESSION_ENDING)); |
| |
| // After aborting, we should be showing just the screen locker window. |
| msg.set_param(0, chromeos::WM_IPC_POWER_BUTTON_ABORTED_SHUTDOWN); |
| SendWmIpcMessage(msg); |
| ASSERT_NE(-1, handler_->destroy_snapshot_timeout_id_); |
| event_loop_->RunTimeoutForTesting(handler_->destroy_snapshot_timeout_id_); |
| EXPECT_EQ(-1, handler_->destroy_snapshot_timeout_id_); |
| EXPECT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SCREEN_LOCKER)); |
| } |
| |
| // Test that we do stuff in response to notification that the system is |
| // shutting down. |
| TEST_F(ScreenLockerHandlerTest, HandleShutdown) { |
| // Go into the pre-shutdown state first. |
| WmIpc::Message msg(chromeos::WM_IPC_MESSAGE_WM_NOTIFY_POWER_BUTTON_STATE); |
| msg.set_param(0, chromeos::WM_IPC_POWER_BUTTON_PRE_SHUTDOWN); |
| SendWmIpcMessage(msg); |
| |
| // Check that we've started the slow-close animation. |
| MockCompositor::TexturePixmapActor* actor = GetSnapshotActor(); |
| ASSERT_TRUE(actor != NULL); |
| TestActorConfiguredForSlowClose(actor); |
| EXPECT_NE(-1, handler_->destroy_snapshot_timeout_id_); |
| EXPECT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SESSION_ENDING)); |
| |
| // Notify the window manager that the system is being shut down. |
| msg.set_type(chromeos::WM_IPC_MESSAGE_WM_NOTIFY_SHUTTING_DOWN); |
| msg.set_param(0, 0); |
| SendWmIpcMessage(msg); |
| |
| // Check that we grabbed the pointer and keyboard and assigned a transparent |
| // cursor to the root window. |
| XWindow root = xconn_->GetRootWindow(); |
| EXPECT_EQ(root, xconn_->pointer_grab_xid()); |
| EXPECT_EQ(root, xconn_->keyboard_grab_xid()); |
| EXPECT_EQ(MockXConnection::kTransparentCursor, |
| xconn_->GetWindowInfoOrDie(root)->cursor); |
| |
| // We should be using the same snapshot that we already grabbed, and we |
| // should be displaying the fast-close animation. |
| ASSERT_EQ(actor, GetSnapshotActor()); |
| TestActorConfiguredForFastClose(actor); |
| EXPECT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SESSION_ENDING)); |
| |
| // There's no need to destroy the snapshot after we're done with the |
| // animation; we're not going to be showing anything else onscreen. |
| EXPECT_EQ(-1, handler_->destroy_snapshot_timeout_id_); |
| } |
| |
| // Test that we repeatedly try to grab the pointer and keyboard when the |
| // session is ending. |
| TEST_F(ScreenLockerHandlerTest, InputsAlreadyGrabbed) { |
| // Create a window and pretend that it's grabbed both inputs. |
| XWindow other_xid = CreateSimpleWindow(); |
| xconn_->set_pointer_grab_xid(other_xid); |
| xconn_->set_keyboard_grab_xid(other_xid); |
| |
| // Tell the window manager that the system is shutting down. |
| WmIpc::Message msg(chromeos::WM_IPC_MESSAGE_WM_NOTIFY_SHUTTING_DOWN); |
| SendWmIpcMessage(msg); |
| EXPECT_EQ(other_xid, xconn_->pointer_grab_xid()); |
| EXPECT_EQ(other_xid, xconn_->keyboard_grab_xid()); |
| |
| // Now pretend that the pointer grab was released and check that after the |
| // timeout fires, the WM installs a pointer grab. |
| xconn_->set_pointer_grab_xid(0); |
| EXPECT_NE(-1, handler_->grab_inputs_timeout_id_); |
| event_loop_->RunTimeoutForTesting(handler_->grab_inputs_timeout_id_); |
| EXPECT_EQ(xconn_->GetRootWindow(), xconn_->pointer_grab_xid()); |
| EXPECT_EQ(other_xid, xconn_->keyboard_grab_xid()); |
| |
| // Do the same thing with the keyboard. |
| xconn_->set_keyboard_grab_xid(0); |
| EXPECT_NE(-1, handler_->grab_inputs_timeout_id_); |
| event_loop_->RunTimeoutForTesting(handler_->grab_inputs_timeout_id_); |
| EXPECT_EQ(xconn_->GetRootWindow(), xconn_->pointer_grab_xid()); |
| EXPECT_EQ(xconn_->GetRootWindow(), xconn_->keyboard_grab_xid()); |
| |
| // Both inputs are grabbed, so the timeout should be unregistered now. |
| EXPECT_EQ(-1, handler_->grab_inputs_timeout_id_); |
| } |
| |
| // Test that we don't consider the screen to be locked until the screen |
| // locker window is actually visible. |
| TEST_F(ScreenLockerHandlerTest, DeferLockUntilWindowIsVisible) { |
| // Enable the sync request protocol on a screen locker window before |
| // mapping it so that we'll hold off on fetching its pixmap until it |
| // tells us that it's ready. |
| XWindow screen_locker_xid = CreateSimpleWindow(); |
| wm_->wm_ipc()->SetWindowType( |
| screen_locker_xid, chromeos::WM_IPC_WINDOW_CHROME_SCREEN_LOCKER, NULL); |
| ConfigureWindowForSyncRequestProtocol(screen_locker_xid); |
| |
| // We should continue showing all actors after the locker window is mapped. |
| SendInitialEventsForWindow(screen_locker_xid); |
| Window* screen_locker_win = wm_->GetWindowOrDie(screen_locker_xid); |
| ASSERT_FALSE(screen_locker_win->has_initial_pixmap()); |
| EXPECT_FALSE(handler_->is_locked_); |
| EXPECT_EQ(static_cast<size_t>(0), |
| compositor_->active_visibility_groups().size()); |
| |
| // When we're notified that the pixmap is painted, we should switch to |
| // showing only the screen locker actor. |
| SendSyncRequestProtocolAlarm(screen_locker_xid); |
| ASSERT_TRUE(screen_locker_win->has_initial_pixmap()); |
| EXPECT_TRUE(handler_->is_locked_); |
| EXPECT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SCREEN_LOCKER)); |
| } |
| |
| // Check that when we see an override-redirect info bubble window that asks to |
| // remain visible while the screen is locked, we add it to the screen locker |
| // visibility group. |
| TEST_F(ScreenLockerHandlerTest, ShowSomeOtherWindowsWhileLocked) { |
| XWindow info_bubble_xid = CreateSimpleWindow(); |
| xconn_->GetWindowInfoOrDie(info_bubble_xid)->override_redirect = true; |
| vector<int> params; |
| params.push_back(1); // show while locked |
| wm_->wm_ipc()->SetWindowType( |
| info_bubble_xid, chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE, ¶ms); |
| xconn_->MapWindow(info_bubble_xid); |
| SendInitialEventsForWindow(info_bubble_xid); |
| MockCompositor::TexturePixmapActor* info_bubble_actor = |
| GetMockActorForWindow(wm_->GetWindowOrDie(info_bubble_xid)); |
| EXPECT_TRUE(info_bubble_actor->visibility_groups().count( |
| WindowManager::VISIBILITY_GROUP_SCREEN_LOCKER)); |
| |
| // The actor should be removed from the visibility group when the window is |
| // unmapped. |
| XEvent event; |
| xconn_->InitUnmapEvent(&event, info_bubble_xid); |
| wm_->HandleEvent(&event); |
| EXPECT_FALSE(info_bubble_actor->visibility_groups().count( |
| WindowManager::VISIBILITY_GROUP_SCREEN_LOCKER)); |
| } |
| |
| // Test that we handle messages from Chrome notifying us that the user is |
| // signing out. |
| TEST_F(ScreenLockerHandlerTest, SigningOut) { |
| WmIpc::Message msg(chromeos::WM_IPC_MESSAGE_WM_NOTIFY_SIGNING_OUT); |
| SendWmIpcMessage(msg); |
| |
| // We should grab the pointer and keyboard, assign a transparent cursor to the |
| // root window, and fade out a snapshot of the screen. |
| XWindow root = xconn_->GetRootWindow(); |
| EXPECT_EQ(root, xconn_->pointer_grab_xid()); |
| EXPECT_EQ(root, xconn_->keyboard_grab_xid()); |
| EXPECT_EQ(MockXConnection::kTransparentCursor, |
| xconn_->GetWindowInfoOrDie(root)->cursor); |
| TestActorConfiguredForFadeout(GetSnapshotActor()); |
| EXPECT_TRUE(IsOnlyActiveVisibilityGroup( |
| WindowManager::VISIBILITY_GROUP_SESSION_ENDING)); |
| } |
| |
| } // namespace window_manager |
| |
| int main(int argc, char** argv) { |
| return window_manager::InitAndRunTests(&argc, argv, &FLAGS_logtostderr); |
| } |