diff --git a/wayland_adapter/framework/BUILD.gn b/wayland_adapter/framework/BUILD.gn index bb906c1880e78415749dfa336aae6ef37bd712dc..cd729989e9ef5a4f8407c9f4d2ad996669659d54 100644 --- a/wayland_adapter/framework/BUILD.gn +++ b/wayland_adapter/framework/BUILD.gn @@ -44,6 +44,8 @@ ft_source_set("wayland_framewok_sources") { "stable/wayland_xdg_surface.cpp", "stable/wayland_xdg_toplevel.cpp", "stable/wayland_xdg_wm_base.cpp", + "stable/wayland_xdg_popup.cpp", + "stable/wayland_xdg_positioner.cpp", ] sources += [ diff --git a/wayland_adapter/framework/core/wayland_surface.h b/wayland_adapter/framework/core/wayland_surface.h index 9c385ddbddd959c2f92a2e0f11418bcf172241e7..df975f1c43e01a8e31e9b1dededd076c81253160 100644 --- a/wayland_adapter/framework/core/wayland_surface.h +++ b/wayland_adapter/framework/core/wayland_surface.h @@ -125,8 +125,5 @@ private: SkBitmap srcBitmap_; std::vector> pengindCb_; }; - - - } // namespace Wayland } // namespace FT diff --git a/wayland_adapter/framework/stable/wayland_xdg_popup.cpp b/wayland_adapter/framework/stable/wayland_xdg_popup.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d046d904494edc156b688af90777a58035d613ed --- /dev/null +++ b/wayland_adapter/framework/stable/wayland_xdg_popup.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023 Huawei Technologies Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wayland_xdg_popup.h" + +#include "wayland_objects_pool.h" +#include "wayland_xdg_toplevel.h" +#include "wayland_xdg_wm_base.h" + +namespace FT { +namespace Wayland { +namespace { + constexpr HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WAYLAND, "WaylandXdgPopup"}; +} + +struct xdg_popup_interface WaylandXdgPopupInterface::impl_ = { + .destroy = WaylandResourceObject::DefaultDestroyResource, + .grab = WaylandXdgPopupInterface::Grab, + .reposition = WaylandXdgPopupInterface::Reposition}; + +void WaylandXdgPopupInterface::Grab( + struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *seat, + uint32_t serial) +{} + +void WaylandXdgPopupInterface::Reposition( + struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *positioner, + uint32_t token) +{} + +OHOS::sptr WaylandXdgPopup::Create( + const OHOS::sptr &xdgSurface, + const OHOS::sptr &parentXdgSurface, + const OHOS::sptr &positioner, + uint32_t id) +{ + if (xdgSurface == nullptr) { + LOG_ERROR("WaylandXdgPopup::Create: xdgSurface is nullptr."); + return nullptr; + } + + if (parentXdgSurface == nullptr) { + LOG_ERROR("WaylandXdgPopup::Create: parentXdgSurface is nullptr."); + return nullptr; + } + + if (positioner == nullptr) { + LOG_ERROR("WaylandXdgPopup::Create: positioner is nullptr."); + return nullptr; + } + + auto xdgPopUp = OHOS::sptr(new WaylandXdgPopup(xdgSurface, parentXdgSurface, positioner, id)); + WaylandObjectsPool::GetInstance().AddObject(ObjectId(xdgPopUp->WlClient(), xdgPopUp->Id()), xdgPopUp); + return xdgPopUp; +} + +WaylandXdgPopup::WaylandXdgPopup( + const OHOS::sptr &xdgSurface, + const OHOS::sptr &parentXdgSurface, + const OHOS::sptr &positioner, + uint32_t id) + : WaylandResourceObject( + xdgSurface->WlClient(), + &xdg_popup_interface, + xdgSurface->Version(), + id, + &WaylandXdgPopupInterface::impl_), + xdgSurface_(xdgSurface), + parentXdgSurface_(parentXdgSurface) +{ + // TODO: get information from positioner. + LOG_DEBUG("WaylandXdgPopup ctor."); +} + +WaylandXdgPopup::~WaylandXdgPopup() noexcept +{ + LOG_DEBUG("WaylandXdgPopup dtor."); +} + +void WaylandXdgPopup::OnSurfaceCommitted() {} + +void WaylandXdgPopup::Grab(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, uint32_t serial) +{} + +void WaylandXdgPopup::Reposition( + struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *positioner, + uint32_t token) +{} + +void WaylandXdgPopup::UpdateSize(int32_t x, int32_t y, uint32_t width, uint32_t height) +{ +} + +void WaylandXdgPopup::SetGeometry(int32_t x, int32_t y, uint32_t width, uint32_t height) +{ +} +} // namespace Wayland +} // namespace FT diff --git a/wayland_adapter/framework/stable/wayland_xdg_popup.h b/wayland_adapter/framework/stable/wayland_xdg_popup.h new file mode 100644 index 0000000000000000000000000000000000000000..b68615bc538eadc94c1b04e3f9576e86b36e3f6e --- /dev/null +++ b/wayland_adapter/framework/stable/wayland_xdg_popup.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2023 Huawei Technologies Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "wayland_resource_object.h" +#include "wayland_xdg_positioner.h" +#include "wayalnd_utils.h" + +namespace FT { +namespace Wayland { +class WaylandXdgSurface; + +struct WaylandXdgPopupInterface { + /** + * make the popup take an explicit grab + * + * This request makes the created popup take an explicit grab. An + * explicit grab will be dismissed when the user dismisses the + * popup, or when the client destroys the xdg_popup. This can be + * done by the user clicking outside the surface, using the + * keyboard, or even locking the screen through closing the lid or + * a timeout. + * + * If the compositor denies the grab, the popup will be immediately + * dismissed. + * + * This request must be used in response to some sort of user + * action like a button press, key press, or touch down event. The + * serial number of the event should be passed as 'serial'. + * + * The parent of a grabbing popup must either be an xdg_toplevel + * surface or another xdg_popup with an explicit grab. If the + * parent is another xdg_popup it means that the popups are nested, + * with this popup now being the topmost popup. + * + * Nested popups must be destroyed in the reverse order they were + * created in, e.g. the only popup you are allowed to destroy at + * all times is the topmost one. + * + * When compositors choose to dismiss a popup, they may dismiss + * every nested grabbing popup as well. When a compositor dismisses + * popups, it will follow the same dismissing order as required + * from the client. + * + * The parent of a grabbing popup must either be another xdg_popup + * with an active explicit grab, or an xdg_popup or xdg_toplevel, + * if there are no explicit grabs already taken. + * + * If the topmost grabbing popup is destroyed, the grab will be + * returned to the parent of the popup, if that parent previously + * had an explicit grab. + * + * If the parent is a grabbing popup which has already been + * dismissed, this popup will be immediately dismissed. If the + * parent is a popup that did not take an explicit grab, an error + * will be raised. + * + * During a popup grab, the client owning the grab will receive + * pointer and touch events for all their surfaces as normal + * (similar to an "owner-events" grab in X11 parlance), while the + * top most grabbing popup will always have keyboard focus. + * @param seat the wl_seat of the user event + * @param serial the serial of the user event + */ + static void Grab(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, uint32_t serial); + /** + * recalculate the popup's location + * + * Reposition an already-mapped popup. The popup will be placed + * given the details in the passed xdg_positioner object, and a + * xdg_popup.repositioned followed by xdg_popup.configure and + * xdg_surface.configure will be emitted in response. Any + * parameters set by the previous positioner will be discarded. + * + * The passed token will be sent in the corresponding + * xdg_popup.repositioned event. The new popup position will not + * take effect until the corresponding configure event is + * acknowledged by the client. See xdg_popup.repositioned for + * details. The token itself is opaque, and has no other special + * meaning. + * + * If multiple reposition requests are sent, the compositor may + * skip all but the last one. + * + * If the popup is repositioned in response to a configure event + * for its parent, the client should send an + * xdg_positioner.set_parent_configure and possibly an + * xdg_positioner.set_parent_size request to allow the compositor + * to properly constrain the popup. + * + * If the popup is repositioned together with a parent that is + * being resized, but not in response to a configure event, the + * client should send an xdg_positioner.set_parent_size request. + * @param token reposition request token + * @since 3 + */ + static void Reposition( + struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *positioner, + uint32_t token); + + static struct xdg_popup_interface impl_; +}; + +class WaylandXdgPopup : public WaylandResourceObject { +public: + static OHOS::sptr Create( + const OHOS::sptr &xdgSurface, + const OHOS::sptr &parentXdgSurface, + const OHOS::sptr &positioner, + uint32_t id); + ~WaylandXdgPopup() noexcept; + void OnSurfaceCommitted(); + void UpdateSize(int32_t x, int32_t y, uint32_t width, uint32_t height); + void SetGeometry(int32_t x, int32_t y, uint32_t width, uint32_t height); + +private: + WaylandXdgPopup( + const OHOS::sptr &xdgSurface, + const OHOS::sptr &parentXdgSurface, + const OHOS::sptr &positioner, + uint32_t id); + + friend struct WaylandXdgPopupInterface; + + void Grab(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, uint32_t serial); + + void Reposition( + struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *positioner, + uint32_t token); + +private: + OHOS::wptr xdgSurface_; + OHOS::wptr parentXdgSurface_; +}; +} // namespace Wayland +} // namespace FT diff --git a/wayland_adapter/framework/stable/wayland_xdg_positioner.cpp b/wayland_adapter/framework/stable/wayland_xdg_positioner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..543109607b886da73217dbfda736a5b5fb572158 --- /dev/null +++ b/wayland_adapter/framework/stable/wayland_xdg_positioner.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2023 Huawei Technologies Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wayland_xdg_positioner.h" + +#include "wayland_objects_pool.h" +#include "wayland_xdg_surface.h" + +namespace FT { +namespace Wayland { +namespace { + constexpr HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WAYLAND, "WaylandXdgPositioner"}; +} +struct xdg_positioner_interface WaylandXdgPositionerInterface::impl_ = { + .destroy = WaylandResourceObject::DefaultDestroyResource, + .set_size = WaylandXdgPositionerInterface::SetSize, + .set_anchor_rect = WaylandXdgPositionerInterface::SetAnchorRect, + .set_anchor = WaylandXdgPositionerInterface::SetAnchor, + .set_gravity = WaylandXdgPositionerInterface::SetGravity, + .set_constraint_adjustment = WaylandXdgPositionerInterface::SetConstraintAdjustment, + .set_offset = WaylandXdgPositionerInterface::SetOffset, + .set_reactive = WaylandXdgPositionerInterface::SetReactive, + .set_parent_size = WaylandXdgPositionerInterface::SetParentSize, + .set_parent_configure = WaylandXdgPositionerInterface::SetParentConfigure}; + +void WaylandXdgPositionerInterface::SetSize( + struct wl_client *client, + struct wl_resource *resource, + int32_t width, + int32_t height) +{ + LOG_DEBUG("Request: xdg_positioner-->set_size."); + UNUSED(client); + CAST_OBJECT_AND_CALL_FUNC( + WaylandXdgPositioner, resource, "WaylandXdgPositioner::SetSize: failed to find object.", SetSize, width, height); +} + +void WaylandXdgPositionerInterface::SetAnchorRect( + struct wl_client *client, + struct wl_resource *resource, + int32_t x, + int32_t y, + int32_t width, + int32_t height) +{ + LOG_DEBUG("Request: xdg_positioner-->set_anchor_rect."); + UNUSED(client); + CAST_OBJECT_AND_CALL_FUNC( + WaylandXdgPositioner, + resource, + "WaylandXdgPositioner::SetAnchorRect: failed to find object.", + SetAnchorRect, + x, + y, + width, + height); +} + +void WaylandXdgPositionerInterface::SetAnchor(struct wl_client *client, struct wl_resource *resource, uint32_t anchor) +{ + LOG_DEBUG("Request: xdg_positioner-->set_anchor."); + UNUSED(client); + CAST_OBJECT_AND_CALL_FUNC( + WaylandXdgPositioner, resource, "WaylandXdgPositioner::SetAnchor: failed to find object.", SetAnchor, anchor); +} + +void WaylandXdgPositionerInterface::SetGravity(struct wl_client *client, struct wl_resource *resource, uint32_t gravity) +{ + LOG_DEBUG("Request: xdg_positioner-->set_gravity."); + UNUSED(client); + CAST_OBJECT_AND_CALL_FUNC( + WaylandXdgPositioner, resource, "WaylandXdgPositioner::SetGravity: failed to find object.", SetGravity, gravity); +} + +void WaylandXdgPositionerInterface::SetConstraintAdjustment( + struct wl_client *client, + struct wl_resource *resource, + uint32_t constraintAdjustment) +{ + LOG_DEBUG("Request: xdg_positioner-->set_constraint_adjustment."); + UNUSED(client); + CAST_OBJECT_AND_CALL_FUNC( + WaylandXdgPositioner, + resource, + "WaylandXdgPositioner::SetConstraintAdjustment: failed to find object.", + SetConstraintAdjustment, + constraintAdjustment); +} + +void WaylandXdgPositionerInterface::SetOffset(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y) +{ + LOG_DEBUG("Request: xdg_positioner-->set_offset."); + UNUSED(client); + CAST_OBJECT_AND_CALL_FUNC( + WaylandXdgPositioner, resource, "WaylandXdgPositioner::SetOffset: failed to find object.", SetOffset, x, y); +} + +void WaylandXdgPositionerInterface::SetReactive(struct wl_client *client, struct wl_resource *resource) +{ + LOG_DEBUG("Request: xdg_positioner-->set_reactive."); + UNUSED(client); + CAST_OBJECT_AND_CALL_FUNC( + WaylandXdgPositioner, resource, "WaylandXdgPositioner::SetReactive: failed to find object.", SetReactive); +} + +void WaylandXdgPositionerInterface::SetParentSize( + struct wl_client *client, + struct wl_resource *resource, + int32_t parentWidth, + int32_t parentHeight) +{ + LOG_DEBUG("Request: xdg_positioner-->set_parent_size."); + UNUSED(client); + CAST_OBJECT_AND_CALL_FUNC( + WaylandXdgPositioner, + resource, + "WaylandXdgPositioner::SetParentSize: failed to find object.", + SetParentSize, + parentWidth, + parentHeight); +} + +void WaylandXdgPositionerInterface::SetParentConfigure( + struct wl_client *client, + struct wl_resource *resource, + uint32_t serial) +{ + LOG_DEBUG("Request: xdg_positioner-->set_parent_configure."); + UNUSED(client); + CAST_OBJECT_AND_CALL_FUNC( + WaylandXdgPositioner, + resource, + "WaylandXdgPositioner::SetParentConfigure: failed to find object.", + SetParentConfigure, + serial); +} + +OHOS::sptr WaylandXdgPositioner::Create(struct wl_client *client, uint32_t version, uint32_t id) +{ + // check + if (client == nullptr) { + LOG_WARN("WaylandXdgPositioner::Create failed: client is nullptr."); + return nullptr; + } + + auto xdgPositioner = OHOS::sptr(new WaylandXdgPositioner(client, version, id)); + WaylandObjectsPool::GetInstance().AddObject(ObjectId(xdgPositioner->WlClient(), xdgPositioner->Id()), xdgPositioner); + return xdgPositioner; +} + +WaylandXdgPositioner::WaylandXdgPositioner(struct wl_client *client, uint32_t version, uint32_t id) + : WaylandResourceObject(client, &xdg_positioner_interface, version, id, &WaylandXdgPositionerInterface::impl_) +{ + LOG_DEBUG("WaylandXdgPositioner ctor."); +} + +WaylandXdgPositioner::~WaylandXdgPositioner() noexcept +{ + LOG_DEBUG("WaylandXdgPositioner dtor."); +} + +void WaylandXdgPositioner::SetSize(int32_t width, int32_t height) +{ + if (width < 1 || height < 1) { + wl_resource_post_error( + WlResource(), XDG_POSITIONER_ERROR_INVALID_INPUT, "width and height must be positives and non-zero"); + return; + } + + size_.width = width; + size_.height = height; +} + +void WaylandXdgPositioner::SetAnchorRect(int32_t x, int32_t y, int32_t width, int32_t height) +{ + if (width < 0 || height < 0) { + wl_resource_post_error( + WlResource(), XDG_POSITIONER_ERROR_INVALID_INPUT, "width and height must be non-negative"); + return; + } + + anchorRect_.x = x; + anchorRect_.y = y; + anchorRect_.width = width; + anchorRect_.height = height; +} + +void WaylandXdgPositioner::SetAnchor(uint32_t anchor) +{ + auto newAnchor = static_cast(anchor); + switch (newAnchor) { + case XDG_POSITIONER_ANCHOR_NONE: + case XDG_POSITIONER_ANCHOR_TOP: + case XDG_POSITIONER_ANCHOR_BOTTOM: + case XDG_POSITIONER_ANCHOR_LEFT: + case XDG_POSITIONER_ANCHOR_RIGHT: + case XDG_POSITIONER_ANCHOR_TOP_LEFT: + case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: + case XDG_POSITIONER_ANCHOR_TOP_RIGHT: + case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT: + anchor_ = newAnchor; + break; + default: + break; + } +} + +void WaylandXdgPositioner::SetGravity(uint32_t gravity) +{ + auto newGravity = static_cast(gravity); + switch (newGravity) { + case XDG_POSITIONER_GRAVITY_NONE: + case XDG_POSITIONER_GRAVITY_TOP: + case XDG_POSITIONER_GRAVITY_BOTTOM: + case XDG_POSITIONER_GRAVITY_LEFT: + case XDG_POSITIONER_GRAVITY_RIGHT: + case XDG_POSITIONER_GRAVITY_TOP_LEFT: + case XDG_POSITIONER_GRAVITY_BOTTOM_LEFT: + case XDG_POSITIONER_GRAVITY_TOP_RIGHT: + case XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT: + gravity_ = newGravity; + break; + default: + break; + } +} + +void WaylandXdgPositioner::SetConstraintAdjustment(uint32_t constraintAdjustment) +{ + auto newConstraintAdjustment = static_cast(constraintAdjustment); + switch (newConstraintAdjustment) { + case XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE: + case XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X: + case XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y: + case XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X: + case XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y: + case XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X: + case XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y: + constraintAdjustment_ = newConstraintAdjustment; + break; + default: + break; + } +} + +void WaylandXdgPositioner::SetOffset(int32_t x, int32_t y) +{ + offset_.x = x; + offset_.y = y; +} + +void WaylandXdgPositioner::SetReactive() +{ + reactive_ = true; +} + +void WaylandXdgPositioner::SetParentSize(int32_t parentWidth, int32_t parentHeight) +{ + if (parentWidth < 1 || parentHeight < 1) { + wl_resource_post_error( + WlResource(), + XDG_POSITIONER_ERROR_INVALID_INPUT, + "positioner parent width and height must be positives and non-zero"); + return; + } + + parentSize_.width = parentWidth; + parentSize_.height = parentHeight; +} + +void WaylandXdgPositioner::SetParentConfigure(uint32_t serial) +{ + parentConfigureSerial_ = serial; +} +} // namespace Wayland +} // namespace FT diff --git a/wayland_adapter/framework/stable/wayland_xdg_positioner.h b/wayland_adapter/framework/stable/wayland_xdg_positioner.h new file mode 100644 index 0000000000000000000000000000000000000000..3aed8a5a9dd070f35a52da714904dd7d7ad52ff6 --- /dev/null +++ b/wayland_adapter/framework/stable/wayland_xdg_positioner.h @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2023 Huawei Technologies Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "wayland_resource_object.h" +#include "wayalnd_utils.h" + +namespace FT { +namespace Wayland { +struct WaylandXdgPositionerInterface { + /** + * set the size of the to-be positioned rectangle + * + * Set the size of the surface that is to be positioned with the + * positioner object. The size is in surface-local coordinates and + * corresponds to the window geometry. See + * xdg_surface.set_window_geometry. + * + * If a zero or negative size is set the invalid_input error is + * raised. + * @param width width of positioned rectangle + * @param height height of positioned rectangle + */ + static void SetSize(struct wl_client *client, struct wl_resource *resource, int32_t width, int32_t height); + /** + * set the anchor rectangle within the parent surface + * + * Specify the anchor rectangle within the parent surface that + * the child surface will be placed relative to. The rectangle is + * relative to the window geometry as defined by + * xdg_surface.set_window_geometry of the parent surface. + * + * When the xdg_positioner object is used to position a child + * surface, the anchor rectangle may not extend outside the window + * geometry of the positioned child's parent surface. + * + * If a negative size is set the invalid_input error is raised. + * @param x x position of anchor rectangle + * @param y y position of anchor rectangle + * @param width width of anchor rectangle + * @param height height of anchor rectangle + */ + static void SetAnchorRect( + struct wl_client *client, + struct wl_resource *resource, + int32_t x, + int32_t y, + int32_t width, + int32_t height); + /** + * set anchor rectangle anchor + * + * Defines the anchor point for the anchor rectangle. The + * specified anchor is used derive an anchor point that the child + * surface will be positioned relative to. If a corner anchor is + * set (e.g. 'top_left' or 'bottom_right'), the anchor point will + * be at the specified corner; otherwise, the derived anchor point + * will be centered on the specified edge, or in the center of the + * anchor rectangle if no edge is specified. + * @param anchor anchor + */ + static void SetAnchor(struct wl_client *client, struct wl_resource *resource, uint32_t anchor); + /** + * set child surface gravity + * + * Defines in what direction a surface should be positioned, + * relative to the anchor point of the parent surface. If a corner + * gravity is specified (e.g. 'bottom_right' or 'top_left'), then + * the child surface will be placed towards the specified gravity; + * otherwise, the child surface will be centered over the anchor + * point on any axis that had no gravity specified. + * @param gravity gravity direction + */ + static void SetGravity(struct wl_client *client, struct wl_resource *resource, uint32_t gravity); + /** + * set the adjustment to be done when constrained + * + * Specify how the window should be positioned if the originally + * intended position caused the surface to be constrained, meaning + * at least partially outside positioning boundaries set by the + * compositor. The adjustment is set by constructing a bitmask + * describing the adjustment to be made when the surface is + * constrained on that axis. + * + * If no bit for one axis is set, the compositor will assume that + * the child surface should not change its position on that axis + * when constrained. + * + * If more than one bit for one axis is set, the order of how + * adjustments are applied is specified in the corresponding + * adjustment descriptions. + * + * The default adjustment is none. + * @param constraintAdjustment bit mask of constraint adjustments + */ + static void SetConstraintAdjustment( + struct wl_client *client, + struct wl_resource *resource, + uint32_t constraintAdjustment); + /** + * set surface position offset + * + * Specify the surface position offset relative to the position + * of the anchor on the anchor rectangle and the anchor on the + * surface. For example if the anchor of the anchor rectangle is at + * (x, y), the surface has the gravity bottom|right, and the offset + * is (ox, oy), the calculated surface position will be (x + ox, y + * + oy). The offset position of the surface is the one used for + * constraint testing. See set_constraint_adjustment. + * + * An example use case is placing a popup menu on top of a user + * interface element, while aligning the user interface element of + * the parent surface with some user interface element placed + * somewhere in the popup surface. + * @param x surface position x offset + * @param y surface position y offset + */ + static void SetOffset(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y); + /** + * continuously reconstrain the surface + * + * When set reactive, the surface is reconstrained if the + * conditions used for constraining changed, e.g. the parent window + * moved. + * + * If the conditions changed and the popup was reconstrained, an + * xdg_popup.configure event is sent with updated geometry, + * followed by an xdg_surface.configure event. + * @since 3 + */ + static void SetReactive(struct wl_client *client, struct wl_resource *resource); + /** + * + * + * Set the parent window geometry the compositor should use when + * positioning the popup. The compositor may use this information + * to determine the future state the popup should be constrained + * using. If this doesn't match the dimension of the parent the + * popup is eventually positioned against, the behavior is + * undefined. + * + * The arguments are given in the surface-local coordinate space. + * @param parentWidth future window geometry width of parent + * @param parentHeight future window geometry height of parent + * @since 3 + */ + static void SetParentSize( + struct wl_client *client, + struct wl_resource *resource, + int32_t parentWidth, + int32_t parentHeight); + /** + * set parent configure this is a response to + * + * Set the serial of an xdg_surface.configure event this + * positioner will be used in response to. The compositor may use + * this information together with set_parent_size to determine what + * future state the popup should be constrained using. + * @param serial serial of parent configure event + * @since 3 + */ + static void SetParentConfigure(struct wl_client *client, struct wl_resource *resource, uint32_t serial); + + static struct xdg_positioner_interface impl_; +}; + +class WaylandXdgPositioner final : public WaylandResourceObject { +public: + /** + * @brief Create XdgOutput resource by XdgOutputManager + * + * @param client + * @param manager + * @param version + * @param id + * @param output + * @return OHOS::sptr + */ + static OHOS::sptr Create(struct wl_client *client, uint32_t version, uint32_t id); + ~WaylandXdgPositioner() noexcept override; + + Size GetSize() const + { + return size_; + } + Rect GetAnchorRect() const + { + return anchorRect_; + } + enum xdg_positioner_anchor GetAnchor() const + { + return anchor_; + } + enum xdg_positioner_gravity GetGravity() const + { + return gravity_; + } + enum xdg_positioner_constraint_adjustment GetConstraintAdjustment() const + { + return constraintAdjustment_; + } + Offset GetOffset() const + { + return offset_; + } + bool GetReactive() const + { + return reactive_; + } + Size GetParentSize() const + { + return parentSize_; + } + uint32_t GetParentConfigureSerial() const + { + return parentConfigureSerial_; + } + +private: + WaylandXdgPositioner(struct wl_client *client, uint32_t version, uint32_t id); + +private: + friend struct WaylandXdgPositionerInterface; + // WaylandXdgPositionerInterface will call these member functions. + void SetSize(int32_t width, int32_t height); + void SetAnchorRect(int32_t x, int32_t y, int32_t width, int32_t height); + // enum xdg_positioner_anchor { + // XDG_POSITIONER_ANCHOR_NONE = 0, + // XDG_POSITIONER_ANCHOR_TOP = 1, + // XDG_POSITIONER_ANCHOR_BOTTOM = 2, + // XDG_POSITIONER_ANCHOR_LEFT = 3, + // XDG_POSITIONER_ANCHOR_RIGHT = 4, + // XDG_POSITIONER_ANCHOR_TOP_LEFT = 5, + // XDG_POSITIONER_ANCHOR_BOTTOM_LEFT = 6, + // XDG_POSITIONER_ANCHOR_TOP_RIGHT = 7, + // XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT = 8, + // }; + void SetAnchor(uint32_t anchor); + // enum xdg_positioner_gravity { + // XDG_POSITIONER_GRAVITY_NONE = 0, + // XDG_POSITIONER_GRAVITY_TOP = 1, + // XDG_POSITIONER_GRAVITY_BOTTOM = 2, + // XDG_POSITIONER_GRAVITY_LEFT = 3, + // XDG_POSITIONER_GRAVITY_RIGHT = 4, + // XDG_POSITIONER_GRAVITY_TOP_LEFT = 5, + // XDG_POSITIONER_GRAVITY_BOTTOM_LEFT = 6, + // XDG_POSITIONER_GRAVITY_TOP_RIGHT = 7, + // XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT = 8, + // }; + void SetGravity(uint32_t gravity); + // enum xdg_positioner_constraint_adjustment { + // XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE = 0, + // XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1, + // XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 2, + // XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X = 4, + // XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y = 8, + // XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X = 16, + // XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 32, + // }; + void SetConstraintAdjustment(uint32_t constraintAdjustment); + void SetOffset(int32_t x, int32_t y); + void SetReactive(); + void SetParentSize(int32_t parentWidth, int32_t parentHeight); + void SetParentConfigure(uint32_t serial); + +private: + Size size_; + Rect anchorRect_; + enum xdg_positioner_anchor anchor_ = XDG_POSITIONER_ANCHOR_NONE; + enum xdg_positioner_gravity gravity_ = XDG_POSITIONER_GRAVITY_NONE; + enum xdg_positioner_constraint_adjustment constraintAdjustment_ = XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE; + Offset offset_; + bool reactive_ = false; + Size parentSize_; + uint32_t parentConfigureSerial_ = 0; +}; +} // namespace Wayland +} // namespace FT diff --git a/wayland_adapter/framework/stable/wayland_xdg_surface.cpp b/wayland_adapter/framework/stable/wayland_xdg_surface.cpp index 9dcb7bcfa8d2d519c8f2f4dabb6c9f5efe690df0..6f55815b16987c77da3af23f007499dd836a2dc3 100644 --- a/wayland_adapter/framework/stable/wayland_xdg_surface.cpp +++ b/wayland_adapter/framework/stable/wayland_xdg_surface.cpp @@ -102,6 +102,26 @@ void WaylandXdgSurface::GetToplevel(uint32_t id) void WaylandXdgSurface::GetPopup(uint32_t id, struct wl_resource *parent, struct wl_resource *positioner) { LOG_DEBUG("Window %{public}s.", windowTitle_.c_str()); + auto parentXdgSurface = CastFromResource(parent); + if (parentXdgSurface == nullptr) { + LOG_ERROR("parentXdgSurface is nullptr."); + return; + } + + auto xdgPositioner = CastFromResource(positioner); + if (xdgPositioner == nullptr) { + LOG_ERROR("xdgPositioner is nullptr."); + return; + } + + auto popUp = WaylandXdgPopup::Create(this, parentXdgSurface, xdgPositioner, id); + if (popUp == nullptr) { + LOG_ERROR("no memory"); + return; + } + popUp_ = popUp; + popUp_->UpdateSize(0, 0, xdgPositioner->GetSize().width, xdgPositioner->GetSize().height); + role_ = SurfaceRole::XDG_POPUP; } void WaylandXdgSurface::SetWindowGeometry(int32_t x, int32_t y, int32_t width, int32_t height) diff --git a/wayland_adapter/framework/stable/wayland_xdg_surface.h b/wayland_adapter/framework/stable/wayland_xdg_surface.h index 62d8951e101cfea72b8aa69273cfabbc5a41068f..e72126bbd94625aa0c245772859129ac6118ff1f 100644 --- a/wayland_adapter/framework/stable/wayland_xdg_surface.h +++ b/wayland_adapter/framework/stable/wayland_xdg_surface.h @@ -19,6 +19,7 @@ #include "wayland_resource_object.h" #include "wayland_surface.h" #include "wayalnd_utils.h" +#include "wayland_xdg_popup.h" namespace FT { namespace Wayland { @@ -71,6 +72,7 @@ private: OHOS::wptr xdgWm_; OHOS::wptr surface_; OHOS::wptr toplevel_; + OHOS::wptr popUp_; std::string windowTitle_ = "unknow"; }; } // namespace Wayland diff --git a/wayland_adapter/framework/stable/wayland_xdg_wm_base.cpp b/wayland_adapter/framework/stable/wayland_xdg_wm_base.cpp index a47ee5fd6fde290c74f150d86801908789290e23..705c3c39501c339a56f99863ab2b26bf16c0905e 100644 --- a/wayland_adapter/framework/stable/wayland_xdg_wm_base.cpp +++ b/wayland_adapter/framework/stable/wayland_xdg_wm_base.cpp @@ -17,6 +17,7 @@ #include "wayland_objects_pool.h" #include "wayland_xdg_surface.h" +#include "wayland_xdg_positioner.h" #include "version.h" namespace FT { @@ -72,6 +73,16 @@ WaylandXdgWmObject::~WaylandXdgWmObject() noexcept {} void WaylandXdgWmObject::CreatePositioner(struct wl_client *client, uint32_t id) { + if (client != client_) { + LOG_WARN("client conflict"); + return; + } + + auto xdgPositioner = WaylandXdgPositioner::Create(client, Version(), id); + if (xdgPositioner == nullptr) { + LOG_ERROR("no memory"); + return; + } } void WaylandXdgWmObject::GetXdgSurface(struct wl_client *client, struct wl_resource *xdgWmBaseResource, diff --git a/wayland_adapter/utils/include/wayalnd_utils.h b/wayland_adapter/utils/include/wayalnd_utils.h index 7fa5215743b1f5f53f412a1e3f25640e32200df6..729dcdaa27a7d3dc56e191fc68a4ffd0f0f76491 100644 --- a/wayland_adapter/utils/include/wayalnd_utils.h +++ b/wayland_adapter/utils/include/wayalnd_utils.h @@ -36,6 +36,26 @@ struct Rect { } }; +struct Offset { + int32_t x = 0; + int32_t y = 0; + void Reset() + { + x = 0; + y = 0; + } +}; + +struct Size { + uint32_t width = 0; + uint32_t height = 0; + void Reset() + { + width = 0; + height = 0; + } +}; + using SurfaceCommitCallback = std::function; using SurfaceRectCallback = std::function;