diff --git a/wayland_adapter/framework/core/wayland_subsurface.cpp b/wayland_adapter/framework/core/wayland_subsurface.cpp index 009315c097bace81a24a51fc07ca3da67afef8b6..e12ce9fe9a33edad944b4910c43cb69fb9d4ff9a 100644 --- a/wayland_adapter/framework/core/wayland_subsurface.cpp +++ b/wayland_adapter/framework/core/wayland_subsurface.cpp @@ -16,6 +16,7 @@ #include "wayland_subsurface.h" #include "wayland_objects_pool.h" +#include "wayland_surface.h" namespace FT { namespace Wayland { @@ -32,7 +33,11 @@ struct wl_subsurface_interface IWaylandSubSurface::impl_ = { .set_desync = IWaylandSubSurface::SetDesync, }; -void IWaylandSubSurface::SetPosition(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y) {} +void IWaylandSubSurface::SetPosition(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y) +{ + CAST_OBJECT_AND_CALL_FUNC(WaylandSubSurface, resource, + "IWaylandSubSurface::SetPosition: failed to find object.", SetPosition, resource, x, y); +} void IWaylandSubSurface::PlaceAbove(struct wl_client *client, struct wl_resource *resource, struct wl_resource *sibling) {} @@ -58,7 +63,24 @@ OHOS::sptr WaylandSubSurface::Create(struct wl_client *client WaylandSubSurface::WaylandSubSurface(struct wl_client *client, uint32_t version, uint32_t id, struct wl_resource *surface, struct wl_resource *parent) - : WaylandResourceObject(client, &wl_subsurface_interface, version, id, &IWaylandSubSurface::impl_) {} + : WaylandResourceObject(client, &wl_subsurface_interface, version, id, &IWaylandSubSurface::impl_) +{ + parentSurfaceRes_ = parent; + childSurfaceRes_ = surface; +} + +void WaylandSubSurface::SetPosition(struct wl_resource *resource, int32_t x, int32_t y) +{ + if ((positionX_ != x) || (positionY_ != y)) { + LOG_INFO("SetPosition X:%{public}d, Y:%{public}d", x, y); + auto surfaceParent = CastFromResource(parentSurfaceRes_); + auto surfaceChild = CastFromResource(childSurfaceRes_); + surfaceParent->AddChild(childSurfaceRes_, x, y); + surfaceChild->AddParent(parentSurfaceRes_); + positionX_ = x; + positionY_ = y; + } +} WaylandSubSurface::~WaylandSubSurface() noexcept {} } // namespace Wayland diff --git a/wayland_adapter/framework/core/wayland_subsurface.h b/wayland_adapter/framework/core/wayland_subsurface.h index fffa6b41c80eb8296256083cb3a8395e10cf053b..71048a24749f0c6f696d52dec3c4e2fb352a1389 100644 --- a/wayland_adapter/framework/core/wayland_subsurface.h +++ b/wayland_adapter/framework/core/wayland_subsurface.h @@ -33,10 +33,16 @@ public: static OHOS::sptr Create(struct wl_client *client, uint32_t version, uint32_t id, struct wl_resource *surface, struct wl_resource *parent); ~WaylandSubSurface() noexcept override; + void SetPosition(struct wl_resource *resource, int32_t x, int32_t y); private: WaylandSubSurface(struct wl_client *client, uint32_t version, uint32_t id, struct wl_resource *surface, struct wl_resource *parent); + + struct wl_resource *parentSurfaceRes_; + struct wl_resource *childSurfaceRes_; + int32_t positionX_ = -1; + int32_t positionY_ = -1; }; } // namespace Wayland } // namespace FT diff --git a/wayland_adapter/framework/core/wayland_surface.cpp b/wayland_adapter/framework/core/wayland_surface.cpp index a077929e85338960070571590abaa42e82121063..3291c44ce5bf73f7702d8c8044457d3e44b2802b 100644 --- a/wayland_adapter/framework/core/wayland_surface.cpp +++ b/wayland_adapter/framework/core/wayland_surface.cpp @@ -300,9 +300,10 @@ void WaylandSurface::Damage(int32_t x, int32_t y, int32_t width, int32_t height) void WaylandSurface::Frame(uint32_t callback) { + bool pending = false; if (new_.cb != nullptr) { + pending = true; LOG_WARN("duplicate frame request"); - return; } auto cb = FrameCallback::Create(WlClient(), WAYLAND_VERSION_MAJOR, callback); @@ -312,6 +313,10 @@ void WaylandSurface::Frame(uint32_t callback) } WaylandObjectsPool::GetInstance().AddObject(ObjectId(cb->WlClient(), cb->Id()), cb); + if (pending) { + pengindCb_.push_back(cb); + return; + } new_.cb = cb; } @@ -361,15 +366,21 @@ void WaylandSurface::Commit() return; // it is pointer surface, we do not handle commit! } - if (window_ == nullptr) { + if (withTopLevel_ && (window_ == nullptr)) { CreateWindow(); - } else { + LOG_DEBUG("CreateWindow"); + + } + { HandleCommit(); + LOG_DEBUG("withTopLevel_ %{public}d", withTopLevel_); } for (auto &cb : commitCallbacks_) { cb(); } + + } void WaylandSurface::SetBufferTransform(int32_t transform) @@ -417,6 +428,11 @@ void WaylandSurface::HandleCommit() { wl_callback_send_done(new_.cb->WlResource(), 0); wl_resource_destroy(new_.cb->WlResource()); new_.cb = nullptr; + for (auto &cb : pengindCb_) { + wl_callback_send_done(cb->WlResource(), 0); + wl_resource_destroy(cb->WlResource()); + } + pengindCb_.clear(); } old_ = new_; @@ -498,11 +514,6 @@ void WaylandSurface::CreateWindow() void WaylandSurface::CopyBuffer(struct wl_shm_buffer *shm) { - if (rsSurface_ == nullptr) { - LOG_ERROR("rsSurface_ is nullptr"); - return; - } - SkColorType format = ShmFormatToSkia(wl_shm_buffer_get_format(shm)); if (format == SkColorType::kUnknown_SkColorType) { LOG_ERROR("unsupported format %{public}d", wl_shm_buffer_get_format(shm)); @@ -522,26 +533,22 @@ void WaylandSurface::CopyBuffer(struct wl_shm_buffer *shm) LOG_ERROR("wl_shm_buffer_get_data fail"); return; } - - auto framePtr = rsSurface_->RequestFrame(width, height); - if (framePtr == nullptr) { - LOG_ERROR("RequestFrame failed"); - return; + SkImageInfo imageInfo = SkImageInfo::Make(width, height, format, kUnpremul_SkAlphaType); + SkPixmap srcPixmap(imageInfo, data, stride); + { + std::lock_guard lg(bitmapMutex_); + srcBitmap_.installPixels(srcPixmap); } - auto canvas = framePtr->GetCanvas(); - if (canvas == nullptr) { - LOG_ERROR("GetCanvas failed"); + if (!withTopLevel_) { + auto surfaceParent = CastFromResource(parentSurfaceRes_); + if (parentSurfaceRes_ != nullptr) { + surfaceParent->TriggerInnerCompose(); + } + LOG_DEBUG("return because without toplevel"); return; } - canvas->clear(SK_ColorTRANSPARENT); - - SkImageInfo imageInfo = SkImageInfo::Make(width, height, format, kUnpremul_SkAlphaType); - SkPixmap srcPixmap(imageInfo, data, stride); - SkBitmap srcBitmap; - srcBitmap.installPixels(srcPixmap); - canvas->drawBitmap(srcBitmap, 0, 0); - rsSurface_->FlushFrame(framePtr); + TriggerInnerCompose(); } void WaylandSurface::OnSizeChange(const OHOS::Rosen::Rect& rect, OHOS::Rosen::WindowSizeChangeReason reason) @@ -664,5 +671,74 @@ void WaylandSurface::Close() } window_->Close(); } + +void WaylandSurface::WithTopLevel(bool toplevel) +{ + withTopLevel_ = toplevel; +} + +void WaylandSurface::AddChild(struct wl_resource *child, int32_t x, int32_t y) +{ + if (child == nullptr) { + LOG_ERROR("AddChild with nullptr resource"); + return; + } + if (childs_.count(child) > 0) { + childs_[child].offsetX = x; + childs_[child].offsetX = y; + return; + } + SubSurfaceData data; + data.surface = child; + data.offsetX = x; + data.offsetY = y; + childs_[child] = data; + for (auto &cb : rectCallbacks_) { + cb(rect_); + } +} + +void WaylandSurface::AddParent(struct wl_resource *parent) +{ + parentSurfaceRes_ = parent; +} + +void WaylandSurface::ProcessSrcBitmap(SkCanvas* canvas, int32_t x, int32_t y) +{ + std::lock_guard lg(bitmapMutex_); + canvas->drawBitmap(srcBitmap_, x, y); + LOG_DEBUG("draw child offsetx %{public}d, offsety %{public}d,", x, y); +} + +void WaylandSurface::TriggerInnerCompose() +{ + if (rsSurface_ == nullptr) { + LOG_ERROR("rsSurface_ is nullptr"); + return; + } + auto framePtr = rsSurface_->RequestFrame(srcBitmap_.width(), srcBitmap_.height()); + if (framePtr == nullptr) { + LOG_ERROR("RequestFrame failed"); + return; + } + + auto canvas = framePtr->GetCanvas(); + if (canvas == nullptr) { + LOG_ERROR("GetCanvas failed"); + return; + } + canvas->clear(SK_ColorTRANSPARENT); + canvas->drawBitmap(srcBitmap_, 0, 0); + for (auto &&[childKey, data] : childs_) { + if (data.surface == nullptr) { + continue; + } + LOG_DEBUG("Draw Child"); + auto surfaceChild = CastFromResource(data.surface); + surfaceChild->ProcessSrcBitmap(canvas, data.offsetX, data.offsetY); + } + rsSurface_->FlushFrame(framePtr); +} + } // namespace Wayland } // namespace FT diff --git a/wayland_adapter/framework/core/wayland_surface.h b/wayland_adapter/framework/core/wayland_surface.h index f58794bb165e9ec3ddbb7547efd13f09c7c20b8d..9c385ddbddd959c2f92a2e0f11418bcf172241e7 100644 --- a/wayland_adapter/framework/core/wayland_surface.h +++ b/wayland_adapter/framework/core/wayland_surface.h @@ -16,6 +16,9 @@ #pragma once #include +#include +#include +#include #include #include "wayland_resource_object.h" #include "wayalnd_utils.h" @@ -45,6 +48,7 @@ struct IWaylandSurface { static struct wl_surface_interface impl_; }; + class WaylandSurface final : public WaylandResourceObject { friend struct IWaylandSurface; @@ -72,7 +76,12 @@ public: void UnSetFullscreen(); void SetMinimized(); void Close(); - + void WithTopLevel(bool toplevel); + void AddChild(struct wl_resource *child, int32_t x, int32_t y); + void AddParent(struct wl_resource *parent); + void ProcessSrcBitmap(SkCanvas* canvas, int32_t x, int32_t y); + void TriggerInnerCompose(); + private: WaylandSurface(struct wl_client *client, struct wl_resource *parent, uint32_t version, uint32_t id); @@ -109,6 +118,15 @@ private: std::shared_ptr rsSurface_; std::string windowTitle_ = "unknow"; bool maximized_ = false; + bool withTopLevel_ = false; + std::map childs_; + struct wl_resource *parentSurfaceRes_ = nullptr; + std::mutex bitmapMutex_; + SkBitmap srcBitmap_; + std::vector> pengindCb_; }; + + + } // 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 2604c248ccbdb497e0742821b3e6ae98975eab61..9dcb7bcfa8d2d519c8f2f4dabb6c9f5efe690df0 100644 --- a/wayland_adapter/framework/stable/wayland_xdg_surface.cpp +++ b/wayland_adapter/framework/stable/wayland_xdg_surface.cpp @@ -96,6 +96,7 @@ void WaylandXdgSurface::GetToplevel(uint32_t id) } role_ = SurfaceRole::XDG_TOPLEVEL; + surface_->WithTopLevel(true); } void WaylandXdgSurface::GetPopup(uint32_t id, struct wl_resource *parent, struct wl_resource *positioner) @@ -157,6 +158,7 @@ void WaylandXdgSurface::OnSurfaceRect(Rect rect) auto topLevel = toplevel_.promote(); if (topLevel != nullptr) { topLevel->SetRect(rect); + xdg_surface_send_configure(WlResource(), wl_display_next_serial(WlDisplay())); } } } diff --git a/wayland_adapter/framework/stable/wayland_xdg_toplevel.cpp b/wayland_adapter/framework/stable/wayland_xdg_toplevel.cpp index 23bab9fad9547fe9876c80b9f4b4cb9d854fb892..baa6931d6f4bd1e49ad247993ea264a75df0a24a 100644 --- a/wayland_adapter/framework/stable/wayland_xdg_toplevel.cpp +++ b/wayland_adapter/framework/stable/wayland_xdg_toplevel.cpp @@ -147,7 +147,7 @@ OHOS::sptr WaylandXdgToplevel::Create(const OHOS::sptr &xdgSurface, uint32_t id) : WaylandResourceObject(xdgSurface->WlClient(), &xdg_toplevel_interface, xdgSurface->Version(), id, &IWaylandXdgToplevel::impl_), - xdgSurface_(xdgSurface) + xdgSurface_(xdgSurface) { LOG_DEBUG("enter"); } @@ -274,14 +274,15 @@ void WaylandXdgToplevel::HandleCommit() void WaylandXdgToplevel::SetRect(Rect rect) { - LOG_DEBUG("Window %{public}s.", windowTitle_.c_str()); rect_ = rect; - struct wl_array states; uint32_t *s; wl_array_init(&states); + wl_array_init(&states); s = static_cast(wl_array_add(&states, sizeof(uint32_t))); *s = XDG_TOPLEVEL_STATE_RESIZING; + s = static_cast(wl_array_add(&states, sizeof(uint32_t))); + *s = XDG_TOPLEVEL_STATE_ACTIVATED; xdg_toplevel_send_configure(WlResource(), rect.width, rect.height, &states); wl_array_release(&states); } diff --git a/wayland_adapter/utils/include/wayalnd_utils.h b/wayland_adapter/utils/include/wayalnd_utils.h index 666aba4d32166be65d6d2632c8eb17f38d79167e..7fa5215743b1f5f53f412a1e3f25640e32200df6 100644 --- a/wayland_adapter/utils/include/wayalnd_utils.h +++ b/wayland_adapter/utils/include/wayalnd_utils.h @@ -93,5 +93,12 @@ static SkColorType ShmFormatToSkia(const uint32_t& shmFormat) return SkColorType::kUnknown_SkColorType; } } + +struct SubSurfaceData { + struct wl_resource *surface = nullptr; + int32_t offsetX = 0; + int32_t offsetY = 0; +}; + } // namespace Wayland } // namespace FT