summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/window_sizer_ash.cc
blob: bb4148fbf3b26572056c7f2c8002ad9ab4dfa1b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright (c) 2012 The Chromium 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 "chrome/browser/ui/window_sizer.h"

#include "ash/shell.h"
#include "ash/wm/window_cycle_controller.h"
#include "ash/wm/window_util.h"
#include "base/compiler_specific.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/gfx/screen.h"

namespace {

// Check if the window was not created as popup or as panel.
bool IsValidToplevelWindow(aura::Window* window) {
  for (BrowserList::const_iterator iter = BrowserList::begin();
       iter != BrowserList::end();
       ++iter) {
    Browser* browser = *iter;
    if (browser && browser->window() &&
        browser->window()->GetNativeHandle() == window) {
      return (!(browser->is_type_popup() || browser->is_type_panel()));
    }
  }
  // A window which has no browser associated with it is probably not a window
  // of which we want to copy the size from.
  return false;
}

// Get the first open window in the stack on the screen.
aura::Window* GetTopWindow() {
  // Get the active window.
  aura::Window* window = ash::wm::GetActiveWindow();
  if (window && window->type() == aura::client::WINDOW_TYPE_NORMAL &&
      window->IsVisible() && IsValidToplevelWindow(window))
    return window;

  // Get a list of all windows.
  const std::vector<aura::Window*> windows =
      ash::WindowCycleController::BuildWindowList();

  if (windows.empty())
    return NULL;

  aura::Window::Windows::const_iterator iter = windows.begin();
  // Find the index of the current window.
  if (window)
    iter = std::find(windows.begin(), windows.end(), window);

  int index = (iter == windows.end()) ? 0 : (iter - windows.begin());

  // Scan the cycle list backwards to see which is the second topmost window
  // (and so on). Note that we might cycle a few indices twice if there is no
  // suitable window. However - since the list is fairly small this should be
  // very fast anyways.
  for (int i = index + windows.size(); i >= 0; i--) {
    aura::Window* window = windows[i % windows.size()];
    if (window && window->type() == aura::client::WINDOW_TYPE_NORMAL &&
        window->IsVisible() && IsValidToplevelWindow(window))
      return window;
  }
  return NULL;
}

}  // namespace

bool WindowSizer::GetBoundsIgnoringPreviousState(
    const gfx::Rect& specified_bounds,
    gfx::Rect* bounds) const {
  *bounds = specified_bounds;
  DCHECK(bounds->IsEmpty());
  if (browser_ != NULL && browser_->type() == Browser::TYPE_TABBED) {
    // This is a window / app. See if there is no window and try to place it.
    aura::Window* top_window = GetTopWindow();
    // If there are no windows we have a special case and try to
    // maximize which leaves a 'border' which shows the desktop.
    if (top_window == NULL) {
      GetDefaultWindowBounds(bounds);
    } else {
      *bounds = top_window->GetBoundsInRootWindow();
    }
    return true;
    // If both fail we will continue the default path.
  }

  return false;
}

void WindowSizer::GetDefaultWindowBounds(gfx::Rect* default_bounds) const {
  DCHECK(default_bounds);
  DCHECK(monitor_info_provider_.get());

  gfx::Rect work_area = monitor_info_provider_->GetPrimaryMonitorWorkArea();

  DCHECK_EQ(kDesktopBorderSize, ash::Shell::GetInstance()->GetGridSize());

  // There should be a 'desktop' border around the window at the left and right
  // side.
  int default_width = work_area.width() - 2 * kDesktopBorderSize;
  // There should also be a 'desktop' border around the window at the top.
  // Since the workspace excludes the tray area we only need one border size.
  int default_height = work_area.height() - kDesktopBorderSize;
  // We align the size to the grid size to avoid any surprise when the
  // monitor height isn't divide-able by our alignment factor.
  default_width -= default_width % kDesktopBorderSize;
  default_height -= default_height % kDesktopBorderSize;
  int offset_x = kDesktopBorderSize;
  int maximum_window_width = 1280;
  if (default_width > maximum_window_width) {
    // The window should get centered on the screen and not follow the grid.
    offset_x = (work_area.width() - maximum_window_width) / 2;
    // Never make a window wider then 1280.
    default_width = maximum_window_width;
  }
  default_bounds->SetRect(work_area.x() + offset_x,
                          work_area.y() + kDesktopBorderSize,
                          default_width,
                          default_height);
}