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 |