| 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,
|
|
|