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

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

Issue 2645663004: exo: Initial support for multiple displays in ARC (Closed)
Patch Set: Fix race and refactor 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.cc ('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 152c72694a5a051e52ba4d28ed73dfc0f02836e2..e75d30b316429aa4403d6a3f02c431b97f9d3e12 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)
@@ -1967,6 +1968,20 @@ void remote_surface_unset_system_modal(wl_client* client,
GetUserDataAs<ShellSurface>(resource)->SetSystemModal(false);
}
+void remote_surface_ack_configure(wl_client* client,
+ wl_resource* resource,
+ uint32_t serial) {
+ GetUserDataAs<ShellSurface>(resource)->AcknowledgeConfigure(serial);
+}
+
+void remote_surface_set_moving(wl_client* client, wl_resource* resource) {
+ GetUserDataAs<ShellSurface>(resource)->SetMoving();
+}
+
+void remote_surface_unset_moving(wl_client* client, wl_resource* resource) {
+ GetUserDataAs<ShellSurface>(resource)->UnsetMoving(false /* revert */);
+}
+
const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
remote_surface_destroy,
remote_surface_set_app_id,
@@ -1985,7 +2000,10 @@ const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
remote_surface_pin,
remote_surface_unpin,
remote_surface_set_system_modal,
- remote_surface_unset_system_modal};
+ remote_surface_unset_system_modal,
+ remote_surface_ack_configure,
+ remote_surface_set_moving,
+ remote_surface_unset_moving};
////////////////////////////////////////////////////////////////////////////////
// notification_surface_interface:
@@ -2002,6 +2020,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 {
@@ -2019,7 +2056,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 {
@@ -2031,7 +2068,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(
@@ -2041,40 +2090,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:
@@ -2084,27 +2133,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_));
@@ -2149,10 +2220,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);
@@ -2210,6 +2286,21 @@ 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) {
+ 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(),
+ serial);
+ wl_client_flush(wl_resource_get_client(resource));
+ return serial;
+}
+
void remote_shell_get_remote_surface(wl_client* client,
wl_resource* resource,
uint32_t id,
@@ -2234,6 +2325,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));
@@ -2272,7 +2366,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 = 1;
+const uint32_t remote_shell_version = 2;
void bind_remote_shell(wl_client* client,
void* data,
« components/exo/shell_surface.cc ('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