From 9a7aa34e63132edb5906914ff99b861e64ee9099 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 27 Apr 2021 11:59:28 +0300 Subject: Refactor: Added a proper Root object `Root` encapsulates the root widget and the associated UI state. --- src/app.c | 8 +++--- src/ui/paint.c | 4 +-- src/ui/root.c | 78 ++++++++++++++++++++++++++------------------------ src/ui/root.h | 27 ++++++++--------- src/ui/sidebarwidget.c | 2 +- src/ui/touch.c | 12 ++++---- src/ui/util.c | 16 +++++------ src/ui/widget.c | 63 ++++++++++++++++++++-------------------- src/ui/window.c | 40 ++++++++++++-------------- src/ui/window.h | 6 ++-- 10 files changed, 129 insertions(+), 127 deletions(-) (limited to 'src') diff --git a/src/app.c b/src/app.c index c4511dc7..cefb707d 100644 --- a/src/app.c +++ b/src/app.c @@ -1046,7 +1046,7 @@ void processEvents_App(enum iAppEventMode eventMode) { handleCommand_MacOS(command_UserEvent(&ev)); #endif if (isMetricsChange_UserEvent(&ev)) { - arrange_Widget(d->window->root); + arrange_Widget(d->window->root.widget); } if (!wasUsed) { /* No widget handled the command, so we'll do it. */ @@ -1131,7 +1131,7 @@ static int run_App_(iApp *d) { void refresh_App(void) { iApp *d = &app_; - destroyPending_RootData(data_Root()); + destroyPending_Root(&d->window->root); #if defined (LAGRANGE_ENABLE_IDLE_SLEEP) if (d->warmupFrames == 0 && d->isIdling) { return; @@ -1262,7 +1262,7 @@ void postCommandf_App(const char *command, ...) { iAny *findWidget_App(const char *id) { if (!*id) return NULL; - return findChild_Widget(app_.window->root, id); + return findChild_Widget(app_.window->root.widget, id); } void addTicker_App(iTickerFunc ticker, iAny *context) { @@ -2120,7 +2120,7 @@ iBool handleCommand_App(const char *cmd) { else if (equal_Command(cmd, "ident.import")) { iCertImportWidget *imp = new_CertImportWidget(); setPageContent_CertImportWidget(imp, sourceContent_DocumentWidget(document_App())); - addChild_Widget(d->window->root, iClob(imp)); + addChild_Widget(d->window->root.widget, iClob(imp)); finalizeSheet_Widget(as_Widget(imp)); postRefresh_App(); 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) { void drawRect_Paint(const iPaint *d, iRect rect, int color) { iInt2 br = bottomRight_Rect(rect); /* Keep the right/bottom edge visible in the window. */ - if (br.x == d->dst->root->rect.size.x) br.x--; - if (br.y == d->dst->root->rect.size.y) br.y--; + if (br.x == d->dst->root.widget->rect.size.x) br.x--; + if (br.y == d->dst->root.widget->rect.size.y) br.y--; const SDL_Point edges[] = { { left_Rect(rect), top_Rect(rect) }, { 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_[] = { static const int loadAnimIntervalMs_ = 133; static int loadAnimIndex_ = 0; -static iWidget * activeRoot_ = NULL; -static iRootData * activeRootData_ = NULL; +static iRoot * activeRoot_ = NULL; -void setCurrent_Root(iWidget *root, iRootData *rootData) { - activeRoot_ = root; - activeRootData_ = rootData; +iDefineTypeConstruction(Root) + +void init_Root(iRoot *d) { + iZap(*d); } -iWidget *get_Root(void) { - return activeRoot_; +void deinit_Root(iRoot *d) { + iReleasePtr(&d->widget); +} + +void setCurrent_Root(iRoot *root) { + activeRoot_ = root; } -iRootData *data_Root(void) { - return activeRootData_; +iRoot *get_Root(void) { + return activeRoot_; } -void destroyPending_RootData(iRootData *d) { +void destroyPending_Root(iRoot *d) { iForEach(PtrSet, i, d->pendingDestruction) { iWidget *widget = *i.value; if (!isFinished_Anim(&widget->visualOffset)) { @@ -265,12 +269,11 @@ void destroyPending_RootData(iRootData *d) { } } -iPtrArray *onTop_RootData(void) { - iAssert(activeRootData_); - if (!activeRootData_->onTop) { - activeRootData_->onTop = new_PtrArray(); +iPtrArray *onTop_Root(iRoot *d) { + if (!d->onTop) { + d->onTop = new_PtrArray(); } - return activeRootData_->onTop; + return d->onTop; } static iBool handleRootCommands_(iWidget *root, const char *cmd) { @@ -423,7 +426,7 @@ static uint32_t updateReloadAnimation_Window_(uint32_t interval, void *window) { static void setReloadLabel_Window_(iWindow *d, iBool animating) { const iBool isMobile = deviceType_App() != desktop_AppDeviceType; - iLabelWidget *label = findChild_Widget(d->root, "reload"); + iLabelWidget *label = findChild_Widget(d->root.widget, "reload"); updateTextCStr_LabelWidget(label, animating ? loadAnimationCStr_() : (isMobile ? pageMenuCStr_ : reloadCStr_)); if (isMobile) { @@ -444,13 +447,13 @@ static void checkLoadAnimation_Window_(iWindow *d) { setReloadLabel_Window_(d, isOngoing); } -void updatePadding_Root(iWidget *d) { +void updatePadding_Root(iRoot *d) { #if defined (iPlatformAppleMobile) - iWidget *toolBar = findChild_Widget(d, "toolbar"); + iWidget *toolBar = findChild_Widget(d->widget, "toolbar"); float left, top, right, bottom; safeAreaInsets_iOS(&left, &top, &right, &bottom); /* Respect the safe area insets. */ { - setPadding_Widget(findChild_Widget(d, "navdiv"), left, top, right, 0); + setPadding_Widget(findChild_Widget(d->widget, "navdiv"), left, top, right, 0); if (toolBar) { setPadding_Widget(toolBar, left, 0, right, bottom); } @@ -458,8 +461,8 @@ void updatePadding_Root(iWidget *d) { if (toolBar) { /* TODO: get this from toolBar height, but it's buggy for some reason */ const int sidebarBottomPad = isPortrait_App() ? 11 * gap_UI + bottom : 0; - setPadding_Widget(findChild_Widget(d, "sidebar"), 0, 0, 0, sidebarBottomPad); - setPadding_Widget(findChild_Widget(d, "sidebar2"), 0, 0, 0, sidebarBottomPad); + setPadding_Widget(findChild_Widget(d->widget, "sidebar"), 0, 0, 0, sidebarBottomPad); + setPadding_Widget(findChild_Widget(d->widget, "sidebar2"), 0, 0, 0, sidebarBottomPad); /* TODO: There seems to be unrelated layout glitch in the sidebar where its children are not arranged correctly until it's hidden and reshown. */ } @@ -469,10 +472,10 @@ void updatePadding_Root(iWidget *d) { #endif } -void dismissPortraitPhoneSidebars_Root(iWidget *root) { +void dismissPortraitPhoneSidebars_Root(iRoot *d) { if (deviceType_App() == phone_AppDeviceType && isPortrait_App()) { - iWidget *sidebar = findChild_Widget(root, "sidebar"); - iWidget *sidebar2 = findChild_Widget(root, "sidebar2"); + iWidget *sidebar = findChild_Widget(d->widget, "sidebar"); + iWidget *sidebar2 = findChild_Widget(d->widget, "sidebar2"); if (isVisible_Widget(sidebar)) { postCommand_App("sidebar.toggle"); setVisualOffset_Widget(sidebar, height_Widget(sidebar), 250, easeIn_AnimFlag); @@ -564,7 +567,7 @@ static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) { updateSize_LabelWidget(btn); } } - arrange_Widget(get_Window()->root); + arrange_Widget(get_Window()->root.widget); } /* Resize the URL input field. */ { iWidget *urlBar = findChild_Widget(navBar, "url"); @@ -716,7 +719,7 @@ static iBool handleSearchBarCommands_(iWidget *searchBar, const char *cmd) { if (pointer_Command(cmd) == findChild_Widget(searchBar, "find.input")) { if (!isVisible_Widget(searchBar)) { setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); - arrange_Widget(get_Window()->root); + arrange_Widget(get_Window()->root.widget); postRefresh_App(); } } @@ -824,9 +827,9 @@ static int appIconSize_(void) { return lineHeight_Text(uiContent_FontId); } -void updateMetrics_Root(iWidget *d) { +void updateMetrics_Root(iRoot *d) { /* Custom frame. */ - iWidget *winBar = findChild_Widget(d, "winbar"); + iWidget *winBar = findChild_Widget(d->widget, "winbar"); if (winBar) { iWidget *appIcon = findChild_Widget(winBar, "winbar.icon"); iWidget *appTitle = findChild_Widget(winBar, "winbar.title"); @@ -839,9 +842,9 @@ void updateMetrics_Root(iWidget *d) { setFixedSize_Widget(appClose, appMin->rect.size); setFixedSize_Widget(appIcon, init_I2(appIconSize_(), appMin->rect.size.y)); } - iWidget *navBar = findChild_Widget(d, "navbar"); + iWidget *navBar = findChild_Widget(d->widget, "navbar"); iWidget *lock = findChild_Widget(navBar, "navbar.lock"); - iWidget *url = findChild_Widget(d, "url"); + iWidget *url = findChild_Widget(d->widget, "url"); iWidget *rightEmbed = findChild_Widget(navBar, "url.rightembed"); iWidget *embedPad = findChild_Widget(navBar, "url.embedpad"); setPadding_Widget(as_Widget(url), 0, gap_UI, 0, gap_UI); @@ -852,12 +855,12 @@ void updateMetrics_Root(iWidget *d) { width_Widget(lock) * 0.75); rightEmbed->rect.pos.y = gap_UI; updatePadding_Root(d); - arrange_Widget(d); + arrange_Widget(d->widget); postRefresh_App(); } -iWidget *createUserInterface_Root(void) { - iWidget *root = new_Widget(); +void createUserInterface_Root(iRoot *d) { + iWidget *root = d->widget = new_Widget(); setId_Widget(root, "root"); /* Children of root cover the entire window. */ setFlags_Widget( @@ -1180,7 +1183,7 @@ iWidget *createUserInterface_Root(void) { setId_Widget(menu, "toolbar.menu"); /* view menu */ } #endif - updatePadding_Root(root); + updatePadding_Root(d); /* Global context menus. */ { iWidget *tabsMenu = makeMenu_Widget( root, @@ -1226,14 +1229,13 @@ iWidget *createUserInterface_Root(void) { addAction_Widget(root, '4', rightSidebar_KeyModifier, "sidebar2.mode arg:3 toggle:1"); addAction_Widget(root, '5', rightSidebar_KeyModifier, "sidebar2.mode arg:4 toggle:1"); } - updateMetrics_Root(root); - return root; + updateMetrics_Root(d); } -void showToolbars_Root(iWidget *root, iBool show) { +void showToolbars_Root(iRoot *d, iBool show) { /* The toolbar is only used on phone portrait layout. */ if (isLandscape_App()) return; - iWidget *toolBar = findChild_Widget(root, "toolbar"); + iWidget *toolBar = findChild_Widget(d->widget, "toolbar"); if (!toolBar) return; const int height = rootSize_Window(get_Window()).y - top_Rect(boundsWithoutVisualOffset_Widget(toolBar)); 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 @@ #include "widget.h" #include -iDeclareType(RootData) +iDeclareType(Root) -/* TODO: Rename to Root, include `iWidget *root` as well. */ -struct Impl_RootData { +struct Impl_Root { + iWidget * widget; iWidget * hover; iWidget * mouseGrab; iWidget * focus; @@ -14,18 +14,19 @@ struct Impl_RootData { iPtrSet * pendingDestruction; }; +iDeclareTypeConstruction(Root) + /*----------------------------------------------------------------------------------------------*/ -iWidget * createUserInterface_Root (void); +void createUserInterface_Root (iRoot *); -void setCurrent_Root (iWidget *root, iRootData *rootData); -iWidget * get_Root (void); -iRootData * data_Root (void); +void setCurrent_Root (iRoot *); +iRoot * get_Root (void); -iPtrArray * onTop_RootData (void); -void destroyPending_RootData (iRootData *); +iPtrArray * onTop_Root (iRoot *); +void destroyPending_Root (iRoot *); -void updateMetrics_Root (iWidget *); -void updatePadding_Root (iWidget *); /* TODO: is part of metrics? */ -void dismissPortraitPhoneSidebars_Root (iWidget *); -void showToolbars_Root (iWidget *, iBool show); +void updateMetrics_Root (iRoot *); +void updatePadding_Root (iRoot *); /* TODO: is part of metrics? */ +void dismissPortraitPhoneSidebars_Root (iRoot *); +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) else if (isCommand_Widget(w, ev, "ident.edit")) { const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); if (ident) { - makeValueInput_Widget(get_Window()->root, + makeValueInput_Widget(get_Window()->root.widget, &ident->notes, uiHeading_ColorEscape "${heading.ident.notes}", 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) { static void dispatchMotion_Touch_(iFloat3 pos, int buttonState) { touchState_()->currentTouchPos = initF3_I2(pos); - dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &(SDL_MouseMotionEvent){ + dispatchEvent_Widget(get_Window()->root.widget, (SDL_Event *) &(SDL_MouseMotionEvent){ .type = SDL_MOUSEMOTION, .timestamp = SDL_GetTicks(), .which = SDL_TOUCH_MOUSEID, @@ -185,12 +185,12 @@ static iBool dispatchClick_Touch_(const iTouch *d, int button) { .x = x_F3(tapPos), .y = y_F3(tapPos) }; - iBool wasUsed = dispatchEvent_Widget(window->root, (SDL_Event *) &btn); + iBool wasUsed = dispatchEvent_Widget(window->root.widget, (SDL_Event *) &btn); /* Immediately released, too. */ btn.type = SDL_MOUSEBUTTONUP; btn.state = SDL_RELEASED; btn.timestamp = SDL_GetTicks(); - dispatchEvent_Widget(window->root, (SDL_Event *) &btn); + dispatchEvent_Widget(window->root.widget, (SDL_Event *) &btn); if (!wasUsed && button == SDL_BUTTON_RIGHT) { postContextClick_Window(window, &btn); } @@ -199,7 +199,7 @@ static iBool dispatchClick_Touch_(const iTouch *d, int button) { static void dispatchButtonDown_Touch_(iFloat3 pos) { touchState_()->currentTouchPos = initF3_I2(pos); - dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &(SDL_MouseButtonEvent){ + dispatchEvent_Widget(get_Window()->root.widget, (SDL_Event *) &(SDL_MouseButtonEvent){ .type = SDL_MOUSEBUTTONDOWN, .timestamp = SDL_GetTicks(), .clicks = 1, @@ -213,7 +213,7 @@ static void dispatchButtonDown_Touch_(iFloat3 pos) { static void dispatchButtonUp_Touch_(iFloat3 pos) { touchState_()->currentTouchPos = initF3_I2(pos); - dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &(SDL_MouseButtonEvent){ + dispatchEvent_Widget(get_Window()->root.widget, (SDL_Event *) &(SDL_MouseButtonEvent){ .type = SDL_MOUSEBUTTONUP, .timestamp = SDL_GetTicks(), .clicks = 1, @@ -458,7 +458,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { else if (x > rootSize.x - edgeWidth) { edge = right_TouchEdge; } - iWidget *aff = hitChild_Widget(window->root, init_I2(iRound(x), iRound(y_F3(pos)))); + iWidget *aff = hitChild_Widget(window->root.widget, init_I2(iRound(x), iRound(y_F3(pos)))); if (edge == left_TouchEdge) { dragging = findSlidePanel_Widget_(aff); 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) { } if ((equal_Command(cmd, "mouse.clicked") || equal_Command(cmd, "mouse.missed")) && arg_Command(cmd)) { - if (hitChild_Widget(get_Window()->root, coord_Command(cmd)) == parentMenuButton_(menu)) { + if (hitChild_Widget(get_Window()->root.widget, coord_Command(cmd)) == parentMenuButton_(menu)) { return iFalse; } /* Dismiss open menus when clicking outside them. */ @@ -1366,7 +1366,7 @@ void finalizeSheet_Widget(iWidget *sheet) { easier to create phone versions of each dialog, but at least this works with any future changes to the UI (..."works"). At least this way it is possible to enforce a consistent styling. */ - if (deviceType_App() == phone_AppDeviceType && parent_Widget(sheet) == get_Window()->root) { + if (deviceType_App() == phone_AppDeviceType && parent_Widget(sheet) == get_Window()->root.widget) { if (~flags_Widget(sheet) & keepOnTop_WidgetFlag) { /* Already finalized. */ arrange_Widget(sheet); @@ -1573,7 +1573,7 @@ void finalizeSheet_Widget(iWidget *sheet) { destroy_Widget(pageContent); setFlags_Widget(owner, drawBackgroundToBottom_WidgetFlag, iTrue); } - destroyPending_RootData(data_Root()); + destroyPending_Root(get_Root()); /* Additional elements for preferences. */ if (isPrefs) { addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(defaultBig_FontId)))); @@ -1966,7 +1966,7 @@ iWidget *makeQuestion_Widget(const char *title, const char *msg, } addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); addChild_Widget(dlg, iClob(makeDialogButtons_Widget(items, numItems))); - addChild_Widget(get_Window()->root, iClob(dlg)); + addChild_Widget(get_Window()->root.widget, iClob(dlg)); arrange_Widget(dlg); /* BUG: This extra arrange shouldn't be needed but the dialog won't be arranged correctly unless it's here. */ finalizeSheet_Widget(dlg); @@ -2412,7 +2412,7 @@ iWidget *makePreferences_Widget(void) { addChild_Widget(dlg, iClob(makeDialogButtons_Widget( (iMenuItem[]){ { "${dismiss}", SDLK_ESCAPE, 0, "prefs.dismiss" } }, 1))); - addChild_Widget(get_Window()->root, iClob(dlg)); + addChild_Widget(get_Window()->root.widget, iClob(dlg)); finalizeSheet_Widget(dlg); //printTree_Widget(dlg); return dlg; @@ -2445,7 +2445,7 @@ iWidget *makeBookmarkEditor_Widget(void) { KMOD_PRIMARY, "bmed.accept" } }, 2))); - addChild_Widget(get_Window()->root, iClob(dlg)); + addChild_Widget(get_Window()->root.widget, iClob(dlg)); finalizeSheet_Widget(dlg); return dlg; } @@ -2578,7 +2578,7 @@ iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) { setId_Widget(child_Widget(buttons, childCount_Widget(buttons) - 1), "feedcfg.save"); arrange_Widget(dlg); as_Widget(input)->rect.size.x = 100 * gap_UI - headings->rect.size.x; - addChild_Widget(get_Window()->root, iClob(dlg)); + addChild_Widget(get_Window()->root.widget, iClob(dlg)); finalizeSheet_Widget(dlg); /* Initialize. */ { const iBookmark *bm = bookmarkId ? get_Bookmarks(bookmarks_App(), bookmarkId) : NULL; @@ -2654,7 +2654,7 @@ iWidget *makeIdentityCreation_Widget(void) { KMOD_PRIMARY, "ident.accept" } }, 2))); - addChild_Widget(get_Window()->root, iClob(dlg)); + addChild_Widget(get_Window()->root.widget, iClob(dlg)); finalizeSheet_Widget(dlg); return dlg; } 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) { //#endif deinit_String(&d->id); if (d->flags & keepOnTop_WidgetFlag) { - removeAll_PtrArray(onTop_RootData(), d); + removeAll_PtrArray(onTop_Root(get_Root()), d); } if (d->flags & visualOffset_WidgetFlag) { removeTicker_App(visualOffsetAnimation_Widget_, d); @@ -95,10 +95,10 @@ static void aboutToBeDestroyed_Widget_(iWidget *d) { return; } if (flags_Widget(d) & keepOnTop_WidgetFlag) { - removeOne_PtrArray(onTop_RootData(), d); + removeOne_PtrArray(onTop_Root(get_Root()), d); } if (isHover_Widget(d)) { - data_Root()->hover = NULL; + get_Root()->hover = NULL; } iForEach(ObjectList, i, d->children) { aboutToBeDestroyed_Widget_(as_Widget(i.object)); @@ -111,10 +111,11 @@ void destroy_Widget(iWidget *d) { postRefresh_App(); } aboutToBeDestroyed_Widget_(d); - if (!data_Root()->pendingDestruction) { - data_Root()->pendingDestruction = new_PtrSet(); + iRoot *root = get_Root(); + if (!root->pendingDestruction) { + root->pendingDestruction = new_PtrSet(); } - insert_PtrSet(data_Root()->pendingDestruction, d); + insert_PtrSet(root->pendingDestruction, d); } } @@ -138,7 +139,7 @@ void setFlags_Widget(iWidget *d, int64_t flags, iBool set) { } iChangeFlags(d->flags, flags, set); if (flags & keepOnTop_WidgetFlag) { - iPtrArray *onTop = onTop_RootData(); + iPtrArray *onTop = onTop_Root(get_Root()); if (set) { iAssert(indexOf_PtrArray(onTop, d) == iInvalidPos); pushBack_PtrArray(onTop, d); @@ -186,7 +187,7 @@ void showCollapsed_Widget(iWidget *d, iBool show) { if ((isVisible && !show) || (!isVisible && show)) { setFlags_Widget(d, hidden_WidgetFlag, !show); /* The entire UI may be affected, if parents are resized due to the (un)collapsing. */ - arrange_Widget(get_Window()->root); + arrange_Widget(get_Window()->root.widget); postRefresh_App(); } } @@ -733,7 +734,7 @@ static iBool filterEvent_Widget_(const iWidget *d, const SDL_Event *ev) { } void unhover_Widget(void) { - data_Root()->hover = NULL; + get_Root()->hover = NULL; } iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { @@ -743,14 +744,14 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { /* Hover widget may change. */ setHover_Widget(NULL); } - if (data_Root()->focus && isKeyboardEvent_(ev)) { + if (get_Root()->focus && isKeyboardEvent_(ev)) { /* Root dispatches keyboard events directly to the focused widget. */ - if (dispatchEvent_Widget(data_Root()->focus, ev)) { + if (dispatchEvent_Widget(get_Root()->focus, ev)) { return iTrue; } } /* Root offers events first to widgets on top. */ - iReverseForEach(PtrArray, i, data_Root()->onTop) { + iReverseForEach(PtrArray, i, get_Root()->onTop) { iWidget *widget = *i.value; if (isVisible_Widget(widget) && dispatchEvent_Widget(widget, ev)) { #if 0 @@ -774,7 +775,7 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { } } else if (ev->type == SDL_MOUSEMOTION && - (!data_Root()->hover || hasParent_Widget(d, data_Root()->hover)) && + (!get_Root()->hover || hasParent_Widget(d, get_Root()->hover)) && flags_Widget(d) & hover_WidgetFlag && ~flags_Widget(d) & hidden_WidgetFlag && ~flags_Widget(d) & disabled_WidgetFlag) { 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) { handle the events first. */ iReverseForEach(ObjectList, i, d->children) { iWidget *child = as_Widget(i.object); - if (child == data_Root()->focus && isKeyboardEvent_(ev)) { + if (child == get_Root()->focus && isKeyboardEvent_(ev)) { continue; /* Already dispatched. */ } if (isVisible_Widget(child) && child->flags & keepOnTop_WidgetFlag) { @@ -1081,7 +1082,7 @@ void drawChildren_Widget(const iWidget *d) { } /* Root draws the on-top widgets on top of everything else. */ if (!d->parent) { - iConstForEach(PtrArray, i, onTop_RootData()) { + iConstForEach(PtrArray, i, onTop_Root(get_Root())) { const iWidget *top = *i.value; draw_Widget(top); } @@ -1198,7 +1199,7 @@ iAny *hitChild_Widget(const iWidget *d, iInt2 coord) { } /* Check for on-top widgets first. */ if (!d->parent) { - iReverseForEach(PtrArray, i, onTop_RootData()) { + iReverseForEach(PtrArray, i, onTop_Root(get_Root())) { iWidget *child = i.ptr; // printf("ontop: %s (%s) hidden:%d hittable:%d\n", cstr_String(id_Widget(child)), // class_Widget(child)->name, @@ -1286,12 +1287,12 @@ iBool isDisabled_Widget(const iAnyObject *d) { iBool isFocused_Widget(const iAnyObject *d) { iAssert(isInstance_Object(d, &Class_Widget)); - return data_Root()->focus == d; + return get_Root()->focus == d; } iBool isHover_Widget(const iAnyObject *d) { iAssert(isInstance_Object(d, &Class_Widget)); - return data_Root()->hover == d; + return get_Root()->hover == d; } iBool isSelected_Widget(const iAnyObject *d) { @@ -1337,12 +1338,12 @@ iBool isAffectedByVisualOffset_Widget(const iWidget *d) { } void setFocus_Widget(iWidget *d) { - if (data_Root()->focus != d) { - if (data_Root()->focus) { - iAssert(!contains_PtrSet(data_Root()->pendingDestruction, data_Root()->focus)); - postCommand_Widget(data_Root()->focus, "focus.lost"); + if (get_Root()->focus != d) { + if (get_Root()->focus) { + iAssert(!contains_PtrSet(get_Root()->pendingDestruction, get_Root()->focus)); + postCommand_Widget(get_Root()->focus, "focus.lost"); } - data_Root()->focus = d; + get_Root()->focus = d; if (d) { iAssert(flags_Widget(d) & focusable_WidgetFlag); postCommand_Widget(d, "focus.gained"); @@ -1351,15 +1352,15 @@ void setFocus_Widget(iWidget *d) { } iWidget *focus_Widget(void) { - return data_Root()->focus; + return get_Root()->focus; } void setHover_Widget(iWidget *d) { - data_Root()->hover = d; + get_Root()->hover = d; } iWidget *hover_Widget(void) { - return data_Root()->hover; + return get_Root()->hover; } static const iWidget *findFocusable_Widget_(const iWidget *d, const iWidget *startFrom, @@ -1403,7 +1404,7 @@ static const iWidget *findFocusRoot_Widget_(const iWidget *d) { } iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusDir) { - const iWidget *root = findFocusRoot_Widget_(get_Window()->root); + const iWidget *root = findFocusRoot_Widget_(get_Window()->root.widget); iAssert(root != NULL); iBool getNext = (startFrom ? iFalse : iTrue); const iWidget *found = findFocusable_Widget_(root, startFrom, &getNext, focusDir); @@ -1415,14 +1416,14 @@ iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusD } void setMouseGrab_Widget(iWidget *d) { - if (data_Root()->mouseGrab != d) { - data_Root()->mouseGrab = d; + if (get_Root()->mouseGrab != d) { + get_Root()->mouseGrab = d; SDL_CaptureMouse(d != NULL); } } iWidget *mouseGrab_Widget(void) { - return data_Root()->mouseGrab; + return get_Root()->mouseGrab; } void postCommand_Widget(const iAnyObject *d, const char *cmd, ...) { @@ -1456,7 +1457,7 @@ void refresh_Widget(const iAnyObject *d) { } void raise_Widget(iWidget *d) { - iPtrArray *onTop = onTop_RootData(); + iPtrArray *onTop = onTop_Root(get_Root()); if (d->flags & keepOnTop_WidgetFlag) { iAssert(indexOf_PtrArray(onTop, d) != iInvalidPos); 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) { #if defined (iPlatformAppleDesktop) insertMacMenus_(); #endif - static iRootData rootData_; - setCurrent_Root(NULL, &rootData_); - d->root = createUserInterface_Root(); - setCurrent_Root(d->root, &rootData_); + setCurrent_Root(&d->root); + createUserInterface_Root(&d->root); } static void updateRootSize_Window_(iWindow *d, iBool notifyAlways) { - iInt2 *size = &d->root->rect.size; + iInt2 *size = &d->root.widget->rect.size; const iInt2 oldSize = *size; SDL_GetRendererOutputSize(d->render, &size->x, &size->y); size->y -= d->keyboardHeight; - d->root->minSize = *size; + d->root.widget->minSize = *size; if (notifyAlways || !isEqual_I2(oldSize, *size)) { - updatePadding_Root(d->root); + updatePadding_Root(&d->root); const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x); const iBool isVert = (d->place.lastNotifiedSize.y != size->y); - arrange_Widget(d->root); + arrange_Widget(d->root.widget); postCommandf_App("window.resized width:%d height:%d horiz:%d vert:%d", size->x, size->y, @@ -196,8 +194,8 @@ static void updateRootSize_Window_(iWindow *d, iBool notifyAlways) { void drawWhileResizing_Window(iWindow *d, int w, int h) { /* This is called while a window resize is in progress, so we can be pretty confident the size has actually changed. */ - d->root->rect.size = coord_Window(d, w, h); - arrange_Widget(d->root); + d->root.widget->rect.size = coord_Window(d, w, h); + arrange_Widget(d->root.widget); draw_Window(d); } @@ -347,7 +345,7 @@ static SDL_Surface *loadImage_(const iBlock *data, int resized) { void init_Window(iWindow *d, iRect rect) { theWindow_ = d; d->win = NULL; - d->root = NULL; + init_Root(&d->root); iZap(d->cursors); d->place.initialPos = rect.pos; d->place.normalRect = rect; @@ -460,7 +458,7 @@ void deinit_Window(iWindow *d) { SDL_FreeCursor(d->cursors[i]); } } - iReleasePtr(&d->root); + deinit_Root(&d->root); deinit_Text(); SDL_DestroyRenderer(d->render); SDL_DestroyWindow(d->win); @@ -636,7 +634,7 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { return iTrue; } case SDL_WINDOWEVENT_RESIZED: - updatePadding_Root(d->root); + updatePadding_Root(&d->root); if (d->isMinimized) { updateRootSize_Window_(d, iTrue); return iTrue; @@ -768,7 +766,7 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { event.button.x = pos.x; event.button.y = pos.y; } - iWidget *widget = d->root; + iWidget *widget = d->root.widget; if (event.type == SDL_MOUSEMOTION || event.type == SDL_MOUSEWHEEL || event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) { if (mouseGrab_Widget()) { @@ -796,7 +794,7 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { } } if (isMetricsChange_UserEvent(&event)) { - updateMetrics_Root(d->root); + updateMetrics_Root(&d->root); } if (isCommand_UserEvent(&event, "lang.changed")) { #if defined (iPlatformAppleDesktop) @@ -805,8 +803,8 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { insertMacMenus_(); #endif invalidate_Window_(d); - updatePreferencesLayout_Widget(findChild_Widget(d->root, "prefs")); - arrange_Widget(d->root); + updatePreferencesLayout_Widget(findChild_Widget(d->root.widget, "prefs")); + arrange_Widget(d->root.widget); //printTree_Widget(findChild_Widget(d->root, "prefs")); } if (oldHover != hover_Widget()) { @@ -823,7 +821,7 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { iBool postContextClick_Window(iWindow *d, const SDL_MouseButtonEvent *ev) { /* A context menu may still get triggered here. */ - const iWidget *hit = hitChild_Widget(d->root, init_I2(ev->x, ev->y)); + const iWidget *hit = hitChild_Widget(d->root.widget, init_I2(ev->x, ev->y)); while (hit && isEmpty_String(id_Widget(hit))) { hit = parent_Widget(hit); } @@ -868,7 +866,7 @@ void draw_Window(iWindow *d) { /* Draw widgets. */ d->frameTime = SDL_GetTicks(); if (isExposed_Window(d)) { - draw_Widget(d->root); + draw_Widget(d->root.widget); #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) /* App icon. */ const iWidget *appIcon = findChild_Widget(d->root, "winbar.icon"); @@ -907,7 +905,7 @@ void resize_Window(iWindow *d, int w, int h) { void setTitle_Window(iWindow *d, const iString *title) { SDL_SetWindowTitle(d->win, cstr_String(title)); - iLabelWidget *bar = findChild_Widget(d->root, "winbar.title"); + iLabelWidget *bar = findChild_Widget(d->root.widget, "winbar.title"); if (bar) { updateText_LabelWidget(bar, title); } @@ -942,7 +940,7 @@ uint32_t id_Window(const iWindow *d) { } iInt2 rootSize_Window(const iWindow *d) { - return d && d->root ? d->root->rect.size : zero_I2(); + return d && d->root.widget ? d->root.widget->rect.size : zero_I2(); } 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. */ #pragma once -#include "widget.h" +#include "root.h" #include #include @@ -66,8 +66,8 @@ struct Impl_Window { iBool ignoreClick; uint32_t focusGainedAt; SDL_Renderer *render; - iWidget * root; - float pixelRatio; /* conversion between points and pixels, e.g., coords, window size */ + iRoot root; /* root widget and UI state */ + float pixelRatio; /* conversion between points and pixels, e.g., coords, window size */ float displayScale; /* DPI-based scaling factor of current display, affects uiScale only */ float uiScale; uint32_t frameTime; -- cgit v1.2.3