Commit 167f2c01 authored by Wei Lee's avatar Wei Lee Committed by Commit Bot

[CCA WebUI] Implement CameraAppWindowStateController

This is for SWA version to control its window state just as we did in
Chrome App Window API.

Bug: 980846
Test: Tested with previous CLs to make sure the window state is
controllable in the SWA version of CCA.

Change-Id: Ib757e78ed0d9a9bec23f1e78c5a257d6e312bc4c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2257084
Commit-Queue: Wei Lee <wtlee@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarInker Kuo <inker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#822610}
parent 27fe6066
...@@ -18,6 +18,8 @@ static_library("camera_app_ui") { ...@@ -18,6 +18,8 @@ static_library("camera_app_ui") {
"camera_app_window_manager.h", "camera_app_window_manager.h",
"camera_app_window_manager_factory.cc", "camera_app_window_manager_factory.cc",
"camera_app_window_manager_factory.h", "camera_app_window_manager_factory.h",
"camera_app_window_state_controller.cc",
"camera_app_window_state_controller.h",
"resources.h", "resources.h",
"url_constants.cc", "url_constants.cc",
"url_constants.h", "url_constants.h",
......
...@@ -44,6 +44,45 @@ interface CameraUsageOwnershipMonitor { ...@@ -44,6 +44,45 @@ interface CameraUsageOwnershipMonitor {
OnCameraUsageOwnershipChanged(bool has_usage) => (); OnCameraUsageOwnershipChanged(bool has_usage) => ();
}; };
// The window states that we care about.
enum WindowStateType {
MINIMIZED = 0,
MAXIMIZED = 1,
FULLSCREEN = 2,
REGULAR = 3, // None of the above.
};
// Interface for monitoring window state.
interface WindowStateMonitor {
// Updates when the window state is changed.
OnWindowStateChanged(WindowStateType state);
};
// Interface for window controlling.
interface WindowStateController {
// Adds |monitor| for window state changes.
AddMonitor(pending_remote<WindowStateMonitor> monitor)
=> (WindowStateType state);
// Gets current |state| of the window.
GetWindowState() => (WindowStateType state);
// Minimize the window.
Minimize() => ();
// Restore the window.
Restore() => ();
// Maximize the window.
Maximize() => ();
// Fullscreen the window.
Fullscreen() => ();
// Focus the window.
Focus() => ();
};
// Interface for communication between Chrome Camera App (Remote) and Chrome // Interface for communication between Chrome Camera App (Remote) and Chrome
// (Receiver). // (Receiver).
interface CameraAppHelper { interface CameraAppHelper {
...@@ -99,4 +138,8 @@ interface CameraAppHelper { ...@@ -99,4 +138,8 @@ interface CameraAppHelper {
// Sets the monitor to monitor the camera usage ownership changed. // Sets the monitor to monitor the camera usage ownership changed.
SetCameraUsageMonitor( SetCameraUsageMonitor(
pending_remote<CameraUsageOwnershipMonitor> usage_monitor) => (); pending_remote<CameraUsageOwnershipMonitor> usage_monitor) => ();
// Gets the controller to control and monitor the window state of app.
GetWindowStateController()
=> (pending_remote<WindowStateController> controller);
}; };
...@@ -89,7 +89,7 @@ void CameraAppHelperImpl::StopPerfEventTrace(const std::string& event) { ...@@ -89,7 +89,7 @@ void CameraAppHelperImpl::StopPerfEventTrace(const std::string& event) {
void CameraAppHelperImpl::SetTabletMonitor( void CameraAppHelperImpl::SetTabletMonitor(
mojo::PendingRemote<TabletModeMonitor> monitor, mojo::PendingRemote<TabletModeMonitor> monitor,
SetTabletMonitorCallback callback) { SetTabletMonitorCallback callback) {
tablet_monitor_ = mojo::Remote<TabletModeMonitor>(std::move(monitor)); tablet_mode_monitor_ = mojo::Remote<TabletModeMonitor>(std::move(monitor));
std::move(callback).Run(ash::TabletMode::Get()->InTabletMode()); std::move(callback).Run(ash::TabletMode::Get()->InTabletMode());
} }
...@@ -144,14 +144,30 @@ void CameraAppHelperImpl::SetCameraUsageMonitor( ...@@ -144,14 +144,30 @@ void CameraAppHelperImpl::SetCameraUsageMonitor(
window_, std::move(usage_monitor), std::move(callback)); window_, std::move(usage_monitor), std::move(callback));
} }
void CameraAppHelperImpl::GetWindowStateController(
GetWindowStateControllerCallback callback) {
DCHECK_NE(camera_app_ui_, nullptr);
if (!window_state_controller_) {
window_state_controller_ =
std::make_unique<chromeos::CameraAppWindowStateController>(
views::Widget::GetWidgetForNativeWindow(window_));
}
mojo::PendingRemote<chromeos_camera::mojom::WindowStateController>
controller_remote;
window_state_controller_->AddReceiver(
controller_remote.InitWithNewPipeAndPassReceiver());
std::move(callback).Run(std::move(controller_remote));
}
void CameraAppHelperImpl::OnTabletModeStarted() { void CameraAppHelperImpl::OnTabletModeStarted() {
if (tablet_monitor_.is_bound()) if (tablet_mode_monitor_.is_bound())
tablet_monitor_->Update(true); tablet_mode_monitor_->Update(true);
} }
void CameraAppHelperImpl::OnTabletModeEnded() { void CameraAppHelperImpl::OnTabletModeEnded() {
if (tablet_monitor_.is_bound()) if (tablet_mode_monitor_.is_bound())
tablet_monitor_->Update(false); tablet_mode_monitor_->Update(false);
} }
void CameraAppHelperImpl::OnScreenStateChanged(ash::ScreenState screen_state) { void CameraAppHelperImpl::OnScreenStateChanged(ash::ScreenState screen_state) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "chromeos/components/camera_app_ui/camera_app_helper.mojom.h" #include "chromeos/components/camera_app_ui/camera_app_helper.mojom.h"
#include "chromeos/components/camera_app_ui/camera_app_ui.h" #include "chromeos/components/camera_app_ui/camera_app_ui.h"
#include "chromeos/components/camera_app_ui/camera_app_window_state_controller.h"
#include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/remote.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/display/display_observer.h" #include "ui/display/display_observer.h"
...@@ -62,6 +63,8 @@ class CameraAppHelperImpl : public ash::TabletModeObserver, ...@@ -62,6 +63,8 @@ class CameraAppHelperImpl : public ash::TabletModeObserver,
void SetCameraUsageMonitor( void SetCameraUsageMonitor(
mojo::PendingRemote<CameraUsageOwnershipMonitor> usage_monitor, mojo::PendingRemote<CameraUsageOwnershipMonitor> usage_monitor,
SetCameraUsageMonitorCallback callback) override; SetCameraUsageMonitorCallback callback) override;
void GetWindowStateController(
GetWindowStateControllerCallback callback) override;
private: private:
void CheckExternalScreenState(); void CheckExternalScreenState();
...@@ -89,12 +92,15 @@ class CameraAppHelperImpl : public ash::TabletModeObserver, ...@@ -89,12 +92,15 @@ class CameraAppHelperImpl : public ash::TabletModeObserver,
aura::Window* window_; aura::Window* window_;
mojo::Remote<TabletModeMonitor> tablet_monitor_; mojo::Remote<TabletModeMonitor> tablet_mode_monitor_;
mojo::Remote<ScreenStateMonitor> screen_state_monitor_; mojo::Remote<ScreenStateMonitor> screen_state_monitor_;
mojo::Remote<ExternalScreenMonitor> external_screen_monitor_; mojo::Remote<ExternalScreenMonitor> external_screen_monitor_;
mojo::Receiver<chromeos_camera::mojom::CameraAppHelper> receiver_{this}; mojo::Receiver<chromeos_camera::mojom::CameraAppHelper> receiver_{this};
std::unique_ptr<chromeos::CameraAppWindowStateController>
window_state_controller_;
DISALLOW_COPY_AND_ASSIGN(CameraAppHelperImpl); DISALLOW_COPY_AND_ASSIGN(CameraAppHelperImpl);
}; };
......
// Copyright 2020 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 "chromeos/components/camera_app_ui/camera_app_window_state_controller.h"
namespace chromeos {
CameraAppWindowStateController::CameraAppWindowStateController(
views::Widget* widget)
: widget_(widget), window_state_(GetCurrentWindowState()) {
widget_->AddObserver(this);
}
CameraAppWindowStateController::~CameraAppWindowStateController() {
widget_->RemoveObserver(this);
}
void CameraAppWindowStateController::AddReceiver(
mojo::PendingReceiver<chromeos_camera::mojom::WindowStateController>
receiver) {
receivers_.Add(this, std::move(receiver));
}
void CameraAppWindowStateController::AddMonitor(
mojo::PendingRemote<chromeos_camera::mojom::WindowStateMonitor> monitor,
AddMonitorCallback callback) {
auto remote = mojo::Remote<chromeos_camera::mojom::WindowStateMonitor>(
std::move(monitor));
monitors_.push_back(std::move(remote));
std::move(callback).Run(window_state_);
}
void CameraAppWindowStateController::GetWindowState(
GetWindowStateCallback callback) {
std::move(callback).Run(window_state_);
}
void CameraAppWindowStateController::Minimize(MinimizeCallback callback) {
minimize_callbacks_.push(std::move(callback));
widget_->Minimize();
}
void CameraAppWindowStateController::Restore(RestoreCallback callback) {
restore_callbacks_.push(std::move(callback));
widget_->Restore();
}
void CameraAppWindowStateController::Maximize(MaximizeCallback callback) {
maximize_callbacks_.push(std::move(callback));
widget_->Maximize();
}
void CameraAppWindowStateController::Fullscreen(FullscreenCallback callback) {
fullscreen_callbacks_.push(std::move(callback));
widget_->SetFullscreen(true);
}
void CameraAppWindowStateController::Focus(FocusCallback callback) {
focus_callbacks_.push(std::move(callback));
widget_->Activate();
}
void CameraAppWindowStateController::OnWidgetVisibilityChanged(
views::Widget* widget,
bool visible) {
OnWindowStateChanged();
}
void CameraAppWindowStateController::OnWidgetActivationChanged(
views::Widget* widget,
bool active) {
while (!focus_callbacks_.empty()) {
std::move(focus_callbacks_.front()).Run();
focus_callbacks_.pop();
}
}
void CameraAppWindowStateController::OnWidgetBoundsChanged(
views::Widget* widget,
const gfx::Rect& new_bounds) {
OnWindowStateChanged();
}
void CameraAppWindowStateController::OnWindowStateChanged() {
auto prev_state = window_state_;
window_state_ = GetCurrentWindowState();
std::queue<base::OnceClosure>* callbacks;
switch (window_state_) {
case WindowStateType::MINIMIZED:
callbacks = &minimize_callbacks_;
break;
case WindowStateType::REGULAR:
callbacks = &restore_callbacks_;
break;
case WindowStateType::MAXIMIZED:
callbacks = &maximize_callbacks_;
break;
case WindowStateType::FULLSCREEN:
callbacks = &fullscreen_callbacks_;
break;
}
while (!callbacks->empty()) {
std::move(callbacks->front()).Run();
callbacks->pop();
}
if (prev_state != window_state_) {
for (const auto& monitor : monitors_) {
monitor->OnWindowStateChanged(window_state_);
}
}
}
CameraAppWindowStateController::WindowStateType
CameraAppWindowStateController::GetCurrentWindowState() {
if (widget_->IsMinimized()) {
return WindowStateType::MINIMIZED;
} else if (widget_->IsMaximized()) {
return WindowStateType::MAXIMIZED;
} else if (widget_->IsFullscreen()) {
return WindowStateType::FULLSCREEN;
} else {
return WindowStateType::REGULAR;
}
}
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_COMPONENTS_CAMERA_APP_UI_CAMERA_APP_WINDOW_STATE_CONTROLLER_H_
#define CHROMEOS_COMPONENTS_CAMERA_APP_UI_CAMERA_APP_WINDOW_STATE_CONTROLLER_H_
#include <queue>
#include <vector>
#include "chromeos/components/camera_app_ui/camera_app_helper.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
namespace chromeos {
class CameraAppWindowStateController
: public chromeos_camera::mojom::WindowStateController,
public views::WidgetObserver {
public:
using WindowStateType = chromeos_camera::mojom::WindowStateType;
using WindowStateMonitor = chromeos_camera::mojom::WindowStateMonitor;
CameraAppWindowStateController(views::Widget* widget);
CameraAppWindowStateController(const CameraAppWindowStateController&) =
delete;
CameraAppWindowStateController& operator=(
const CameraAppWindowStateController&) = delete;
~CameraAppWindowStateController() override;
void AddReceiver(
mojo::PendingReceiver<chromeos_camera::mojom::WindowStateController>
receiver);
// chromeos_camera::mojom::WindowStateController implementations.
void AddMonitor(
mojo::PendingRemote<chromeos_camera::mojom::WindowStateMonitor> monitor,
AddMonitorCallback callback) override;
void GetWindowState(GetWindowStateCallback callback) override;
void Minimize(MinimizeCallback callback) override;
void Restore(RestoreCallback callback) override;
void Maximize(MaximizeCallback callback) override;
void Fullscreen(FullscreenCallback callback) override;
void Focus(FocusCallback callback) override;
// views::WidgetObserver implementations.
void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override;
void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
void OnWidgetBoundsChanged(views::Widget* widget,
const gfx::Rect& new_bounds) override;
private:
void OnWindowStateChanged();
WindowStateType GetCurrentWindowState();
views::Widget* widget_;
WindowStateType window_state_;
mojo::ReceiverSet<chromeos_camera::mojom::WindowStateController> receivers_;
std::vector<mojo::Remote<WindowStateMonitor>> monitors_;
std::queue<base::OnceClosure> minimize_callbacks_;
std::queue<base::OnceClosure> restore_callbacks_;
std::queue<base::OnceClosure> maximize_callbacks_;
std::queue<base::OnceClosure> fullscreen_callbacks_;
std::queue<base::OnceClosure> focus_callbacks_;
};
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_CAMERA_APP_UI_CAMERA_APP_WINDOW_STATE_CONTROLLER_H_
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import {windowController} from '../window_controller/window_controller.js';
/** /**
* The singleton instance of ChromeHelper. Initialized by the first * The singleton instance of ChromeHelper. Initialized by the first
* invocation of getInstance(). * invocation of getInstance().
...@@ -103,8 +105,12 @@ export class ChromeHelper { ...@@ -103,8 +105,12 @@ export class ChromeHelper {
await releaseUsage(); await releaseUsage();
} }
}); });
await this.remote_.setCameraUsageMonitor( await this.remote_.setCameraUsageMonitor(
usageCallbackRouter.$.bindNewPipeAndPassRemote()); usageCallbackRouter.$.bindNewPipeAndPassRemote());
const {controller} = await this.remote_.getWindowStateController();
await windowController.bind(controller);
} }
/** /**
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import {NotImplementedError} from '../type.js'; import {assertInstanceof} from '../chrome_util.js';
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
import {WindowController} from './window_controller_interface.js'; import {WindowController} from './window_controller_interface.js';
...@@ -15,43 +15,84 @@ export class MojoWindowController { ...@@ -15,43 +15,84 @@ export class MojoWindowController {
/** /**
* @public * @public
*/ */
constructor() {} constructor() {
/**
* The remote controller from Mojo interface.
* @type {?chromeosCamera.mojom.WindowStateControllerRemote}
*/
this.windowStateController_ = null;
/**
* Current window state.
* @type {?chromeosCamera.mojom.WindowStateType}
*/
this.windowState_ = null;
}
/** @override */
async bind(remoteController) {
this.windowStateController_ = remoteController;
const windowMonitorCallbackRouter =
new chromeosCamera.mojom.WindowStateMonitorCallbackRouter();
windowMonitorCallbackRouter.onWindowStateChanged.addListener((state) => {
this.windowState_ = state;
});
const {state} = await this.windowStateController_.addMonitor(
windowMonitorCallbackRouter.$.bindNewPipeAndPassRemote());
this.windowState_ = state;
}
/** @override */ /** @override */
async minimize() { async minimize() {
throw new NotImplementedError(); assertInstanceof(
this.windowStateController_,
chromeosCamera.mojom.WindowStateControllerRemote)
.minimize();
} }
/** @override */ /** @override */
async maximize() { async maximize() {
throw new NotImplementedError(); assertInstanceof(
this.windowStateController_,
chromeosCamera.mojom.WindowStateControllerRemote)
.maximize();
} }
/** @override */ /** @override */
async restore() { async restore() {
throw new NotImplementedError(); assertInstanceof(
this.windowStateController_,
chromeosCamera.mojom.WindowStateControllerRemote)
.restore();
} }
/** @override */ /** @override */
async fullscreen() { async fullscreen() {
throw new NotImplementedError(); assertInstanceof(
this.windowStateController_,
chromeosCamera.mojom.WindowStateControllerRemote)
.fullscreen();
} }
/** @override */ /** @override */
async focus() { async focus() {
throw new NotImplementedError(); assertInstanceof(
this.windowStateController_,
chromeosCamera.mojom.WindowStateControllerRemote)
.focus();
} }
/** @override */ /** @override */
isMinimized() { isMinimized() {
// TODO(980846): Implement the minimization monitor. return this.windowState_ === chromeosCamera.mojom.WindowStateType.MINIMIZED;
return false;
} }
/** @override */ /** @override */
isFullscreenOrMaximized() { isFullscreenOrMaximized() {
// TODO(980846): Implement the fullscreen monitor. return this.windowState_ ===
return false; chromeosCamera.mojom.WindowStateType.FULLSCREEN ||
this.windowState_ === chromeosCamera.mojom.WindowStateType.MAXIMIZED;
} }
/** @override */ /** @override */
......
...@@ -39,6 +39,12 @@ function changeWindowState(predicate, getEventTarget, changeState) { ...@@ -39,6 +39,12 @@ function changeWindowState(predicate, getEventTarget, changeState) {
* @implements {WindowController} * @implements {WindowController}
*/ */
export class ChromeWindowController { export class ChromeWindowController {
/** @override */
async bind(remoteController) {
// We control the window uses Chrome AppWindow API directly for platform
// app. There is no need to bind to the implementation through Mojo.
}
/** @override */ /** @override */
async minimize() { async minimize() {
changeWindowState( changeWindowState(
......
...@@ -7,6 +7,14 @@ ...@@ -7,6 +7,14 @@
* @interface * @interface
*/ */
export class WindowController { export class WindowController {
/**
* Binds the controller remote from Mojo interface.
* @param {!chromeosCamera.mojom.WindowStateControllerRemote} remoteController
* @return {!Promise}
* @abstract
*/
async bind(remoteController) {}
/** /**
* Minimizes the window. * Minimizes the window.
* @return {!Promise} * @return {!Promise}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment