blob: 96b23170158af5460a8c55ae0d480388f40790e4 [file] [log] [blame]
// Copyright 2017 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 "ui/ozone/platform/wayland/xdg_popup_wrapper_v6.h"
#include <xdg-shell-unstable-v6-client-protocol.h>
#include "ui/gfx/geometry/rect.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_window.h"
#include "ui/ozone/platform/wayland/xdg_surface_wrapper_v6.h"
namespace ui {
XDGPopupWrapperV6::XDGPopupWrapperV6(std::unique_ptr<XDGSurfaceWrapper> surface,
WaylandWindow* wayland_window)
: wayland_window_(wayland_window), zxdg_surface_v6_(std::move(surface)) {
DCHECK(zxdg_surface_v6_);
}
XDGPopupWrapperV6::~XDGPopupWrapperV6() {}
bool XDGPopupWrapperV6::Initialize(WaylandConnection* connection,
wl_surface* surface,
WaylandWindow* parent_window,
const gfx::Rect& bounds) {
DCHECK(connection && surface && parent_window);
static const struct zxdg_popup_v6_listener zxdg_popup_v6_listener = {
&XDGPopupWrapperV6::Configure, &XDGPopupWrapperV6::PopupDone,
};
XDGSurfaceWrapperV6* xdg_surface =
static_cast<XDGSurfaceWrapperV6*>(zxdg_surface_v6_.get());
if (!xdg_surface)
return false;
XDGSurfaceWrapperV6* parent_xdg_surface;
// If the parent window is a popup, the surface of that popup must be used as
// a parent.
if (parent_window->xdg_popup()) {
XDGPopupWrapperV6* popup =
reinterpret_cast<XDGPopupWrapperV6*>(parent_window->xdg_popup());
parent_xdg_surface =
reinterpret_cast<XDGSurfaceWrapperV6*>(popup->xdg_surface());
} else {
parent_xdg_surface =
reinterpret_cast<XDGSurfaceWrapperV6*>(parent_window->xdg_surface());
}
if (!parent_xdg_surface)
return false;
zxdg_positioner_v6* positioner = CreatePositioner(connection, bounds);
if (!positioner)
return false;
xdg_popup_.reset(zxdg_surface_v6_get_popup(xdg_surface->xdg_surface(),
parent_xdg_surface->xdg_surface(),
positioner));
if (!xdg_popup_)
return false;
zxdg_positioner_v6_destroy(positioner);
zxdg_popup_v6_grab(xdg_popup_.get(), connection->seat(),
connection->serial());
zxdg_popup_v6_add_listener(xdg_popup_.get(), &zxdg_popup_v6_listener, this);
wl_surface_commit(surface);
return true;
}
zxdg_positioner_v6* XDGPopupWrapperV6::CreatePositioner(
WaylandConnection* connection,
const gfx::Rect& bounds) {
struct zxdg_positioner_v6* positioner;
positioner = zxdg_shell_v6_create_positioner(connection->shell_v6());
if (!positioner)
return nullptr;
zxdg_positioner_v6_set_anchor_rect(positioner, bounds.x(), bounds.y(), 1, 1);
zxdg_positioner_v6_set_size(positioner, bounds.width(), bounds.height());
zxdg_positioner_v6_set_anchor(
positioner,
ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
zxdg_positioner_v6_set_gravity(
positioner,
ZXDG_POSITIONER_V6_ANCHOR_BOTTOM | ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
return positioner;
}
// static
void XDGPopupWrapperV6::Configure(void* data,
struct zxdg_popup_v6* zxdg_popup_v6,
int32_t x,
int32_t y,
int32_t width,
int32_t height) {}
// static
void XDGPopupWrapperV6::PopupDone(void* data,
struct zxdg_popup_v6* zxdg_popup_v6) {
CHECK(false);
WaylandWindow* window =
static_cast<XDGPopupWrapperV6*>(data)->wayland_window_;
DCHECK(window);
window->Hide();
window->OnCloseRequest();
}
XDGSurfaceWrapper* XDGPopupWrapperV6::xdg_surface() {
DCHECK(zxdg_surface_v6_.get());
return zxdg_surface_v6_.get();
}
} // namespace ui