OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 "chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h" | |
6 | |
7 #include "ash/shelf/shelf_util.h" | |
8 #include "ash/wm/window_util.h" | |
9 #include "base/bind.h" | |
10 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" | |
11 #include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller .h" | |
12 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" | |
13 #include "components/arc/arc_bridge_service.h" | |
14 #include "components/exo/shell_surface.h" | |
15 #include "ui/aura/env.h" | |
16 #include "ui/base/base_window.h" | |
17 #include "ui/views/widget/widget.h" | |
18 | |
19 class ArcAppWindowLauncherController::AppWindow : public ui::BaseWindow { | |
20 public: | |
21 AppWindow(int task_id, views::Widget* widget) | |
22 : task_id_(task_id), widget_(widget) {} | |
23 ~AppWindow() {} | |
24 | |
25 void SetController(ArcAppWindowLauncherItemController* controller) { | |
26 DCHECK(!controller_ && controller); | |
27 controller_ = controller; | |
28 } | |
29 | |
30 int task_id() const { return task_id_; } | |
31 | |
32 ArcAppWindowLauncherItemController* controller() { return controller_; } | |
33 | |
34 // ui::BaseWindow: | |
35 bool IsActive() const override { return widget_->IsActive(); } | |
36 | |
37 bool IsMaximized() const override { return widget_->IsMaximized(); } | |
38 | |
39 bool IsMinimized() const override { return widget_->IsMinimized(); } | |
40 | |
41 bool IsFullscreen() const override { return widget_->IsFullscreen(); } | |
42 | |
43 gfx::NativeWindow GetNativeWindow() const override { | |
44 return widget_->GetNativeWindow(); | |
45 } | |
46 | |
47 gfx::Rect GetRestoredBounds() const override { | |
48 return widget_->GetRestoredBounds(); | |
49 } | |
50 | |
51 ui::WindowShowState GetRestoredState() const override { | |
52 // Stub implementation. See also ChromeNativeAppWindowViews. | |
53 if (IsMaximized()) | |
54 return ui::SHOW_STATE_MAXIMIZED; | |
55 if (IsFullscreen()) | |
56 return ui::SHOW_STATE_FULLSCREEN; | |
57 return ui::SHOW_STATE_NORMAL; | |
58 } | |
59 | |
60 gfx::Rect GetBounds() const override { | |
61 return widget_->GetWindowBoundsInScreen(); | |
62 } | |
63 | |
64 void Show() override { | |
65 if (widget_->IsVisible()) { | |
66 widget_->Activate(); | |
67 return; | |
68 } | |
69 widget_->Show(); | |
70 } | |
71 | |
72 void ShowInactive() override { | |
73 if (widget_->IsVisible()) | |
74 return; | |
75 | |
76 widget_->ShowInactive(); | |
77 } | |
78 | |
79 void Hide() override { widget_->Hide(); } | |
80 | |
81 void Close() override { widget_->Close(); } | |
82 | |
83 void Activate() override { widget_->Activate(); } | |
84 | |
85 void Deactivate() override { widget_->Deactivate(); } | |
86 | |
87 void Maximize() override { widget_->Maximize(); } | |
88 | |
89 void Minimize() override { widget_->Minimize(); } | |
90 | |
91 void Restore() override { widget_->Restore(); } | |
92 | |
93 void SetBounds(const gfx::Rect& bounds) override { | |
94 widget_->SetBounds(bounds); | |
95 } | |
96 | |
97 void FlashFrame(bool flash) override { widget_->FlashFrame(flash); } | |
98 | |
99 bool IsAlwaysOnTop() const override { return widget_->IsAlwaysOnTop(); } | |
100 | |
101 void SetAlwaysOnTop(bool always_on_top) override { | |
102 widget_->SetAlwaysOnTop(always_on_top); | |
103 } | |
104 | |
105 private: | |
106 int task_id_; | |
107 // Unowned pointers | |
108 views::Widget* widget_; | |
109 ArcAppWindowLauncherItemController* controller_ = nullptr; | |
110 | |
111 DISALLOW_COPY_AND_ASSIGN(AppWindow); | |
112 }; | |
113 | |
114 ArcAppWindowLauncherController::ArcAppWindowLauncherController( | |
115 ChromeLauncherController* owner) | |
116 : AppWindowLauncherController(owner), observed_windows_(this) { | |
117 aura::Env* env = aura::Env::GetInstanceDontCreate(); | |
118 if (env) | |
119 env->AddObserver(this); | |
120 } | |
121 | |
122 ArcAppWindowLauncherController::~ArcAppWindowLauncherController() { | |
123 aura::Env* env = aura::Env::GetInstanceDontCreate(); | |
124 if (env) | |
125 env->RemoveObserver(this); | |
126 } | |
127 | |
128 void ArcAppWindowLauncherController::OnWindowInitialized(aura::Window* window) { | |
129 DCHECK(!observed_windows_.IsObserving(window)); | |
130 | |
131 // Root Arc window has type WINDOW_TYPE_NORMAL. | |
132 if (window->type() != ui::wm::WINDOW_TYPE_NORMAL) | |
xiyuan
2016/03/23 23:22:53
Does ARC++ provide some way to observe its window?
khmel
2016/03/24 16:30:37
At this moment no, At my first implementation I ad
xiyuan
2016/03/24 16:47:16
Acknowledged.
| |
133 return; | |
134 | |
135 observed_windows_.Add(window); | |
136 } | |
137 | |
138 void ArcAppWindowLauncherController::OnWindowPropertyChanged( | |
139 aura::Window* window, | |
140 const void* key, | |
141 intptr_t old) { | |
142 if (window_to_app_window_.find(window) != window_to_app_window_.end()) | |
143 return; | |
144 | |
145 const std::string app_id = exo::ShellSurface::GetApplicationId(window); | |
146 if (app_id.empty()) | |
147 return; | |
148 | |
149 int task_id = 0; | |
150 if (sscanf(app_id.c_str(), "org.chromium.arc.%d", &task_id) != 1 || !task_id) | |
151 return; | |
152 | |
153 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window); | |
154 DCHECK(widget); | |
155 window_to_app_window_[window].reset(new AppWindow(task_id, widget)); | |
156 | |
157 arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); | |
158 if (!bridge_service) { | |
159 NOTREACHED(); | |
160 return; | |
161 } | |
162 | |
163 arc::AppInstance* app_instance = bridge_service->app_instance(); | |
164 if (!app_instance) { | |
165 VLOG(2) << "Request to resolve task when bridge service is not ready."; | |
166 return; | |
167 } | |
168 | |
169 // Resolve information about task. | |
170 app_instance->GetTaskInfo( | |
171 task_id, base::Bind(&ArcAppWindowLauncherController::OnGetTaskInfo, | |
172 base::Unretained(this), task_id)); | |
xiyuan
2016/03/23 23:22:53
WeakPtr instead of base::Unretained(this) ?
khmel
2016/03/24 16:30:37
Done.
| |
173 } | |
174 | |
175 void ArcAppWindowLauncherController::OnWindowDestroying(aura::Window* window) { | |
176 DCHECK(observed_windows_.IsObserving(window)); | |
177 observed_windows_.Remove(window); | |
178 | |
179 WindowToAppWindow::iterator it = window_to_app_window_.find(window); | |
180 if (it == window_to_app_window_.end()) | |
181 return; | |
182 | |
183 ArcAppWindowLauncherItemController* controller = it->second->controller(); | |
184 if (controller) { | |
185 const std::string app_id = controller->app_id(); | |
186 controller->RemoveWindowForNativeWindow(window); | |
187 if (!controller->window_count()) { | |
188 ash::ShelfID shelf_id = ash::GetShelfIDForWindow(window); | |
189 DCHECK(shelf_id); | |
190 owner()->CloseLauncherItem(shelf_id); | |
191 AppControllerMap::iterator it2 = app_controller_map_.find(app_id); | |
192 DCHECK(it2 != app_controller_map_.end()); | |
193 app_controller_map_.erase(it2); | |
194 } | |
195 } | |
196 window_to_app_window_.erase(it); | |
197 } | |
198 | |
199 ArcAppWindowLauncherController::AppWindow* | |
200 ArcAppWindowLauncherController::GetAppWindowForTask(int task_id) { | |
201 for (auto& it : window_to_app_window_) { | |
202 if (it.second->task_id() == task_id) | |
203 return it.second.get(); | |
204 } | |
205 return nullptr; | |
206 } | |
207 | |
208 void ArcAppWindowLauncherController::OnGetTaskInfo(int task_id, | |
209 mojo::String package_name, | |
210 mojo::String activity_name) { | |
211 AppWindow* app_window = GetAppWindowForTask(task_id); | |
212 if (!app_window) | |
213 return; | |
214 | |
215 DCHECK(app_window && !app_window->controller()); | |
216 ash::ShelfItemStatus status = | |
217 ash::wm::IsActiveWindow(app_window->GetNativeWindow()) | |
218 ? ash::STATUS_ACTIVE | |
219 : ash::STATUS_RUNNING; | |
220 | |
221 const std::string app_id = | |
222 ArcAppListPrefs::GetAppId(package_name, activity_name); | |
223 | |
224 ArcAppWindowLauncherItemController* controller; | |
225 AppControllerMap::iterator it = app_controller_map_.find(app_id); | |
226 ash::ShelfID shelf_id = 0; | |
227 if (it != app_controller_map_.end()) { | |
228 controller = it->second; | |
229 DCHECK(controller->app_id() == app_id); | |
230 shelf_id = controller->shelf_id(); | |
231 controller->AddWindow(app_window); | |
232 } else { | |
233 controller = new ArcAppWindowLauncherItemController(app_id, owner()); | |
234 controller->AddWindow(app_window); | |
235 shelf_id = owner()->GetShelfIDForAppID(app_id); | |
236 if (shelf_id == 0) | |
237 shelf_id = owner()->CreateAppLauncherItem(controller, app_id, status); | |
238 else | |
239 owner()->SetItemController(shelf_id, controller); | |
xiyuan
2016/03/23 23:22:53
We should probably update CreateAppLauncherItem an
khmel
2016/03/24 16:30:37
Actually owner of this is ShelfItemDelegateManager
xiyuan
2016/03/24 16:47:16
Acknowledged.
| |
240 app_controller_map_[app_id] = controller; | |
241 } | |
242 app_window->SetController(controller); | |
243 owner()->SetItemStatus(shelf_id, status); | |
244 ash::SetShelfIDForWindow(shelf_id, app_window->GetNativeWindow()); | |
245 } | |
246 | |
247 AppWindowLauncherItemController* | |
248 ArcAppWindowLauncherController::ControllerForWindow(aura::Window* window) { | |
249 WindowToAppWindow::iterator it = window_to_app_window_.find(window); | |
250 if (it == window_to_app_window_.end()) | |
251 return nullptr; | |
252 return it->second->controller(); | |
253 } | |
OLD | NEW |