Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(360)

Unified Diff: components/exo/wayland/server.cc

Issue 2645663004: exo: Initial support for multiple displays in ARC (Closed)
Patch Set: Fix bad merge in test Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« components/exo/shell_surface.h ('K') | « components/exo/test/exo_test_helper.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/exo/wayland/server.cc
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 1cb7b44091b8f6860f21e207cc2f9e0187103c83..b5a0adfad822226d9224f4bf4cfcbd50b5eb9a6f 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -27,9 +27,9 @@
#include <cstdlib>
#include <iterator>
#include <string>
+#include <unordered_set>
#include <utility>
-#include "ash/common/shell_observer.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "base/bind.h"
@@ -1006,7 +1006,8 @@ uint32_t HandleShellSurfaceConfigureCallback(
const gfx::Size& size,
ash::wm::WindowStateType state_type,
bool resizing,
- bool activated) {
+ bool activated,
+ const gfx::Point& origin) {
wl_shell_surface_send_configure(resource, WL_SHELL_SURFACE_RESIZE_NONE,
size.width(), size.height());
wl_client_flush(wl_resource_get_client(resource));
@@ -1089,8 +1090,6 @@ class WaylandPrimaryDisplayObserver : public display::DisplayObserver {
}
// Overridden from display::DisplayObserver:
- void OnDisplayAdded(const display::Display& new_display) override {}
- void OnDisplayRemoved(const display::Display& new_display) override {}
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override {
if (display::Screen::GetScreen()->GetPrimaryDisplay().id() != display.id())
@@ -1533,7 +1532,8 @@ uint32_t HandleXdgToplevelV6ConfigureCallback(
const gfx::Size& size,
ash::wm::WindowStateType state_type,
bool resizing,
- bool activated) {
+ bool activated,
+ const gfx::Point& origin) {
wl_array states;
wl_array_init(&states);
if (state_type == ash::wm::WINDOW_STATE_TYPE_MAXIMIZED)
@@ -1670,7 +1670,8 @@ uint32_t HandleXdgSurfaceV5ConfigureCallback(
const gfx::Size& size,
ash::wm::WindowStateType state_type,
bool resizing,
- bool activated) {
+ bool activated,
+ const gfx::Point& origin) {
wl_array states;
wl_array_init(&states);
if (state_type == ash::wm::WINDOW_STATE_TYPE_MAXIMIZED)
@@ -1979,15 +1980,11 @@ void remote_surface_set_rectangular_surface_shadow(wl_client* client,
void remote_surface_ack_configure(wl_client* client,
wl_resource* resource,
uint32_t serial) {
- NOTIMPLEMENTED();
-}
-
-void remote_surface_set_moving(wl_client* client, wl_resource* resource) {
- NOTIMPLEMENTED();
+ GetUserDataAs<ShellSurface>(resource)->AcknowledgeConfigure(serial);
}
-void remote_surface_unset_moving(wl_client* client, wl_resource* resource) {
- NOTIMPLEMENTED();
+void remote_surface_move(wl_client* client, wl_resource* resource) {
+ GetUserDataAs<ShellSurface>(resource)->Move();
}
const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
@@ -2011,8 +2008,7 @@ const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
remote_surface_unset_system_modal,
remote_surface_set_rectangular_surface_shadow,
remote_surface_ack_configure,
- remote_surface_set_moving,
- remote_surface_unset_moving};
+ remote_surface_move};
////////////////////////////////////////////////////////////////////////////////
// notification_surface_interface:
@@ -2029,6 +2025,25 @@ const struct zcr_notification_surface_v1_interface
// Implements remote shell interface and monitors workspace state needed
// for the remote shell interface.
+//
+// This class is also responsible for conversion between server-side screen
+// coordinates and client-side virtual coordinates. This mapping enables
+// support for multiple displays when the client is limited to a single
+// display. In that case, the client uses a virtual display computed as
+// the bounding box of the physical displays, and the server translates
+// positions based on the display layout. For example, P is the client's
+// origin in virtual coordinates, and Q is the server's origin in screen
+// coordinates.
+//
+// P Q
+// +-----+ /
+// | |/
+// | 2 +-----------+
+// | | |
+// +-----+ 1 |
+// | |
+// +-----------+
+//
class WaylandRemoteShell : public WMHelper::MaximizeModeObserver,
public WMHelper::ActivationObserver,
public display::DisplayObserver {
@@ -2046,7 +2061,7 @@ class WaylandRemoteShell : public WMHelper::MaximizeModeObserver,
? ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET
: ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED;
- SendPrimaryDisplayMetrics();
+ SendDisplayMetrics();
SendActivated(helper->GetActiveWindow(), nullptr);
}
~WaylandRemoteShell() override {
@@ -2058,7 +2073,19 @@ class WaylandRemoteShell : public WMHelper::MaximizeModeObserver,
std::unique_ptr<ShellSurface> CreateShellSurface(Surface* surface,
int container) {
- return display_->CreateRemoteShellSurface(surface, container);
+ std::unique_ptr<ShellSurface> shell_surface =
+ display_->CreateRemoteShellSurface(surface, virtual_origin_, container);
+
+ shell_surfaces_.insert(shell_surface.get());
+ shell_surface->set_destroyed_callback(
+ base::Bind(&WaylandRemoteShell::OnShellSurfaceDestroyed,
+ weak_ptr_factory_.GetWeakPtr(), shell_surface.get()));
+
+ return shell_surface;
+ }
+
+ void OnShellSurfaceDestroyed(ShellSurface* shell_surface) {
+ shell_surfaces_.erase(shell_surface);
}
std::unique_ptr<NotificationSurface> CreateNotificationSurface(
@@ -2068,40 +2095,40 @@ class WaylandRemoteShell : public WMHelper::MaximizeModeObserver,
}
// Overridden from display::DisplayObserver:
- void OnDisplayAdded(const display::Display& new_display) override {}
- void OnDisplayRemoved(const display::Display& new_display) override {}
+ void OnDisplayAdded(const display::Display& new_display) override {
+ if (IsMultiDisplaySupported())
+ ScheduleSendDisplayMetrics();
+ }
+
+ void OnDisplayRemoved(const display::Display& old_display) override {
+ if (IsMultiDisplaySupported())
+ ScheduleSendDisplayMetrics();
+ }
+
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override {
- if (display::Screen::GetScreen()->GetPrimaryDisplay().id() != display.id())
+ if (!IsMultiDisplaySupported() &&
+ display::Screen::GetScreen()->GetPrimaryDisplay().id() != display.id())
return;
- // No need to update when a primary dislpay has changed without bounds
+ // No need to update when a primary display has changed without bounds
// change. See WaylandPrimaryDisplayObserver::OnDisplayMetricsChanged
// for more details.
if (changed_metrics &
(DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
DISPLAY_METRIC_ROTATION | DISPLAY_METRIC_WORK_AREA)) {
- SendDisplayMetrics(display);
+ ScheduleSendDisplayMetrics();
}
}
// Overridden from WMHelper::MaximizeModeObserver:
void OnMaximizeModeStarted() override {
layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET;
-
- send_configure_after_layout_change_ = true;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&WaylandRemoteShell::MaybeSendConfigure,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kConfigureDelayAfterLayoutSwitchMs));
+ ScheduleSendDisplayMetrics(kConfigureDelayAfterLayoutSwitchMs);
}
void OnMaximizeModeEnded() override {
layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED;
- send_configure_after_layout_change_ = true;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&WaylandRemoteShell::MaybeSendConfigure,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kConfigureDelayAfterLayoutSwitchMs));
+ ScheduleSendDisplayMetrics(kConfigureDelayAfterLayoutSwitchMs);
}
// Overridden from WMHelper::ActivationObserver:
@@ -2111,27 +2138,49 @@ class WaylandRemoteShell : public WMHelper::MaximizeModeObserver,
}
private:
- void SendPrimaryDisplayMetrics() {
- const display::Display primary =
- display::Screen::GetScreen()->GetPrimaryDisplay();
-
- SendDisplayMetrics(primary);
+ bool IsMultiDisplaySupported() const {
+ return wl_resource_get_version(remote_shell_resource_) >= 2;
}
- void MaybeSendConfigure() {
- if (send_configure_after_layout_change_)
- SendPrimaryDisplayMetrics();
+ void ScheduleSendDisplayMetrics(int delay_ms = 0) {
+ needs_send_display_metrics_ = true;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&WaylandRemoteShell::SendDisplayMetrics,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(delay_ms));
}
- void SendDisplayMetrics(const display::Display& display) {
- send_configure_after_layout_change_ = false;
+ void SendDisplayMetrics() {
+ if (!needs_send_display_metrics_)
+ return;
+ needs_send_display_metrics_ = false;
+
+ const display::Screen* screen = display::Screen::GetScreen();
+ const display::Display primary = screen->GetPrimaryDisplay();
+
+ gfx::Size size = primary.size();
- const gfx::Insets& work_area_insets = display.GetWorkAreaInsets();
+ if (IsMultiDisplaySupported()) {
+ // Virtual screen is the bounding box of the displays in screen
+ // coordinates.
+ gfx::Rect bounds;
+ for (const auto& display : screen->GetAllDisplays())
+ bounds.Union(display.bounds());
+
+ virtual_origin_ = bounds.origin();
+ size = bounds.size();
+
+ for (ShellSurface* shell_surface : shell_surfaces_)
+ shell_surface->SetOrigin(virtual_origin_);
+ }
+
+ // TODO(domlaskowski): Send insets for each workspace.
+ const gfx::Insets& work_area_insets = primary.GetWorkAreaInsets();
zcr_remote_shell_v1_send_configuration_changed(
- remote_shell_resource_, display.size().width(), display.size().height(),
- OutputTransform(display.rotation()),
- wl_fixed_from_double(display.device_scale_factor()),
+ remote_shell_resource_, size.width(), size.height(),
+ OutputTransform(primary.rotation()),
+ wl_fixed_from_double(primary.device_scale_factor()),
work_area_insets.left(), work_area_insets.top(),
work_area_insets.right(), work_area_insets.bottom(), layout_mode_);
wl_client_flush(wl_resource_get_client(remote_shell_resource_));
@@ -2176,10 +2225,15 @@ class WaylandRemoteShell : public WMHelper::MaximizeModeObserver,
// The remote shell resource associated with observer.
wl_resource* const remote_shell_resource_;
- bool send_configure_after_layout_change_ = false;
+ bool needs_send_display_metrics_ = true;
int layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED;
+ // Origin of the virtual screen relative to the primary display.
+ gfx::Point virtual_origin_;
+
+ std::unordered_set<ShellSurface*> shell_surfaces_; // Unowned.
+
base::WeakPtrFactory<WaylandRemoteShell> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(WaylandRemoteShell);
@@ -2237,6 +2291,24 @@ void HandleRemoteSurfaceStateChangedCallback(
wl_client_flush(wl_resource_get_client(resource));
}
+uint32_t HandleRemoteSurfaceConfigureCallback(
+ wl_resource* resource,
+ const gfx::Size& size,
+ ash::wm::WindowStateType state_type,
+ bool resizing,
+ bool activated,
+ const gfx::Point& origin) {
+ wl_array states;
+ wl_array_init(&states);
+ uint32_t serial = wl_display_next_serial(
+ wl_client_get_display(wl_resource_get_client(resource)));
+ zcr_remote_surface_v1_send_configure(resource, origin.x(), origin.y(),
+ &states, serial);
+ wl_client_flush(wl_resource_get_client(resource));
+ wl_array_release(&states);
+ return serial;
+}
+
void remote_shell_get_remote_surface(wl_client* client,
wl_resource* resource,
uint32_t id,
@@ -2261,6 +2333,9 @@ void remote_shell_get_remote_surface(wl_client* client,
shell_surface->set_state_changed_callback(
base::Bind(&HandleRemoteSurfaceStateChangedCallback,
base::Unretained(remote_surface_resource)));
+ shell_surface->set_configure_callback(
+ base::Bind(&HandleRemoteSurfaceConfigureCallback,
+ base::Unretained(remote_surface_resource)));
SetImplementation(remote_surface_resource, &remote_surface_implementation,
std::move(shell_surface));
@@ -2299,7 +2374,7 @@ const struct zcr_remote_shell_v1_interface remote_shell_implementation = {
remote_shell_destroy, remote_shell_get_remote_surface,
remote_shell_get_notification_surface};
-const uint32_t remote_shell_version = 2;
+const uint32_t remote_shell_version = 3;
void bind_remote_shell(wl_client* client,
void* data,
« components/exo/shell_surface.h ('K') | « components/exo/test/exo_test_helper.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698