Skip to content

Commit

Permalink
This is the 1st CL to add Virtual Screen Coordinates to ash.
Browse files Browse the repository at this point in the history
- Add flag to enable virtual screen coordinate system
- Changed StackingController to use the bounds to pick the matching root window when the virtual screen coordinates is enabled.
- Added Shell::GetRootWindowMatching. Updated Shell::GetRootWindowAt to use VSC when enabled.

BUG=123160
TEST=ExtendedDesktopTest.CycleWindow is changed to use virtual screen coordinate. ExtendedDesktopTest.{GetRootRootAt|GetRootWindowMatching)

Review URL: https://chromiumcodereview.appspot.com/10637007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@143770 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
oshima@chromium.org committed Jun 23, 2012
1 parent e4ddff2 commit 20c5976
Show file tree
Hide file tree
Showing 18 changed files with 206 additions and 43 deletions.
3 changes: 3 additions & 0 deletions ash/ash_switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ const char kAshNotifyDisabled[] = "ash-notify-disabled";
// Enables the heads-up display for tracking touch points.
const char kAshTouchHud[] = "ash-touch-hud";

// Enables virtual screen coordinate system.
const char kAshVirtualScreenCoordinates[] = "ash-virtual-screen-coordinates";

// If present animations are disabled.
const char kAshWindowAnimationsDisabled[] = "ash-window-animations-disabled";

Expand Down
1 change: 1 addition & 0 deletions ash/ash_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ ASH_EXPORT extern const char kAshEnableOak[];
ASH_EXPORT extern const char kAshExtendedDesktop[];
ASH_EXPORT extern const char kAshNotifyDisabled[];
ASH_EXPORT extern const char kAshTouchHud[];
ASH_EXPORT extern const char kAshVirtualScreenCoordinates[];
ASH_EXPORT extern const char kAshWindowAnimationsDisabled[];
ASH_EXPORT extern const char kAuraGoogleDialogFrames[];
ASH_EXPORT extern const char kAuraLegacyPowerButton[];
Expand Down
83 changes: 72 additions & 11 deletions ash/extended_desktop_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,18 +186,19 @@ TEST_F(ExtendedDesktopTest, TestCursor) {
}

TEST_F(ExtendedDesktopTest, CycleWindows) {
UpdateMonitor("0+0-1000x600,1001+0-600x400");
internal::MonitorController::SetVirtualScreenCoordinatesEnabled(true);
UpdateMonitor("0+0-700x500,0+0-500x500");
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
// Emulate virtual screen coordinate system.
root_windows[0]->SetBounds(gfx::Rect(0, 0, 700, 500));
root_windows[1]->SetBounds(gfx::Rect(700, 0, 500, 500));

WindowCycleController* controller =
Shell::GetInstance()->window_cycle_controller();

// Switch active windows between root windows.
Shell::GetInstance()->set_active_root_window(root_windows[0]);
views::Widget* d1_w1 = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
EXPECT_EQ(root_windows[0], d1_w1->GetNativeView()->GetRootWindow());

Shell::GetInstance()->set_active_root_window(root_windows[1]);
views::Widget* d2_w1 = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
views::Widget* d2_w1 = CreateTestWidget(gfx::Rect(800, 10, 100, 100));
EXPECT_EQ(root_windows[1], d2_w1->GetNativeView()->GetRootWindow());
EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));

Expand All @@ -211,12 +212,9 @@ TEST_F(ExtendedDesktopTest, CycleWindows) {
EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));

// Cycle through all windows across root windows.
Shell::GetInstance()->set_active_root_window(root_windows[0]);
views::Widget* d1_w2 = CreateTestWidget(gfx::Rect(100, 100, 100, 100));
views::Widget* d1_w2 = CreateTestWidget(gfx::Rect(10, 200, 100, 100));
EXPECT_EQ(root_windows[0], d1_w2->GetNativeView()->GetRootWindow());

