GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_widget_event_process.c Lines: 120 120 100.0 %
Date: 2026-03-06 19:21:09 Branches: 71 71 100.0 %

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
/**   Widget Management (Widget)                                          */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define GX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "gx_api.h"
28
#include "gx_system.h"
29
#include "gx_widget.h"
30
31
/**************************************************************************/
32
/*                                                                        */
33
/*  FUNCTION                                               RELEASE        */
34
/*                                                                        */
35
/*    _gx_widget_children_show_event_process              PORTABLE C      */
36
/*                                                           6.1          */
37
/*  AUTHOR                                                                */
38
/*                                                                        */
39
/*    Kenneth Maxwell, Microsoft Corporation                              */
40
/*                                                                        */
41
/*  DESCRIPTION                                                           */
42
/*                                                                        */
43
/*    Internal helper function to propagate widget show events to the     */
44
/*    client children of the specified widget first, and then pass the    */
45
/*    event to the non-client children.                                   */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    widget                                Widget control block          */
50
/*    event_ptr                             Incoming event to process     */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    None                                                                */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    [gx_widget_event_process_function]    Child widget event processing */
59
/*                                                                        */
60
/*  CALLED BY                                                             */
61
/*                                                                        */
62
/*    _gx_widget_event_process                                            */
63
/*                                                                        */
64
/**************************************************************************/
65
32734
static VOID  _gx_widget_children_show_event_process(GX_WIDGET *widget, GX_EVENT *event_ptr)
66
{
67
68
GX_WIDGET *child;
69
32734
GX_WIDGET *start = GX_NULL;
70
32734
GX_WIDGET *end = GX_NULL;
71
72
    /* Pickup the first child of the widget.  */
73
32734
    child = widget -> gx_widget_first_child;
74
75
    /* Loop to send event to all client children of widget.  */
76
61757
    while (child)
77
    {
78
29023
        if (child -> gx_widget_status & GX_STATUS_NONCLIENT)
79
        {
80
428
            if (start == GX_NULL)
81
            {
82
                /* Record first non-client widget. */
83
268
                start = child;
84
            }
85
86
            /* Record last non-client widget. */
87
428
            end = child;
88
        }
89
        else
90
        {
91
            /* Call widget's event processing.  */
92
28595
            child -> gx_widget_event_process_function(child, event_ptr);
93
        }
94
95
        /* Move to next child widget.  */
96
29023
        child = child -> gx_widget_next;
97
    }
98
99
32734
    if (start)
100
    {
101
        /* Loop to send event to all non-client children of widget.  */
102
449
        while (start != end)
103
        {
104
181
            if (start -> gx_widget_status & GX_STATUS_NONCLIENT)
105
            {
106
                /* Call widget's event processing.  */
107
160
                start -> gx_widget_event_process_function(start, event_ptr);
108
            }
109
110
181
            start = start -> gx_widget_next;
111
        }
112
113
268
        start -> gx_widget_event_process_function(start, event_ptr);
114
    }
115
32734
}
116
117
/**************************************************************************/
118
/*                                                                        */
119
/*  FUNCTION                                               RELEASE        */
120
/*                                                                        */
121
/*    _gx_widget_event_process                            PORTABLE C      */
122
/*                                                           6.4.0        */
123
/*  AUTHOR                                                                */
124
/*                                                                        */
125
/*    Kenneth Maxwell, Microsoft Corporation                              */
126
/*                                                                        */
127
/*  DESCRIPTION                                                           */
128
/*                                                                        */
129
/*    This function processes events for the specified widget.            */
130
/*                                                                        */
131
/*  INPUT                                                                 */
132
/*                                                                        */
133
/*    widget                                Widget control block          */
134
/*    event_ptr                             Incoming event to process     */
135
/*                                                                        */
136
/*  OUTPUT                                                                */
137
/*                                                                        */
138
/*    status                                Completion status             */
139
/*                                                                        */
140
/*  CALLS                                                                 */
141
/*                                                                        */
142
/*    _gx_widget_children_event_process     Forward event to children     */
143
/*    [gx_widget_event_process_function]    Widget-specific event process */
144
/*                                            routine                     */
145
/*    _gx_system_dirty_mark                 Mark the widget as dirty      */
146
/*    _gx_widget_event_to_parent            Signal the parent             */
147
/*    _gx_widget_event_generate             Generate an event             */
148
/*                                                                        */
149
/*  CALLED BY                                                             */
150
/*                                                                        */
151
/*    Application Code                                                    */
152
/*    GUIX Internal Code                                                  */
153
/*                                                                        */
154
/**************************************************************************/
155
104111
UINT  _gx_widget_event_process(GX_WIDGET *widget, GX_EVENT *event_ptr)
156
{
157
GX_WIDGET *child;
158
GX_EVENT   new_event;
159
104111
UINT       status = GX_SUCCESS;
160
GX_EVENT   input_release_event;
161
162
    /* Process relative to the type of event. */
163



104111
    switch (event_ptr -> gx_event_type)
164
    {
165
32972
    case GX_EVENT_SHOW:
166
32972
        if (!(widget -> gx_widget_status & (GX_STATUS_VISIBLE | GX_STATUS_HIDDEN)))
167
        {
168
32734
            widget -> gx_widget_status |= GX_STATUS_VISIBLE;
169
32734
            _gx_widget_children_show_event_process(widget, event_ptr);
170
        }
171
32972
        break;
172
173
16863
    case GX_EVENT_HIDE:
174
16863
        if (widget -> gx_widget_status & GX_STATUS_VISIBLE)
175
        {
176
16788
            widget -> gx_widget_status &= ~GX_STATUS_VISIBLE;
177
178
            /* Check if the widget still owns system input. */
179
16788
            if (widget -> gx_widget_status & GX_STATUS_OWNS_INPUT)
180
            {
181
36
                memset(&input_release_event, 0, sizeof(GX_EVENT));
182
36
                input_release_event.gx_event_target = widget;
183
36
                input_release_event.gx_event_type = GX_EVENT_INPUT_RELEASE;
184
36
                widget -> gx_widget_event_process_function(widget, &input_release_event);
185
            }
186
16788
            _gx_widget_children_event_process(widget, event_ptr);
187
        }
188
16863
        break;
189
190
7373
    case GX_EVENT_FOCUS_GAINED:
191
        /* if I don't already have focus */
192
7373
        if (!(widget -> gx_widget_status & GX_STATUS_HAS_FOCUS) &&
193
7360
            widget -> gx_widget_status & GX_STATUS_ACCEPTS_FOCUS)
194
        {
195
            /* then status flag indicating I have focus */
196
197
7354
            widget -> gx_widget_status |= GX_STATUS_HAS_FOCUS;
198
199
            /* and make sure my parent has focus as well */
200
7354
            if (widget -> gx_widget_parent)
201
            {
202
6364
                if (!(widget -> gx_widget_parent -> gx_widget_status & GX_STATUS_HAS_FOCUS))
203
                {
204
1271
                    widget -> gx_widget_parent -> gx_widget_event_process_function(widget -> gx_widget_parent, event_ptr);
205
                }
206
207
                /* test to see if this widget should notify it's parent when it gains focus */
208

6364
                if (widget -> gx_widget_id && widget -> gx_widget_status & GX_STATUS_NOTIFY_ON_GAIN_FOCUS)
209
                {
210
1
                    _gx_widget_event_generate(widget, GX_EVENT_FOCUS_GAIN_NOTIFY, 0);
211
                }
212
            }
213
7354
            if (widget -> gx_widget_style & GX_STYLE_ENABLED)
214
            {
215
2296
                widget -> gx_widget_style |= GX_STYLE_DRAW_SELECTED;
216
2296
                _gx_system_dirty_mark(widget);
217
            }
218
        }
219
7373
        break;
220
221
5168
    case GX_EVENT_FOCUS_LOST:
222
        /* if I previously had focus */
223
5168
        if (widget -> gx_widget_status & GX_STATUS_HAS_FOCUS)
224
        {
225
            /* clear focus status flag */
226
5145
            widget -> gx_widget_status &= ~GX_STATUS_HAS_FOCUS;
227
228
5145
            if (widget -> gx_widget_style & GX_STYLE_ENABLED)
229
            {
230
1713
                widget -> gx_widget_style &= ~GX_STYLE_DRAW_SELECTED;
231
1713
                _gx_system_dirty_mark(widget);
232
            }
233
        }
234
235
        /* and make sure my children don't think they have focus */
236
237
5168
        child = widget -> gx_widget_first_child;
238
239
24132
        while (child)
240
        {
241
21282
            if (child -> gx_widget_status & GX_STATUS_HAS_FOCUS)
242
            {
243
2318
                child -> gx_widget_event_process_function(child, event_ptr);
244
2318
                break;
245
            }
246
18964
            child = child -> gx_widget_next;
247
        }
248
5168
        break;
249
250
10169
    case GX_EVENT_PEN_DOWN:
251
10169
        if (widget -> gx_widget_status & GX_STATUS_SELECTABLE)
252
        {
253
3581
            if (widget -> gx_widget_id > 0)
254
            {
255
1301
                _gx_widget_event_generate(widget, GX_EVENT_CLICKED, 0);
256
            }
257
        }
258
10169
        status = _gx_widget_event_to_parent(widget, event_ptr);
259
10169
        break;
260
261
262
3534
    case GX_EVENT_LANGUAGE_CHANGE:
263
    case GX_EVENT_RESOURCE_CHANGE:
264
#if defined(GX_DYNAMIC_BIDI_TEXT_SUPPORT)
265
    case GX_EVENT_DYNAMIC_BIDI_TEXT_DISABLE:
266
    case GX_EVENT_DYNAMIC_BIDI_TEXT_ENABLE:
267
#endif
268
        /* pass this event down to all my children */
269
3534
        child = widget -> gx_widget_first_child;
270
6946
        while (child)
271
        {
272
3412
            child -> gx_widget_event_process_function(child, event_ptr);
273
3412
            child = child -> gx_widget_next;
274
        }
275
3534
        break;
276
277
910
    case GX_EVENT_KEY_DOWN:
278
910
        memset(&new_event, 0, sizeof(GX_EVENT));
279
280

910
        switch (event_ptr -> gx_event_payload.gx_event_ushortdata[0])
281
        {
282
2
        case GX_KEY_SELECT:
283
2
            if (widget -> gx_widget_style & GX_STYLE_ENABLED)
284
            {
285
                /* generate pen-down event */
286
1
                new_event.gx_event_type = GX_EVENT_SELECT;
287
1
                widget -> gx_widget_event_process_function(widget, &new_event);
288
            }
289
2
            break;
290
291
1
        case GX_KEY_NEXT:
292
1
            new_event.gx_event_type = GX_EVENT_FOCUS_NEXT;
293
1
            new_event.gx_event_sender = widget -> gx_widget_id;
294
1
            widget -> gx_widget_event_process_function(widget, &new_event);
295
1
            break;
296
297
1
        case GX_KEY_PREVIOUS:
298
1
            new_event.gx_event_type = GX_EVENT_FOCUS_PREVIOUS;
299
1
            new_event.gx_event_sender = widget -> gx_widget_id;
300
1
            widget -> gx_widget_event_process_function(widget, &new_event);
301
1
            break;
302
303
906
        default:
304
906
            _gx_widget_event_to_parent(widget, event_ptr);
305
906
            break;
306
        }
307
910
        break;
308
309
377
    case GX_EVENT_KEY_UP:
310
377
        if (widget -> gx_widget_style & GX_STYLE_ENABLED)
311
        {
312
189
            if (event_ptr -> gx_event_payload.gx_event_ushortdata[0] == GX_KEY_SELECT)
313
            {
314
                /* generate de-select event */
315
1
                memset(&new_event, 0, sizeof(GX_EVENT));
316
1
                new_event.gx_event_type = GX_EVENT_DESELECT;
317
1
                widget -> gx_widget_event_process_function(widget, &new_event);
318
            }
319
            else
320
            {
321
188
                _gx_widget_event_to_parent(widget, event_ptr);
322
            }
323
        }
324
377
        break;
325
326
1
    case GX_EVENT_FOCUS_NEXT:
327
1
        _gx_widget_focus_next(widget);
328
1
        break;
329
330
1
    case GX_EVENT_FOCUS_PREVIOUS:
331
1
        _gx_widget_focus_previous(widget);
332
1
        break;
333
334
8
    case GX_EVENT_INPUT_RELEASE:
335
8
        if (widget -> gx_widget_status & GX_STATUS_OWNS_INPUT)
336
        {
337
7
            _gx_system_input_release(widget);
338
        }
339
8
        break;
340
341
5977
    case GX_EVENT_STYLE_CHANGED:
342
    case GX_EVENT_CLIENT_UPDATED:
343
    case GX_EVENT_PARENT_SIZED:
344
    case GX_EVENT_RESIZED:
345
    case GX_EVENT_DELETE:
346
5977
        break;
347
348
20758
    case GX_EVENT_PEN_UP:
349
    case GX_EVENT_PEN_DRAG:
350
    default:
351
20758
        status = _gx_widget_event_to_parent(widget, event_ptr);
352
20758
        break;
353
    }
354
355
104111
    return(status);
356
}
357