GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_vertical_list_event_process.c Lines: 106 106 100.0 %
Date: 2026-03-06 19:21:09 Branches: 69 70 98.6 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** GUIX Component                                                        */
17
/**                                                                       */
18
/**   Vertical List (List)                                                */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define GX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "gx_api.h"
28
#include "gx_widget.h"
29
#include "gx_window.h"
30
#include "gx_system.h"
31
#include "gx_scrollbar.h"
32
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _gx_vertical_list_event_process                     PORTABLE C      */
38
/*                                                           6.1.12       */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Kenneth Maxwell, Microsoft Corporation                              */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This service processes an event for the vertical list.              */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    list                                  Vertical list control block   */
50
/*    event_ptr                             Pointer to event to process   */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    status                                Completion status             */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    _gx_vertical_list_selected_set        Set the list entry at the     */
59
/*                                            current list index          */
60
/*    _gx_widget_find                       Retrieve the height of the    */
61
/*                                            widget                      */
62
/*    _gx_vertical_list_children_position   Position the children for     */
63
/*                                            the vertical list           */
64
/*    _gx_first_client_child_get            Get the first client child    */
65
/*    _gx_vertical_list_scroll              Move up or down the scrollbar */
66
/*    _gx_vertical_list_slide_back_check    Check the sliding back of     */
67
/*                                            the scrollbar               */
68
/*    _gx_window_scrollbar_find             Assign a background wallpaper */
69
/*                                            to a GX_WINDOW object       */
70
/*    _gx_scrollbar_reset                   Calculate new scrollbar value */
71
/*    _gx_system_timer_start                Allocate a free timer and     */
72
/*                                            activates it                */
73
/*    _gx_system_top_widget_find            Find top widget under pen     */
74
/*    _gx_system_timer_stop                 Stop an active GUIX timer     */
75
/*    _gx_window_event_process              Process events for the        */
76
/*                                            specified window            */
77
/*                                                                        */
78
/*  CALLED BY                                                             */
79
/*                                                                        */
80
/*    Application Code                                                    */
81
/*                                                                        */
82
/**************************************************************************/
83
3131
UINT  _gx_vertical_list_event_process(GX_VERTICAL_LIST *list, GX_EVENT *event_ptr)
84
{
85
3131
GX_WIDGET    *widget = (GX_WIDGET *)list;
86
GX_SCROLLBAR *pScroll;
87
INT           snap_dist;
88
UINT          timer_id;
89
3131
UINT          status = GX_SUCCESS;
90
GX_WIDGET    *child;
91
INT           list_height;
92
INT           widget_height;
93
INT           new_pen_index;
94
GX_WIDGET   **stackptr;
95
GX_WIDGET   **stacktop;
96
GX_EVENT      input_release_event;
97
98


3131
    switch (event_ptr -> gx_event_type)
99
    {
100
168
    case GX_EVENT_SHOW:
101
102
        /* show the children before attempting to position them, because child
103
           widgets often do not know their size until shown
104
         */
105
106
168
        status = _gx_window_event_process((GX_WINDOW *)list, event_ptr);
107
108
        /* now position the child widgets */
109
168
        if (!list -> gx_vertical_list_child_count)
110
        {
111
143
            _gx_vertical_list_children_position(list);
112
        }
113
114
        /* and now re-calculate scrolling parameters */
115
168
        _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_VERTICAL_SCROLL, &pScroll);
116
117
168
        if (pScroll)
118
        {
119
31
            _gx_scrollbar_reset(pScroll, GX_NULL);
120
        }
121
168
        break;
122
123
2
    case GX_EVENT_FOCUS_NEXT:
124
2
        if (list -> gx_vertical_list_selected < list -> gx_vertical_list_total_rows - 1)
125
        {
126
1
            _gx_vertical_list_selected_set(list, list -> gx_vertical_list_selected + 1);
127
        }
128
2
        break;
129
130
2
    case GX_EVENT_FOCUS_PREVIOUS:
131
2
        if (list -> gx_vertical_list_selected > 0)
132
        {
133
1
            _gx_vertical_list_selected_set(list, list -> gx_vertical_list_selected - 1);
134
        }
135
2
        break;
136
137
335
    case GX_EVENT_VERTICAL_SCROLL:
138
335
        _gx_vertical_list_scroll(list, event_ptr -> gx_event_payload.gx_event_intdata[1] - event_ptr -> gx_event_payload.gx_event_intdata[0]);
139
335
        return 0;
140
141
147
    case GX_EVENT_PEN_DOWN:
142
147
        _gx_system_input_capture(widget);
143
147
        list -> gx_window_move_start = event_ptr -> gx_event_payload.gx_event_pointdata;
144
145
        /* determine which child widget has been selected for future list select event */
146
147
        child = _gx_system_top_widget_find((GX_WIDGET *)list, event_ptr -> gx_event_payload.gx_event_pointdata, GX_STATUS_SELECTABLE);
147
148

150
        while (child && child -> gx_widget_parent != (GX_WIDGET *)list)
149
        {
150
3
            child = child -> gx_widget_parent;
151
        }
152
153
147
        if (child)
154
        {
155
145
            list -> gx_vertical_list_pen_index = list -> gx_vertical_list_top_index + _gx_widget_client_index_get(widget, child);
156
145
            if (list -> gx_vertical_list_pen_index >= list -> gx_vertical_list_total_rows)
157
            {
158
13
                list -> gx_vertical_list_pen_index -= list -> gx_vertical_list_total_rows;
159
            }
160
        }
161
147
        break;
162
163
148
    case GX_EVENT_PEN_UP:
164
148
        if (list -> gx_widget_status & GX_STATUS_OWNS_INPUT)
165
        {
166
146
            _gx_system_input_release(widget);
167
168
146
            list_height = list -> gx_vertical_list_child_count * list -> gx_vertical_list_child_height;
169
146
            widget_height = list -> gx_window_client.gx_rectangle_bottom - list -> gx_window_client.gx_rectangle_top + 1;
170
171
146
            if (list_height > widget_height)
172
            {
173
137
                _gx_vertical_list_slide_back_check(list);
174
            }
175

146
            if (list -> gx_vertical_list_pen_index >= 0 && list -> gx_vertical_list_snap_back_distance == 0)
176
            {
177
                /* test to see if pen-up is over same child widget as pen-down */
178
15
                child = _gx_system_top_widget_find((GX_WIDGET *)list, event_ptr -> gx_event_payload.gx_event_pointdata, GX_STATUS_SELECTABLE);
179

16
                while (child && child -> gx_widget_parent != (GX_WIDGET *)list)
180
                {
181
1
                    child = child -> gx_widget_parent;
182
                }
183
184
15
                if (child)
185
                {
186
13
                    new_pen_index = list -> gx_vertical_list_top_index + _gx_widget_client_index_get(widget, child);
187
13
                    if (new_pen_index >= list -> gx_vertical_list_total_rows)
188
                    {
189
1
                        new_pen_index -= list -> gx_vertical_list_total_rows;
190
                    }
191
13
                    if (new_pen_index == list -> gx_vertical_list_pen_index)
192
                    {
193
12
                        _gx_vertical_list_selected_set(list, list -> gx_vertical_list_pen_index);
194
                    }
195
                }
196
            }
197
        }
198
        else
199
        {
200
2
            _gx_widget_event_to_parent((GX_WIDGET *)list, event_ptr);
201
        }
202
148
        break;
203
204
133
    case GX_EVENT_PEN_DRAG:
205
133
        if ((widget -> gx_widget_status & GX_STATUS_OWNS_INPUT) &&
206
132
            (event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_y - list -> gx_window_move_start.gx_point_y) != 0)
207
        {
208
131
            list_height = list -> gx_vertical_list_child_count * list -> gx_vertical_list_child_height;
209
131
            widget_height = list -> gx_window_client.gx_rectangle_bottom - list -> gx_window_client.gx_rectangle_top + 1;
210
211
131
            if (list_height > widget_height)
212
            {
213
                /* Start sliding, remove other widgets from input capture stack.  */
214
130
                stackptr = _gx_system_input_capture_stack;
215
130
                stacktop = _gx_system_input_capture_stack + _gx_system_capture_count;
216
217
130
                memset(&input_release_event, 0, sizeof(GX_EVENT));
218
130
                input_release_event.gx_event_type = GX_EVENT_INPUT_RELEASE;
219
220
262
                while (stackptr < stacktop)
221
                {
222

132
                    if (*stackptr != GX_NULL && *stackptr != widget)
223
                    {
224
2
                        input_release_event.gx_event_target = *stackptr;
225
2
                        _gx_system_event_send(&input_release_event);
226
                    }
227
132
                    stackptr++;
228
                }
229
230
130
                _gx_vertical_list_scroll(list,
231
130
                                         event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_y -
232
130
                                         list -> gx_window_move_start.gx_point_y);
233
130
                _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_VERTICAL_SCROLL, &pScroll);
234
235
130
                if (pScroll)
236
                {
237
67
                    _gx_scrollbar_reset(pScroll, GX_NULL);
238
                }
239
130
                list -> gx_window_move_start = event_ptr -> gx_event_payload.gx_event_pointdata;
240
130
                list -> gx_vertical_list_pen_index = -1;
241
            }
242
        }
