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


1291
    switch (event_ptr -> gx_event_type)
115
    {
116
169
    case GX_EVENT_SHOW:
117
118
        /* show the children before attempting to position them, because child
119
           widgets often do not know their size until shown
120
         */
121
122
169
        status = _gx_window_event_process((GX_WINDOW *)list, event_ptr);
123
124
169
        if (!list -> gx_horizontal_list_child_count)
125
        {
126
160
            _gx_horizontal_list_children_position(list);
127
        }
128
129
169
        _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_HORIZONTAL_SCROLL, &pScroll);
130
131
169
        if (pScroll)
132
        {
133
15
            _gx_scrollbar_reset(pScroll, GX_NULL);
134
        }
135
169
        break;
136
137
2
    case GX_EVENT_FOCUS_NEXT:
138
2
        if (list -> gx_horizontal_list_selected < list -> gx_horizontal_list_total_columns - 1)
139
        {
140
1
            _gx_horizontal_list_selected_set(list, list -> gx_horizontal_list_selected + 1);
141
        }
142
2
        break;
143
144
2
    case GX_EVENT_FOCUS_PREVIOUS:
145
2
        if (list -> gx_horizontal_list_selected > 0)
146
        {
147
1
            _gx_horizontal_list_selected_set(list, list -> gx_horizontal_list_selected - 1);
148
        }
149
2
        break;
150
151
62
    case GX_EVENT_HORIZONTAL_SCROLL:
152
62
        _gx_horizontal_list_scroll(list, event_ptr -> gx_event_payload.gx_event_intdata[1] - event_ptr -> gx_event_payload.gx_event_intdata[0]);
153
62
        return 0;
154
155
149
    case GX_EVENT_PEN_DOWN:
156
149
        _gx_system_input_capture(widget);
157
149
        list -> gx_window_move_start = event_ptr -> gx_event_payload.gx_event_pointdata;
158
159
        /* determine which child widget has been selected for future list select event */
160
149
        child = _gx_system_top_widget_find((GX_WIDGET *)list, event_ptr -> gx_event_payload.gx_event_pointdata, GX_STATUS_SELECTABLE);
161
162

151
        while (child && child -> gx_widget_parent != (GX_WIDGET *)list)
163
        {
164
2
            child = child -> gx_widget_parent;
165
        }
166
167
149
        if (child)
168
        {
169
147
            list -> gx_horizontal_list_pen_index = list -> gx_horizontal_list_top_index + _gx_widget_client_index_get(widget, child);
170
147
            if (list -> gx_horizontal_list_pen_index >= list -> gx_horizontal_list_total_columns)
171
            {
172
13
                list -> gx_horizontal_list_pen_index -= list -> gx_horizontal_list_total_columns;
173
            }
174
        }
175
149
        break;
176
177
149
    case GX_EVENT_PEN_UP:
178
149
        if (list -> gx_widget_status & GX_STATUS_OWNS_INPUT)
179
        {
180
148
            _gx_system_input_release(widget);
181
182
148
            list_width = list -> gx_horizontal_list_child_count * list -> gx_horizontal_list_child_width;
183
148
            widget_width = list -> gx_window_client.gx_rectangle_right - list -> gx_window_client.gx_rectangle_left + 1;
184
185
148
            if (list_width > widget_width)
186
            {
187
141
                _gx_horizontal_list_slide_back_check(list);
188
            }
189
190

148
            if (list -> gx_horizontal_list_pen_index >= 0 && list -> gx_horizontal_list_snap_back_distance == 0)
191
            {
192
                /* test to see if pen-up is over same child widget as pen-down */
193
21
                child = _gx_system_top_widget_find((GX_WIDGET *)list, event_ptr -> gx_event_payload.gx_event_pointdata, GX_STATUS_SELECTABLE);
194

23
                while (child && child -> gx_widget_parent != (GX_WIDGET *)list)
195
                {
196
2
                    child = child -> gx_widget_parent;
197
                }
198
199
21
                if (child)
200
                {
201
19
                    new_pen_index = list -> gx_horizontal_list_top_index + _gx_widget_client_index_get(widget, child);
202
19
                    if (new_pen_index >= list -> gx_horizontal_list_total_columns)
203
                    {
204
1
                        new_pen_index -= list -> gx_horizontal_list_total_columns;
205
                    }
206
19
                    if (new_pen_index == list -> gx_horizontal_list_pen_index)
207
                    {
208
18
                        _gx_horizontal_list_selected_set(list, list -> gx_horizontal_list_pen_index);
209
                    }
210
                }
211
            }
212
        }
213
        else
214
        {
215
1
            _gx_widget_event_to_parent(widget, event_ptr);
216
        }
217
149
        break;
218
219
131
    case GX_EVENT_PEN_DRAG:
