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_system.h"
28 #include "gx_widget.h"
29 #include "gx_animation.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _gx_animation_drag_event_check                      PORTABLE C      */
37 /*                                                           6.1.8        */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Kenneth Maxwell, Microsoft Corporation                              */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    Internal helper function that handles incoming events for screen    */
45 /*    drag animation.                                                     */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    animation                             Pointer to animation control  */
50 /*                                            block                       */
51 /*    event_ptr                             Event to process              */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    status                                Completion status             */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _gx_animation_slide_landing           Move animation screens one    */
60 /*                                            step toward target position */
61 /*    _gx_animation_slide_landing_start     Prepare for screen landing    */
62 /*    _gx_animation_drag_tracking_start     Prepare for screen slide      */
63 /*                                            animation                   */
64 /*    _gx_animation_drag_tracking           Shift animation screens       */
65 /*                                            accordion to pen pos        */
66 /*    _gx_system_event_send                 Send an event for processing  */
67 /*    _gx_system_input_capture              Temporarily direct all input  */
68 /*                                            events to specified widget  */
69 /*    _gx_system_input_release              Release captured input events */
70 /*    _gx_system_timer_stop                 Stop a timer for a widget     */
71 /*                                                                        */
72 /*  CALLED BY                                                             */
73 /*                                                                        */
74 /*    _gx_animation_drag_event_process                                    */
75 /*                                                                        */
76 /*  RELEASE HISTORY                                                       */
77 /*                                                                        */
78 /*    DATE              NAME                      DESCRIPTION             */
79 /*                                                                        */
80 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
81 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
82 /*                                            resulting in version 6.1    */
83 /*  08-02-2021     Kenneth Maxwell          Modified comment(s),          */
84 /*                                            replaced abs with GX_ABS,   */
85 /*                                            resulting in version 6.1.8  */
86 /*                                                                        */
87 /**************************************************************************/
_gx_animation_drag_event_check(GX_ANIMATION * animation,GX_EVENT * event_ptr)88 static UINT  _gx_animation_drag_event_check(GX_ANIMATION *animation, GX_EVENT *event_ptr)
89 {
90 GX_ANIMATION_INFO *info = &animation -> gx_animation_info;
91 GX_RECTANGLE      *size;
92 INT                delta;
93 INT                temp;
94 GX_WIDGET        **stackptr;
95 GX_EVENT           input_release_event;
96 INT                shift;
97 
98     switch (event_ptr -> gx_event_type)
99     {
100     case GX_EVENT_PEN_DOWN:
101         if (animation -> gx_animation_status == GX_ANIMATION_IDLE)
102         {
103             _gx_system_input_capture(info -> gx_animation_parent);
104 
105             /* Initiate animation information. */
106             animation -> gx_animation_status = GX_ANIMATION_SLIDE_TRACKING;
107 
108             if (info -> gx_animation_style & GX_ANIMATION_VERTICAL)
109             {
110                 animation -> gx_animation_slide_tracking_start_pos = event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_y;
111                 animation -> gx_animation_slide_tracking_current_pos = event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_y;
112             }
113             else
114             {
115                 animation -> gx_animation_slide_tracking_start_pos = event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_x;
116                 animation -> gx_animation_slide_tracking_current_pos = event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_x;
117             }
118             animation -> gx_animation_slide_target_index_1 = -1;
119             animation -> gx_animation_slide_target_index_2 = -1;
120         }
121         break;
122 
123     case GX_EVENT_PEN_DRAG:
124         if (animation -> gx_animation_status == GX_ANIMATION_SLIDE_TRACKING)
125         {
126             if (info -> gx_animation_style & GX_ANIMATION_VERTICAL)
127             {
128                 delta = GX_ABS(event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_y - animation -> gx_animation_slide_tracking_start_pos);
129             }
130             else
131             {
132                 delta = GX_ABS(event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_x - animation -> gx_animation_slide_tracking_start_pos);
133             }
134 
135             if ((animation -> gx_animation_slide_target_index_1 == -1) &&
136                 (delta > GX_ANIMATION_MIN_SLIDING_DIST))
137             {
138                 /* Start swiping, remove other widgets from input capture stack.  */
139                 stackptr = _gx_system_input_capture_stack;
140                 memset(&input_release_event, 0, sizeof(GX_EVENT));
141                 input_release_event.gx_event_type = GX_EVENT_INPUT_RELEASE;
142 
143                 while (*stackptr)
144                 {
145                     if (*stackptr != info -> gx_animation_parent)
146                     {
147                         input_release_event.gx_event_target = *stackptr;
148                         _gx_system_event_send(&input_release_event);
149                     }
150                     stackptr++;
151                 }
152 
153                 _gx_animation_drag_tracking_start(animation, event_ptr -> gx_event_payload.gx_event_pointdata);
154             }
155 
156              _gx_animation_drag_tracking(animation, event_ptr -> gx_event_payload.gx_event_pointdata);
157         }
158         break;
159 
160     case GX_EVENT_PEN_UP:
161         if (animation -> gx_animation_status == GX_ANIMATION_SLIDE_TRACKING)
162         {
163             _gx_system_input_release(info -> gx_animation_parent);
164             animation -> gx_animation_status = GX_ANIMATION_IDLE;
165 
166             size = &info -> gx_animation_parent -> gx_widget_size;
167 
168             delta = animation -> gx_animation_slide_tracking_current_pos - animation -> gx_animation_slide_tracking_start_pos;
169             if (info -> gx_animation_style & GX_ANIMATION_VERTICAL)
170             {
171                 shift = (size -> gx_rectangle_bottom - size -> gx_rectangle_top + 1) >> 1;
172             }
173             else
174             {
175                 shift = (size -> gx_rectangle_right - size -> gx_rectangle_left + 1) >> 1;
176             }
177 
178             if ((GX_ABS(delta) < shift) || (animation -> gx_animation_slide_target_index_2 == -1))
179             {
180                 /* slide back to original when slide distance is less than half screen width/height. */
181                 if (animation -> gx_animation_slide_target_index_2 >= 0)
182                 {
183                     temp = animation -> gx_animation_slide_target_index_1;
184                     animation -> gx_animation_slide_target_index_1 = animation -> gx_animation_slide_target_index_2;
185                     animation -> gx_animation_slide_target_index_2 = (GX_VALUE)temp;
186                 }
187 
188                 switch (animation -> gx_animation_slide_direction)
189                 {
190                 case GX_ANIMATION_SLIDE_LEFT:
191                     animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_RIGHT;
192                     break;
193 
194                 case GX_ANIMATION_SLIDE_RIGHT:
195                     animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_LEFT;
196                     break;
197 
198                 case GX_ANIMATION_SLIDE_UP:
199                     animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_DOWN;
200                     break;
201 
202                 case GX_ANIMATION_SLIDE_DOWN:
203                     animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_UP;
204                     break;
205                 }
206             }
207 
208             if (delta)
209             {
210                 _gx_animation_slide_landing_start(animation);
211             }
212         }
213         break;
214 
215     case GX_EVENT_HORIZONTAL_FLICK:
216     case GX_EVENT_VERTICAL_FLICK:
217         if (animation -> gx_animation_status == GX_ANIMATION_SLIDE_LANDING)
218         {
219             delta = event_ptr -> gx_event_payload.gx_event_intdata[0];
220 
221             if (((animation -> gx_animation_slide_direction == GX_ANIMATION_SLIDE_LEFT) && (delta > 0)) ||
222                 ((animation -> gx_animation_slide_direction == GX_ANIMATION_SLIDE_RIGHT) && (delta < 0)) ||
223                 ((animation -> gx_animation_slide_direction == GX_ANIMATION_SLIDE_UP) && (delta > 0)) ||
224                 ((animation -> gx_animation_slide_direction == GX_ANIMATION_SLIDE_DOWN) && (delta < 0)))
225             {
226                 /* landing direction is different to flick direction
227                    exchange targets */
228                 if (animation -> gx_animation_slide_target_index_2 >= 0)
229                 {
230                     temp = animation -> gx_animation_slide_target_index_1;
231                     animation -> gx_animation_slide_target_index_1 = animation -> gx_animation_slide_target_index_2;
232                     animation -> gx_animation_slide_target_index_2 = (GX_VALUE)temp;
233                 }
234 
235                 animation -> gx_animation_status = GX_ANIMATION_IDLE;
236 
237                 switch (animation -> gx_animation_slide_direction)
238                 {
239                 case GX_ANIMATION_SLIDE_LEFT:
240                     animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_RIGHT;
241                     break;
242 
243                 case GX_ANIMATION_SLIDE_RIGHT:
244                     animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_LEFT;
245                     break;
246 
247                 case GX_ANIMATION_SLIDE_UP:
248                     animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_DOWN;
249                     break;
250 
251                 default:
252                     animation -> gx_animation_slide_direction = GX_ANIMATION_SLIDE_UP;
253                     break;
254                 }
255             }
256 
257             if (delta)
258             {
259                 _gx_animation_slide_landing_start(animation);
260             }
261         }
262         break;
263 
264     case GX_EVENT_TIMER:
265         if (event_ptr -> gx_event_payload.gx_event_timer_id == GX_ANIMATION_SLIDE_TIMER)
266         {
267             if (animation -> gx_animation_status != GX_ANIMATION_SLIDE_LANDING)
268             {
269                 _gx_system_timer_stop(info -> gx_animation_parent, GX_ANIMATION_SLIDE_TIMER);
270                 break;
271             }
272 
273             _gx_animation_slide_landing(animation);
274         }
275         break;
276     }
277 
278     return GX_SUCCESS;
279 }
280 
281 /**************************************************************************/
282 /*                                                                        */
283 /*  FUNCTION                                               RELEASE        */
284 /*                                                                        */
285 /*    _gx_animation_drag_event_process                    PORTABLE C      */
286 /*                                                           6.1          */
287 /*  AUTHOR                                                                */
288 /*                                                                        */
289 /*    Kenneth Maxwell, Microsoft Corporation                              */
290 /*                                                                        */
291 /*  DESCRIPTION                                                           */
292 /*                                                                        */
293 /*    This function handles incoming events for screen drag animation.    */
294 /*                                                                        */
295 /*  INPUT                                                                 */
296 /*                                                                        */
297 /*    widget                                Pointer to widget control     */
298 /*                                            block                       */
299 /*    event_ptr                             Event to process              */
300 /*                                                                        */
301 /*  OUTPUT                                                                */
302 /*                                                                        */
303 /*    status                                Completion status             */
304 /*                                                                        */
305 /*  CALLS                                                                 */
306 /*                                                                        */
307 /*    _gx_animation_slide_event_check       Handle incoming events for    */
308 /*                                            screen drag animation       */
309 /*                                                                        */
310 /*  CALLED BY                                                             */
311 /*                                                                        */
312 /*    GUIX Internal Code                                                  */
313 /*                                                                        */
314 /*  RELEASE HISTORY                                                       */
315 /*                                                                        */
316 /*    DATE              NAME                      DESCRIPTION             */
317 /*                                                                        */
318 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
319 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
320 /*                                            resulting in version 6.1    */
321 /*                                                                        */
322 /**************************************************************************/
_gx_animation_drag_event_process(GX_WIDGET * widget,GX_EVENT * event_ptr)323 UINT  _gx_animation_drag_event_process(GX_WIDGET *widget, GX_EVENT *event_ptr)
324 {
325 GX_ANIMATION *animation;
326 
327     animation = _gx_system_animation_list;
328 
329     while (animation)
330     {
331         if ((animation -> gx_animation_info.gx_animation_parent == widget) &&
332             (animation -> gx_animation_original_event_process_function))
333         {
334             _gx_animation_drag_event_check(animation, event_ptr);
335 
336             /* Call original event process function.  */
337             animation -> gx_animation_original_event_process_function(widget, event_ptr);
338         }
339 
340         animation = animation -> gx_animation_next;
341     }
342 
343     return GX_SUCCESS;
344 }
345 
346