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 /**   Widget Management (Widget)                                          */
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 
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _gx_widget_nav_order_initialize                     PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Kenneth Maxwell, Microsoft Corporation                              */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function configures next/previous navigation order.            */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    widget                                Widget control block          */
48 /*                                                                        */
49 /*  OUTPUT                                                                */
50 /*                                                                        */
51 /*    status                                Completion status             */
52 /*                                                                        */
53 /*  CALLS                                                                 */
54 /*                                                                        */
55 /*                                                                        */
56 /*  CALLED BY                                                             */
57 /*                                                                        */
58 /*    GUIX Internal Code                                                  */
59 /*                                                                        */
60 /*  RELEASE HISTORY                                                       */
61 /*                                                                        */
62 /*    DATE              NAME                      DESCRIPTION             */
63 /*                                                                        */
64 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
65 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
66 /*                                            resulting in version 6.1    */
67 /*                                                                        */
68 /**************************************************************************/
_gx_widget_nav_order_initialize(GX_WIDGET * widget)69 VOID _gx_widget_nav_order_initialize(GX_WIDGET *widget)
70 {
71 GX_WIDGET *winner;
72 GX_WIDGET *child;
73 GX_WIDGET *first_stop = NULL;
74 GX_WIDGET *last_stop = NULL;
75 GX_BOOL    assign_default_focus = GX_TRUE;
76 
77     child = widget -> gx_widget_first_child;
78 
79     /* test to see if any child already has default focus status flag */
80     while (child)
81     {
82         if (assign_default_focus)
83         {
84             if (child -> gx_widget_status & GX_STATUS_DEFAULT_FOCUS)
85             {
86                 assign_default_focus = GX_FALSE;
87             }
88         }
89         else
90         {
91             /* make sure only one child has default focus flag */
92             child -> gx_widget_status &= ~GX_STATUS_DEFAULT_FOCUS;
93         }
94 
95         child -> gx_widget_nav_next = GX_NULL;
96         child -> gx_widget_nav_previous = GX_NULL;
97         child = child -> gx_widget_next;
98     }
99 
100     /* loop through child widgets looking for
101        the top-left child and assigning the navigation order
102        in left-to-right top-to-bottom order.
103      */
104 
105     do
106     {
107         child = widget -> gx_widget_first_child;
108         winner = GX_NULL;
109 
110         while (child)
111         {
112             if (child == last_stop || (child -> gx_widget_status & GX_STATUS_VISIBLE) == 0)
113             {
114                 child = child -> gx_widget_next;
115                 continue;
116             }
117 
118             if (!child -> gx_widget_nav_next)
119             {
120                 if ((child -> gx_widget_status & GX_STATUS_ACCEPTS_FOCUS) &&
121                     !(child -> gx_widget_status & GX_STATUS_NONCLIENT))
122                 {
123                     if (winner)
124                     {
125                         if (child -> gx_widget_size.gx_rectangle_top < winner -> gx_widget_size.gx_rectangle_top)
126                         {
127                             winner = child;
128                         }
129                         else
130                         {
131                             if (child -> gx_widget_size.gx_rectangle_top == winner -> gx_widget_size.gx_rectangle_top &&
132                                 child -> gx_widget_size.gx_rectangle_left < winner -> gx_widget_size.gx_rectangle_left)
133                             {
134                                 winner = child;
135                             }
136                         }
137                     }
138                     else
139                     {
140                         winner = child;
141                     }
142                 }
143             }
144 
145             child = child -> gx_widget_next;
146         }
147 
148         if (winner)
149         {
150             if (!first_stop)
151             {
152                 first_stop = winner;
153 
154                 if (assign_default_focus)
155                 {
156                     first_stop -> gx_widget_status |= GX_STATUS_DEFAULT_FOCUS;
157                 }
158             }
159 
160             if (last_stop)
161             {
162                 winner -> gx_widget_nav_previous = last_stop;
163                 last_stop -> gx_widget_nav_next = winner;
164             }
165             last_stop = winner;
166         }
167     } while (winner);
168 
169     /* loop the last in the order back to the first */
170     if (last_stop)
171     {
172         last_stop -> gx_widget_nav_next = first_stop;
173         first_stop -> gx_widget_nav_previous = last_stop;
174     }
175 }
176 
177