220
131
        if ((widget -> gx_widget_status & GX_STATUS_OWNS_INPUT) &&
221
130
            (event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_x - list -> gx_window_move_start.gx_point_x) != 0)
222
        {
223
127
            list_width = list -> gx_horizontal_list_child_count * list -> gx_horizontal_list_child_width;
224
127
            widget_width = list -> gx_window_client.gx_rectangle_right - list -> gx_window_client.gx_rectangle_left + 1;
225
226
127
            if (list_width > widget_width)
227
            {
228
                /* Start sliding, remove other widgets from input capture stack.  */
229
126
                stackptr = _gx_system_input_capture_stack;
230
126
                stacktop = _gx_system_input_capture_stack + _gx_system_capture_count;
231
232
126
                memset(&input_release_event, 0, sizeof(GX_EVENT));
233
126
                input_release_event.gx_event_type = GX_EVENT_INPUT_RELEASE;
234
235
255
                while (stackptr < stacktop)
236
                {
237

129
                    if (*stackptr != GX_NULL && *stackptr != widget)
238
                    {
239
3
                        input_release_event.gx_event_target = *stackptr;
240
3
                        _gx_system_event_send(&input_release_event);
241
                    }
242
129
                    stackptr++;
243
                }
244
245
126
                _gx_horizontal_list_scroll(list,
246
126
                                           event_ptr -> gx_event_payload.gx_event_pointdata.gx_point_x -
247
126
                                           list -> gx_window_move_start.gx_point_x);
248
126
                _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_HORIZONTAL_SCROLL, &pScroll);
249
250
126
                if (pScroll)
251
                {
252
65
                    _gx_scrollbar_reset(pScroll, GX_NULL);
253
                }
254
126
                list -> gx_window_move_start = event_ptr -> gx_event_payload.gx_event_pointdata;
255
126
                list -> gx_horizontal_list_pen_index = -1;
256
            }
257
        }
258
        else
259
        {
260
4
            _gx_widget_event_to_parent(widget, event_ptr);
261
        }
262
131
        break;
263
264
5
    case GX_EVENT_HORIZONTAL_FLICK:
265
5
        list_width = list -> gx_horizontal_list_child_count * list -> gx_horizontal_list_child_width;
266
5
        widget_width = list -> gx_window_client.gx_rectangle_right - list -> gx_window_client.gx_rectangle_left + 1;
267
268
5
        if (list_width > widget_width)
269
        {
270
3
            list -> gx_horizontal_list_snap_back_distance = (GX_VALUE)(GX_FIXED_VAL_TO_INT(event_ptr -> gx_event_payload.gx_event_intdata[0]) * 8);
271
3
            _gx_system_timer_start((GX_WIDGET *)list, GX_FLICK_TIMER, 1, 1);
272
        }
273
5
        list -> gx_horizontal_list_pen_index = -1;
274
5
        break;
275
276
144
    case GX_EVENT_TIMER:
277
144
        timer_id = (INT)(event_ptr -> gx_event_payload.gx_event_timer_id);
278
279

144
        if (timer_id == GX_FLICK_TIMER || timer_id == GX_SNAP_TIMER)
280
        {
281
143
            if (GX_ABS(list -> gx_horizontal_list_snap_back_distance) < GX_ABS(list -> gx_horizontal_list_child_width) / 3)
282
            {
283
19
                _gx_system_timer_stop(widget, event_ptr -> gx_event_payload.gx_event_timer_id);
284
19
                _gx_horizontal_list_scroll(list, list -> gx_horizontal_list_snap_back_distance);
285
286
19
                if (event_ptr -> gx_event_payload.gx_event_timer_id == GX_FLICK_TIMER)
287
                {
288
3
                    _gx_horizontal_list_slide_back_check(list);
289
                }
290
            }
291
            else
292
            {
293
124
                snap_dist = (list -> gx_horizontal_list_snap_back_distance) / 5;
294
124
                list -> gx_horizontal_list_snap_back_distance = (GX_VALUE)(list -> gx_horizontal_list_snap_back_distance - snap_dist);
295
124
                _gx_horizontal_list_scroll(list, snap_dist);
296
            }
297
143
            _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_HORIZONTAL_SCROLL, &pScroll);
298
299
143
            if (pScroll)
300
            {
301
141
                _gx_scrollbar_reset(pScroll, GX_NULL);
302
            }
303
        }
304
        else
305
        {
306
1
            status = _gx_window_event_process((GX_WINDOW *)list, event_ptr);
307
        }
308
144
        break;
309
310
478
    default:
311
478
        status = _gx_window_event_process((GX_WINDOW *)list, event_ptr);
312
478
        break;
313
    }
314
1229
    return status;
315
}
316