1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "pointer_drawing_manager.h"
16 #include <display_type.h>
17 #include "libmmi_util.h"
18 #include "image/bitmap.h"
19 #include "image_source.h"
20 #include "image_type.h"
21 #include "image_utils.h"
22 #include "input_device_manager.h"
23 #include "mmi_log.h"
24 #include "pixel_map.h"
25
26 namespace OHOS {
27 namespace MMI {
28 namespace {
29 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "PointerDrawingManager" };
30 const std::string IMAGE_POINTER_JPEG_PATH = "/system/etc/multimodalinput/mouse_icon/angle.png";
31 }
32 } // namespace MMI
33 } // namespace OHOS
34
35 namespace OHOS {
36 namespace MMI {
DrawPointer(int32_t displayId,int32_t globalX,int32_t globalY)37 void PointerDrawingManager::DrawPointer(int32_t displayId, int32_t globalX, int32_t globalY)
38 {
39 MMI_LOGD("enter, display:%{public}d,globalX:%{public}d,globalY:%{public}d", displayId, globalX, globalY);
40 FixCursorPosition(globalX, globalY);
41 lastGlobalX_ = globalX;
42 lastGlobalY_ = globalY;
43 if (pointerWindow_ != nullptr) {
44 pointerWindow_->MoveTo(globalX, globalY);
45 pointerWindow_->Show();
46 MMI_LOGD("leave, display:%{public}d,globalX:%{public}d,globalY:%{public}d", displayId, globalX, globalY);
47 return;
48 }
49
50 CreatePointerWindow(displayId, globalX, globalY);
51 CHKPV(pointerWindow_);
52 sptr<OHOS::Surface> layer = GetLayer();
53 if (layer == nullptr) {
54 MMI_LOGE("draw pointer is faild, get layer is nullptr");
55 pointerWindow_->Destroy();
56 pointerWindow_ = nullptr;
57 return;
58 }
59
60 sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer);
61 if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
62 MMI_LOGE("draw pointer is faild, buffer or virAddr is nullptr");
63 pointerWindow_->Destroy();
64 pointerWindow_ = nullptr;
65 return;
66 }
67
68 auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
69 DoDraw(addr, buffer->GetWidth(), buffer->GetHeight());
70 OHOS::BufferFlushConfig flushConfig = {
71 .damage = {
72 .w = buffer->GetWidth(),
73 .h = buffer->GetHeight(),
74 },
75 };
76 OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
77 MMI_LOGD("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
78 pointerWindow_->Show();
79 MMI_LOGD("leave, display:%{public}d,globalX:%{public}d,globalY:%{public}d", displayId, globalX, globalY);
80 }
81
FixCursorPosition(int32_t & globalX,int32_t & globalY)82 void PointerDrawingManager::FixCursorPosition(int32_t &globalX, int32_t &globalY)
83 {
84 if (globalX < 0) {
85 globalX = 0;
86 }
87
88 if (globalY < 0) {
89 globalY = 0;
90 }
91
92 int32_t size = 16;
93 int32_t fcursorW = IMAGE_WIDTH / size;
94 if ((globalX + fcursorW) > displayWidth_) {
95 globalX = displayWidth_ - fcursorW;
96 }
97 int32_t fcursorH = IMAGE_HEIGHT / size;
98 if ((globalY + fcursorH) > displayHeight_) {
99 globalY = displayHeight_ - fcursorH;
100 }
101 }
102
CreatePointerWindow(int32_t displayId,int32_t globalX,int32_t globalY)103 void PointerDrawingManager::CreatePointerWindow(int32_t displayId, int32_t globalX, int32_t globalY)
104 {
105 sptr<OHOS::Rosen::WindowOption> option = new OHOS::Rosen::WindowOption();
106 option->SetWindowType(OHOS::Rosen::WindowType::WINDOW_TYPE_POINTER);
107 option->SetWindowMode(OHOS::Rosen::WindowMode::WINDOW_MODE_FLOATING);
108 option->SetDisplayId(displayId);
109 OHOS::Rosen::Rect rect = {
110 .posX_ = globalX,
111 .posY_ = globalY,
112 .width_ = IMAGE_WIDTH,
113 .height_ = IMAGE_HEIGHT,
114 };
115 option->SetWindowRect(rect);
116 option->SetFocusable(false);
117 option->SetTouchable(false);
118 std::string windowName = "pointer window";
119 pointerWindow_ = OHOS::Rosen::Window::Create(windowName, option, nullptr);
120 }
121
GetLayer()122 sptr<OHOS::Surface> PointerDrawingManager::GetLayer()
123 {
124 std::shared_ptr<OHOS::Rosen::RSSurfaceNode> surfaceNode = pointerWindow_->GetSurfaceNode();
125 if (surfaceNode == nullptr) {
126 MMI_LOGE("draw pointer is faild, get node is nullptr");
127 pointerWindow_->Destroy();
128 pointerWindow_ = nullptr;
129 return nullptr;
130 }
131 return surfaceNode->GetSurface();
132 }
133
GetSurfaceBuffer(sptr<OHOS::Surface> layer)134 sptr<OHOS::SurfaceBuffer> PointerDrawingManager::GetSurfaceBuffer(sptr<OHOS::Surface> layer)
135 {
136 sptr<OHOS::SurfaceBuffer> buffer;
137 int32_t releaseFence = 0;
138 OHOS::BufferRequestConfig config = {
139 .width = IMAGE_WIDTH,
140 .height = IMAGE_HEIGHT,
141 .strideAlignment = 0x8,
142 .format = PIXEL_FMT_RGBA_8888,
143 .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
144 };
145
146 OHOS::SurfaceError ret = layer->RequestBuffer(buffer, releaseFence, config);
147 if (ret != OHOS::SURFACE_ERROR_OK) {
148 MMI_LOGE("request buffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
149 return nullptr;
150 }
151 return buffer;
152 }
153
DoDraw(uint8_t * addr,uint32_t width,uint32_t height)154 void PointerDrawingManager::DoDraw(uint8_t *addr, uint32_t width, uint32_t height)
155 {
156 MMI_LOGD("enter");
157 OHOS::Rosen::Drawing::Bitmap bitmap;
158 OHOS::Rosen::Drawing::BitmapFormat format { OHOS::Rosen::Drawing::COLORTYPE_RGBA_8888,
159 OHOS::Rosen::Drawing::ALPHATYPE_OPAQUYE };
160 bitmap.Build(width, height, format);
161 OHOS::Rosen::Drawing::Canvas canvas;
162 canvas.Bind(bitmap);
163 canvas.Clear(OHOS::Rosen::Drawing::Color::COLOR_TRANSPARENT);
164 DrawPixelmap(canvas);
165 constexpr uint32_t stride = 4;
166 uint32_t addrSize = width * height * stride;
167 auto ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
168 CHK(ret == EOK, MEMCPY_SEC_FUN_FAIL);
169 MMI_LOGD("leave");
170 }
171
DrawPixelmap(OHOS::Rosen::Drawing::Canvas & canvas)172 void PointerDrawingManager::DrawPixelmap(OHOS::Rosen::Drawing::Canvas &canvas)
173 {
174 MMI_LOGD("enter");
175 std::unique_ptr<OHOS::Media::PixelMap> pixelmap = DecodeImageToPixelMap(IMAGE_POINTER_JPEG_PATH);
176 CHKPV(pixelmap);
177 OHOS::Rosen::Drawing::Pen pen;
178 pen.SetAntiAlias(true);
179 pen.SetColor(OHOS::Rosen::Drawing::Color::COLOR_BLUE);
180 OHOS::Rosen::Drawing::scalar penWidth = 1;
181 pen.SetWidth(penWidth);
182 canvas.AttachPen(pen);
183 canvas.DrawBitmap(*pixelmap, 0, 0);
184 MMI_LOGD("leave");
185 }
186
DecodeImageToPixelMap(const std::string & imagePath)187 std::unique_ptr<OHOS::Media::PixelMap> PointerDrawingManager::DecodeImageToPixelMap(const std::string &imagePath)
188 {
189 OHOS::Media::SourceOptions opts;
190 opts.formatHint = "image/png";
191 uint32_t ret = 0;
192 auto imageSource = OHOS::Media::ImageSource::CreateImageSource(imagePath, opts, ret);
193 CHKPP(imageSource);
194 std::set<std::string> formats;
195 ret = imageSource->GetSupportedFormats(formats);
196 MMI_LOGD("get supported format ret:%{public}u", ret);
197
198 OHOS::Media::DecodeOptions decodeOpts;
199 std::unique_ptr<OHOS::Media::PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, ret);
200 if (pixelMap == nullptr) {
201 MMI_LOGE("pixelMap is nullptr");
202 }
203 return pixelMap;
204 }
205
TellDisplayInfo(int32_t displayId,int32_t width,int32_t height)206 void PointerDrawingManager::TellDisplayInfo(int32_t displayId, int32_t width, int32_t height)
207 {
208 MMI_LOGD("enter");
209 hasDisplay_ = true;
210 displayId_ = displayId;
211 displayWidth_ = width;
212 displayHeight_ = height;
213 DrawManager();
214 }
215
UpdatePointerDevice(bool hasPointerDevice)216 void PointerDrawingManager::UpdatePointerDevice(bool hasPointerDevice)
217 {
218 MMI_LOGD("enter");
219 hasPointerDevice_ = hasPointerDevice;
220 DrawManager();
221 }
222
DrawManager()223 void PointerDrawingManager::DrawManager()
224 {
225 if (hasDisplay_ && hasPointerDevice_ && pointerWindow_ == nullptr) {
226 MMI_LOGD("draw pointer begin");
227 if (lastGlobalX_ == -1 || lastGlobalY_ == -1) {
228 DrawPointer(displayId_, displayWidth_/2, displayHeight_/2);
229 return;
230 }
231 DrawPointer(displayId_, lastGlobalX_, lastGlobalY_);
232 return;
233 }
234
235 if (!hasPointerDevice_ && pointerWindow_ != nullptr) {
236 MMI_LOGD("destroy draw pointer");
237 pointerWindow_->Destroy();
238 pointerWindow_ = nullptr;
239 }
240 }
241
Init()242 bool PointerDrawingManager::Init()
243 {
244 MMI_LOGD("enter");
245 InputDevMgr->Attach(shared_from_this());
246 return true;
247 }
248
GetInstance()249 std::shared_ptr<IPointerDrawingManager> IPointerDrawingManager::GetInstance()
250 {
251 if (iPointDrawMgr_ == nullptr) {
252 iPointDrawMgr_ = std::make_shared<PointerDrawingManager>();
253 }
254 return iPointDrawMgr_;
255 }
256 } // namespace MMI
257 } // namespace OHOS