| OLD | NEW |
| (Empty) |
| 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 | |
| 5 #include "mash/wm/user_window_controller_impl.h" | |
| 6 | |
| 7 #include "ash/public/interfaces/container.mojom.h" | |
| 8 #include "components/mus/public/cpp/property_type_converters.h" | |
| 9 #include "components/mus/public/cpp/window.h" | |
| 10 #include "components/mus/public/cpp/window_property.h" | |
| 11 #include "components/mus/public/cpp/window_tree_client.h" | |
| 12 #include "mash/wm/property_util.h" | |
| 13 #include "mash/wm/root_window_controller.h" | |
| 14 #include "mojo/common/common_type_converters.h" | |
| 15 #include "ui/resources/grit/ui_resources.h" | |
| 16 | |
| 17 MUS_DECLARE_WINDOW_PROPERTY_TYPE(uint32_t); | |
| 18 | |
| 19 namespace mash { | |
| 20 namespace wm { | |
| 21 | |
| 22 // Key used for storing identifier sent to clients for windows. | |
| 23 MUS_DEFINE_LOCAL_WINDOW_PROPERTY_KEY(uint32_t, kUserWindowIdKey, 0u); | |
| 24 | |
| 25 namespace { | |
| 26 | |
| 27 // Returns |window|, or an ancestor thereof, parented to |container|, or null. | |
| 28 mus::Window* GetTopLevelWindow(mus::Window* window, mus::Window* container) { | |
| 29 while (window && window->parent() != container) | |
| 30 window = window->parent(); | |
| 31 return window; | |
| 32 } | |
| 33 | |
| 34 // Get a UserWindow struct from a mus::Window. | |
| 35 ash::mojom::UserWindowPtr GetUserWindow(mus::Window* window) { | |
| 36 ash::mojom::UserWindowPtr user_window(ash::mojom::UserWindow::New()); | |
| 37 DCHECK_NE(0u, window->GetLocalProperty(kUserWindowIdKey)); | |
| 38 user_window->window_id = window->GetLocalProperty(kUserWindowIdKey); | |
| 39 user_window->window_title = mojo::String::From(GetWindowTitle(window)); | |
| 40 user_window->window_app_icon = GetWindowAppIcon(window); | |
| 41 user_window->window_app_id = mojo::String::From(GetAppID(window)); | |
| 42 user_window->ignored_by_shelf = GetWindowIgnoredByShelf(window); | |
| 43 mus::Window* focused = window->window_tree()->GetFocusedWindow(); | |
| 44 focused = GetTopLevelWindow(focused, window->parent()); | |
| 45 user_window->window_has_focus = focused == window; | |
| 46 return user_window; | |
| 47 } | |
| 48 | |
| 49 } // namespace | |
| 50 | |
| 51 // Observes property changes on user windows. UserWindowControllerImpl uses | |
| 52 // this separate observer to avoid observing duplicate tree change | |
| 53 // notifications. | |
| 54 class WindowPropertyObserver : public mus::WindowObserver { | |
| 55 public: | |
| 56 explicit WindowPropertyObserver(UserWindowControllerImpl* controller) | |
| 57 : controller_(controller) {} | |
| 58 ~WindowPropertyObserver() override {} | |
| 59 | |
| 60 private: | |
| 61 // mus::WindowObserver: | |
| 62 void OnWindowSharedPropertyChanged( | |
| 63 mus::Window* window, | |
| 64 const std::string& name, | |
| 65 const std::vector<uint8_t>* old_data, | |
| 66 const std::vector<uint8_t>* new_data) override { | |
| 67 if (!controller_->user_window_observer()) | |
| 68 return; | |
| 69 if (name == mus::mojom::WindowManager::kWindowTitle_Property) { | |
| 70 controller_->user_window_observer()->OnUserWindowTitleChanged( | |
| 71 window->GetLocalProperty(kUserWindowIdKey), | |
| 72 mojo::String::From(GetWindowTitle(window))); | |
| 73 } else if (name == mus::mojom::WindowManager::kWindowAppIcon_Property) { | |
| 74 controller_->user_window_observer()->OnUserWindowAppIconChanged( | |
| 75 window->GetLocalProperty(kUserWindowIdKey), | |
| 76 new_data ? mojo::Array<uint8_t>::From(*new_data) | |
| 77 : mojo::Array<uint8_t>()); | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 UserWindowControllerImpl* controller_; | |
| 82 DISALLOW_COPY_AND_ASSIGN(WindowPropertyObserver); | |
| 83 }; | |
| 84 | |
| 85 UserWindowControllerImpl::UserWindowControllerImpl() | |
| 86 : root_controller_(nullptr) {} | |
| 87 | |
| 88 UserWindowControllerImpl::~UserWindowControllerImpl() { | |
| 89 if (!root_controller_) | |
| 90 return; | |
| 91 | |
| 92 mus::Window* user_container = GetUserWindowContainer(); | |
| 93 if (!user_container) | |
| 94 return; | |
| 95 | |
| 96 RemoveObservers(user_container); | |
| 97 } | |
| 98 | |
| 99 void UserWindowControllerImpl::Initialize( | |
| 100 RootWindowController* root_controller) { | |
| 101 DCHECK(root_controller); | |
| 102 DCHECK(!root_controller_); | |
| 103 root_controller_ = root_controller; | |
| 104 GetUserWindowContainer()->AddObserver(this); | |
| 105 GetUserWindowContainer()->window_tree()->AddObserver(this); | |
| 106 window_property_observer_.reset(new WindowPropertyObserver(this)); | |
| 107 for (mus::Window* window : GetUserWindowContainer()->children()) { | |
| 108 AssignIdIfNecessary(window); | |
| 109 window->AddObserver(window_property_observer_.get()); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 void UserWindowControllerImpl::AssignIdIfNecessary(mus::Window* window) { | |
| 114 if (window->GetLocalProperty(kUserWindowIdKey) == 0u) | |
| 115 window->SetLocalProperty(kUserWindowIdKey, next_id_++); | |
| 116 } | |
| 117 | |
| 118 void UserWindowControllerImpl::RemoveObservers(mus::Window* user_container) { | |
| 119 user_container->RemoveObserver(this); | |
| 120 user_container->window_tree()->RemoveObserver(this); | |
| 121 for (auto iter : user_container->children()) | |
| 122 iter->RemoveObserver(window_property_observer_.get()); | |
| 123 } | |
| 124 | |
| 125 mus::Window* UserWindowControllerImpl::GetUserWindowById(uint32_t id) { | |
| 126 for (mus::Window* window : GetUserWindowContainer()->children()) { | |
| 127 if (window->GetLocalProperty(kUserWindowIdKey) == id) | |
| 128 return window; | |
| 129 } | |
| 130 return nullptr; | |
| 131 } | |
| 132 | |
| 133 mus::Window* UserWindowControllerImpl::GetUserWindowContainer() const { | |
| 134 return root_controller_->GetWindowForContainer( | |
| 135 ash::mojom::Container::USER_PRIVATE_WINDOWS); | |
| 136 } | |
| 137 | |
| 138 void UserWindowControllerImpl::OnTreeChanging(const TreeChangeParams& params) { | |
| 139 DCHECK(root_controller_); | |
| 140 if (params.new_parent == GetUserWindowContainer()) { | |
| 141 params.target->AddObserver(window_property_observer_.get()); | |
| 142 AssignIdIfNecessary(params.target); | |
| 143 if (user_window_observer_) | |
| 144 user_window_observer_->OnUserWindowAdded(GetUserWindow(params.target)); | |
| 145 } else if (params.old_parent == GetUserWindowContainer()) { | |
| 146 params.target->RemoveObserver(window_property_observer_.get()); | |
| 147 if (user_window_observer_) | |
| 148 user_window_observer_->OnUserWindowRemoved( | |
| 149 params.target->GetLocalProperty(kUserWindowIdKey)); | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 void UserWindowControllerImpl::OnWindowDestroying(mus::Window* window) { | |
| 154 if (window == GetUserWindowContainer()) | |
| 155 RemoveObservers(window); | |
| 156 } | |
| 157 | |
| 158 void UserWindowControllerImpl::OnWindowTreeFocusChanged( | |
| 159 mus::Window* gained_focus, | |
| 160 mus::Window* lost_focus) { | |
| 161 if (!user_window_observer_) | |
| 162 return; | |
| 163 | |
| 164 // Treat focus in the user window hierarchy as focus of the top-level window. | |
| 165 gained_focus = GetTopLevelWindow(gained_focus, GetUserWindowContainer()); | |
| 166 lost_focus = GetTopLevelWindow(lost_focus, GetUserWindowContainer()); | |
| 167 if (gained_focus == lost_focus) | |
| 168 return; | |
| 169 | |
| 170 if (lost_focus) { | |
| 171 user_window_observer_->OnUserWindowFocusChanged( | |
| 172 lost_focus->GetLocalProperty(kUserWindowIdKey), false); | |
| 173 } | |
| 174 if (gained_focus) { | |
| 175 user_window_observer_->OnUserWindowFocusChanged( | |
| 176 gained_focus->GetLocalProperty(kUserWindowIdKey), true); | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 void UserWindowControllerImpl::AddUserWindowObserver( | |
| 181 ash::mojom::UserWindowObserverPtr observer) { | |
| 182 // TODO(msw): Support multiple observers. | |
| 183 user_window_observer_ = std::move(observer); | |
| 184 | |
| 185 const mus::Window::Children& windows = GetUserWindowContainer()->children(); | |
| 186 mojo::Array<ash::mojom::UserWindowPtr> user_windows = | |
| 187 mojo::Array<ash::mojom::UserWindowPtr>::New(windows.size()); | |
| 188 for (size_t i = 0; i < windows.size(); ++i) | |
| 189 user_windows[i] = GetUserWindow(windows[i]); | |
| 190 user_window_observer_->OnUserWindowObserverAdded(std::move(user_windows)); | |
| 191 } | |
| 192 | |
| 193 void UserWindowControllerImpl::FocusUserWindow(uint32_t window_id) { | |
| 194 mus::Window* window = GetUserWindowById(window_id); | |
| 195 if (window) | |
| 196 window->SetFocus(); | |
| 197 } | |
| 198 | |
| 199 } // namespace wm | |
| 200 } // namespace mash | |
| OLD | NEW |