| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/exo/wayland/wl_shell.h" |
| |
| #include <wayland-server-core.h> |
| #include <wayland-server-protocol-core.h> |
| |
| #include "ash/public/cpp/shell_window_ids.h" |
| #include "base/bind.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "components/exo/display.h" |
| #include "components/exo/shell_surface.h" |
| #include "components/exo/wayland/server_util.h" |
| |
| namespace exo { |
| namespace wayland { |
| namespace { |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // wl_shell_surface_interface: |
| |
| void shell_surface_pong(wl_client* client, |
| wl_resource* resource, |
| uint32_t serial) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void shell_surface_move(wl_client* client, |
| wl_resource* resource, |
| wl_resource* seat_resource, |
| uint32_t serial) { |
| GetUserDataAs<ShellSurface>(resource)->StartMove(); |
| } |
| |
| void shell_surface_resize(wl_client* client, |
| wl_resource* resource, |
| wl_resource* seat_resource, |
| uint32_t serial, |
| uint32_t edges) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void shell_surface_set_toplevel(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<ShellSurface>(resource)->SetEnabled(true); |
| } |
| |
| void shell_surface_set_transient(wl_client* client, |
| wl_resource* resource, |
| wl_resource* parent_resource, |
| int x, |
| int y, |
| uint32_t flags) { |
| ShellSurface* shell_surface = GetUserDataAs<ShellSurface>(resource); |
| if (shell_surface->GetEnabled()) |
| return; |
| |
| if (flags & WL_SHELL_SURFACE_TRANSIENT_INACTIVE) { |
| shell_surface->SetContainer(ash::kShellWindowId_SystemModalContainer); |
| shell_surface->SetActivatable(false); |
| } |
| |
| shell_surface->SetEnabled(true); |
| } |
| |
| void shell_surface_set_fullscreen(wl_client* client, |
| wl_resource* resource, |
| uint32_t method, |
| uint32_t framerate, |
| wl_resource* output_resource) { |
| ShellSurface* shell_surface = GetUserDataAs<ShellSurface>(resource); |
| if (shell_surface->GetEnabled()) |
| return; |
| |
| shell_surface->SetEnabled(true); |
| shell_surface->SetFullscreen(true); |
| } |
| |
| void shell_surface_set_popup(wl_client* client, |
| wl_resource* resource, |
| wl_resource* seat_resource, |
| uint32_t serial, |
| wl_resource* parent_resource, |
| int32_t x, |
| int32_t y, |
| uint32_t flags) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void shell_surface_set_maximized(wl_client* client, |
| wl_resource* resource, |
| wl_resource* output_resource) { |
| ShellSurface* shell_surface = GetUserDataAs<ShellSurface>(resource); |
| if (shell_surface->GetEnabled()) |
| return; |
| |
| shell_surface->SetEnabled(true); |
| shell_surface->Maximize(); |
| } |
| |
| void shell_surface_set_title(wl_client* client, |
| wl_resource* resource, |
| const char* title) { |
| GetUserDataAs<ShellSurface>(resource)->SetTitle( |
| base::string16(base::UTF8ToUTF16(title))); |
| } |
| |
| void shell_surface_set_class(wl_client* client, |
| wl_resource* resource, |
| const char* clazz) { |
| GetUserDataAs<ShellSurface>(resource)->SetApplicationId(clazz); |
| } |
| |
| const struct wl_shell_surface_interface shell_surface_implementation = { |
| shell_surface_pong, shell_surface_move, |
| shell_surface_resize, shell_surface_set_toplevel, |
| shell_surface_set_transient, shell_surface_set_fullscreen, |
| shell_surface_set_popup, shell_surface_set_maximized, |
| shell_surface_set_title, shell_surface_set_class}; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // wl_shell_interface: |
| |
| uint32_t HandleShellSurfaceConfigureCallback( |
| wl_resource* resource, |
| const gfx::Size& size, |
| ash::WindowStateType state_type, |
| bool resizing, |
| bool activated, |
| const gfx::Vector2d& origin_offset) { |
| wl_shell_surface_send_configure(resource, WL_SHELL_SURFACE_RESIZE_NONE, |
| size.width(), size.height()); |
| wl_client_flush(wl_resource_get_client(resource)); |
| return 0; |
| } |
| |
| void shell_get_shell_surface(wl_client* client, |
| wl_resource* resource, |
| uint32_t id, |
| wl_resource* surface) { |
| std::unique_ptr<ShellSurface> shell_surface = |
| GetUserDataAs<Display>(resource)->CreateShellSurface( |
| GetUserDataAs<Surface>(surface)); |
| if (!shell_surface) { |
| wl_resource_post_error(resource, WL_SHELL_ERROR_ROLE, |
| "surface has already been assigned a role"); |
| return; |
| } |
| |
| wl_resource* shell_surface_resource = |
| wl_resource_create(client, &wl_shell_surface_interface, 1, id); |
| |
| // Shell surfaces are initially disabled and needs to be explicitly mapped |
| // before they are enabled and can become visible. |
| shell_surface->SetEnabled(false); |
| |
| shell_surface->set_configure_callback( |
| base::Bind(&HandleShellSurfaceConfigureCallback, |
| base::Unretained(shell_surface_resource))); |
| |
| shell_surface->set_surface_destroyed_callback(base::BindOnce( |
| &wl_resource_destroy, base::Unretained(shell_surface_resource))); |
| |
| SetImplementation(shell_surface_resource, &shell_surface_implementation, |
| std::move(shell_surface)); |
| } |
| |
| const struct wl_shell_interface shell_implementation = { |
| shell_get_shell_surface}; |
| |
| } // namespace |
| |
| void bind_shell(wl_client* client, void* data, uint32_t version, uint32_t id) { |
| wl_resource* resource = |
| wl_resource_create(client, &wl_shell_interface, 1, id); |
| |
| wl_resource_set_implementation(resource, &shell_implementation, data, |
| nullptr); |
| } |
| |
| } // namespace wayland |
| } // namespace exo |