Commit 677d9287 authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Commit Bot

exo: Add extensions to WaylandDisplayObserver

We add extensions to WaylandDisplayObserver called
WaylandDisplayObserverExtensions that allow display information to be
sent through other protocols and be followed by a wl_output "done"
event.

WaylandDisplayObserver only reported scale changes to its observers.
Since remote_output needs to know about work area changes as well as
scale changes, we modify WaylandDisplayObserver to report all metrics
changes to its extensions, which can decide if it needs to send any
updates.

BUG=b:165094142
TEST=exo_unittests
TEST=Verify insets are updated in ARC++.

Change-Id: I6577fe15eb5b09527008cf69a26b5eec7a7f1374
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2363481Reviewed-by: default avatarJun Mukai <mukai@chromium.org>
Commit-Queue: Prabir Pradhan <prabirmsp@chromium.org>
Auto-Submit: Prabir Pradhan <prabirmsp@chromium.org>
Cr-Commit-Position: refs/heads/master@{#800229}
parent 34cb7e79
......@@ -16,50 +16,74 @@
namespace exo {
namespace wayland {
WaylandDisplayObserver::WaylandDisplayObserver(WaylandDisplayOutput* output,
wl_resource* output_resource)
WaylandDisplayHandler::WaylandDisplayHandler(WaylandDisplayOutput* output,
wl_resource* output_resource)
: output_(output), output_resource_(output_resource) {
output_->RegisterOutput(output_resource_);
display::Screen::GetScreen()->AddObserver(this);
SendDisplayMetrics();
// Adding itself as an observer will send the initial display metrics.
AddObserver(this);
}
WaylandDisplayObserver::~WaylandDisplayObserver() {
WaylandDisplayHandler::~WaylandDisplayHandler() {
output_->UnregisterOutput(output_resource_);
display::Screen::GetScreen()->RemoveObserver(this);
}
void WaylandDisplayObserver::AddScaleObserver(ScaleObserver* scale_observer) {
scale_observers_.AddObserver(scale_observer);
SendDisplayMetrics();
void WaylandDisplayHandler::AddObserver(WaylandDisplayObserver* observer) {
observers_.AddObserver(observer);
display::Display display;
bool rv = display::Screen::GetScreen()->GetDisplayWithDisplayId(output_->id(),
&display);
DCHECK(rv);
// Send the first round of changes to the observer.
constexpr uint32_t all_changes = 0xFFFFFFFF;
if (observer->SendDisplayMetrics(display, all_changes)) {
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_));
}
}
void WaylandDisplayObserver::OnDisplayMetricsChanged(
void WaylandDisplayHandler::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t changed_metrics) {
if (output_->id() != display.id())
return;
bool needs_done = false;
for (auto& observer : observers_)
needs_done |= observer.SendDisplayMetrics(display, changed_metrics);
if (needs_done) {
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_));
}
}
bool WaylandDisplayHandler::SendDisplayMetrics(const display::Display& display,
uint32_t changed_metrics) {
// 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
// unplug the display, 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();
if (!(changed_metrics &
(DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
DISPLAY_METRIC_ROTATION))) {
return false;
}
}
void WaylandDisplayObserver::SendDisplayMetrics() {
display::Display display;
bool rv = display::Screen::GetScreen()->GetDisplayWithDisplayId(output_->id(),
&display);
DCHECK(rv);
const display::ManagedDisplayInfo& info =
WMHelper::GetInstance()->GetDisplayInfo(display.id());
......@@ -99,18 +123,10 @@ void WaylandDisplayObserver::SendDisplayMetrics() {
WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED,
bounds.width(), bounds.height(), static_cast<int>(60000));
for (auto& observer : scale_observers_)
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_));
return true;
}
wl_output_transform WaylandDisplayObserver::OutputTransform(
wl_output_transform WaylandDisplayHandler::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
......
......@@ -18,30 +18,39 @@ namespace exo {
namespace wayland {
class WaylandDisplayOutput;
class WaylandDisplayObserver : public display::DisplayObserver {
// An observer that allows display information changes to be sent
// via different protocols while being synced with the wl_output's
// "done" event through WaylandDisplayHandler.
class WaylandDisplayObserver : public base::CheckedObserver {
public:
class ScaleObserver : public base::CheckedObserver {
public:
ScaleObserver() {}
WaylandDisplayObserver() {}
virtual void OnDisplayScalesChanged(const display::Display& display) = 0;
// Returns |true| if the observer reported any changes and needs
// to be followed by "done" event, |false| otherwise.
virtual bool SendDisplayMetrics(const display::Display& display,
uint32_t changed_metrics) = 0;
protected:
~ScaleObserver() override {}
};
protected:
~WaylandDisplayObserver() override {}
};
WaylandDisplayObserver(WaylandDisplayOutput* output,
wl_resource* output_resource);
~WaylandDisplayObserver() override;
void AddScaleObserver(ScaleObserver* scale_observer);
bool HasScaleObserver(ScaleObserver* scale_observer) const;
class WaylandDisplayHandler : public display::DisplayObserver,
public WaylandDisplayObserver {
public:
WaylandDisplayHandler(WaylandDisplayOutput* output,
wl_resource* output_resource);
~WaylandDisplayHandler() override;
void AddObserver(WaylandDisplayObserver* observer);
// Overridden from display::DisplayObserver:
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override;
private:
void SendDisplayMetrics();
// Overridden from WaylandDisplayObserver:
bool SendDisplayMetrics(const display::Display& display,
uint32_t changed_metrics) override;
// 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);
......@@ -52,9 +61,9 @@ class WaylandDisplayObserver : public display::DisplayObserver {
// The output resource associated with the display.
wl_resource* const output_resource_;
base::ObserverList<ScaleObserver> scale_observers_;
base::ObserverList<WaylandDisplayObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(WaylandDisplayObserver);
DISALLOW_COPY_AND_ASSIGN(WaylandDisplayHandler);
};
} // namespace wayland
......
......@@ -38,7 +38,7 @@ void bind_output(wl_client* client,
wl_resource_create(client, &wl_output_interface,
std::min(version, kWlOutputVersion), output_id);
SetImplementation(resource, &output_implementation,
std::make_unique<WaylandDisplayObserver>(output, resource));
std::make_unique<WaylandDisplayHandler>(output, resource));
}
} // namespace wayland
......
......@@ -22,6 +22,7 @@
#include "components/exo/wm_helper.h"
#include "ui/aura/env.h"
#include "ui/aura/window_occlusion_tracker.h"
#include "ui/display/display_observer.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/display_util.h"
#include "ui/display/screen.h"
......@@ -373,12 +374,20 @@ namespace {
////////////////////////////////////////////////////////////////////////////////
// aura_output_interface:
class AuraOutput : public WaylandDisplayObserver::ScaleObserver {
class AuraOutput : public WaylandDisplayObserver {
public:
explicit AuraOutput(wl_resource* resource) : resource_(resource) {}
// Overridden from WaylandDisplayObserver::ScaleObserver:
void OnDisplayScalesChanged(const display::Display& display) override {
// Overridden from WaylandDisplayObserver:
bool SendDisplayMetrics(const display::Display& display,
uint32_t changed_metrics) override {
if (!(changed_metrics &
(display::DisplayObserver::DISPLAY_METRIC_BOUNDS |
display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
display::DisplayObserver::DISPLAY_METRIC_ROTATION))) {
return false;
}
const WMHelper* wm_helper = WMHelper::GetInstance();
const display::ManagedDisplayInfo& display_info =
wm_helper->GetDisplayInfo(display.id());
......@@ -434,6 +443,8 @@ class AuraOutput : public WaylandDisplayObserver::ScaleObserver {
zaura_output_send_device_scale_factor(
resource_, display_info.device_scale_factor() * 1000);
}
return true;
}
private:
......@@ -469,14 +480,14 @@ 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);
WaylandDisplayHandler* display_handler =
GetUserDataAs<WaylandDisplayHandler>(output_resource);
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->AddScaleObserver(aura_output.get());
display_handler->AddObserver(aura_output.get());
SetImplementation(aura_output_resource, nullptr, std::move(aura_output));
}
......
......@@ -742,14 +742,21 @@ const struct zcr_remote_output_v1_interface remote_output_implementation = {
remote_output_destroy,
};
class WaylandRemoteOutput : public WaylandDisplayObserver::ScaleObserver {
class WaylandRemoteOutput : public WaylandDisplayObserver {
public:
explicit WaylandRemoteOutput(wl_resource* resource) : resource_(resource) {}
// Overridden from WaylandDisplayObserver::ScaleObserver:
void OnDisplayScalesChanged(const display::Display& display) override {
// Overridden from WaylandDisplayObserver:
bool SendDisplayMetrics(const display::Display& display,
uint32_t changed_metrics) override {
if (wl_resource_get_version(resource_) < 29)
return;
return false;
if (initial_config_sent_ &&
!(changed_metrics &
display::DisplayObserver::DISPLAY_METRIC_WORK_AREA)) {
return false;
}
if (!initial_config_sent_) {
initial_config_sent_ = true;
......@@ -803,6 +810,8 @@ class WaylandRemoteOutput : public WaylandDisplayObserver::ScaleObserver {
: ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE;
zcr_remote_output_v1_send_systemui_visibility(resource_,
systemui_visibility);
return true;
}
private:
......@@ -1470,8 +1479,8 @@ void remote_shell_get_remote_output(wl_client* client,
wl_resource* resource,
uint32_t id,
wl_resource* output_resource) {
WaylandDisplayObserver* display_observer =
GetUserDataAs<WaylandDisplayObserver>(output_resource);
WaylandDisplayHandler* display_handler =
GetUserDataAs<WaylandDisplayHandler>(output_resource);
wl_resource* remote_output_resource =
wl_resource_create(client, &zcr_remote_output_v1_interface,
......@@ -1479,7 +1488,7 @@ void remote_shell_get_remote_output(wl_client* client,
auto remote_output =
std::make_unique<WaylandRemoteOutput>(remote_output_resource);
display_observer->AddScaleObserver(remote_output.get());
display_handler->AddObserver(remote_output.get());
SetImplementation(remote_output_resource, &remote_output_implementation,
std::move(remote_output));
......
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