243
        else
244
        {
245
2
            _gx_widget_event_to_parent((GX_WIDGET *)list, event_ptr);
246
        }
247
133
        break;
248
249
6
    case GX_EVENT_VERTICAL_FLICK:
250
6
        list_height = list -> gx_vertical_list_child_count * list -> gx_vertical_list_child_height;
251
6
        widget_height = list -> gx_window_client.gx_rectangle_bottom - list -> gx_window_client.gx_rectangle_top + 1;
252
253
6
        if (list_height > widget_height)
254
        {
255
4
            list -> gx_vertical_list_snap_back_distance = (GX_VALUE)(GX_FIXED_VAL_TO_INT(event_ptr -> gx_event_payload.gx_event_intdata[0]) * 8);
256
4
            _gx_system_timer_start((GX_WIDGET *)list, GX_FLICK_TIMER, 1, 1);
257
        }
258
6
        list -> gx_vertical_list_pen_index = -1;
259
6
        break;
260
261
152
    case GX_EVENT_TIMER:
262
152
        timer_id = event_ptr -> gx_event_payload.gx_event_timer_id;
263
264

152
        if (timer_id == GX_FLICK_TIMER || timer_id == GX_SNAP_TIMER)
265
        {
266
151
            if (GX_ABS(list -> gx_vertical_list_snap_back_distance) < GX_ABS(list -> gx_vertical_list_child_height) / 3)
267
            {
268
21
                _gx_system_timer_stop(widget, event_ptr -> gx_event_payload.gx_event_timer_id);
269
21
                _gx_vertical_list_scroll(list, list -> gx_vertical_list_snap_back_distance);
270
271
21
                if (event_ptr -> gx_event_payload.gx_event_timer_id == GX_FLICK_TIMER)
272
                {
273
3
                    _gx_vertical_list_slide_back_check(list);
274
                }
275
            }
276
            else
277
            {
278
130
                snap_dist = (list -> gx_vertical_list_snap_back_distance) / 5;
279
130
                list -> gx_vertical_list_snap_back_distance = (GX_VALUE)(list -> gx_vertical_list_snap_back_distance - snap_dist);
280
130
                _gx_vertical_list_scroll(list, snap_dist);
281
            }
282
151
            _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_VERTICAL_SCROLL, &pScroll);
283
284
151
            if (pScroll)
285
            {
286
149
                _gx_scrollbar_reset(pScroll, GX_NULL);
287
            }
288
        }
289
        else
290
        {
291
1
            status = _gx_window_event_process((GX_WINDOW *)list, event_ptr);
292
        }
293
152
        break;
294
295
2038
    default:
296
2038
        status = _gx_window_event_process((GX_WINDOW *)list, event_ptr);
297
2038
        break;
298
    }
299
300
2796
    return status;
301
}
302