| // 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. |
| |
| #include <map> |
| |
| #include <gflags/gflags.h> |
| #include <gtest/gtest.h> |
| |
| #include "base/logging.h" |
| #include "window_manager/test_lib.h" |
| #include "window_manager/transient_window_collection.h" |
| #include "window_manager/stacking_manager.h" |
| #include "window_manager/window.h" |
| #include "window_manager/window_manager.h" |
| |
| DEFINE_bool(logtostderr, false, |
| "Print debugging messages to stderr (suppressed otherwise)"); |
| |
| using std::map; |
| |
| namespace window_manager { |
| |
| class TransientWindowCollectionTest : public BasicWindowManagerTest {}; |
| |
| TEST_F(TransientWindowCollectionTest, Stacking) { |
| // Create an owner window and stack it in the fullscreen layer. |
| XWindow owner_xid = CreateSimpleWindow(); |
| XConnection::WindowGeometry geometry; |
| ASSERT_TRUE(xconn_->GetWindowGeometry(owner_xid, &geometry)); |
| Window owner_win(wm_.get(), owner_xid, false, geometry); |
| wm_->stacking_manager()->StackWindowAtTopOfLayer( |
| &owner_win, |
| StackingManager::LAYER_FULLSCREEN_WINDOW, |
| StackingManager::SHADOW_AT_BOTTOM_OF_SHADOW_LAYER, |
| StackingManager::LAYER_FULLSCREEN_WINDOW); |
| |
| TestEventConsumer event_consumer; |
| TransientWindowCollection transients( |
| &owner_win, |
| TransientWindowCollection::STACK_ABOVE_OWNER, |
| TransientWindowCollection::CENTER_OVER_OWNER, |
| TransientWindowCollection::KEEP_ONSCREEN_ALWAYS, |
| &event_consumer); |
| |
| // Create a window to treat as transient. |
| XWindow transient_xid = CreateSimpleWindow(); |
| ASSERT_TRUE(xconn_->GetWindowGeometry(transient_xid, &geometry)); |
| Window transient_win(wm_.get(), transient_xid, false, geometry); |
| |
| // After the window is added to the collection, it should be stacked above its |
| // owner. |
| transients.AddWindow(&transient_win); |
| EXPECT_TRUE(WindowIsInLayer(&transient_win, |
| StackingManager::LAYER_FULLSCREEN_WINDOW)); |
| MockCompositor::StageActor* stage = compositor_->GetDefaultStage(); |
| EXPECT_LT(stage->GetStackingIndex(transient_win.GetBottomActor()), |
| stage->GetStackingIndex(owner_win.GetTopActor())); |
| |
| // Now change the stacking policy and check that the transient is restacked. |
| transients.set_stacking_policy(TransientWindowCollection::STACK_IN_LAYER); |
| transients.ApplyStackingForAllWindows(); |
| EXPECT_TRUE(WindowIsInLayer(&transient_win, |
| StackingManager::LAYER_ACTIVE_TRANSIENT_WINDOW)); |
| |
| // Add a second transient. It should get stacked on top. |
| XWindow transient_xid2 = CreateSimpleWindow(); |
| ASSERT_TRUE(xconn_->GetWindowGeometry(transient_xid2, &geometry)); |
| Window transient_win2(wm_.get(), transient_xid2, false, geometry); |
| transients.AddWindow(&transient_win2); |
| EXPECT_LT(stage->GetStackingIndex(transient_win2.GetBottomActor()), |
| stage->GetStackingIndex(transient_win.GetTopActor())); |
| |
| // Make the second transient modal. |
| map<XAtom, bool> wm_state; |
| wm_state[xconn_->GetAtomOrDie("_NET_WM_STATE_MODAL")] = true; |
| transient_win2.ChangeWmState(wm_state); |
| ASSERT_TRUE(transient_win2.wm_state_modal()); |
| |
| // Now add a third, non-modal transient and check that it gets stacked below |
| // the second transient. |
| XWindow transient_xid3 = CreateSimpleWindow(); |
| ASSERT_TRUE(xconn_->GetWindowGeometry(transient_xid3, &geometry)); |
| Window transient_win3(wm_.get(), transient_xid3, false, geometry); |
| transients.AddWindow(&transient_win3); |
| EXPECT_LT(stage->GetStackingIndex(transient_win2.GetBottomActor()), |
| stage->GetStackingIndex(transient_win3.GetTopActor())); |
| EXPECT_LT(stage->GetStackingIndex(transient_win3.GetBottomActor()), |
| stage->GetStackingIndex(transient_win.GetTopActor())); |
| |
| // If all of the windows are modal, then a fourth, non-modal transient should |
| // get stacked on the bottom. |
| transient_win.ChangeWmState(wm_state); |
| transient_win3.ChangeWmState(wm_state); |
| XWindow transient_xid4 = CreateSimpleWindow(); |
| ASSERT_TRUE(xconn_->GetWindowGeometry(transient_xid4, &geometry)); |
| Window transient_win4(wm_.get(), transient_xid4, false, geometry); |
| transients.AddWindow(&transient_win4); |
| EXPECT_LT(stage->GetStackingIndex(transient_win2.GetBottomActor()), |
| stage->GetStackingIndex(transient_win3.GetTopActor())); |
| EXPECT_LT(stage->GetStackingIndex(transient_win3.GetBottomActor()), |
| stage->GetStackingIndex(transient_win.GetTopActor())); |
| EXPECT_LT(stage->GetStackingIndex(transient_win.GetBottomActor()), |
| stage->GetStackingIndex(transient_win4.GetTopActor())); |
| |
| transients.RemoveWindow(&transient_win); |
| transients.RemoveWindow(&transient_win2); |
| transients.RemoveWindow(&transient_win3); |
| transients.RemoveWindow(&transient_win4); |
| } |
| |
| } // namespace window_manager |
| |
| int main(int argc, char** argv) { |
| return window_manager::InitAndRunTests(&argc, argv, &FLAGS_logtostderr); |
| } |