GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_vertical_list_event_process.c Lines: 106 106 100.0 %
Date: 2024-12-05 08:52:37 Branches: 69 70 98.6 %

Line Branch Exec Source
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
/**   Vertical List (List)                                                */
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_window.h"
29
#include "gx_system.h"
30
#include "gx_scrollbar.h"
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_vertical_list_event_process                     PORTABLE C      */
37
/*                                                           6.1.12       */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This service processes an event for the vertical list.              */
45
/*                                                                        */
46
/*  INPUT                                                                 */
47
/*                                                                        */
48
/*    list                                  Vertical list control block   */
49
/*    event_ptr                             Pointer to event to process   */
50
/*                                                                        */
51
/*  OUTPUT                                                                */
52
/*                                                                        */
53
/*    status                                Completion status             */
54
/*                                                                        */
55
/*  CALLS                                                                 */
56
/*                                                                        */
57
/*    _gx_vertical_list_selected_set        Set the list entry at the     */
58
/*                                            current list index          */
59
/*    _gx_widget_find                       Retrieve the height of the    */
60
/*                                            widget                      */
61
/*    _gx_vertical_list_children_position   Position the children for     */
62
/*                                            the vertical list           */
63
/*    _gx_first_client_child_get            Get the first client child    */
64
/*    _gx_vertical_list_scroll              Move up or down the scrollbar */
65
/*    _gx_vertical_list_slide_back_check    Check the sliding back of     */
66
/*                                            the scrollbar               */
67
/*    _gx_window_scrollbar_find             Assign a background wallpaper */
68
/*                                            to a GX_WINDOW object       */
69
/*    _gx_scrollbar_reset                   Calculate new scrollbar value */
70
/*    _gx_system_timer_start                Allocate a free timer and     */
71
/*                                            activates it                */
72
/*    _gx_system_top_widget_find            Find top widget under pen     */
73
/*    _gx_system_timer_stop                 Stop an active GUIX timer     */
74
/*    _gx_window_event_process              Process events for the        */
75
/*                                            specified window            */
76
/*                                                                        */
77
/*  CALLED BY                                                             */
78
/*                                                                        */
79
/*    Application Code                                                    */
80
/*                                                                        */
81
/*  RELEASE HISTORY                                                       */
82
/*                                                                        */
83
/*    DATE              NAME                      DESCRIPTION             */
84
/*                                                                        */
85
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
86
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
87
/*                                            resulting in version 6.1    */
88
/*  07-29-2022     Kenneth Maxwell          Modified comment(s),          */
89
/*                                            fixed bug in EVENT_PEN_DRAG */
90
/*                                            handler,                    */
91
/*                                            resulting in version 6.1.12 */
92
/*                                                                        */
93
/**************************************************************************/
94
3131
UINT  _gx_vertical_list_event_process(GX_VERTICAL_LIST *list, GX_EVENT *event_ptr)
95
{
96
3131
GX_WIDGET    *widget = (GX_WIDGET *)list;
97
GX_SCROLLBAR *pScroll;
98
INT           snap_dist;
99
UINT          timer_id;
100
3131
UINT          status = GX_SUCCESS;
101
GX_WIDGET    *child;
102
INT           list_height;
103
INT           widget_height;
104
INT           new_pen_index;
105
GX_WIDGET   **stackptr;
106
GX_WIDGET   **stacktop;
107
GX_EVENT      input_release_event;
108
109


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

150
        while (child && child -> gx_widget_parent != (GX_WIDGET *)list)
160
        {
161
3
            child = child -> gx_widget_parent;
162
        }
163
164
147
        if (child)
165
        {
166
145
            list -> gx_vertical_list_pen_index = list -> gx_vertical_list_top_index + _gx_widget_client_index_get(widget, child);
167
145
            if (list -> gx_vertical_list_pen_index >= list -> gx_vertical_list_total_rows)
168
            {
169
13
                list -> gx_vertical_list_pen_index -= list -> gx_vertical_list_total_rows;
170
            }
171
        }
172
147
        break;
173
174
148
    case GX_EVENT_PEN_UP:
175
148
        if (list -> gx_widget_status & GX_STATUS_OWNS_INPUT)
176
        {
177
146
            _gx_system_input_release(widget);
178
179
146
            list_height = list -> gx_vertical_list_child_count * list -> gx_vertical_list_child_height;
180
146
            widget_height = list -> gx_window_client.gx_rectangle_bottom - list -> gx_window_client.gx_rectangle_top + 1;
181
182
146
            if (list_height > widget_height)
183
            {
184
137
                _gx_vertical_list_slide_back_check(list);
185
            }
186

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

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

132
                    if (*stackptr != GX_NULL && *stackptr != widget)
234
                    {
235
2
                        input_release_event.gx_event_target = *stackptr;
236
2
                        _gx_system_event_send(&input_release_event);
237
                    }
238
132
                    stackptr++;
239
                }
240
241
130
                _gx_vertical_list_scroll(list,
242
130
                                         event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_y -
243
130
                                         list -> gx_window_move_start.gx_point_y);
244
130
                _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_VERTICAL_SCROLL, &pScroll);
