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 /** System Management (System) */
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_system_focus_claim PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Kenneth Maxwell, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This service claims the focus for the specified widget. */
44 /* */
45 /* INPUT */
46 /* */
47 /* widget Pointer to widget control */
48 /* block to claim focus */
49 /* */
50 /* OUTPUT */
51 /* */
52 /* status Completion status */
53 /* */
54 /* CALLS */
55 /* */
56 /* _gx_system_error_process Processes internal GUIX */
57 /* system errors */
58 /* _gx_widget_child_detect Detect if one widget is child */
59 /* of another. */
60 /* [gx_widget_event_process_function] Widget event process routine */
61 /* CALLED BY */
62 /* */
63 /* GUIX Application */
64 /* GUIX Internal Code */
65 /* */
66 /* RELEASE HISTORY */
67 /* */
68 /* DATE NAME DESCRIPTION */
69 /* */
70 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
71 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
72 /* resulting in version 6.1 */
73 /* */
74 /**************************************************************************/
_gx_system_focus_claim(GX_WIDGET * widget)75 UINT _gx_system_focus_claim(GX_WIDGET *widget)
76 {
77 GX_EVENT newevent;
78 GX_WIDGET *parent;
79 GX_BOOL detect_result;
80
81 newevent.gx_event_target = GX_NULL;
82 /* is this a visible widget? */
83 if (widget -> gx_widget_status & GX_STATUS_VISIBLE)
84 {
85 while (!(widget -> gx_widget_status & GX_STATUS_ACCEPTS_FOCUS))
86 {
87 widget = widget -> gx_widget_parent;
88 if (!widget)
89 {
90 /* this should not happened. Somehow we have a portion of
91 the widget tree that does not accept focus, including the
92 root window. Return an error.
93 */
94 _gx_system_error_process(GX_PTR_ERROR);
95 return(GX_PTR_ERROR);
96 }
97 }
98
99 /* check to see if this widget already owns focus, if so
100 just return
101 */
102 if (widget == _gx_system_focus_owner)
103 {
104 return(GX_NO_CHANGE);
105 }
106
107 /* first figure out who is losing focus */
108 if (_gx_system_focus_owner)
109 {
110 parent = _gx_system_focus_owner;
111
112 /* is the widget gaining focus a child of widget which currently has focus ? */
113 _gx_widget_child_detect(parent, widget, &detect_result);
114
115 if (detect_result)
116 {
117 /* yes, do not send focus lost */
118 parent = GX_NULL;
119 }
120 else
121 {
122 while (parent -> gx_widget_parent)
123 {
124 _gx_widget_child_detect(parent -> gx_widget_parent, widget, &detect_result);
125
126 /* does this object have same parent as object gaining focus ? */
127 if (detect_result)
128 {
129 /* yes, that's where we stop "losing focus" */
130 break;
131 }
132 /* move up one layer */
133 parent = parent -> gx_widget_parent;
134 }
135 }
136
137 /* tell the top-most "non common ancestor" that he and his children are losing focus */
138 if (parent)
139 {
140 newevent.gx_event_type = GX_EVENT_FOCUS_LOST;
141 parent -> gx_widget_event_process_function(parent, &newevent);
142 }
143 }
144
145 /* now tell the new owner he has focus */
146 _gx_system_focus_owner = widget;
147 newevent.gx_event_type = GX_EVENT_FOCUS_GAINED;
148 widget -> gx_widget_event_process_function(widget, &newevent);
149 }
150
151 /* send event to add focus */
152 return GX_SUCCESS;
153 }
154
155