Skip to content

Commit

Permalink
Consolidate the surface lookup for focus logic.
Browse files Browse the repository at this point in the history
zcr_remote_shell should use the same one as seat uses

Bug: none
Test: added shell_surface_util_tests

Change-Id: I4a4221d01f5212653b90e61ca95a9c0d64d9f95a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2676184
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: Jun Mukai <mukai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#858813}
  • Loading branch information
mitoshima authored and Chromium LUCI CQ committed Mar 2, 2021
1 parent 861372a commit 7a29f96
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 68 deletions.
1 change: 1 addition & 0 deletions components/exo/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ source_set("unit_tests") {
"seat_unittest.cc",
"shared_memory_unittest.cc",
"shell_surface_unittest.cc",
"shell_surface_util_unittest.cc",
"sub_surface_unittest.cc",
"surface_unittest.cc",
"text_input_unittest.cc",
Expand Down
26 changes: 3 additions & 23 deletions components/exo/seat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,6 @@
namespace exo {
namespace {

Surface* GetEffectiveFocus(aura::Window* window) {
if (!window)
return nullptr;
Surface* const surface = Surface::AsSurface(window);
if (surface)
return surface;
ShellSurfaceBase* shell_surface_base = nullptr;
for (auto* current = window; current && !shell_surface_base;
current = current->parent()) {
shell_surface_base = GetShellSurfaceBaseForWindow(current);
}
// Make sure the |window| is the toplevel or a host window, but not
// another window added to the toplevel.
if (shell_surface_base &&
(shell_surface_base->GetWidget()->GetNativeWindow() == window ||
shell_surface_base->host_window()->Contains(window))) {
return shell_surface_base->root_surface();
}
return nullptr;
}

} // namespace

Seat::Seat(std::unique_ptr<DataExchangeDelegate> delegate)
Expand Down Expand Up @@ -120,7 +99,8 @@ void Seat::RemoveObserver(SeatObserver* observer) {
}

Surface* Seat::GetFocusedSurface() {
return GetEffectiveFocus(WMHelper::GetInstance()->GetFocusedWindow());
return GetTargetSurfaceForKeyboardFocus(
WMHelper::GetInstance()->GetFocusedWindow());
}

void Seat::StartDrag(DataSource* source,
Expand Down Expand Up @@ -286,7 +266,7 @@ void Seat::OnAllReadsFinished(

void Seat::OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) {
Surface* const surface = GetEffectiveFocus(gained_focus);
Surface* const surface = GetTargetSurfaceForKeyboardFocus(gained_focus);
for (auto& observer : observers_) {
observer.OnSurfaceFocusing(surface);
}
Expand Down
5 changes: 2 additions & 3 deletions components/exo/shell_surface_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "ash/public/cpp/test/shell_test_api.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/shell.h"
#include "ash/wm/resize_shadow.h"
#include "ash/wm/resize_shadow_controller.h"
#include "ash/wm/window_state.h"
#include "ash/wm/wm_event.h"
#include "ash/wm/workspace_controller_test_api.h"
Expand Down Expand Up @@ -45,9 +47,6 @@
#include "ui/wm/core/shadow_types.h"
#include "ui/wm/core/window_util.h"

#include "ash/wm/resize_shadow.h"
#include "ash/wm/resize_shadow_controller.h"

namespace exo {

using ShellSurfaceTest = test::ExoTestBase;
Expand Down
22 changes: 21 additions & 1 deletion components/exo/shell_surface_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ Surface* GetTargetSurfaceForLocatedEvent(

aura::Window* focused =
static_cast<aura::Window*>(targeter->FindTargetForEvent(window, event));

if (focused) {
Surface* surface = Surface::AsSurface(focused);
if (focused != window)
Expand Down Expand Up @@ -216,6 +215,27 @@ Surface* GetTargetSurfaceForLocatedEvent(
}
}

Surface* GetTargetSurfaceForKeyboardFocus(aura::Window* window) {
if (!window)
return nullptr;
Surface* const surface = Surface::AsSurface(window);
if (surface)
return surface;
ShellSurfaceBase* shell_surface_base = nullptr;
for (auto* current = window; current && !shell_surface_base;
current = current->parent()) {
shell_surface_base = GetShellSurfaceBaseForWindow(current);
}
// Make sure the |window| is the toplevel or a host window, but not
// another window added to the toplevel.
if (shell_surface_base &&
(shell_surface_base->GetWidget()->GetNativeWindow() == window ||
shell_surface_base->host_window()->Contains(window))) {
return shell_surface_base->root_surface();
}
return nullptr;
}

void GrantPermissionToActivate(aura::Window* window, base::TimeDelta timeout) {
// Activation is the only permission, so just set the property. The window
// owns the Permission object.
Expand Down
6 changes: 6 additions & 0 deletions components/exo/shell_surface_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ ShellSurfaceBase* GetShellSurfaceBaseForWindow(aura::Window* window);
// requested grab.
Surface* GetTargetSurfaceForLocatedEvent(const ui::LocatedEvent* event);

// Returns the focused surface for given 'focused_window'. If a surface is
// attached to the window, this will return that surface. If the window is
// either the shell surface's window, or host window, it will return the root
// surface, otherwise returns nullptr.
Surface* GetTargetSurfaceForKeyboardFocus(aura::Window* focused_window);

// Allows the |window| to activate itself for the duration of |timeout|. Revokes
// any existing permission.
void GrantPermissionToActivate(aura::Window* window, base::TimeDelta timeout);
Expand Down
80 changes: 80 additions & 0 deletions components/exo/shell_surface_util_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2021 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/shell_surface_util.h"

#include "components/exo/shell_surface.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/test/exo_test_base.h"
#include "components/exo/test/shell_surface_builder.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"

namespace exo {
namespace {

using ShellSurfaceUtilTest = test::ExoTestBase;

void SetPositionAtOrigin(ui::LocatedEvent* event, aura::Window* target) {
ui::Event::DispatcherApi test_api(event);
test_api.set_target(target);
gfx::Point point;
aura::Window::ConvertPointToTarget(target, target->GetRootWindow(), &point);
event->set_location(point);
}

TEST_F(ShellSurfaceUtilTest, TargetForLocatedEvent) {
auto shell_surface = test::ShellSurfaceBuilder({20, 20})
.SetOrigin({10, 10})
.BuildShellSurface();
auto* root_surface = shell_surface->root_surface();
auto* child_surface = test::ShellSurfaceBuilder::AddChildSurface(
root_surface, {10, 10, 10, 10});
child_surface->Commit();
root_surface->Commit();

ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(0, 0),
gfx::Point(0, 0), ui::EventTimeForNow(), 0, 0);
aura::Window* root_window = root_surface->window()->GetRootWindow();
ui::Event::DispatcherApi(&mouse_event).set_target(root_window);
EXPECT_EQ(nullptr, GetTargetSurfaceForLocatedEvent(&mouse_event));

SetPositionAtOrigin(&mouse_event, root_surface->window());
EXPECT_EQ(root_surface, GetTargetSurfaceForLocatedEvent(&mouse_event));
SetPositionAtOrigin(&mouse_event, child_surface->window());
EXPECT_EQ(child_surface, GetTargetSurfaceForLocatedEvent(&mouse_event));

// Capture
auto* shell_surface_window = shell_surface->GetWidget()->GetNativeWindow();
shell_surface_window->SetCapture();
ui::Event::DispatcherApi(&mouse_event).set_target(shell_surface_window);
mouse_event.set_location({-1, -1});
EXPECT_EQ(root_surface, GetTargetSurfaceForLocatedEvent(&mouse_event));
mouse_event.set_location({1, 1});
EXPECT_EQ(root_surface, GetTargetSurfaceForLocatedEvent(&mouse_event));
mouse_event.set_location({11, 11});
EXPECT_EQ(child_surface, GetTargetSurfaceForLocatedEvent(&mouse_event));
shell_surface.reset();
}

TEST_F(ShellSurfaceUtilTest, TargetForKeyboardFocus) {
auto shell_surface = test::ShellSurfaceBuilder({20, 20})
.SetOrigin({10, 10})
.BuildShellSurface();
auto* root_surface = shell_surface->root_surface();
auto* child_surface = test::ShellSurfaceBuilder::AddChildSurface(
root_surface, {10, 10, 10, 10});

EXPECT_EQ(child_surface,
GetTargetSurfaceForKeyboardFocus(child_surface->window()));
EXPECT_EQ(root_surface,
GetTargetSurfaceForKeyboardFocus(root_surface->window()));
EXPECT_EQ(root_surface,
GetTargetSurfaceForKeyboardFocus(shell_surface->host_window()));
EXPECT_EQ(root_surface, GetTargetSurfaceForKeyboardFocus(
shell_surface->GetWidget()->GetNativeWindow()));
}

} // namespace
} // namespace exo
97 changes: 81 additions & 16 deletions components/exo/test/shell_surface_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,78 @@

#include "components/exo/test/shell_surface_builder.h"

#include <tuple>

#include "ash/wm/desks/desks_util.h"
#include "ash/wm/window_positioning_utils.h"
#include "components/exo/buffer.h"
#include "components/exo/sub_surface.h"
#include "components/exo/surface.h"
#include "components/exo/test/exo_test_helper.h"
#include "components/exo/xdg_shell_surface.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "ui/aura/env.h"

#include "base/logging.h"

namespace {

// Internal structure that owns buffer and surface. This is owned by
// the host window as an owned property.
// Internal structure that owns buffer, surface and subsurface instances.
// This is owned by the host window as an owned property.
struct Holder {
std::unique_ptr<exo::Buffer> root_buffer;
std::unique_ptr<exo::Surface> root_surface;
exo::Surface* root_surface = nullptr;
std::vector<std::tuple<std::unique_ptr<exo::Buffer>,
std::unique_ptr<exo::Surface>,
std::unique_ptr<exo::SubSurface>>>
sub_surfaces;

void AddRootSurface(const gfx::Size& size, gfx::BufferFormat buffer_format) {
auto buffer = std::make_unique<exo::Buffer>(
aura::Env::GetInstance()
->context_factory()
->GetGpuMemoryBufferManager()
->CreateGpuMemoryBuffer(size, buffer_format,
gfx::BufferUsage::GPU_READ,
gpu::kNullSurfaceHandle));
auto surface = std::make_unique<exo::Surface>();
surface->Attach(buffer.get());
root_surface = surface.get();
sub_surfaces.push_back(
std::make_tuple<>(std::move(buffer), std::move(surface), nullptr));
}

exo::Surface* AddChildSurface(exo::Surface* parent, const gfx::Rect& bounds) {
auto buffer = std::make_unique<exo::Buffer>(
aura::Env::GetInstance()
->context_factory()
->GetGpuMemoryBufferManager()
->CreateGpuMemoryBuffer(bounds.size(), gfx::BufferFormat::RGBA_8888,
gfx::BufferUsage::GPU_READ,
gpu::kNullSurfaceHandle));

auto surface = std::make_unique<exo::Surface>();
surface->Attach(buffer.get());
auto sub_surface = std::make_unique<exo::SubSurface>(surface.get(), parent);
sub_surface->SetPosition(bounds.origin());

auto* surface_ptr = surface.get();
sub_surfaces.push_back(std::make_tuple<>(
std::move(buffer), std::move(surface), std::move(sub_surface)));
return surface_ptr;
}

void DestroyRootSurface() {
DCHECK(root_surface);
for (auto& tuple : sub_surfaces) {
if (std::get<1>(tuple).get() == root_surface) {
std::get<0>(tuple).reset();
std::get<1>(tuple).reset();
std::get<2>(tuple).reset();
break;
}
}
root_surface = nullptr;
}
};

} // namespace
Expand All @@ -32,6 +88,16 @@ namespace {

DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(Holder, kBuilderResourceHolderKey, nullptr)

Holder* FindHolder(Surface* surface) {
aura::Window* window = surface->window();
Holder* holder = window->GetProperty(kBuilderResourceHolderKey);
while (!holder && window->parent()) {
window = window->parent();
holder = window->GetProperty(kBuilderResourceHolderKey);
}
return holder;
}

} // namespace

ShellSurfaceBuilder::ShellSurfaceBuilder(const gfx::Size& buffer_size)
Expand Down Expand Up @@ -93,30 +159,29 @@ void ShellSurfaceBuilder::DestroyRootSurface(ShellSurfaceBase* shell_surface) {
Holder* holder =
shell_surface->host_window()->GetProperty(kBuilderResourceHolderKey);
DCHECK(holder);
holder->root_surface.reset();
holder->DestroyRootSurface();
}

// static
Surface* ShellSurfaceBuilder::AddChildSurface(Surface* parent,
const gfx::Rect& bounds) {
Holder* holder = FindHolder(parent);
DCHECK(holder);
return holder->AddChildSurface(parent, bounds);
}

std::unique_ptr<ShellSurface> ShellSurfaceBuilder::BuildShellSurface() {
DCHECK(!built_);
built_ = true;
Holder* holder = new Holder();
holder->root_buffer = std::make_unique<Buffer>(
aura::Env::GetInstance()
->context_factory()
->GetGpuMemoryBufferManager()
->CreateGpuMemoryBuffer(root_buffer_size_, root_buffer_format_,
gfx::BufferUsage::GPU_READ,
gpu::kNullSurfaceHandle));

holder->root_surface = std::make_unique<Surface>();
holder->AddRootSurface(root_buffer_size_, root_buffer_format_);

int container = use_system_modal_container_
? ash::kShellWindowId_SystemModalContainer
: ash::desks_util::GetActiveDeskContainerId();

auto shell_surface = std::make_unique<ShellSurface>(
holder->root_surface.get(), origin_, can_minimize_, container);
holder->root_surface->Attach(holder->root_buffer.get());
holder->root_surface, origin_, can_minimize_, container);
shell_surface->host_window()->SetProperty(kBuilderResourceHolderKey, holder);

if (parent_shell_surface_)
Expand Down
3 changes: 3 additions & 0 deletions components/exo/test/shell_surface_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
namespace exo {
class ShellSurface;
class ShellSurfaceBase;
class Surface;

namespace test {

Expand Down Expand Up @@ -45,6 +46,8 @@ class ShellSurfaceBuilder {

// Destroy's the root surface of the given 'shell_surface'.
static void DestroyRootSurface(ShellSurfaceBase* shell_surface);
static Surface* AddChildSurface(Surface* parent_surface,
const gfx::Rect& bounds);

private:
gfx::Size root_buffer_size_;
Expand Down
11 changes: 6 additions & 5 deletions components/exo/ui_lock_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@ UILockController::~UILockController() {
}

void UILockController::OnKeyEvent(ui::KeyEvent* event) {
// If the event target is not an exo::Surface, let another handler process the
// event.
if (!GetShellRootSurface(static_cast<aura::Window*>(event->target())) &&
!Surface::AsSurface(static_cast<aura::Window*>(event->target()))) {
// TODO(oshima): Rather than handling key event here, add a hook in
// keyboard.cc to intercept key event and handle this.

// If no surface is focused, let another handler process the event.
aura::Window* window = static_cast<aura::Window*>(event->target());
if (!GetTargetSurfaceForKeyboardFocus(window))
return;
}

if (event->code() == ui::DomCode::ESCAPE &&
(event->flags() & kExcludedFlags) == 0) {
Expand Down
Loading

0 comments on commit 7a29f96

Please sign in to comment.