245
246
130
                if (pScroll)
247
                {
248
67
                    _gx_scrollbar_reset(pScroll, GX_NULL);
249
                }
250
130
                list -> gx_window_move_start = event_ptr -> gx_event_payload.gx_event_pointdata;
251
130
                list -> gx_vertical_list_pen_index = -1;
252
            }
253
        }
254
        else
255
        {
256
2
            _gx_widget_event_to_parent((GX_WIDGET *)list, event_ptr);
257
        }
258
133
        break;
259
260
6
    case GX_EVENT_VERTICAL_FLICK:
261
6
        list_height = list -> gx_vertical_list_child_count * list -> gx_vertical_list_child_height;
262
6
        widget_height = list -> gx_window_client.gx_rectangle_bottom - list -> gx_window_client.gx_rectangle_top + 1;
263
264
6
        if (list_height > widget_height)
265
        {
266
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);
267
4
            _gx_system_timer_start((GX_WIDGET *)list, GX_FLICK_TIMER, 1, 1);
268
        }
269
6
        list -> gx_vertical_list_pen_index = -1;
270
6
        break;
271
272
152
    case GX_EVENT_TIMER:
273
152
        timer_id = event_ptr -> gx_event_payload.gx_event_timer_id;
274
275

152
        if (timer_id == GX_FLICK_TIMER || timer_id == GX_SNAP_TIMER)
276
        {
277
151
            if (GX_ABS(list -> gx_vertical_list_snap_back_distance) < GX_ABS(list -> gx_vertical_list_child_height) / 3)
278
            {
279
21
                _gx_system_timer_stop(widget, event_ptr -> gx_event_payload.gx_event_timer_id);
280
21
                _gx_vertical_list_scroll(list, list -> gx_vertical_list_snap_back_distance);
281
282
21
                if (event_ptr -> gx_event_payload.gx_event_timer_id == GX_FLICK_TIMER)
283
                {
284
3
                    _gx_vertical_list_slide_back_check(list);
285
                }
286
            }
287
            else
288
            {
289
130
                snap_dist = (list -> gx_vertical_list_snap_back_distance) / 5;
290
130
                list -> gx_vertical_list_snap_back_distance = (GX_VALUE)(list -> gx_vertical_list_snap_back_distance - snap_dist);
291
130
                _gx_vertical_list_scroll(list, snap_dist);
292
            }
293
151
            _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_VERTICAL_SCROLL, &pScroll);
294
295
151
            if (pScroll)
296
            {
297
149
                _gx_scrollbar_reset(pScroll, GX_NULL);
298
            }
299
        }
300
        else
301
        {
302
1
            status = _gx_window_event_process((GX_WINDOW *)list, event_ptr);
303
        }
304
152
        break;
305
306
2038
    default:
307
2038
        status = _gx_window_event_process((GX_WINDOW *)list, event_ptr);
308
2038
        break;
309
    }
310
311
2796
    return status;
312
}
313