From 54882a015e4ea880fb817f013609a3f8411db725 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 18 May 2021 14:58:58 +0300 Subject: App: Fixed init of UI palette on first run IssueID #275 --- src/app.c | 1 + src/ui/window.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app.c b/src/app.c index 27ce93ce..526c7752 100644 --- a/src/app.c +++ b/src/app.c @@ -732,6 +732,7 @@ static void init_App_(iApp *d, int argc, char **argv) { setupApplication_iOS(); #endif init_Keys(); + setThemePalette_Color(d->prefs.theme); /* default UI colors */ loadPrefs_App_(d); load_Keys(dataDir_App_()); d->window = new_Window(d->initialWindowRect); diff --git a/src/ui/window.c b/src/ui/window.c index abdc363d..5bf2aa53 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -59,7 +59,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ static iWindow *theWindow_ = NULL; -#if defined (iPlatformApple) || defined (iPlatformLinux) +#if defined (iPlatformApple) || defined (iPlatformLinux) || defined (iPlatformOther) static float initialUiScale_ = 1.0f; #else static float initialUiScale_ = 1.1f; -- cgit v1.2.3 From 88e1a4667d981bf7d87f1e4052a7671a960351da Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 18 May 2021 06:57:18 +0300 Subject: SidebarWidget: Don't animate at launch --- src/app.c | 4 ++-- src/ui/sidebarwidget.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/app.c b/src/app.c index 526c7752..6c559f33 100644 --- a/src/app.c +++ b/src/app.c @@ -420,8 +420,8 @@ static iBool loadState_App_(iApp *d) { if (deviceType_App() != phone_AppDeviceType) { setWidth_SidebarWidget(sidebar, widths[0]); setWidth_SidebarWidget(sidebar2, widths[1]); - if (flags & 1) postCommand_Root(root, "sidebar.toggle"); - if (flags & 2) postCommand_Root(root, "sidebar2.toggle"); + if (flags & 1) postCommand_Root(root, "sidebar.toggle noanim:1"); + if (flags & 2) postCommand_Root(root, "sidebar2.toggle noanim:1"); } } } diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 436eb250..cb6dab65 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c @@ -878,7 +878,8 @@ static iBool handleSidebarCommand_SidebarWidget_(iSidebarWidget *d, const char * if (arg_Command(cmd) && isVisible_Widget(w)) { return iTrue; } - const iBool isAnimated = (deviceType_App() != phone_AppDeviceType); + const iBool isAnimated = argLabel_Command(cmd, "noanim") == 0 && + (deviceType_App() != phone_AppDeviceType); int visX = 0; if (isVisible_Widget(w)) { visX = left_Rect(bounds_Widget(w)) - left_Rect(w->root->widget->rect); @@ -895,6 +896,7 @@ static iBool handleSidebarCommand_SidebarWidget_(iSidebarWidget *d, const char * } } else if (isAnimated) { + setFlags_Widget(w, horizontalOffset_WidgetFlag, iTrue); if (d->side == right_SideBarSide) { setVisualOffset_Widget(w, visX, 0, 0); setVisualOffset_Widget(w, visX + w->rect.size.x, 300, easeOut_AnimFlag | softer_AnimFlag); -- cgit v1.2.3 From 8026b29755cde294ed1db34dd254bba4d0d0b381 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 18 May 2021 08:53:28 +0300 Subject: Root: Updating size of navbar buttons/indicators Not all UI elements were appropriate sized when switching between normal and tight layout. --- src/ui/root.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/ui/root.c b/src/ui/root.c index 6cf3f424..8c98bdd3 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -583,20 +583,22 @@ static void updateNavBarSize_(iWidget *navBar) { /* Button sizing. */ if (isNarrow ^ ((flags_Widget(navBar) & tight_WidgetFlag) != 0)) { setFlags_Widget(navBar, tight_WidgetFlag, isNarrow); - iForEach(ObjectList, i, navBar->children) { - iWidget *child = as_Widget(i.object); - setFlags_Widget(child, tight_WidgetFlag, isNarrow); - if (isInstance_Object(i.object, &Class_LabelWidget)) { - iLabelWidget *label = i.object; - updateSize_LabelWidget(label); + iObjectList *lists[] = { + children_Widget(navBar), + children_Widget(findChild_Widget(navBar, "url")), + children_Widget(findChild_Widget(navBar, "url.buttons")), + }; + iForIndices(k, lists) { + iForEach(ObjectList, i, lists[k]) { + iWidget *child = as_Widget(i.object); + setFlags_Widget(child, tight_WidgetFlag, isNarrow); + if (isInstance_Object(i.object, &Class_LabelWidget)) { + iLabelWidget *label = i.object; + updateSize_LabelWidget(label); + } } } updateUrlInputContentPadding_(navBar); - /* Note that InputWidget uses the `tight` flag to adjust its inner padding. */ -// const int embedButtonWidth = width_Widget(findChild_Widget(navBar, "navbar.lock")); -// setContentPadding_InputWidget(findChild_Widget(navBar, "url"), -// embedButtonWidth * 0.75f, -// embedButtonWidth * 0.75f); } if (isPhone) { static const char *buttons[] = { "navbar.back", "navbar.forward", "navbar.sidebar", @@ -620,7 +622,8 @@ static void updateNavBarSize_(iWidget *navBar) { urlBar->rect.size.x = iMini(navBarAvailableSpace_(navBar), 167 * gap_UI); arrange_Widget(navBar); } - refresh_Widget(navBar); + updateMetrics_Root(navBar->root); /* tight flags changed; need to resize URL bar contents */ +// refresh_Widget(navBar); postCommand_Widget(navBar, "layout.changed id:navbar"); } @@ -1086,7 +1089,9 @@ void createUserInterface_Root(iRoot *d) { setNoAutoMinHeight_LabelWidget(pin, iTrue); addChildFlags_Widget(rightEmbed, iClob(pin), - collapse_WidgetFlag | hidden_WidgetFlag | tight_WidgetFlag | frameless_WidgetFlag); + collapse_WidgetFlag | hidden_WidgetFlag | tight_WidgetFlag | + frameless_WidgetFlag); + updateSize_LabelWidget(pin); } iWidget *urlButtons = new_Widget(); setId_Widget(urlButtons, "url.buttons"); -- cgit v1.2.3 From 4530faec76c12f5fcf337f3786c1819f94bcd7b9 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 18 May 2021 08:53:44 +0300 Subject: LabelWidget: Respect `noAutoMinHeight` --- src/ui/labelwidget.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 44ed795b..7ee7bfc8 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -404,7 +404,9 @@ void updateSize_LabelWidget(iLabelWidget *d) { iWidget *w = as_Widget(d); const int64_t flags = flags_Widget(w); const iInt2 size = defaultSize_LabelWidget(d); - w->minSize.y = size.y; /* vertically text must remain visible */ + if (!d->flags.noAutoMinHeight) { + w->minSize.y = size.y; /* vertically text must remain visible */ + } /* Wrapped text implies that width must be defined by arrangement. */ if (!(flags & (fixedWidth_WidgetFlag | wrapText_WidgetFlag))) { w->rect.size.x = size.x; -- cgit v1.2.3 From 538f0fe2433344184f8c6c9435334a0e475fdcc6 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 18 May 2021 12:31:42 +0300 Subject: DocumentWidget: Run drawing vs. backgrounds Erasing the background of every run should no longer be necessary (with progressive rendering), unless the run can change appearance. --- src/ui/documentwidget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 9d60f86f..9b8340fb 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -3682,8 +3682,8 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { // &d->paint, addY_I2(bottomLeft_Rect(wideRect), -1), width_Rect(wideRect), frame); // } } - else { - /* Normal background for other runs. */ + else if (run->linkId) { + /* Normal background for runs that may change appearance. */ fillRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmBackground_ColorId); } } -- cgit v1.2.3 From 58b4bbc5e92d4eb64da507d44fe5bbc9f535eee5 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 18 May 2021 12:33:10 +0300 Subject: App: Attempt to fix app restore issue Cached content like font glyphs are (were?) not being restored when returning to foreground. --- src/app.c | 3 +++ src/ui/window.c | 14 +++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/app.c b/src/app.c index 6c559f33..d259f541 100644 --- a/src/app.c +++ b/src/app.c @@ -1008,6 +1008,9 @@ void processEvents_App(enum iAppEventMode eventMode) { case SDL_APP_LOWMEMORY: clearCache_App_(); break; + case SDL_APP_WILLENTERFOREGROUND: + invalidate_Window(d->window); + break; case SDL_APP_DIDENTERFOREGROUND: gotEvents = iTrue; d->warmupFrames = 5; diff --git a/src/ui/window.c b/src/ui/window.c index 5bf2aa53..252b3bdb 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -566,14 +566,18 @@ iRoot *otherRoot_Window(const iWindow *d, iRoot *root) { return root == d->roots[0] && d->roots[1] ? d->roots[1] : d->roots[0]; } -void invalidate_Window(iWindow *d) { - if (d && !d->isInvalidated) { +static void invalidate_Window_(iWindow *d, iBool forced) { + if (d && (!d->isInvalidated || forced)) { d->isInvalidated = iTrue; resetFonts_Text(); postCommand_App("theme.changed auto:1"); /* forces UI invalidation */ } } +void invalidate_Window(iWindow *d) { + invalidate_Window_(d, iFalse); +} + static iBool isNormalPlacement_Window_(const iWindow *d) { if (d->isDrawFrozen) return iFalse; #if defined (iPlatformApple) @@ -741,14 +745,14 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { return iTrue; case SDL_WINDOWEVENT_RESTORED: updateSize_Window_(d, iTrue); - invalidate_Window(d); + invalidate_Window_(d, iTrue); d->isMinimized = iFalse; postRefresh_App(); return iTrue; case SDL_WINDOWEVENT_MINIMIZED: d->isMinimized = iTrue; return iTrue; -#endif +#endif /* defined (iPlatformDesktop) */ case SDL_WINDOWEVENT_LEAVE: unhover_Widget(); d->isMouseInside = iFalse; @@ -772,7 +776,7 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { d->isExposed = iTrue; #if defined (iPlatformMobile) /* Returned to foreground, may have lost buffered content. */ - invalidate_Window(d); + invalidate_Window_(d, iTrue); postCommand_App("window.unfreeze"); #endif return iFalse; -- cgit v1.2.3 From f37308c5b89c24a63af7c0aa1194e10cea305653 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 18 May 2021 12:34:29 +0300 Subject: Mobile: Tablet tweaks Heights of InputWidget vs. LabelWidget. The default sizes should be equal, e.g., so the navbar elements align properly. Don't set the input focus automatically when opening a dialog, since the keyboard may cover much of the UI. --- src/app.c | 6 ++++-- src/ui/inputwidget.c | 12 +++++++----- src/ui/labelwidget.c | 2 +- src/ui/sidebarwidget.c | 8 ++++++-- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/app.c b/src/app.c index d259f541..3f0ec2c4 100644 --- a/src/app.c +++ b/src/app.c @@ -2153,7 +2153,7 @@ iBool handleCommand_App(const char *cmd) { iWidget *tabs = findWidget_App("doctabs"); #if defined (iPlatformAppleMobile) /* Can't close the last on mobile. */ - if (tabCount_Widget(tabs) == 1) { + if (tabCount_Widget(tabs) == 1 && numRoots_Window(get_Window()) == 1) { postCommand_App("navigate.home"); return iTrue; } @@ -2331,7 +2331,9 @@ iBool handleCommand_App(const char *cmd) { bookmarkTitle_DocumentWidget(doc), siteIcon_GmDocument(document_DocumentWidget(doc))); } - postCommand_App("focus.set id:bmed.title"); + if (deviceType_App() == desktop_AppDeviceType) { + postCommand_App("focus.set id:bmed.title"); + } return iTrue; } else if (equal_Command(cmd, "feeds.subscribe")) { diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 3b72cc60..64fd2ed0 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c @@ -148,6 +148,8 @@ iLocalDef iInt2 padding_(void) { return init_I2(gap_UI / 2, gap_UI / 2); } +#define extraPaddingHeight_ (1.25f * gap_UI) + static iRect contentBounds_InputWidget_(const iInputWidget *d) { const iWidget *w = constAs_Widget(d); // const iRect widgetBounds = bounds_Widget(w); @@ -157,7 +159,7 @@ static iRect contentBounds_InputWidget_(const iInputWidget *d) { shrink_Rect(&bounds, init_I2(gap_UI * (flags_Widget(w) & tight_WidgetFlag ? 1 : 2), 0)); bounds.pos.y += padding_().y / 2; if (flags_Widget(w) & extraPadding_WidgetFlag) { - bounds.pos.y += gap_UI; + bounds.pos.y += extraPaddingHeight_ / 2; } return bounds; } @@ -205,7 +207,7 @@ static void updateSizeForFixedLength_InputWidget_(iInputWidget *d) { /* Set a fixed size based on maximum possible width of the text. */ iBlock *content = new_Block(d->maxLen); fill_Block(content, 'M'); - int extraHeight = (flags_Widget(as_Widget(d)) & extraPadding_WidgetFlag ? 2 * gap_UI : 0); + int extraHeight = (flags_Widget(as_Widget(d)) & extraPadding_WidgetFlag ? extraPaddingHeight_ : 0); setFixedSize_Widget( as_Widget(d), add_I2(measure_Text(d->font, cstr_Block(content)), @@ -299,7 +301,7 @@ static int contentHeight_InputWidget_(const iInputWidget *d, iBool forLayout) { if (forLayout) { numLines = iMin(numLines, d->maxLayoutLines); } - return numLines * lineHeight_Text(d->font); + return (int) numLines * lineHeight_Text(d->font); } static void updateMetrics_InputWidget_(iInputWidget *d) { @@ -308,7 +310,7 @@ static void updateMetrics_InputWidget_(iInputWidget *d) { /* Caller must arrange the width, but the height is fixed. */ w->rect.size.y = contentHeight_InputWidget_(d, iTrue) + 3.0f * padding_().y; /* TODO: Why 3x? */ if (flags_Widget(w) & extraPadding_WidgetFlag) { - w->rect.size.y += 2 * gap_UI; + w->rect.size.y += extraPaddingHeight_; } invalidateBuffered_InputWidget_(d); postCommand_Widget(d, "input.resized"); @@ -960,7 +962,7 @@ static iRect bounds_InputWidget_(const iInputWidget *d) { } bounds.size.y = contentHeight_InputWidget_(d, iFalse) + 3 * padding_().y; if (w->flags & extraPadding_WidgetFlag) { - bounds.size.y += 2 * gap_UI; + bounds.size.y += extraPaddingHeight_; } return bounds; } diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 7ee7bfc8..95f281be 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -66,7 +66,7 @@ static iInt2 padding_LabelWidget_(const iLabelWidget *d, int corner) { #if defined (iPlatformAppleMobile) return add_I2(widgetPad, init_I2(flags & tight_WidgetFlag ? 2 * gap_UI : (4 * gap_UI), - (flags & extraPadding_WidgetFlag ? 1.5f : 1) * 3 * gap_UI / 2)); + (flags & extraPadding_WidgetFlag ? 1.5f : 1.0f) * 3 * gap_UI / 2)); #else return add_I2(widgetPad, init_I2(flags & tight_WidgetFlag ? 3 * gap_UI / 2 : (3 * gap_UI), diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index cb6dab65..86410d11 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c @@ -1142,7 +1142,9 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) } if (isCommand_Widget(w, ev, "feed.entry.bookmark")) { makeBookmarkCreation_Widget(&item->url, &item->label, item->icon); - postCommand_App("focus.set id:bmed.title"); + if (deviceType_App() == desktop_AppDeviceType) { + postCommand_App("focus.set id:bmed.title"); + } return iTrue; } iBookmark *feedBookmark = get_Bookmarks(bookmarks_App(), item->id); @@ -1290,7 +1292,9 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) &item->url, collect_String(newRange_String(urlHost_String(&item->url))), 0x1f310 /* globe */); - postCommand_App("focus.set id:bmed.title"); + if (deviceType_App() == desktop_AppDeviceType) { + postCommand_App("focus.set id:bmed.title"); + } } } else if (equal_Command(cmd, "history.clear")) { -- cgit v1.2.3 From 4b7d2f8978881b8a01f4b37ce33486dfa6484d1c Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 18 May 2021 16:54:15 +0300 Subject: Mobile: No view split on phone; layout fixes --- src/ui/documentwidget.c | 3 +++ src/ui/mobile.c | 18 ++++++++++++------ src/ui/widget.c | 6 ++++-- src/ui/window.c | 5 +++++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 9b8340fb..e227bcef 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -3053,6 +3053,9 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e 0, format_CStr("!open newtab:5 url:%s", cstr_String(linkUrl)) } }, 4); + if (deviceType_App() == phone_AppDeviceType) { + removeN_Array(&items, size_Array(&items) - 2, iInvalidSize); + } } else if (!willUseProxy_App(scheme)) { pushBack_Array( diff --git a/src/ui/mobile.c b/src/ui/mobile.c index 1f5e9758..6c3a0b32 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c @@ -253,7 +253,9 @@ static iAnyObject *addPanelChild_(iWidget *panel, iAnyObject *child, int64_t fla } } if ((elementType == toggle_PrefsElement && precedingElementType != toggle_PrefsElement) || - (elementType == textInput_PrefsElement && precedingElementType != textInput_PrefsElement)) { + (elementType == textInput_PrefsElement && precedingElementType != textInput_PrefsElement) || + (elementType == dropdown_PrefsElement && precedingElementType != dropdown_PrefsElement) || + (elementType == radioButton_PrefsElement && precedingElementType == heading_PrefsElement)) { flags |= borderTop_WidgetFlag; } return addChildFlags_Widget(panel, child, flags); @@ -305,6 +307,7 @@ static iWidget *makeValuePadding_(iWidget *value) { } static iWidget *makeValuePaddingWithHeading_(iLabelWidget *heading, iWidget *value) { + const iBool isInput = isInstance_Object(value, &Class_InputWidget); iWidget *div = new_Widget(); setFlags_Widget(div, borderBottom_WidgetFlag | arrangeHeight_WidgetFlag | @@ -313,10 +316,11 @@ static iWidget *makeValuePaddingWithHeading_(iLabelWidget *heading, iWidget *val setBackgroundColor_Widget(div, uiBackgroundSidebar_ColorId); setPadding_Widget(div, gap_UI, gap_UI, 4 * gap_UI, gap_UI); addChildFlags_Widget(div, iClob(heading), 0); + setPadding1_Widget(as_Widget(heading), 0); //setFixedSize_Widget(as_Widget(heading), init_I2(-1, height_Widget(value))); setFont_LabelWidget(heading, labelFont_()); setTextColor_LabelWidget(heading, uiTextStrong_ColorId); - if (isInstance_Object(value, &Class_InputWidget)) { + if (isInput) { addChildFlags_Widget(div, iClob(value), expand_WidgetFlag); } else if (isInstance_Object(value, &Class_LabelWidget) && @@ -332,6 +336,7 @@ static iWidget *makeValuePaddingWithHeading_(iLabelWidget *heading, iWidget *val addChildFlags_Widget(div, iClob(new_Widget()), expand_WidgetFlag); addChild_Widget(div, iClob(value)); } + printTree_Widget(div); return div; } @@ -374,7 +379,9 @@ void finalizeSheet_Mobile(iWidget *sheet) { postRefresh_App(); return; } - /* Landscape Layout    Portrait Layout + /* TODO: In portrait, top panel and detail stack are all stacked together. + + Landscape Layout    Portrait Layout    ┌─────────┬──────Detail─Stack─────┐    ┌─────────┬ ─ ─ ─ ─ ┐ │ │┌───────────────────┐ │    │ │Detail @@ -616,10 +623,9 @@ void finalizeSheet_Mobile(iWidget *sheet) { addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(labelFont_())))); iLabelWidget *aboutButton = addChildFlags_Widget(topPanel, iClob(makePanelButton_(planet_Icon " ${menu.about}", "panel.open")), - chevron_WidgetFlag); + chevron_WidgetFlag | borderTop_WidgetFlag); addChildFlags_Widget(topPanel, - iClob(makePanelButton_(info_Icon " ${menu.help}", "!open url:about:help")), - borderTop_WidgetFlag); + iClob(makePanelButton_(info_Icon " ${menu.help}", "!open url:about:help")), 0); /* The About panel. */ { iWidget *panel = addChildPanel_(detailStack, aboutButton, NULL); iString *msg = collectNew_String(); diff --git a/src/ui/widget.c b/src/ui/widget.c index 3439fb1b..3ff2e713 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -726,13 +726,15 @@ static void resetArrangement_Widget_(iWidget *d) { if (d->flags & arrangeHorizontal_WidgetFlag) { child->rect.pos.x = 0; } - if (d->flags & resizeWidthOfChildren_WidgetFlag && child->flags & expand_WidgetFlag) { + if (d->flags & resizeWidthOfChildren_WidgetFlag && child->flags & expand_WidgetFlag && + ~child->flags & fixedWidth_WidgetFlag) { child->rect.size.x = 0; } if (d->flags & arrangeVertical_WidgetFlag) { child->rect.pos.y = 0; } - if (d->flags & resizeHeightOfChildren_WidgetFlag && child->flags & expand_WidgetFlag) { + if (d->flags & resizeHeightOfChildren_WidgetFlag && child->flags & expand_WidgetFlag && + ~child->flags & fixedHeight_WidgetFlag) { child->rect.size.y = 0; } } diff --git a/src/ui/window.c b/src/ui/window.c index 252b3bdb..87db2f3e 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -1199,6 +1199,11 @@ void swapRoots_Window(iWindow *d) { void setSplitMode_Window(iWindow *d, int splitFlags) { const int splitMode = splitFlags & mode_WindowSplit; + if (deviceType_App() == phone_AppDeviceType) { + /* There isn't enough room on the phone. */ + /* TODO: Maybe in landscape only? */ + return; + } iAssert(current_Root() == NULL); if (d->splitMode != splitMode) { int oldCount = numRoots_Window(d); -- cgit v1.2.3 From ba425fa4038580fa71bb944e55fedb04238d7197 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Wed, 19 May 2021 10:43:15 +0300 Subject: iOS: Updated SDL patch The SDL patch now contains the macOS scroll event change and, as a new addition, iOS status bar appearance control via the SDL view controller. --- README.md | 2 +- sdl2-macos-ios.diff | 85 +++++++++++++++++++++++++++++++++++++++++ sdl2-macos-mouse-scrolling.diff | 36 ----------------- 3 files changed, 86 insertions(+), 37 deletions(-) create mode 100644 sdl2-macos-ios.diff delete mode 100644 sdl2-macos-mouse-scrolling.diff diff --git a/README.md b/README.md index 3d5ec5ac..f1a62578 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ When using OpenSSL 1.1.1 from Homebrew, you must add its pkgconfig path to your export PKG_CONFIG_PATH=/opt/homebrew/Cellar/openssl@1.1/1.1.1i/lib/pkgconfig -Also, SDL's trackpad scrolling behavior on macOS is not optimal for regular GUI apps because it emulates a physical mouse wheel. This may change in a future release of SDL, but at least in 2.0.14 (and earlier) a [small patch](https://git.skyjake.fi/gemini/lagrange/raw/branch/dev/sdl2-macos-mouse-scrolling.diff) is required to allow momentum scrolling to come through as single-pixel mouse wheel events. Note that SDL comes with an Xcode project; use the "Shared Library" target and check that you are doing a Release build. +Also, SDL's trackpad scrolling behavior on macOS is not optimal for regular GUI apps because it emulates a physical mouse wheel. This may change in a future release of SDL, but at least in 2.0.14 (and earlier) a [small patch](https://git.skyjake.fi/gemini/lagrange/raw/branch/dev/sdl2-macos-ios.diff) is required to allow momentum scrolling to come through as single-pixel mouse wheel events. Note that SDL comes with an Xcode project; use the "Shared Library" target and check that you are doing a Release build. ### Compiling on Windows diff --git a/sdl2-macos-ios.diff b/sdl2-macos-ios.diff new file mode 100644 index 00000000..04d0f2e5 --- /dev/null +++ b/sdl2-macos-ios.diff @@ -0,0 +1,85 @@ +Only in SDL2-2.0.14/src: .DS_Store +diff -ru SDL2-2.0.14-original/src/events/SDL_mouse.c SDL2-2.0.14/src/events/SDL_mouse.c +--- SDL2-2.0.14-original/src/events/SDL_mouse.c 2020-12-21 19:44:36.000000000 +0200 ++++ SDL2-2.0.14/src/events/SDL_mouse.c 2021-01-06 18:31:18.000000000 +0200 +@@ -647,8 +647,8 @@ + event.wheel.preciseX = x; + event.wheel.preciseY = y; + #endif +- event.wheel.x = integral_x; +- event.wheel.y = integral_y; ++ event.wheel.x = x; //integral_x; ++ event.wheel.y = y; //integral_y; + event.wheel.direction = (Uint32)direction; + posted = (SDL_PushEvent(&event) > 0); + } +Only in SDL2-2.0.14/src/video: .DS_Store +diff -ru SDL2-2.0.14-original/src/video/cocoa/SDL_cocoamouse.m SDL2-2.0.14/src/video/cocoa/SDL_cocoamouse.m +--- SDL2-2.0.14-original/src/video/cocoa/SDL_cocoamouse.m 2020-12-21 19:44:36.000000000 +0200 ++++ SDL2-2.0.14/src/video/cocoa/SDL_cocoamouse.m 2021-01-06 18:31:18.000000000 +0200 +@@ -423,10 +423,16 @@ + } + + SDL_MouseID mouseID = mouse->mouseID; +- CGFloat x = -[event deltaX]; +- CGFloat y = [event deltaY]; ++ CGFloat x = -[event scrollingDeltaX]; ++ CGFloat y = [event scrollingDeltaY]; + SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL; + ++ /* HACK: Make a distinction between precise and imprecise scrolling. ++ Trackpad seems to be mouseID 0. */ ++ if (![event hasPreciseScrollingDeltas]) { ++ mouseID = 1; ++ } ++ + if ([event respondsToSelector:@selector(isDirectionInvertedFromDevice)]) { + if ([event isDirectionInvertedFromDevice] == YES) { + direction = SDL_MOUSEWHEEL_FLIPPED; +Only in SDL2-2.0.14/src/video/cocoa: SDL_cocoamouse.m.orig +diff -ru SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.h SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.h +--- SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.h 2020-12-21 19:44:36.000000000 +0200 ++++ SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.h 2021-05-17 13:11:13.000000000 +0300 +@@ -58,10 +58,13 @@ + #if !TARGET_OS_TV + - (NSUInteger)supportedInterfaceOrientations; + - (BOOL)prefersStatusBarHidden; ++- (void)setStatusStyle:(UIStatusBarStyle)style; ++- (UIStatusBarStyle)preferredStatusBarStyle; + - (BOOL)prefersHomeIndicatorAutoHidden; + - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures; + + @property (nonatomic, assign) int homeIndicatorHidden; ++@property (nonatomic, assign) UIStatusBarStyle statusBarStyle; + #endif + + #if SDL_IPHONE_KEYBOARD +diff -ru SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.m SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.m +--- SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.m 2020-12-21 19:44:36.000000000 +0200 ++++ SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.m 2021-05-17 13:11:58.000000000 +0300 +@@ -104,6 +104,7 @@ + #endif + + #if !TARGET_OS_TV ++ self.statusBarStyle = UIStatusBarStyleDefault; + SDL_AddHintCallback(SDL_HINT_IOS_HIDE_HOME_INDICATOR, + SDL_HideHomeIndicatorHintChanged, + (__bridge void *) self); +@@ -229,6 +230,17 @@ + return hidden; + } + ++- (void)setStatusStyle:(UIStatusBarStyle)style ++{ ++ self.statusBarStyle = style; ++ [self setNeedsStatusBarAppearanceUpdate]; ++} ++ ++- (UIStatusBarStyle)preferredStatusBarStyle ++{ ++ return self.statusBarStyle; ++} ++ + - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures + { + if (self.homeIndicatorHidden >= 0) { diff --git a/sdl2-macos-mouse-scrolling.diff b/sdl2-macos-mouse-scrolling.diff deleted file mode 100644 index e2f30c24..00000000 --- a/sdl2-macos-mouse-scrolling.diff +++ /dev/null @@ -1,36 +0,0 @@ -diff -r 4f06c06b6d19 src/events/SDL_mouse.c ---- a/src/events/SDL_mouse.c Wed Aug 05 15:28:51 2020 +0200 -+++ b/src/events/SDL_mouse.c Tue Nov 10 12:16:06 2020 +0200 -@@ -642,8 +642,8 @@ - event.wheel.preciseX = x; - event.wheel.preciseY = y; - #endif -- event.wheel.x = integral_x; -- event.wheel.y = integral_y; -+ event.wheel.x = x; //integral_x; -+ event.wheel.y = y; //integral_y; - event.wheel.direction = (Uint32)direction; - posted = (SDL_PushEvent(&event) > 0); - } -diff -r 4f06c06b6d19 src/video/cocoa/SDL_cocoamouse.m ---- a/src/video/cocoa/SDL_cocoamouse.m Wed Aug 05 15:28:51 2020 +0200 -+++ b/src/video/cocoa/SDL_cocoamouse.m Tue Nov 10 12:16:06 2020 +0200 -@@ -424,10 +424,16 @@ - } - - SDL_MouseID mouseID = mouse->mouseID; -- CGFloat x = -[event deltaX]; -- CGFloat y = [event deltaY]; -+ CGFloat x = -[event scrollingDeltaX]; -+ CGFloat y = [event scrollingDeltaY]; - SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL; - -+ /* HACK: Make a distinction between precise and imprecise scrolling. -+ Trackpad seems to be mouseID 0. */ -+ if (![event hasPreciseScrollingDeltas]) { -+ mouseID = 1; -+ } -+ - if ([event respondsToSelector:@selector(isDirectionInvertedFromDevice)]) { - if ([event isDirectionInvertedFromDevice] == YES) { - direction = SDL_MOUSEWHEEL_FLIPPED; -- cgit v1.2.3 From d5cf10db60a613db48d74426ceec9b12ffd54ce2 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Wed, 19 May 2021 11:25:26 +0300 Subject: Mobile: InputWidget Return key vs. maxLen Only unlimited-length input should allow line breaks with the Return key. --- src/ui/inputwidget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 64fd2ed0..0dc5ffcb 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c @@ -1162,7 +1162,8 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { return iTrue; case SDLK_RETURN: case SDLK_KP_ENTER: - if (mods == KMOD_SHIFT || (~d->inFlags & isUrl_InputWidgetFlag && + if (mods == KMOD_SHIFT || (d->maxLen == 0 && + ~d->inFlags & isUrl_InputWidgetFlag && deviceType_App() != desktop_AppDeviceType)) { pushUndo_InputWidget_(d); deleteMarked_InputWidget_(d); -- cgit v1.2.3 From 31840540e60d85ddef2642d9a748258d45241186 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Wed, 19 May 2021 11:25:32 +0300 Subject: Cleanup --- src/ui/root.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ui/root.c b/src/ui/root.c index 8c98bdd3..9ed62711 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -776,17 +776,12 @@ static iBool handleSearchBarCommands_(iWidget *searchBar, const char *cmd) { else if (equal_Command(cmd, "focus.gained")) { if (pointer_Command(cmd) == findChild_Widget(searchBar, "find.input")) { if (!isVisible_Widget(searchBar)) { -// setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); -// arrange_Widget(root_Widget(searchBar)); -// postRefresh_App(); showCollapsed_Widget(searchBar, iTrue); } } } else if (equal_Command(cmd, "find.close")) { if (isVisible_Widget(searchBar)) { - //setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iTrue); - //arrange_Widget(searchBar->parent); showCollapsed_Widget(searchBar, iFalse); if (isFocused_Widget(findChild_Widget(searchBar, "find.input"))) { setFocus_Widget(NULL); -- cgit v1.2.3 From d2a76230effce8586b7d90beff519e221e744bf7 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Wed, 19 May 2021 11:52:24 +0300 Subject: Widget: Fixed arrangement bug Whenever a widget is resized, we may need to rearrange its children. The up-to-date sizes must be used for determining positions for other children. --- src/ui/documentwidget.c | 5 +++-- src/ui/widget.c | 46 ++++++++++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index e227bcef..0906a1d4 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -571,10 +571,11 @@ static float normScrollPos_DocumentWidget_(const iDocumentWidget *d) { } static int scrollMax_DocumentWidget_(const iDocumentWidget *d) { - int sm = size_GmDocument(d->doc).y - height_Rect(bounds_Widget(constAs_Widget(d))) + + const iWidget *w = constAs_Widget(d); + int sm = size_GmDocument(d->doc).y - height_Rect(bounds_Widget(w)) + (hasSiteBanner_GmDocument(d->doc) ? 1 : 2) * d->pageMargin * gap_UI; if (d->phoneToolbar) { - sm += size_Root(constAs_Widget(d)->root).y - + sm += size_Root(w->root).y - top_Rect(boundsWithoutVisualOffset_Widget(d->phoneToolbar)); } return sm; diff --git a/src/ui/widget.c b/src/ui/widget.c index 3ff2e713..43bbe56e 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -314,50 +314,48 @@ static void printf_Widget_(const iWidget *d, const char *format, ...) { delete_String(msg); } -static void setWidth_Widget_(iWidget *d, int width) { +static iBool setWidth_Widget_(iWidget *d, int width) { iAssert(width >= 0); TRACE(d, "attempt to set width to %d (current: %d, min width: %d)", width, d->rect.size.x, d->minSize.x); width = iMax(width, d->minSize.x); - if (~d->flags & fixedWidth_WidgetFlag) { //} || d->flags & collapse_WidgetFlag) { + if (~d->flags & fixedWidth_WidgetFlag) { if (d->rect.size.x != width) { d->rect.size.x = width; TRACE(d, "width has changed to %d", width); if (class_Widget(d)->sizeChanged) { const int oldHeight = d->rect.size.y; class_Widget(d)->sizeChanged(d); - if (d->rect.size.y != oldHeight) { - TRACE(d, "sizeChanged() cuased height change to %d; redoing parent", d->rect.size.y); - /* Widget updated its height. */ - arrange_Widget_(d->parent); - TRACE(d, "parent layout redone"); - } } + return iTrue; } } else { TRACE(d, "changing width not allowed; flags: %x", d->flags); } + return iFalse; } -static void setHeight_Widget_(iWidget *d, int height) { +static iBool setHeight_Widget_(iWidget *d, int height) { iAssert(height >= 0); if (d->sizeRef) { return; /* height defined by another widget */ } TRACE(d, "attempt to set height to %d (current: %d, min height: %d)", height, d->rect.size.y, d->minSize.y); height = iMax(height, d->minSize.y); - if (~d->flags & fixedHeight_WidgetFlag) { //} || d->flags & collapse_WidgetFlag) { + if (~d->flags & fixedHeight_WidgetFlag) { if (d->rect.size.y != height) { d->rect.size.y = height; TRACE(d, "height has changed to %d", height); if (class_Widget(d)->sizeChanged) { class_Widget(d)->sizeChanged(d); } + return iTrue; } } else { TRACE(d, "changing height not allowed; flags: %x", d->flags); } + return iFalse; } iLocalDef iRect innerRect_Widget_(const iWidget *d) { @@ -578,6 +576,12 @@ static void arrange_Widget_(iWidget *d) { TRACE(d, "...done changing child sizes (EVEN mode)"); } } + /* Children arrange themselves. */ { + iForEach(ObjectList, i, d->children) { + iWidget *child = as_Widget(i.object); + arrange_Widget_(child); + } + } /* Resize the expanding children to fill the remaining available space. */ if (expCount > 0 && (d->flags & (arrangeHorizontal_WidgetFlag | arrangeVertical_WidgetFlag))) { TRACE(d, "%d expanding children, resizing them %s...", expCount, @@ -600,16 +604,20 @@ static void arrange_Widget_(iWidget *d) { TRACE(d, "child %p size is not arranged", child); continue; } + iBool sizeChanged = iFalse; if (child->flags & expand_WidgetFlag) { if (d->flags & arrangeHorizontal_WidgetFlag) { - setWidth_Widget_(child, avail.x); - setHeight_Widget_(child, height_Rect(innerRect)); + sizeChanged |= setWidth_Widget_(child, avail.x); + sizeChanged |= setHeight_Widget_(child, height_Rect(innerRect)); } else if (d->flags & arrangeVertical_WidgetFlag) { - setWidth_Widget_(child, width_Rect(innerRect)); - setHeight_Widget_(child, avail.y); + sizeChanged |= setWidth_Widget_(child, width_Rect(innerRect)); + sizeChanged |= setHeight_Widget_(child, avail.y); } } + if (sizeChanged) { + arrange_Widget_(child); /* its children may need rearranging */ + } } } if (d->flags & resizeChildrenToWidestChild_WidgetFlag) { @@ -618,7 +626,9 @@ static void arrange_Widget_(iWidget *d) { iForEach(ObjectList, i, d->children) { iWidget *child = as_Widget(i.object); if (isArrangedSize_Widget_(child)) { - setWidth_Widget_(child, widest); + if (setWidth_Widget_(child, widest)) { + arrange_Widget_(child); /* its children may need rearranging */ + } } else { TRACE(d, "child %p cannot be resized (parentCannotResize: %d)", child, @@ -633,7 +643,6 @@ static void arrange_Widget_(iWidget *d) { d->flags & arrangeVertical_WidgetFlag ? " vert" : ""); iForEach(ObjectList, i, d->children) { iWidget *child = as_Widget(i.object); - arrange_Widget_(child); if (isCollapsed_Widget_(child) || !isArrangedPos_Widget_(child)) { TRACE(d, "child %p arranging prohibited", child); continue; @@ -743,6 +752,11 @@ static void resetArrangement_Widget_(iWidget *d) { void arrange_Widget(iWidget *d) { if (d) { +#if !defined (NDEBUG) + if (tracing_) { + puts("\n==== NEW WIDGET ARRANGEMENT ====\n"); + } +#endif resetArrangement_Widget_(d); /* back to initial default sizes */ arrange_Widget_(d); } -- cgit v1.2.3