Skip to content

Commit

Permalink
[DoNotCarryForward] [ozone/wayland] Implement not implemented methods…
Browse files Browse the repository at this point in the history
… in WaylandScreen.

- GetDisplayForAcceleratedWidget:
* This CL implements wl_surface_listener, which says what
 wl_output a wl_surface enters. That information is then
 used to identify on what display an accelerated widget is shown.

 To give more details, a WaylandWindow sets a wl_surface_listener now.
 As soon as that specific window enters a certain display,
 wl_surface_listener::enter event is called, and the WaylandWindow
 receives a pointer to that specific wl_output where it is shown.

 Then, the window uses WaylandOutputManager to identify the id of
 that display/output and stores it.

 Once the WaylandScreen::GetDisplayForAcceleratedWidget call comes,
 a WaylandWindow, which corresponds to that specific widget, is found
 and the id of the output it is shown on is taken.

 If there are two outputs used to show the window, the very first one
 is always used.

- GetAcceleratedWidgetAtScreenPoint
* This is a tricky one. To ensure right functionality, a widget under a
 cursor must be returned. But, Wayland clients cannot know where the windows
 are located in the global space coordinate system. Instead, it's possible
 to know widgets located on a surface local coordinate system (remember that
 clients cannot also know the position of the pointer in the global space
 coordinate system, but rather on a local surface coordinate system). That
 is, we will have to pretend that a single surface is a "display", where
 other widgets (child widgets are located in the surface local coordinate
 system, where the main surface has 0,0 origin) are shown. Whenever that
 surface is focused (the cursor is located under that widget), we will use
 it to determine if the point is on that main surface, a menu surface and
 etc.

 Note that bounds where widgets are shown will be fixed in the follow-up cl.
 Now, the widgets are not shown properly if the returned display has origin
 different from 0,0. That is, remember that wayland requires placing them
 relatively to the parent surface, which Chromium does not honor, but rather
 uses global space coordinate system.

- GetDisplayNearestPoint and GetDisplayMatching:
* Nothing special. Both of them use the existing helper methods.

Bug: 875161, 890271, 890272
Change-Id: I7d6d8a7d6827cf639df2c3f0992deece156b2962
  • Loading branch information
msisov authored and jkim-julie committed Oct 15, 2018
1 parent 1785f1f commit 005f532
Show file tree
Hide file tree
Showing 12 changed files with 473 additions and 63 deletions.
10 changes: 10 additions & 0 deletions ui/ozone/platform/wayland/fake_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,16 @@ void FakeServer::Resume() {
resume_event_.Signal();
}

MockOutput* FakeServer::CreateAndInitializeOutput() {
auto output = std::make_unique<MockOutput>();
output->Initialize(display());

MockOutput* output_ptr = output.get();
globals_.push_back(std::move(output));

return output_ptr;
}

