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