split window componentization

Signed-off-by: xingyanan <xingyanan2@huawei.com>
Change-Id: I7b2d17ad5edfd668f08f9eda750d8cf5da24280e
Signed-off-by: xingyanan <xingyanan2@huawei.com>
This commit is contained in:
xingyanan 2022-06-01 19:16:55 +08:00
parent f46ad2632e
commit 8caa461a3e
36 changed files with 526 additions and 463 deletions

View File

@ -59,7 +59,8 @@
"//foundation/windowmanager/utils:libwmutil",
"//foundation/windowmanager/snapshot:snapshot_display",
"//foundation/windowmanager/interfaces/kits/napi/window_runtime/window_stage_napi:windowstage",
"//foundation/windowmanager/interfaces/kits/napi:napi_packages"
"//foundation/windowmanager/interfaces/kits/napi:napi_packages",
"//foundation/windowmanager/resources:window_resources"
],
"inner_kits": [
{

View File

@ -21,21 +21,6 @@ config("libdms_private_config") {
]
}
ohos_prebuilt_etc("display_manager_config") {
if (device_name == "rk3568") {
source =
"//foundation/windowmanager/resources/rk3568/display_manager_config.xml"
install_enable = true
} else {
source =
"//foundation/windowmanager/resources/other/display_manager_config.xml"
install_enable = false
}
part_name = "window_manager"
subsystem_name = "window"
relative_install_dir = "window/resources"
}
config("libdms_public_config") {
include_dirs = [ "include" ]
}
@ -60,7 +45,6 @@ ohos_shared_library("libdms") {
public_configs = [ ":libdms_public_config" ]
deps = [
":display_manager_config",
"//foundation/windowmanager/dm:libdm",
"//foundation/windowmanager/utils:libwmutil",

View File

@ -23,6 +23,7 @@ enum class WindowType : uint32_t {
APP_WINDOW_BASE = 1,
APP_MAIN_WINDOW_BASE = APP_WINDOW_BASE,
WINDOW_TYPE_APP_MAIN_WINDOW = APP_MAIN_WINDOW_BASE,
WINDOW_TYPE_PLACE_HOLDER,
APP_MAIN_WINDOW_END,
APP_SUB_WINDOW_BASE = 1000,
@ -60,7 +61,6 @@ enum class WindowType : uint32_t {
WINDOW_TYPE_FREEZE_DISPLAY,
WINDOW_TYPE_VOICE_INTERACTION,
ABOVE_APP_SYSTEM_WINDOW_END,
SYSTEM_WINDOW_END = ABOVE_APP_SYSTEM_WINDOW_END,
};

20
resources/BUILD.gn Normal file
View File

@ -0,0 +1,20 @@
# 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.
group("window_resources") {
deps = [
"config:window_config",
"dialog_ui:dialog_ui",
"media:window_resources_media",
]
}

46
resources/config/BUILD.gn Normal file
View File

@ -0,0 +1,46 @@
# 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.
import("//build/ohos.gni")
ohos_prebuilt_etc("window_manager_config") {
if (device_name == "rk3568") {
source = "//foundation/windowmanager/resources/config/rk3568/window_manager_config.xml"
install_enable = true
} else {
source = "//foundation/windowmanager/resources/config/other/window_manager_config.xml"
install_enable = false
}
part_name = "window_manager"
subsystem_name = "window"
relative_install_dir = "window/resources"
}
ohos_prebuilt_etc("display_manager_config") {
if (device_name == "rk3568") {
source = "//foundation/windowmanager/resources/config/rk3568/display_manager_config.xml"
install_enable = true
} else {
source = "//foundation/windowmanager/resources/config/other/display_manager_config.xml"
install_enable = false
}
part_name = "window_manager"
subsystem_name = "window"
relative_install_dir = "window/resources"
}
group("window_config") {
deps = [
":display_manager_config",
":window_manager_config",
]
}

View File

@ -0,0 +1,16 @@
# 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.
group("dialog_ui") {
deps = [ "divider_dialog_ui/js:dialog_divider_ui_js_files_etc" ]
}

View File

@ -0,0 +1,27 @@
# 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.
import("//build/ohos.gni")
import("//foundation/arkui/ace_engine/build/ace_gen_sa_dialog_js.gni")
gen_sa_dialog_js("dialog_divider_ui_js_files_etc") {
project_path =
"//foundation/windowmanager/resources/dialog_ui/divider_dialog_ui/js"
i18n_files = [
"i18n/en-US.json",
"i18n/zh-CN.json",
]
common_files = []
dialog_name = "dialog_divider_ui"
part_name = "window_manager"
subsystem_name = "window"
}

View File

@ -0,0 +1,8 @@
{
"message": {
},
"color": {
"gray": "gray",
"black": "black"
}
}

View File

@ -0,0 +1,4 @@
{
"message": {
}
}

View File

@ -0,0 +1,43 @@
/*
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.
*/
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.divider-button {
flex-direction: row;
justify-content: space-around;
background-color: whitesmoke;
}
@media screen and (device-type: phone) or (orientation: portrait) {
.divider-button {
width: 10%;
height: 90%;
}
}
@media screen and (device-type: tablet) or (orientation: landscape) {
.divider-button {
width: 90%;
height: 10%;
}
}

View File

@ -0,0 +1,23 @@
<!--
/*
* 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.
*/
-->
<div class="container" style="background-color: {{ backgroundColor }}"
ontouchend="onTouchEnd" ontouchstart="onTouching">
<button class="divider-button" onclick="onExchange" ondoubleclick="onExchangeDoubleClick"
click-effect="spring-small">
</button>
</div>

View File

@ -0,0 +1,49 @@
/*
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.
*/
import router from '@ohos.router'
import window from '@ohos.window';
export default {
data: {
backgroundColor:"black"
},
onInit() {
callNativeHandler("EVENT_INIT", "");
},
onCancel() {
callNativeHandler("EVENT_CANCEL", "");
},
onExit() {
callNativeHandler("EVENT_CANCEL", "");
},
onExchange() {
},
onExchangeDoubleClick() {
console.info('double click exchange');
},
onFocus(){
this.backgroundColor = "black"
},
recoveryColor(){
this.backgroundColor = "gray"
},
onTouching(){
this.backgroundColor = "gray"
},
onTouchEnd(){
this.backgroundColor = "black"
}
}

24
resources/media/BUILD.gn Normal file
View File

@ -0,0 +1,24 @@
# 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.
import("//build/ohos.gni")
ohos_prebuilt_etc("window_divider_image") {
source = "//foundation/windowmanager/resources/media/img/bg_split_handle.png"
part_name = "window_manager"
subsystem_name = "window"
relative_install_dir = "window/resources"
}
group("window_resources_media") {
deps = [ ":window_divider_image" ]
}

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View File

@ -129,6 +129,7 @@ namespace {
constexpr uint32_t MIN_HORIZONTAL_SPLIT_WIDTH = 320;
constexpr uint32_t MAX_FLOATING_SIZE = 2560;
const std::string WINDOW_MANAGER_CONFIG_XML = "/system/etc/window/resources/window_manager_config.xml";
const Rect IVALID_EMPTY_RECT = {0, 0, 0, 0};
}
}
}

View File

@ -2059,6 +2059,16 @@ void WindowImpl::SetDefaultOption()
property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
break;
}
case WindowType::WINDOW_TYPE_DOCK_SLICE: {
property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
property_->SetFocusable(false);
break;
}
case WindowType::WINDOW_TYPE_PLACE_HOLDER: {
AddWindowFlag(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE);
property_->SetFocusable(false);
break;
}
default:
break;
}

