summaryrefslogtreecommitdiff
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
parent83e14d99ba75316da265cfa5f3fd092caa1498cf (diff)
Refactor: Moving RootData so it can become non-global state
-rw-r--r--src/app.c2
-rw-r--r--src/ui/root.c35
-rw-r--r--src/ui/root.h20
-rw-r--r--src/ui/util.c11
-rw-r--r--src/ui/widget.c96
-rw-r--r--src/ui/window.c7
6 files changed, 93 insertions, 78 deletions
diff --git a/src/app.c b/src/app.c
index e6707b04..c4511dc7 100644
--- a/src/app.c
+++ b/src/app.c
@@ -1131,7 +1131,7 @@ static int run_App_(iApp *d) {
1131 1131
1132void refresh_App(void) { 1132void refresh_App(void) {
1133 iApp *d = &app_; 1133 iApp *d = &app_;
1134 destroyPending_Widget(); 1134 destroyPending_RootData(data_Root());
1135#if defined (LAGRANGE_ENABLE_IDLE_SLEEP) 1135#if defined (LAGRANGE_ENABLE_IDLE_SLEEP)
1136 if (d->warmupFrames == 0 && d->isIdling) { 1136 if (d->warmupFrames == 0 && d->isIdling) {
1137 return; 1137 return;
diff --git a/src/ui/root.c b/src/ui/root.c
index 50c4992e..f6b93abd 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -234,16 +234,45 @@ static const char *stopSeqCStr_[] = {
234static const int loadAnimIntervalMs_ = 133; 234static const int loadAnimIntervalMs_ = 133;
235static int loadAnimIndex_ = 0; 235static int loadAnimIndex_ = 0;
236 236
237static iWidget * activeRoot_ = NULL; 237static iWidget * activeRoot_ = NULL;
238static iRootData * activeRootData_ = NULL;
238 239
239void setCurrent_Root(iWidget *root) { 240void setCurrent_Root(iWidget *root, iRootData *rootData) {
240 activeRoot_ = root; 241 activeRoot_ = root;
242 activeRootData_ = rootData;
241} 243}
242 244
243iWidget *get_Root(void) { 245iWidget *get_Root(void) {
244 return activeRoot_; 246 return activeRoot_;
245} 247}
246 248
249iRootData *data_Root(void) {
250 return activeRootData_;
251}
252
253void destroyPending_RootData(iRootData *d) {
254 iForEach(PtrSet, i, d->pendingDestruction) {
255 iWidget *widget = *i.value;
256 if (!isFinished_Anim(&widget->visualOffset)) {
257 continue;
258 }
259 if (widget->parent) {
260 removeChild_Widget(widget->parent, widget);
261 }
262 iAssert(widget->parent == NULL);
263 iRelease(widget);
264 remove_PtrSetIterator(&i);
265 }
266}
267
268iPtrArray *onTop_RootData(void) {
269 iAssert(activeRootData_);
270 if (!activeRootData_->onTop) {
271 activeRootData_->onTop = new_PtrArray();
272 }
273 return activeRootData_->onTop;
274}
275
247static iBool handleRootCommands_(iWidget *root, const char *cmd) { 276static iBool handleRootCommands_(iWidget *root, const char *cmd) {
248 iUnused(root); 277 iUnused(root);
249 if (equal_Command(cmd, "menu.open")) { 278 if (equal_Command(cmd, "menu.open")) {
@@ -1031,8 +1060,6 @@ iWidget *createUserInterface_Root(void) {
1031# endif 1060# endif
1032 setAlignVisually_LabelWidget(navMenu, iTrue); 1061 setAlignVisually_LabelWidget(navMenu, iTrue);
1033 setId_Widget(addChildFlags_Widget(navBar, iClob(navMenu), collapse_WidgetFlag), "navbar.menu"); 1062 setId_Widget(addChildFlags_Widget(navBar, iClob(navMenu), collapse_WidgetFlag), "navbar.menu");
1034#else
1035 insertMacMenus_();
1036#endif 1063#endif
1037 } 1064 }
1038 /* Tab bar. */ { 1065 /* Tab bar. */ {
diff --git a/src/ui/root.h b/src/ui/root.h
index a3e595ba..fcb5b1b0 100644
--- a/src/ui/root.h
+++ b/src/ui/root.h
@@ -1,12 +1,30 @@
1#pragma once 1#pragma once
2 2
3#include "widget.h" 3#include "widget.h"
4#include <the_Foundation/ptrset.h>
5
6iDeclareType(RootData)
7
8/* TODO: Rename to Root, include `iWidget *root` as well. */
9struct Impl_RootData {
10 iWidget * hover;
11 iWidget * mouseGrab;
12 iWidget * focus;
13 iPtrArray *onTop; /* order is important; last one is topmost */
14 iPtrSet * pendingDestruction;
15};
16
17/*----------------------------------------------------------------------------------------------*/
4 18
5iWidget * createUserInterface_Root (void); 19iWidget * createUserInterface_Root (void);
6 20
7void setCurrent_Root (iWidget *root); 21void setCurrent_Root (iWidget *root, iRootData *rootData);
8iWidget * get_Root (void); 22iWidget * get_Root (void);
23iRootData * data_Root (void);
9 24
25iPtrArray * onTop_RootData (void);
26void destroyPending_RootData (iRootData *);
27
10void updateMetrics_Root (iWidget *); 28void updateMetrics_Root (iWidget *);
11void updatePadding_Root (iWidget *); /* TODO: is part of metrics? */ 29void updatePadding_Root (iWidget *); /* TODO: is part of metrics? */
12void dismissPortraitPhoneSidebars_Root (iWidget *); 30void dismissPortraitPhoneSidebars_Root (iWidget *);
diff --git a/src/ui/util.c b/src/ui/util.c
index 0e2deede..b80f7650 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -23,20 +23,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
23#include "util.h" 23#include "util.h"
24 24
25#include "app.h" 25#include "app.h"
26#include "bindingswidget.h"
26#include "bookmarks.h" 27#include "bookmarks.h"
27#include "color.h" 28#include "color.h"
28#include "command.h" 29#include "command.h"
29#include "defs.h" 30#include "defs.h"
30#include "documentwidget.h" 31#include "documentwidget.h"
31#include "gmutil.h"
32#include "feeds.h" 32#include "feeds.h"
33#include "labelwidget.h" 33#include "gmutil.h"
34#include "inputwidget.h" 34#include "inputwidget.h"
35#include "bindingswidget.h"
36#include "keys.h" 35#include "keys.h"
37#include "widget.h" 36#include "labelwidget.h"
37#include "root.h"
38#include "text.h" 38#include "text.h"
39#include "touch.h" 39#include "touch.h"
40#include "widget.h"
40#include "window.h" 41#include "window.h"
41 42
42#if defined (iPlatformAppleMobile) 43#if defined (iPlatformAppleMobile)
@@ -1572,7 +1573,7 @@ void finalizeSheet_Widget(iWidget *sheet) {
1572 destroy_Widget(pageContent); 1573 destroy_Widget(pageContent);
1573 setFlags_Widget(owner, drawBackgroundToBottom_WidgetFlag, iTrue); 1574 setFlags_Widget(owner, drawBackgroundToBottom_WidgetFlag, iTrue);
1574 } 1575 }
1575 destroyPending_Widget(); 1576 destroyPending_RootData(data_Root());
1576 /* Additional elements for preferences. */ 1577 /* Additional elements for preferences. */
1577 if (isPrefs) { 1578 if (isPrefs) {
1578 addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(defaultBig_FontId)))); 1579 addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(defaultBig_FontId))));
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);
diff --git a/src/ui/window.c b/src/ui/window.c
index 9732a4f9..ea2a4ec0 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -162,8 +162,13 @@ static void removeMacMenus_(void) {
162#endif 162#endif
163 163
164static void setupUserInterface_Window(iWindow *d) { 164static void setupUserInterface_Window(iWindow *d) {
165#if defined (iPlatformAppleDesktop)
166 insertMacMenus_();
167#endif
168 static iRootData rootData_;
169 setCurrent_Root(NULL, &rootData_);
165 d->root = createUserInterface_Root(); 170 d->root = createUserInterface_Root();
166 setCurrent_Root(d->root); 171 setCurrent_Root(d->root, &rootData_);
167} 172}
168 173
169static void updateRootSize_Window_(iWindow *d, iBool notifyAlways) { 174static void updateRootSize_Window_(iWindow *d, iBool notifyAlways) {