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