Commit 3d3468d1 authored by Daichi Hirono's avatar Daichi Hirono Committed by Commit Bot

Add Seat object to exo

Seat is corresponding to wl_saet and will be used to synchronize
wl_data_device#selection and wl_keyboard#enter events

Bug: 773978
Change-Id: Iaca10177f95aebac3822e6e534b9e640852e4ead
Reviewed-on: https://chromium-review.googlesource.com/770453Reviewed-by: default avatarYoshiki Iguchi <yoshiki@chromium.org>
Reviewed-by: default avatarDavid Reveman <reveman@chromium.org>
Commit-Queue: Daichi Hirono <hirono@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517743}
parent 7bfd0bc8
......@@ -37,6 +37,9 @@ source_set("exo") {
"pointer.cc",
"pointer.h",
"pointer_delegate.h",
"seat.cc",
"seat.h",
"seat_observer.h",
"shared_memory.cc",
"shared_memory.h",
"shell_surface.cc",
......@@ -125,6 +128,7 @@ source_set("unit_tests") {
"gaming_seat_unittest.cc",
"keyboard_unittest.cc",
"pointer_unittest.cc",
"seat_unittest.cc",
"shared_memory_unittest.cc",
"shell_surface_unittest.cc",
"sub_surface_unittest.cc",
......
......@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/memory/shared_memory_handle.h"
#include "components/exo/seat.h"
#if defined(USE_OZONE)
#include "base/files/scoped_file.h"
......@@ -86,9 +87,13 @@ class Display {
// Creates a data device for a |delegate|.
std::unique_ptr<DataDevice> CreateDataDevice(DataDeviceDelegate* delegate);
// Obtains seat instance.
Seat* seat() { return &seat_; }
private:
NotificationSurfaceManager* const notification_surface_manager_;
std::unique_ptr<FileHelper> file_helper_;
Seat seat_;
#if defined(USE_OZONE)
std::vector<gfx::BufferFormat> overlay_formats_;
......
......@@ -7,7 +7,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "components/exo/keyboard_delegate.h"
#include "components/exo/keyboard_device_configuration_delegate.h"
#include "components/exo/shell_surface.h"
#include "components/exo/seat.h"
#include "components/exo/surface.h"
#include "components/exo/wm_helper.h"
#include "ui/aura/client/focus_client.h"
......@@ -126,17 +126,18 @@ bool IsReservedAccelerator(const ui::KeyEvent* event) {
////////////////////////////////////////////////////////////////////////////////
// Keyboard, public:
Keyboard::Keyboard(KeyboardDelegate* delegate)
Keyboard::Keyboard(KeyboardDelegate* delegate, Seat* seat)
: delegate_(delegate),
seat_(seat),
expiration_delay_for_pending_key_acks_(base::TimeDelta::FromMilliseconds(
kExpirationDelayForPendingKeyAcksMs)),
weak_ptr_factory_(this) {
auto* helper = WMHelper::GetInstance();
AddEventHandler();
helper->AddFocusObserver(this);
seat_->AddObserver(this);
helper->AddTabletModeObserver(this);
helper->AddInputDeviceEventObserver(this);
OnWindowFocused(helper->GetFocusedWindow(), nullptr);
OnSurfaceFocused(seat_->GetFocusedSurface());
}
Keyboard::~Keyboard() {
......@@ -146,7 +147,7 @@ Keyboard::~Keyboard() {
focus_->RemoveSurfaceObserver(this);
auto* helper = WMHelper::GetInstance();
RemoveEventHandler();
helper->RemoveFocusObserver(this);
seat_->RemoveObserver(this);
helper->RemoveTabletModeObserver(this);
helper->RemoveInputDeviceEventObserver(this);
}
......@@ -267,29 +268,6 @@ void Keyboard::OnKeyEvent(ui::KeyEvent* event) {
ScheduleProcessExpiredPendingKeyAcks(expiration_delay_for_pending_key_acks_);
}
////////////////////////////////////////////////////////////////////////////////
// aura::client::FocusChangeObserver overrides:
void Keyboard::OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) {
Surface* gained_focus_surface =
gained_focus ? GetEffectiveFocus(gained_focus) : nullptr;
if (gained_focus_surface != focus_) {
if (focus_) {
delegate_->OnKeyboardLeave(focus_);
focus_->RemoveSurfaceObserver(this);
focus_ = nullptr;
pending_key_acks_.clear();
}
if (gained_focus_surface) {
delegate_->OnKeyboardModifiers(modifier_flags_);
delegate_->OnKeyboardEnter(gained_focus_surface, pressed_keys_);
focus_ = gained_focus_surface;
focus_->AddSurfaceObserver(this);
}
}
}
////////////////////////////////////////////////////////////////////////////////
// SurfaceObserver overrides:
......@@ -323,22 +301,32 @@ void Keyboard::OnTabletModeEnded() {
}
////////////////////////////////////////////////////////////////////////////////
// Keyboard, private:
// SeatObserver overrides:
Surface* Keyboard::GetEffectiveFocus(aura::Window* window) const {
// Use window surface as effective focus.
Surface* focus = Surface::AsSurface(window);
if (!focus) {
// Fallback to main surface.
aura::Window* top_level_window = window->GetToplevelWindow();
if (top_level_window)
focus = ShellSurface::GetMainSurface(top_level_window);
void Keyboard::OnSurfaceFocused(Surface* gained_focus) {
Surface* gained_focus_surface =
gained_focus && delegate_->CanAcceptKeyboardEventsForSurface(gained_focus)
? gained_focus
: nullptr;
if (gained_focus_surface != focus_) {
if (focus_) {
delegate_->OnKeyboardLeave(focus_);
focus_->RemoveSurfaceObserver(this);
focus_ = nullptr;
pending_key_acks_.clear();
}
if (gained_focus_surface) {
delegate_->OnKeyboardModifiers(modifier_flags_);
delegate_->OnKeyboardEnter(gained_focus_surface, pressed_keys_);
focus_ = gained_focus_surface;
focus_->AddSurfaceObserver(this);
}
}
return focus && delegate_->CanAcceptKeyboardEventsForSurface(focus) ? focus
: nullptr;
}
////////////////////////////////////////////////////////////////////////////////
// Keyboard, private:
void Keyboard::ProcessExpiredPendingKeyAcks() {
DCHECK(process_expired_pending_key_acks_pending_);
process_expired_pending_key_acks_pending_ = false;
......
......@@ -12,8 +12,8 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "components/exo/keyboard_observer.h"
#include "components/exo/seat_observer.h"
#include "components/exo/surface_observer.h"
#include "ui/aura/client/focus_change_observer.h"
#include "ui/events/devices/input_device_event_observer.h"
#include "ui/events/event.h"
#include "ui/events/event_handler.h"
......@@ -26,17 +26,18 @@ class KeyEvent;
namespace exo {
class KeyboardDelegate;
class KeyboardDeviceConfigurationDelegate;
class Seat;
class Surface;
// This class implements a client keyboard that represents one or more keyboard
// devices.
class Keyboard : public ui::EventHandler,
public aura::client::FocusChangeObserver,
public ui::InputDeviceEventObserver,
public ash::TabletModeObserver,
public SurfaceObserver {
public SurfaceObserver,
public SeatObserver {
public:
explicit Keyboard(KeyboardDelegate* delegate);
Keyboard(KeyboardDelegate* delegate, Seat* seat);
~Keyboard() override;
bool HasDeviceConfigurationDelegate() const;
......@@ -56,9 +57,6 @@ class Keyboard : public ui::EventHandler,
// Overridden from ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override;
// Overridden ui::aura::client::FocusChangeObserver:
void OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) override;
// Overridden from SurfaceObserver:
void OnSurfaceDestroying(Surface* surface) override;
......@@ -71,10 +69,10 @@ class Keyboard : public ui::EventHandler,
void OnTabletModeEnding() override;
void OnTabletModeEnded() override;
private:
// Returns the effective focus for |window|.
Surface* GetEffectiveFocus(aura::Window* window) const;
// Overridden from SeatObserver:
void OnSurfaceFocused(Surface* gained_focus) override;
private:
// Processes expired key state changes in |pending_key_acks_| as they have not
// been acknowledged.
void ProcessExpiredPendingKeyAcks();
......@@ -94,6 +92,9 @@ class Keyboard : public ui::EventHandler,
// configuration are dispatched to.
KeyboardDelegate* const delegate_;
// Seat that the Keyboard recieves focus events from.
Seat* const seat_;
// The delegate instance that events about device configuration are dispatched
// to.
KeyboardDeviceConfigurationDelegate* device_configuration_delegate_ = nullptr;
......
......@@ -12,6 +12,7 @@
#include "components/exo/keyboard_delegate.h"
#include "components/exo/keyboard_device_configuration_delegate.h"
#include "components/exo/keyboard_observer.h"
#include "components/exo/seat.h"
#include "components/exo/shell_surface.h"
#include "components/exo/surface.h"
#include "components/exo/test/exo_test_base.h"
......@@ -83,7 +84,8 @@ TEST_F(KeyboardTest, OnKeyboardEnter) {
MockKeyboardDelegate delegate;
EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
.WillOnce(testing::Return(false));
std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
generator.PressKey(ui::VKEY_A, 0);
......@@ -120,7 +122,8 @@ TEST_F(KeyboardTest, OnKeyboardLeave) {
focus_client->FocusWindow(nullptr);
MockKeyboardDelegate delegate;
std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
.WillOnce(testing::Return(true));
......@@ -149,7 +152,8 @@ TEST_F(KeyboardTest, OnKeyboardKey) {
focus_client->FocusWindow(nullptr);
MockKeyboardDelegate delegate;
std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
.WillOnce(testing::Return(true));
......@@ -187,7 +191,8 @@ TEST_F(KeyboardTest, OnKeyboardModifiers) {
focus_client->FocusWindow(nullptr);
MockKeyboardDelegate delegate;
std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
.WillOnce(testing::Return(true));
......@@ -242,7 +247,8 @@ TEST_F(KeyboardTest, OnKeyboardTypeChanged) {
tablet_mode_controller->EnableTabletModeWindowManager(true);
MockKeyboardDelegate delegate;
std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
MockKeyboardDeviceConfigurationDelegate configuration_delegate;
EXPECT_CALL(configuration_delegate, OnKeyboardTypeChanged(true));
......@@ -278,7 +284,8 @@ TEST_F(KeyboardTest, KeyboardObserver) {
focus_client->FocusWindow(nullptr);
MockKeyboardDelegate delegate;
auto keyboard = std::make_unique<Keyboard>(&delegate);
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
MockKeyboardObserver observer;
keyboard->AddObserver(&observer);
......@@ -300,7 +307,8 @@ TEST_F(KeyboardTest, NeedKeyboardKeyAcks) {
focus_client->FocusWindow(nullptr);
MockKeyboardDelegate delegate;
auto keyboard = std::make_unique<Keyboard>(&delegate);
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
EXPECT_FALSE(keyboard->AreKeyboardKeyAcksNeeded());
keyboard->SetNeedKeyboardKeyAcks(true);
......@@ -325,7 +333,8 @@ TEST_F(KeyboardTest, AckKeyboardKey) {
focus_client->FocusWindow(nullptr);
MockKeyboardDelegate delegate;
std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
.WillOnce(testing::Return(true));
......@@ -403,7 +412,8 @@ TEST_F(KeyboardTest, AckKeyboardKeyMoveFocus) {
focus_client->FocusWindow(nullptr);
MockKeyboardDelegate delegate;
std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
.WillOnce(testing::Return(true));
......@@ -445,7 +455,8 @@ TEST_F(KeyboardTest, AckKeyboardKeyExpired) {
focus_client->FocusWindow(nullptr);
MockKeyboardDelegate delegate;
std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
.WillOnce(testing::Return(true));
......@@ -517,7 +528,8 @@ TEST_F(KeyboardTest, AckKeyboardKeyExpiredWithMovingFocusAccelerator) {
focus_client->FocusWindow(nullptr);
MockKeyboardDelegate delegate;
std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
Seat seat;
auto keyboard = std::make_unique<Keyboard>(&delegate, &seat);
EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
.WillOnce(testing::Return(true));
......
// Copyright 2017 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/seat.h"
#include "ash/shell.h"
#include "components/exo/keyboard.h"
#include "components/exo/shell_surface.h"
#include "components/exo/surface.h"
#include "components/exo/wm_helper.h"
#include "ui/aura/client/focus_client.h"
namespace exo {
namespace {
Surface* GetEffectiveFocus(aura::Window* window) {
if (!window)
return nullptr;
Surface* const surface = Surface::AsSurface(window);
if (surface)
return surface;
// Fallback to main surface.
aura::Window* const top_level_window = window->GetToplevelWindow();
if (!top_level_window)
return nullptr;
return ShellSurface::GetMainSurface(top_level_window);
}
} // namespace
Seat::Seat() {
aura::client::GetFocusClient(ash::Shell::Get()->GetPrimaryRootWindow())
->AddObserver(this);
}
Seat::~Seat() {
aura::client::GetFocusClient(ash::Shell::Get()->GetPrimaryRootWindow())
->RemoveObserver(this);
}
void Seat::AddObserver(SeatObserver* observer) {
observers_.AddObserver(observer);
}
void Seat::RemoveObserver(SeatObserver* observer) {
observers_.RemoveObserver(observer);
}
Surface* Seat::GetFocusedSurface() {
return GetEffectiveFocus(WMHelper::GetInstance()->GetFocusedWindow());
}
void Seat::OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) {
Surface* const surface = GetEffectiveFocus(gained_focus);
for (auto& observer : observers_) {
observer.OnSurfaceFocused(surface);
}
}
} // namespace exo
// Copyright 2017 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_SEAT_H_
#define COMPONENTS_EXO_SEAT_H_
#include "base/observer_list.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/client/focus_change_observer.h"
namespace exo {
class SeatObserver;
class Surface;
// Seat object represent a group of input devices such as keyboard, pointer and
// touch devices and keeps track of input focus.
class Seat : public aura::client::FocusChangeObserver {
public:
Seat();
~Seat() override;
void AddObserver(SeatObserver* observer);
void RemoveObserver(SeatObserver* observer);
// Returns currently focused surface.
Surface* GetFocusedSurface();
// Overridden from aura::client::FocusChangeObserver:
void OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) override;
private:
base::ObserverList<SeatObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(Seat);
};
} // namespace exo
#endif // COMPONENTS_EXO_SEAT_H_
// Copyright 2017 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_SEAT_OBSERVER_H_
#define COMPONENTS_EXO_SEAT_OBSERVER_H_
namespace exo {
class Surface;
// Observers can listen to various events on the Seats.
class SeatObserver {
public:
// Called when a new surface receives keyboard focus.
virtual void OnSurfaceFocused(Surface* surface) = 0;
protected:
virtual ~SeatObserver() {}
};
} // namespace exo
#endif // COMPONENTS_EXO_SEAT_OBSERVER_H_
// Copyright 2017 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/seat.h"
#include "base/memory/scoped_refptr.h"
#include "components/exo/seat_observer.h"
#include "components/exo/test/exo_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace exo {
namespace {
using SeatTest = test::ExoTestBase;
class MockSeatObserver : public SeatObserver {
public:
int on_surface_focused_count() { return on_surface_focused_count_; }
// Overridden from SeatObserver:
void OnSurfaceFocused(Surface* surface) override {
on_surface_focused_count_++;
}
private:
int on_surface_focused_count_ = 0;
};
TEST_F(SeatTest, OnSurfaceFocused) {
Seat seat;
MockSeatObserver observer;
seat.AddObserver(&observer);
seat.OnWindowFocused(nullptr, nullptr);
ASSERT_EQ(1, observer.on_surface_focused_count());
seat.RemoveObserver(&observer);
seat.OnWindowFocused(nullptr, nullptr);
ASSERT_EQ(1, observer.on_surface_focused_count());
}
} // namespace
} // namespace exo
......@@ -119,6 +119,8 @@ source_set("unit_tests") {
":wayland",
"//base",
"//components/exo",
"//components/exo:test_support",
"//skia",
"//testing/gtest",
"//third_party/wayland:wayland_client",
]
......
......@@ -3365,7 +3365,8 @@ void seat_get_keyboard(wl_client* client, wl_resource* resource, uint32_t id) {
WaylandKeyboardDelegate* delegate =
new WaylandKeyboardDelegate(keyboard_resource);
std::unique_ptr<Keyboard> keyboard = std::make_unique<Keyboard>(delegate);
std::unique_ptr<Keyboard> keyboard =
std::make_unique<Keyboard>(delegate, GetUserDataAs<Seat>(resource));
keyboard->AddObserver(delegate);
SetImplementation(keyboard_resource, &keyboard_implementation,
std::move(keyboard));
......@@ -4454,7 +4455,7 @@ Server::Server(Display* display)
data_device_manager_version, display_,
bind_data_device_manager);
wl_global_create(wl_display_.get(), &wl_seat_interface, seat_version,
display_, bind_seat);
display_->seat(), bind_seat);
wl_global_create(wl_display_.get(), &wp_viewporter_interface, 1, display_,
bind_viewporter);
wl_global_create(wl_display_.get(), &wp_presentation_interface, 1, display_,
......
......@@ -17,6 +17,7 @@
#include "base/strings/stringprintf.h"
#include "base/threading/thread.h"
#include "components/exo/display.h"
#include "components/exo/test/exo_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace exo {
......@@ -30,7 +31,7 @@ std::string GetUniqueSocketName() {
g_next_socket_id.GetNext());
}
class ServerTest : public testing::Test {
class ServerTest : public test::ExoTestBase {
public:
ServerTest() {}
~ServerTest() override {}
......@@ -39,7 +40,7 @@ class ServerTest : public testing::Test {
ASSERT_TRUE(xdg_temp_dir_.CreateUniqueTempDir());
setenv("XDG_RUNTIME_DIR", xdg_temp_dir_.GetPath().MaybeAsASCII().c_str(),
1 /* overwrite */);
testing::Test::SetUp();
test::ExoTestBase::SetUp();
}
private:
......
......@@ -15,6 +15,7 @@
#include "components/exo/keyboard.h"
#include "components/exo/keyboard_delegate.h"
#include "components/exo/notification_surface.h"
#include "components/exo/seat.h"
#include "components/exo/surface.h"
#include "components/exo/test/exo_test_helper.h"
#include "components/exo/wm_helper.h"
......@@ -512,7 +513,8 @@ TEST_F(ArcNotificationContentViewTest, AcceptInputTextWithActivate) {
MockKeyboardDelegate delegate;
EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface()))
.WillOnce(testing::Return(true));
auto keyboard = std::make_unique<exo::Keyboard>(&delegate);
exo::Seat seat;
auto keyboard = std::make_unique<exo::Keyboard>(&delegate, &seat);
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_A, true));
......@@ -534,7 +536,8 @@ TEST_F(ArcNotificationContentViewTest, NotAcceptInputTextWithoutActivate) {
MockKeyboardDelegate delegate;
EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface())).Times(0);
auto keyboard = std::make_unique<exo::Keyboard>(&delegate);
exo::Seat seat;
auto keyboard = std::make_unique<exo::Keyboard>(&delegate, &seat);
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, OnKeyboardKey(testing::_, testing::_, testing::_))
......
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