• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025-2025 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 "screen_pointer.h"
16 
17 #include "define_multimodal.h"
18 #include "transaction/rs_transaction.h"
19 #include "transaction/rs_interfaces.h"
20 
21 #undef MMI_LOG_DOMAIN
22 #define MMI_LOG_DOMAIN MMI_LOG_CURSOR
23 #undef MMI_LOG_TAG
24 #define MMI_LOG_TAG "ScreenPointer"
25 
26 namespace OHOS::MMI {
27 const char* RS_SURFACE_NODE_NAME{"pointer window"};
28 const char* POINTER_SIZE{"pointerSize"};
29 constexpr int32_t RS_NODE_CANVAS_INDEX{-1};
30 constexpr int32_t DEFAULT_POINTER_SIZE{1};
31 constexpr int32_t DEVICE_INDEPENDENT_PIXELS{40};
32 constexpr int32_t BASELINE_DENSITY{160};
33 constexpr int32_t POINTER_WINDOW_INIT_SIZE{64};
34 constexpr int32_t BUFFER_RELEASE_WAIT_MS{1000};
35 constexpr int32_t NUM_TWO{2};
36 constexpr int32_t DEFAULT_BUFFER_SIZE{10};
37 constexpr int32_t DEFAULT_CURSOR_SIZE{512};
38 constexpr uint32_t FOCUS_POINT = DEFAULT_CURSOR_SIZE / NUM_TWO;
39 constexpr int32_t BUFFER_TIMEOUT{150};
40 constexpr int32_t STRIDE_ALIGNMENT{8};
41 constexpr float CALCULATE_MOUSE_ICON_BIAS{5.0f};
42 constexpr float INCREASE_RATIO{1.22f};
43 constexpr uint32_t RENDER_STRIDE{4};
44 
GetScreenInfoWidth(screen_info_ptr_t si)45 uint32_t GetScreenInfoWidth(screen_info_ptr_t si)
46 {
47     uint32_t width = 0;
48     auto modeId = si->GetModeId();
49     auto modes = si->GetModes();
50     if (modeId < 0 || modeId >= modes.size()) {
51         return 0;
52     }
53     return modes[modeId]->width_;
54 }
GetScreenInfoHeight(screen_info_ptr_t si)55 uint32_t GetScreenInfoHeight(screen_info_ptr_t si)
56 {
57     uint32_t height = 0;
58     auto modeId = si->GetModeId();
59     auto modes = si->GetModes();
60     if (modeId < 0 || modeId >= modes.size()) {
61         return 0;
62     }
63     return modes[modeId]->height_;
64 }
65 
ScreenPointer(hwcmgr_ptr_t hwcMgr,handler_ptr_t handler,const DisplayInfo & di)66 ScreenPointer::ScreenPointer(hwcmgr_ptr_t hwcMgr, handler_ptr_t handler, const DisplayInfo &di)
67     : hwcMgr_(hwcMgr), handler_(handler)
68 {
69     screenId_ = di.id;
70     width_ = di.width;
71     height_ = di.height;
72     rotation_ = static_cast<rotation_t>(di.direction);
73     if (rotation_ == rotation_t::ROTATION_90 ||
74         rotation_ == rotation_t::ROTATION_270) {
75         std::swap(width_, height_);
76     }
77     dpi_ = float(di.dpi) / BASELINE_DENSITY;
78     MMI_HILOGI("Construct with DisplayInfo, id=%{public}u, shape=(%{public}u, %{public}u), mode=%{public}u, "
79         "rotation=%{public}u, dpi=%{public}f", screenId_, width_, height_, mode_, rotation_, dpi_);
80 }
81 
ScreenPointer(hwcmgr_ptr_t hwcMgr,handler_ptr_t handler,screen_info_ptr_t si)82 ScreenPointer::ScreenPointer(hwcmgr_ptr_t hwcMgr, handler_ptr_t handler, screen_info_ptr_t si)
83     : hwcMgr_(hwcMgr), handler_(handler)
84 {
85     screenId_ = si->GetScreenId();
86     width_ = GetScreenInfoWidth(si);
87     height_ = GetScreenInfoHeight(si);
88     mode_ = si->GetSourceMode();
89     rotation_ = si->GetRotation();
90     dpi_ = si->GetVirtualPixelRatio();
91     MMI_HILOGI("Construct with ScreenInfo, id=%{public}u, shape=(%{public}u, %{public}u), mode=%{public}u, "
92         "rotation=%{public}u, dpi=%{public}f", screenId_, width_, height_, mode_, rotation_, dpi_);
93 }
94 
Init()95 bool ScreenPointer::Init()
96 {
97     if (!InitSurface()) {
98         MMI_HILOGE("ScreenPointer InitSurface failed");
99         return false;
100     }
101 
102     // Init buffers
103     OHOS::BufferRequestConfig bufferCfg = {
104         .width = DEFAULT_CURSOR_SIZE,
105         .height = DEFAULT_CURSOR_SIZE,
106         .strideAlignment = STRIDE_ALIGNMENT,
107         .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
108         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_HW_COMPOSER,
109         .timeout = BUFFER_TIMEOUT,
110     };
111     for (int32_t i = 0; i < DEFAULT_BUFFER_SIZE && buffers_.size() < DEFAULT_BUFFER_SIZE; i++) {
112         sptr<OHOS::SurfaceBuffer> buffer = OHOS::SurfaceBuffer::Create();
113         if (buffer == nullptr) {
114             MMI_HILOGE("SurfaceBuffer Create failed");
115             return false;
116         }
117         OHOS::GSError ret = buffer->Alloc(bufferCfg);
118         if (ret != OHOS::GSERROR_OK) {
119             MMI_HILOGE("SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
120             return false;
121         }
122         buffers_.push_back(buffer);
123     }
124     return true;
125 }
126 
InitSurface()127 bool ScreenPointer::InitSurface()
128 {
129     // create SurfaceNode
130     Rosen::RSSurfaceNodeConfig surfaceNodeConfig;
131     surfaceNodeConfig.SurfaceNodeName = RS_SURFACE_NODE_NAME;
132     surfaceNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, Rosen::RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE);
133     CHKPF(surfaceNode_);
134     MMI_HILOGE("SurfaceNode::Create success");
135 
136     // set soft cursor buffer size
137     auto surface = surfaceNode_->GetSurface();
138     surface->SetQueueSize(DEFAULT_BUFFER_SIZE);
139 
140     surfaceNode_->SetVisible(true);
141     surfaceNode_->SetFrameGravity(Rosen::Gravity::TOP_LEFT);
142     surfaceNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
143     surfaceNode_->AttachToDisplay(screenId_);
144     MMI_HILOGI("AttachToDisplay %{public}d completed", screenId_);
145 
146     // create canvas node
147     canvasNode_ = Rosen::RSCanvasNode::Create();
148     CHKPF(canvasNode_);
149     canvasNode_->SetBounds(0, 0, DEFAULT_CURSOR_SIZE, DEFAULT_CURSOR_SIZE);
150     canvasNode_->SetFrame(0, 0, DEFAULT_CURSOR_SIZE, DEFAULT_CURSOR_SIZE);
151 #ifndef USE_ROSEN_DRAWING
152     canvasNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
153 #else
154     canvasNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
155 #endif // USE_ROSEN_DRAWING
156 
157     canvasNode_->SetCornerRadius(1);
158     canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
159     canvasNode_->SetRotation(float(rotation_));
160     surfaceNode_->AddChild(canvasNode_, RS_NODE_CANVAS_INDEX);
161 
162     MMI_HILOGI("InitSurface completed");
163     return true;
164 }
165 
UpdateScreenInfo(const sptr<OHOS::Rosen::ScreenInfo> si)166 void ScreenPointer::UpdateScreenInfo(const sptr<OHOS::Rosen::ScreenInfo> si)
167 {
168     auto id = si->GetScreenId();
169     if (screenId_ != id) {
170         surfaceNode_->AttachToDisplay(id);
171         Rosen::RSTransaction::FlushImplicitTransaction();
172     }
173 
174     screenId_ = si->GetScreenId();
175     width_ = GetScreenInfoWidth(si);
176     height_ = GetScreenInfoHeight(si);
177     mode_ = si->GetSourceMode();
178     rotation_ = si->GetRotation();
179     dpi_ = si->GetVirtualPixelRatio();
180     if (IsExtend()) {
181         surfaceNode_->AttachToDisplay(screenId_);
182         Rosen::RSTransaction::FlushImplicitTransaction();
183     }
184     MMI_HILOGI("Update with ScreenInfo, id=%{public}u, shape=(%{public}u, %{public}u), mode=%{public}u, "
185         "rotation=%{public}u, dpi=%{public}f", screenId_, width_, height_, mode_, rotation_, dpi_);
186 }
187 
OnDisplayInfo(const DisplayInfo & di)188 void ScreenPointer::OnDisplayInfo(const DisplayInfo &di)
189 {
190     if (screenId_ != uint32_t(di.id)) {
191         return;
192     }
193 
194     isCurrentOffScreenRendering_ = di.isCurrentOffScreenRendering;
195     dpi_ = float(di.dpi) / BASELINE_DENSITY;
196     if (!IsMirror()) {
197         rotation_ = static_cast<rotation_t>(di.direction);
198     }
199     MMI_HILOGD("Update with DisplayInfo, id=%{public}u, shape=(%{public}u, %{public}u), mode=%{public}u, "
200         "rotation=%{public}u, dpi=%{public}f", screenId_, width_, height_, mode_, rotation_, dpi_);
201     if (isCurrentOffScreenRendering_) {
202         screenRealDPI_ = di.screenRealDPI;
203         offRenderScale_ = float(di.screenRealWidth) / di.width;
204         MMI_HILOGD("Update with DisplayInfo, screenRealDPI=%{public}u, offRenderScale_=(%{public}f ",
205             screenRealDPI_, offRenderScale_);
206     }
207 }
208 
UpdatePadding(uint32_t mainWidth,uint32_t mainHeight)209 bool ScreenPointer::UpdatePadding(uint32_t mainWidth, uint32_t mainHeight)
210 {
211     if (!IsMirror()) {
212         MMI_HILOGI("UpdatePadidng, reset padding, screenId=%{public}u, scale=%{public}f, "
213             "paddingTop_=%{public}u, paddingLeft_=%{public}u", screenId_, scale_, paddingTop_, paddingLeft_);
214         scale_ = 1.0;
215         paddingTop_ = 0;
216         paddingLeft_ = 0;
217         return false;
218     }
219     if (mainWidth == 0 || mainHeight == 0) {
220         MMI_HILOGE("Invalid parameters, mainWidth=%{public}u, mainHeight=%{public}u", mainWidth, mainHeight);
221         return false;
222     }
223     if (rotation_ == rotation_t::ROTATION_90 || rotation_ == rotation_t::ROTATION_270) {
224         std::swap(mainWidth, mainHeight);
225     }
226 
227     // caculate padding for mirror screens
228     scale_ = fmin(float(width_) / mainWidth, float(height_) / mainHeight);
229     paddingTop_ = (height_ - mainHeight * scale_) / NUM_TWO;
230     paddingLeft_ = (width_ - mainWidth * scale_) / NUM_TWO;
231     MMI_HILOGI("UpdatePadding, screenId=%{public}u, scale=%{public}f, paddingTop_=%{public}u, paddingLeft_=%{public}u",
232         screenId_, scale_, paddingTop_, paddingLeft_);
233     return true;
234 }
235 
RequestBuffer()236 sptr<OHOS::SurfaceBuffer> ScreenPointer::RequestBuffer()
237 {
238     if (!buffers_.size()) {
239         return nullptr;
240     }
241 
242     bufferId_++;
243     bufferId_ %= buffers_.size();
244 
245     return buffers_[bufferId_];
246 }
247 
GetCurrentBuffer()248 sptr<OHOS::SurfaceBuffer> ScreenPointer::GetCurrentBuffer()
249 {
250     if (bufferId_ >= buffers_.size()) {
251         return nullptr;
252     }
253     return buffers_[bufferId_];
254 }
255 
Rotate(rotation_t rotation,int32_t & x,int32_t & y)256 void ScreenPointer::Rotate(rotation_t rotation, int32_t& x, int32_t& y)
257 {
258     // 坐标轴绕原点旋转 再平移
259     int32_t tmpX = x;
260     int32_t tmpY = y;
261     int32_t width = static_cast<int32_t>(width_);
262     int32_t height = static_cast<int32_t>(height_);
263     if (IsMirror()) {
264         height -= paddingTop_ * NUM_TWO;
265         width -= paddingLeft_ * NUM_TWO;
266     }
267     // 主屏旋转 坐标系会一起旋转,但镜像屏此时坐标系不旋转
268     if (IsMirror() && (rotation_ == rotation_t::ROTATION_90 || rotation_ == rotation_t::ROTATION_270)) {
269         std::swap(width, height);
270     }
271 
272     if (rotation == rotation_t(DIRECTION90)) {
273         x = height - tmpY;
274         y = tmpX;
275     } else if (rotation == rotation_t(DIRECTION180)) {
276         x = width - tmpX;
277         y = height - tmpY;
278     } else if (rotation == rotation_t(DIRECTION270)) {
279         x = tmpY;
280         y = width - tmpX;
281     }
282 }
283 
CalculateHwcPositionForMirror(int32_t & x,int32_t & y)284 void ScreenPointer::CalculateHwcPositionForMirror(int32_t& x, int32_t& y)
285 {
286     x = x * scale_;
287     y = y * scale_;
288     Rotate(rotation_, x, y);
289 
290     x += paddingLeft_;
291     y += paddingTop_;
292 }
293 
CalculateHwcPositionForExtend(int32_t & x,int32_t & y)294 void ScreenPointer::CalculateHwcPositionForExtend(int32_t& x, int32_t& y)
295 {
296     x = x * offRenderScale_;
297     y = y * offRenderScale_;
298 }
299 
Move(int32_t x,int32_t y,ICON_TYPE align)300 bool ScreenPointer::Move(int32_t x, int32_t y, ICON_TYPE align)
301 {
302 #ifdef OHOS_BUILD_ENABLE_HARDWARE_CURSOR
303     CHKPF(hwcMgr_);
304 
305     int32_t px = 0;
306     int32_t py = 0;
307     if (IsMirror()) {
308         CalculateHwcPositionForMirror(x, y);
309     } else if (GetIsCurrentOffScreenRendering() && !IsMirror()) {
310         CalculateHwcPositionForExtend(x, y);
311     }
312 
313     px = x - FOCUS_POINT;
314     py = y - FOCUS_POINT;
315 
316     auto buffer = GetCurrentBuffer();
317     CHKPF(buffer);
318     auto bh = buffer->GetBufferHandle();
319     CHKPF(bh);
320     auto ret = hwcMgr_->SetPosition(screenId_, px, py, bh);
321     if (ret != RET_OK) {
322         MMI_HILOGE("SetPosition failed, screenId=%{public}u, pos=(%{public}d, %{public}d)", screenId_, px, py);
323         return false;
324     }
325 #endif // OHOS_BUILD_ENABLE_HARDWARE_CURSOR
326     return true;
327 }
328 
MoveSoft(int32_t x,int32_t y,ICON_TYPE align)329 bool ScreenPointer::MoveSoft(int32_t x, int32_t y, ICON_TYPE align)
330 {
331     CHKPF(surfaceNode_);
332     int32_t px = 0;
333     int32_t py = 0;
334     if (IsMirror()) {
335         CalculateHwcPositionForMirror(x, y);
336     } else if (!IsExtend()) {
337         Rotate(rotation_, x, y);
338     }
339     px = x - FOCUS_POINT;
340     py = y - FOCUS_POINT;
341 
342     if (!IsMirror()) {
343         int64_t nodeId = surfaceNode_->GetId();
344         Rosen::RSInterfaces::GetInstance().SetHwcNodeBounds(nodeId, px, py, DEFAULT_CURSOR_SIZE, DEFAULT_CURSOR_SIZE);
345     } else {
346         surfaceNode_->SetBounds(px, py, DEFAULT_CURSOR_SIZE, DEFAULT_CURSOR_SIZE);
347     }
348 
349     return true;
350 }
351 
SetInvisible()352 bool ScreenPointer::SetInvisible()
353 {
354 #ifdef OHOS_BUILD_ENABLE_HARDWARE_CURSOR
355     CHKPF(hwcMgr_);
356 
357     auto buffer = RequestBuffer();
358     CHKPF(buffer);
359     auto addr = static_cast<uint8_t*>(buffer->GetVirAddr());
360     CHKPF(addr);
361     if (buffer->GetWidth() >= 0 && buffer->GetHeight() >= 0) {
362         uint32_t addrSize = static_cast<uint32_t>(buffer->GetWidth()) *
363             static_cast<uint32_t>(buffer->GetHeight()) * RENDER_STRIDE;
364         memset_s(addr, addrSize, 0, addrSize);
365     } else {
366         MMI_HILOGI("The input data is negative, and the data is incorrect.");
367         return false;
368     }
369 
370     auto bh = buffer->GetBufferHandle();
371     CHKPF(bh);
372     auto ret = hwcMgr_->SetPosition(screenId_, 0, 0, bh);
373     if (ret != RET_OK) {
374         MMI_HILOGE("SetLocation failed, screenId=%{public}u, loc=(%{public}d, %{public}d)", screenId_, 0, 0);
375         return false;
376     }
377     MMI_HILOGI("SetInvisible success, screenId=%{public}u", screenId_);
378 #endif // OHOS_BUILD_ENABLE_HARDWARE_CURSOR
379     return true;
380 }
381 
GetRenderDPI() const382 float ScreenPointer::GetRenderDPI() const
383 {
384     if (GetIsCurrentOffScreenRendering() && !IsMirror()) {
385         return float(GetScreenRealDPI()) / BASELINE_DENSITY;
386     } else {
387         return dpi_ * scale_;
388     }
389 }
390 
391 } // namespace OHOS::MMI