1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** GUIX Component */
16 /** */
17 /** Animation Management (Animation) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_widget.h"
28 #include "gx_animation.h"
29 #include "gx_system.h"
30 #include "gx_canvas.h"
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _gx_animation_drag_tracking_start PORTABLE C */
37 /* 6.1.11 */
38 /* AUTHOR */
39 /* */
40 /* Kenneth Maxwell, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function prepares for screen slide animation. */
45 /* */
46 /* INPUT */
47 /* */
48 /* animation Pointer to animation control */
49 /* block */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* status Completion status */
54 /* */
55 /* CALLS */
56 /* */
57 /* _gx_widget_resize Resize widget */
58 /* _gx_widget_attach Attach a widget to its parent */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* _gx_animation_drag_event_check */
63 /* */
64 /* RELEASE HISTORY */
65 /* */
66 /* DATE NAME DESCRIPTION */
67 /* */
68 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
69 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
70 /* resulting in version 6.1 */
71 /* 04-25-2022 Ting Zhu Modified comment(s), */
72 /* added canvas support, */
73 /* resulting in version 6.1.11 */
74 /* */
75 /**************************************************************************/
_gx_animation_drag_tracking_start(GX_ANIMATION * animation,GX_POINT penpos)76 UINT _gx_animation_drag_tracking_start(GX_ANIMATION *animation, GX_POINT penpos)
77 {
78 GX_ANIMATION_INFO *info;
79 GX_RECTANGLE size;
80 INT width;
81 GX_WIDGET *target_1;
82 GX_WIDGET *target_2 = GX_NULL;
83 INT index;
84 INT current_pos;
85 GX_WINDOW_ROOT *root;
86 GX_VALUE left;
87 GX_VALUE top;
88 VOID (*active_display_area_set)(INT layer, GX_RECTANGLE *size);
89
90 info = &animation -> gx_animation_info;
91
92 target_1 = info -> gx_animation_slide_screen_list[0];
93 index = 0;
94
95 /* Search for visible screen, which is the first animation target. */
96 while (target_1)
97 {
98 if (target_1 -> gx_widget_status & GX_STATUS_VISIBLE)
99 {
100 animation -> gx_animation_slide_target_index_1 = (GX_VALUE)index;
101 }
102 index++;
103 target_1 = info -> gx_animation_slide_screen_list[index];
104 }
105
106 animation -> gx_animation_slide_screen_list_size = (USHORT)index;
107
108 if (animation -> gx_animation_slide_target_index_1 == -1)
109 {
110 return(GX_FAILURE);
111 }
112
113 if (info -> gx_animation_style & GX_ANIMATION_VERTICAL)
114 {
115 current_pos = penpos.gx_point_y;
116 }
117 else
118 {
119 current_pos = penpos.gx_point_x;
120 }
121
122 /* Find second animation target according to sliding direction. */
123 if (current_pos < animation -> gx_animation_slide_tracking_start_pos)
124 {
125 /* Sliding left/up. */
126 index = animation -> gx_animation_slide_target_index_1 + 1;
127
128 if ((index >= animation -> gx_animation_slide_screen_list_size) &&
129 (info -> gx_animation_style & GX_ANIMATION_WRAP))
130 {
131 index = 0;
132 }
133 }
134 else
135 {
136 /* Sliding right/down. */
137 index = animation -> gx_animation_slide_target_index_1 - 1;
138
139 if ((index < 0) && (info -> gx_animation_style & GX_ANIMATION_WRAP))
140 {
141 index = animation -> gx_animation_slide_screen_list_size - 1;
142 }
143 }
144
145 if (info -> gx_animation_style & GX_ANIMATION_VERTICAL)
146 {
147 if (current_pos < animation -> gx_animation_slide_tracking_start_pos)
148 {
149 animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_UP;
150 }
151 else
152 {
153 animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_DOWN;
154 }
155 }
156 else
157 {
158 if (current_pos < animation -> gx_animation_slide_tracking_start_pos)
159 {
160 animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_LEFT;
161 }
162 else
163 {
164 animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_RIGHT;
165 }
166 }
167
168 target_1 = info -> gx_animation_slide_screen_list[animation -> gx_animation_slide_target_index_1];
169
170 if ((index >= 0) && (index < animation -> gx_animation_slide_screen_list_size))
171 {
172 animation -> gx_animation_slide_target_index_2 = (GX_VALUE)(index);
173
174 target_2 = info -> gx_animation_slide_screen_list[index];
175
176 size = target_2 -> gx_widget_size;
177
178 if (info -> gx_animation_style & GX_ANIMATION_VERTICAL)
179 {
180 width = size.gx_rectangle_bottom - size.gx_rectangle_top + 1;
181
182 switch (animation -> gx_animation_slide_direction)
183 {
184 case GX_ANIMATION_SLIDE_UP:
185
186 /* Slide up. */
187 size.gx_rectangle_top = (GX_VALUE)(target_1 -> gx_widget_size.gx_rectangle_bottom + 1);
188 size.gx_rectangle_bottom = (GX_VALUE)(size.gx_rectangle_top + width - 1);
189 break;
190
191 default:
192 /* Slide down. */
193 size.gx_rectangle_bottom = (GX_VALUE)(target_1 -> gx_widget_size.gx_rectangle_top - 1);
194 size.gx_rectangle_top = (GX_VALUE)(size.gx_rectangle_bottom - width + 1);
195 break;
196 }
197 size.gx_rectangle_left = (GX_VALUE)target_1 -> gx_widget_size.gx_rectangle_left;
198 size.gx_rectangle_right = (GX_VALUE)target_1 -> gx_widget_size.gx_rectangle_right;
199 }
200 else
201 {
202 width = size.gx_rectangle_right - size.gx_rectangle_left + 1;
203
204 switch (animation -> gx_animation_slide_direction)
205 {
206 case GX_ANIMATION_SLIDE_LEFT:
207 /* Slide left. */
208 size.gx_rectangle_left = (GX_VALUE)(target_1 -> gx_widget_size.gx_rectangle_right + 1);
209 size.gx_rectangle_right = (GX_VALUE)(size.gx_rectangle_left + width - 1);
210 break;
211 default:
212 /* Slide right. */
213 size.gx_rectangle_right = (GX_VALUE)(target_1 -> gx_widget_size.gx_rectangle_left - 1);
214 size.gx_rectangle_left = (GX_VALUE)(size.gx_rectangle_right - width + 1);
215 break;
216 }
217
218 size.gx_rectangle_top = (GX_VALUE)target_1 -> gx_widget_size.gx_rectangle_top;
219 size.gx_rectangle_bottom = (GX_VALUE)target_1 -> gx_widget_size.gx_rectangle_bottom;
220 }
221
222 /* Resize the second animation target. */
223 _gx_widget_resize(target_2, &size);
224
225 if (!animation -> gx_animation_canvas)
226 {
227
228 /* Attach the second target to animation parent. */
229 _gx_widget_attach(info -> gx_animation_parent, target_2);
230 }
231 }
232 else
233 {
234 animation -> gx_animation_slide_target_index_2 = -1;
235 }
236
237 if (animation -> gx_animation_canvas)
238 {
239 /* Find animation root. */
240 root = _gx_system_root_window_created_list;
241 while (root && root -> gx_window_root_canvas != animation -> gx_animation_canvas)
242 {
243 root = (GX_WINDOW_ROOT *)root -> gx_widget_next;
244 }
245
246 if (animation -> gx_animation_slide_direction == GX_ANIMATION_SLIDE_UP ||
247 animation -> gx_animation_slide_direction == GX_ANIMATION_SLIDE_LEFT ||
248 (!target_2))
249 {
250 left = target_1 -> gx_widget_size.gx_rectangle_left;
251 top = target_1 -> gx_widget_size.gx_rectangle_top;
252 }
253 else
254 {
255 left = target_2 -> gx_widget_size.gx_rectangle_left;
256 top = target_2 -> gx_widget_size.gx_rectangle_top;
257 }
258
259 if (left || top)
260 {
261 _gx_widget_shift(target_1, (GX_VALUE)-left, (GX_VALUE)-top, GX_TRUE);
262
263 if (target_2)
264 {
265 _gx_widget_shift(target_2, (GX_VALUE)-left, (GX_VALUE)-top, GX_TRUE);
266 }
267 }
268
269 /* Position the canvas at the animation starting position. */
270 _gx_canvas_offset_set(animation -> gx_animation_canvas, left, top);
271
272 if (animation -> gx_animation_canvas -> gx_canvas_hardware_layer >= 0)
273 {
274 active_display_area_set = animation -> gx_animation_canvas -> gx_canvas_display -> gx_display_layer_services -> gx_display_layer_active_display_area_set;
275
276 if (active_display_area_set)
277 {
278 /* Set active display area as the animation parent widget size. */
279 active_display_area_set(animation -> gx_animation_canvas -> gx_canvas_hardware_layer, &info -> gx_animation_parent -> gx_widget_size);
280 }
281 }
282
283 if (root)
284 {
285 /* Link the target to the animation root window. */
286 _gx_widget_attach((GX_WIDGET *)root, target_1);
287
288 if (target_2)
289 {
290 _gx_widget_attach((GX_WIDGET *)root, target_2);
291 }
292
293 /* and show the animation root window to make everything visible */
294 _gx_widget_show((GX_WIDGET *)root);
295 _gx_canvas_drawing_initiate(animation -> gx_animation_canvas, (GX_WIDGET *)root, &root -> gx_widget_size);
296 _gx_widget_children_draw((GX_WIDGET *)root);
297 _gx_canvas_drawing_complete(animation -> gx_animation_canvas, GX_FALSE);
298
299 /* set the initial alpha and make our canvas visible */
300 _gx_canvas_alpha_set(animation -> gx_animation_canvas, info -> gx_animation_start_alpha);
301 _gx_canvas_show(animation -> gx_animation_canvas);
302 }
303 }
304
305 /* Return completion status code. */
306 return(GX_SUCCESS);
307 }
308
309