1/*
2 * Copyright (c) 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
16// gtest
17#include <gtest/gtest.h>
18#include "window_test_utils.h"
19#include "wm_common.h"
20
21using namespace testing;
22using namespace testing::ext;
23
24namespace OHOS {
25namespace Rosen {
26using Utils = WindowTestUtils;
27const int WAIT_CALLBACK_US = 1;  // 1s
28
29class TestDragListener : public IWindowDragListener {
30public:
31    PointInfo point_ { 0, 0 };
32    DragEvent event_ = DragEvent::DRAG_EVENT_END;
33    void OnDrag(int32_t x, int32_t y, DragEvent event) override;
34};
35
36void TestDragListener::OnDrag(int32_t x, int32_t y, DragEvent event)
37{
38    event_ = event;
39    point_.x = x;
40    point_.y = y;
41}
42
43class WindowDragTest : public testing::Test {
44public:
45    static void SetUpTestCase();
46    static void TearDownTestCase();
47    virtual void SetUp() override;
48    virtual void TearDown() override;
49
50    static sptr<TestDragListener> firstWindowDragListener_;
51    static sptr<TestDragListener> secondWindowDragListener_;
52    Utils::TestWindowInfo dragWindowInfo_;
53    Utils::TestWindowInfo firstWindowInfo_;
54    Utils::TestWindowInfo secondWindowInfo_;
55    std::vector<sptr<Window>> activeWindows_;
56};
57
58sptr<TestDragListener> WindowDragTest::firstWindowDragListener_ =
59    new TestDragListener();
60sptr<TestDragListener> WindowDragTest::secondWindowDragListener_ =
61    new TestDragListener();
62
63void WindowDragTest::SetUpTestCase() {}
64
65void WindowDragTest::TearDownTestCase() {}
66
67void WindowDragTest::SetUp()
68{
69    dragWindowInfo_ = {
70        .name = "dragWindow",
71        .rect = {200, 200, 380, 380},
72        .type = WindowType::WINDOW_TYPE_DRAGGING_EFFECT,
73        .mode = WindowMode::WINDOW_MODE_FLOATING,
74        .needAvoid = false,
75        .parentLimit = false,
76        .showWhenLocked = true,
77        .parentId = INVALID_WINDOW_ID,
78    };
79
80    firstWindowInfo_ = {
81        .name = "firstWindow",
82        .rect = Utils::customAppRect_,
83        .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW,
84        .mode = WindowMode::WINDOW_MODE_FULLSCREEN,
85        .needAvoid = false,
86        .parentLimit = false,
87        .showWhenLocked = true,
88        .parentId = INVALID_WINDOW_ID,
89    };
90
91    secondWindowInfo_ = {
92        .name = "secondWindow",
93        .rect = Utils::customAppRect_,
94        .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW,
95        .mode = WindowMode::WINDOW_MODE_FLOATING,
96        .needAvoid = false,
97        .parentLimit = false,
98        .showWhenLocked = true,
99        .parentId = INVALID_WINDOW_ID,
100    };
101    activeWindows_.clear();
102}
103
104void WindowDragTest::TearDown() {
105    while (!activeWindows_.empty()) {
106        ASSERT_EQ(WMError::WM_OK, activeWindows_.back()->Destroy());
107        activeWindows_.pop_back();
108    }
109}
110
111namespace {
112/**
113 * @tc.name: DragIn
114 * @tc.desc: Drag a window to another window
115 * @tc.type: FUNC
116 */
117HWTEST_F(WindowDragTest, DragIn, Function | MediumTest | Level3) {
118    const sptr<Window> &firstWindow = Utils::CreateTestWindow(firstWindowInfo_);
119    if (firstWindow == nullptr) {
120        return;
121    }
122    ASSERT_NE(firstWindow, nullptr);
123    activeWindows_.push_back(firstWindow);
124    firstWindow->RegisterDragListener(firstWindowDragListener_);
125    firstWindow->SetTurnScreenOn(true);
126    firstWindow->Show();
127
128    const sptr<Window> &dragWindow = Utils::CreateTestWindow(dragWindowInfo_);
129    ASSERT_NE(dragWindow, nullptr);
130    activeWindows_.push_back(dragWindow);
131    dragWindow->Show();
132    dragWindow->MoveTo(300, 300);
133    sleep(WAIT_CALLBACK_US);
134
135    ASSERT_EQ(300, firstWindowDragListener_->point_.x);
136    ASSERT_EQ(300, firstWindowDragListener_->point_.y);
137    ASSERT_EQ(DragEvent::DRAG_EVENT_IN, firstWindowDragListener_->event_);
138
139    firstWindow->UnregisterDragListener(firstWindowDragListener_);
140}
141
142/**
143 * @tc.name: DragMove
144 * @tc.desc: Window Move
145 * @tc.type: FUNC
146 */
147HWTEST_F(WindowDragTest, DragMove, Function | MediumTest | Level3) {
148    const sptr<Window> &firstWindow = Utils::CreateTestWindow(firstWindowInfo_);
149    if (firstWindow == nullptr) {
150        return;
151    }
152    ASSERT_NE(firstWindow, nullptr);
153    activeWindows_.push_back(firstWindow);
154    firstWindow->RegisterDragListener(firstWindowDragListener_);
155    firstWindow->SetTurnScreenOn(true);
156    firstWindow->Show();
157
158    const sptr<Window> &dragWindow = Utils::CreateTestWindow(dragWindowInfo_);
159    ASSERT_NE(dragWindow, nullptr);
160    activeWindows_.push_back(dragWindow);
161    dragWindow->Show();
162    dragWindow->MoveTo(300, 300);
163
164    sleep(WAIT_CALLBACK_US);
165    ASSERT_EQ(300, firstWindowDragListener_->point_.x);
166    ASSERT_EQ(300, firstWindowDragListener_->point_.y);
167    ASSERT_EQ(DragEvent::DRAG_EVENT_IN, firstWindowDragListener_->event_);
168
169    dragWindow->MoveTo(400, 400);
170    sleep(WAIT_CALLBACK_US);
171    ASSERT_EQ(400, firstWindowDragListener_->point_.x);
172    ASSERT_EQ(400, firstWindowDragListener_->point_.y);
173    ASSERT_EQ(DragEvent::DRAG_EVENT_MOVE, firstWindowDragListener_->event_);
174
175    firstWindow->UnregisterDragListener(firstWindowDragListener_);
176}
177
178/**
179 * @tc.name: DragOut
180 * @tc.desc: Drag the drag window out of the current window
181 * @tc.type: FUNC
182 */
183HWTEST_F(WindowDragTest, DragOut, Function | MediumTest | Level3) {
184    const sptr<Window> &firstWindow = Utils::CreateTestWindow(firstWindowInfo_);
185    if (firstWindow == nullptr) {
186        return;
187    }
188    ASSERT_NE(firstWindow, nullptr);
189    activeWindows_.push_back(firstWindow);
190    firstWindow->RegisterDragListener(firstWindowDragListener_);
191    firstWindow->SetTurnScreenOn(true);
192    firstWindow->Show();
193
194    secondWindowInfo_.rect = {500, 500, 500, 500};
195    const sptr<Window> &secondWindow = Utils::CreateTestWindow(secondWindowInfo_);
196    ASSERT_NE(secondWindow, nullptr);
197    activeWindows_.push_back(secondWindow);
198    secondWindow->RegisterDragListener(secondWindowDragListener_);
199    secondWindow->Show();
200
201    const sptr<Window> &dragWindow = Utils::CreateTestWindow(dragWindowInfo_);
202    ASSERT_NE(secondWindow, nullptr);
203    activeWindows_.push_back(dragWindow);
204    dragWindow->Show();
205    dragWindow->MoveTo(300, 300);
206
207    sleep(WAIT_CALLBACK_US);
208    ASSERT_EQ(300, firstWindowDragListener_->point_.x);
209    ASSERT_EQ(300, firstWindowDragListener_->point_.y);
210    ASSERT_EQ(DragEvent::DRAG_EVENT_IN, firstWindowDragListener_->event_);
211
212    dragWindow->MoveTo(400, 400);
213    sleep(WAIT_CALLBACK_US);
214    ASSERT_EQ(400, firstWindowDragListener_->point_.x);
215    ASSERT_EQ(400, firstWindowDragListener_->point_.y);
216    ASSERT_EQ(DragEvent::DRAG_EVENT_MOVE, firstWindowDragListener_->event_);
217
218    dragWindow->MoveTo(600, 600);
219    sleep(WAIT_CALLBACK_US);
220    ASSERT_EQ(100, secondWindowDragListener_->point_.x);
221    ASSERT_EQ(100, secondWindowDragListener_->point_.y);
222    ASSERT_EQ(DragEvent::DRAG_EVENT_IN, secondWindowDragListener_->event_);
223    ASSERT_EQ(DragEvent::DRAG_EVENT_OUT, firstWindowDragListener_->event_);
224
225    firstWindow->UnregisterDragListener(firstWindowDragListener_);
226    secondWindow->UnregisterDragListener(secondWindowDragListener_);
227}
228
229/**
230 * @tc.name: DragEnd
231 * @tc.desc: End window drag
232 * @tc.type: FUNC
233 */
234HWTEST_F(WindowDragTest, DragEnd, Function | MediumTest | Level3) {
235    const sptr<Window> firstWindow = Utils::CreateTestWindow(firstWindowInfo_);
236    if (firstWindow == nullptr) {
237        return;
238    }
239    ASSERT_NE(nullptr, firstWindow);
240    firstWindow->RegisterDragListener(firstWindowDragListener_);
241    firstWindow->SetTurnScreenOn(true);
242    firstWindow->Show();
243
244    const sptr<Window> dragWindow = Utils::CreateTestWindow(dragWindowInfo_);
245    ASSERT_NE(nullptr, dragWindow);
246    dragWindow->Show();
247    dragWindow->MoveTo(199, 199);
248
249    sleep(WAIT_CALLBACK_US);
250    dragWindow->Destroy();
251    sleep(WAIT_CALLBACK_US);
252    ASSERT_EQ(DragEvent::DRAG_EVENT_END, firstWindowDragListener_->event_);
253
254    firstWindow->UnregisterDragListener(firstWindowDragListener_);
255    firstWindow->Destroy();
256}
257} // namespace
258} // namespace Rosen
259} // namespace OHOS
260