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