diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-27 11:59:28 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-27 11:59:28 +0300 |
commit | 9a7aa34e63132edb5906914ff99b861e64ee9099 (patch) | |
tree | 327e275b7f4fd6eb05150f7c03a87a72794d22a0 | |
parent | 170209cf926e2f714d507fefaa6b30fd245811ad (diff) |
Refactor: Added a proper Root object
`Root` encapsulates the root widget and the associated UI state.
-rw-r--r-- | src/app.c | 8 | ||||
-rw-r--r-- | src/ui/paint.c | 4 | ||||
-rw-r--r-- | src/ui/root.c | 78 | ||||
-rw-r--r-- | src/ui/root.h | 27 | ||||
-rw-r--r-- | src/ui/sidebarwidget.c | 2 | ||||
-rw-r--r-- | src/ui/touch.c | 12 | ||||
-rw-r--r-- | src/ui/util.c | 16 | ||||
-rw-r--r-- | src/ui/widget.c | 63 | ||||
-rw-r--r-- | src/ui/window.c | 40 | ||||
-rw-r--r-- | src/ui/window.h | 6 |
10 files changed, 129 insertions, 127 deletions
@@ -1046,7 +1046,7 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1046 | handleCommand_MacOS(command_UserEvent(&ev)); | 1046 | handleCommand_MacOS(command_UserEvent(&ev)); |
1047 | #endif | 1047 | #endif |
1048 | if (isMetricsChange_UserEvent(&ev)) { | 1048 | if (isMetricsChange_UserEvent(&ev)) { |
1049 | arrange_Widget(d->window->root); | 1049 | arrange_Widget(d->window->root.widget); |
1050 | } | 1050 | } |
1051 | if (!wasUsed) { | 1051 | if (!wasUsed) { |
1052 | /* No widget handled the command, so we'll do it. */ | 1052 | /* No widget handled the command, so we'll do it. */ |
@@ -1131,7 +1131,7 @@ static int run_App_(iApp *d) { | |||
1131 | 1131 | ||
1132 | void refresh_App(void) { | 1132 | void refresh_App(void) { |
1133 | iApp *d = &app_; | 1133 | iApp *d = &app_; |
1134 | destroyPending_RootData(data_Root()); | 1134 | destroyPending_Root(&d->window->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; |
@@ -1262,7 +1262,7 @@ void postCommandf_App(const char *command, ...) { | |||
1262 | 1262 | ||
1263 | iAny *findWidget_App(const char *id) { | 1263 | iAny *findWidget_App(const char *id) { |
1264 | if (!*id) return NULL; | 1264 | if (!*id) return NULL; |
1265 | return findChild_Widget(app_.window->root, id); | 1265 | return findChild_Widget(app_.window->root.widget, id); |
1266 | } | 1266 | } |
1267 | 1267 | ||
1268 | void addTicker_App(iTickerFunc ticker, iAny *context) { | 1268 | void addTicker_App(iTickerFunc ticker, iAny *context) { |
@@ -2120,7 +2120,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2120 | else if (equal_Command(cmd, "ident.import")) { | 2120 | else if (equal_Command(cmd, "ident.import")) { |
2121 | iCertImportWidget *imp = new_CertImportWidget(); | 2121 | iCertImportWidget *imp = new_CertImportWidget(); |
2122 | setPageContent_CertImportWidget(imp, sourceContent_DocumentWidget(document_App())); | 2122 | setPageContent_CertImportWidget(imp, sourceContent_DocumentWidget(document_App())); |
2123 | addChild_Widget(d->window->root, iClob(imp)); | 2123 | addChild_Widget(d->window->root.widget, iClob(imp)); |
2124 | finalizeSheet_Widget(as_Widget(imp)); | 2124 | finalizeSheet_Widget(as_Widget(imp)); |
2125 | postRefresh_App(); | 2125 | postRefresh_App(); |
2126 | return iTrue; | 2126 | return iTrue; |
diff --git a/src/ui/paint.c b/src/ui/paint.c index 857bf20c..02914489 100644 --- a/src/ui/paint.c +++ b/src/ui/paint.c | |||
@@ -87,8 +87,8 @@ void unsetClip_Paint(iPaint *d) { | |||
87 | void drawRect_Paint(const iPaint *d, iRect rect, int color) { | 87 | void drawRect_Paint(const iPaint *d, iRect rect, int color) { |
88 | iInt2 br = bottomRight_Rect(rect); | 88 | iInt2 br = bottomRight_Rect(rect); |
89 | /* Keep the right/bottom edge visible in the window. */ | 89 | /* Keep the right/bottom edge visible in the window. */ |
90 | if (br.x == d->dst->root->rect.size.x) br.x--; | 90 | if (br.x == d->dst->root.widget->rect.size.x) br.x--; |
91 | if (br.y == d->dst->root->rect.size.y) br.y--; | 91 | if (br.y == d->dst->root.widget->rect.size.y) br.y--; |
92 | const SDL_Point edges[] = { | 92 | const SDL_Point edges[] = { |
93 | { left_Rect(rect), top_Rect(rect) }, | 93 | { left_Rect(rect), top_Rect(rect) }, |
94 | { br.x, top_Rect(rect) }, | 94 | { br.x, top_Rect(rect) }, |
diff --git a/src/ui/root.c b/src/ui/root.c index f6b93abd..1fa36851 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -234,23 +234,27 @@ static const char *stopSeqCStr_[] = { | |||
234 | static const int loadAnimIntervalMs_ = 133; | 234 | static const int loadAnimIntervalMs_ = 133; |
235 | static int loadAnimIndex_ = 0; | 235 | static int loadAnimIndex_ = 0; |
236 | 236 | ||
237 | static iWidget * activeRoot_ = NULL; | 237 | static iRoot * activeRoot_ = NULL; |
238 | static iRootData * activeRootData_ = NULL; | ||
239 | 238 | ||
240 | void setCurrent_Root(iWidget *root, iRootData *rootData) { | 239 | iDefineTypeConstruction(Root) |
241 | activeRoot_ = root; | 240 | |
242 | activeRootData_ = rootData; | 241 | void init_Root(iRoot *d) { |
242 | iZap(*d); | ||
243 | } | 243 | } |
244 | 244 | ||
245 | iWidget *get_Root(void) { | 245 | void deinit_Root(iRoot *d) { |
246 | return activeRoot_; | 246 | iReleasePtr(&d->widget); |
247 | } | ||
248 | |||
249 | void setCurrent_Root(iRoot *root) { | ||
250 | activeRoot_ = root; | ||
247 | } | 251 | } |
248 | 252 | ||
249 | iRootData *data_Root(void) { | 253 | iRoot *get_Root(void) { |
250 | return activeRootData_; | 254 | return activeRoot_; |
251 | } | 255 | } |
252 | 256 | ||
253 | void destroyPending_RootData(iRootData *d) { | 257 | void destroyPending_Root(iRoot *d) { |
254 | iForEach(PtrSet, i, d->pendingDestruction) { | 258 | iForEach(PtrSet, i, d->pendingDestruction) { |
255 | iWidget *widget = *i.value; | 259 | iWidget *widget = *i.value; |
256 | if (!isFinished_Anim(&widget->visualOffset)) { | 260 | if (!isFinished_Anim(&widget->visualOffset)) { |
@@ -265,12 +269,11 @@ void destroyPending_RootData(iRootData *d) { | |||
265 | } | 269 | } |
266 | } | 270 | } |
267 | 271 | ||
268 | iPtrArray *onTop_RootData(void) { | 272 | iPtrArray *onTop_Root(iRoot *d) { |
269 | iAssert(activeRootData_); | 273 | if (!d->onTop) { |
270 | if (!activeRootData_->onTop) { | 274 | d->onTop = new_PtrArray(); |
271 | activeRootData_->onTop = new_PtrArray(); | ||
272 | } | 275 | } |
273 | return activeRootData_->onTop; | 276 | return d->onTop; |
274 | } | 277 | } |
275 | 278 | ||
276 | static iBool handleRootCommands_(iWidget *root, const char *cmd) { | 279 | static iBool handleRootCommands_(iWidget *root, const char *cmd) { |
@@ -423,7 +426,7 @@ static uint32_t updateReloadAnimation_Window_(uint32_t interval, void *window) { | |||
423 | 426 | ||
424 | static void setReloadLabel_Window_(iWindow *d, iBool animating) { | 427 | static void setReloadLabel_Window_(iWindow *d, iBool animating) { |
425 | const iBool isMobile = deviceType_App() != desktop_AppDeviceType; | 428 | const iBool isMobile = deviceType_App() != desktop_AppDeviceType; |
426 | iLabelWidget *label = findChild_Widget(d->root, "reload"); | 429 | iLabelWidget *label = findChild_Widget(d->root.widget, "reload"); |
427 | updateTextCStr_LabelWidget(label, animating ? loadAnimationCStr_() : | 430 | updateTextCStr_LabelWidget(label, animating ? loadAnimationCStr_() : |
428 | (isMobile ? pageMenuCStr_ : reloadCStr_)); | 431 | (isMobile ? pageMenuCStr_ : reloadCStr_)); |
429 | if (isMobile) { | 432 | if (isMobile) { |
@@ -444,13 +447,13 @@ static void checkLoadAnimation_Window_(iWindow *d) { | |||
444 | setReloadLabel_Window_(d, isOngoing); | 447 | setReloadLabel_Window_(d, isOngoing); |
445 | } | 448 | } |
446 | 449 | ||
447 | void updatePadding_Root(iWidget *d) { | 450 | void updatePadding_Root(iRoot *d) { |
448 | #if defined (iPlatformAppleMobile) | 451 | #if defined (iPlatformAppleMobile) |
449 | iWidget *toolBar = findChild_Widget(d, "toolbar"); | 452 | iWidget *toolBar = findChild_Widget(d->widget, "toolbar"); |
450 | float left, top, right, bottom; | 453 | float left, top, right, bottom; |
451 | safeAreaInsets_iOS(&left, &top, &right, &bottom); | 454 | safeAreaInsets_iOS(&left, &top, &right, &bottom); |
452 | /* Respect the safe area insets. */ { | 455 | /* Respect the safe area insets. */ { |
453 | setPadding_Widget(findChild_Widget(d, "navdiv"), left, top, right, 0); | 456 | setPadding_Widget(findChild_Widget(d->widget, "navdiv"), left, top, right, 0); |
454 | if (toolBar) { | 457 | if (toolBar) { |
455 | setPadding_Widget(toolBar, left, 0, right, bottom); | 458 | setPadding_Widget(toolBar, left, 0, right, bottom); |
456 | } | 459 | } |
@@ -458,8 +461,8 @@ void updatePadding_Root(iWidget *d) { | |||
458 | if (toolBar) { | 461 | if (toolBar) { |
459 | /* TODO: get this from toolBar height, but it's buggy for some reason */ | 462 | /* TODO: get this from toolBar height, but it's buggy for some reason */ |
460 | const int sidebarBottomPad = isPortrait_App() ? 11 * gap_UI + bottom : 0; | 463 | const int sidebarBottomPad = isPortrait_App() ? 11 * gap_UI + bottom : 0; |
461 | setPadding_Widget(findChild_Widget(d, "sidebar"), 0, 0, 0, sidebarBottomPad); | 464 | setPadding_Widget(findChild_Widget(d->widget, "sidebar"), 0, 0, 0, sidebarBottomPad); |
462 | setPadding_Widget(findChild_Widget(d, "sidebar2"), 0, 0, 0, sidebarBottomPad); | 465 | setPadding_Widget(findChild_Widget(d->widget, "sidebar2"), 0, 0, 0, sidebarBottomPad); |
463 | /* TODO: There seems to be unrelated layout glitch in the sidebar where its children | 466 | /* TODO: There seems to be unrelated layout glitch in the sidebar where its children |
464 | are not arranged correctly until it's hidden and reshown. */ | 467 | are not arranged correctly until it's hidden and reshown. */ |
465 | } | 468 | } |
@@ -469,10 +472,10 @@ void updatePadding_Root(iWidget *d) { | |||
469 | #endif | 472 | #endif |
470 | } | 473 | } |
471 | 474 | ||
472 | void dismissPortraitPhoneSidebars_Root(iWidget *root) { | 475 | void dismissPortraitPhoneSidebars_Root(iRoot *d) { |
473 | if (deviceType_App() == phone_AppDeviceType && isPortrait_App()) { | 476 | if (deviceType_App() == phone_AppDeviceType && isPortrait_App()) { |
474 | iWidget *sidebar = findChild_Widget(root, "sidebar"); | 477 | iWidget *sidebar = findChild_Widget(d->widget, "sidebar"); |
475 | iWidget *sidebar2 = findChild_Widget(root, "sidebar2"); | 478 | iWidget *sidebar2 = findChild_Widget(d->widget, "sidebar2"); |
476 | if (isVisible_Widget(sidebar)) { | 479 | if (isVisible_Widget(sidebar)) { |
477 | postCommand_App("sidebar.toggle"); | 480 | postCommand_App("sidebar.toggle"); |
478 | setVisualOffset_Widget(sidebar, height_Widget(sidebar), 250, easeIn_AnimFlag); | 481 | setVisualOffset_Widget(sidebar, height_Widget(sidebar), 250, easeIn_AnimFlag); |
@@ -564,7 +567,7 @@ static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) { | |||
564 | updateSize_LabelWidget(btn); | 567 | updateSize_LabelWidget(btn); |
565 | } | 568 | } |
566 | } | 569 | } |
567 | arrange_Widget(get_Window()->root); | 570 | arrange_Widget(get_Window()->root.widget); |
568 | } | 571 | } |
569 | /* Resize the URL input field. */ { | 572 | /* Resize the URL input field. */ { |
570 | iWidget *urlBar = findChild_Widget(navBar, "url"); | 573 | iWidget *urlBar = findChild_Widget(navBar, "url"); |
@@ -716,7 +719,7 @@ static iBool handleSearchBarCommands_(iWidget *searchBar, const char *cmd) { | |||
716 | if (pointer_Command(cmd) == findChild_Widget(searchBar, "find.input")) { | 719 | if (pointer_Command(cmd) == findChild_Widget(searchBar, "find.input")) { |
717 | if (!isVisible_Widget(searchBar)) { | 720 | if (!isVisible_Widget(searchBar)) { |
718 | setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); | 721 | setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); |
719 | arrange_Widget(get_Window()->root); | 722 | arrange_Widget(get_Window()->root.widget); |
720 | postRefresh_App(); | 723 | postRefresh_App(); |
721 | } | 724 | } |
722 | } | 725 | } |
@@ -824,9 +827,9 @@ static int appIconSize_(void) { | |||
824 | return lineHeight_Text(uiContent_FontId); | 827 | return lineHeight_Text(uiContent_FontId); |
825 | } | 828 | } |
826 | 829 | ||
827 | void updateMetrics_Root(iWidget *d) { | 830 | void updateMetrics_Root(iRoot *d) { |
828 | /* Custom frame. */ | 831 | /* Custom frame. */ |
829 | iWidget *winBar = findChild_Widget(d, "winbar"); | 832 | iWidget *winBar = findChild_Widget(d->widget, "winbar"); |
830 | if (winBar) { | 833 | if (winBar) { |
831 | iWidget *appIcon = findChild_Widget(winBar, "winbar.icon"); | 834 | iWidget *appIcon = findChild_Widget(winBar, "winbar.icon"); |
832 | iWidget *appTitle = findChild_Widget(winBar, "winbar.title"); | 835 | iWidget *appTitle = findChild_Widget(winBar, "winbar.title"); |
@@ -839,9 +842,9 @@ void updateMetrics_Root(iWidget *d) { | |||
839 | setFixedSize_Widget(appClose, appMin->rect.size); | 842 | setFixedSize_Widget(appClose, appMin->rect.size); |
840 | setFixedSize_Widget(appIcon, init_I2(appIconSize_(), appMin->rect.size.y)); | 843 | setFixedSize_Widget(appIcon, init_I2(appIconSize_(), appMin->rect.size.y)); |
841 | } | 844 | } |
842 | iWidget *navBar = findChild_Widget(d, "navbar"); | 845 | iWidget *navBar = findChild_Widget(d->widget, "navbar"); |
843 | iWidget *lock = findChild_Widget(navBar, "navbar.lock"); | 846 | iWidget *lock = findChild_Widget(navBar, "navbar.lock"); |
844 | iWidget *url = findChild_Widget(d, "url"); | 847 | iWidget *url = findChild_Widget(d->widget, "url"); |
845 | iWidget *rightEmbed = findChild_Widget(navBar, "url.rightembed"); | 848 | iWidget *rightEmbed = findChild_Widget(navBar, "url.rightembed"); |
846 | iWidget *embedPad = findChild_Widget(navBar, "url.embedpad"); | 849 | iWidget *embedPad = findChild_Widget(navBar, "url.embedpad"); |
847 | setPadding_Widget(as_Widget(url), 0, gap_UI, 0, gap_UI); | 850 | setPadding_Widget(as_Widget(url), 0, gap_UI, 0, gap_UI); |
@@ -852,12 +855,12 @@ void updateMetrics_Root(iWidget *d) { | |||
852 | width_Widget(lock) * 0.75); | 855 | width_Widget(lock) * 0.75); |
853 | rightEmbed->rect.pos.y = gap_UI; | 856 | rightEmbed->rect.pos.y = gap_UI; |
854 | updatePadding_Root(d); | 857 | updatePadding_Root(d); |
855 | arrange_Widget(d); | 858 | arrange_Widget(d->widget); |
856 | postRefresh_App(); | 859 | postRefresh_App(); |
857 | } | 860 | } |
858 | 861 | ||
859 | iWidget *createUserInterface_Root(void) { | 862 | void createUserInterface_Root(iRoot *d) { |
860 | iWidget *root = new_Widget(); | 863 | iWidget *root = d->widget = new_Widget(); |
861 | setId_Widget(root, "root"); | 864 | setId_Widget(root, "root"); |
862 | /* Children of root cover the entire window. */ | 865 | /* Children of root cover the entire window. */ |
863 | setFlags_Widget( | 866 | setFlags_Widget( |
@@ -1180,7 +1183,7 @@ iWidget *createUserInterface_Root(void) { | |||
1180 | setId_Widget(menu, "toolbar.menu"); /* view menu */ | 1183 | setId_Widget(menu, "toolbar.menu"); /* view menu */ |
1181 | } | 1184 | } |
1182 | #endif | 1185 | #endif |
1183 | updatePadding_Root(root); | 1186 | updatePadding_Root(d); |
1184 | /* Global context menus. */ { | 1187 | /* Global context menus. */ { |
1185 | iWidget *tabsMenu = makeMenu_Widget( | 1188 | iWidget *tabsMenu = makeMenu_Widget( |
1186 | root, | 1189 | root, |
@@ -1226,14 +1229,13 @@ iWidget *createUserInterface_Root(void) { | |||
1226 | addAction_Widget(root, '4', rightSidebar_KeyModifier, "sidebar2.mode arg:3 toggle:1"); | 1229 | addAction_Widget(root, '4', rightSidebar_KeyModifier, "sidebar2.mode arg:3 toggle:1"); |
1227 | addAction_Widget(root, '5', rightSidebar_KeyModifier, "sidebar2.mode arg:4 toggle:1"); | 1230 | addAction_Widget(root, '5', rightSidebar_KeyModifier, "sidebar2.mode arg:4 toggle:1"); |
1228 | } | 1231 | } |
1229 | updateMetrics_Root(root); | 1232 | updateMetrics_Root(d); |
1230 | return root; | ||
1231 | } | 1233 | } |
1232 | 1234 | ||
1233 | void showToolbars_Root(iWidget *root, iBool show) { | 1235 | void showToolbars_Root(iRoot *d, iBool show) { |
1234 | /* The toolbar is only used on phone portrait layout. */ | 1236 | /* The toolbar is only used on phone portrait layout. */ |
1235 | if (isLandscape_App()) return; | 1237 | if (isLandscape_App()) return; |
1236 | iWidget *toolBar = findChild_Widget(root, "toolbar"); | 1238 | iWidget *toolBar = findChild_Widget(d->widget, "toolbar"); |
1237 | if (!toolBar) return; | 1239 | if (!toolBar) return; |
1238 | const int height = rootSize_Window(get_Window()).y - top_Rect(boundsWithoutVisualOffset_Widget(toolBar)); | 1240 | const int height = rootSize_Window(get_Window()).y - top_Rect(boundsWithoutVisualOffset_Widget(toolBar)); |
1239 | if (show && !isVisible_Widget(toolBar)) { | 1241 | if (show && !isVisible_Widget(toolBar)) { |
diff --git a/src/ui/root.h b/src/ui/root.h index fcb5b1b0..4b14b942 100644 --- a/src/ui/root.h +++ b/src/ui/root.h | |||
@@ -3,10 +3,10 @@ | |||
3 | #include "widget.h" | 3 | #include "widget.h" |
4 | #include <the_Foundation/ptrset.h> | 4 | #include <the_Foundation/ptrset.h> |
5 | 5 | ||
6 | iDeclareType(RootData) | 6 | iDeclareType(Root) |
7 | 7 | ||
8 | /* TODO: Rename to Root, include `iWidget *root` as well. */ | 8 | struct Impl_Root { |
9 | struct Impl_RootData { | 9 | iWidget * widget; |
10 | iWidget * hover; | 10 | iWidget * hover; |
11 | iWidget * mouseGrab; | 11 | iWidget * mouseGrab; |
12 | iWidget * focus; | 12 | iWidget * focus; |
@@ -14,18 +14,19 @@ struct Impl_RootData { | |||
14 | iPtrSet * pendingDestruction; | 14 | iPtrSet * pendingDestruction; |
15 | }; | 15 | }; |
16 | 16 | ||
17 | iDeclareTypeConstruction(Root) | ||
18 | |||
17 | /*----------------------------------------------------------------------------------------------*/ | 19 | /*----------------------------------------------------------------------------------------------*/ |
18 | 20 | ||
19 | iWidget * createUserInterface_Root (void); | 21 | void createUserInterface_Root (iRoot *); |
20 | 22 | ||
21 | void setCurrent_Root (iWidget *root, iRootData *rootData); | 23 | void setCurrent_Root (iRoot *); |
22 | iWidget * get_Root (void); | 24 | iRoot * get_Root (void); |
23 | iRootData * data_Root (void); | ||
24 | 25 | ||
25 | iPtrArray * onTop_RootData (void); | 26 | iPtrArray * onTop_Root (iRoot *); |
26 | void destroyPending_RootData (iRootData *); | 27 | void destroyPending_Root (iRoot *); |
27 | 28 | ||
28 | void updateMetrics_Root (iWidget *); | 29 | void updateMetrics_Root (iRoot *); |
29 | void updatePadding_Root (iWidget *); /* TODO: is part of metrics? */ | 30 | void updatePadding_Root (iRoot *); /* TODO: is part of metrics? */ |
30 | void dismissPortraitPhoneSidebars_Root (iWidget *); | 31 | void dismissPortraitPhoneSidebars_Root (iRoot *); |
31 | void showToolbars_Root (iWidget *, iBool show); | 32 | void showToolbars_Root (iRoot *, iBool show); |
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 683f6436..8d83eed6 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -1170,7 +1170,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1170 | else if (isCommand_Widget(w, ev, "ident.edit")) { | 1170 | else if (isCommand_Widget(w, ev, "ident.edit")) { |
1171 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); | 1171 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); |
1172 | if (ident) { | 1172 | if (ident) { |
1173 | makeValueInput_Widget(get_Window()->root, | 1173 | makeValueInput_Widget(get_Window()->root.widget, |
1174 | &ident->notes, | 1174 | &ident->notes, |
1175 | uiHeading_ColorEscape "${heading.ident.notes}", | 1175 | uiHeading_ColorEscape "${heading.ident.notes}", |
1176 | format_CStr(cstr_Lang("dlg.ident.notes"), cstr_String(name_GmIdentity(ident))), | 1176 | format_CStr(cstr_Lang("dlg.ident.notes"), cstr_String(name_GmIdentity(ident))), |
diff --git a/src/ui/touch.c b/src/ui/touch.c index 22f22f9b..75bbf765 100644 --- a/src/ui/touch.c +++ b/src/ui/touch.c | |||
@@ -161,7 +161,7 @@ static iBool clearWidgetMomentum_TouchState_(iTouchState *d, iWidget *widget) { | |||
161 | 161 | ||
162 | static void dispatchMotion_Touch_(iFloat3 pos, int buttonState) { | 162 | static void dispatchMotion_Touch_(iFloat3 pos, int buttonState) { |
163 | touchState_()->currentTouchPos = initF3_I2(pos); | 163 | touchState_()->currentTouchPos = initF3_I2(pos); |
164 | dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &(SDL_MouseMotionEvent){ | 164 | dispatchEvent_Widget(get_Window()->root.widget, (SDL_Event *) &(SDL_MouseMotionEvent){ |
165 | .type = SDL_MOUSEMOTION, | 165 | .type = SDL_MOUSEMOTION, |
166 | .timestamp = SDL_GetTicks(), | 166 | .timestamp = SDL_GetTicks(), |
167 | .which = SDL_TOUCH_MOUSEID, | 167 | .which = SDL_TOUCH_MOUSEID, |
@@ -185,12 +185,12 @@ static iBool dispatchClick_Touch_(const iTouch *d, int button) { | |||
185 | .x = x_F3(tapPos), | 185 | .x = x_F3(tapPos), |
186 | .y = y_F3(tapPos) | 186 | .y = y_F3(tapPos) |
187 | }; | 187 | }; |
188 | iBool wasUsed = dispatchEvent_Widget(window->root, (SDL_Event *) &btn); | 188 | iBool wasUsed = dispatchEvent_Widget(window->root.widget, (SDL_Event *) &btn); |
189 | /* Immediately released, too. */ | 189 | /* Immediately released, too. */ |
190 | btn.type = SDL_MOUSEBUTTONUP; | 190 | btn.type = SDL_MOUSEBUTTONUP; |
191 | btn.state = SDL_RELEASED; | 191 | btn.state = SDL_RELEASED; |
192 | btn.timestamp = SDL_GetTicks(); | 192 | btn.timestamp = SDL_GetTicks(); |
193 | dispatchEvent_Widget(window->root, (SDL_Event *) &btn); | 193 | dispatchEvent_Widget(window->root.widget, (SDL_Event *) &btn); |
194 | if (!wasUsed && button == SDL_BUTTON_RIGHT) { | 194 | if (!wasUsed && button == SDL_BUTTON_RIGHT) { |
195 | postContextClick_Window(window, &btn); | 195 | postContextClick_Window(window, &btn); |
196 | } | 196 | } |
@@ -199,7 +199,7 @@ static iBool dispatchClick_Touch_(const iTouch *d, int button) { | |||
199 | 199 | ||
200 | static void dispatchButtonDown_Touch_(iFloat3 pos) { | 200 | static void dispatchButtonDown_Touch_(iFloat3 pos) { |
201 | touchState_()->currentTouchPos = initF3_I2(pos); | 201 | touchState_()->currentTouchPos = initF3_I2(pos); |
202 | dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &(SDL_MouseButtonEvent){ | 202 | dispatchEvent_Widget(get_Window()->root.widget, (SDL_Event *) &(SDL_MouseButtonEvent){ |
203 | .type = SDL_MOUSEBUTTONDOWN, | 203 | .type = SDL_MOUSEBUTTONDOWN, |
204 | .timestamp = SDL_GetTicks(), | 204 | .timestamp = SDL_GetTicks(), |
205 | .clicks = 1, | 205 | .clicks = 1, |
@@ -213,7 +213,7 @@ static void dispatchButtonDown_Touch_(iFloat3 pos) { | |||
213 | 213 | ||
214 | static void dispatchButtonUp_Touch_(iFloat3 pos) { | 214 | static void dispatchButtonUp_Touch_(iFloat3 pos) { |
215 | touchState_()->currentTouchPos = initF3_I2(pos); | 215 | touchState_()->currentTouchPos = initF3_I2(pos); |
216 | dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &(SDL_MouseButtonEvent){ | 216 | dispatchEvent_Widget(get_Window()->root.widget, (SDL_Event *) &(SDL_MouseButtonEvent){ |
217 | .type = SDL_MOUSEBUTTONUP, | 217 | .type = SDL_MOUSEBUTTONUP, |
218 | .timestamp = SDL_GetTicks(), | 218 | .timestamp = SDL_GetTicks(), |
219 | .clicks = 1, | 219 | .clicks = 1, |
@@ -458,7 +458,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
458 | else if (x > rootSize.x - edgeWidth) { | 458 | else if (x > rootSize.x - edgeWidth) { |
459 | edge = right_TouchEdge; | 459 | edge = right_TouchEdge; |
460 | } | 460 | } |
461 | iWidget *aff = hitChild_Widget(window->root, init_I2(iRound(x), iRound(y_F3(pos)))); | 461 | iWidget *aff = hitChild_Widget(window->root.widget, init_I2(iRound(x), iRound(y_F3(pos)))); |
462 | if (edge == left_TouchEdge) { | 462 | if (edge == left_TouchEdge) { |
463 | dragging = findSlidePanel_Widget_(aff); | 463 | dragging = findSlidePanel_Widget_(aff); |
464 | if (dragging) { | 464 | if (dragging) { |
diff --git a/src/ui/util.c b/src/ui/util.c index b80f7650..6b9a43d9 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -635,7 +635,7 @@ static iBool menuHandler_(iWidget *menu, const char *cmd) { | |||
635 | } | 635 | } |
636 | if ((equal_Command(cmd, "mouse.clicked") || equal_Command(cmd, "mouse.missed")) && | 636 | if ((equal_Command(cmd, "mouse.clicked") || equal_Command(cmd, "mouse.missed")) && |
637 | arg_Command(cmd)) { | 637 | arg_Command(cmd)) { |
638 | if (hitChild_Widget(get_Window()->root, coord_Command(cmd)) == parentMenuButton_(menu)) { | 638 | if (hitChild_Widget(get_Window()->root.widget, coord_Command(cmd)) == parentMenuButton_(menu)) { |
639 | return iFalse; | 639 | return iFalse; |
640 | } | 640 | } |
641 | /* Dismiss open menus when clicking outside them. */ | 641 | /* Dismiss open menus when clicking outside them. */ |
@@ -1366,7 +1366,7 @@ void finalizeSheet_Widget(iWidget *sheet) { | |||
1366 | easier to create phone versions of each dialog, but at least this works with any | 1366 | easier to create phone versions of each dialog, but at least this works with any |
1367 | future changes to the UI (..."works"). At least this way it is possible to enforce | 1367 | future changes to the UI (..."works"). At least this way it is possible to enforce |
1368 | a consistent styling. */ | 1368 | a consistent styling. */ |
1369 | if (deviceType_App() == phone_AppDeviceType && parent_Widget(sheet) == get_Window()->root) { | 1369 | if (deviceType_App() == phone_AppDeviceType && parent_Widget(sheet) == get_Window()->root.widget) { |
1370 | if (~flags_Widget(sheet) & keepOnTop_WidgetFlag) { | 1370 | if (~flags_Widget(sheet) & keepOnTop_WidgetFlag) { |
1371 | /* Already finalized. */ | 1371 | /* Already finalized. */ |
1372 | arrange_Widget(sheet); | 1372 | arrange_Widget(sheet); |
@@ -1573,7 +1573,7 @@ void finalizeSheet_Widget(iWidget *sheet) { | |||
1573 | destroy_Widget(pageContent); | 1573 | destroy_Widget(pageContent); |
1574 | setFlags_Widget(owner, drawBackgroundToBottom_WidgetFlag, iTrue); | 1574 | setFlags_Widget(owner, drawBackgroundToBottom_WidgetFlag, iTrue); |
1575 | } | 1575 | } |
1576 | destroyPending_RootData(data_Root()); | 1576 | destroyPending_Root(get_Root()); |
1577 | /* Additional elements for preferences. */ | 1577 | /* Additional elements for preferences. */ |
1578 | if (isPrefs) { | 1578 | if (isPrefs) { |
1579 | addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(defaultBig_FontId)))); | 1579 | addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(defaultBig_FontId)))); |
@@ -1966,7 +1966,7 @@ iWidget *makeQuestion_Widget(const char *title, const char *msg, | |||
1966 | } | 1966 | } |
1967 | addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); | 1967 | addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); |
1968 | addChild_Widget(dlg, iClob(makeDialogButtons_Widget(items, numItems))); | 1968 | addChild_Widget(dlg, iClob(makeDialogButtons_Widget(items, numItems))); |
1969 | addChild_Widget(get_Window()->root, iClob(dlg)); | 1969 | addChild_Widget(get_Window()->root.widget, iClob(dlg)); |
1970 | arrange_Widget(dlg); /* BUG: This extra arrange shouldn't be needed but the dialog won't | 1970 | arrange_Widget(dlg); /* BUG: This extra arrange shouldn't be needed but the dialog won't |
1971 | be arranged correctly unless it's here. */ | 1971 | be arranged correctly unless it's here. */ |
1972 | finalizeSheet_Widget(dlg); | 1972 | finalizeSheet_Widget(dlg); |
@@ -2412,7 +2412,7 @@ iWidget *makePreferences_Widget(void) { | |||
2412 | addChild_Widget(dlg, | 2412 | addChild_Widget(dlg, |
2413 | iClob(makeDialogButtons_Widget( | 2413 | iClob(makeDialogButtons_Widget( |
2414 | (iMenuItem[]){ { "${dismiss}", SDLK_ESCAPE, 0, "prefs.dismiss" } }, 1))); | 2414 | (iMenuItem[]){ { "${dismiss}", SDLK_ESCAPE, 0, "prefs.dismiss" } }, 1))); |
2415 | addChild_Widget(get_Window()->root, iClob(dlg)); | 2415 | addChild_Widget(get_Window()->root.widget, iClob(dlg)); |
2416 | finalizeSheet_Widget(dlg); | 2416 | finalizeSheet_Widget(dlg); |
2417 | //printTree_Widget(dlg); | 2417 | //printTree_Widget(dlg); |
2418 | return dlg; | 2418 | return dlg; |
@@ -2445,7 +2445,7 @@ iWidget *makeBookmarkEditor_Widget(void) { | |||
2445 | KMOD_PRIMARY, | 2445 | KMOD_PRIMARY, |
2446 | "bmed.accept" } }, | 2446 | "bmed.accept" } }, |
2447 | 2))); | 2447 | 2))); |
2448 | addChild_Widget(get_Window()->root, iClob(dlg)); | 2448 | addChild_Widget(get_Window()->root.widget, iClob(dlg)); |
2449 | finalizeSheet_Widget(dlg); | 2449 | finalizeSheet_Widget(dlg); |
2450 | return dlg; | 2450 | return dlg; |
2451 | } | 2451 | } |
@@ -2578,7 +2578,7 @@ iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) { | |||
2578 | setId_Widget(child_Widget(buttons, childCount_Widget(buttons) - 1), "feedcfg.save"); | 2578 | setId_Widget(child_Widget(buttons, childCount_Widget(buttons) - 1), "feedcfg.save"); |
2579 | arrange_Widget(dlg); | 2579 | arrange_Widget(dlg); |
2580 | as_Widget(input)->rect.size.x = 100 * gap_UI - headings->rect.size.x; | 2580 | as_Widget(input)->rect.size.x = 100 * gap_UI - headings->rect.size.x; |
2581 | addChild_Widget(get_Window()->root, iClob(dlg)); | 2581 | addChild_Widget(get_Window()->root.widget, iClob(dlg)); |
2582 | finalizeSheet_Widget(dlg); | 2582 | finalizeSheet_Widget(dlg); |
2583 | /* Initialize. */ { | 2583 | /* Initialize. */ { |
2584 | const iBookmark *bm = bookmarkId ? get_Bookmarks(bookmarks_App(), bookmarkId) : NULL; | 2584 | const iBookmark *bm = bookmarkId ? get_Bookmarks(bookmarks_App(), bookmarkId) : NULL; |
@@ -2654,7 +2654,7 @@ iWidget *makeIdentityCreation_Widget(void) { | |||
2654 | KMOD_PRIMARY, | 2654 | KMOD_PRIMARY, |
2655 | "ident.accept" } }, | 2655 | "ident.accept" } }, |
2656 | 2))); | 2656 | 2))); |
2657 | addChild_Widget(get_Window()->root, iClob(dlg)); | 2657 | addChild_Widget(get_Window()->root.widget, iClob(dlg)); |
2658 | finalizeSheet_Widget(dlg); | 2658 | finalizeSheet_Widget(dlg); |
2659 | return dlg; | 2659 | return dlg; |
2660 | } | 2660 | } |
diff --git a/src/ui/widget.c b/src/ui/widget.c index b3f7b27f..47522dbe 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -81,7 +81,7 @@ void deinit_Widget(iWidget *d) { | |||
81 | //#endif | 81 | //#endif |
82 | deinit_String(&d->id); | 82 | deinit_String(&d->id); |
83 | if (d->flags & keepOnTop_WidgetFlag) { | 83 | if (d->flags & keepOnTop_WidgetFlag) { |
84 | removeAll_PtrArray(onTop_RootData(), d); | 84 | removeAll_PtrArray(onTop_Root(get_Root()), d); |
85 | } | 85 | } |
86 | if (d->flags & visualOffset_WidgetFlag) { | 86 | if (d->flags & visualOffset_WidgetFlag) { |
87 | removeTicker_App(visualOffsetAnimation_Widget_, d); | 87 | removeTicker_App(visualOffsetAnimation_Widget_, d); |
@@ -95,10 +95,10 @@ static void aboutToBeDestroyed_Widget_(iWidget *d) { | |||
95 | return; | 95 | return; |
96 | } | 96 | } |
97 | if (flags_Widget(d) & keepOnTop_WidgetFlag) { | 97 | if (flags_Widget(d) & keepOnTop_WidgetFlag) { |
98 | removeOne_PtrArray(onTop_RootData(), d); | 98 | removeOne_PtrArray(onTop_Root(get_Root()), d); |
99 | } | 99 | } |
100 | if (isHover_Widget(d)) { | 100 | if (isHover_Widget(d)) { |
101 | data_Root()->hover = NULL; | 101 | get_Root()->hover = NULL; |
102 | } | 102 | } |
103 | iForEach(ObjectList, i, d->children) { | 103 | iForEach(ObjectList, i, d->children) { |
104 | aboutToBeDestroyed_Widget_(as_Widget(i.object)); | 104 | aboutToBeDestroyed_Widget_(as_Widget(i.object)); |
@@ -111,10 +111,11 @@ void destroy_Widget(iWidget *d) { | |||
111 | postRefresh_App(); | 111 | postRefresh_App(); |
112 | } | 112 | } |
113 | aboutToBeDestroyed_Widget_(d); | 113 | aboutToBeDestroyed_Widget_(d); |
114 | if (!data_Root()->pendingDestruction) { | 114 | iRoot *root = get_Root(); |
115 | data_Root()->pendingDestruction = new_PtrSet(); | 115 | if (!root->pendingDestruction) { |
116 | root->pendingDestruction = new_PtrSet(); | ||
116 | } | 117 | } |
117 | insert_PtrSet(data_Root()->pendingDestruction, d); | 118 | insert_PtrSet(root->pendingDestruction, d); |
118 | } | 119 | } |
119 | } | 120 | } |
120 | 121 | ||
@@ -138,7 +139,7 @@ void setFlags_Widget(iWidget *d, int64_t flags, iBool set) { | |||
138 | } | 139 | } |
139 | iChangeFlags(d->flags, flags, set); | 140 | iChangeFlags(d->flags, flags, set); |
140 | if (flags & keepOnTop_WidgetFlag) { | 141 | if (flags & keepOnTop_WidgetFlag) { |
141 | iPtrArray *onTop = onTop_RootData(); | 142 | iPtrArray *onTop = onTop_Root(get_Root()); |
142 | if (set) { | 143 | if (set) { |
143 | iAssert(indexOf_PtrArray(onTop, d) == iInvalidPos); | 144 | iAssert(indexOf_PtrArray(onTop, d) == iInvalidPos); |
144 | pushBack_PtrArray(onTop, d); | 145 | pushBack_PtrArray(onTop, d); |
@@ -186,7 +187,7 @@ void showCollapsed_Widget(iWidget *d, iBool show) { | |||
186 | if ((isVisible && !show) || (!isVisible && show)) { | 187 | if ((isVisible && !show) || (!isVisible && show)) { |
187 | setFlags_Widget(d, hidden_WidgetFlag, !show); | 188 | setFlags_Widget(d, hidden_WidgetFlag, !show); |
188 | /* The entire UI may be affected, if parents are resized due to the (un)collapsing. */ | 189 | /* The entire UI may be affected, if parents are resized due to the (un)collapsing. */ |
189 | arrange_Widget(get_Window()->root); | 190 | arrange_Widget(get_Window()->root.widget); |
190 | postRefresh_App(); | 191 | postRefresh_App(); |
191 | } | 192 | } |
192 | } | 193 | } |
@@ -733,7 +734,7 @@ static iBool filterEvent_Widget_(const iWidget *d, const SDL_Event *ev) { | |||
733 | } | 734 | } |
734 | 735 | ||
735 | void unhover_Widget(void) { | 736 | void unhover_Widget(void) { |
736 | data_Root()->hover = NULL; | 737 | get_Root()->hover = NULL; |
737 | } | 738 | } |
738 | 739 | ||
739 | iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { | 740 | iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { |
@@ -743,14 +744,14 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { | |||
743 | /* Hover widget may change. */ | 744 | /* Hover widget may change. */ |
744 | setHover_Widget(NULL); | 745 | setHover_Widget(NULL); |
745 | } | 746 | } |
746 | if (data_Root()->focus && isKeyboardEvent_(ev)) { | 747 | if (get_Root()->focus && isKeyboardEvent_(ev)) { |
747 | /* Root dispatches keyboard events directly to the focused widget. */ | 748 | /* Root dispatches keyboard events directly to the focused widget. */ |
748 | if (dispatchEvent_Widget(data_Root()->focus, ev)) { | 749 | if (dispatchEvent_Widget(get_Root()->focus, ev)) { |
749 | return iTrue; | 750 | return iTrue; |
750 | } | 751 | } |
751 | } | 752 | } |
752 | /* Root offers events first to widgets on top. */ | 753 | /* Root offers events first to widgets on top. */ |
753 | iReverseForEach(PtrArray, i, data_Root()->onTop) { | 754 | iReverseForEach(PtrArray, i, get_Root()->onTop) { |
754 | iWidget *widget = *i.value; | 755 | iWidget *widget = *i.value; |
755 | if (isVisible_Widget(widget) && dispatchEvent_Widget(widget, ev)) { | 756 | if (isVisible_Widget(widget) && dispatchEvent_Widget(widget, ev)) { |
756 | #if 0 | 757 | #if 0 |
@@ -774,7 +775,7 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { | |||
774 | } | 775 | } |
775 | } | 776 | } |
776 | else if (ev->type == SDL_MOUSEMOTION && | 777 | else if (ev->type == SDL_MOUSEMOTION && |
777 | (!data_Root()->hover || hasParent_Widget(d, data_Root()->hover)) && | 778 | (!get_Root()->hover || hasParent_Widget(d, get_Root()->hover)) && |
778 | flags_Widget(d) & hover_WidgetFlag && ~flags_Widget(d) & hidden_WidgetFlag && | 779 | flags_Widget(d) & hover_WidgetFlag && ~flags_Widget(d) & hidden_WidgetFlag && |
779 | ~flags_Widget(d) & disabled_WidgetFlag) { | 780 | ~flags_Widget(d) & disabled_WidgetFlag) { |
780 | if (contains_Widget(d, init_I2(ev->motion.x, ev->motion.y))) { | 781 | if (contains_Widget(d, init_I2(ev->motion.x, ev->motion.y))) { |
@@ -792,7 +793,7 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { | |||
792 | handle the events first. */ | 793 | handle the events first. */ |
793 | iReverseForEach(ObjectList, i, d->children) { | 794 | iReverseForEach(ObjectList, i, d->children) { |
794 | iWidget *child = as_Widget(i.object); | 795 | iWidget *child = as_Widget(i.object); |
795 | if (child == data_Root()->focus && isKeyboardEvent_(ev)) { | 796 | if (child == get_Root()->focus && isKeyboardEvent_(ev)) { |
796 | continue; /* Already dispatched. */ | 797 | continue; /* Already dispatched. */ |
797 | } | 798 | } |
798 | if (isVisible_Widget(child) && child->flags & keepOnTop_WidgetFlag) { | 799 | if (isVisible_Widget(child) && child->flags & keepOnTop_WidgetFlag) { |
@@ -1081,7 +1082,7 @@ void drawChildren_Widget(const iWidget *d) { | |||
1081 | } | 1082 | } |
1082 | /* Root draws the on-top widgets on top of everything else. */ | 1083 | /* Root draws the on-top widgets on top of everything else. */ |
1083 | if (!d->parent) { | 1084 | if (!d->parent) { |
1084 | iConstForEach(PtrArray, i, onTop_RootData()) { | 1085 | iConstForEach(PtrArray, i, onTop_Root(get_Root())) { |
1085 | const iWidget *top = *i.value; | 1086 | const iWidget *top = *i.value; |
1086 | draw_Widget(top); | 1087 | draw_Widget(top); |
1087 | } | 1088 | } |
@@ -1198,7 +1199,7 @@ iAny *hitChild_Widget(const iWidget *d, iInt2 coord) { | |||
1198 | } | 1199 | } |
1199 | /* Check for on-top widgets first. */ | 1200 | /* Check for on-top widgets first. */ |
1200 | if (!d->parent) { | 1201 | if (!d->parent) { |
1201 | iReverseForEach(PtrArray, i, onTop_RootData()) { | 1202 | iReverseForEach(PtrArray, i, onTop_Root(get_Root())) { |
1202 | iWidget *child = i.ptr; | 1203 | iWidget *child = i.ptr; |
1203 | // printf("ontop: %s (%s) hidden:%d hittable:%d\n", cstr_String(id_Widget(child)), | 1204 | // printf("ontop: %s (%s) hidden:%d hittable:%d\n", cstr_String(id_Widget(child)), |
1204 | // class_Widget(child)->name, | 1205 | // class_Widget(child)->name, |
@@ -1286,12 +1287,12 @@ iBool isDisabled_Widget(const iAnyObject *d) { | |||
1286 | 1287 | ||
1287 | iBool isFocused_Widget(const iAnyObject *d) { | 1288 | iBool isFocused_Widget(const iAnyObject *d) { |
1288 | iAssert(isInstance_Object(d, &Class_Widget)); | 1289 | iAssert(isInstance_Object(d, &Class_Widget)); |
1289 | return data_Root()->focus == d; | 1290 | return get_Root()->focus == d; |
1290 | } | 1291 | } |
1291 | 1292 | ||
1292 | iBool isHover_Widget(const iAnyObject *d) { | 1293 | iBool isHover_Widget(const iAnyObject *d) { |
1293 | iAssert(isInstance_Object(d, &Class_Widget)); | 1294 | iAssert(isInstance_Object(d, &Class_Widget)); |
1294 | return data_Root()->hover == d; | 1295 | return get_Root()->hover == d; |
1295 | } | 1296 | } |
1296 | 1297 | ||
1297 | iBool isSelected_Widget(const iAnyObject *d) { | 1298 | iBool isSelected_Widget(const iAnyObject *d) { |
@@ -1337,12 +1338,12 @@ iBool isAffectedByVisualOffset_Widget(const iWidget *d) { | |||
1337 | } | 1338 | } |
1338 | 1339 | ||
1339 | void setFocus_Widget(iWidget *d) { | 1340 | void setFocus_Widget(iWidget *d) { |
1340 | if (data_Root()->focus != d) { | 1341 | if (get_Root()->focus != d) { |
1341 | if (data_Root()->focus) { | 1342 | if (get_Root()->focus) { |
1342 | iAssert(!contains_PtrSet(data_Root()->pendingDestruction, data_Root()->focus)); | 1343 | iAssert(!contains_PtrSet(get_Root()->pendingDestruction, get_Root()->focus)); |
1343 | postCommand_Widget(data_Root()->focus, "focus.lost"); | 1344 | postCommand_Widget(get_Root()->focus, "focus.lost"); |
1344 | } | 1345 | } |
1345 | data_Root()->focus = d; | 1346 | get_Root()->focus = d; |
1346 | if (d) { | 1347 | if (d) { |
1347 | iAssert(flags_Widget(d) & focusable_WidgetFlag); | 1348 | iAssert(flags_Widget(d) & focusable_WidgetFlag); |
1348 | postCommand_Widget(d, "focus.gained"); | 1349 | postCommand_Widget(d, "focus.gained"); |
@@ -1351,15 +1352,15 @@ void setFocus_Widget(iWidget *d) { | |||
1351 | } | 1352 | } |
1352 | 1353 | ||
1353 | iWidget *focus_Widget(void) { | 1354 | iWidget *focus_Widget(void) { |
1354 | return data_Root()->focus; | 1355 | return get_Root()->focus; |
1355 | } | 1356 | } |
1356 | 1357 | ||
1357 | void setHover_Widget(iWidget *d) { | 1358 | void setHover_Widget(iWidget *d) { |
1358 | data_Root()->hover = d; | 1359 | get_Root()->hover = d; |
1359 | } | 1360 | } |
1360 | 1361 | ||
1361 | iWidget *hover_Widget(void) { | 1362 | iWidget *hover_Widget(void) { |
1362 | return data_Root()->hover; | 1363 | return get_Root()->hover; |
1363 | } | 1364 | } |
1364 | 1365 | ||
1365 | static const iWidget *findFocusable_Widget_(const iWidget *d, const iWidget *startFrom, | 1366 | static const iWidget *findFocusable_Widget_(const iWidget *d, const iWidget *startFrom, |
@@ -1403,7 +1404,7 @@ static const iWidget *findFocusRoot_Widget_(const iWidget *d) { | |||
1403 | } | 1404 | } |
1404 | 1405 | ||
1405 | iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusDir) { | 1406 | iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusDir) { |
1406 | const iWidget *root = findFocusRoot_Widget_(get_Window()->root); | 1407 | const iWidget *root = findFocusRoot_Widget_(get_Window()->root.widget); |
1407 | iAssert(root != NULL); | 1408 | iAssert(root != NULL); |
1408 | iBool getNext = (startFrom ? iFalse : iTrue); | 1409 | iBool getNext = (startFrom ? iFalse : iTrue); |
1409 | const iWidget *found = findFocusable_Widget_(root, startFrom, &getNext, focusDir); | 1410 | const iWidget *found = findFocusable_Widget_(root, startFrom, &getNext, focusDir); |
@@ -1415,14 +1416,14 @@ iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusD | |||
1415 | } | 1416 | } |
1416 | 1417 | ||
1417 | void setMouseGrab_Widget(iWidget *d) { | 1418 | void setMouseGrab_Widget(iWidget *d) { |
1418 | if (data_Root()->mouseGrab != d) { | 1419 | if (get_Root()->mouseGrab != d) { |
1419 | data_Root()->mouseGrab = d; | 1420 | get_Root()->mouseGrab = d; |
1420 | SDL_CaptureMouse(d != NULL); | 1421 | SDL_CaptureMouse(d != NULL); |
1421 | } | 1422 | } |
1422 | } | 1423 | } |
1423 | 1424 | ||
1424 | iWidget *mouseGrab_Widget(void) { | 1425 | iWidget *mouseGrab_Widget(void) { |
1425 | return data_Root()->mouseGrab; | 1426 | return get_Root()->mouseGrab; |
1426 | } | 1427 | } |
1427 | 1428 | ||
1428 | void postCommand_Widget(const iAnyObject *d, const char *cmd, ...) { | 1429 | void postCommand_Widget(const iAnyObject *d, const char *cmd, ...) { |
@@ -1456,7 +1457,7 @@ void refresh_Widget(const iAnyObject *d) { | |||
1456 | } | 1457 | } |
1457 | 1458 | ||
1458 | void raise_Widget(iWidget *d) { | 1459 | void raise_Widget(iWidget *d) { |
1459 | iPtrArray *onTop = onTop_RootData(); | 1460 | iPtrArray *onTop = onTop_Root(get_Root()); |
1460 | if (d->flags & keepOnTop_WidgetFlag) { | 1461 | if (d->flags & keepOnTop_WidgetFlag) { |
1461 | iAssert(indexOf_PtrArray(onTop, d) != iInvalidPos); | 1462 | iAssert(indexOf_PtrArray(onTop, d) != iInvalidPos); |
1462 | removeOne_PtrArray(onTop, d); | 1463 | removeOne_PtrArray(onTop, d); |
diff --git a/src/ui/window.c b/src/ui/window.c index ea2a4ec0..627f16b1 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -165,23 +165,21 @@ static void setupUserInterface_Window(iWindow *d) { | |||
165 | #if defined (iPlatformAppleDesktop) | 165 | #if defined (iPlatformAppleDesktop) |
166 | insertMacMenus_(); | 166 | insertMacMenus_(); |
167 | #endif | 167 | #endif |
168 | static iRootData rootData_; | 168 | setCurrent_Root(&d->root); |
169 | setCurrent_Root(NULL, &rootData_); | 169 | createUserInterface_Root(&d->root); |
170 | d->root = createUserInterface_Root(); | ||
171 | setCurrent_Root(d->root, &rootData_); | ||
172 | } | 170 | } |
173 | 171 | ||
174 | static void updateRootSize_Window_(iWindow *d, iBool notifyAlways) { | 172 | static void updateRootSize_Window_(iWindow *d, iBool notifyAlways) { |
175 | iInt2 *size = &d->root->rect.size; | 173 | iInt2 *size = &d->root.widget->rect.size; |
176 | const iInt2 oldSize = *size; | 174 | const iInt2 oldSize = *size; |
177 | SDL_GetRendererOutputSize(d->render, &size->x, &size->y); | 175 | SDL_GetRendererOutputSize(d->render, &size->x, &size->y); |
178 | size->y -= d->keyboardHeight; | 176 | size->y -= d->keyboardHeight; |
179 | d->root->minSize = *size; | 177 | d->root.widget->minSize = *size; |
180 | if (notifyAlways || !isEqual_I2(oldSize, *size)) { | 178 | if (notifyAlways || !isEqual_I2(oldSize, *size)) { |
181 | updatePadding_Root(d->root); | 179 | updatePadding_Root(&d->root); |
182 | const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x); | 180 | const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x); |
183 | const iBool isVert = (d->place.lastNotifiedSize.y != size->y); | 181 | const iBool isVert = (d->place.lastNotifiedSize.y != size->y); |
184 | arrange_Widget(d->root); | 182 | arrange_Widget(d->root.widget); |
185 | postCommandf_App("window.resized width:%d height:%d horiz:%d vert:%d", | 183 | postCommandf_App("window.resized width:%d height:%d horiz:%d vert:%d", |
186 | size->x, | 184 | size->x, |
187 | size->y, | 185 | size->y, |
@@ -196,8 +194,8 @@ static void updateRootSize_Window_(iWindow *d, iBool notifyAlways) { | |||
196 | void drawWhileResizing_Window(iWindow *d, int w, int h) { | 194 | void drawWhileResizing_Window(iWindow *d, int w, int h) { |
197 | /* This is called while a window resize is in progress, so we can be pretty confident | 195 | /* This is called while a window resize is in progress, so we can be pretty confident |
198 | the size has actually changed. */ | 196 | the size has actually changed. */ |
199 | d->root->rect.size = coord_Window(d, w, h); | 197 | d->root.widget->rect.size = coord_Window(d, w, h); |
200 | arrange_Widget(d->root); | 198 | arrange_Widget(d->root.widget); |
201 | draw_Window(d); | 199 | draw_Window(d); |
202 | } | 200 | } |
203 | 201 | ||
@@ -347,7 +345,7 @@ static SDL_Surface *loadImage_(const iBlock *data, int resized) { | |||
347 | void init_Window(iWindow *d, iRect rect) { | 345 | void init_Window(iWindow *d, iRect rect) { |
348 | theWindow_ = d; | 346 | theWindow_ = d; |
349 | d->win = NULL; | 347 | d->win = NULL; |
350 | d->root = NULL; | 348 | init_Root(&d->root); |
351 | iZap(d->cursors); | 349 | iZap(d->cursors); |
352 | d->place.initialPos = rect.pos; | 350 | d->place.initialPos = rect.pos; |
353 | d->place.normalRect = rect; | 351 | d->place.normalRect = rect; |
@@ -460,7 +458,7 @@ void deinit_Window(iWindow *d) { | |||
460 | SDL_FreeCursor(d->cursors[i]); | 458 | SDL_FreeCursor(d->cursors[i]); |
461 | } | 459 | } |
462 | } | 460 | } |
463 | iReleasePtr(&d->root); | 461 | deinit_Root(&d->root); |
464 | deinit_Text(); | 462 | deinit_Text(); |
465 | SDL_DestroyRenderer(d->render); | 463 | SDL_DestroyRenderer(d->render); |
466 | SDL_DestroyWindow(d->win); | 464 | SDL_DestroyWindow(d->win); |
@@ -636,7 +634,7 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
636 | return iTrue; | 634 | return iTrue; |
637 | } | 635 | } |
638 | case SDL_WINDOWEVENT_RESIZED: | 636 | case SDL_WINDOWEVENT_RESIZED: |
639 | updatePadding_Root(d->root); | 637 | updatePadding_Root(&d->root); |
640 | if (d->isMinimized) { | 638 | if (d->isMinimized) { |
641 | updateRootSize_Window_(d, iTrue); | 639 | updateRootSize_Window_(d, iTrue); |
642 | return iTrue; | 640 | return iTrue; |
@@ -768,7 +766,7 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
768 | event.button.x = pos.x; | 766 | event.button.x = pos.x; |
769 | event.button.y = pos.y; | 767 | event.button.y = pos.y; |
770 | } | 768 | } |
771 | iWidget *widget = d->root; | 769 | iWidget *widget = d->root.widget; |
772 | if (event.type == SDL_MOUSEMOTION || event.type == SDL_MOUSEWHEEL || | 770 | if (event.type == SDL_MOUSEMOTION || event.type == SDL_MOUSEWHEEL || |
773 | event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) { | 771 | event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) { |
774 | if (mouseGrab_Widget()) { | 772 | if (mouseGrab_Widget()) { |
@@ -796,7 +794,7 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
796 | } | 794 | } |
797 | } | 795 | } |
798 | if (isMetricsChange_UserEvent(&event)) { | 796 | if (isMetricsChange_UserEvent(&event)) { |
799 | updateMetrics_Root(d->root); | 797 | updateMetrics_Root(&d->root); |
800 | } | 798 | } |
801 | if (isCommand_UserEvent(&event, "lang.changed")) { | 799 | if (isCommand_UserEvent(&event, "lang.changed")) { |
802 | #if defined (iPlatformAppleDesktop) | 800 | #if defined (iPlatformAppleDesktop) |
@@ -805,8 +803,8 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
805 | insertMacMenus_(); | 803 | insertMacMenus_(); |
806 | #endif | 804 | #endif |
807 | invalidate_Window_(d); | 805 | invalidate_Window_(d); |
808 | updatePreferencesLayout_Widget(findChild_Widget(d->root, "prefs")); | 806 | updatePreferencesLayout_Widget(findChild_Widget(d->root.widget, "prefs")); |
809 | arrange_Widget(d->root); | 807 | arrange_Widget(d->root.widget); |
810 | //printTree_Widget(findChild_Widget(d->root, "prefs")); | 808 | //printTree_Widget(findChild_Widget(d->root, "prefs")); |
811 | } | 809 | } |
812 | if (oldHover != hover_Widget()) { | 810 | if (oldHover != hover_Widget()) { |
@@ -823,7 +821,7 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
823 | 821 | ||
824 | iBool postContextClick_Window(iWindow *d, const SDL_MouseButtonEvent *ev) { | 822 | iBool postContextClick_Window(iWindow *d, const SDL_MouseButtonEvent *ev) { |
825 | /* A context menu may still get triggered here. */ | 823 | /* A context menu may still get triggered here. */ |
826 | const iWidget *hit = hitChild_Widget(d->root, init_I2(ev->x, ev->y)); | 824 | const iWidget *hit = hitChild_Widget(d->root.widget, init_I2(ev->x, ev->y)); |
827 | while (hit && isEmpty_String(id_Widget(hit))) { | 825 | while (hit && isEmpty_String(id_Widget(hit))) { |
828 | hit = parent_Widget(hit); | 826 | hit = parent_Widget(hit); |
829 | } | 827 | } |
@@ -868,7 +866,7 @@ void draw_Window(iWindow *d) { | |||
868 | /* Draw widgets. */ | 866 | /* Draw widgets. */ |
869 | d->frameTime = SDL_GetTicks(); | 867 | d->frameTime = SDL_GetTicks(); |
870 | if (isExposed_Window(d)) { | 868 | if (isExposed_Window(d)) { |
871 | draw_Widget(d->root); | 869 | draw_Widget(d->root.widget); |
872 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 870 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) |
873 | /* App icon. */ | 871 | /* App icon. */ |
874 | const iWidget *appIcon = findChild_Widget(d->root, "winbar.icon"); | 872 | const iWidget *appIcon = findChild_Widget(d->root, "winbar.icon"); |
@@ -907,7 +905,7 @@ void resize_Window(iWindow *d, int w, int h) { | |||
907 | 905 | ||
908 | void setTitle_Window(iWindow *d, const iString *title) { | 906 | void setTitle_Window(iWindow *d, const iString *title) { |
909 | SDL_SetWindowTitle(d->win, cstr_String(title)); | 907 | SDL_SetWindowTitle(d->win, cstr_String(title)); |
910 | iLabelWidget *bar = findChild_Widget(d->root, "winbar.title"); | 908 | iLabelWidget *bar = findChild_Widget(d->root.widget, "winbar.title"); |
911 | if (bar) { | 909 | if (bar) { |
912 | updateText_LabelWidget(bar, title); | 910 | updateText_LabelWidget(bar, title); |
913 | } | 911 | } |
@@ -942,7 +940,7 @@ uint32_t id_Window(const iWindow *d) { | |||
942 | } | 940 | } |
943 | 941 | ||
944 | iInt2 rootSize_Window(const iWindow *d) { | 942 | iInt2 rootSize_Window(const iWindow *d) { |
945 | return d && d->root ? d->root->rect.size : zero_I2(); | 943 | return d && d->root.widget ? d->root.widget->rect.size : zero_I2(); |
946 | } | 944 | } |
947 | 945 | ||
948 | iRect safeRootRect_Window(const iWindow *d) { | 946 | iRect safeRootRect_Window(const iWindow *d) { |
diff --git a/src/ui/window.h b/src/ui/window.h index 9d9a6aeb..f90bd863 100644 --- a/src/ui/window.h +++ b/src/ui/window.h | |||
@@ -22,7 +22,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
22 | 22 | ||
23 | #pragma once | 23 | #pragma once |
24 | 24 | ||
25 | #include "widget.h" | 25 | #include "root.h" |
26 | 26 | ||
27 | #include <the_Foundation/rect.h> | 27 | #include <the_Foundation/rect.h> |
28 | #include <SDL_events.h> | 28 | #include <SDL_events.h> |
@@ -66,8 +66,8 @@ struct Impl_Window { | |||
66 | iBool ignoreClick; | 66 | iBool ignoreClick; |
67 | uint32_t focusGainedAt; | 67 | uint32_t focusGainedAt; |
68 | SDL_Renderer *render; | 68 | SDL_Renderer *render; |
69 | iWidget * root; | 69 | iRoot root; /* root widget and UI state */ |
70 | float pixelRatio; /* conversion between points and pixels, e.g., coords, window size */ | 70 | float pixelRatio; /* conversion between points and pixels, e.g., coords, window size */ |
71 | float displayScale; /* DPI-based scaling factor of current display, affects uiScale only */ | 71 | float displayScale; /* DPI-based scaling factor of current display, affects uiScale only */ |
72 | float uiScale; | 72 | float uiScale; |
73 | uint32_t frameTime; | 73 | uint32_t frameTime; |