• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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