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
22namespace OHOS {
23namespace {
24#define EXPAND_RECT(x) x.GetLeft(), x.GetTop(), x.GetRight(), x.GetBottom()
25const uint16_t CURSOR_WIDTH = 24;
26const uint16_t CURSOR_HEIGHT = 25;
27const 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
95const uint8_t MAX_WINDOW_NUMBLE = 32;
96const uint32_t WINDOW_ID_FULL_STORAGE = 0xFFFFFFFF;
97}
98
99LiteWM::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
123LiteWM::~LiteWM()
124{
125}
126
127LiteWM* LiteWM::GetInstance()
128{
129    static LiteWM liteWm;
130    return &liteWm;
131}
132
133void 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
151void 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
163void 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
173Surface* 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
182void 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
192void 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
202void 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
221void 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
240void 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
249void 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
275void 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
284LiteWindow* 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
302ListNode<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
320void 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
328LiteWindow* 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
347void 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
362bool 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
371int32_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
385void 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
393void 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
402void 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
415void 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
452void 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
479void 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
508void 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
565void 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
588void 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
621LiteWindow* 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
663void 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
699bool 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
710void 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    }
749end1:
750    screenshotSurface_->FlushBuffer(buffer);
751end2:
752    delete screenshotSurface_;
753    screenshotSurface_ = nullptr;
754}
755
756void 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