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_utility.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _gx_system_dirty_partial_add PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Kenneth Maxwell, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This service marks the partial area of this widget as dirty. */
44 /* */
45 /* INPUT */
46 /* */
47 /* widget Pointer to widget control */
48 /* block */
49 /* dirty_area Dirty area of widget to add */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* status Completion status */
54 /* */
55 /* CALLS */
56 /* */
57 /* GX_ENTER_CRITICAL Enter critical section */
58 /* _gx_utility_rectangle_overlap_detect Detect overlapping rectangles */
59 /* _gx_utility_rectangle_combine Combine two rectangles */
60 /* GX_EXIT_CRITICAL Exit critical section */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* Application Code */
65 /* GUIX Internal Code */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
72 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
73 /* resulting in version 6.1 */
74 /* */
75 /**************************************************************************/
_gx_system_dirty_entry_shift(GX_WIDGET * widget,INT xShift,INT yShift)76 VOID _gx_system_dirty_entry_shift(GX_WIDGET *widget, INT xShift, INT yShift)
77 {
78 UINT index;
79 GX_DIRTY_AREA *dirty_entry;
80 GX_WIDGET *test;
81 GX_WINDOW_ROOT *root;
82 GX_CANVAS *canvas;
83
84 if (!widget)
85 {
86 return;
87 }
88 if ((widget -> gx_widget_status & (GX_STATUS_VISIBLE | GX_STATUS_DIRTY)) != (GX_STATUS_VISIBLE | GX_STATUS_DIRTY))
89 {
90 return;
91 }
92
93 /* lock access before linked list update */
94 GX_ENTER_CRITICAL
95
96 /* walk up to find root window */
97 test = widget;
98
99 while (test -> gx_widget_parent)
100 {
101 test = test -> gx_widget_parent;
102 }
103
104 if (test -> gx_widget_type != GX_TYPE_ROOT_WINDOW)
105 {
106 GX_EXIT_CRITICAL
107 return;
108 }
109
110 root = (GX_WINDOW_ROOT *)test;
111
112 /* pick up pointer to canvas */
113 canvas = root -> gx_window_root_canvas;
114
115 /* Setup pointer to dirty list. */
116
117 dirty_entry = canvas -> gx_canvas_dirty_list;
118
119 /* Find existing entrie(s) */
120 for (index = 0; index < canvas -> gx_canvas_dirty_count; index++)
121 {
122 if (dirty_entry -> gx_dirty_area_widget == widget)
123 {
124 _gx_utility_rectangle_shift(&dirty_entry -> gx_dirty_area_rectangle, (GX_VALUE)xShift, (GX_VALUE)yShift);
125 }
126
127 /* Move to next dirty entry. */
128 dirty_entry++;
129 }
130 GX_EXIT_CRITICAL
131 }
132
133 #ifndef GUIX_STUDIO
_gx_system_dirty_partial_add(GX_WIDGET * widget,GX_RECTANGLE * dirty_area)134 UINT _gx_system_dirty_partial_add(GX_WIDGET *widget, GX_RECTANGLE *dirty_area)
135 {
136
137 UINT index;
138 GX_DIRTY_AREA *dirty_entry;
139 GX_WIDGET *test;
140 GX_WINDOW_ROOT *root;
141 GX_CANVAS *canvas;
142
143 if (!widget)
144 {
145 return GX_PTR_ERROR;
146 }
147 if (!(widget -> gx_widget_status & GX_STATUS_VISIBLE))
148 {
149 return GX_PTR_ERROR;
150 }
151
152 /* lock access before linked list update */
153 GX_ENTER_CRITICAL
154
155 /* if a widget is transparent, we actually need to mark it's
156 first non-transparent parent as being dirty
157 */
158
159 while(widget -> gx_widget_parent)
160 {
161 if (widget -> gx_widget_status & GX_STATUS_TRANSPARENT)
162 {
163 widget = widget -> gx_widget_parent;
164 }
165 else
166 {
167 break;
168 }
169 }
170
171 /* walk up to find root window */
172 test = widget;
173
174 while (test -> gx_widget_parent)
175 {
176 test = test -> gx_widget_parent;
177 }
178
179 if (test -> gx_widget_type != GX_TYPE_ROOT_WINDOW)
180 {
181 GX_EXIT_CRITICAL
182 return GX_PTR_ERROR;
183 }
184
185 root = (GX_WINDOW_ROOT *)test;
186
187 /* pick up pointer to canvas */
188 canvas = root -> gx_window_root_canvas;
189
190 /* if we are running low on dirty-area records, only allow
191 marking the root as dirty
192 */
193 if (canvas -> gx_canvas_dirty_count >= GX_MAX_DIRTY_AREAS - 1)
194 {
195 widget = (GX_WIDGET *)root;
196 }
197
198 /* Setup pointer to dirty list. */
199
200 dirty_entry = canvas -> gx_canvas_dirty_list;
201
202 /* Check to see if widget already has an entry. */
203 if (widget -> gx_widget_status & GX_STATUS_DIRTY)
204 {
205 for (index = 0; index < canvas -> gx_canvas_dirty_count; index++)
206 {
207 /* Is the same widget is present. */
208 if (dirty_entry -> gx_dirty_area_widget == widget)
209 {
210 /* if rectangles overlap or if we are running low on dirty area,
211 records, combine them rather than adding another entry
212 */
213 if (canvas -> gx_canvas_dirty_count >= GX_MAX_DIRTY_AREAS - 1 ||
214 _gx_utility_rectangle_overlap_detect(&dirty_entry -> gx_dirty_area_rectangle,
215 dirty_area, GX_NULL))
216 {
217 /* Combine the dirty rectangles. */
218 _gx_utility_rectangle_combine(&dirty_entry -> gx_dirty_area_rectangle, dirty_area);
219
220 /* Return success. */
221 GX_EXIT_CRITICAL
222 return(GX_SUCCESS);
223 }
224 }
225
226 /* Move to next dirty entry. */
227 dirty_entry++;
228 }
229 }
230
231 /* If we get here, we didn't find an entry for this caller. Add a new entry. */
232
233 /* Are there more dirty entries? */
234 if (canvas -> gx_canvas_dirty_count < GX_MAX_DIRTY_AREAS)
235 {
236 /* Yes, more dirty entries, add this one! */
237 dirty_entry = &canvas -> gx_canvas_dirty_list[canvas -> gx_canvas_dirty_count];
238 canvas -> gx_canvas_dirty_count++;
239 dirty_entry -> gx_dirty_area_widget = widget;
240 dirty_entry -> gx_dirty_area_rectangle = *dirty_area;
241 widget -> gx_widget_status |= GX_STATUS_DIRTY;
242 }
243
244 /* end of critical section */
245 GX_EXIT_CRITICAL
246
247 /* Return success. */
248 return(GX_SUCCESS);
249 }
250
251 #endif
252
253