wm: Make _NET_ACTIVE_WINDOW contain transient windows.

We previously only stored "toplevel" (i.e. maximized)
windows in this hint, but storing transients there when they
have the focus will hopefully get along better with Chrome's
info bubble implementation.

Intended to fix http://code.google.com/p/chromium-os/issues/detail?id=1012.

Review URL: http://codereview.chromium.org/506026
diff --git a/layout_manager.cc b/layout_manager.cc
index 66d1b21..b8a2425 100644
--- a/layout_manager.cc
+++ b/layout_manager.cc
@@ -288,8 +288,6 @@
           if (mode_ == MODE_ACTIVE &&
               active_toplevel_ != NULL &&
               active_toplevel_->IsWindowOrTransientFocused()) {
-            // The _NET_ACTIVE_WINDOW property should already refer to
-            // 'active_toplevel_', since it previously had the focus.
             active_toplevel_->TakeFocus(wm_->GetCurrentTimeFromServer());
           }
           break;
@@ -492,10 +490,11 @@
     return false;
   toplevel->HandleFocusChange(win, focus_in);
 
-  // When a transient window gets the focus, we say that its owner is the
-  // "active" window (in the _NET_ACTIVE_WINDOW sense).
+  // Announce that the new window is the "active" window (in the
+  // _NET_ACTIVE_WINDOW sense), regardless of whether it's a toplevel
+  // window or a transient.
   if (focus_in)
-    wm_->SetActiveWindowProperty(toplevel->win()->xid());
+    wm_->SetActiveWindowProperty(win->xid());
 
   return true;
 }
diff --git a/layout_manager_test.cc b/layout_manager_test.cc
index 28a0d33..9fc1a99 100644
--- a/layout_manager_test.cc
+++ b/layout_manager_test.cc
@@ -130,13 +130,13 @@
   EXPECT_EQ(xid, xconn_->focused_xid());
   ASSERT_TRUE(lm_->active_toplevel_ != NULL);
   EXPECT_EQ(xid, lm_->active_toplevel_->win()->xid());
-  EXPECT_EQ(None, wm_->active_window_xid());
+  EXPECT_EQ(None, GetActiveWindowProperty());
   EXPECT_TRUE(info->all_buttons_grabbed);
 
   // We shouldn't actually update _NET_ACTIVE_WINDOW and remove the passive
   // button grab until we get the FocusIn event.
   SendFocusEvents(xconn_->GetRootWindow(), xid);
-  EXPECT_EQ(xid, wm_->active_window_xid());
+  EXPECT_EQ(xid, GetActiveWindowProperty());
   EXPECT_FALSE(info->all_buttons_grabbed);
 
   // Now create a second window.
@@ -161,7 +161,7 @@
 
   // Now send the appropriate FocusOut and FocusIn events.
   SendFocusEvents(xid, xid2);
-  EXPECT_EQ(xid2, wm_->active_window_xid());
+  EXPECT_EQ(xid2, GetActiveWindowProperty());
   EXPECT_TRUE(info->all_buttons_grabbed);
   EXPECT_FALSE(info2->all_buttons_grabbed);
 
@@ -182,7 +182,7 @@
 
   // Send the appropriate FocusOut and FocusIn events.
   SendFocusEvents(xid2, xid);
-  EXPECT_EQ(xid, wm_->active_window_xid());
+  EXPECT_EQ(xid, GetActiveWindowProperty());
   EXPECT_FALSE(info->all_buttons_grabbed);
   EXPECT_TRUE(info2->all_buttons_grabbed);
 
@@ -194,7 +194,7 @@
   EXPECT_EQ(xid2, lm_->active_toplevel_->win()->xid());
 
   SendFocusEvents(None, xid2);
-  EXPECT_EQ(xid2, wm_->active_window_xid());
+  EXPECT_EQ(xid2, GetActiveWindowProperty());
   EXPECT_FALSE(info2->all_buttons_grabbed);
 }
 
@@ -280,7 +280,7 @@
   EXPECT_EQ(xid, xconn_->focused_xid());
   SendFocusEvents(xconn_->GetRootWindow(), xid);
   EXPECT_FALSE(info->all_buttons_grabbed);
-  EXPECT_EQ(xid, wm_->active_window_xid());
+  EXPECT_EQ(xid, GetActiveWindowProperty());
   EXPECT_TRUE(wm_->GetWindow(xid)->focused());
 
   // Now create a transient window.
@@ -304,9 +304,9 @@
   EXPECT_FALSE(wm_->GetWindow(xid)->focused());
   EXPECT_TRUE(wm_->GetWindow(transient_xid)->focused());
 
-  // _NET_ACTIVE_WINDOW should still be set to the owner instead of the
-  // transient window, though.
-  EXPECT_EQ(xid, wm_->active_window_xid());
+  // _NET_ACTIVE_WINDOW should also be set to the transient window (EWMH is
+  // vague about this, but it seems to match what other WMs do).
+  EXPECT_EQ(transient_xid, GetActiveWindowProperty());
 
   // Now simulate a button press on the owner window.
   xconn_->set_pointer_grab_xid(xid);
@@ -323,7 +323,7 @@
   SendFocusEvents(transient_xid, xid);
   EXPECT_FALSE(info->all_buttons_grabbed);
   EXPECT_TRUE(transient_info->all_buttons_grabbed);
-  EXPECT_EQ(xid, wm_->active_window_xid());
+  EXPECT_EQ(xid, GetActiveWindowProperty());
   EXPECT_TRUE(wm_->GetWindow(xid)->focused());
   EXPECT_FALSE(wm_->GetWindow(transient_xid)->focused());
 
