Commit 787ef559 authored by Shawn Gallea's avatar Shawn Gallea Committed by Commit Bot

EXO: Move zaura_shell interface and wl_output out of server.cc

Refactor zaura_shell and wl_output out of server.cc to isolate generic
Wayland API implementations from ChromeOS specific ones. This will allow
ChromeOS specific APIs to be conditionally compiled on builds that don't
need them. This helps port EXO to Chromecast where Ash (ChromeOS' window
manager) isn't present.

Changes:
 * Move zaura_shell into its own file since this won't be compiled on
 Chromecast.
 * Move Output and WaylandDisplayObserver into their own files since
 these are shared between zaura_shell, wl_output and Server.
 * Move wl_output into its own file since all its dependencies have been
 refactored out of server.cc.

Bug: 896710
Test: Run exo_unittests
Change-Id: I51b42301b5b7fcf53b1879373a2b50db6e799dd1
Reviewed-on: https://chromium-review.googlesource.com/c/1328233Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Reviewed-by: default avatarDaniel Nicoara <dnicoara@chromium.org>
Commit-Queue: Daniel Nicoara <dnicoara@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611410}
parent 6405d08c
......@@ -35,6 +35,10 @@ source_set("wayland") {
"server.h",
"server_util.cc",
"server_util.h",
"wayland_display_observer.cc",
"wayland_display_observer.h",
"wayland_display_output.cc",
"wayland_display_output.h",
"wayland_input_delegate.cc",
"wayland_input_delegate.h",
"wayland_keyboard_delegate.cc",
......@@ -43,10 +47,14 @@ source_set("wayland") {
"wayland_pointer_delegate.h",
"wayland_touch_delegate.cc",
"wayland_touch_delegate.h",
"wl_output.cc",
"wl_output.h",
"wl_seat.cc",
"wl_seat.h",
"wl_shell.cc",
"wl_shell.h",
"zaura_shell.cc",
"zaura_shell.h",
"zcr_cursor_shapes.cc",
"zcr_cursor_shapes.h",
"zcr_gaming_input.cc",
......
This diff is collapsed.
......@@ -14,34 +14,17 @@
#include "components/exo/wayland/scoped_wl.h"
#include "ui/display/display_observer.h"
struct wl_global;
namespace exo {
class Display;
namespace wayland {
class WaylandDisplayOutput;
// This class is a thin wrapper around a Wayland display server. All Wayland
// requests are dispatched into the given Exosphere display.
class Server : public display::DisplayObserver {
public:
// Class that represent a wayland output. Tied to a specific display ID
// and associated with a global.
class Output {
public:
explicit Output(int64_t id);
~Output();
int64_t id() const { return id_; }
void set_global(wl_global* global) { global_ = global; }
private:
const int64_t id_;
wl_global* global_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(Output);
};
explicit Server(Display* display);
~Server() override;
......@@ -72,7 +55,7 @@ class Server : public display::DisplayObserver {
private:
Display* const display_;
std::unique_ptr<wl_display, WlDisplayDeleter> wl_display_;
base::flat_map<int64_t, std::unique_ptr<Output>> outputs_;
base::flat_map<int64_t, std::unique_ptr<WaylandDisplayOutput>> outputs_;
DISALLOW_COPY_AND_ASSIGN(Server);
};
......
// Copyright 2018 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/wayland/wayland_display_observer.h"
#include <wayland-server-core.h>
#include "components/exo/wm_helper.h"
#include "ui/display/manager/managed_display_info.h"
#include "ui/display/screen.h"
namespace exo {
namespace wayland {
WaylandDisplayObserver::WaylandDisplayObserver(int64_t id,
wl_resource* output_resource)
: id_(id), output_resource_(output_resource) {
display::Screen::GetScreen()->AddObserver(this);
SendDisplayMetrics();
}
WaylandDisplayObserver::~WaylandDisplayObserver() {
display::Screen::GetScreen()->RemoveObserver(this);
}
void WaylandDisplayObserver::SetScaleObserver(
base::WeakPtr<ScaleObserver> scale_observer) {
scale_observer_ = scale_observer;
SendDisplayMetrics();
}
bool WaylandDisplayObserver::HasScaleObserver() const {
return !!scale_observer_;
}
void WaylandDisplayObserver::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t changed_metrics) {
if (id_ != display.id())
return;
// There is no need to check DISPLAY_METRIC_PRIMARY because when primary
// changes, bounds always changes. (new primary should have had non
// 0,0 origin).
// Only exception is when switching to newly connected primary with
// the same bounds. This happens whenyou're in docked mode, suspend,
// unplug the dislpay, then resume to the internal display which has
// the same resolution. Since metrics does not change, there is no need
// to notify clients.
if (changed_metrics &
(DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
DISPLAY_METRIC_ROTATION)) {
SendDisplayMetrics();
}
}
void WaylandDisplayObserver::SendDisplayMetrics() {
display::Display display;
bool rv =
display::Screen::GetScreen()->GetDisplayWithDisplayId(id_, &display);
DCHECK(rv);
const display::ManagedDisplayInfo& info =
WMHelper::GetInstance()->GetDisplayInfo(display.id());
const float kInchInMm = 25.4f;
const char* kUnknown = "unknown";
const std::string& make = info.manufacturer_id();
const std::string& model = info.product_id();
gfx::Rect bounds = info.bounds_in_native();
wl_output_send_geometry(
output_resource_, bounds.x(), bounds.y(),
static_cast<int>(kInchInMm * bounds.width() / info.device_dpi()),
static_cast<int>(kInchInMm * bounds.height() / info.device_dpi()),
WL_OUTPUT_SUBPIXEL_UNKNOWN, make.empty() ? kUnknown : make.c_str(),
model.empty() ? kUnknown : model.c_str(),
OutputTransform(display.rotation()));
if (wl_resource_get_version(output_resource_) >=
WL_OUTPUT_SCALE_SINCE_VERSION) {
wl_output_send_scale(output_resource_, display.device_scale_factor());
}
// TODO(reveman): Send real list of modes.
wl_output_send_mode(output_resource_,
WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED,
bounds.width(), bounds.height(), static_cast<int>(60000));
if (HasScaleObserver())
scale_observer_->OnDisplayScalesChanged(display);
if (wl_resource_get_version(output_resource_) >=
WL_OUTPUT_DONE_SINCE_VERSION) {
wl_output_send_done(output_resource_);
}
wl_client_flush(wl_resource_get_client(output_resource_));
}
wl_output_transform WaylandDisplayObserver::OutputTransform(
display::Display::Rotation rotation) {
// Note: |rotation| describes the counter clockwise rotation that a
// display's output is currently adjusted for, which is the inverse
// of what we need to return.
switch (rotation) {
case display::Display::ROTATE_0:
return WL_OUTPUT_TRANSFORM_NORMAL;
case display::Display::ROTATE_90:
return WL_OUTPUT_TRANSFORM_270;
case display::Display::ROTATE_180:
return WL_OUTPUT_TRANSFORM_180;
case display::Display::ROTATE_270:
return WL_OUTPUT_TRANSFORM_90;
}
NOTREACHED();
return WL_OUTPUT_TRANSFORM_NORMAL;
}
} // namespace wayland
} // namespace exo
// Copyright 2018 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_WAYLAND_WAYLAND_DISPLAY_OBSERVER_H_
#define COMPONENTS_EXO_WAYLAND_WAYLAND_DISPLAY_OBSERVER_H_
#include <stdint.h>
#include <wayland-server-protocol-core.h>
#include "ui/display/display.h"
#include "ui/display/display_observer.h"
struct wl_resource;
namespace exo {
namespace wayland {
class WaylandDisplayObserver : public display::DisplayObserver {
public:
class ScaleObserver : public base::SupportsWeakPtr<ScaleObserver> {
public:
ScaleObserver() {}
virtual void OnDisplayScalesChanged(const display::Display& display) = 0;
protected:
virtual ~ScaleObserver() {}
};
WaylandDisplayObserver(int64_t id, wl_resource* output_resource);
~WaylandDisplayObserver() override;
void SetScaleObserver(base::WeakPtr<ScaleObserver> scale_observer);
bool HasScaleObserver() const;
// Overridden from display::DisplayObserver:
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override;
private:
void SendDisplayMetrics();
// Returns the transform that a compositor will apply to a surface to
// compensate for the rotation of an output device.
wl_output_transform OutputTransform(display::Display::Rotation rotation);
// The ID of the display being observed.
const int64_t id_;
// The output resource associated with the display.
wl_resource* const output_resource_;
base::WeakPtr<ScaleObserver> scale_observer_;
DISALLOW_COPY_AND_ASSIGN(WaylandDisplayObserver);
};
} // namespace wayland
} // namespace exo
#endif // COMPONENTS_EXO_WAYLAND_WAYLAND_DISPLAY_OBSERVER_H_
// Copyright 2018 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/wayland/wayland_display_output.h"
#include <wayland-server-core.h>
#include <wayland-server-protocol-core.h>
namespace exo {
namespace wayland {
WaylandDisplayOutput::WaylandDisplayOutput(int64_t id) : id_(id) {}
WaylandDisplayOutput::~WaylandDisplayOutput() {
if (global_)
wl_global_destroy(global_);
}
int64_t WaylandDisplayOutput::id() const {
return id_;
}
void WaylandDisplayOutput::set_global(wl_global* global) {
global_ = global;
}
} // namespace wayland
} // namespace exo
// Copyright 2018 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_WAYLAND_WAYLAND_DISPLAY_OUTPUT_H_
#define COMPONENTS_EXO_WAYLAND_WAYLAND_DISPLAY_OUTPUT_H_
#include <stdint.h>
#include "base/macros.h"
struct wl_global;
namespace exo {
namespace wayland {
// Class that represent a wayland output. Tied to a specific display ID
// and associated with a global.
class WaylandDisplayOutput {
public:
explicit WaylandDisplayOutput(int64_t id);
~WaylandDisplayOutput();
int64_t id() const;
void set_global(wl_global* global);
private:
const int64_t id_;
wl_global* global_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(WaylandDisplayOutput);
};
} // namespace wayland
} // namespace exo
#endif // COMPONENTS_EXO_WAYLAND_WAYLAND_DISPLAY_OUTPUT_H_
// Copyright 2018 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/wayland/wl_output.h"
#include <wayland-server-core.h>
#include <wayland-server-protocol-core.h>
#include "components/exo/wayland/server_util.h"
#include "components/exo/wayland/wayland_display_observer.h"
#include "components/exo/wayland/wayland_display_output.h"
#include "components/exo/wm_helper.h"
#include "ui/display/display.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/managed_display_info.h"
#include "ui/display/screen.h"
namespace exo {
namespace wayland {
////////////////////////////////////////////////////////////////////////////////
// wl_output_interface:
void bind_output(wl_client* client, void* data, uint32_t version, uint32_t id) {
WaylandDisplayOutput* output = static_cast<WaylandDisplayOutput*>(data);
wl_resource* resource = wl_resource_create(
client, &wl_output_interface, std::min(version, kWlOutputVersion), id);
SetImplementation(
resource, nullptr,
std::make_unique<WaylandDisplayObserver>(output->id(), resource));
}
} // namespace wayland
} // namespace exo
// Copyright 2018 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_WAYLAND_WL_OUTPUT_H_
#define COMPONENTS_EXO_WAYLAND_WL_OUTPUT_H_
#include <stdint.h>
struct wl_client;
namespace exo {
namespace wayland {
constexpr uint32_t kWlOutputVersion = 2;
void bind_output(wl_client* client, void* data, uint32_t version, uint32_t id);
} // namespace wayland
} // namespace exo
#endif // COMPONENTS_EXO_WAYLAND_WL_OUTPUT_H_
// Copyright 2018 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/wayland/zaura_shell.h"
#include <aura-shell-server-protocol.h>
#include <wayland-server-core.h>
#include <wayland-server-protocol-core.h>
#include "ash/shell.h"
#include "components/exo/surface_observer.h"
#include "components/exo/wayland/server_util.h"
#include "components/exo/wayland/wayland_display_observer.h"
#include "components/exo/wayland/wl_output.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/display_util.h"
namespace exo {
namespace wayland {
namespace {
// A property key containing a boolean set to true if na aura surface object is
// associated with surface object.
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSurfaceHasAuraSurfaceKey, false);
////////////////////////////////////////////////////////////////////////////////
// aura_surface_interface:
class AuraSurface : public SurfaceObserver {
public:
explicit AuraSurface(Surface* surface) : surface_(surface) {
surface_->AddSurfaceObserver(this);
surface_->SetProperty(kSurfaceHasAuraSurfaceKey, true);
}
~AuraSurface() override {
if (surface_) {
surface_->RemoveSurfaceObserver(this);
surface_->SetProperty(kSurfaceHasAuraSurfaceKey, false);
}
}
void SetFrame(SurfaceFrameType type) {
if (surface_)
surface_->SetFrame(type);
}
void SetFrameColors(SkColor active_frame_color,
SkColor inactive_frame_color) {
if (surface_)
surface_->SetFrameColors(active_frame_color, inactive_frame_color);
}
void SetParent(AuraSurface* parent, const gfx::Point& position) {
if (surface_)
surface_->SetParent(parent ? parent->surface_ : nullptr, position);
}
void SetStartupId(const char* startup_id) {
if (surface_)
surface_->SetStartupId(startup_id);
}
void SetApplicationId(const char* application_id) {
if (surface_)
surface_->SetApplicationId(application_id);
}
// Overridden from SurfaceObserver:
void OnSurfaceDestroying(Surface* surface) override {
surface->RemoveSurfaceObserver(this);
surface_ = nullptr;
}
private:
Surface* surface_;
DISALLOW_COPY_AND_ASSIGN(AuraSurface);
};
SurfaceFrameType AuraSurfaceFrameType(uint32_t frame_type) {
switch (frame_type) {
case ZAURA_SURFACE_FRAME_TYPE_NONE:
return SurfaceFrameType::NONE;
case ZAURA_SURFACE_FRAME_TYPE_NORMAL:
return SurfaceFrameType::NORMAL;
case ZAURA_SURFACE_FRAME_TYPE_SHADOW:
return SurfaceFrameType::SHADOW;
default:
VLOG(2) << "Unkonwn aura-shell frame type: " << frame_type;
return SurfaceFrameType::NONE;
}
}
void aura_surface_set_frame(wl_client* client,
wl_resource* resource,
uint32_t type) {
GetUserDataAs<AuraSurface>(resource)->SetFrame(AuraSurfaceFrameType(type));
}
void aura_surface_set_parent(wl_client* client,
wl_resource* resource,
wl_resource* parent_resource,
int32_t x,
int32_t y) {
GetUserDataAs<AuraSurface>(resource)->SetParent(
parent_resource ? GetUserDataAs<AuraSurface>(parent_resource) : nullptr,
gfx::Point(x, y));
}
void aura_surface_set_frame_colors(wl_client* client,
wl_resource* resource,
uint32_t active_color,
uint32_t inactive_color) {
GetUserDataAs<AuraSurface>(resource)->SetFrameColors(active_color,
inactive_color);
}
void aura_surface_set_startup_id(wl_client* client,
wl_resource* resource,
const char* startup_id) {
GetUserDataAs<AuraSurface>(resource)->SetStartupId(startup_id);
}
void aura_surface_set_application_id(wl_client* client,
wl_resource* resource,
const char* application_id) {
GetUserDataAs<AuraSurface>(resource)->SetApplicationId(application_id);
}
const struct zaura_surface_interface aura_surface_implementation = {
aura_surface_set_frame, aura_surface_set_parent,
aura_surface_set_frame_colors, aura_surface_set_startup_id,
aura_surface_set_application_id};
////////////////////////////////////////////////////////////////////////////////
// aura_output_interface:
class AuraOutput : public WaylandDisplayObserver::ScaleObserver {
public:
explicit AuraOutput(wl_resource* resource) : resource_(resource) {}
// Overridden from WaylandDisplayObserver::ScaleObserver:
void OnDisplayScalesChanged(const display::Display& display) override {
display::DisplayManager* display_manager =
ash::Shell::Get()->display_manager();
const display::ManagedDisplayInfo& display_info =
display_manager->GetDisplayInfo(display.id());
if (wl_resource_get_version(resource_) >=
ZAURA_OUTPUT_SCALE_SINCE_VERSION) {
display::ManagedDisplayMode active_mode;
bool rv = display_manager->GetActiveModeForDisplayId(display.id(),
&active_mode);
DCHECK(rv);
const int32_t current_output_scale =
std::round(display_info.zoom_factor() * 1000.f);
std::vector<float> zoom_factors =
display::GetDisplayZoomFactors(active_mode);
// Ensure that the current zoom factor is a part of the list.
auto it = std::find_if(
zoom_factors.begin(), zoom_factors.end(),
[&display_info](float zoom_factor) -> bool {
return std::abs(display_info.zoom_factor() - zoom_factor) <=
std::numeric_limits<float>::epsilon();
});
if (it == zoom_factors.end())
zoom_factors.push_back(display_info.zoom_factor());
for (float zoom_factor : zoom_factors) {
int32_t output_scale = std::round(zoom_factor * 1000.f);
uint32_t flags = 0;
if (output_scale == 1000)
flags |= ZAURA_OUTPUT_SCALE_PROPERTY_PREFERRED;
if (current_output_scale == output_scale)
flags |= ZAURA_OUTPUT_SCALE_PROPERTY_CURRENT;
// TODO(malaykeshav): This can be removed in the future when client
// has been updated.
if (wl_resource_get_version(resource_) < 6)
output_scale = std::round(1000.f / zoom_factor);
zaura_output_send_scale(resource_, flags, output_scale);
}
}
if (wl_resource_get_version(resource_) >=
ZAURA_OUTPUT_CONNECTION_SINCE_VERSION) {
zaura_output_send_connection(resource_,
display.IsInternal()
? ZAURA_OUTPUT_CONNECTION_TYPE_INTERNAL
: ZAURA_OUTPUT_CONNECTION_TYPE_UNKNOWN);
}
if (wl_resource_get_version(resource_) >=
ZAURA_OUTPUT_DEVICE_SCALE_FACTOR_SINCE_VERSION) {
zaura_output_send_device_scale_factor(
resource_, display_info.device_scale_factor() * 1000);
}
}
private:
wl_resource* const resource_;
DISALLOW_COPY_AND_ASSIGN(AuraOutput);
};
////////////////////////////////////////////////////////////////////////////////
// aura_shell_interface:
void aura_shell_get_aura_surface(wl_client* client,
wl_resource* resource,
uint32_t id,
wl_resource* surface_resource) {
Surface* surface = GetUserDataAs<Surface>(surface_resource);
if (surface->GetProperty(kSurfaceHasAuraSurfaceKey)) {
wl_resource_post_error(
resource, ZAURA_SHELL_ERROR_AURA_SURFACE_EXISTS,
"an aura surface object for that surface already exists");
return;
}
wl_resource* aura_surface_resource = wl_resource_create(
client, &zaura_surface_interface, wl_resource_get_version(resource), id);
SetImplementation(aura_surface_resource, &aura_surface_implementation,
std::make_unique<AuraSurface>(surface));
}
void aura_shell_get_aura_output(wl_client* client,
wl_resource* resource,
uint32_t id,
wl_resource* output_resource) {
WaylandDisplayObserver* display_observer =
GetUserDataAs<WaylandDisplayObserver>(output_resource);
if (display_observer->HasScaleObserver()) {
wl_resource_post_error(
resource, ZAURA_SHELL_ERROR_AURA_OUTPUT_EXISTS,
"an aura output object for that output already exists");
return;
}
wl_resource* aura_output_resource = wl_resource_create(
client, &zaura_output_interface, wl_resource_get_version(resource), id);
auto aura_output = std::make_unique<AuraOutput>(aura_output_resource);
display_observer->SetScaleObserver(aura_output->AsWeakPtr());
SetImplementation(aura_output_resource, nullptr, std::move(aura_output));
}
const struct zaura_shell_interface aura_shell_implementation = {
aura_shell_get_aura_surface, aura_shell_get_aura_output};
} // namespace
void bind_aura_shell(wl_client* client,
void* data,
uint32_t version,
uint32_t id) {
wl_resource* resource =
wl_resource_create(client, &zaura_shell_interface,
std::min(version, kZAuraShellVersion), id);
wl_resource_set_implementation(resource, &aura_shell_implementation, nullptr,
nullptr);
}
} // namespace wayland
} // namespace exo
// Copyright 2018 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_WAYLAND_ZAURA_SHELL_H_
#define COMPONENTS_EXO_WAYLAND_ZAURA_SHELL_H_
#include <stdint.h>
struct wl_client;
namespace exo {
namespace wayland {
constexpr uint32_t kZAuraShellVersion = 6;
void bind_aura_shell(wl_client* client,
void* data,
uint32_t version,
uint32_t id);
} // namespace wayland
} // namespace exo
#endif // COMPONENTS_EXO_WAYLAND_ZCR_CURSOR_SHAPES_H_
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