1 /*
2 * Copyright (c) 2021-2023 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 <event_handler.h>
17 #include <iostream>
18 #include <surface.h>
19
20 #include "include/core/SkCanvas.h"
21 #include "include/core/SkColor.h"
22 #include "window.h"
23
24 #include "accesstoken_kit.h"
25 #ifdef SUPPORT_ACCESS_TOKEN
26 #include "nativetoken_kit.h"
27 #include "token_setproc.h"
28 #endif
29 #include "modifier/rs_extended_modifier.h"
30 #include "modifier/rs_property_modifier.h"
31 #include "render/rs_border.h"
32 #include "transaction/rs_transaction.h"
33 #include "ui/rs_display_node.h"
34 #include "ui/rs_root_node.h"
35 #include "ui/rs_surface_extractor.h"
36 #include "ui/rs_surface_node.h"
37 #include "ui/rs_ui_director.h"
38
39 using namespace OHOS;
40 using namespace OHOS::Rosen;
41 using namespace std;
42
43 std::shared_ptr<RSNode> rootNode;
44 std::vector<std::shared_ptr<RSCanvasNode>> nodes;
45
Init(std::shared_ptr<RSUIDirector> rsUiDirector,int width,int height)46 void Init(std::shared_ptr<RSUIDirector> rsUiDirector, int width, int height)
47 {
48 std::cout << "rs app demo Init Rosen Backend!" << std::endl;
49
50 rootNode = RSRootNode::Create();
51 rootNode->SetBounds(0, 0, width, height);
52 rootNode->SetFrame(0, 0, width, height);
53 rootNode->SetBackgroundColor(SK_ColorYELLOW);
54
55 nodes.emplace_back(RSCanvasNode::Create());
56 nodes[0]->SetBounds(10, 10, 100, 100);
57 nodes[0]->SetFrame(10, 10, 100, 100);
58 nodes[0]->SetBackgroundColor(SK_ColorBLUE);
59
60 rootNode->AddChild(nodes[0], -1);
61
62 rootNode->AddChild(nodes[0], -1);
63 rsUiDirector->SetRoot(rootNode->GetId());
64 }
65
66 class NodeModifier : public RSNodeModifier {
67 public:
68 NodeModifier() = default;
69 virtual ~NodeModifier() = default;
70
Modify(RSNode & target) const71 void Modify(RSNode& target) const override
72 {
73 target.SetTranslate(translate_->Get());
74 }
75
SetTranslate(Vector2f translate)76 void SetTranslate(Vector2f translate)
77 {
78 if (translate_ == nullptr) {
79 translate_ = std::make_shared<RSAnimatableProperty<Vector2f>>(translate);
80 AttachProperty(translate_);
81 } else {
82 translate_->Set(translate);
83 }
84 }
85
GetTranslate() const86 Vector2f GetTranslate() const
87 {
88 return currentTranslateValue_;
89 }
90
SetTranslateCallBack()91 bool SetTranslateCallBack()
92 {
93 if (!translate_) {
94 return false;
95 }
96
97 // add callback for each frame
98 translate_->SetUpdateCallback([&](Vector2f vec) { currentTranslateValue_ = vec; });
99 return true;
100 }
101
102 Vector2f currentTranslateValue_ = Vector2f(0.0f, 0.0f);
103
104 private:
105 std::shared_ptr<RSAnimatableProperty<Vector2f>> translate_;
106 };
107
InitNativeTokenInfo()108 void InitNativeTokenInfo()
109 {
110 #ifdef SUPPORT_ACCESS_TOKEN
111 uint64_t tokenId;
112 const char *perms[1];
113 perms[0] = "ohos.permission.SYSTEM_FLOAT_WINDOW";
114 NativeTokenInfoParams infoInstance = {
115 .dcapsNum = 0,
116 .permsNum = 1,
117 .aclsNum = 0,
118 .dcaps = NULL,
119 .perms = perms,
120 .acls = NULL,
121 .processName = "render_service_client_gesture_interrupt_animation_demo",
122 .aplStr = "system_basic",
123 };
124 tokenId = GetAccessTokenId(&infoInstance);
125 SetSelfTokenID(tokenId);
126 Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
127 std::cout << "init native token for float window" << std::endl;
128 #endif
129 }
130
main()131 int main()
132 {
133 #ifdef SUPPORT_ACCESS_TOKEN
134 int cnt = 0;
135 InitNativeTokenInfo();
136 // Init demo env
137 std::cout << "rs app demo start!" << std::endl;
138 sptr<WindowOption> option = new WindowOption();
139 option->SetWindowType(WindowType::WINDOW_TYPE_FLOAT);
140 option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
141 option->SetWindowRect({ 0, 0, 720, 1280 });
142 auto window = Window::Create("app_demo", option);
143 window->Show();
144 sleep(1);
145 auto rect = window->GetRect();
146 while (rect.width_ == 0 && rect.height_ == 0) {
147 std::cout << "rs app demo create window failed: " << rect.width_ << " " << rect.height_ << std::endl;
148 window->Hide();
149 window->Destroy();
150 window = Window::Create("app_demo", option);
151 window->Show();
152 sleep(1);
153 rect = window->GetRect();
154 }
155 std::cout << "rs app demo create window " << rect.width_ << " " << rect.height_ << std::endl;
156 auto surfaceNode = window->GetSurfaceNode();
157
158 // Build rosen renderThread & create nodes
159 std::cout << "rs app demo stage " << cnt++ << std::endl;
160 auto rsUiDirector = RSUIDirector::Create();
161 rsUiDirector->Init();
162 auto runner = OHOS::AppExecFwk::EventRunner::Create(true);
163 auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
164 rsUiDirector->SetUITaskRunner(
165 [handler](const std::function<void()>& task, uint32_t delay) { handler->PostTask(task); });
166 runner->Run();
167 RSTransaction::FlushImplicitTransaction();
168 rsUiDirector->SetRSSurfaceNode(surfaceNode);
169 Init(rsUiDirector, rect.width_, rect.height_);
170
171 std::cout << "rs app demo stage " << cnt++ << std::endl;
172
173 // simulate sliding trajecity
174 int pointsNum = 30;
175 vector<Vector2f> handPoint(pointsNum);
176 for (int i = 0; i < handPoint.size(); i++) {
177 handPoint[i].data_[0] = 0.0f;
178 handPoint[i].data_[1] = 0.5f * i * i;
179 }
180
181 // simulate sliding stage
182 for (auto vec : handPoint) {
183 nodes[0]->SetTranslate(vec);
184 rsUiDirector->SendMessages();
185 usleep(30000);
186 }
187
188 // calculate sliding velocity
189 auto velocity = (handPoint[pointsNum - 1] - handPoint[pointsNum - 2]) * (1.0f / (30000.0f * 1e-6));
190
191 // calculate final points
192 Vector2f finalTrans = handPoint[pointsNum - 1] + velocity * 0.5;
193
194 std::cout << "rs app demo stage " << cnt++ << std::endl;
195
196 auto nodeModifier = std::make_shared<NodeModifier>();
197 nodes[0]->AddModifier(nodeModifier);
198
199 // init property
200 nodes[0]->SetTranslate(handPoint[pointsNum - 1]);
201
202 RSAnimationTimingProtocol protocol;
203 // duration is not effective when the curve is interpolatingSpring
204 protocol.SetDuration(3000);
205
206 auto timingCurve = RSAnimationTimingCurve::CreateInterpolatingSpring(1.0f, 225.0f, 30.0f, 2.0f);
207
208 // create property animation
209 RSNode::Animate(
210 protocol, timingCurve,
211 [&]() {
212 std::cout << "the end tranlate of sliding animation is " << finalTrans.data_[0] << ", "
213 << finalTrans.data_[1] << std::endl;
214 nodeModifier->SetTranslate(finalTrans);
215 },
216 []() { std::cout << "sliding animation finish callback" << std::endl; });
217
218 int64_t startNum = 80825861106;
219 int64_t interruptNum = 80825861106 * 15;
220
221 bool hasRunningAnimation = true;
222 bool stopSignal = true;
223
224 while (hasRunningAnimation) {
225 hasRunningAnimation = rsUiDirector->FlushAnimation(startNum);
226 rsUiDirector->FlushModifier();
227 rsUiDirector->SendMessages();
228 std::cout << "the current translate is " << nodeModifier->GetTranslate().data_[0] << ", "
229 << nodeModifier->GetTranslate().data_[1] << endl;
230
231 // simulate to stop animation by gesture
232 if ((startNum >= interruptNum) && stopSignal) {
233 std::cout << "stop sliding animation in current translate " << nodeModifier->GetTranslate().data_[0] << ", "
234 << nodeModifier->GetTranslate().data_[1] << endl;
235
236 // set duration to 0
237 protocol.SetDuration(0);
238
239 // create interrupt animation
240 RSNode::Animate(
241 protocol, RSAnimationTimingCurve::EASE_IN_OUT,
242 [&]() { nodeModifier->SetTranslate(nodeModifier->GetTranslate()); },
243 [&]() {
244 std::cout << "interrupt animation finish callback, the end translate is "
245 << nodeModifier->GetTranslate().data_[0] << ", " << nodeModifier->GetTranslate().data_[1]
246 << std::endl;
247 });
248
249 stopSignal = false;
250 }
251 startNum += 100000000;
252 usleep(100000);
253 }
254
255 // dump property via modifiers
256 std::cout << "rs app demo stage " << cnt++ << std::endl;
257 std::cout << nodes[0]->GetStagingProperties().Dump() << std::endl;
258 std::cout << "rs app demo end!" << std::endl;
259 sleep(3);
260
261 window->Hide();
262 window->Destroy();
263 #endif
264 return 0;
265 }