Shell::GetInstance()->set_active_root_window(root_windows[1]);
views::Widget* d2_w2 = CreateTestWidget(gfx::Rect(100, 100, 100, 100));
views::Widget* d2_w2 = CreateTestWidget(gfx::Rect(800, 200, 100, 100));
EXPECT_EQ(root_windows[1], d2_w2->GetNativeView()->GetRootWindow());

controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
Expand All @@ -237,6 +235,69 @@ TEST_F(ExtendedDesktopTest, CycleWindows) {
EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
EXPECT_TRUE(wm::IsActiveWindow(d2_w2->GetNativeView()));
internal::MonitorController::SetVirtualScreenCoordinatesEnabled(false);
}

TEST_F(ExtendedDesktopTest, GetRootWindowAt) {
internal::MonitorController::SetVirtualScreenCoordinatesEnabled(true);
UpdateMonitor("0+0-700x500,0+0-500x500");
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
// Emulate virtual screen coordinate system.
root_windows[0]->SetBounds(gfx::Rect(500, 0, 700, 500));
root_windows[1]->SetBounds(gfx::Rect(0, 0, 500, 500));

EXPECT_EQ(root_windows[1], Shell::GetRootWindowAt(gfx::Point(100, 100)));
EXPECT_EQ(root_windows[1], Shell::GetRootWindowAt(gfx::Point(499, 100)));
EXPECT_EQ(root_windows[0], Shell::GetRootWindowAt(gfx::Point(500, 300)));
EXPECT_EQ(root_windows[0], Shell::GetRootWindowAt(gfx::Point(1200,300)));

// Zero origin.
EXPECT_EQ(root_windows[1], Shell::GetRootWindowAt(gfx::Point(0, 0)));

// Out of range point should return the primary root window
EXPECT_EQ(root_windows[0], Shell::GetRootWindowAt(gfx::Point(-100, 0)));
EXPECT_EQ(root_windows[0], Shell::GetRootWindowAt(gfx::Point(1201, 100)));
internal::MonitorController::SetVirtualScreenCoordinatesEnabled(false);
}

TEST_F(ExtendedDesktopTest, GetRootWindowMatching) {
internal::MonitorController::SetVirtualScreenCoordinatesEnabled(true);
UpdateMonitor("0+0-700x500,0+0-500x500");
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
// Emulate virtual screen coordinate system.
root_windows[0]->SetBounds(gfx::Rect(500, 0, 700, 500));
root_windows[1]->SetBounds(gfx::Rect(0, 0, 500, 500));

// Containing rect.
EXPECT_EQ(root_windows[1],
Shell::GetRootWindowMatching(gfx::Rect(200, 10, 50, 50)));
EXPECT_EQ(root_windows[0],
Shell::GetRootWindowMatching(gfx::Rect(600, 10, 50, 50)));

// Intersecting rect.
EXPECT_EQ(root_windows[1],
Shell::GetRootWindowMatching(gfx::Rect(300, 0, 300, 300)));
EXPECT_EQ(root_windows[0],
Shell::GetRootWindowMatching(gfx::Rect(400, 0, 300, 300)));

// Zero origin.
EXPECT_EQ(root_windows[1],
Shell::GetRootWindowMatching(gfx::Rect(0, 0, 0, 0)));
EXPECT_EQ(root_windows[1],
Shell::GetRootWindowMatching(gfx::Rect(0, 0, 1, 1)));

// Empty rect.
EXPECT_EQ(root_windows[1],
Shell::GetRootWindowMatching(gfx::Rect(100, 100, 0, 0)));
EXPECT_EQ(root_windows[0],
Shell::GetRootWindowMatching(gfx::Rect(600, 100, 0, 0)));

// Out of range rect should return the primary root window.
EXPECT_EQ(root_windows[0],
Shell::GetRootWindowMatching(gfx::Rect(-100, -300, 50, 50)));
EXPECT_EQ(root_windows[0],
Shell::GetRootWindowMatching(gfx::Rect(0, 2000, 50, 50)));
internal::MonitorController::SetVirtualScreenCoordinatesEnabled(false);
}

