Commit de089763 authored by David Reveman's avatar David Reveman Committed by Commit Bot

exo: Add suppot for multiple wl_outputs.

This makes the wayland server instance keep track of when
displays are added and removed. wl_output globals are created
and destroyed in order to match the current display
configuration.

Bug: 824449
Change-Id: I99a3642cda2b1e3c868988738c531172d2db83ed
Reviewed-on: https://chromium-review.googlesource.com/979614
Commit-Queue: David Reveman <reveman@chromium.org>
Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Cr-Commit-Position: refs/heads/master@{#545832}
parent da839bb4
......@@ -93,7 +93,6 @@
#include "ui/base/hit_test.h"
#include "ui/base/ui_features.h"
#include "ui/compositor/compositor_vsync_manager.h"
#include "ui/display/display_observer.h"
#include "ui/display/manager/managed_display_info.h"
#include "ui/display/screen.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
......@@ -1234,7 +1233,7 @@ wl_output_transform OutputTransform(display::Display::Rotation rotation) {
return WL_OUTPUT_TRANSFORM_NORMAL;
}
class WaylandPrimaryDisplayObserver : public display::DisplayObserver {
class WaylandDisplayObserver : public display::DisplayObserver {
public:
class ScaleObserver : public base::SupportsWeakPtr<ScaleObserver> {
public:
......@@ -1246,12 +1245,12 @@ class WaylandPrimaryDisplayObserver : public display::DisplayObserver {
virtual ~ScaleObserver() {}
};
explicit WaylandPrimaryDisplayObserver(wl_resource* output_resource)
: output_resource_(output_resource) {
WaylandDisplayObserver(int64_t id, wl_resource* output_resource)
: id_(id), output_resource_(output_resource) {
display::Screen::GetScreen()->AddObserver(this);
SendDisplayMetrics();
}
~WaylandPrimaryDisplayObserver() override {
~WaylandDisplayObserver() override {
display::Screen::GetScreen()->RemoveObserver(this);
}
......@@ -1265,7 +1264,7 @@ class WaylandPrimaryDisplayObserver : public display::DisplayObserver {
// Overridden from display::DisplayObserver:
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override {
if (display::Screen::GetScreen()->GetPrimaryDisplay().id() != display.id())
if (id_ != display.id())
return;
// There is no need to check DISPLAY_METRIC_PRIMARY because when primary
......@@ -1285,22 +1284,27 @@ class WaylandPrimaryDisplayObserver : public display::DisplayObserver {
private:
void SendDisplayMetrics() {
display::Display display =
display::Screen::GetScreen()->GetPrimaryDisplay();
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* kUnknownMake = "unknown";
const char* kUnknownModel = "unknown";
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, kUnknownMake, kUnknownModel,
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_) >=
......@@ -1322,22 +1326,28 @@ class WaylandPrimaryDisplayObserver : public display::DisplayObserver {
}
}
// 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(WaylandPrimaryDisplayObserver);
DISALLOW_COPY_AND_ASSIGN(WaylandDisplayObserver);
};
const uint32_t output_version = 2;
void bind_output(wl_client* client, void* data, uint32_t version, uint32_t id) {
Server::Output* output = static_cast<Server::Output*>(data);
wl_resource* resource = wl_resource_create(
client, &wl_output_interface, std::min(version, output_version), id);
SetImplementation(resource, nullptr,
std::make_unique<WaylandPrimaryDisplayObserver>(resource));
SetImplementation(
resource, nullptr,
std::make_unique<WaylandDisplayObserver>(output->id(), resource));
}
////////////////////////////////////////////////////////////////////////////////
......@@ -2308,7 +2318,7 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override {
// No need to update when a primary display has changed without bounds
// change. See WaylandPrimaryDisplayObserver::OnDisplayMetricsChanged
// change. See WaylandDisplayObserver::OnDisplayMetricsChanged
// for more details.
if (changed_metrics &
(DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
......@@ -2754,11 +2764,11 @@ const struct zaura_surface_interface aura_surface_implementation = {
////////////////////////////////////////////////////////////////////////////////
// aura_output_interface:
class AuraOutput : public WaylandPrimaryDisplayObserver::ScaleObserver {
class AuraOutput : public WaylandDisplayObserver::ScaleObserver {
public:
explicit AuraOutput(wl_resource* resource) : resource_(resource) {}
// Overridden from WaylandPrimaryDisplayObserver::ScaleObserver:
// Overridden from WaylandDisplayObserver::ScaleObserver:
void OnDisplayScalesChanged(const display::Display& display) override {
display::DisplayManager* display_manager =
ash::Shell::Get()->display_manager();
......@@ -2819,8 +2829,8 @@ void aura_shell_get_aura_output(wl_client* client,
wl_resource* resource,
uint32_t id,
wl_resource* output_resource) {
WaylandPrimaryDisplayObserver* display_observer =
GetUserDataAs<WaylandPrimaryDisplayObserver>(output_resource);
WaylandDisplayObserver* display_observer =
GetUserDataAs<WaylandDisplayObserver>(output_resource);
if (display_observer->HasScaleObserver()) {
wl_resource_post_error(
resource, ZAURA_SHELL_ERROR_AURA_OUTPUT_EXISTS,
......@@ -4829,6 +4839,16 @@ void bind_input_timestamps_manager(wl_client* client,
} // namespace
////////////////////////////////////////////////////////////////////////////////
// Server::Output, public:
Server::Output::Output(int64_t id) : id_(id) {}
Server::Output::~Output() {
if (global_)
wl_global_destroy(global_);
}
////////////////////////////////////////////////////////////////////////////////
// Server, public:
......@@ -4845,8 +4865,9 @@ Server::Server(Display* display)
bind_subcompositor);
wl_global_create(wl_display_.get(), &wl_shell_interface, 1, display_,
bind_shell);
wl_global_create(wl_display_.get(), &wl_output_interface, output_version,
display_, bind_output);
display::Screen::GetScreen()->AddObserver(this);
for (const auto& display : display::Screen::GetScreen()->GetAllDisplays())
OnDisplayAdded(display);
wl_global_create(wl_display_.get(), &zxdg_shell_v6_interface, 1, display_,
bind_xdg_shell_v6);
wl_global_create(wl_display_.get(), &zcr_vsync_feedback_v1_interface, 1,
......@@ -4886,7 +4907,9 @@ Server::Server(Display* display)
bind_input_timestamps_manager);
}
Server::~Server() {}
Server::~Server() {
display::Screen::GetScreen()->RemoveObserver(this);
}
// static
std::unique_ptr<Server> Server::Create(Display* display) {
......@@ -4960,5 +4983,19 @@ void Server::Flush() {
wl_display_flush_clients(wl_display_.get());
}
void Server::OnDisplayAdded(const display::Display& new_display) {
auto output = std::make_unique<Output>(new_display.id());
output->set_global(wl_global_create(wl_display_.get(), &wl_output_interface,
output_version, output.get(),
bind_output));
DCHECK_EQ(outputs_.count(new_display.id()), 0u);
outputs_.insert(std::make_pair(new_display.id(), std::move(output)));
}
void Server::OnDisplayRemoved(const display::Display& old_display) {
DCHECK_EQ(outputs_.count(old_display.id()), 1u);
outputs_.erase(old_display.id());
}
} // namespace wayland
} // namespace exo
......@@ -8,9 +8,13 @@
#include <memory>
#include <string>
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "components/exo/wayland/scoped_wl.h"
#include "ui/display/display_observer.h"
struct wl_global;
namespace exo {
class Display;
......@@ -19,10 +23,27 @@ namespace wayland {
// This class is a thin wrapper around a Wayland display server. All Wayland
// requests are dispatched into the given Exosphere display.
class Server {
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();
~Server() override;
// Creates a Wayland display server that clients can connect to using the
// default socket name.
......@@ -44,9 +65,14 @@ class Server {
// Send all buffered events to the clients.
void Flush();
// Overridden from display::DisplayObserver:
void OnDisplayAdded(const display::Display& new_display) override;
void OnDisplayRemoved(const display::Display& old_display) override;
private:
Display* const display_;
std::unique_ptr<wl_display, WlDisplayDeleter> wl_display_;
base::flat_map<int64_t, std::unique_ptr<Output>> outputs_;
DISALLOW_COPY_AND_ASSIGN(Server);
};
......
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