Chromium Code Reviews| Index: components/exo/wayland/server.cc |
| diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc |
| index 88a81a0edec22c43fe8e89e4386d98aac784f3d8..49c323f8870e977356326d535278b5b7657bacb9 100644 |
| --- a/components/exo/wayland/server.cc |
| +++ b/components/exo/wayland/server.cc |
| @@ -27,6 +27,7 @@ |
| #include <cstdlib> |
| #include <iterator> |
| #include <string> |
| +#include <unordered_set> |
| #include <utility> |
| #include "ash/public/cpp/shell_window_ids.h" |
| @@ -1005,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)); |
| @@ -1530,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) |
| @@ -1667,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) |
| @@ -1976,11 +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(); |
| + GetUserDataAs<ShellSurface>(resource)->AcknowledgeConfigure(serial); |
| } |
| void remote_surface_move(wl_client* client, wl_resource* resource) { |
| - NOTIMPLEMENTED(); |
| + GetUserDataAs<ShellSurface>(resource)->Move(); |
| } |
| const struct zcr_remote_surface_v1_interface remote_surface_implementation = { |
| @@ -2021,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 { |
| @@ -2050,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( |
| @@ -2060,9 +2095,20 @@ class WaylandRemoteShell : public WMHelper::MaximizeModeObserver, |
| } |
| // Overridden from display::DisplayObserver: |
| + void OnDisplayAdded(const display::Display& new_display) override { |
| + if (IsMultiDisplaySupported()) |
| + ScheduleSendDisplayMetrics(0); |
| + } |
| + |
| + void OnDisplayRemoved(const display::Display& old_display) override { |
| + if (IsMultiDisplaySupported()) |
| + ScheduleSendDisplayMetrics(0); |
| + } |
| + |
| 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 display has changed without bounds |
| @@ -2092,6 +2138,10 @@ class WaylandRemoteShell : public WMHelper::MaximizeModeObserver, |
| } |
| private: |
| + bool IsMultiDisplaySupported() const { |
| + return wl_resource_get_version(remote_shell_resource_) >= 3; |
| + } |
| + |
| void ScheduleSendDisplayMetrics(int delay_ms) { |
| needs_send_display_metrics_ = true; |
| base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| @@ -2108,12 +2158,27 @@ class WaylandRemoteShell : public WMHelper::MaximizeModeObserver, |
| const display::Screen* screen = display::Screen::GetScreen(); |
| const display::Display primary_display = screen->GetPrimaryDisplay(); |
| + gfx::Size size = primary_display.size(); |
| + |
| + 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_display.GetWorkAreaInsets(); |
| zcr_remote_shell_v1_send_configuration_changed( |
| - remote_shell_resource_, |
| - primary_display.size().width(), |
| - primary_display.size().height(), |
| + remote_shell_resource_, size.width(), size.height(), |
| OutputTransform(primary_display.rotation()), |
| wl_fixed_from_double(primary_display.device_scale_factor()), |
| work_area_insets.left(), work_area_insets.top(), |
| @@ -2164,6 +2229,11 @@ class WaylandRemoteShell : public WMHelper::MaximizeModeObserver, |
| 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. |
|
reveman
2017/02/17 01:29:34
As discussed. Please refactor ShellSurface so this
|
| + |
| base::WeakPtrFactory<WaylandRemoteShell> weak_ptr_factory_; |
| DISALLOW_COPY_AND_ASSIGN(WaylandRemoteShell); |
| @@ -2221,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, |
| @@ -2245,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)); |
| @@ -2283,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, |