void FakeServer::DoPause() {
base::RunLoop().RunUntilIdle();
pause_event_.Signal();
Expand Down
6 changes: 1 addition & 5 deletions ui/ozone/platform/wayland/fake_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,11 +453,7 @@ class FakeServer : public base::Thread, base::MessagePumpLibevent::FdWatcher {
return resource ? T::FromResource(resource) : nullptr;
}

void CreateAndInitializeOutput() {
auto output = std::make_unique<MockOutput>();
output->Initialize(display());
globals_.push_back(std::move(output));
}
MockOutput* CreateAndInitializeOutput();

MockDataDeviceManager* data_device_manager() { return &data_device_manager_; }
MockSeat* seat() { return &seat_; }
Expand Down
3 changes: 2 additions & 1 deletion ui/ozone/platform/wayland/ozone_platform_wayland.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ class OzonePlatformWayland : public OzonePlatform {
// The WaylandConnection and the WaylandOutputManager must be created before
// PlatformScreen.
DCHECK(connection_ && connection_->wayland_output_manager());
return connection_->wayland_output_manager()->CreateWaylandScreen();
return connection_->wayland_output_manager()->CreateWaylandScreen(
connection_.get());
}

void InitializeUI(const InitParams& args) override {
Expand Down
5 changes: 3 additions & 2 deletions ui/ozone/platform/wayland/wayland_output.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ void WaylandOutput::Initialize(Delegate* delegate) {
}

void WaylandOutput::TriggerDelegateNotification() const {
DCHECK(!rect_in_physical_pixels_.IsEmpty());
delegate_->OnOutputHandleMetrics(output_id_, rect_in_physical_pixels_,
device_scale_factor_);
}
Expand All @@ -51,8 +50,10 @@ void WaylandOutput::OutputHandleGeometry(void* data,
const char* model,
int32_t output_transform) {
WaylandOutput* wayland_output = static_cast<WaylandOutput*>(data);
if (wayland_output)
if (wayland_output) {
wayland_output->rect_in_physical_pixels_.set_origin(gfx::Point(x, y));
wayland_output->TriggerDelegateNotification();
}
}

// static
Expand Down
3 changes: 3 additions & 0 deletions ui/ozone/platform/wayland/wayland_output.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class WaylandOutput {

void TriggerDelegateNotification() const;

// Says whether this WaylandOutput is a wrapper of the passed |output|.
bool has_output(wl_output* output) const { return output_.get() == output; }

uint32_t output_id() const { return output_id_; }

// Tells if the output has already received physical screen dimensions in the
Expand Down
15 changes: 13 additions & 2 deletions ui/ozone/platform/wayland/wayland_output_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,19 @@ void WaylandOutputManager::RemoveWaylandOutput(const uint32_t output_id) {
OnWaylandOutputRemoved(output_id);
}

std::unique_ptr<WaylandScreen> WaylandOutputManager::CreateWaylandScreen() {
auto wayland_screen = std::make_unique<WaylandScreen>();
uint32_t WaylandOutputManager::GetIdForOutput(wl_output* output) const {
auto output_it = std::find_if(output_list_.begin(), output_list_.end(),
[output](const auto& wayland_output) {
return wayland_output->has_output(output);
});
// This is unlikely to happen, but let's be explicit here.
DCHECK(output_it != output_list_.end());
return output_it->get()->output_id();
}

std::unique_ptr<WaylandScreen> WaylandOutputManager::CreateWaylandScreen(
WaylandConnection* connection) {
auto wayland_screen = std::make_unique<WaylandScreen>(connection);
wayland_screen_ = wayland_screen->GetWeakPtr();

// As long as |wl_output| sends geometry and other events asynchronously (that
Expand Down
6 changes: 5 additions & 1 deletion ui/ozone/platform/wayland/wayland_output_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct wl_output;

namespace ui {

class WaylandConnection;
class WaylandOutput;

class WaylandOutputManager : public WaylandOutput::Delegate {
Expand All @@ -32,8 +33,11 @@ class WaylandOutputManager : public WaylandOutput::Delegate {
void AddWaylandOutput(const uint32_t output_id, wl_output* output);
void RemoveWaylandOutput(const uint32_t output_id);

uint32_t GetIdForOutput(wl_output* output) const;

// Creates a platform screen and feeds it with existing outputs.
std::unique_ptr<WaylandScreen> CreateWaylandScreen();
std::unique_ptr<WaylandScreen> CreateWaylandScreen(
WaylandConnection* connection);

private:
void OnWaylandOutputAdded(uint32_t output_id);
Expand Down
86 changes: 68 additions & 18 deletions ui/ozone/platform/wayland/wayland_screen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
#include "ui/display/display_observer.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_window.h"

namespace ui {

WaylandScreen::WaylandScreen() : weak_factory_(this) {}
WaylandScreen::WaylandScreen(WaylandConnection* connection)
: connection_(connection), weak_factory_(this) {}

WaylandScreen::~WaylandScreen() = default;

Expand Down Expand Up @@ -59,12 +62,23 @@ display::Display WaylandScreen::GetPrimaryDisplay() const {

display::Display WaylandScreen::GetDisplayForAcceleratedWidget(
gfx::AcceleratedWidget widget) const {
// TODO(msisov): implement wl_surface_listener::enter and
// wl_surface_listener::leave for a wl_surface to know what surface the window
// is located on.
//
// https://crbug.com/890271
NOTIMPLEMENTED_LOG_ONCE();
auto* wayland_window = connection_->GetWindow(widget);
if (!wayland_window)
return GetPrimaryDisplay();

const std::vector<uint32_t> entered_outputs_ids =
wayland_window->entered_outputs_ids();
if (entered_outputs_ids.empty())
return GetPrimaryDisplay();

// A widget can be located on two displays. Return the one, which was the very
// first used.
for (const auto& display : display_list_.displays()) {
if (display.id() == entered_outputs_ids.front())
return display;
}

NOTREACHED();
return GetPrimaryDisplay();
}

Expand All @@ -75,25 +89,61 @@ gfx::Point WaylandScreen::GetCursorScreenPoint() const {

gfx::AcceleratedWidget WaylandScreen::GetAcceleratedWidgetAtScreenPoint(
const gfx::Point& point) const {
// TODO(msisov): implement this once wl_surface_listener::enter and ::leave
// are used.
//
// https://crbug.com/890271
NOTIMPLEMENTED_LOG_ONCE();
return gfx::kNullAcceleratedWidget;
// This is a tricky one. To ensure right functionality, a widget under a
// cursor must be returned. But, Wayland clients cannot know where the windows
// are located in the global space coordinate system. Instead, it's possible
// to know widgets located on a surface local coordinate system (remember that
// clients cannot also know the position of the pointer in the global space
// coordinate system, but rather on a local surface coordinate system). That
// is, we will have to pretend that a single surface is a "display", where
// other widgets (child widgets are located in the surface local coordinate
// system, where the main surface has 0,0 origin) are shown. Whenever that
// surface is focused (the cursor is located under that widget), we will use
// it to determine if the point is on that main surface, a menu surface and
// etc.

// This call comes only when a cursor is under a certain window (see how
// Wayland sends pointer events for better understanding + comment above).
auto* window = connection_->GetCurrentFocusedWindow();
if (!window)
return gfx::kNullAcceleratedWidget;

// If |point| is at origin and the focused window does not contain that point,
// it must be the root parent, which contains that |point|.
if (point.IsOrigin() && !window->GetBounds().Contains(point)) {
WaylandWindow* parent_window = nullptr;
do {
parent_window = window->parent_window();
if (parent_window)
window = parent_window;
} while (parent_window);
DCHECK(!window->parent_window());
}

DCHECK(window->GetBounds().Contains(point));
return window->GetWidget();
}

display::Display WaylandScreen::GetDisplayNearestPoint(
const gfx::Point& point) const {
NOTIMPLEMENTED_LOG_ONCE();
return GetPrimaryDisplay();
if (display_list_.displays().size() <= 1)
return GetPrimaryDisplay();
for (const auto& display : display_list_.displays()) {
if (display.bounds().Contains(point))
return display;
}

return *FindDisplayNearestPoint(display_list_.displays(), point);
}

display::Display WaylandScreen::GetDisplayMatching(
const gfx::Rect& match_rect) const {
// TODO(msisov): https://crbug.com/890272
NOTIMPLEMENTED_LOG_ONCE();
return GetPrimaryDisplay();
if (match_rect.IsEmpty())
return GetDisplayNearestPoint(match_rect.origin());

const display::Display* match =
FindDisplayWithBiggestIntersection(display_list_.displays(), match_rect);
return match ? *match : GetPrimaryDisplay();
}

void WaylandScreen::AddObserver(display::DisplayObserver* observer) {
Expand Down
7 changes: 6 additions & 1 deletion ui/ozone/platform/wayland/wayland_screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

namespace ui {

class WaylandConnection;

// A PlatformScreen implementation for Wayland.
class WaylandScreen : public PlatformScreen {
public:
WaylandScreen();
explicit WaylandScreen(WaylandConnection* connection);
~WaylandScreen() override;

void OnOutputAdded(uint32_t output_id, bool is_primary);
Expand Down Expand Up @@ -52,6 +54,9 @@ class WaylandScreen : public PlatformScreen {

base::ObserverList<display::DisplayObserver> observers_;

// Non-owned pointer.
WaylandConnection* connection_ = nullptr;

base::WeakPtrFactory<WaylandScreen> weak_factory_;

DISALLOW_COPY_AND_ASSIGN(WaylandScreen);
Expand Down
Loading

0 comments on commit 005f532

Please sign in to comment.