summaryrefslogtreecommitdiff
path: root/src/ui/widget.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-04-27 11:40:50 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-04-27 11:40:50 +0300
commit170209cf926e2f714d507fefaa6b30fd245811ad (patch)
tree1dd6ff1e7c9ecf69c0857b8524bfdc82f07794b9 /src/ui/widget.c
parent83e14d99ba75316da265cfa5f3fd092caa1498cf (diff)
Refactor: Moving RootData so it can become non-global state
Diffstat (limited to 'src/ui/widget.c')
-rw-r--r--src/ui/widget.c96
1 files changed, 30 insertions, 66 deletions
diff --git a/src/ui/widget.c b/src/ui/widget.c
index b7458528..b3f7b27f 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -39,42 +39,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
39# include "../ios.h" 39# include "../ios.h"
40#endif 40#endif
41 41
42iDeclareType(RootData)
43
44/* TODO: Move to root.c, one instance per root widget. */
45struct Impl_RootData {
46 iWidget *hover;
47 iWidget *mouseGrab;
48 iWidget *focus;
49 iPtrArray *onTop; /* order is important; last one is topmost */
50 iPtrSet *pendingDestruction;
51};
52
53static iRootData rootData_;
54
55iPtrArray *onTop_RootData_(void) {
56 if (!rootData_.onTop) {
57 rootData_.onTop = new_PtrArray();
58 }
59 return rootData_.onTop;
60}
61
62void destroyPending_Widget(void) {
63 iForEach(PtrSet, i, rootData_.pendingDestruction) {
64 iWidget *widget = *i.value;
65 if (!isFinished_Anim(&widget->visualOffset)) {
66 continue;
67 }
68 if (widget->parent) {
69 removeChild_Widget(widget->parent, widget);
70 }
71 iAssert(widget->parent == NULL);
72// iAssert(widget->object.refCount == 1); /* ref could be held in garbage still */
73 iRelease(widget);
74 remove_PtrSetIterator(&i);
75 }
76}
77
78void releaseChildren_Widget(iWidget *d) { 42void releaseChildren_Widget(iWidget *d) {
79 iForEach(ObjectList, i, d->children) { 43 iForEach(ObjectList, i, d->children) {
80 ((iWidget *) i.object)->parent = NULL; /* the actual reference being held */ 44 ((iWidget *) i.object)->parent = NULL; /* the actual reference being held */
@@ -117,7 +81,7 @@ void deinit_Widget(iWidget *d) {
117//#endif 81//#endif
118 deinit_String(&d->id); 82 deinit_String(&d->id);
119 if (d->flags & keepOnTop_WidgetFlag) { 83 if (d->flags & keepOnTop_WidgetFlag) {
120 removeAll_PtrArray(onTop_RootData_(), d); 84 removeAll_PtrArray(onTop_RootData(), d);
121 } 85 }
122 if (d->flags & visualOffset_WidgetFlag) { 86 if (d->flags & visualOffset_WidgetFlag) {
123 removeTicker_App(visualOffsetAnimation_Widget_, d); 87 removeTicker_App(visualOffsetAnimation_Widget_, d);
@@ -131,10 +95,10 @@ static void aboutToBeDestroyed_Widget_(iWidget *d) {
131 return; 95 return;
132 } 96 }
133 if (flags_Widget(d) & keepOnTop_WidgetFlag) { 97 if (flags_Widget(d) & keepOnTop_WidgetFlag) {
134 removeOne_PtrArray(onTop_RootData_(), d); 98 removeOne_PtrArray(onTop_RootData(), d);
135 } 99 }
136 if (isHover_Widget(d)) { 100 if (isHover_Widget(d)) {
137 rootData_.hover = NULL; 101 data_Root()->hover = NULL;
138 } 102 }
139 iForEach(ObjectList, i, d->children) { 103 iForEach(ObjectList, i, d->children) {
140 aboutToBeDestroyed_Widget_(as_Widget(i.object)); 104 aboutToBeDestroyed_Widget_(as_Widget(i.object));
@@ -147,10 +111,10 @@ void destroy_Widget(iWidget *d) {
147 postRefresh_App(); 111 postRefresh_App();
148 } 112 }
149 aboutToBeDestroyed_Widget_(d); 113 aboutToBeDestroyed_Widget_(d);
150 if (!rootData_.pendingDestruction) { 114 if (!data_Root()->pendingDestruction) {
151 rootData_.pendingDestruction = new_PtrSet(); 115 data_Root()->pendingDestruction = new_PtrSet();
152 } 116 }
153 insert_PtrSet(rootData_.pendingDestruction, d); 117 insert_PtrSet(data_Root()->pendingDestruction, d);
154 } 118 }
155} 119}
156 120
@@ -174,7 +138,7 @@ void setFlags_Widget(iWidget *d, int64_t flags, iBool set) {
174 } 138 }
175 iChangeFlags(d->flags, flags, set); 139 iChangeFlags(d->flags, flags, set);
176 if (flags & keepOnTop_WidgetFlag) { 140 if (flags & keepOnTop_WidgetFlag) {
177 iPtrArray *onTop = onTop_RootData_(); 141 iPtrArray *onTop = onTop_RootData();
178 if (set) { 142 if (set) {
179 iAssert(indexOf_PtrArray(onTop, d) == iInvalidPos); 143 iAssert(indexOf_PtrArray(onTop, d) == iInvalidPos);
180 pushBack_PtrArray(onTop, d); 144 pushBack_PtrArray(onTop, d);
@@ -769,24 +733,24 @@ static iBool filterEvent_Widget_(const iWidget *d, const SDL_Event *ev) {
769} 733}
770 734
771void unhover_Widget(void) { 735void unhover_Widget(void) {
772 rootData_.hover = NULL; 736 data_Root()->hover = NULL;
773} 737}
774 738
775iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { 739iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
776 if (!d->parent) { 740 if (!d->parent) {
777 setCurrent_Root(d); 741 //setCurrent_Root(d);
778 if (ev->type == SDL_MOUSEMOTION) { 742 if (ev->type == SDL_MOUSEMOTION) {
779 /* Hover widget may change. */ 743 /* Hover widget may change. */
780 setHover_Widget(NULL); 744 setHover_Widget(NULL);
781 } 745 }
782 if (rootData_.focus && isKeyboardEvent_(ev)) { 746 if (data_Root()->focus && isKeyboardEvent_(ev)) {
783 /* Root dispatches keyboard events directly to the focused widget. */ 747 /* Root dispatches keyboard events directly to the focused widget. */
784 if (dispatchEvent_Widget(rootData_.focus, ev)) { 748 if (dispatchEvent_Widget(data_Root()->focus, ev)) {
785 return iTrue; 749 return iTrue;
786 } 750 }
787 } 751 }
788 /* Root offers events first to widgets on top. */ 752 /* Root offers events first to widgets on top. */
789 iReverseForEach(PtrArray, i, rootData_.onTop) { 753 iReverseForEach(PtrArray, i, data_Root()->onTop) {
790 iWidget *widget = *i.value; 754 iWidget *widget = *i.value;
791 if (isVisible_Widget(widget) && dispatchEvent_Widget(widget, ev)) { 755 if (isVisible_Widget(widget) && dispatchEvent_Widget(widget, ev)) {
792#if 0 756#if 0
@@ -810,7 +774,7 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
810 } 774 }
811 } 775 }
812 else if (ev->type == SDL_MOUSEMOTION && 776 else if (ev->type == SDL_MOUSEMOTION &&
813 (!rootData_.hover || hasParent_Widget(d, rootData_.hover)) && 777 (!data_Root()->hover || hasParent_Widget(d, data_Root()->hover)) &&
814 flags_Widget(d) & hover_WidgetFlag && ~flags_Widget(d) & hidden_WidgetFlag && 778 flags_Widget(d) & hover_WidgetFlag && ~flags_Widget(d) & hidden_WidgetFlag &&
815 ~flags_Widget(d) & disabled_WidgetFlag) { 779 ~flags_Widget(d) & disabled_WidgetFlag) {
816 if (contains_Widget(d, init_I2(ev->motion.x, ev->motion.y))) { 780 if (contains_Widget(d, init_I2(ev->motion.x, ev->motion.y))) {
@@ -828,7 +792,7 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
828 handle the events first. */ 792 handle the events first. */
829 iReverseForEach(ObjectList, i, d->children) { 793 iReverseForEach(ObjectList, i, d->children) {
830 iWidget *child = as_Widget(i.object); 794 iWidget *child = as_Widget(i.object);
831 if (child == rootData_.focus && isKeyboardEvent_(ev)) { 795 if (child == data_Root()->focus && isKeyboardEvent_(ev)) {
832 continue; /* Already dispatched. */ 796 continue; /* Already dispatched. */
833 } 797 }
834 if (isVisible_Widget(child) && child->flags & keepOnTop_WidgetFlag) { 798 if (isVisible_Widget(child) && child->flags & keepOnTop_WidgetFlag) {
@@ -1117,7 +1081,7 @@ void drawChildren_Widget(const iWidget *d) {
1117 } 1081 }
1118 /* Root draws the on-top widgets on top of everything else. */ 1082 /* Root draws the on-top widgets on top of everything else. */
1119 if (!d->parent) { 1083 if (!d->parent) {
1120 iConstForEach(PtrArray, i, onTop_RootData_()) { 1084 iConstForEach(PtrArray, i, onTop_RootData()) {
1121 const iWidget *top = *i.value; 1085 const iWidget *top = *i.value;
1122 draw_Widget(top); 1086 draw_Widget(top);
1123 } 1087 }
@@ -1234,7 +1198,7 @@ iAny *hitChild_Widget(const iWidget *d, iInt2 coord) {
1234 } 1198 }
1235 /* Check for on-top widgets first. */ 1199 /* Check for on-top widgets first. */
1236 if (!d->parent) { 1200 if (!d->parent) {
1237 iReverseForEach(PtrArray, i, onTop_RootData_()) { 1201 iReverseForEach(PtrArray, i, onTop_RootData()) {
1238 iWidget *child = i.ptr; 1202 iWidget *child = i.ptr;
1239// printf("ontop: %s (%s) hidden:%d hittable:%d\n", cstr_String(id_Widget(child)), 1203// printf("ontop: %s (%s) hidden:%d hittable:%d\n", cstr_String(id_Widget(child)),
1240// class_Widget(child)->name, 1204// class_Widget(child)->name,
@@ -1322,12 +1286,12 @@ iBool isDisabled_Widget(const iAnyObject *d) {
1322 1286
1323iBool isFocused_Widget(const iAnyObject *d) { 1287iBool isFocused_Widget(const iAnyObject *d) {
1324 iAssert(isInstance_Object(d, &Class_Widget)); 1288 iAssert(isInstance_Object(d, &Class_Widget));
1325 return rootData_.focus == d; 1289 return data_Root()->focus == d;
1326} 1290}
1327 1291
1328iBool isHover_Widget(const iAnyObject *d) { 1292iBool isHover_Widget(const iAnyObject *d) {
1329 iAssert(isInstance_Object(d, &Class_Widget)); 1293 iAssert(isInstance_Object(d, &Class_Widget));
1330 return rootData_.hover == d; 1294 return data_Root()->hover == d;
1331} 1295}
1332 1296
1333iBool isSelected_Widget(const iAnyObject *d) { 1297iBool isSelected_Widget(const iAnyObject *d) {
@@ -1373,12 +1337,12 @@ iBool isAffectedByVisualOffset_Widget(const iWidget *d) {
1373} 1337}
1374 1338
1375void setFocus_Widget(iWidget *d) { 1339void setFocus_Widget(iWidget *d) {
1376 if (rootData_.focus != d) { 1340 if (data_Root()->focus != d) {
1377 if (rootData_.focus) { 1341 if (data_Root()->focus) {
1378 iAssert(!contains_PtrSet(rootData_.pendingDestruction, rootData_.focus)); 1342 iAssert(!contains_PtrSet(data_Root()->pendingDestruction, data_Root()->focus));
1379 postCommand_Widget(rootData_.focus, "focus.lost"); 1343 postCommand_Widget(data_Root()->focus, "focus.lost");
1380 } 1344 }
1381 rootData_.focus = d; 1345 data_Root()->focus = d;
1382 if (d) { 1346 if (d) {
1383 iAssert(flags_Widget(d) & focusable_WidgetFlag); 1347 iAssert(flags_Widget(d) & focusable_WidgetFlag);
1384 postCommand_Widget(d, "focus.gained"); 1348 postCommand_Widget(d, "focus.gained");
@@ -1387,15 +1351,15 @@ void setFocus_Widget(iWidget *d) {
1387} 1351}
1388 1352
1389iWidget *focus_Widget(void) { 1353iWidget *focus_Widget(void) {
1390 return rootData_.focus; 1354 return data_Root()->focus;
1391} 1355}
1392 1356
1393void setHover_Widget(iWidget *d) { 1357void setHover_Widget(iWidget *d) {
1394 rootData_.hover = d; 1358 data_Root()->hover = d;
1395} 1359}
1396 1360
1397iWidget *hover_Widget(void) { 1361iWidget *hover_Widget(void) {
1398 return rootData_.hover; 1362 return data_Root()->hover;
1399} 1363}
1400 1364
1401static const iWidget *findFocusable_Widget_(const iWidget *d, const iWidget *startFrom, 1365static const iWidget *findFocusable_Widget_(const iWidget *d, const iWidget *startFrom,
@@ -1451,14 +1415,14 @@ iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusD
1451} 1415}
1452 1416
1453void setMouseGrab_Widget(iWidget *d) { 1417void setMouseGrab_Widget(iWidget *d) {
1454 if (rootData_.mouseGrab != d) { 1418 if (data_Root()->mouseGrab != d) {
1455 rootData_.mouseGrab = d; 1419 data_Root()->mouseGrab = d;
1456 SDL_CaptureMouse(d != NULL); 1420 SDL_CaptureMouse(d != NULL);
1457 } 1421 }
1458} 1422}
1459 1423
1460iWidget *mouseGrab_Widget(void) { 1424iWidget *mouseGrab_Widget(void) {
1461 return rootData_.mouseGrab; 1425 return data_Root()->mouseGrab;
1462} 1426}
1463 1427
1464void postCommand_Widget(const iAnyObject *d, const char *cmd, ...) { 1428void postCommand_Widget(const iAnyObject *d, const char *cmd, ...) {
@@ -1492,7 +1456,7 @@ void refresh_Widget(const iAnyObject *d) {
1492} 1456}
1493 1457
1494void raise_Widget(iWidget *d) { 1458void raise_Widget(iWidget *d) {
1495 iPtrArray *onTop = onTop_RootData_(); 1459 iPtrArray *onTop = onTop_RootData();
1496 if (d->flags & keepOnTop_WidgetFlag) { 1460 if (d->flags & keepOnTop_WidgetFlag) {
1497 iAssert(indexOf_PtrArray(onTop, d) != iInvalidPos); 1461 iAssert(indexOf_PtrArray(onTop, d) != iInvalidPos);
1498 removeOne_PtrArray(onTop, d); 1462 removeOne_PtrArray(onTop, d);