Commit 87e9510c authored by Toshiki Kikuchi's avatar Toshiki Kikuchi Committed by Commit Bot

exo: Add toast shell for ARC++ toasts

This CL introduces a new shell type for ARC++ toasts in remote-shell.
Since the purpose of toasts is a notification for users and the toast
appears and disappears quickly without any user interaction, so toasts
are supposed to be shown over Chrome OS's virtual keyboard.

ARC++ side CL: ag/11272597
design overview: go/vk-overlays-toasts

BUG=b:109717200
TEST=ToastSurfaceTest

Change-Id: I3cec22a031a7046ff63770ff308b6d0695c313e5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2167792
Commit-Queue: Toshiki Kikuchi <toshikikikuchi@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarYuichiro Hanada <yhanada@chromium.org>
Cr-Commit-Position: refs/heads/master@{#786617}
parent f6ff7f6b
......@@ -20,6 +20,7 @@
#include "chrome/common/chrome_switches.h"
#include "components/exo/file_helper.h"
#include "components/exo/server/wayland_server_controller.h"
#include "components/exo/toast_surface_manager.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/drop_data.h"
......@@ -125,7 +126,7 @@ ExoParts::ExoParts() {
wayland_server_ = exo::WaylandServerController::CreateIfNecessary(
std::make_unique<ChromeFileHelper>(),
std::make_unique<ash::ArcNotificationSurfaceManagerImpl>(),
std::make_unique<ash::ArcInputMethodSurfaceManager>());
std::make_unique<ash::ArcInputMethodSurfaceManager>(), nullptr);
ash::Shell::Get()->TrackInputMethodBounds(
ash::ArcInputMethodBoundsTracker::Get());
}
......@@ -138,6 +138,9 @@ static_library("exo") {
"shell_surface_base.h",
"text_input.cc",
"text_input.h",
"toast_surface.cc",
"toast_surface.h",
"toast_surface_manager.h",
"wm_helper_chromeos.cc",
"wm_helper_chromeos.h",
"xdg_shell_surface.cc",
......@@ -258,6 +261,7 @@ source_set("unit_tests") {
"sub_surface_unittest.cc",
"surface_unittest.cc",
"text_input_unittest.cc",
"toast_surface_unittest.cc",
"touch_unittest.cc",
"xdg_shell_surface_unittest.cc",
]
......
......@@ -349,6 +349,24 @@ void ClientControlledShellSurface::SetBounds(int64_t display_id,
SetGeometry(bounds);
}
void ClientControlledShellSurface::SetBoundsOrigin(const gfx::Point& origin) {
TRACE_EVENT1("exo", "ClientControlledShellSurface::SetBoundsOrigin", "origin",
origin.ToString());
pending_geometry_.set_origin(origin);
}
void ClientControlledShellSurface::SetBoundsSize(const gfx::Size& size) {
TRACE_EVENT1("exo", "ClientControlledShellSurface::SetBoundsSize", "size",
size.ToString());
if (size.IsEmpty()) {
DLOG(WARNING) << "Bounds size must be non-empty";
return;
}
pending_geometry_.set_size(size);
}
void ClientControlledShellSurface::SetMaximized() {
TRACE_EVENT0("exo", "ClientControlledShellSurface::SetMaximized");
pending_window_state_ = ash::WindowStateType::kMaximized;
......
......@@ -63,6 +63,12 @@ class ClientControlledShellSurface : public ShellSurfaceBase,
// Set bounds in root window coordinates relative to the given display.
void SetBounds(int64_t display_id, const gfx::Rect& bounds);
// Set origin of bounds for surface while preserving the size.
void SetBoundsOrigin(const gfx::Point& origin);
// Set size of bounds for surface while preserving the origin.
void SetBoundsSize(const gfx::Size& size);
// Called when the client was maximized.
void SetMaximized();
......
......@@ -40,6 +40,8 @@
#include "components/exo/client_controlled_shell_surface.h"
#include "components/exo/input_method_surface.h"
#include "components/exo/shell_surface.h"
#include "components/exo/toast_surface.h"
#include "components/exo/toast_surface_manager.h"
#include "components/exo/xdg_shell_surface.h"
#endif
......@@ -60,9 +62,11 @@ Display::Display()
Display::Display(
std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
std::unique_ptr<ToastSurfaceManager> toast_surface_manager,
std::unique_ptr<FileHelper> file_helper)
: notification_surface_manager_(std::move(notification_surface_manager)),
input_method_surface_manager_(std::move(input_method_surface_manager)),
toast_surface_manager_(std::move(toast_surface_manager)),
file_helper_(std::move(file_helper)),
client_native_pixmap_factory_(
gfx::CreateClientNativePixmapFactoryDmabuf()) {}
......@@ -212,6 +216,26 @@ std::unique_ptr<InputMethodSurface> Display::CreateInputMethodSurface(
input_method_surface_manager_.get(), surface,
default_device_scale_factor);
}
std::unique_ptr<ToastSurface> Display::CreateToastSurface(
Surface* surface,
double default_device_scale_factor) {
TRACE_EVENT1("exo", "Display::CreateToastSurface", "surface",
surface->AsTracedValue());
if (!toast_surface_manager_) {
DLOG(ERROR) << "Toast surface cannot be registered";
return nullptr;
}
if (surface->HasSurfaceDelegate()) {
DLOG(ERROR) << "Surface has already been assigned a role";
return nullptr;
}
return std::make_unique<ToastSurface>(toast_surface_manager_.get(), surface,
default_device_scale_factor);
}
#endif // defined(OS_CHROMEOS)
std::unique_ptr<SubSurface> Display::CreateSubSurface(Surface* surface,
......
......@@ -40,6 +40,8 @@ class Surface;
#if defined(OS_CHROMEOS)
class InputMethodSurface;
class ShellSurface;
class ToastSurface;
class ToastSurfaceManager;
class XdgShellSurface;
#endif
......@@ -58,6 +60,7 @@ class Display {
Display(
std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
std::unique_ptr<ToastSurfaceManager> toast_surface_manager,
std::unique_ptr<FileHelper> file_helper);
#endif // defined(OS_CHROMEOS)
......@@ -103,6 +106,11 @@ class Display {
std::unique_ptr<InputMethodSurface> CreateInputMethodSurface(
Surface* surface,
double default_device_scale_factor);
// Creates a toast surface for a surface.
std::unique_ptr<ToastSurface> CreateToastSurface(
Surface* surface,
double default_device_scale_factor);
#endif // defined(OS_CHROMEOS)
// Creates a sub-surface for an existing surface. The sub-surface will be
......@@ -126,6 +134,7 @@ class Display {
#if defined(OS_CHROMEOS)
std::unique_ptr<NotificationSurfaceManager> notification_surface_manager_;
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager_;
std::unique_ptr<ToastSurfaceManager> toast_surface_manager_;
#endif // defined(OS_CHROMEOS)
std::unique_ptr<FileHelper> file_helper_;
......
......@@ -18,6 +18,7 @@
#include "components/exo/sub_surface.h"
#include "components/exo/surface.h"
#include "components/exo/test/exo_test_base.h"
#include "components/exo/toast_surface_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(USE_OZONE)
......@@ -241,7 +242,8 @@ class TestFileHelper : public FileHelper {
TEST_F(DisplayTest, CreateDataDevice) {
TestDataDeviceDelegate device_delegate;
Display display(nullptr, nullptr, std::make_unique<TestFileHelper>());
Display display(nullptr, nullptr, nullptr,
std::make_unique<TestFileHelper>());
std::unique_ptr<DataDevice> device =
display.CreateDataDevice(&device_delegate);
......
......@@ -13,6 +13,7 @@
#include "components/exo/file_helper.h"
#include "components/exo/input_method_surface_manager.h"
#include "components/exo/notification_surface_manager.h"
#include "components/exo/toast_surface_manager.h"
#include "components/exo/wayland/server.h"
#include "components/exo/wayland/wayland_watcher.h"
#include "components/exo/wm_helper.h"
......@@ -25,10 +26,12 @@ std::unique_ptr<WaylandServerController>
WaylandServerController::CreateIfNecessary(
std::unique_ptr<FileHelper> file_helper,
std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager) {
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
std::unique_ptr<ToastSurfaceManager> toast_surface_manager) {
return std::make_unique<WaylandServerController>(
std::move(file_helper), std::move(notification_surface_manager),
std::move(input_method_surface_manager));
std::move(input_method_surface_manager),
std::move(toast_surface_manager));
}
WaylandServerController::~WaylandServerController() {
......@@ -37,11 +40,13 @@ WaylandServerController::~WaylandServerController() {
WaylandServerController::WaylandServerController(
std::unique_ptr<FileHelper> file_helper,
std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager)
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
std::unique_ptr<ToastSurfaceManager> toast_surface_manager)
: wm_helper_(std::make_unique<WMHelperChromeOS>()),
display_(
std::make_unique<Display>(std::move(notification_surface_manager),
std::move(input_method_surface_manager),
std::move(toast_surface_manager),
std::move(file_helper))),
wayland_server_(wayland::Server::Create(display_.get())) {
......
......@@ -21,6 +21,7 @@ class FileHelper;
class WMHelper;
class NotificationSurfaceManager;
class InputMethodSurfaceManager;
class ToastSurfaceManager;
class WaylandServerController {
public:
......@@ -32,7 +33,8 @@ class WaylandServerController {
static std::unique_ptr<WaylandServerController> CreateIfNecessary(
std::unique_ptr<FileHelper> file_helper,
std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager);
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
std::unique_ptr<ToastSurfaceManager> toast_surface_manager);
~WaylandServerController();
......@@ -43,7 +45,8 @@ class WaylandServerController {
WaylandServerController(
std::unique_ptr<FileHelper> file_helper,
std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager);
std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
std::unique_ptr<ToastSurfaceManager> toast_surface_manager);
private:
std::unique_ptr<WMHelper> wm_helper_;
......
......@@ -15,6 +15,7 @@
#include "components/exo/display.h"
#include "components/exo/input_method_surface.h"
#include "components/exo/surface.h"
#include "components/exo/toast_surface.h"
#include "components/exo/wm_helper.h"
#include "components/exo/xdg_shell_surface.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
......@@ -191,5 +192,21 @@ std::unique_ptr<InputMethodSurface> ExoTestHelper::CreateInputMethodSurface(
return shell_surface;
}
std::unique_ptr<ToastSurface> ExoTestHelper::CreateToastSurface(
Surface* surface,
ToastSurfaceManager* surface_manager) {
auto shell_surface = std::make_unique<ToastSurface>(
surface_manager, surface,
WMHelper::GetInstance()->GetDefaultDeviceScaleFactor());
shell_surface->set_state_changed_callback(base::BindRepeating(
&HandleWindowStateRequest, base::Unretained(shell_surface.get())));
shell_surface->set_bounds_changed_callback(
base::BindRepeating(&HandleBoundsChangedRequest, shell_surface.get()));
return shell_surface;
}
} // namespace test
} // namespace exo
......@@ -25,6 +25,8 @@ class InputMethodSurface;
class InputMethodSurfaceManager;
class Surface;
class ShellSurface;
class ToastSurface;
class ToastSurfaceManager;
namespace test {
......@@ -63,6 +65,9 @@ class ExoTestHelper {
std::unique_ptr<InputMethodSurface> CreateInputMethodSurface(
Surface* surface,
InputMethodSurfaceManager* surface_manager);
std::unique_ptr<ToastSurface> CreateToastSurface(
Surface* surface,
ToastSurfaceManager* surface_manager);
private:
DISALLOW_COPY_AND_ASSIGN(ExoTestHelper);
......
// 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 "components/exo/toast_surface.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "components/exo/toast_surface_manager.h"
#include "components/exo/wm_helper.h"
#include "ui/base/class_property.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/accessibility/view_accessibility.h"
namespace exo {
ToastSurface::ToastSurface(ToastSurfaceManager* manager,
Surface* surface,
double default_device_scale_factor)
: ClientControlledShellSurface(surface,
false /* can_minimize */,
ash::kShellWindowId_OverlayContainer),
manager_(manager) {
SetScale(default_device_scale_factor);
SetActivatable(false);
DisableMovement();
host_window()->SetName("ExoToastSurface");
}
ToastSurface::~ToastSurface() {
if (added_to_manager_)
manager_->RemoveSurface(this);
}
void ToastSurface::OnSurfaceCommit() {
ClientControlledShellSurface::OnSurfaceCommit();
if (!added_to_manager_) {
added_to_manager_ = true;
manager_->AddSurface(this);
}
}
} // namespace exo
// 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 COMPONENTS_EXO_TOAST_SURFACE_H_
#define COMPONENTS_EXO_TOAST_SURFACE_H_
#include "base/macros.h"
#include "components/exo/client_controlled_shell_surface.h"
#include "components/exo/surface_delegate.h"
#include "components/exo/surface_observer.h"
namespace exo {
class ToastSurfaceManager;
// Handles toast surface role of a given surface.
class ToastSurface : public ClientControlledShellSurface {
public:
ToastSurface(ToastSurfaceManager* manager,
Surface* surface,
double default_device_scale_factor);
~ToastSurface() override;
// Overridden from SurfaceDelegate:
void OnSurfaceCommit() override;
private:
ToastSurfaceManager* const manager_;
bool added_to_manager_ = false;
DISALLOW_COPY_AND_ASSIGN(ToastSurface);
};
} // namespace exo
#endif // COMPONENTS_EXO_TOAST_SURFACE_H_
// 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 COMPONENTS_EXO_TOAST_SURFACE_MANAGER_H_
#define COMPONENTS_EXO_TOAST_SURFACE_MANAGER_H_
namespace exo {
class ToastSurface;
class ToastSurfaceManager {
public:
virtual ~ToastSurfaceManager() = default;
// Adds an ToastSurface to the manager.
virtual void AddSurface(ToastSurface* surface) = 0;
// Removes an ToastSurface from the manager.
virtual void RemoveSurface(ToastSurface* surface) = 0;
};
} // namespace exo
#endif // COMPONENTS_EXO_TOAST_SURFACE_MANAGER_H_
// 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 "components/exo/toast_surface.h"
#include "components/exo/test/exo_test_base.h"
#include "components/exo/test/exo_test_helper.h"
#include "components/exo/toast_surface_manager.h"
namespace exo {
class ToastSurfaceTest : public test::ExoTestBase, public ToastSurfaceManager {
public:
ToastSurfaceTest() = default;
ToastSurfaceTest(const ToastSurfaceTest&) = delete;
ToastSurfaceTest& operator=(const ToastSurfaceTest&) = delete;
// Overridden from ToastSurfaceManager:
void AddSurface(ToastSurface* surface) override {}
void RemoveSurface(ToastSurface* surface) override {}
};
TEST_F(ToastSurfaceTest, ToastSurfaceShouldNotBeActivatable) {
std::unique_ptr<Surface> surface(new Surface);
auto shell_surface =
exo_test_helper()->CreateToastSurface(surface.get(), this);
surface->Commit();
views::Widget* widget = shell_surface->GetWidget();
EXPECT_FALSE(widget->CanActivate());
}
} // namespace exo
......@@ -20,6 +20,7 @@
#include "components/exo/file_helper.h"
#include "components/exo/input_method_surface_manager.h"
#include "components/exo/notification_surface_manager.h"
#include "components/exo/toast_surface_manager.h"
#include "components/exo/wayland/server.h"
#include "components/exo/wm_helper_chromeos.h"
#include "ui/aura/window_tree_host.h"
......@@ -110,7 +111,7 @@ void WaylandClientTestHelper::SetUpOnUIThread(base::WaitableEvent* event) {
ash_test_helper_->SetUp();
wm_helper_ = std::make_unique<WMHelperChromeOS>();
display_ = std::make_unique<Display>(nullptr, nullptr, nullptr);
display_ = std::make_unique<Display>(nullptr, nullptr, nullptr, nullptr);
wayland_server_ = exo::wayland::Server::Create(display_.get());
DCHECK(wayland_server_);
wayland_watcher_ = std::make_unique<WaylandWatcher>(wayland_server_.get());
......
......@@ -32,6 +32,7 @@
#include "components/exo/shell_surface_base.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/surface_delegate.h"
#include "components/exo/toast_surface.h"
#include "components/exo/wayland/server_util.h"
#include "components/exo/wm_helper_chromeos.h"
#include "ui/display/display_observer.h"
......@@ -698,6 +699,35 @@ const struct zcr_input_method_surface_v1_interface
input_method_surface_implementation = {input_method_surface_destroy,
input_method_surface_set_bounds};
////////////////////////////////////////////////////////////////////////////////
// toast_surface_interface:
void toast_surface_destroy(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource);
}
void toast_surface_set_position(wl_client* client,
wl_resource* resource,
uint32_t display_id_hi,
uint32_t display_id_lo,
int32_t x,
int32_t y) {
GetUserDataAs<ToastSurface>(resource)->SetDisplay(
static_cast<int64_t>(display_id_hi) << 32 | display_id_lo);
GetUserDataAs<ToastSurface>(resource)->SetBoundsOrigin(gfx::Point(x, y));
}
void toast_surface_set_size(wl_client* client,
wl_resource* resource,
int32_t width,
int32_t height) {
GetUserDataAs<ToastSurface>(resource)->SetBoundsSize(
gfx::Size(width, height));
}
const struct zcr_toast_surface_v1_interface toast_surface_implementation = {
toast_surface_destroy, toast_surface_set_position, toast_surface_set_size};
////////////////////////////////////////////////////////////////////////////////
// remote_shell_interface:
......@@ -756,6 +786,12 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
default_device_scale_factor);
}
std::unique_ptr<ToastSurface> CreateToastSurface(
Surface* surface,
double default_device_scale_factor) {
return display_->CreateToastSurface(surface, default_device_scale_factor);
}
// TODO(mukai, oshima): rewrite this through delegate-style instead of
// creating callbacks.
ClientControlledShellSurface::BoundsChangedCallback
......@@ -1308,10 +1344,36 @@ void remote_shell_get_input_method_surface(wl_client* client,
std::move(input_method_surface));
}
void remote_shell_get_toast_surface(wl_client* client,
wl_resource* resource,
uint32_t id,
wl_resource* surface) {
if (GetUserDataAs<Surface>(surface)->HasSurfaceDelegate()) {
wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V1_ERROR_ROLE,
"surface has already been assigned a role");
return;
}
std::unique_ptr<ClientControlledShellSurface> toast_surface =
GetUserDataAs<WaylandRemoteShell>(resource)->CreateToastSurface(
GetUserDataAs<Surface>(surface), GetDefaultDeviceScaleFactor());
if (!toast_surface) {
wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V1_ERROR_ROLE,
"Cannot create an toast surface");
return;
}
wl_resource* toast_surface_resource =
wl_resource_create(client, &zcr_toast_surface_v1_interface,
wl_resource_get_version(resource), id);
SetImplementation(toast_surface_resource, &toast_surface_implementation,
std::move(toast_surface));
}
const struct zcr_remote_shell_v1_interface remote_shell_implementation = {
remote_shell_destroy, remote_shell_get_remote_surface,
remote_shell_get_notification_surface,
remote_shell_get_input_method_surface};
remote_shell_get_input_method_surface, remote_shell_get_toast_surface};
} // namespace
......
......@@ -38,7 +38,7 @@
reset.
</description>
<interface name="zcr_remote_shell_v1" version="27">
<interface name="zcr_remote_shell_v1" version="28">
<description summary="remote_shell">
The global interface that allows clients to turn a wl_surface into a
"real window" which is remotely managed but can be stacked, activated
......@@ -235,6 +235,16 @@
<arg name="identification_data" type="array" summary="EDID blob data"/>
</event>
<!-- Version 28 additions -->
<request name="get_toast_surface" since="28">
<description summary="Create a toast surface from a surface">
Creates an toast_surface for the given surface, gives it
the toast_surface role.
</description>
<arg name="id" type="new_id" interface="zcr_toast_surface_v1"/>
<arg name="surface" type="object" interface="wl_surface"/>
</request>
</interface>
<interface name="zcr_remote_surface_v1" version="27">
......@@ -1128,4 +1138,59 @@
</request>
</interface>
<interface name="zcr_toast_surface_v1" version="1">
<description summary="A toast window">
An interface that may be implemented by a wl_surface to host
toast contents.
</description>
<request name="destroy" type="destructor">
<description summary="Destroy the toast_surface">
Unmap and destroy the toast surface.
</description>
</request>
<request name="set_position">
<description summary="set toast bounds position">
Set the position of bounds of a window from the user's perspective.
The bounds are double buffered, and will be applied at the
time wl_surface.commit of the corresponding wl_surface is called.
Once the bounds are set, it is not possible to unset them, and they will
remain the same until set_position is called again, even if a new sub-
surface or buffer is attached.
If never set, the compositor will determine the toast position.
The bounds are relative to the given display. If the display is invalid,
they are assumed to be relative to the primary display.
</description>
<arg name="display_id_hi" type="uint"/>
<arg name="display_id_lo" type="uint"/>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
</request>
<request name="set_size">
<description summary="set toast bounds size">
Set the size of bounds of a window from the user's perspective.
The bounds are double buffered, and will be applied at the
time wl_surface.commit of the corresponding wl_surface is called.
Once the bounds are set, it is not possible to unset them, and they will
remain the same until set_size is called again, even if a new sub-
surface or buffer is attached.
If never set, the value is the surface content bounds. This updates
dynamically on every commit.
The width and height must be greater than zero.
</description>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</request>
</interface>
</protocol>
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