View File

@ -59,6 +59,12 @@ void WindowInputChannel::HandlePointerEvent(std::shared_ptr<MMI::PointerEvent>&
return;
}
if (inputListener_ != nullptr) {
// divider window consumes pointer events directly
if (window_->GetType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
window_->ConsumePointerEvent(pointerEvent);
inputListener_->OnInputEvent(pointerEvent);
return;
}
int32_t action = pointerEvent->GetPointerAction();
if (action == MMI::PointerEvent::POINTER_ACTION_DOWN ||
action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {

View File

@ -35,35 +35,6 @@ config("libwms_config") {
defines += gpu_defines
}
ohos_prebuilt_etc("window_divider_image") {
source = "//foundation/windowmanager/resources/bg_split_handle.png"
part_name = "window_manager"
subsystem_name = "window"
relative_install_dir = "window/resources"
}
ohos_prebuilt_etc("window_manager_config") {
if (device_name == "rk3568") {
source =
"//foundation/windowmanager/resources/rk3568/window_manager_config.xml"
install_enable = true
} else {
source =
"//foundation/windowmanager/resources/other/window_manager_config.xml"
install_enable = false
}
part_name = "window_manager"
subsystem_name = "window"
relative_install_dir = "window/resources"
}
ohos_prebuilt_etc("window_starting_image") {
source = "//foundation/windowmanager/resources/starting_window.png"
part_name = "window_manager"
subsystem_name = "window"
relative_install_dir = "window/resources"
}
ohos_shared_library("libwms") {
sources = [
"../wm/src/zidl/window_manager_agent_proxy.cpp",
@ -101,9 +72,7 @@ ohos_shared_library("libwms") {
configs = [ ":libwms_config" ]
deps = [
":window_divider_image",
":window_manager_config",
":window_starting_image",
"//foundation/arkui/ace_engine/interfaces/inner_api/ui_service_manager:ui_service_mgr",
"//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client",
"//foundation/windowmanager/dm:libdm",
"//foundation/windowmanager/dmserver:libdms",

View File

@ -53,6 +53,7 @@ public:
const std::map<DisplayId, Rect>& displayRectMap,
DisplayStateChangeType type);
sptr<WindowPair> GetWindowPairByDisplayId(DisplayId displayId);
void SetInitalDividerRect(DisplayId displayId, const Rect& rect);
DisplayGroupWindowTree displayGroupWindowTree_;
std::map<DisplayId, SysBarNodeMap> sysBarNodeMaps_;

View File

@ -1,85 +1,60 @@
/*
* Copyright (c) 2021-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 <condition_variable>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
#include "include/core/SkBitmap.h"
#ifdef ACE_ENABLE_GL
#include "render_context/render_context.h"
#endif
#include "transaction/rs_transaction.h"
#include "ui/rs_surface_extractor.h"
#include "wm_single_instance.h"
#include "singleton_delegator.h"
#include "window.h"
#include "wm_common.h"
namespace OHOS {
namespace Rosen {
enum class InnerWMCmd : uint32_t {
INNER_WM_CREATE_DIVIDER,
INNER_WM_DESTROY_DIVIDER,
INNER_WM_DESTROY_THREAD,
};
struct WindowInnerMessage {
InnerWMCmd cmdType;
DisplayId displayId;
Rect dividerRect;
};
class WindowInnerManager {
WM_DECLARE_SINGLE_INSTANCE(WindowInnerManager);
public:
void Init();
void SendMessage(InnerWMCmd cmdType, DisplayId displayId = 0);
private:
static inline SingletonDelegator<WindowInnerManager> delegator;
void HandleMessage();
sptr<Window> CreateWindow(DisplayId displayId, const WindowType& type, const Rect& rect);
void CreateAndShowDivider(std::unique_ptr<WindowInnerMessage> msg);
void HideAndDestroyDivider(std::unique_ptr<WindowInnerMessage> msg);
void DestroyThread(std::unique_ptr<WindowInnerMessage> msg);
void DrawSurface(const sptr<Window>& window);
void DrawColor(std::shared_ptr<RSSurface>& rsSurface, uint32_t width, uint32_t height);
void DrawBitmap(std::shared_ptr<RSSurface>& rsSurface, uint32_t width, uint32_t height);
sptr<Window> GetDividerWindow(DisplayId displayId) const;
bool DecodeImageFile(const char* filename, SkBitmap& bitmap);
std::mutex mutex_;
std::condition_variable conVar_;
bool ready_ = false;
#ifdef ACE_ENABLE_GL
std::unique_ptr<RenderContext> renderContext_;
#endif
std::map<uint32_t, sptr<Window>> dividerMap_;
std::vector<std::unique_ptr<WindowInnerMessage>> messages_;
bool hasInitThread_ = false;
bool needDestroyThread_ = false;
bool isDividerImageLoaded_ = false;
const char *splitIconPath_ = "/etc/window/resources/bg_split_handle.png";
uint32_t DIVIDER_HANDLE_COLOR = 0xff808080; // gray
SkBitmap dividerBitmap_;
};
}
}
#endif // OHOS_ROSEN_WINDOW_INNER_MANAGER_H
/*
* 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 <refbase.h>
#include "event_handler.h"
#include "event_runner.h"
#include "wm_common.h"
#include "wm_single_instance.h"
namespace OHOS {
namespace Rosen {
class WindowInnerManager : public RefBase {
WM_DECLARE_SINGLE_INSTANCE_BASE(WindowInnerManager);
using EventRunner = OHOS::AppExecFwk::EventRunner;
using EventHandler = OHOS::AppExecFwk::EventHandler;
public:
void Start();
void Stop();
void CreateWindow(std::string name, WindowType type, Rect rect);
void DestroyWindow();
public:
enum class InnerWMRunningState {
STATE_NOT_START,
STATE_RUNNING,
};
~WindowInnerManager();
private:
WindowInnerManager();
bool Init();
void HandleCreateWindow(std::string name, WindowType type, Rect rect);
void HandleDestroyWindow();
private:
int32_t dialogId_ = -1;
std::shared_ptr<EventHandler> eventHandler_;
std::shared_ptr<EventRunner> eventLoop_;
InnerWMRunningState state_;
std::string dividerParams_ = "";
const std::string INNER_WM_THREAD_NAME = "inner_window_manager";
};
} // namespace Rosen
} // namespace OHOS
#endif // OHOS_ROSEN_WINDOW_INNER_MANAGER_H

View File

@ -52,6 +52,7 @@ public:
virtual void UpdateWindowNode(const sptr<WindowNode>& node, bool isAddWindow = false);
virtual void UpdateLayoutRect(const sptr<WindowNode>& node) = 0;
virtual void SetSplitDividerWindowRects(std::map<DisplayId, Rect> dividerWindowRects) {};
virtual Rect GetInitalDividerRect(DisplayId displayId) const;
float GetVirtualPixelRatio(DisplayId displayId) const;
void UpdateClientRectAndResetReason(const sptr<WindowNode>& node, const Rect& lastLayoutRect, const Rect& winRect);
Rect GetDisplayGroupRect() const;
@ -101,6 +102,14 @@ protected:
WindowType::WINDOW_TYPE_STATUS_BAR,
WindowType::WINDOW_TYPE_NAVIGATION_BAR,
};
struct LayoutRects {
Rect primaryRect_;
Rect secondaryRect_;
Rect primaryLimitRect_;
Rect secondaryLimitRect_;
Rect dividerRect_;
Rect firstCascadeRect_;
};
sptr<DisplayGroupInfo> displayGroupInfo_;
mutable std::map<DisplayId, Rect> limitRectMap_;
DisplayGroupWindowTree& displayGroupWindowTree_;

View File

@ -41,6 +41,7 @@ public:
void UpdateLayoutRect(const sptr<WindowNode>& node) override;
void SetSplitDividerWindowRects(std::map<DisplayId, Rect> dividerWindowRects) override;
void RemoveWindowNode(const sptr<WindowNode>& node) override;
Rect GetInitalDividerRect(DisplayId displayId) const override;
private:
void InitAllRects();
@ -70,7 +71,7 @@ private:
Rect dividerRect_;
Rect firstCascadeRect_;
};
mutable std::map<DisplayId, CascadeRects> cascadeRectsMap_;
mutable std::map<DisplayId, LayoutRects> cascadeRectsMap_;
std::map<DisplayId, Rect> restoringDividerWindowRects_;
};
}

View File

@ -167,6 +167,8 @@ public:
*/
void SetAllAppWindowsRestoring(bool isAllAppWindowsRestoring);
void SetInitalDividerRect(const Rect& rect);
private:
/**
* Gets whether the window is related to split window.
@ -207,14 +209,6 @@ private:
*/
void DumpPairInfo();
/**
* Send inner window message.
*
* @param cmd the message of inner window manager
* @param displayId the id of target display
*/
void SendInnerMessage(InnerWMCmd cmd, DisplayId displayId);
/**
* Find pairable window frome window trees.
*
@ -248,6 +242,7 @@ private:
WindowPairStatus status_ = {WindowPairStatus::STATUS_EMPTY};
DisplayGroupWindowTree& displayGroupWindowTree_;
bool isAllAppWindowsRestoring_ { false };
Rect initalDivderRect_ {0, 0, 0, 0};
};
} // namespace Rosen
} // namespace OHOS

View File

@ -38,6 +38,7 @@ private:
// main window
{ WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, 0 },
{ WindowType::WINDOW_TYPE_PLACE_HOLDER, 0 },
// system-specific window
{ WindowType::WINDOW_TYPE_WALLPAPER, 0 },

View File

@ -364,14 +364,12 @@ void DisplayGroupController::ProcessDisplayCreate(DisplayId displayId,
auto displayInfo = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId);
displayGroupInfo_->AddDisplayInfo(displayInfo);
// create new window pair for split window
auto windowPair = new WindowPair(displayId, displayGroupWindowTree_);
windowPairMap_.insert(std::make_pair(displayId, windowPair));
// modify RSTree and window tree of displayGroup for cross-display nodes
ProcessCrossNodes(DisplayStateChangeType::CREATE);
UpdateDisplayGroupWindowTree();
windowNodeContainer_->GetLayoutPolicy()->ProcessDisplayCreate(displayId, displayRectMap);
Rect initialDividerRect = windowNodeContainer_->GetLayoutPolicy()->GetInitalDividerRect(displayId);
SetInitalDividerRect(displayId, initialDividerRect);
}
void DisplayGroupController::ProcessDisplayDestroy(DisplayId displayId,
@ -440,5 +438,12 @@ sptr<WindowPair> DisplayGroupController::GetWindowPairByDisplayId(DisplayId disp
}
return nullptr;
}
void DisplayGroupController::SetInitalDividerRect(DisplayId displayId, const Rect& rect)
{
if (windowPairMap_.find(displayId) != windowPairMap_.end()) {
windowPairMap_[displayId]->SetInitalDividerRect(rect);
}
}
} // namespace Rosen
} // namespace OHOS

View File

@ -1,303 +1,127 @@
/*
* Copyright (c) 2021-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 <cinttypes>
#include "include/core/SkCanvas.h"
#include "include/codec/SkCodec.h"
#include "include/core/SkData.h"
#include "include/core/SkImage.h"
#include "vsync_station.h"
#include "window_manager_hilog.h"
#include "window_option.h"
namespace OHOS {
namespace Rosen {
namespace {
constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowInnerManager"};
}
WM_IMPLEMENT_SINGLE_INSTANCE(WindowInnerManager)
bool WindowInnerManager::DecodeImageFile(const char* filename, SkBitmap& bitmap)
{
sk_sp<SkData> data(SkData::MakeFromFileName(filename));
std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(std::move(data));
if (codec == nullptr) {
return false;
}
SkColorType colorType = kN32_SkColorType;
SkImageInfo info = codec->getInfo().makeColorType(colorType);
if (!bitmap.tryAllocPixels(info)) {
return false;
}
return SkCodec::kSuccess == codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes());
}
void WindowInnerManager::DrawSurface(const sptr<Window>& window)
{
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> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
if (rsSurface == nullptr) {
WLOGFE("RSSurface is nullptr");
return;
}
#ifdef ACE_ENABLE_GL
rsSurface->SetRenderContext(renderContext_.get());
#endif
if (!isDividerImageLoaded_) {
isDividerImageLoaded_ = DecodeImageFile(splitIconPath_, dividerBitmap_);
}
if (!dividerBitmap_.isNull() && dividerBitmap_.width() != 0 && dividerBitmap_.height() != 0) {
DrawBitmap(rsSurface, width, height);
} else {
DrawColor(rsSurface, width, height);
}
}
void WindowInnerManager::DrawBitmap(std::shared_ptr<RSSurface>& rsSurface, uint32_t width, uint32_t height)
{
std::unique_ptr<RSSurfaceFrame> frame = rsSurface->RequestFrame(width, height);
if (frame == nullptr) {
WLOGFE("DrawBitmap frameptr is nullptr");
return;
}
auto canvas = frame->GetCanvas();
if (canvas == nullptr) {
WLOGFE("DrawBitmap canvas is nullptr");
return;
}
canvas->clear(SK_ColorTRANSPARENT);
SkPaint paint;
SkMatrix matrix;
SkRect rect;
rect.set(0, 0, static_cast<int>(width), static_cast<int>(height));
if (dividerBitmap_.width() != 0 && dividerBitmap_.height() != 0) {
if (width > height) {
// rotate when divider is horizontal
matrix.setScale(static_cast<float>(height) / dividerBitmap_.width(),
static_cast<float>(width) / dividerBitmap_.height());
matrix.postRotate(-90.0f); // divider shader rotate -90.0
} else {
matrix.setScale(static_cast<float>(width) / dividerBitmap_.width(),
static_cast<float>(height) / dividerBitmap_.height());
}
}
paint.setShader(dividerBitmap_.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat));
if (paint.getShader() == nullptr) {
WLOGFE("DrawBitmap shader is nullptr");
return;
}
paint.setShader(paint.getShader()->makeWithLocalMatrix(matrix));
canvas->drawRect(rect, paint);
frame->SetDamageRegion(0, 0, width, height);
rsSurface->FlushFrame(frame);
}
void WindowInnerManager::DrawColor(std::shared_ptr<RSSurface>& rsSurface, uint32_t width, uint32_t height)
{
std::unique_ptr<RSSurfaceFrame> frame = rsSurface->RequestFrame(width, height);
if (frame == nullptr) {
WLOGFE("DrawColor frameptr is nullptr");
return;
}
auto canvas = frame->GetCanvas();
if (canvas == nullptr) {
WLOGFE("DrawColor canvas is nullptr");
return;
}
canvas->clear(SK_ColorTRANSPARENT);
SkPaint paint;
paint.setAntiAlias(true);
paint.setStyle(SkPaint::kFill_Style);
const SkScalar skWidth = 20; // stroke width is 20.
paint.setStrokeWidth(skWidth);
paint.setStrokeJoin(SkPaint::kRound_Join);
paint.setColor(DIVIDER_HANDLE_COLOR);
SkPoint rectPts[] = { {0, 0}, {static_cast<int>(width), static_cast<int>(height)} };
SkRect rect;
rect.set(rectPts[0], rectPts[1]);
canvas->drawRect(rect, paint);
frame->SetDamageRegion(0, 0, width, height);
rsSurface->FlushFrame(frame);
return;
}
sptr<Window> WindowInnerManager::GetDividerWindow(DisplayId displayId) const
{
auto iter = dividerMap_.find(displayId);
if (iter == dividerMap_.end()) {
return nullptr;
}
return iter->second;
}
sptr<Window> WindowInnerManager::CreateWindow(DisplayId displayId, const WindowType& type, const Rect& rect)
{
sptr<Window> window = GetDividerWindow(displayId);
if (window == nullptr) {
sptr<WindowOption> divWindowOp = new (std::nothrow) WindowOption();
if (divWindowOp == nullptr) {
WLOGFE("Window option is nullptr.");
return nullptr;
}
divWindowOp->SetWindowRect(rect);
divWindowOp->SetWindowType(type);
divWindowOp->SetFocusable(false);
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(std::unique_ptr<WindowInnerMessage> msg)
{
auto window = CreateWindow(msg->displayId, WindowType::WINDOW_TYPE_DOCK_SLICE, msg->dividerRect);
if (window == nullptr) {
return;
}
WMError res = window->Show();
if (res != WMError::WM_OK) {
WLOGFE("Show window failed");
return;
}
#ifdef ACE_ENABLE_GL
if (renderContext_ == nullptr) {
renderContext_ = std::make_unique<RenderContext>();
renderContext_->InitializeEglContext();
}
#endif
DrawSurface(window);
WLOGFI("CreateAndShowDivider success");
}
void WindowInnerManager::HideAndDestroyDivider(std::unique_ptr<WindowInnerMessage> msg)
{
sptr<Window> window = GetDividerWindow(msg->displayId);
if (window == nullptr) {
WLOGFE("Window is nullptr");
return;
}
WMError res = window->Hide();
if (res != WMError::WM_OK) {
WLOGFE("Hide window failed");
return;
}
res = window->Destroy();
if (res != WMError::WM_OK) {
WLOGFE("Destroy window failed");
return;
}
dividerMap_.erase(msg->displayId);
WLOGFI("HideAndDestroyDivider success");
}
void WindowInnerManager::DestroyThread(std::unique_ptr<WindowInnerMessage> msg)
{
hasInitThread_ = false;
needDestroyThread_ = true;
isDividerImageLoaded_ = false;
WLOGFI("DestroyThread success");
}
void WindowInnerManager::HandleMessage()
{
WLOGFI("HandleMessage");
std::vector<std::unique_ptr<WindowInnerMessage>> handleMsgs;
while (!needDestroyThread_) {
// lock to store massages
{
std::unique_lock<std::mutex> lk(mutex_);
conVar_.wait(lk, [this] { return ready_; });
for (auto& iter: messages_) {
handleMsgs.push_back(std::move(iter));
}
messages_.clear();
ready_ = false;
}
// loop to handle massages
for (auto& msg : handleMsgs) {
if (!msg) {
continue;
}
auto cmdType = msg->cmdType;
using Func_t = void(WindowInnerManager::*)(std::unique_ptr<WindowInnerMessage> winMsg);
static const std::map<InnerWMCmd, Func_t> funcMap = {
std::make_pair(InnerWMCmd::INNER_WM_CREATE_DIVIDER, &WindowInnerManager::CreateAndShowDivider),
std::make_pair(InnerWMCmd::INNER_WM_DESTROY_DIVIDER, &WindowInnerManager::HideAndDestroyDivider),
std::make_pair(InnerWMCmd::INNER_WM_DESTROY_THREAD, &WindowInnerManager::DestroyThread)};
auto it = funcMap.find(cmdType);
if (it != funcMap.end()) {
(this->*(it->second))(std::move(msg));
}
}
handleMsgs.clear();
}
}
void WindowInnerManager::SendMessage(InnerWMCmd cmdType, DisplayId displayId)
{
std::unique_lock<std::mutex> lk(mutex_);
if (!hasInitThread_) {
WLOGFI("Inner window manager thread has not been created");
return;
}
std::unique_ptr<WindowInnerMessage> winMsg = std::make_unique<WindowInnerMessage>();
if (!winMsg) {
WLOGFI("alloc winMsg failed");
return;
}
winMsg->cmdType = cmdType;
winMsg->displayId = displayId;
WLOGFI("SendMessage : displayId = %{public}" PRIu64", type = %{public}d",
winMsg->displayId, static_cast<uint32_t>(cmdType));
messages_.push_back(std::move(winMsg));
ready_ = true;
conVar_.notify_one();
}
void WindowInnerManager::Init()
{
std::unique_lock<std::mutex> lk(mutex_);
needDestroyThread_ = false;
// create inner thread
std::thread innerWMThread(&WindowInnerManager::HandleMessage, this);
innerWMThread.detach();
hasInitThread_ = true;
VsyncStation::GetInstance().SetIsMainHandlerAvailable(false);
WLOGFI("Inner window manager thread create success");
}
}
}
/*
* 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 "ui_service_mgr_client.h"
#include "window_manager_hilog.h"
#include "window.h"
namespace OHOS {
namespace Rosen {
namespace {
constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowInnerManager"};
}
WM_IMPLEMENT_SINGLE_INSTANCE(WindowInnerManager)
WindowInnerManager::WindowInnerManager() : eventHandler_(nullptr), eventLoop_(nullptr),
state_(InnerWMRunningState::STATE_NOT_START)
{
}
WindowInnerManager::~WindowInnerManager()
{
Stop();
}
bool WindowInnerManager::Init()
{
eventLoop_ = AppExecFwk::EventRunner::Create(INNER_WM_THREAD_NAME);
if (eventLoop_ == nullptr) {
return false;
}
eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(eventLoop_);
if (eventHandler_ == nullptr) {
return false;
}
WLOGFI("init window inner manager service success.");
return true;
}
void WindowInnerManager::Start()
{
if (state_ == InnerWMRunningState::STATE_RUNNING) {
WLOGFI("window inner manager service has already started.");
}
if (!Init()) {
WLOGFI("failed to init window inner manager service.");
return;
}
state_ = InnerWMRunningState::STATE_RUNNING;
eventLoop_->Run();
WLOGFI("window inner manager service start success.");
}
void WindowInnerManager::Stop()
{
WLOGFI("stop window inner manager service.");
if (eventLoop_ != nullptr) {
eventLoop_->Stop();
eventLoop_.reset();
}
if (eventHandler_ != nullptr) {
eventHandler_.reset();
}
state_ = InnerWMRunningState::STATE_NOT_START;
}
void WindowInnerManager::HandleCreateWindow(std::string name, WindowType type, Rect rect)
{
auto dialogCallback = [this](int32_t id, const std::string& event, const std::string& params) {
if (params == "EVENT_CANCLE_CODE") {
Ace::UIServiceMgrClient::GetInstance()->CancelDialog(id);
}
};
Ace::UIServiceMgrClient::GetInstance()->ShowDialog(name, dividerParams_, type,
rect.posX_, rect.posY_, rect.width_, rect.height_, dialogCallback, &dialogId_);
WLOGFI("create inner window id: %{public}d succes", dialogId_);
return;
}
void WindowInnerManager::HandleDestroyWindow()
{
if (dialogId_ == -1) {
return;
}
WLOGFI("destroy inner window id:: %{public}d.", dialogId_);
Ace::UIServiceMgrClient::GetInstance()->CancelDialog(dialogId_);
dialogId_ = -1;
return;
}
void WindowInnerManager::CreateWindow(std::string name, WindowType type, Rect rect)
{
if (dialogId_ != -1) {
return;
}
eventHandler_->PostTask([this, name, type, rect]() {
HandleCreateWindow(name, type, rect);
});
return;
}
void WindowInnerManager::DestroyWindow()
{
if (dialogId_ == -1) {
WLOGFI("inner window has destroyed.");
return;
}
eventHandler_->PostTask([this]() {
HandleDestroyWindow();
});
return;
}
} // Rosen
} // OHOS

View File

@ -931,5 +931,10 @@ void WindowLayoutPolicy::SetFloatingWindowLimitsConfig(const FloatingWindowLimit
{
floatingWindowLimitsConfig_ = floatingWindowLimitsConfig;
}
Rect WindowLayoutPolicy::GetInitalDividerRect(DisplayId displayId) const
{
return IVALID_EMPTY_RECT;
}
}
}

View File

@ -30,7 +30,7 @@ WindowLayoutPolicyCascade::WindowLayoutPolicyCascade(const sptr<DisplayGroupInfo
DisplayGroupWindowTree& displayGroupWindowTree)
: WindowLayoutPolicy(displayGroupInfo, displayGroupWindowTree)
{
CascadeRects cascadeRects {
LayoutRects cascadeRects {
.primaryRect_ = {0, 0, 0, 0},
.secondaryRect_ = {0, 0, 0, 0},
.primaryLimitRect_ = {0, 0, 0, 0},
@ -183,6 +183,11 @@ void WindowLayoutPolicyCascade::AddWindowNode(const sptr<WindowNode>& node)
node->SetRequestRect(restoringDividerWindowRects_[displayId]);
}
restoringDividerWindowRects_.erase(displayId);
} else if (node->GetWindowType() == WindowType::WINDOW_TYPE_PLACE_HOLDER) {
Rect placeHolderRect = node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ?
cascadeRectsMap_[node->GetDisplayId()].primaryLimitRect_ :
cascadeRectsMap_[node->GetDisplayId()].secondaryLimitRect_;
node->SetRequestRect(placeHolderRect); // init place holder window
}
UpdateWindowNode(node, true); // currently, update and add do the same process
}
@ -530,5 +535,13 @@ void WindowLayoutPolicyCascade::SetCascadeRect(const sptr<WindowNode>& node)
node->SetRequestRect(rect);
node->SetDecoStatus(true);
}
Rect WindowLayoutPolicyCascade::GetInitalDividerRect(DisplayId displayId) const
{
Rect dividerRect = {0, 0, 0, 0};
if (cascadeRectsMap_.find(displayId) != std::end(cascadeRectsMap_)) {
dividerRect = cascadeRectsMap_[displayId].dividerRect_;
}
return dividerRect;
}
} // Rosen
} // OHOS

View File

@ -68,7 +68,7 @@ void WindowManagerService::OnStart()
if (!Init()) {
return;
}
SingletonContainer::Get<WindowInnerManager>().Init();
WindowInnerManager::GetInstance().Start();
sptr<IDisplayChangeListener> listener = new DisplayChangeListener();
DisplayManagerServiceInner::GetInstance().RegisterDisplayChangeListener(listener);
RegisterSnapshotHandler();
@ -256,7 +256,7 @@ void WindowManagerService::ConfigureWindowManagerService()
void WindowManagerService::OnStop()
{
SingletonContainer::Get<WindowInnerManager>().SendMessage(InnerWMCmd::INNER_WM_DESTROY_THREAD);
WindowInnerManager::GetInstance().Stop();
WLOGFI("ready to stop service.");
}

View File

@ -61,6 +61,8 @@ WindowNodeContainer::WindowNodeContainer(const sptr<DisplayInfo>& displayInfo, S
layoutPolicy_ = layoutPolicys_[WindowLayoutMode::CASCADE];
layoutPolicy_->Launch();
Rect initalDividerRect = layoutPolicys_[WindowLayoutMode::CASCADE]->GetInitalDividerRect(displayId);
displayGroupController_->SetInitalDividerRect(displayId, initalDividerRect);
// init avoidAreaController
UpdateAvoidAreaFunc func = std::bind(&WindowNodeContainer::OnAvoidAreaChange, this,
std::placeholders::_1, std::placeholders::_2);

View File

@ -22,6 +22,8 @@
#include "window_helper.h"
#include "wm_trace.h"
#include "window_inner_manager.h"
namespace OHOS {
namespace Rosen {
namespace {
@ -39,13 +41,6 @@ WindowPair::~WindowPair()
Clear();
}
void WindowPair::SendInnerMessage(InnerWMCmd cmd, DisplayId displayId)
{
WLOGI("Send inner message cmd id: %{public}u display id: %{public}u.", static_cast<uint32_t>(cmd),
static_cast<uint32_t>(displayId));
SingletonContainer::Get<WindowInnerManager>().SendMessage(cmd, displayId);
}
void WindowPair::SendBroadcastMsg(sptr<WindowNode>& node)
{
if (node == nullptr) {
@ -171,7 +166,7 @@ void WindowPair::Clear()
primary_ = nullptr;
secondary_ = nullptr;
if (divider_ != nullptr) {
SendInnerMessage(InnerWMCmd::INNER_WM_DESTROY_DIVIDER, displayId_);
WindowInnerManager::GetInstance().DestroyWindow();
divider_ = nullptr;
}
status_ = WindowPairStatus::STATUS_EMPTY;
@ -329,7 +324,8 @@ void WindowPair::UpdateWindowPairStatus()
prevStatus == WindowPairStatus::STATUS_SINGLE_SECONDARY || prevStatus == WindowPairStatus::STATUS_EMPTY) &&
status_ == WindowPairStatus::STATUS_PAIRING) {
// create divider
SendInnerMessage(InnerWMCmd::INNER_WM_CREATE_DIVIDER, displayId_);
WindowInnerManager::GetInstance().CreateWindow("dialog_divider_ui", WindowType::WINDOW_TYPE_DOCK_SLICE,
initalDivderRect_);
} else if ((prevStatus == WindowPairStatus::STATUS_PAIRED_DONE || prevStatus == WindowPairStatus::STATUS_PAIRING) &&
(status_ != WindowPairStatus::STATUS_PAIRED_DONE && status_ != WindowPairStatus::STATUS_PAIRING)) {
// clear pair
@ -452,5 +448,10 @@ void WindowPair::SetAllAppWindowsRestoring(bool isAllAppWindowsRestoring)
{
isAllAppWindowsRestoring_ = isAllAppWindowsRestoring;
}
void WindowPair::SetInitalDividerRect(const Rect& rect)
{
initalDivderRect_ = rect;
}
} // namespace Rosen
} // namespace OHOS