@@ -333,6 +333,7 @@
   EXPECT_TRUE(wm_->HandleEvent(&event));
   EXPECT_EQ(transient_xid, xconn_->focused_xid());
   SendFocusEvents(xid, transient_xid);
+  EXPECT_EQ(transient_xid, GetActiveWindowProperty());
   EXPECT_FALSE(wm_->GetWindow(xid)->focused());
   EXPECT_TRUE(wm_->GetWindow(transient_xid)->focused());
 
@@ -348,17 +349,18 @@
   MockXConnection::InitButtonPressEvent(&event, xid, 0, 0, 1);
   EXPECT_TRUE(wm_->HandleEvent(&event));
   EXPECT_EQ(transient_xid, xconn_->focused_xid());
+  EXPECT_EQ(transient_xid, GetActiveWindowProperty());
   EXPECT_FALSE(wm_->GetWindow(xid)->focused());
   EXPECT_TRUE(wm_->GetWindow(transient_xid)->focused());
 
-  // Now create another top-level window, which we'll switch to
+  // Now create another toplevel window, which we'll switch to
   // automatically.
   XWindow xid2 = CreateSimpleWindow();
   MockXConnection::WindowInfo* info2 = xconn_->GetWindowInfoOrDie(xid2);
   SendInitialEventsForWindow(xid2);
   EXPECT_EQ(xid2, xconn_->focused_xid());
   SendFocusEvents(transient_xid, xid2);
-  EXPECT_EQ(xid2, wm_->active_window_xid());
+  EXPECT_EQ(xid2, GetActiveWindowProperty());
   EXPECT_FALSE(wm_->GetWindow(xid)->focused());
   EXPECT_FALSE(wm_->GetWindow(transient_xid)->focused());
   EXPECT_TRUE(wm_->GetWindow(xid2)->focused());
@@ -368,7 +370,7 @@
   lm_->CycleActiveToplevelWindow(false);
   EXPECT_EQ(transient_xid, xconn_->focused_xid());
   SendFocusEvents(xid2, transient_xid);
-  EXPECT_EQ(xid, wm_->active_window_xid());
+  EXPECT_EQ(transient_xid, GetActiveWindowProperty());
   EXPECT_FALSE(wm_->GetWindow(xid)->focused());
   EXPECT_TRUE(wm_->GetWindow(transient_xid)->focused());
   EXPECT_FALSE(wm_->GetWindow(xid2)->focused());
@@ -377,7 +379,7 @@
   lm_->CycleActiveToplevelWindow(false);
   EXPECT_EQ(xid2, xconn_->focused_xid());
   SendFocusEvents(transient_xid, xid2);
-  EXPECT_EQ(xid2, wm_->active_window_xid());
+  EXPECT_EQ(xid2, GetActiveWindowProperty());
   EXPECT_FALSE(wm_->GetWindow(xid)->focused());
   EXPECT_FALSE(wm_->GetWindow(transient_xid)->focused());
   EXPECT_TRUE(wm_->GetWindow(xid2)->focused());
@@ -402,7 +404,7 @@
   MockXConnection::InitFocusInEvent(
       &event, transient_xid, NotifyNormal, NotifyNonlinear);
   EXPECT_TRUE(wm_->HandleEvent(&event));
-  EXPECT_EQ(xid, wm_->active_window_xid());
+  EXPECT_EQ(transient_xid, GetActiveWindowProperty());
   EXPECT_FALSE(wm_->GetWindow(xid)->focused());
   EXPECT_TRUE(wm_->GetWindow(transient_xid)->focused());
   EXPECT_FALSE(wm_->GetWindow(xid2)->focused());
@@ -418,7 +420,7 @@
   MockXConnection::InitFocusInEvent(
       &event, transient_xid, NotifyWhileGrabbed, NotifyPointer);
   EXPECT_FALSE(wm_->HandleEvent(&event));
-  EXPECT_EQ(None, wm_->active_window_xid());
+  EXPECT_EQ(None, GetActiveWindowProperty());
   EXPECT_FALSE(wm_->GetWindow(xid)->focused());
   EXPECT_FALSE(wm_->GetWindow(transient_xid)->focused());
   EXPECT_FALSE(wm_->GetWindow(xid2)->focused());
diff --git a/panel_bar_test.cc b/panel_bar_test.cc
index 3a9a2e0..7770c58 100644
--- a/panel_bar_test.cc
+++ b/panel_bar_test.cc
@@ -43,7 +43,7 @@
   // It should be initially focused.
   EXPECT_EQ(toplevel_xid, xconn_->focused_xid());
   SendFocusEvents(xconn_->GetRootWindow(), toplevel_xid);
-  EXPECT_EQ(toplevel_xid, wm_->active_window_xid());
+  EXPECT_EQ(toplevel_xid, GetActiveWindowProperty());
 
   // Now create a panel titlebar, and then the actual panel window.
   const int initial_titlebar_height = 16;
@@ -119,7 +119,7 @@
   // Send FocusOut and FocusIn events and check that the active window hint
   // is updated to contain the panel window.
   SendFocusEvents(toplevel_xid, panel_xid);
-  EXPECT_EQ(panel_xid, wm_->active_window_xid());
+  EXPECT_EQ(panel_xid, GetActiveWindowProperty());
 
   // Create a second toplevel window.
   XWindow toplevel_xid2 = CreateSimpleWindow();