GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_scrollbar_event_process.c Lines: 96 96 100.0 %
Date: 2024-12-05 08:52:37 Branches: 54 54 100.0 %

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
/**   Scrollbar Management (Scrollbar)                                    */
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_window.h"
30
#include "gx_utility.h"
31
#include "gx_scrollbar.h"
32
33
34
/**************************************************************************/
35
/*                                                                        */
36
/*  FUNCTION                                               RELEASE        */
37
/*                                                                        */
38
/*    _gx_scrollbar_event_process                         PORTABLE C      */
39
/*                                                           6.1          */
40
/*  AUTHOR                                                                */
41
/*                                                                        */
42
/*    Kenneth Maxwell, Microsoft Corporation                              */
43
/*                                                                        */
44
/*  DESCRIPTION                                                           */
45
/*                                                                        */
46
/*    This function processes events for the specified window.            */
47
/*                                                                        */
48
/*  INPUT                                                                 */
49
/*                                                                        */
50
/*    scrollbar                             Scrollbar control block       */
51
/*    event_ptr                             Incoming event to process     */
52
/*                                                                        */
53
/*  OUTPUT                                                                */
54
/*                                                                        */
55
/*    status                                Completion status             */
56
/*                                                                        */
57
/*  CALLS                                                                 */
58
/*                                                                        */
59
/*    _gx_utility_rectangle_center_find     Locate the center of a        */
60
/*                                             rectangle                  */
61
/*    [gx_widget_event_process_function]    Parent widget event process   */
62
/*                                            routine                     */
63
/*    _gx_scrollbar_thumb_position_calculate                              */
64
/*                                          Calculate the position of the */
65
/*                                            thumb                       */
66
/*    _gx_scrollbar_limit_check             Check for scroll limit        */
67
/*    _gx_system_dirty_mark                 Mark the widget dirty         */
68
/*    _gx_scrollbar_value_calcualte         Calculate the value of the    */
69
/*                                            scrollbar                   */
70
/*    _gx_scrollbar_reset                   Reset the scrollbar           */
71
/*    _gx_widget_border_width_get           Retrieve widget border width  */
72
/*    _gx_widget_child_clipping_update      Update widget child clipping  */
73
/*                                            area                        */
74
/*    _gx_widget_type_find                  Find the type of the widget   */
75
/*    _gx_scrollbar_size_update             Update the size of scrollbar  */
76
/*    _gx_widget_event_process              Invoke the widget event       */
77
/*                                            process routine             */
78
/*                                                                        */
79
/*  CALLED BY                                                             */
80
/*                                                                        */
81
/*    Application Code                                                    */
82
/*    GUIX Internal Code                                                  */
83
/*                                                                        */
84
/*  RELEASE HISTORY                                                       */
85
/*                                                                        */
86
/*    DATE              NAME                      DESCRIPTION             */
87
/*                                                                        */
88
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
89
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
90
/*                                            resulting in version 6.1    */
91
/*                                                                        */
92
/**************************************************************************/
93
3064
UINT  _gx_scrollbar_event_process(GX_SCROLLBAR *scrollbar, GX_EVENT *event_ptr)
94
{
95
96
UINT             status;
97
GX_EVENT         newevent;
98
GX_WINDOW       *win;
99
GX_SCROLLBAR    *scroll_ptr;
100
GX_SCROLL_THUMB *thumb;
101
GX_POINT         pen_point;
102
GX_VALUE         parent_border_width;
103
INT              temp_value;
104
GX_VALUE         edge;
105
GX_RECTANGLE     rect;
106
107
3064
    status = GX_SUCCESS;
108
109
    /* Process relative to the type of event.  */
110


3064
    switch (event_ptr -> gx_event_type)
111
    {
112
11
    case GX_EVENT_PEN_DOWN:
113
11
        rect = scrollbar->gx_widget_size;
114
115
11
        if (scrollbar->gx_scrollbar_upleft.gx_widget_size.gx_rectangle_left !=
116
11
            scrollbar->gx_scrollbar_upleft.gx_widget_size.gx_rectangle_right)
117
        {
118
10
            if (scrollbar->gx_widget_style & GX_SCROLLBAR_VERTICAL)
119
            {
120
4
                rect.gx_rectangle_top = (GX_VALUE)(scrollbar->gx_scrollbar_upleft.gx_widget_size.gx_rectangle_bottom + 1);
121
4
                rect.gx_rectangle_bottom = (GX_VALUE)(scrollbar->gx_scrollbar_downright.gx_widget_size.gx_rectangle_top - 1);
122
            }
123
            else
124
            {
125
6
                rect.gx_rectangle_left = (GX_VALUE)(scrollbar->gx_scrollbar_upleft.gx_widget_size.gx_rectangle_right + 1);
126
6
                rect.gx_rectangle_right = (GX_VALUE)(scrollbar->gx_scrollbar_downright.gx_widget_size.gx_rectangle_left - 1);
127
            }
128
        }
129
130
        /* Calculate valid rectangle here to avoid situation that click on scrollbar end button, since we delivery PEN_DOWN event
131
           to parent, if we click on scrollbar end buttons, the PEN_DOWN event will also be sent to it's parent, which handles scrollbar
132
           thumb in another way.  */
133
134
        /* save the position */
135
11
        pen_point = event_ptr -> gx_event_payload.gx_event_pointdata;
136
137
11
        if (_gx_utility_rectangle_point_detect(&rect, pen_point))
138
        {
139
3
            thumb = &scrollbar -> gx_scrollbar_thumb;
140
            /* find center of thumb button */
141
3
            _gx_utility_rectangle_center_find(&thumb -> gx_widget_size,
142
                                              &event_ptr -> gx_event_payload.gx_event_pointdata);
143
144
            /* pass the even to my scroll thumb */
145
3
            thumb -> gx_widget_event_process_function((GX_WIDGET *)thumb, event_ptr);
146
147
            /* now pass original position in drag message */
148
3
            newevent.gx_event_type = GX_EVENT_PEN_DRAG;
149
3
            newevent.gx_event_payload.gx_event_pointdata = pen_point;
150
3
            thumb -> gx_widget_event_process_function((GX_WIDGET *)thumb, &newevent);
151
        }
152
        /* Return successful status.  */
153
11
        return(GX_SUCCESS);
154
155
835
    case GX_SIGNAL(GX_ID_SCROLL_UP_LEFT, GX_EVENT_CLICKED):
156
    case GX_SIGNAL(GX_ID_SCROLL_DOWN_RIGHT, GX_EVENT_CLICKED):
157
835
        temp_value = scrollbar -> gx_scrollbar_info.gx_scroll_value;
158
159
835
        if (event_ptr -> gx_event_sender == GX_ID_SCROLL_UP_LEFT)
160
        {
161
438
            temp_value = temp_value - scrollbar -> gx_scrollbar_info.gx_scroll_increment;
162
        }
163
        else
164
        {
165
397
            temp_value = scrollbar -> gx_scrollbar_info.gx_scroll_value + scrollbar -> gx_scrollbar_info.gx_scroll_increment;
166
        }
167
168
835
        _gx_scrollbar_value_set(scrollbar, temp_value);
169
835
        break;
170
171
1221
    case GX_EVENT_VERTICAL_SCROLL:
172
    case GX_EVENT_HORIZONTAL_SCROLL:
173
        /* this event arrives from my thumb button. Calculate new value
174
           and send event to parent window
175
         */
176
1221
        _gx_scrollbar_value_calculate(scrollbar, event_ptr -> gx_event_payload.gx_event_intdata[0],
177
                                      event_ptr -> gx_event_payload.gx_event_intdata[1]);
178
1221
        break;
179
180
8
    case GX_EVENT_PEN_UP:
181
8
        break;
182
183
14
    case GX_EVENT_PARENT_SIZED:
184
14
        _gx_scrollbar_reset(scrollbar, GX_NULL);
185
14
        break;
186
187
262
    case GX_EVENT_HIDE:
188
262
        status = _gx_widget_event_process((GX_WIDGET *)scrollbar, event_ptr);
189
190
        /* adjust my parent window client size */
191
262
        win = (GX_WINDOW *)scrollbar -> gx_widget_parent;
192
262
        if (win)
193
        {
194
261
            _gx_widget_border_width_get((GX_WIDGET *)win, &parent_border_width);
195
196
261
            if (scrollbar -> gx_widget_type == GX_TYPE_VERTICAL_SCROLL)
197
            {
198
145
                win -> gx_window_client.gx_rectangle_right = (GX_VALUE)(win -> gx_widget_size.gx_rectangle_right - parent_border_width);
199
145
                _gx_widget_child_clipping_update(scrollbar -> gx_widget_parent);
200
145
                _gx_widget_type_find(scrollbar -> gx_widget_parent,  GX_TYPE_HORIZONTAL_SCROLL, (GX_WIDGET **)&scroll_ptr);
201
202
145
                if (scroll_ptr)
203
                {
204
112
                    if (scroll_ptr -> gx_widget_status & GX_STATUS_VISIBLE)
205
                    {
206
11
                        _gx_scrollbar_size_update(scroll_ptr);
207
                    }
208
                }
209
            }
210
            else
211
            {
212
116
                win -> gx_window_client.gx_rectangle_bottom = (GX_VALUE)(win -> gx_widget_size.gx_rectangle_bottom - parent_border_width);
213
116
                _gx_widget_child_clipping_update(scrollbar -> gx_widget_parent);
214
116
                _gx_widget_type_find(scrollbar -> gx_widget_parent, GX_TYPE_VERTICAL_SCROLL, (GX_WIDGET **)&scroll_ptr);
215
216
116
                if (scroll_ptr)
217
                {
218
112
                    if (scroll_ptr -> gx_widget_status & GX_STATUS_VISIBLE)
219
                    {
220
83
                        _gx_scrollbar_size_update(scroll_ptr);
221
                    }
222
                }
223
            }
224
225
            /* notify window of client modification */
226
227
261
            if (win -> gx_widget_status & GX_STATUS_VISIBLE)
228
            {
229
114
                newevent.gx_event_type = GX_EVENT_CLIENT_UPDATED;
230
114
                newevent.gx_event_target = (GX_WIDGET *)win;
231
114
                _gx_system_event_fold(&newevent);
232
            }
233
        }
234
262
        break;
235
236
457
    case GX_EVENT_SHOW:
237
        /* do the default handling */
238
457
         status = _gx_widget_event_process((GX_WIDGET *)scrollbar, event_ptr);
239
240
        /* test to see if I should be marked transparent */
241
457
        if (scrollbar -> gx_scrollbar_appearance.gx_scroll_fill_pixelmap)
242
        {
243
58
            if (_gx_widget_transparent_pixelmap_detect((GX_WIDGET *)scrollbar, scrollbar -> gx_scrollbar_appearance.gx_scroll_fill_pixelmap))
244
            {
245
49
                scrollbar -> gx_widget_status |= GX_STATUS_TRANSPARENT;
246
            }
247
        }
248
249
        /* adjust my parent window client size */
250
457
        win = (GX_WINDOW *) (scrollbar -> gx_widget_parent);
251
252
457
        if (win)
253
        {
254
456
            _gx_widget_border_width_get((GX_WIDGET *)win, &parent_border_width);
255
256
456
            if (scrollbar -> gx_widget_type == GX_TYPE_VERTICAL_SCROLL)
257
            {
258
266
                edge = (GX_VALUE)(win -> gx_widget_size.gx_rectangle_right - parent_border_width);
259
260
266
                if (!(scrollbar -> gx_widget_style & GX_STYLE_TRANSPARENT))
261
                {
262
264
                    edge = (GX_VALUE)(win -> gx_window_client.gx_rectangle_right - scrollbar -> gx_scrollbar_appearance.gx_scroll_width);
263
                }
264
266
                if (win -> gx_window_client.gx_rectangle_right != edge)
265
                {
266
265
                    win -> gx_window_client.gx_rectangle_right = edge;
267
265
                    _gx_widget_child_clipping_update((GX_WIDGET *) win);
268
                }
269
270
                /* if we have a horizontal scrollbar and it is already visible, it needs to be adjusted */
271
266
                _gx_widget_type_find((GX_WIDGET *)win, GX_TYPE_HORIZONTAL_SCROLL, (GX_WIDGET **)&scroll_ptr);
272
273
266
                if (scroll_ptr)
274
                {
275
171
                    if (scroll_ptr -> gx_widget_status & GX_STATUS_VISIBLE)
276
                    {
277
153
                        _gx_scrollbar_reset(scroll_ptr, GX_NULL);
278
                    }
279
                }
280
            }
281
            else
282
            {
283
190
                edge = (GX_VALUE)(win -> gx_widget_size.gx_rectangle_bottom - parent_border_width);
284
285
190
                if (!(scrollbar -> gx_widget_style & GX_STYLE_TRANSPARENT))
286
                {
287
176
                    edge = (GX_VALUE)(win -> gx_window_client.gx_rectangle_bottom - scrollbar -> gx_scrollbar_appearance.gx_scroll_width);
288
                }
289
190
                if (win -> gx_window_client.gx_rectangle_bottom != edge)
290
                {
291
176
                    win -> gx_window_client.gx_rectangle_bottom = edge;
292
176
                    _gx_widget_child_clipping_update((GX_WIDGET *) win);
293
                }
294
295
                /* if we have a vertical scrollbar and it is already visible, it needs to be adjusted */
296
190
                _gx_widget_type_find(scrollbar -> gx_widget_parent, GX_TYPE_VERTICAL_SCROLL, (GX_WIDGET **)&scroll_ptr);
297
298
190
                if (scroll_ptr)
299
                {
300
172
                    if (scroll_ptr -> gx_widget_status & GX_STATUS_VISIBLE)
301
                    {
302
23
                        _gx_scrollbar_reset(scroll_ptr, GX_NULL);
303
                    }
304
                }
305
            }
306
307
            /* notify window of client modification */
308
309
456
            newevent.gx_event_type = GX_EVENT_CLIENT_UPDATED;
310
456
            newevent.gx_event_target = (GX_WIDGET *) win;
311
456
            _gx_system_event_fold(&newevent);
312
        }
313
457
        _gx_scrollbar_reset(scrollbar, GX_NULL);
314
457
        break;
315
316
256
    default:
317
318
        /* Call the widget default processing.  */
319
256
        status =  _gx_widget_event_process((GX_WIDGET *)scrollbar, event_ptr);
320
    }
321
    /* Return widget event processing status.  */
322
3053
    return(status);
323
}
324