// Copyright 2018 The ChromiumOS Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "sommelier.h" // NOLINT(build/include_directory) #include "sommelier-transform.h" // NOLINT(build/include_directory) #include #include #include "xdg-shell-client-protocol.h" // NOLINT(build/include_directory) #include "xdg-shell-server-protocol.h" // NOLINT(build/include_directory) struct sl_host_xdg_shell { struct sl_context* ctx; struct wl_resource* resource; struct xdg_wm_base* proxy; }; MAP_STRUCTS(xdg_wm_base, sl_host_xdg_shell); struct sl_host_xdg_surface { struct sl_context* ctx; struct wl_resource* resource; struct xdg_surface* proxy; struct sl_host_surface* originator; }; MAP_STRUCTS(xdg_surface, sl_host_xdg_surface); struct sl_host_xdg_toplevel { struct sl_context* ctx; struct wl_resource* resource; struct xdg_toplevel* proxy; struct sl_host_xdg_surface* originator; }; MAP_STRUCTS(xdg_toplevel, sl_host_xdg_toplevel); struct sl_host_xdg_popup { struct sl_context* ctx; struct wl_resource* resource; struct xdg_popup* proxy; struct sl_host_xdg_surface* originator; }; MAP_STRUCTS(xdg_popup, sl_host_xdg_popup); struct sl_host_xdg_positioner { struct sl_context* ctx; struct wl_resource* resource; struct xdg_positioner* proxy; }; MAP_STRUCTS(xdg_positioner, sl_host_xdg_positioner); static void sl_xdg_positioner_destroy(struct wl_client* client, struct wl_resource* resource) { wl_resource_destroy(resource); } static void sl_xdg_positioner_set_size(struct wl_client* client, struct wl_resource* resource, int32_t width, int32_t height) { struct sl_host_xdg_positioner* host = static_cast(wl_resource_get_user_data(resource)); int32_t iwidth = width; int32_t iheight = height; sl_transform_guest_to_host(host->ctx, nullptr, &iwidth, &iheight); xdg_positioner_set_size(host->proxy, iwidth, iheight); } static void sl_xdg_positioner_set_anchor_rect(struct wl_client* client, struct wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) { struct sl_host_xdg_positioner* host = static_cast(wl_resource_get_user_data(resource)); int32_t x1 = x; int32_t y1 = y; int32_t x2 = x + width; int32_t y2 = y + height; sl_transform_guest_to_host(host->ctx, nullptr, &x1, &y1); sl_transform_guest_to_host(host->ctx, nullptr, &x2, &y2); xdg_positioner_set_anchor_rect(host->proxy, x1, y1, x2 - x1, y2 - y1); } static void sl_xdg_positioner_set_offset(struct wl_client* client, struct wl_resource* resource, int32_t x, int32_t y) { struct sl_host_xdg_positioner* host = static_cast(wl_resource_get_user_data(resource)); int32_t ix = x, iy = y; sl_transform_guest_to_host(host->ctx, nullptr, &ix, &iy); xdg_positioner_set_offset(host->proxy, ix, iy); } static const struct xdg_positioner_interface sl_xdg_positioner_implementation = {sl_xdg_positioner_destroy, sl_xdg_positioner_set_size, sl_xdg_positioner_set_anchor_rect, ForwardRequest, ForwardRequest, ForwardRequest, sl_xdg_positioner_set_offset}; static void sl_destroy_host_xdg_positioner(struct wl_resource* resource) { struct sl_host_xdg_positioner* host = static_cast(wl_resource_get_user_data(resource)); xdg_positioner_destroy(host->proxy); wl_resource_set_user_data(resource, NULL); delete host; } static void sl_xdg_popup_destroy(struct wl_client* client, struct wl_resource* resource) { wl_resource_destroy(resource); } static const struct xdg_popup_interface sl_xdg_popup_implementation = { sl_xdg_popup_destroy, ForwardRequest}; static struct sl_host_surface* get_host_surface( struct sl_host_xdg_surface* xdg) { // For xdg_popup/xdg_toplevel they will point to the // originating xdg_surface. The originating surface // will point to the source sl_host_surface if (xdg && xdg->originator) return xdg->originator; else return nullptr; } static void sl_xdg_popup_configure(void* data, struct xdg_popup* xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height) { struct sl_host_xdg_popup* host = static_cast(xdg_popup_get_user_data(xdg_popup)); int32_t x1 = x; int32_t y1 = y; int32_t x2 = x + width; int32_t y2 = y + height; sl_transform_host_to_guest(host->ctx, get_host_surface(host->originator), &x1, &y1); sl_transform_host_to_guest(host->ctx, get_host_surface(host->originator), &x2, &y2); xdg_popup_send_configure(host->resource, x1, y1, x2 - x1, y2 - y1); } static void sl_xdg_popup_popup_done(void* data, struct xdg_popup* xdg_popup) { struct sl_host_xdg_popup* host = static_cast(xdg_popup_get_user_data(xdg_popup)); xdg_popup_send_popup_done(host->resource); } static const struct xdg_popup_listener sl_xdg_popup_listener = { sl_xdg_popup_configure, sl_xdg_popup_popup_done}; static void sl_destroy_host_xdg_popup(struct wl_resource* resource) { struct sl_host_xdg_popup* host = static_cast(wl_resource_get_user_data(resource)); xdg_popup_destroy(host->proxy); wl_resource_set_user_data(resource, NULL); delete host; } static void sl_xdg_toplevel_destroy(struct wl_client* client, struct wl_resource* resource) { wl_resource_destroy(resource); } static void sl_xdg_toplevel_show_window_menu(struct wl_client* client, struct wl_resource* resource, struct wl_resource* seat_resource, uint32_t serial, int32_t x, int32_t y) { struct sl_host_xdg_toplevel* host = static_cast(wl_resource_get_user_data(resource)); struct sl_host_seat* host_seat = seat_resource ? static_cast(wl_resource_get_user_data(seat_resource)) : NULL; // TODO(mrisaacb): There was no scaling performed here in the original code. // Figure out why this was. xdg_toplevel_show_window_menu( host->proxy, host_seat ? host_seat->proxy : NULL, serial, x, y); } // NOLINT(whitespace/indent) static const struct xdg_toplevel_interface sl_xdg_toplevel_implementation = { sl_xdg_toplevel_destroy, ForwardRequest, ForwardRequest, ForwardRequest, sl_xdg_toplevel_show_window_menu, ForwardRequest, ForwardRequest, ForwardRequest, ForwardRequest, ForwardRequest, ForwardRequest, ForwardRequest, ForwardRequest, ForwardRequest, }; static void sl_xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, int32_t width, int32_t height, struct wl_array* states) { struct sl_host_xdg_toplevel* host = static_cast( xdg_toplevel_get_user_data(xdg_toplevel)); int32_t iwidth = width; int32_t iheight = height; sl_transform_host_to_guest(host->ctx, get_host_surface(host->originator), &iwidth, &iheight); xdg_toplevel_send_configure(host->resource, iwidth, iheight, states); } static void sl_xdg_toplevel_close(void* data, struct xdg_toplevel* xdg_toplevel) { struct sl_host_xdg_toplevel* host = static_cast( xdg_toplevel_get_user_data(xdg_toplevel)); xdg_toplevel_send_close(host->resource); } static const struct xdg_toplevel_listener sl_xdg_toplevel_listener = { sl_xdg_toplevel_configure, sl_xdg_toplevel_close}; static void sl_destroy_host_xdg_toplevel(struct wl_resource* resource) { struct sl_host_xdg_toplevel* host = static_cast(wl_resource_get_user_data(resource)); xdg_toplevel_destroy(host->proxy); wl_resource_set_user_data(resource, NULL); delete host; } static void sl_xdg_surface_destroy(struct wl_client* client, struct wl_resource* resource) { wl_resource_destroy(resource); } static void sl_xdg_surface_get_toplevel(struct wl_client* client, struct wl_resource* resource, uint32_t id) { struct sl_host_xdg_surface* host = static_cast(wl_resource_get_user_data(resource)); struct sl_host_xdg_toplevel* host_xdg_toplevel = new sl_host_xdg_toplevel(); host_xdg_toplevel->ctx = host->ctx; host_xdg_toplevel->resource = wl_resource_create(client, &xdg_toplevel_interface, 1, id); wl_resource_set_implementation( host_xdg_toplevel->resource, &sl_xdg_toplevel_implementation, host_xdg_toplevel, sl_destroy_host_xdg_toplevel); host_xdg_toplevel->proxy = xdg_surface_get_toplevel(host->proxy); host_xdg_toplevel->originator = host; xdg_toplevel_add_listener(host_xdg_toplevel->proxy, &sl_xdg_toplevel_listener, host_xdg_toplevel); } static void sl_xdg_surface_get_popup(struct wl_client* client, struct wl_resource* resource, uint32_t id, struct wl_resource* parent_resource, struct wl_resource* positioner_resource) { struct sl_host_xdg_surface* host = static_cast(wl_resource_get_user_data(resource)); struct sl_host_xdg_surface* host_parent = parent_resource ? static_cast( wl_resource_get_user_data(parent_resource)) : NULL; struct sl_host_xdg_positioner* host_positioner = static_cast( wl_resource_get_user_data(positioner_resource)); struct sl_host_xdg_popup* host_xdg_popup = new sl_host_xdg_popup(); host_xdg_popup->ctx = host->ctx; host_xdg_popup->resource = wl_resource_create(client, &xdg_popup_interface, 1, id); wl_resource_set_implementation(host_xdg_popup->resource, &sl_xdg_popup_implementation, host_xdg_popup, sl_destroy_host_xdg_popup); host_xdg_popup->proxy = xdg_surface_get_popup( host->proxy, host_parent ? host_parent->proxy : NULL, host_positioner->proxy); host_xdg_popup->originator = host_parent; xdg_popup_add_listener(host_xdg_popup->proxy, &sl_xdg_popup_listener, host_xdg_popup); } // NOLINT(whitespace/indent) static void sl_xdg_surface_set_window_geometry(struct wl_client* client, struct wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) { struct sl_host_xdg_surface* host = static_cast(wl_resource_get_user_data(resource)); int32_t x1 = x; int32_t y1 = y; int32_t x2 = x + width; int32_t y2 = y + height; sl_transform_guest_to_host(host->ctx, host->originator, &x1, &y1); sl_transform_guest_to_host(host->ctx, host->originator, &x2, &y2); xdg_surface_set_window_geometry(host->proxy, x1, y1, x2 - x1, y2 - y1); } static const struct xdg_surface_interface sl_xdg_surface_implementation = { sl_xdg_surface_destroy, sl_xdg_surface_get_toplevel, sl_xdg_surface_get_popup, sl_xdg_surface_set_window_geometry, ForwardRequest}; static void sl_xdg_surface_configure(void* data, struct xdg_surface* xdg_surface, uint32_t serial) { struct sl_host_xdg_surface* host = static_cast(xdg_surface_get_user_data(xdg_surface)); xdg_surface_send_configure(host->resource, serial); } static const struct xdg_surface_listener sl_xdg_surface_listener = { sl_xdg_surface_configure}; static void sl_destroy_host_xdg_surface(struct wl_resource* resource) { struct sl_host_xdg_surface* host = static_cast(wl_resource_get_user_data(resource)); xdg_surface_destroy(host->proxy); wl_resource_set_user_data(resource, NULL); delete host; } static void sl_xdg_shell_destroy(struct wl_client* client, struct wl_resource* resource) { wl_resource_destroy(resource); } static void sl_xdg_shell_create_positioner(struct wl_client* client, struct wl_resource* resource, uint32_t id) { struct sl_host_xdg_shell* host = static_cast(wl_resource_get_user_data(resource)); struct sl_host_xdg_positioner* host_xdg_positioner = new sl_host_xdg_positioner(); host_xdg_positioner->ctx = host->ctx; host_xdg_positioner->resource = wl_resource_create(client, &xdg_positioner_interface, 1, id); wl_resource_set_implementation( host_xdg_positioner->resource, &sl_xdg_positioner_implementation, host_xdg_positioner, sl_destroy_host_xdg_positioner); host_xdg_positioner->proxy = xdg_wm_base_create_positioner(host->proxy); xdg_positioner_set_user_data(host_xdg_positioner->proxy, host_xdg_positioner); } static void sl_xdg_shell_get_xdg_surface(struct wl_client* client, struct wl_resource* resource, uint32_t id, struct wl_resource* surface_resource) { struct sl_host_xdg_shell* host = static_cast(wl_resource_get_user_data(resource)); struct sl_host_surface* host_surface = static_cast( wl_resource_get_user_data(surface_resource)); struct sl_host_xdg_surface* host_xdg_surface = new sl_host_xdg_surface(); host_xdg_surface->ctx = host->ctx; host_xdg_surface->resource = wl_resource_create(client, &xdg_surface_interface, 1, id); wl_resource_set_implementation(host_xdg_surface->resource, &sl_xdg_surface_implementation, host_xdg_surface, sl_destroy_host_xdg_surface); host_xdg_surface->proxy = xdg_wm_base_get_xdg_surface(host->proxy, host_surface->proxy); host_xdg_surface->originator = host_surface; xdg_surface_add_listener(host_xdg_surface->proxy, &sl_xdg_surface_listener, host_xdg_surface); host_surface->has_role = 1; } static const struct xdg_wm_base_interface sl_xdg_shell_implementation = { sl_xdg_shell_destroy, sl_xdg_shell_create_positioner, sl_xdg_shell_get_xdg_surface, ForwardRequest}; static void sl_xdg_shell_ping(void* data, struct xdg_wm_base* xdg_shell, uint32_t serial) { struct sl_host_xdg_shell* host = static_cast(xdg_wm_base_get_user_data(xdg_shell)); xdg_wm_base_send_ping(host->resource, serial); } static const struct xdg_wm_base_listener sl_xdg_shell_listener = { sl_xdg_shell_ping}; static void sl_destroy_host_xdg_shell(struct wl_resource* resource) { struct sl_host_xdg_shell* host = static_cast(wl_resource_get_user_data(resource)); xdg_wm_base_destroy(host->proxy); wl_resource_set_user_data(resource, NULL); delete host; } static void sl_bind_host_xdg_shell(struct wl_client* client, void* data, uint32_t version, uint32_t id) { struct sl_context* ctx = (struct sl_context*)data; struct sl_host_xdg_shell* host = new sl_host_xdg_shell(); host->ctx = ctx; host->resource = wl_resource_create(client, &xdg_wm_base_interface, 1, id); wl_resource_set_implementation(host->resource, &sl_xdg_shell_implementation, host, sl_destroy_host_xdg_shell); host->proxy = static_cast( wl_registry_bind(wl_display_get_registry(ctx->display), ctx->xdg_shell->id, &xdg_wm_base_interface, 1)); xdg_wm_base_add_listener(host->proxy, &sl_xdg_shell_listener, host); } struct sl_global* sl_xdg_shell_global_create(struct sl_context* ctx) { return sl_global_create(ctx, &xdg_wm_base_interface, 1, ctx, sl_bind_host_xdg_shell); }