1 /*
2  * Copyright (c) 2020-2021 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 
16 #include "lite_wm.h"
17 
18 #include "gfx_utils/color.h"
19 #include "gfx_utils/graphic_log.h"
20 #include "gfx_utils/pixel_format_utils.h"
21 
22 namespace OHOS {
23 namespace {
24 #define EXPAND_RECT(x) x.GetLeft(), x.GetTop(), x.GetRight(), x.GetBottom()
25 const uint16_t CURSOR_WIDTH = 24;
26 const uint16_t CURSOR_HEIGHT = 25;
27 const uint8_t CURSOR_MAP[] = {
28     /* Pixel format: ARGB1555 */
29     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
32     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80,
37     0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00,
40     0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42     0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80,
43     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45     0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
46     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47     0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48     0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
50     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80,
51     0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52     0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
54     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00,
55     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56     0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
59     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
60     0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80,
61     0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65     0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
66     0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
68     0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00,
69     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70     0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80,
71     0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80,
73     0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
74     0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75     0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76     0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
77     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00,
78     0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
79     0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81     0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
82     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00,
84     0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
87     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89     0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92     0x00, 0x00, 0x00,
93 };
94 
95 const uint8_t MAX_WINDOW_NUMBLE = 32;
96 const uint32_t WINDOW_ID_FULL_STORAGE = 0xFFFFFFFF;
97 }
98 
LiteWM()99 LiteWM::LiteWM()
100     : updates_({}), layerData_(nullptr), cursorInfo_({}), mousePosition_({}), deviceData_({}),
101       needScreenshot_(false), screenshotSurface_(nullptr), winIdStorage(0)
102 {
103     InitMutex(stackLock_, PTHREAD_MUTEX_RECURSIVE);
104     pthread_mutex_init(&mouseLock_, nullptr);
105     pthread_mutex_init(&eventLock_, nullptr);
106     pthread_mutex_init(&screenshotMutex_, nullptr);
107 
108     InputManagerService::GetInstance()->GetDistributer()->AddRawEventListener(this);
109     InitMouseCursor();
110 
111     layerData_ = GetDevSurfaceData();
112     if (layerData_ != nullptr) {
113         if (layerData_->virAddr == nullptr) {
114             GRAPHIC_LOGE("LayerInfo addr is null!");
115         }
116         GRAPHIC_LOGI("LayerInfo, width=%d, height=%d, stride=%d",
117             layerData_->width, layerData_->height, layerData_->stride);
118     } else {
119         GRAPHIC_LOGE("LayerInfo is null!");
120     }
121 }
122 
~LiteWM()123 LiteWM::~LiteWM()
124 {
125 }
126 
GetInstance()127 LiteWM* LiteWM::GetInstance()
128 {
129     static LiteWM liteWm;
130     return &liteWm;
131 }
132 
MainTaskHandler()133 void LiteWM::MainTaskHandler()
134 {
135     if (layerData_ == nullptr || layerData_->virAddr == nullptr) {
136         return;
137     }
138 
139     if (needScreenshot_) {
140         Screenshot();
141         needScreenshot_ = false;
142     }
143 
144     if (cursorInfo_.enableCursor) {
145         UpdateMouseCursor();
146     }
147 
148     ProcessUpdates();
149 }
150 
UpdateMouseCursor()151 void LiteWM::UpdateMouseCursor()
152 {
153     Rect& rect = cursorInfo_.rect;
154     Point point = GetMousePosition();
155     if (rect.GetLeft() == point.x && rect.GetTop() == point.y) {
156         return;
157     }
158     cursorInfo_.needRedraw = true;
159     AddUpdateRegion(rect);
160     rect.SetPosition(point.x, point.y);
161 }
162 
GetLayerInfo(LiteLayerInfo & layerInfo)163 void LiteWM::GetLayerInfo(LiteLayerInfo& layerInfo)
164 {
165     if (layerData_ == nullptr) {
166         return;
167     }
168     layerInfo.pixelFormat = layerData_->pixelFormat;
169     layerInfo.width = layerData_->width;
170     layerInfo.height = layerData_->height;
171 }
172 
GetSurface(int32_t id)173 Surface* LiteWM::GetSurface(int32_t id)
174 {
175     LiteWindow* window = GetWindowById(id);
176     if (window != nullptr) {
177         return window->GetSurface();
178     }
179     return nullptr;
180 }
181 
Show(int32_t id)182 void LiteWM::Show(int32_t id)
183 {
184     GraphicLocker lock(stackLock_);
185     LiteWindow* window = GetWindowById(id);
186     if (window != nullptr) {
187         window->SetIsShow(true);
188         UpdateWindowRegion(window, window->config_.rect);
189     }
190 }
191 
Hide(int32_t id)192 void LiteWM::Hide(int32_t id)
193 {
194     GraphicLocker lock(stackLock_);
195     LiteWindow* window = GetWindowById(id);
196     if (window != nullptr) {
197         window->SetIsShow(false);
198         UpdateWindowRegion(window, window->config_.rect);
199     }
200 }
201 
RaiseToTop(int32_t id)202 void LiteWM::RaiseToTop(int32_t id)
203 {
204     GraphicLocker lock(stackLock_);
205     auto node = GetWindowNodeById(id);
206     if (node != nullptr) {
207         node->prev_->next_ = node->next_;
208         node->next_->prev_ = node->prev_;
209         auto head = winList_.Begin()->prev_;
210         node->next_ = head->next_;
211         node->prev_ = head;
212         head->next_->prev_ = node;
213         head->next_ = node;
214 
215         if (node->data_ != nullptr) {
216             UpdateWindowRegion(winList_.Begin()->data_, node->data_->config_.rect);
217         }
218     }
219 }
220 
LowerToBottom(int32_t id)221 void LiteWM::LowerToBottom(int32_t id)
222 {
223     GraphicLocker lock(stackLock_);
224     auto node = GetWindowNodeById(id);
225     if (node != nullptr) {
226         node->prev_->next_ = node->next_;
227         node->next_->prev_ = node->prev_;
228         auto head = winList_.Begin()->prev_;
229         node->prev_ = head->prev_;
230         node->next_ = head;
231         head->prev_->next_ = node;
232         head->prev_ = node;
233 
234         if (node->data_ != nullptr) {
235             UpdateWindowRegion(winList_.Begin()->data_, node->data_->config_.rect);
236         }
237     }
238 }
239 
MoveTo(int32_t id,int16_t x,int16_t y)240 void LiteWM::MoveTo(int32_t id, int16_t x, int16_t y)
241 {
242     GraphicLocker lock(stackLock_);
243     LiteWindow* window = GetWindowById(id);
244     if (window != nullptr) {
245         window->MoveTo(x, y);
246     }
247 }
248 
Resize(int32_t id,int16_t width,int16_t height)249 void LiteWM::Resize(int32_t id, int16_t width, int16_t height)
250 {
251     GraphicLocker lock(stackLock_);
252     LiteWindow* window = GetWindowById(id);
253     if (window == nullptr) {
254         return;
255     }
256     Rect rectBefore = window->config_.rect;
257     window->Resize(width, height);
258     Rect rectAfter = window->config_.rect;
259     Rect mask;
260     if (mask.Intersect(rectBefore, rectAfter)) {
261         int16_t x1 = mask.GetLeft();
262         int16_t x2 = mask.GetRight();
263         int16_t y1 = mask.GetTop();
264         int16_t y2 = mask.GetBottom();
265         if (x2 != rectBefore.GetRight()) {
266             UpdateWindowRegion(window, {static_cast<int16_t>(x2 + 1), y1, rectBefore.GetRight(),
267                 rectBefore.GetBottom()});
268         }
269         if (y2 != rectBefore.GetBottom()) {
270             UpdateWindowRegion(window, {x1, static_cast<int16_t>(y2 + 1), x2, rectBefore.GetBottom()});
271         }
272     }
273 }
274 
UpdateWindow(int32_t id)275 void LiteWM::UpdateWindow(int32_t id)
276 {
277     GRAPHIC_LOGI("UpdateWindow, id=%d", id);
278     LiteWindow* window = GetWindowById(id);
279     if (window != nullptr) {
280         UpdateWindowRegion(window, window->config_.rect);
281     }
282 }
283 
GetWindowById(int32_t id)284 LiteWindow* LiteWM::GetWindowById(int32_t id)
285 {
286     if (id == INVALID_WINDOW_ID) {
287         return nullptr;
288     }
289 
290     LiteWindow* ret = nullptr;
291     auto node = winList_.Begin();
292     while (node != winList_.End()) {
293         if (node->data_->id_ == id) {
294             ret = node->data_;
295             break;
296         }
297         node = node->next_;
298     }
299     return ret;
300 }
301 
GetWindowNodeById(int32_t id)302 ListNode<LiteWindow*>* LiteWM::GetWindowNodeById(int32_t id)
303 {
304     if (id == INVALID_WINDOW_ID) {
305         return nullptr;
306     }
307 
308     ListNode<LiteWindow*>* ret = nullptr;
309     auto node = winList_.Begin();
310     while (node != winList_.End()) {
311         if (node->data_->id_ == id) {
312             ret = node;
313             break;
314         }
315         node = node->next_;
316     }
317     return ret;
318 }
319 
InitMouseCursor()320 void LiteWM::InitMouseCursor()
321 {
322     GRAPHIC_LOGI("InitMouseCursor");
323     cursorInfo_.rect.SetRect(0, 0, CURSOR_WIDTH - 1, CURSOR_HEIGHT - 1);
324     cursorInfo_.needRedraw = false;
325     cursorInfo_.enableCursor = false;
326 }
327 
CreateWindow(const LiteWinConfig & config,pid_t pid)328 LiteWindow* LiteWM::CreateWindow(const LiteWinConfig& config, pid_t pid)
329 {
330     GraphicLocker lock(stackLock_);
331     if (!CheckWinIdIsAvailable()) {
332         return nullptr;
333     }
334     LiteWindow* window = new LiteWindow(config);
335     if (window == nullptr) {
336         return nullptr;
337     }
338     if (!window->CreateSurface()) {
339         delete window;
340         return nullptr;
341     }
342     window->SetPid(pid);
343     winList_.PushFront(window);
344     return window;
345 }
346 
RemoveWindow(int32_t id)347 void LiteWM::RemoveWindow(int32_t id)
348 {
349     GraphicLocker lock(stackLock_);
350     auto node = GetWindowNodeById(id);
351     if (node == nullptr) {
352         return;
353     }
354     LiteWindow* window = node->data_;
355     winList_.Remove(node);
356     if (window != nullptr) {
357         AddUpdateRegion(window->config_.rect);
358         delete window;
359     }
360 }
361 
CheckWinIdIsAvailable()362 bool LiteWM::CheckWinIdIsAvailable()
363 {
364     if (winIdStorage == WINDOW_ID_FULL_STORAGE) {
365         GRAPHIC_LOGE("reach max window num!");
366         return false;
367     }
368     return true;
369 }
370 
GetUniqueWinId()371 int32_t LiteWM::GetUniqueWinId()
372 {
373     static uint8_t winId = 0;
374     if (!CheckWinIdIsAvailable()) {
375         return INVALID_WINDOW_ID;
376     }
377     while (winIdStorage & (1 << winId)) {
378         winId++;
379         winId %= MAX_WINDOW_NUMBLE;
380     }
381     winIdStorage |= (1 << winId);
382     return winId;
383 }
384 
RecycleWinId(int32_t id)385 void LiteWM::RecycleWinId(int32_t id)
386 {
387     if (id == INVALID_WINDOW_ID) {
388         return;
389     }
390     winIdStorage &= (~(1 << static_cast<uint32_t>(id)));
391 }
392 
InitMutex(pthread_mutex_t & mutex,int type)393 void LiteWM::InitMutex(pthread_mutex_t& mutex, int type)
394 {
395     pthread_mutexattr_t attr;
396     pthread_mutexattr_init(&attr);
397     pthread_mutexattr_settype(&attr, type);
398     pthread_mutex_init(&mutex, &attr);
399     pthread_mutexattr_destroy(&attr);
400 }
401 
UpdateWindowRegion(const LiteWindow * window,const Rect & rect)402 void LiteWM::UpdateWindowRegion(const LiteWindow* window, const Rect& rect)
403 {
404     ListNode<LiteWindow *>* winNode = winList_.Tail();
405     while (winNode != winList_.End()) {
406         if (winNode->data_ == window) {
407             CalculateUpdateRegion(winNode->prev_, EXPAND_RECT(rect));
408             return;
409         }
410         winNode = winNode->prev_;
411     }
412     AddUpdateRegion(rect);
413 }
414 
CalculateUpdateRegion(const ListNode<LiteWindow * > * winNode,int16_t x1,int16_t y1,int16_t x2,int16_t y2)415 void LiteWM::CalculateUpdateRegion(const ListNode<LiteWindow*>* winNode, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
416 {
417     Rect rect(x1, y1, x2, y2);
418     if (winNode == winList_.End()) {
419         AddUpdateRegion(rect);
420         return;
421     }
422     if (winNode == nullptr) {
423         return;
424     }
425     LiteWindow* window = winNode->data_;
426     if ((window != nullptr) && window->isShow_ && window->IsCoverMode()) {
427         Rect& winRect = window->config_.rect;
428         Rect mask;
429         GRAPHIC_LOGD("winRect={%d,%d,%d,%d}, rect={%d,%d,%d,%d}", EXPAND_RECT(winRect), EXPAND_RECT(rect));
430         if (mask.Intersect(winRect, rect)) {
431             if (x1 != mask.GetLeft()) {
432                 CalculateUpdateRegion(winNode->prev_, x1, y1, mask.GetLeft() - 1, y2);
433             }
434 
435             if (y1 != mask.GetTop()) {
436                 CalculateUpdateRegion(winNode->prev_, mask.GetLeft(), y1, x2, mask.GetTop() - 1);
437             }
438 
439             if (x2 != mask.GetRight()) {
440                 CalculateUpdateRegion(winNode->prev_, mask.GetRight() + 1, mask.GetTop(), x2, y2);
441             }
442 
443             if (y2 != mask.GetBottom()) {
444                 CalculateUpdateRegion(winNode->prev_, mask.GetLeft(), mask.GetBottom() + 1, mask.GetRight(), y2);
445             }
446             return;
447         }
448     }
449     CalculateUpdateRegion(winNode->prev_, x1, y1, x2, y2);
450 }
451 
AddUpdateRegion(const Rect & rect)452 void LiteWM::AddUpdateRegion(const Rect& rect)
453 {
454     GraphicLocker lock(stackLock_);
455     GRAPHIC_LOGD("AddUpdateRegion, rect={%d,%d,%d,%d}", EXPAND_RECT(rect));
456     if (updates_.num == 0) {
457         updates_.updates[updates_.num++] = rect;
458         updates_.bound = rect;
459     } else {
460         for (int i = 0; i < updates_.num; i++) {
461             Rect& updateRect = updates_.updates[i];
462             if (updateRect.IsIntersect(rect) || updateRect.IsExtends(rect)) {
463                 updateRect.Join(updateRect, rect);
464                 updates_.bound.Join(updates_.bound, rect);
465                 return;
466             }
467         }
468         if (updates_.num == MAX_UPDATE_SIZE) {
469             updates_.bound.Join(updates_.bound, rect);
470             updates_.num = 0;
471             updates_.updates[updates_.num++] = updates_.bound;
472         } else {
473             updates_.updates[updates_.num++] = rect;
474             updates_.bound.Join(updates_.bound, rect);
475         }
476     }
477 }
478 
ProcessUpdates()479 void LiteWM::ProcessUpdates()
480 {
481     bool needFlush = false;
482     {
483         GraphicLocker lock(stackLock_);
484         for (int i = 0; i < updates_.num; i++) {
485             ListNode<LiteWindow *>* winNode = winList_.Begin();
486             DrawRegion(winNode, EXPAND_RECT(updates_.updates[i]));
487 
488             if (cursorInfo_.enableCursor && cursorInfo_.rect.IsIntersect(updates_.updates[i])) {
489                 cursorInfo_.needRedraw = true;
490             }
491         }
492         if (updates_.num != 0 || (cursorInfo_.enableCursor && cursorInfo_.needRedraw)) {
493             needFlush = true;
494         }
495         updates_ = {};
496     }
497 
498     if (cursorInfo_.enableCursor && cursorInfo_.needRedraw) {
499         DrawMouseCursor();
500         cursorInfo_.needRedraw = false;
501     }
502 
503     if (needFlush) {
504         LcdFlush();
505     }
506 }
507 
DrawRegion(const ListNode<LiteWindow * > * winNode,int16_t x1,int16_t y1,int16_t x2,int16_t y2)508 void LiteWM::DrawRegion(const ListNode<LiteWindow*>* winNode, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
509 {
510     if (winNode == nullptr) {
511         return;
512     }
513 
514     if (winNode == winList_.End()) {
515         DrawBackground(x1, y1, x2, y2);
516         return;
517     }
518 
519     LiteWindow* window = winNode->data_;
520     if (window == nullptr) {
521         return;
522     }
523     window->UpdateBackBuf();
524 
525     Rect rect(x1, y1, x2, y2);
526     Rect& winRect = window->config_.rect;
527     Rect mask;
528     if (!window->isShow_ || window->NoNeedToDraw() ||
529         window->backBuf_ == nullptr || !mask.Intersect(winRect, rect)) {
530         GRAPHIC_LOGI("winRect={%d,%d,%d,%d}, rect={%d,%d,%d,%d}", EXPAND_RECT(winRect), EXPAND_RECT(rect));
531         DrawRegion(winNode->next_, x1, y1, x2, y2);
532         return;
533     }
534 
535     int x = mask.GetLeft();
536     int y = mask.GetTop();
537 
538     if (!window->IsCoverMode()) {
539         DrawRegion(winNode->next_, EXPAND_RECT(mask));
540     }
541 
542     Rect srcRect = mask;
543     srcRect.SetPosition(mask.GetLeft() - winRect.GetLeft(), mask.GetTop() - winRect.GetTop());
544     GRAPHIC_LOGD("Blit, id=%d, srcRect={%d,%d,%d,%d}, x=%d, y=%d", window->id_, EXPAND_RECT(srcRect), x, y);
545     window->Flush(srcRect, layerData_, x, y);
546     GRAPHIC_LOGD("Blit finish");
547 
548     if (x1 != mask.GetLeft()) {
549         DrawRegion(winNode->next_, x1, y1, mask.GetLeft() - 1, y2);
550     }
551 
552     if (y1 != mask.GetTop()) {
553         DrawRegion(winNode->next_, mask.GetLeft(), y1, x2, mask.GetTop() - 1);
554     }
555 
556     if (x2 != mask.GetRight()) {
557         DrawRegion(winNode->next_, mask.GetRight() + 1, mask.GetTop(), x2, y2);
558     }
559 
560     if (y2 != mask.GetBottom()) {
561         DrawRegion(winNode->next_, mask.GetLeft(), mask.GetBottom() + 1, mask.GetRight(), y2);
562     }
563 }
564 
DrawBackground(int16_t x1,int16_t y1,int16_t x2,int16_t y2)565 void LiteWM::DrawBackground(int16_t x1, int16_t y1, int16_t x2, int16_t y2)
566 {
567     Rect rect(0, 0, layerData_->width - 1, layerData_->height - 1);
568     Rect rectBg(x1, y1, x2, y2);
569     if (!rect.Intersect(rect, rectBg)) {
570         return;
571     }
572 
573     x1 = rect.GetLeft();
574     x2 = rect.GetRight();
575     y1 = rect.GetTop();
576     y2 = rect.GetBottom();
577 
578     GRAPHIC_LOGD("DrawBackground, {%d,%d,%d,%d}", x1, y1, x2, y2);
579     int32_t len = static_cast<int32_t>(x2 - x1 + 1) * layerData_->bytePerPixel;
580     for (int16_t y = y1; y <= y2; y++) {
581         LayerColorType* buf1 = reinterpret_cast<LayerColorType*>(layerData_->virAddr + y * layerData_->stride);
582         if (memset_s(buf1 + x1, len, 0, len) != EOK) {
583             GRAPHIC_LOGE("memset_s error!");
584         }
585     }
586 }
587 
DrawMouseCursor()588 void LiteWM::DrawMouseCursor()
589 {
590     Rect rect(0, 0, layerData_->width - 1, layerData_->height - 1);
591     if (!rect.Intersect(rect, cursorInfo_.rect)) {
592         return;
593     }
594 
595     int16_t x1 = rect.GetLeft();
596     int16_t x2 = rect.GetRight();
597     int16_t y1 = rect.GetTop();
598     int16_t y2 = rect.GetBottom();
599 
600     const uint16_t* srcbuf = reinterpret_cast<const uint16_t*>(CURSOR_MAP);
601     uint8_t* dstBuf = layerData_->virAddr + y1 * layerData_->stride + x1 * sizeof(LayerColorType);
602     for (int16_t y = y1; y <= y2; y++) {
603         const uint16_t* tmpSrc = srcbuf;
604         LayerColorType* tmpDst = reinterpret_cast<LayerColorType*>(dstBuf);
605         for (int16_t x = x1; x <= x2; x++) {
606             if ((*tmpSrc) & 0x8000) {
607 #ifdef LAYER_PF_ARGB1555
608                 *tmpDst = *tmpSrc;
609 #elif defined LAYER_PF_ARGB8888
610                 *tmpDst = PixelFormatUtils::ARGB1555ToARGB8888(*tmpSrc);
611 #endif
612             }
613             tmpSrc++;
614             tmpDst++;
615         }
616         dstBuf += layerData_->stride;
617         srcbuf += CURSOR_WIDTH;
618     }
619 }
620 
FindTargetWindow(const RawEvent & event)621 LiteWindow* LiteWM::FindTargetWindow(const RawEvent& event)
622 {
623     if (winList_.IsEmpty()) {
624         return nullptr;
625     }
626 
627     LiteWindow* targetWindow = nullptr;
628     auto node = winList_.Begin();
629     while (node != winList_.End()) {
630         if (node->data_->GetConfig().isModal) {
631             return node->data_;
632         }
633         node = node->next_;
634     }
635 
636     switch (event.type) {
637         case InputDevType::INDEV_TYPE_MOUSE:
638             // fall-through
639         case InputDevType::INDEV_TYPE_TOUCH: {
640             auto win = winList_.Begin();
641             while (win != winList_.End()) {
642                 Point p = { event.x, event.y };
643                 if (win->data_->isShow_ && win->data_->GetConfig().rect.IsContains(p)) {
644                     targetWindow = win->data_;
645                     break;
646                 }
647                 win = win->next_;
648             }
649             break;
650         }
651         case InputDevType::INDEV_TYPE_KEY:
652             // fall-through
653         case InputDevType::INDEV_TYPE_BUTTON: {
654             targetWindow = winList_.Front();
655             break;
656         }
657         default:
658             break;
659     }
660     return targetWindow;
661 }
662 
OnRawEvent(const RawEvent & rawEvent)663 void LiteWM::OnRawEvent(const RawEvent& rawEvent)
664 {
665     static bool firstTime = true;
666     if (layerData_ == nullptr) {
667         return;
668     }
669 
670     RawEvent event = rawEvent;
671     if (GetLayerRotateType() == LAYER_ROTATE_90) {
672         int16_t tmp = layerData_->height - event.x;
673         event.x = event.y;
674         event.y = tmp;
675     }
676 
677     if (firstTime) {
678         if (event.type == InputDevType::INDEV_TYPE_MOUSE) {
679             cursorInfo_.enableCursor = true;
680             cursorInfo_.needRedraw = true;
681         } else {
682             cursorInfo_.enableCursor = false;
683         }
684         firstTime = false;
685     }
686 
687     if (cursorInfo_.enableCursor) {
688         SetMousePosition(event.x, event.y);
689     }
690 
691     LiteWindow* targetWindow = FindTargetWindow(event);
692     if (targetWindow == nullptr) {
693         return;
694     }
695 
696     SetEventData(targetWindow, event);
697 }
698 
OnScreenshot(Surface * surface)699 bool LiteWM::OnScreenshot(Surface* surface)
700 {
701     GraphicLocker lock(screenshotMutex_);
702     if (!needScreenshot_) {
703         screenshotSurface_ = surface;
704         needScreenshot_ = true;
705         return true;
706     }
707     return false;
708 }
709 
Screenshot()710 void LiteWM::Screenshot()
711 {
712     int32_t lineSize = 0;
713     int16_t bpp = 0;
714     uint8_t* dstAddr = nullptr;
715     uint8_t* srcAddr = nullptr;
716     uint32_t width = 0;
717     uint32_t height = 0;
718     if (screenshotSurface_ == nullptr) {
719         return;
720     }
721 
722     SurfaceBuffer* buffer = screenshotSurface_->RequestBuffer();
723     if (buffer == nullptr) {
724         goto end2;
725     }
726 
727     width = screenshotSurface_->GetWidth();
728     height = screenshotSurface_->GetHeight();
729     if (width > layerData_->width || height > layerData_->height) {
730         goto end1;
731     }
732 
733     if (!PixelFormatUtils::BppOfPixelFormat(static_cast<ImagePixelFormat>(screenshotSurface_->GetFormat()), bpp)) {
734         goto end1;
735     }
736 
737     lineSize = width * bpp;
738     dstAddr = static_cast<uint8_t*>(buffer->GetVirAddr());
739     srcAddr = layerData_->virAddr;
740     if (dstAddr != nullptr && srcAddr != nullptr) {
741         for (uint32_t i = 0; i < height; i++) {
742             if (memcpy_s(dstAddr, lineSize, srcAddr, lineSize) != EOK) {
743                 GRAPHIC_LOGE("memcpy_s error!");
744             }
745             dstAddr += lineSize;
746             srcAddr += layerData_->stride;
747         }
748     }
749 end1:
750     screenshotSurface_->FlushBuffer(buffer);
751 end2:
752     delete screenshotSurface_;
753     screenshotSurface_ = nullptr;
754 }
755 
OnClientDeathNotify(pid_t pid)756 void LiteWM::OnClientDeathNotify(pid_t pid)
757 {
758     GRAPHIC_LOGI("OnClientDeathNotify");
759     GraphicLocker lock(stackLock_);
760     auto node = winList_.Begin();
761     while (node != winList_.End()) {
762         auto tmp = node;
763         node = node->next_;
764         LiteWindow* window = tmp->data_;
765         GRAPHIC_LOGI("window->GetPid() = %d,pid = %d", window->GetPid(), pid);
766         if (window->GetPid() == pid) {
767             winList_.Remove(tmp);
768             AddUpdateRegion(window->config_.rect);
769             delete window;
770         }
771     }
772 }
773 }
774