ben | 294d04b | 2015-10-15 01:23:33 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 5 | #include "mash/wm/window_manager.h" |
ben | 294d04b | 2015-10-15 01:23:33 | [diff] [blame] | 6 | |
avi | 703dbbf | 2015-12-22 01:46:28 | [diff] [blame] | 7 | #include <stdint.h> |
dcheng | e4860045 | 2015-12-28 02:24:50 | [diff] [blame] | 8 | #include <utility> |
avi | 703dbbf | 2015-12-22 01:46:28 | [diff] [blame] | 9 | |
fsamuel | b370b5a | 2015-11-14 01:15:10 | [diff] [blame] | 10 | #include "components/mus/common/types.h" |
fsamuel | 68afcf45 | 2015-10-16 00:12:45 | [diff] [blame] | 11 | #include "components/mus/public/cpp/window.h" |
ben | c6f7263b | 2015-10-27 18:17:33 | [diff] [blame] | 12 | #include "components/mus/public/cpp/window_property.h" |
fsamuel | 68afcf45 | 2015-10-16 00:12:45 | [diff] [blame] | 13 | #include "components/mus/public/cpp/window_tree_connection.h" |
sadrul | 46e2c77b | 2015-10-29 01:39:16 | [diff] [blame] | 14 | #include "components/mus/public/interfaces/input_events.mojom.h" |
sky | fd40949 | 2015-12-08 00:52:35 | [diff] [blame] | 15 | #include "components/mus/public/interfaces/mus_constants.mojom.h" |
| 16 | #include "components/mus/public/interfaces/window_manager.mojom.h" |
sky | b044635 | 2015-11-18 00:43:56 | [diff] [blame] | 17 | #include "mash/wm/non_client_frame_controller.h" |
| 18 | #include "mash/wm/property_util.h" |
| 19 | #include "mash/wm/public/interfaces/container.mojom.h" |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 20 | #include "mash/wm/root_window_controller.h" |
sky | 05b0426 | 2015-10-28 22:44:59 | [diff] [blame] | 21 | #include "mojo/converters/geometry/geometry_type_converters.h" |
sky | d4ca12f | 2015-10-28 18:22:26 | [diff] [blame] | 22 | |
sky | 89c6eb07 | 2015-11-25 20:12:27 | [diff] [blame] | 23 | namespace mash { |
| 24 | namespace wm { |
| 25 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 26 | WindowManager::WindowManager() |
ben | 83cd09069 | 2016-02-03 05:07:27 | [diff] [blame] | 27 | : root_controller_(nullptr), |
| 28 | window_manager_client_(nullptr), |
| 29 | binding_(this) {} |
ben | 294d04b | 2015-10-15 01:23:33 | [diff] [blame] | 30 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 31 | WindowManager::~WindowManager() { |
| 32 | if (!root_controller_) |
sadrul | eaa1be2 | 2015-11-30 23:30:48 | [diff] [blame] | 33 | return; |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 34 | for (auto container : root_controller_->root()->children()) { |
ben | fe6381bc | 2015-12-02 16:07:23 | [diff] [blame] | 35 | container->RemoveObserver(this); |
| 36 | for (auto child : container->children()) |
| 37 | child->RemoveObserver(this); |
| 38 | } |
sky | d4ca12f | 2015-10-28 18:22:26 | [diff] [blame] | 39 | } |
ben | 294d04b | 2015-10-15 01:23:33 | [diff] [blame] | 40 | |
ben | 83cd09069 | 2016-02-03 05:07:27 | [diff] [blame] | 41 | void WindowManager::Initialize(RootWindowController* root_controller, |
ben | c740d5b | 2016-03-18 04:54:27 | [diff] [blame] | 42 | session::mojom::Session* session) { |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 43 | DCHECK(root_controller); |
| 44 | DCHECK(!root_controller_); |
| 45 | root_controller_ = root_controller; |
ben | fe6381bc | 2015-12-02 16:07:23 | [diff] [blame] | 46 | // The children of the root are considered containers. |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 47 | for (auto container : root_controller_->root()->children()) { |
ben | fe6381bc | 2015-12-02 16:07:23 | [diff] [blame] | 48 | container->AddObserver(this); |
| 49 | for (auto child : container->children()) |
| 50 | child->AddObserver(this); |
| 51 | } |
sky | f5ece4e | 2016-01-26 19:40:36 | [diff] [blame] | 52 | |
| 53 | // The insets are roughly what is needed by CustomFrameView. The expectation |
| 54 | // is at some point we'll write our own NonClientFrameView and get the insets |
| 55 | // from it. |
| 56 | mus::mojom::FrameDecorationValuesPtr frame_decoration_values = |
| 57 | mus::mojom::FrameDecorationValues::New(); |
| 58 | const gfx::Insets client_area_insets = |
| 59 | NonClientFrameController::GetPreferredClientAreaInsets(); |
| 60 | frame_decoration_values->normal_client_area_insets = |
| 61 | mojo::Insets::From(client_area_insets); |
| 62 | frame_decoration_values->maximized_client_area_insets = |
| 63 | mojo::Insets::From(client_area_insets); |
| 64 | frame_decoration_values->max_title_bar_button_width = |
| 65 | NonClientFrameController::GetMaxTitleBarButtonWidth(); |
| 66 | window_manager_client_->SetFrameDecorationValues( |
| 67 | std::move(frame_decoration_values)); |
ben | 83cd09069 | 2016-02-03 05:07:27 | [diff] [blame] | 68 | |
ben | c740d5b | 2016-03-18 04:54:27 | [diff] [blame] | 69 | if (session) |
| 70 | session->AddScreenlockStateListener(binding_.CreateInterfacePtrAndBind()); |
sadrul | eaa1be2 | 2015-11-30 23:30:48 | [diff] [blame] | 71 | } |
| 72 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 73 | gfx::Rect WindowManager::CalculateDefaultBounds(mus::Window* window) const { |
| 74 | DCHECK(root_controller_); |
sky | 05111cd | 2015-11-16 22:41:57 | [diff] [blame] | 75 | int width, height; |
| 76 | const gfx::Size pref = GetWindowPreferredSize(window); |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 77 | const mus::Window* root = root_controller_->root(); |
sky | 05111cd | 2015-11-16 22:41:57 | [diff] [blame] | 78 | if (pref.IsEmpty()) { |
| 79 | width = root->bounds().width() - 240; |
| 80 | height = root->bounds().height() - 240; |
| 81 | } else { |
| 82 | // TODO(sky): likely want to constrain more than root size. |
| 83 | const gfx::Size max_size = GetMaximizedWindowBounds().size(); |
| 84 | width = std::max(0, std::min(max_size.width(), pref.width())); |
| 85 | height = std::max(0, std::min(max_size.height(), pref.height())); |
| 86 | } |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 87 | return gfx::Rect(40 + (root_controller_->window_count() % 4) * 40, |
| 88 | 40 + (root_controller_->window_count() % 4) * 40, width, |
| 89 | height); |
sky | 05111cd | 2015-11-16 22:41:57 | [diff] [blame] | 90 | } |
| 91 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 92 | gfx::Rect WindowManager::GetMaximizedWindowBounds() const { |
| 93 | DCHECK(root_controller_); |
| 94 | return gfx::Rect(root_controller_->root()->bounds().size()); |
sky | 05111cd | 2015-11-16 22:41:57 | [diff] [blame] | 95 | } |
| 96 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 97 | mus::Window* WindowManager::NewTopLevelWindow( |
sky | c125e4b | 2016-01-30 00:47:49 | [diff] [blame] | 98 | std::map<std::string, std::vector<uint8_t>>* properties) { |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 99 | DCHECK(root_controller_); |
| 100 | mus::Window* root = root_controller_->root(); |
sky | adfb9237 | 2016-01-07 17:34:24 | [diff] [blame] | 101 | DCHECK(root); |
| 102 | |
| 103 | const bool provide_non_client_frame = |
sammc | 16fb38a8 | 2016-01-21 05:30:18 | [diff] [blame] | 104 | GetWindowType(*properties) == mus::mojom::WindowType::WINDOW; |
sky | adfb9237 | 2016-01-07 17:34:24 | [diff] [blame] | 105 | if (provide_non_client_frame) |
| 106 | (*properties)[mus::mojom::kWaitForUnderlay_Property].clear(); |
| 107 | |
| 108 | // TODO(sky): constrain and validate properties before passing to server. |
| 109 | mus::Window* window = root->connection()->NewWindow(properties); |
| 110 | window->SetBounds(CalculateDefaultBounds(window)); |
| 111 | |
| 112 | mojom::Container container = GetRequestedContainer(window); |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 113 | root_controller_->GetWindowForContainer(container)->AddChild(window); |
sky | adfb9237 | 2016-01-07 17:34:24 | [diff] [blame] | 114 | |
sky | adfb9237 | 2016-01-07 17:34:24 | [diff] [blame] | 115 | if (provide_non_client_frame) { |
sky | 423bc2b | 2016-03-31 20:48:09 | [diff] [blame] | 116 | NonClientFrameController::Create(root_controller_->GetConnector(), window, |
| 117 | root_controller_->window_manager_client()); |
sky | adfb9237 | 2016-01-07 17:34:24 | [diff] [blame] | 118 | } |
| 119 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 120 | root_controller_->IncrementWindowCount(); |
sky | adfb9237 | 2016-01-07 17:34:24 | [diff] [blame] | 121 | |
| 122 | return window; |
| 123 | } |
| 124 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 125 | void WindowManager::OnTreeChanging(const TreeChangeParams& params) { |
| 126 | DCHECK(root_controller_); |
| 127 | if (root_controller_->WindowIsContainer(params.old_parent)) |
sadrul | eaa1be2 | 2015-11-30 23:30:48 | [diff] [blame] | 128 | params.target->RemoveObserver(this); |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 129 | else if (root_controller_->WindowIsContainer(params.new_parent)) |
sadrul | eaa1be2 | 2015-11-30 23:30:48 | [diff] [blame] | 130 | params.target->AddObserver(this); |
| 131 | } |
| 132 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 133 | void WindowManager::OnWindowEmbeddedAppDisconnected(mus::Window* window) { |
sadrul | eaa1be2 | 2015-11-30 23:30:48 | [diff] [blame] | 134 | window->Destroy(); |
| 135 | } |
| 136 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 137 | void WindowManager::SetWindowManagerClient(mus::WindowManagerClient* client) { |
sky | f5ece4e | 2016-01-26 19:40:36 | [diff] [blame] | 138 | window_manager_client_ = client; |
sky | bbcf04eb | 2015-10-15 23:07:56 | [diff] [blame] | 139 | } |
sky | d4ca12f | 2015-10-28 18:22:26 | [diff] [blame] | 140 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 141 | bool WindowManager::OnWmSetBounds(mus::Window* window, gfx::Rect* bounds) { |
sky | 6905d4c | 2015-11-26 01:53:21 | [diff] [blame] | 142 | // By returning true the bounds of |window| is updated. |
| 143 | return true; |
| 144 | } |
| 145 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 146 | bool WindowManager::OnWmSetProperty( |
sky | 6905d4c | 2015-11-26 01:53:21 | [diff] [blame] | 147 | mus::Window* window, |
| 148 | const std::string& name, |
| 149 | scoped_ptr<std::vector<uint8_t>>* new_data) { |
| 150 | // TODO(sky): constrain this to set of keys we know about, and allowed |
| 151 | // values. |
| 152 | return name == mus::mojom::WindowManager::kShowState_Property || |
| 153 | name == mus::mojom::WindowManager::kPreferredSize_Property || |
erg | a665cd1 | 2015-12-11 22:06:53 | [diff] [blame] | 154 | name == mus::mojom::WindowManager::kResizeBehavior_Property || |
jamescook | cac8709 | 2016-03-25 18:11:53 | [diff] [blame] | 155 | name == mus::mojom::WindowManager::kWindowAppIcon_Property || |
erg | a665cd1 | 2015-12-11 22:06:53 | [diff] [blame] | 156 | name == mus::mojom::WindowManager::kWindowTitle_Property; |
sky | 6905d4c | 2015-11-26 01:53:21 | [diff] [blame] | 157 | } |
| 158 | |
sky | 7a35dfa | 2016-02-01 21:37:28 | [diff] [blame] | 159 | mus::Window* WindowManager::OnWmCreateTopLevelWindow( |
sky | adfb9237 | 2016-01-07 17:34:24 | [diff] [blame] | 160 | std::map<std::string, std::vector<uint8_t>>* properties) { |
sky | c125e4b | 2016-01-30 00:47:49 | [diff] [blame] | 161 | return NewTopLevelWindow(properties); |
sky | adfb9237 | 2016-01-07 17:34:24 | [diff] [blame] | 162 | } |
| 163 | |
moshayedi | d41e5ab | 2016-03-18 00:08:15 | [diff] [blame] | 164 | void WindowManager::OnAccelerator(uint32_t id, const ui::Event& event) { |
sky | ffa8df2 | 2016-02-02 05:47:34 | [diff] [blame] | 165 | root_controller_->OnAccelerator(id, std::move(event)); |
| 166 | } |
| 167 | |
ben | 83cd09069 | 2016-02-03 05:07:27 | [diff] [blame] | 168 | void WindowManager::ScreenlockStateChanged(bool locked) { |
| 169 | // Hide USER_PRIVATE windows when the screen is locked. |
| 170 | mus::Window* window = root_controller_->GetWindowForContainer( |
| 171 | mash::wm::mojom::Container::USER_PRIVATE); |
| 172 | window->SetVisible(!locked); |
| 173 | } |
| 174 | |
sky | 89c6eb07 | 2015-11-25 20:12:27 | [diff] [blame] | 175 | } // namespace wm |
| 176 | } // namespace mash |