From 88c3f8c44e9c68004599b2241e8b5a7913f591ae Mon Sep 17 00:00:00 2001 From: l00574490 Date: Fri, 14 Jan 2022 10:11:33 +0800 Subject: [PATCH] add for split screen Signed-off-by: l00574490 Change-Id: I0c277688b401f8011cc28dab5cf538e3eab03339 --- interfaces/innerkits/wm/wm_common.h | 5 +- wm/include/window_impl.h | 3 +- wm/src/window_impl.cpp | 44 +++++ wmserver/BUILD.gn | 3 + wmserver/include/window_inner_manager.h | 75 +++++++ wmserver/include/window_layout_policy.h | 21 +- wmserver/include/window_node_container.h | 21 +- wmserver/include/window_root.h | 5 +- wmserver/include/window_zorder_policy.h | 2 +- wmserver/src/window_controller.cpp | 20 +- wmserver/src/window_inner_manager.cpp | 240 +++++++++++++++++++++++ wmserver/src/window_layout_policy.cpp | 82 +++++--- wmserver/src/window_manager_service.cpp | 4 + wmserver/src/window_node_container.cpp | 74 ++++++- wmserver/src/window_root.cpp | 32 ++- 15 files changed, 590 insertions(+), 41 deletions(-) create mode 100644 wmserver/include/window_inner_manager.h create mode 100644 wmserver/src/window_inner_manager.cpp diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index f281ede7ac..e8c86c984b 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -58,8 +58,9 @@ enum class WindowType : uint32_t { }; enum class WindowMode : uint32_t { - WINDOW_MODE_FULLSCREEN, - WINDOW_MODE_SPLIT_PRIMARY, + WINDOW_MODE_UNDEFINED = 0, + WINDOW_MODE_FULLSCREEN = 1, + WINDOW_MODE_SPLIT_PRIMARY = 100, WINDOW_MODE_SPLIT_SECONDARY, WINDOW_MODE_FLOATING, WINDOW_MODE_PIP diff --git a/wm/include/window_impl.h b/wm/include/window_impl.h index 8e8480bc03..d7a7ac2415 100644 --- a/wm/include/window_impl.h +++ b/wm/include/window_impl.h @@ -19,9 +19,9 @@ #include #include #include -#include "window.h" #include "input_transfer_station.h" #include "vsync_station.h" +#include "window.h" #include "window_property.h" namespace OHOS { @@ -76,6 +76,7 @@ public: void UpdateMode(WindowMode mode); virtual void ConsumeKeyEvent(std::shared_ptr& inputEvent) override; virtual void ConsumePointerEvent(std::shared_ptr& inputEvent) override; + void ConsumeDividerPointerEvent(std::shared_ptr& inputEvent); virtual void RequestFrame() override; void UpdateFocusStatus(bool focused); virtual void UpdateConfiguration(const std::shared_ptr& configuration) override; diff --git a/wm/src/window_impl.cpp b/wm/src/window_impl.cpp index bf2207918e..edf45cabba 100644 --- a/wm/src/window_impl.cpp +++ b/wm/src/window_impl.cpp @@ -14,6 +14,8 @@ */ #include "window_impl.h" + +#include #include "display_manager.h" #include "singleton_container.h" #include "window_adapter.h" @@ -506,8 +508,50 @@ void WindowImpl::ConsumeKeyEvent(std::shared_ptr& keyEvent) } } } + +void WindowImpl::ConsumeDividerPointerEvent(std::shared_ptr& pointerEvent) +{ + static int32_t diffX = 0; + static int32_t diffY = 0; + static bool beginMove = false; + int32_t action = pointerEvent->GetPointerAction(); + MMI::PointerEvent::PointerItem pointerItem; + switch (action) { + case MMI::PointerEvent::POINTER_ACTION_DOWN: { + if (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) { + beginMove = true; + diffX = abs(pointerItem.GetGlobalX() - GetRect().posX_); + diffY = abs(pointerItem.GetGlobalY() - GetRect().posY_); + WLOGFI("point down divider, diff: [%{public}d, %{public}d]", diffX, diffY); + } + break; + } + case MMI::PointerEvent::POINTER_ACTION_MOVE: { + if (beginMove && (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem))) { + int32_t targetX = pointerItem.GetGlobalX() - diffX; + int32_t targetY = pointerItem.GetGlobalY() - diffY; + auto res = MoveTo(targetX, targetY); + if (res != WMError::WM_OK) { + WLOGFE("move divider failed"); + } + } + break; + } + case MMI::PointerEvent::POINTER_ACTION_UP: + case MMI::PointerEvent::POINTER_ACTION_CANCEL: + beginMove = false; + break; + default: + break; + } +} + void WindowImpl::ConsumePointerEvent(std::shared_ptr& pointerEvent) { + if (GetType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + ConsumeDividerPointerEvent(pointerEvent); + return; + } if (uiContent_ == nullptr) { WLOGE("ConsumePointerEvent uiContent is nullptr"); return; diff --git a/wmserver/BUILD.gn b/wmserver/BUILD.gn index 3f9a4e214f..8405f0109d 100644 --- a/wmserver/BUILD.gn +++ b/wmserver/BUILD.gn @@ -46,6 +46,7 @@ ohos_shared_library("libwms") { "../wm/src/zidl/window_manager_agent_proxy.cpp", "src/input_window_monitor.cpp", "src/window_controller.cpp", + "src/window_inner_manager.cpp", "src/window_layout_policy.cpp", "src/window_manager_service.cpp", "src/window_manager_service_inner.cpp", @@ -67,6 +68,7 @@ ohos_shared_library("libwms") { "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", "//foundation/graphic/standard:libsurface", "//foundation/graphic/standard/rosen/modules/render_service_base:librender_service_base", + "//foundation/windowmanager/wm:libwm", "//utils/native/base:utils", ] @@ -78,6 +80,7 @@ ohos_shared_library("libwms") { "//foundation/graphic/standard/rosen/modules/render_service_base:librender_service_base", # RSSurface + "//foundation/ace/ace_engine/build/external_config/flutter/skia:ace_skia_ohos", "//foundation/graphic/standard/rosen/modules/render_service_client:librender_service_client", # IMS diff --git a/wmserver/include/window_inner_manager.h b/wmserver/include/window_inner_manager.h new file mode 100644 index 0000000000..386d54893e --- /dev/null +++ b/wmserver/include/window_inner_manager.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2022 Huawei Device 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. + */ + +#ifndef OHOS_ROSEN_WINDOW_INNER_MANAGER_H +#define OHOS_ROSEN_WINDOW_INNER_MANAGER_H + +#include +#include +#include +#include +#ifdef ACE_ENABLE_GL +#include "render_context/render_context.h" +#endif +#include "single_instance.h" +#include "singleton_delegator.h" +#include "window.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +enum InnerWMCmd : uint32_t { + INNER_WM_CREATE_DIVIDER, + INNER_WM_DESTROY_DIVIDER, + INNER_WM_DESTROY_THREAD, +}; + +struct WindowMessage { + InnerWMCmd cmdType; + uint32_t displayId; + Rect dividerRect; +}; + +class WindowInnerManager { +WM_DECLARE_SINGLE_INSTANCE(WindowInnerManager); +public: + void Init(); + void SendMessage(InnerWMCmd cmdType, uint32_t displayId = 0); + void SendMessage(InnerWMCmd cmdType, uint32_t displayId, const Rect& rect); + void HandleMessage(); +private: + static inline SingletonDelegator delegator; + + sptr CreateWindow(uint32_t displayId, const WindowType& type, const Rect& rect); + void CreateAndShowDivider(); + void HideAndDestroyDivider(); + void DestroyThread(); + void DrawSurface(const sptr& window, uint32_t color); + sptr GetDividerWindow(uint32_t displayId) const; + + std::mutex mutex_; + std::condition_variable conVar_; + bool ready_ = false; +#ifdef ACE_ENABLE_GL + RenderContext* rc_ = nullptr; +#endif + std::map> dividerMap_; + std::unique_ptr winMsg_; + bool hasInitThread_ = false; + bool needDestroyThread_ = false; +}; +} +} +#endif // OHOS_ROSEN_WINDOW_INNER_MANAGER_H diff --git a/wmserver/include/window_layout_policy.h b/wmserver/include/window_layout_policy.h index e24deb6602..a9dc89d352 100644 --- a/wmserver/include/window_layout_policy.h +++ b/wmserver/include/window_layout_policy.h @@ -33,32 +33,43 @@ enum class AvoidPosType : uint32_t { AVOID_POS_UNKNOWN }; +struct LayoutDependRects { + Rect fullRect_ = {0, 0, 0, 0}; + Rect priRect_ = {0, 0, 0, 0}; + Rect secRect_ = {0, 0, 0, 0}; + Rect limitFullRect_ = {0, 0, 0, 0}; + Rect limitPriRect_ = {0, 0, 0, 0}; + Rect limitSecRect_ = {0, 0, 0, 0}; +}; + class WindowLayoutPolicy : public RefBase { public: WindowLayoutPolicy() = default; WindowLayoutPolicy(const sptr& belowAppNode, const sptr& appNode, const sptr& aboveAppNode); ~WindowLayoutPolicy() = default; - void UpdateDisplayInfo(const Rect& displayRect); + void UpdateDisplayInfo(const Rect& primaryRect, const Rect& secondaryRect, const Rect& displayRect); void AddWindowNode(sptr& node); void RemoveWindowNode(sptr& node); void UpdateWindowNode(sptr& node); + void UpdateLayoutRect(sptr& node); private: - Rect displayRect_ = {0, 0, 0, 0}; + LayoutDependRects dependRects; sptr belowAppWindowNode_ = new WindowNode(); sptr appWindowNode_ = new WindowNode(); sptr aboveAppWindowNode_ = new WindowNode(); - Rect limitRect_ = {0, 0, 0, 0}; const std::set avoidTypes_ { WindowType::WINDOW_TYPE_STATUS_BAR, WindowType::WINDOW_TYPE_NAVIGATION_BAR, }; - void UpdateLimitRect(const sptr& node); - void UpdateLayoutRect(sptr& node); + void UpdateLimitRect(const sptr& node, Rect& limitRect); void LayoutWindowTree(); void LayoutWindowNode(sptr& node); AvoidPosType GetAvoidPosType(const Rect& rect); + void InitLimitRects(); + Rect& GetLimitRect(const WindowMode mode); + Rect& GetDisplayRect(const WindowMode mode); }; } } diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index 1f2abb492f..47a2061d60 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -52,6 +52,25 @@ public: sptr GetTopImmersiveNode() const; void NotifySystemBarIfChanged(); std::shared_ptr GetDisplayNode() const; + void LayoutDividerWindow(sptr& node); + void UpdateDisplayInfo(); + + class DisplayRects : public RefBase { + public: + DisplayRects() = default; + ~DisplayRects() = default; + + void InitRect(Rect& oriDisplayRect); + void SetSplitRect(float ratio = 0.5); // 0.5 is the default ratio + void SetSplitRect(const Rect& rect); + Rect GetRectByWindowMode(const WindowMode& mode) const; + Rect GetDividerRect() const; + private: + Rect primaryRect_ = {0, 0, 0, 0}; + Rect secondaryRect_ = {0, 0, 0, 0}; + Rect displayRect_ = {0, 0, 0, 0}; + Rect dividerRect_ = {0, 0, 0, 0}; + }; private: void AssignZOrder(sptr& node); @@ -80,10 +99,10 @@ private: }; uint32_t zOrder_ { 0 }; uint32_t focusedWindow_ { 0 }; - Rect displayRect_; uint64_t screenId_ = 0; WindowNodeContainerCallbacks callbacks_; void DumpScreenWindowTree(); + sptr displayRects_ = new DisplayRects(); }; } } diff --git a/wmserver/include/window_root.h b/wmserver/include/window_root.h index 55f43d75f6..99e659a040 100644 --- a/wmserver/include/window_root.h +++ b/wmserver/include/window_root.h @@ -17,8 +17,9 @@ #include #include -#include "zidl/window_manager_agent_interface.h" +#include "display_manager_service_inner.h" #include "window_node_container.h" +#include "zidl/window_manager_agent_interface.h" namespace OHOS { namespace Rosen { @@ -64,6 +65,7 @@ public: WMError RemoveWindowNode(uint32_t windowId); WMError DestroyWindow(uint32_t windowId); WMError UpdateWindowNode(uint32_t windowId); + WMError LayoutDividerWindow(sptr& node); WMError RequestFocus(uint32_t windowId); WMError MinimizeOtherFullScreenAbility(sptr& node); @@ -83,6 +85,7 @@ private: int32_t displayId, bool focused); void UpdateSystemBarProperties(uint64_t displayId, const SystemBarProps& props); WMError DestroyWindowInner(sptr& node); + bool CheckDisplayInfo(const sptr& display); std::recursive_mutex& mutex_; std::map> windowNodeContainerMap_; diff --git a/wmserver/include/window_zorder_policy.h b/wmserver/include/window_zorder_policy.h index 8e91d3d664..4b41705d25 100644 --- a/wmserver/include/window_zorder_policy.h +++ b/wmserver/include/window_zorder_policy.h @@ -42,7 +42,7 @@ private: // system-specific window { WindowType::WINDOW_TYPE_WALLPAPER, 101 }, { WindowType::WINDOW_TYPE_APP_LAUNCHING, 102 }, - { WindowType::WINDOW_TYPE_DOCK_SLICE, 103 }, + { WindowType::WINDOW_TYPE_DOCK_SLICE, 0 }, { WindowType::WINDOW_TYPE_INCOMING_CALL, 104 }, { WindowType::WINDOW_TYPE_SEARCHING_BAR, 105 }, { WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW, 106 }, diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index ade350d949..b833ac7567 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -106,9 +106,23 @@ WMError WindowController::MoveTo(uint32_t windowId, int32_t x, int32_t y) } auto property = node->GetWindowProperty(); Rect lastRect = property->GetWindowRect(); - Rect newRect = { x, y, lastRect.width_, lastRect.height_ }; - property->SetWindowRect(newRect); - WMError res = windowRoot_->UpdateWindowNode(windowId); + Rect newRect; + WMError res; + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + WLOGFI("Moving divider"); + newRect = { x, lastRect.posY_, lastRect.width_, lastRect.height_ }; + property->SetWindowRect(newRect); + res = windowRoot_->LayoutDividerWindow(node); + if (res != WMError::WM_OK) { + WLOGFE("layout divider window failed"); + return res; + }; + } else { + newRect = { x, y, lastRect.width_, lastRect.height_ }; + property->SetWindowRect(newRect); + } + + res = windowRoot_->UpdateWindowNode(windowId); if (res != WMError::WM_OK) { return res; } diff --git a/wmserver/src/window_inner_manager.cpp b/wmserver/src/window_inner_manager.cpp new file mode 100644 index 0000000000..4f13b95c0c --- /dev/null +++ b/wmserver/src/window_inner_manager.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2022 Huawei Device 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 "window_inner_manager.h" + +#include "include/core/SkCanvas.h" +#include "include/core/SkImageInfo.h" +#include "transaction/rs_transaction.h" +#include "ui/rs_surface_extractor.h" + +#include "window_life_cycle_interface.h" +#include "window_manager_hilog.h" +#include "window_option.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "WindowInnerManager"}; +} + +WM_IMPLEMENT_SINGLE_INSTANCE(WindowInnerManager) + +void WindowInnerManager::DrawSurface(const sptr& window, uint32_t color) +{ + auto surfaceNode = window->GetSurfaceNode(); + auto winRect = window->GetRect(); + WLOGFI("SurfaceWindowDraw winRect, x : %{public}d, y : %{public}d, width: %{public}d, height: %{public}d", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + + auto width = winRect.width_; + auto height = winRect.height_; + + std::shared_ptr rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode); + if (rsSurface == nullptr) { + WLOGFE("RSSurface is nullptr"); + return; + } +#ifdef ACE_ENABLE_GL + rsSurface->SetRenderContext(rc_); +#endif + auto frame = rsSurface->RequestFrame(width, height); + std::unique_ptr framePtr = std::move(frame); + if (!framePtr) { + WLOGFE("DrawSurface frameptr is nullptr"); + return; + } + auto canvas = framePtr->GetCanvas(); + if (!canvas) { + WLOGFE("DrawSurface canvas is nullptr"); + return; + } + SkPaint paint; + paint.setAntiAlias(true); + paint.setStyle(SkPaint::kFill_Style); + const SkScalar skWidth = 20; + paint.setStrokeWidth(skWidth); + paint.setStrokeJoin(SkPaint::kRound_Join); + paint.setColor(color); + + SkPoint rectPts[] = { {0, 0}, {static_cast(width), static_cast(height)} }; + SkRect rect; + rect.set(rectPts[0], rectPts[1]); + + canvas->drawRect(rect, paint); + framePtr->SetDamageRegion(0, 0, width, height); + auto framPtr1 = std::move(framePtr); + rsSurface->FlushFrame(framPtr1); +} + + +sptr WindowInnerManager::GetDividerWindow(uint32_t displayId) const +{ + auto iter = dividerMap_.find(displayId); + if (iter == dividerMap_.end()) { + return nullptr; + } + return iter->second; +} + +sptr WindowInnerManager::CreateWindow(uint32_t displayId, const WindowType& type, const Rect& rect) +{ + sptr window = GetDividerWindow(displayId); + if (window == nullptr) { + sptr divWindowOp = new WindowOption(); + divWindowOp->SetWindowRect(rect); + divWindowOp->SetWindowType(type); + divWindowOp->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + window = Window::Create("divider" + std::to_string(displayId), divWindowOp); + if (window == nullptr) { + WLOGFE("Window is nullptr"); + return nullptr; + } + dividerMap_.insert(std::make_pair(displayId, window)); + WLOGFI("CreateWindow success"); + } + return window; +} + +void WindowInnerManager::CreateAndShowDivider() +{ + auto window = CreateWindow(winMsg_->displayId, WindowType::WINDOW_TYPE_DOCK_SLICE, winMsg_->dividerRect); + if (window == nullptr) { + return; + } + + WMError res = window->Show(); + if (res != WMError::WM_OK) { + WLOGFE("Show window failed"); + return; + } + +#ifdef ACE_ENABLE_GL + // init render context + static bool hasInitRC = false; + if (!hasInitRC) { + rc_ = RenderContextFactory::GetInstance().CreateEngine(); + if (rc_) { + rc_->InitializeEglContext(); + hasInitRC = true; + } else { + WLOGFE("InitilizeEglContext failed"); + return; + } + } +#endif + const uint32_t colorGrey = 0xff808080; + DrawSurface(window, colorGrey); + WLOGFI("CreateAndShowDivider success"); +} + +void WindowInnerManager::HideAndDestroyDivider() +{ + sptr window = GetDividerWindow(winMsg_->displayId); + if (window == nullptr) { + WLOGFE("Window is nullptr"); + return; + } + WMError res = window->Destroy(); + if (res != WMError::WM_OK) { + WLOGFE("Destroy window failed"); + return; + } + dividerMap_.erase(winMsg_->displayId); + WLOGFI("HideAndDestroyDivider success"); +} + +void WindowInnerManager::DestroyThread() +{ + hasInitThread_ = false; + needDestroyThread_ = true; + WLOGFI("DestroyThread success"); +} + +void WindowInnerManager::HandleMessage() +{ + WLOGFI("HandleMessage"); + while (!needDestroyThread_) { + std::unique_lock lk(mutex_); + conVar_.wait(lk, [this] { return ready_; }); + + auto cmdType = winMsg_->cmdType; + using Func_t = void(WindowInnerManager::*)(); + static const std::map funcMap = { + std::make_pair(INNER_WM_CREATE_DIVIDER, &WindowInnerManager::CreateAndShowDivider), + std::make_pair(INNER_WM_DESTROY_DIVIDER, &WindowInnerManager::HideAndDestroyDivider), + std::make_pair(INNER_WM_DESTROY_THREAD, &WindowInnerManager::DestroyThread) + }; + auto it = funcMap.find(cmdType); + if (it != funcMap.end()) { + (this->*(it->second))(); + } + ready_ = false; + } +} + +void WindowInnerManager::SendMessage(InnerWMCmd cmdType, uint32_t displayId) +{ + std::unique_lock lk(mutex_); + if (!hasInitThread_) { + WLOGFI("Inner window manager thread has not been created"); + return; + } + winMsg_->cmdType = cmdType; + winMsg_->displayId = displayId; + + ready_ = true; + conVar_.notify_one(); + + WLOGFI("SendMessage : displayId = %{public}d, type = %{public}d", + winMsg_->displayId, static_cast(cmdType)); +} + +void WindowInnerManager::SendMessage(InnerWMCmd cmdType, uint32_t displayId, const Rect& dividerRect) +{ + std::unique_lock lk(mutex_); + if (!hasInitThread_) { + WLOGFI("Inner window manager thread has not been created"); + return; + } + winMsg_->cmdType = cmdType; + winMsg_->displayId = displayId; + winMsg_->dividerRect = dividerRect; + + ready_ = true; + conVar_.notify_one(); + + WLOGFI("SendMessage : displayId = %{public}d, type = %{public}d" \ + " Rect = [%{public}d %{public}d %{public}d %{public}d]", + winMsg_->displayId, static_cast(cmdType), + winMsg_->dividerRect.posX_, winMsg_->dividerRect.posY_, + winMsg_->dividerRect.width_, winMsg_->dividerRect.height_); +} + + +void WindowInnerManager::Init() +{ + std::unique_lock lk(mutex_); + needDestroyThread_ = false; + winMsg_ = std::make_unique(); + + // create inner thread + std::thread innerWMThread(&WindowInnerManager::HandleMessage, this); + innerWMThread.detach(); + hasInitThread_ = true; + WLOGFI("Inner window manager thread create success"); +} +} +} \ No newline at end of file diff --git a/wmserver/src/window_layout_policy.cpp b/wmserver/src/window_layout_policy.cpp index b9c1b6ab54..92fe42c7c5 100644 --- a/wmserver/src/window_layout_policy.cpp +++ b/wmserver/src/window_layout_policy.cpp @@ -32,15 +32,19 @@ WindowLayoutPolicy::WindowLayoutPolicy(const sptr& belowAppNode, aboveAppWindowNode_ = aboveAppNode; } -void WindowLayoutPolicy::UpdateDisplayInfo(const Rect& displayRect) +void WindowLayoutPolicy::UpdateDisplayInfo(const Rect& primaryRect, + const Rect& secondaryRect, + const Rect& displayRect) { - displayRect_ = displayRect; - limitRect_ = displayRect_; + dependRects.priRect_ = primaryRect; + dependRects.secRect_ = secondaryRect; + dependRects.fullRect_ = displayRect; + InitLimitRects(); } void WindowLayoutPolicy::LayoutWindowTree() { - limitRect_ = displayRect_; + InitLimitRects(); std::vector> rootNodes = { aboveAppWindowNode_, appWindowNode_, belowAppWindowNode_ }; for (auto& node : rootNodes) { // ensure that the avoid area windows are traversed first LayoutWindowNode(node); @@ -59,7 +63,9 @@ void WindowLayoutPolicy::LayoutWindowNode(sptr& node) } UpdateLayoutRect(node); if (avoidTypes_.find(node->GetWindowType()) != avoidTypes_.end()) { - UpdateLimitRect(node); + UpdateLimitRect(node, dependRects.limitPriRect_); + UpdateLimitRect(node, dependRects.limitSecRect_); + UpdateLimitRect(node, dependRects.limitFullRect_); } } for (auto& childNode : node->children_) { @@ -117,16 +123,18 @@ void WindowLayoutPolicy::UpdateLayoutRect(sptr& node) bool floatingWindow = (mode == WindowMode::WINDOW_MODE_FLOATING); const Rect& layoutRect = node->GetLayoutRect(); Rect lastRect = layoutRect; - Rect limitRect = displayRect_; + Rect displayRect = GetDisplayRect(mode); + Rect limitRect = displayRect; Rect winRect = node->GetWindowProperty()->GetWindowRect(); + WLOGFI("Id:%{public}d, avoid:%{public}d parLimit:%{public}d floating:%{public}d, sub:%{public}d," \ "type:%{public}d, requestRect:[%{public}d, %{public}d, %{public}d, %{public}d]", node->GetWindowId(), needAvoid, parentLimit, floatingWindow, subWindow, static_cast(type), winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); - if (needAvoid) { - limitRect = limitRect_; + limitRect = GetLimitRect(mode); } + if (!floatingWindow) { // fullscreen window winRect = limitRect; } else { // floating window @@ -145,10 +153,11 @@ void WindowLayoutPolicy::UpdateLayoutRect(sptr& node) } } // Limit window to the maximum window size - winRect.width_ = std::min(displayRect_.width_, winRect.width_); - winRect.height_ = std::min(displayRect_.height_, winRect.height_); + winRect.width_ = std::min(displayRect.width_, winRect.width_); + winRect.height_ = std::min(displayRect.height_, winRect.height_); winRect.width_ = std::max(1u, winRect.width_); winRect.height_ = std::max(1u, winRect.height_); + node->SetLayoutRect(winRect); if (IsLayoutChanged(lastRect, winRect)) { node->GetWindowToken()->UpdateWindowRect(winRect); @@ -174,7 +183,36 @@ AvoidPosType WindowLayoutPolicy::GetAvoidPosType(const Rect& rect) return AvoidPosType::AVOID_POS_UNKNOWN; } -void WindowLayoutPolicy::UpdateLimitRect(const sptr& node) +void WindowLayoutPolicy::InitLimitRects() +{ + dependRects.limitPriRect_ = dependRects.priRect_; + dependRects.limitSecRect_ = dependRects.secRect_; + dependRects.limitFullRect_ = dependRects.fullRect_; +} + +Rect& WindowLayoutPolicy::GetLimitRect(const WindowMode mode) +{ + if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) { + return dependRects.limitPriRect_; + } else if (mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + return dependRects.limitSecRect_; + } else { + return dependRects.limitFullRect_; + } +} + +Rect& WindowLayoutPolicy::GetDisplayRect(const WindowMode mode) +{ + if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) { + return dependRects.priRect_; + } else if (mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + return dependRects.secRect_; + } else { + return dependRects.fullRect_; + } +} + +void WindowLayoutPolicy::UpdateLimitRect(const sptr& node, Rect& limitRect) { auto& layoutRect = node->GetLayoutRect(); if (node->GetWindowType() == WindowType::WINDOW_TYPE_STATUS_BAR || @@ -184,29 +222,29 @@ void WindowLayoutPolicy::UpdateLimitRect(const sptr& node) int32_t offsetW = 0; switch (avoidPosType) { case AvoidPosType::AVOID_POS_TOP: - offsetH = layoutRect.posY_ + layoutRect.height_ - limitRect_.posY_; - limitRect_.posY_ += offsetH; - limitRect_.height_ -= offsetH; + offsetH = layoutRect.posY_ + layoutRect.height_ - limitRect.posY_; + limitRect.posY_ += offsetH; + limitRect.height_ -= offsetH; break; case AvoidPosType::AVOID_POS_BOTTOM: - offsetH = limitRect_.posY_ + limitRect_.height_ - layoutRect.posY_; - limitRect_.height_ -= offsetH; + offsetH = limitRect.posY_ + limitRect.height_ - layoutRect.posY_; + limitRect.height_ -= offsetH; break; case AvoidPosType::AVOID_POS_LEFT: - offsetW = layoutRect.posX_ + layoutRect.width_ - limitRect_.posX_; - limitRect_.posX_ += offsetW; - limitRect_.width_ -= offsetW; + offsetW = layoutRect.posX_ + layoutRect.width_ - limitRect.posX_; + limitRect.posX_ += offsetW; + limitRect.width_ -= offsetW; break; case AvoidPosType::AVOID_POS_RIGHT: - offsetW = limitRect_.posX_ + limitRect_.width_ - layoutRect.posX_; - limitRect_.width_ -= offsetW; + offsetW = limitRect.posX_ + limitRect.width_ - layoutRect.posX_; + limitRect.width_ -= offsetW; break; default: WLOGFE("invaild avoidPosType: %{public}d", avoidPosType); } } WLOGFI("Type: %{public}d, limitRect: %{public}d %{public}d %{public}d %{public}d", - node->GetWindowType(), limitRect_.posX_, limitRect_.posY_, limitRect_.width_, limitRect_.height_); + node->GetWindowType(), limitRect.posX_, limitRect.posY_, limitRect.width_, limitRect.height_); } } } diff --git a/wmserver/src/window_manager_service.cpp b/wmserver/src/window_manager_service.cpp index 2d0b79fc63..ef1cdb5e2b 100644 --- a/wmserver/src/window_manager_service.cpp +++ b/wmserver/src/window_manager_service.cpp @@ -22,6 +22,8 @@ #include #include "dm_common.h" +#include "singleton_container.h" +#include "window_inner_manager.h" #include "window_manager_hilog.h" #include "wm_trace.h" @@ -50,6 +52,7 @@ void WindowManagerService::OnStart() return; } RegisterSnapshotHandler(); + SingletonContainer::Get().Init(); } void WindowManagerService::RegisterSnapshotHandler() @@ -75,6 +78,7 @@ bool WindowManagerService::Init() void WindowManagerService::OnStop() { + SingletonContainer::Get().SendMessage(INNER_WM_DESTROY_THREAD); WLOGFI("ready to stop service."); } diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index 96d5291385..02cbf5bc6b 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -20,6 +20,7 @@ #include #include "window_helper.h" +#include "window_inner_manager.h" #include "window_manager_hilog.h" #include "wm_trace.h" @@ -35,13 +36,14 @@ WindowNodeContainer::WindowNodeContainer(uint64_t screenId, uint32_t width, uint { struct RSDisplayNodeConfig config = {screenId}; displayNode_ = RSDisplayNode::Create(config); - displayRect_ = { + Rect displayRect = { .posX_ = 0, .posY_ = 0, .width_ = width, .height_ = height }; - layoutPolicy_->UpdateDisplayInfo(displayRect_); + displayRects_->InitRect(displayRect); + UpdateDisplayInfo(); } WindowNodeContainer::~WindowNodeContainer() @@ -229,7 +231,7 @@ const std::vector& WindowNodeContainer::Destroy() sptr WindowNodeContainer::FindRoot(WindowType type) const { - if (WindowHelper::IsAppWindow(type)) { + if (WindowHelper::IsAppWindow(type) || type == WindowType::WINDOW_TYPE_DOCK_SLICE) { return appWindowNode_; } if (WindowHelper::IsBelowSystemWindow(type)) { @@ -432,6 +434,70 @@ void WindowNodeContainer::TraverseWindowNode(sptr& node, std::vector } } +void WindowNodeContainer::UpdateDisplayInfo() +{ + const Rect& primaryRect = displayRects_->GetRectByWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + const Rect& secondaryRect = displayRects_->GetRectByWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + const Rect& displayRect = displayRects_->GetRectByWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + layoutPolicy_->UpdateDisplayInfo(primaryRect, secondaryRect, displayRect); +} + +void WindowNodeContainer::LayoutDividerWindow(sptr& node) +{ + layoutPolicy_->UpdateLayoutRect(node); + auto layoutRect = node->GetLayoutRect(); + displayRects_->SetSplitRect(layoutRect); // calculate primary/secondary depend on divider rect + UpdateDisplayInfo(); + WLOGFI("UpdateDividerRects WinId: %{public}d, Rect: %{public}d %{public}d %{public}d %{public}d", + node->GetWindowId(), layoutRect.posX_, layoutRect.posY_, layoutRect.width_, layoutRect.height_); +} + +void WindowNodeContainer::DisplayRects::InitRect(Rect& oriDisplayRect) +{ + displayRect_ = oriDisplayRect; + + const uint32_t dividerWidth = 200; + dividerRect_ = { static_cast((displayRect_.width_ - dividerWidth) * 0.5), 0, // default ratio : 0.5 + dividerWidth, displayRect_.height_ }; + + SetSplitRect(dividerRect_); +} + +void WindowNodeContainer::DisplayRects::SetSplitRect(float ratio) +{ + dividerRect_.posX_ = static_cast((displayRect_.width_ - dividerRect_.width_) * ratio); + SetSplitRect(dividerRect_); +} + +void WindowNodeContainer::DisplayRects::SetSplitRect(const Rect& divRect) +{ + dividerRect_.width_ = divRect.width_; + dividerRect_.height_ = divRect.height_; + + primaryRect_.width_ = divRect.posX_; + primaryRect_.height_ = displayRect_.height_; + + secondaryRect_.posX_ = divRect.posX_ + dividerRect_.width_; + secondaryRect_.width_ = displayRect_.width_ - secondaryRect_.posX_; + secondaryRect_.height_ = displayRect_.height_; +} + +Rect WindowNodeContainer::DisplayRects::GetDividerRect() const +{ + return dividerRect_; +} + +Rect WindowNodeContainer::DisplayRects::GetRectByWindowMode(const WindowMode& mode) const +{ + if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) { + return primaryRect_; + } else if (mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + return secondaryRect_; + } else { + return displayRect_; + } +} + void WindowNodeContainer::DumpScreenWindowTree() { WLOGFI("-------- Screen %{public}" PRIu64" dump window info begin---------", screenId_); @@ -455,7 +521,7 @@ uint64_t WindowNodeContainer::GetScreenId() const Rect WindowNodeContainer::GetDisplayRect() const { - return displayRect_; + return displayRects_->GetRectByWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); } std::shared_ptr WindowNodeContainer::GetDisplayNode() const diff --git a/wmserver/src/window_root.cpp b/wmserver/src/window_root.cpp index eb1c2be83f..b724c8a1ee 100644 --- a/wmserver/src/window_root.cpp +++ b/wmserver/src/window_root.cpp @@ -31,11 +31,17 @@ sptr WindowRoot::GetOrCreateWindowNodeContainer(int32_t dis if (iter != windowNodeContainerMap_.end()) { return iter->second; } - auto abstractDisplay = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId); + const sptr abstractDisplay = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId); if (abstractDisplay == nullptr) { WLOGFE("get display failed displayId:%{public}d", displayId); return nullptr; } + + if (!CheckDisplayInfo(abstractDisplay)) { + WLOGFE("get display invailed infp:%{public}d", displayId); + return nullptr; + } + WLOGFI("create new window node container display width:%{public}d, height:%{public}d, screenId:%{public}" PRIu64"", abstractDisplay->GetWidth(), abstractDisplay->GetHeight(), abstractDisplay->GetId()); @@ -54,6 +60,19 @@ sptr WindowRoot::GetOrCreateWindowNodeContainer(int32_t dis return container; } +bool WindowRoot::CheckDisplayInfo(const sptr& display) +{ + const int32_t minWidth = 50; + const int32_t minHeight = 50; + const int32_t maxWidth = 7680; + const int32_t maxHeight = 7680; // 8k resolution + if (display->GetWidth() < minWidth || display->GetWidth() > maxWidth || + display->GetHeight() < minHeight || display->GetHeight() > maxHeight) { + return false; + } + return true; +} + void WindowRoot::NotifyDisplayRemoved(int32_t displayId) { auto container = GetOrCreateWindowNodeContainer(displayId); @@ -202,6 +221,17 @@ WMError WindowRoot::DestroyWindowInner(sptr& node) return WMError::WM_OK; } +WMError WindowRoot::LayoutDividerWindow(sptr& node) +{ + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("layout divider window failed, window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + container->LayoutDividerWindow(node); + return WMError::WM_OK; +} + WMError WindowRoot::RequestFocus(uint32_t windowId) { auto node = GetWindowNode(windowId); -- Gitee