Chromium Code Reviews| Index: chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc |
| diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..54fbeafd509bdd81086c8920163b8c90b6ef0843 |
| --- /dev/null |
| +++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc |
| @@ -0,0 +1,253 @@ |
| +// Copyright 2016 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/ash/launcher/arc_app_window_launcher_controller.h" |
| + |
| +#include "ash/shelf/shelf_util.h" |
| +#include "ash/wm/window_util.h" |
| +#include "base/bind.h" |
| +#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" |
| +#include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.h" |
| +#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" |
| +#include "components/arc/arc_bridge_service.h" |
| +#include "components/exo/shell_surface.h" |
| +#include "ui/aura/env.h" |
| +#include "ui/base/base_window.h" |
| +#include "ui/views/widget/widget.h" |
| + |
| +class ArcAppWindowLauncherController::AppWindow : public ui::BaseWindow { |
| + public: |
| + AppWindow(int task_id, views::Widget* widget) |
| + : task_id_(task_id), widget_(widget) {} |
| + ~AppWindow() {} |
| + |
| + void SetController(ArcAppWindowLauncherItemController* controller) { |
| + DCHECK(!controller_ && controller); |
| + controller_ = controller; |
| + } |
| + |
| + int task_id() const { return task_id_; } |
| + |
| + ArcAppWindowLauncherItemController* controller() { return controller_; } |
| + |
| + // ui::BaseWindow: |
| + bool IsActive() const override { return widget_->IsActive(); } |
| + |
| + bool IsMaximized() const override { return widget_->IsMaximized(); } |
| + |
| + bool IsMinimized() const override { return widget_->IsMinimized(); } |
| + |
| + bool IsFullscreen() const override { return widget_->IsFullscreen(); } |
| + |
| + gfx::NativeWindow GetNativeWindow() const override { |
| + return widget_->GetNativeWindow(); |
| + } |
| + |
| + gfx::Rect GetRestoredBounds() const override { |
| + return widget_->GetRestoredBounds(); |
| + } |
| + |
| + ui::WindowShowState GetRestoredState() const override { |
| + // Stub implementation. See also ChromeNativeAppWindowViews. |
| + if (IsMaximized()) |
| + return ui::SHOW_STATE_MAXIMIZED; |
| + if (IsFullscreen()) |
| + return ui::SHOW_STATE_FULLSCREEN; |
| + return ui::SHOW_STATE_NORMAL; |
| + } |
| + |
| + gfx::Rect GetBounds() const override { |
| + return widget_->GetWindowBoundsInScreen(); |
| + } |
| + |
| + void Show() override { |
| + if (widget_->IsVisible()) { |
| + widget_->Activate(); |
| + return; |
| + } |
| + widget_->Show(); |
| + } |
| + |
| + void ShowInactive() override { |
| + if (widget_->IsVisible()) |
| + return; |
| + |
| + widget_->ShowInactive(); |
| + } |
| + |
| + void Hide() override { widget_->Hide(); } |
| + |
| + void Close() override { widget_->Close(); } |
| + |
| + void Activate() override { widget_->Activate(); } |
| + |
| + void Deactivate() override { widget_->Deactivate(); } |
| + |
| + void Maximize() override { widget_->Maximize(); } |
| + |
| + void Minimize() override { widget_->Minimize(); } |
| + |
| + void Restore() override { widget_->Restore(); } |
| + |
| + void SetBounds(const gfx::Rect& bounds) override { |
| + widget_->SetBounds(bounds); |
| + } |
| + |
| + void FlashFrame(bool flash) override { widget_->FlashFrame(flash); } |
| + |
| + bool IsAlwaysOnTop() const override { return widget_->IsAlwaysOnTop(); } |
| + |
| + void SetAlwaysOnTop(bool always_on_top) override { |
| + widget_->SetAlwaysOnTop(always_on_top); |
| + } |
| + |
| + private: |
| + int task_id_; |
| + // Unowned pointers |
| + views::Widget* widget_; |
| + ArcAppWindowLauncherItemController* controller_ = nullptr; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(AppWindow); |
| +}; |
| + |
| +ArcAppWindowLauncherController::ArcAppWindowLauncherController( |
| + ChromeLauncherController* owner) |
| + : AppWindowLauncherController(owner), observed_windows_(this) { |
| + aura::Env* env = aura::Env::GetInstanceDontCreate(); |
| + if (env) |
| + env->AddObserver(this); |
| +} |
| + |
| +ArcAppWindowLauncherController::~ArcAppWindowLauncherController() { |
| + aura::Env* env = aura::Env::GetInstanceDontCreate(); |
| + if (env) |
| + env->RemoveObserver(this); |
| +} |
| + |
| +void ArcAppWindowLauncherController::OnWindowInitialized(aura::Window* window) { |
| + DCHECK(!observed_windows_.IsObserving(window)); |
| + |
| + // Root Arc window has type WINDOW_TYPE_NORMAL. |
| + 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.
|
| + return; |
| + |
| + observed_windows_.Add(window); |
| +} |
| + |
| +void ArcAppWindowLauncherController::OnWindowPropertyChanged( |
| + aura::Window* window, |
| + const void* key, |
| + intptr_t old) { |
| + if (window_to_app_window_.find(window) != window_to_app_window_.end()) |
| + return; |
| + |
| + const std::string app_id = exo::ShellSurface::GetApplicationId(window); |
| + if (app_id.empty()) |
| + return; |
| + |
| + int task_id = 0; |
| + if (sscanf(app_id.c_str(), "org.chromium.arc.%d", &task_id) != 1 || !task_id) |
| + return; |
| + |
| + views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window); |
| + DCHECK(widget); |
| + window_to_app_window_[window].reset(new AppWindow(task_id, widget)); |
| + |
| + arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); |
| + if (!bridge_service) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + |
| + arc::AppInstance* app_instance = bridge_service->app_instance(); |
| + if (!app_instance) { |
| + VLOG(2) << "Request to resolve task when bridge service is not ready."; |
| + return; |
| + } |
| + |
| + // Resolve information about task. |
| + app_instance->GetTaskInfo( |
| + task_id, base::Bind(&ArcAppWindowLauncherController::OnGetTaskInfo, |
| + 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.
|
| +} |
| + |
| +void ArcAppWindowLauncherController::OnWindowDestroying(aura::Window* window) { |
| + DCHECK(observed_windows_.IsObserving(window)); |
| + observed_windows_.Remove(window); |
| + |
| + WindowToAppWindow::iterator it = window_to_app_window_.find(window); |
| + if (it == window_to_app_window_.end()) |
| + return; |
| + |
| + ArcAppWindowLauncherItemController* controller = it->second->controller(); |
| + if (controller) { |
| + const std::string app_id = controller->app_id(); |
| + controller->RemoveWindowForNativeWindow(window); |
| + if (!controller->window_count()) { |
| + ash::ShelfID shelf_id = ash::GetShelfIDForWindow(window); |
| + DCHECK(shelf_id); |
| + owner()->CloseLauncherItem(shelf_id); |
| + AppControllerMap::iterator it2 = app_controller_map_.find(app_id); |
| + DCHECK(it2 != app_controller_map_.end()); |
| + app_controller_map_.erase(it2); |
| + } |
| + } |
| + window_to_app_window_.erase(it); |
| +} |
| + |
| +ArcAppWindowLauncherController::AppWindow* |
| +ArcAppWindowLauncherController::GetAppWindowForTask(int task_id) { |
| + for (auto& it : window_to_app_window_) { |
| + if (it.second->task_id() == task_id) |
| + return it.second.get(); |
| + } |
| + return nullptr; |
| +} |
| + |
| +void ArcAppWindowLauncherController::OnGetTaskInfo(int task_id, |
| + mojo::String package_name, |
| + mojo::String activity_name) { |
| + AppWindow* app_window = GetAppWindowForTask(task_id); |
| + if (!app_window) |
| + return; |
| + |
| + DCHECK(app_window && !app_window->controller()); |
| + ash::ShelfItemStatus status = |
| + ash::wm::IsActiveWindow(app_window->GetNativeWindow()) |
| + ? ash::STATUS_ACTIVE |
| + : ash::STATUS_RUNNING; |
| + |
| + const std::string app_id = |
| + ArcAppListPrefs::GetAppId(package_name, activity_name); |
| + |
| + ArcAppWindowLauncherItemController* controller; |
| + AppControllerMap::iterator it = app_controller_map_.find(app_id); |
| + ash::ShelfID shelf_id = 0; |
| + if (it != app_controller_map_.end()) { |
| + controller = it->second; |
| + DCHECK(controller->app_id() == app_id); |
| + shelf_id = controller->shelf_id(); |
| + controller->AddWindow(app_window); |
| + } else { |
| + controller = new ArcAppWindowLauncherItemController(app_id, owner()); |
| + controller->AddWindow(app_window); |
| + shelf_id = owner()->GetShelfIDForAppID(app_id); |
| + if (shelf_id == 0) |
| + shelf_id = owner()->CreateAppLauncherItem(controller, app_id, status); |
| + else |
| + 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.
|
| + app_controller_map_[app_id] = controller; |
| + } |
| + app_window->SetController(controller); |
| + owner()->SetItemStatus(shelf_id, status); |
| + ash::SetShelfIDForWindow(shelf_id, app_window->GetNativeWindow()); |
| +} |
| + |
| +AppWindowLauncherItemController* |
| +ArcAppWindowLauncherController::ControllerForWindow(aura::Window* window) { |
| + WindowToAppWindow::iterator it = window_to_app_window_.find(window); |
| + if (it == window_to_app_window_.end()) |
| + return nullptr; |
| + return it->second->controller(); |
| +} |