TEST_F(ExtendedDesktopTest, Capture) {
Expand Down
16 changes: 16 additions & 0 deletions ash/monitor/monitor_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
namespace ash {
namespace internal {
namespace {
// True if the extended desktop mode is enabled.
bool extended_desktop_enabled = false;

// True if the virtual screen coordinates is enabled.
bool virtual_screen_coordinates_enabled = false;
}

MonitorController::MonitorController()
Expand Down Expand Up @@ -230,6 +234,18 @@ void MonitorController::SetExtendedDesktopEnabled(bool enabled) {
extended_desktop_enabled = enabled;
}

// static
bool MonitorController::IsVirtualScreenCoordinatesEnabled() {
return virtual_screen_coordinates_enabled ||
CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAshVirtualScreenCoordinates);
}

// static
void MonitorController::SetVirtualScreenCoordinatesEnabled(bool enabled) {
virtual_screen_coordinates_enabled = enabled;
}

aura::RootWindow* MonitorController::AddRootWindowForDisplay(
const gfx::Display& display) {
aura::RootWindow* root = aura::Env::GetInstance()->monitor_manager()->
Expand Down
5 changes: 5 additions & 0 deletions ash/monitor/monitor_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ class ASH_EXPORT MonitorController : public aura::DisplayObserver {
// Change the extended desktop mode. Used for testing.
static void SetExtendedDesktopEnabled(bool enabled);

// Is virtual screen coordinates enabled?
static bool IsVirtualScreenCoordinatesEnabled();
// Turns on/off the virtual screen coordinates.
static void SetVirtualScreenCoordinatesEnabled(bool enabled);

private:
// Creates a root window for |display| and stores it in the |root_windows_|
// map.
Expand Down
35 changes: 34 additions & 1 deletion ash/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -312,10 +312,43 @@ aura::RootWindow* Shell::GetActiveRootWindow() {

// static
aura::RootWindow* Shell::GetRootWindowAt(const gfx::Point& point) {
// TODO(oshima): Support multiple root windows.
if (!internal::MonitorController::IsVirtualScreenCoordinatesEnabled())
return GetPrimaryRootWindow();
RootWindowList root_windows = GetAllRootWindows();
for (RootWindowList::const_iterator iter = root_windows.begin();
iter != root_windows.end(); ++iter) {
aura::RootWindow* root_window = *iter;
if (root_window->bounds().Contains(point))
return root_window;
}
// Fallback to the primary window if there is no root window containing
// the |point|.
return GetPrimaryRootWindow();
}

// static
aura::RootWindow* Shell::GetRootWindowMatching(const gfx::Rect& rect) {
if (!internal::MonitorController::IsVirtualScreenCoordinatesEnabled())
return GetPrimaryRootWindow();
if (rect.IsEmpty())
return GetRootWindowAt(rect.origin());
RootWindowList root_windows = GetAllRootWindows();
int max = 0;
aura::RootWindow* matching = NULL;
for (RootWindowList::const_iterator iter = root_windows.begin();
iter != root_windows.end(); ++iter) {
aura::RootWindow* root_window = *iter;
gfx::Rect intersect = root_window->bounds().Intersect(rect);
int area = intersect.width() * intersect.height();
if (area > max) {
max = area;
matching = root_window;
}
}
// Fallback to the primary window if there is no matching root window.
return matching ? matching : GetPrimaryRootWindow();
}

// static
Shell::RootWindowList Shell::GetAllRootWindows() {
return Shell::GetInstance()->monitor_controller()->
Expand Down
4 changes: 4 additions & 0 deletions ash/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ class ASH_EXPORT Shell : aura::CursorDelegate {
// point.
static aura::RootWindow* GetRootWindowAt(const gfx::Point& point);

// Returns the RootWindow that shares the most area with |rect| in
// the virtual scren coordinates.
static aura::RootWindow* GetRootWindowMatching(const gfx::Rect& rect);

// Returns all root windows. In non extended desktop mode, this
// returns the primary root window only.
static RootWindowList GetAllRootWindows();
Expand Down
56 changes: 37 additions & 19 deletions ash/wm/stacking_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "ash/wm/stacking_controller.h"

#include "ash/monitor/monitor_controller.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/always_on_top_controller.h"
Expand All @@ -17,8 +18,21 @@ namespace ash {
namespace internal {
namespace {

aura::Window* GetContainerById(int id) {
return Shell::GetContainer(Shell::GetActiveRootWindow(), id);
// Find a root window that matches the |bounds|. If the virtual screen
// coordinates is enabled and the bounds is specified, the root window
// that matches the window's bound will be used. Otherwise, it'll
// return the active root window.
aura::RootWindow* FindContainerRoot(const gfx::Rect& bounds) {
if (!MonitorController::IsVirtualScreenCoordinatesEnabled() ||
(bounds.origin().x() == 0 && bounds.origin().y() == 0
&& bounds.IsEmpty())) {
return Shell::GetActiveRootWindow();
}
return Shell::GetRootWindowMatching(bounds);
}

aura::Window* GetContainerById(const gfx::Rect& bounds, int id) {
return Shell::GetContainer(FindContainerRoot(bounds), id);
}

aura::Window* GetContainerForWindow(aura::Window* window) {
Expand Down Expand Up @@ -52,25 +66,26 @@ StackingController::~StackingController() {
////////////////////////////////////////////////////////////////////////////////
// StackingController, aura::StackingClient implementation:

aura::Window* StackingController::GetDefaultParent(aura::Window* window) {
aura::Window* StackingController::GetDefaultParent(aura::Window* window,
const gfx::Rect& bounds) {
switch (window->type()) {
case aura::client::WINDOW_TYPE_NORMAL:
case aura::client::WINDOW_TYPE_POPUP:
if (IsSystemModal(window))
return GetSystemModalContainer(window);
return GetSystemModalContainer(window, bounds);
else if (IsWindowModal(window))
return GetContainerForWindow(window->transient_parent());
return GetAlwaysOnTopController()->GetContainer(window);
return GetAlwaysOnTopController(bounds)->GetContainer(window);
case aura::client::WINDOW_TYPE_PANEL:
return GetContainerById(internal::kShellWindowId_PanelContainer);
return GetContainerById(bounds, internal::kShellWindowId_PanelContainer);
case aura::client::WINDOW_TYPE_MENU:
return GetContainerById(internal::kShellWindowId_MenuContainer);
return GetContainerById(bounds, internal::kShellWindowId_MenuContainer);
case aura::client::WINDOW_TYPE_TOOLTIP:
return GetContainerById(
internal::kShellWindowId_DragImageAndTooltipContainer);
bounds, internal::kShellWindowId_DragImageAndTooltipContainer);
case aura::client::WINDOW_TYPE_CONTROL:
return GetContainerById(
internal::kShellWindowId_UnparentedControlContainer);
bounds, internal::kShellWindowId_UnparentedControlContainer);
default:
NOTREACHED() << "Window " << window->id()
<< " has unhandled type " << window->type();
Expand All @@ -83,16 +98,19 @@ aura::Window* StackingController::GetDefaultParent(aura::Window* window) {
// StackingController, private:

aura::Window* StackingController::GetSystemModalContainer(
aura::Window* window) const {
if (!IsSystemModal(window))
return NULL;
aura::Window* window,
const gfx::Rect& bounds) const {
DCHECK(IsSystemModal(window));

// If screen lock is not active, all modal windows are placed into the
// normal modal container.
// TODO(oshima): support multiple root windows.
aura::Window* lock_container =
GetContainerById(internal::kShellWindowId_LockScreenContainer);
if (!lock_container->children().size())
return GetContainerById(internal::kShellWindowId_SystemModalContainer);
GetContainerById(bounds, internal::kShellWindowId_LockScreenContainer);
if (!lock_container->children().size()) {
return GetContainerById(bounds,
internal::kShellWindowId_SystemModalContainer);
}

// Otherwise those that originate from LockScreen container and above are
// placed in the screen lock modal container.
Expand All @@ -102,18 +120,18 @@ aura::Window* StackingController::GetSystemModalContainer(
aura::Window* container = NULL;
if (window_container_id < lock_container_id) {
container = GetContainerById(
internal::kShellWindowId_SystemModalContainer);
bounds, internal::kShellWindowId_SystemModalContainer);
} else {
container = GetContainerById(
internal::kShellWindowId_LockSystemModalContainer);
bounds, internal::kShellWindowId_LockSystemModalContainer);
}

return container;
}

internal::AlwaysOnTopController*
StackingController::GetAlwaysOnTopController() {
aura::RootWindow* root_window = Shell::GetActiveRootWindow();
StackingController::GetAlwaysOnTopController(const gfx::Rect& bounds) {
aura::RootWindow* root_window = FindContainerRoot(bounds);
internal::AlwaysOnTopController* controller =
root_window->GetProperty(internal::kAlwaysOnTopControllerKey);
if (!controller) {
Expand Down
12 changes: 8 additions & 4 deletions ash/wm/stacking_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,22 @@ class StackingController : public aura::client::StackingClient {
virtual ~StackingController();

// Overridden from aura::client::StackingClient:
virtual aura::Window* GetDefaultParent(aura::Window* window) OVERRIDE;
virtual aura::Window* GetDefaultParent(aura::Window* window,
const gfx::Rect& bounds) OVERRIDE;

private:
// Returns corresponding system modal container for a modal window.
// If screen lock is not active, all system modal windows are placed into the
// normal modal container.
// Otherwise those that originate from LockScreen container and above are
// placed in the screen lock modal container.
aura::Window* GetSystemModalContainer(aura::Window* window) const;
aura::Window* GetSystemModalContainer(aura::Window* window,
const gfx::Rect& bounds) const;

// Returns the AlwaysOnTopController for the current active root window.
internal::AlwaysOnTopController* GetAlwaysOnTopController();
// Returns the AlwaysOnTopController of the root window that matches
// |bounds|.
internal::AlwaysOnTopController* GetAlwaysOnTopController(
const gfx::Rect& bounds);

DISALLOW_COPY_AND_ASSIGN(StackingController);
};
Expand Down
6 changes: 5 additions & 1 deletion ui/aura/client/stacking_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

#include "ui/aura/aura_export.h"

namespace gfx {
class Rect;
}

namespace aura {
class Window;
namespace client {
Expand All @@ -19,7 +23,7 @@ class AURA_EXPORT StackingClient {

// Called by the Window when its parent is set to NULL, returns the window
// that |window| should be added to instead.
virtual Window* GetDefaultParent(Window* window) = 0;
virtual Window* GetDefaultParent(Window* window, const gfx::Rect& bounds) = 0;
};

AURA_EXPORT void SetStackingClient(StackingClient* stacking_client);
Expand Down
3 changes: 2 additions & 1 deletion ui/aura/demo/demo_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ class DemoStackingClient : public aura::client::StackingClient {
}

// Overridden from aura::client::StackingClient:
virtual aura::Window* GetDefaultParent(aura::Window* window) OVERRIDE {
virtual aura::Window* GetDefaultParent(aura::Window* window,
const gfx::Rect& bounds) OVERRIDE {
return root_window_;
}

Expand Down
Loading

0 comments on commit 20c5976

Please sign in to comment.