From 2e9f8b247472bc6be3963ee7aad223f895085185 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 30 Nov 2021 15:34:38 +0200 Subject: SidebarWidget: Crash when switching Feeds mode Updating items immediately destroys the action widgets. --- src/ui/widget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ui/widget.c') diff --git a/src/ui/widget.c b/src/ui/widget.c index a171a6cd..cedda461 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -1528,7 +1528,7 @@ static void addToPotentiallyVisible_Widget_(const iWidget *d, iPtrArray *pvs, iR } if (isFullyContainedByOther_Rect(bounds, *fullyMasked)) { return; /* can't be seen */ - } + } pushBack_PtrArray(pvs, d); if (d->bgColor >= 0 && ~d->flags & noBackground_WidgetFlag && isFullyContainedByOther_Rect(*fullyMasked, bounds)) { -- cgit v1.2.3 From 8e7c651faa2e7525cc2e4251516585f89b822ab8 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Thu, 2 Dec 2021 19:33:57 +0200 Subject: Widget: Widget rearrangement issues There were issues where popup menus would only get wider and never narrower. Arrangements should not be dependent on the results of a previous one. --- src/ui/labelwidget.c | 4 ++-- src/ui/util.c | 50 +++++++++++++++++++++++++++++++------------------- src/ui/widget.c | 16 ++++++++++++++++ 3 files changed, 49 insertions(+), 21 deletions(-) (limited to 'src/ui/widget.c') diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 9ef62262..947d5daa 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -491,9 +491,9 @@ int font_LabelWidget(const iLabelWidget *d) { } void updateSize_LabelWidget(iLabelWidget *d) { - iWidget *w = as_Widget(d); + iWidget *w = as_Widget(d); const int64_t flags = flags_Widget(w); - const iInt2 size = defaultSize_LabelWidget(d); + const iInt2 size = defaultSize_LabelWidget(d); if (!d->flags.noAutoMinHeight) { w->minSize.y = size.y; /* vertically text must remain visible */ } diff --git a/src/ui/util.c b/src/ui/util.c index 91b67e06..61d3e9bb 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -861,12 +861,8 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { setFlags_Widget(menu, keepOnTop_WidgetFlag | collapse_WidgetFlag | hidden_WidgetFlag | arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag | - resizeChildrenToWidestChild_WidgetFlag | overflowScrollable_WidgetFlag | - (isPortraitPhone_App() ? drawBackgroundToVerticalSafeArea_WidgetFlag : 0), + resizeChildrenToWidestChild_WidgetFlag | overflowScrollable_WidgetFlag, iTrue); - if (!isPortraitPhone_App()) { - setFrameColor_Widget(menu, uiBackgroundSelected_ColorId); - } makeMenuItems_Widget(menu, items, n); addChild_Widget(parent, menu); iRelease(menu); /* owned by parent now */ @@ -884,6 +880,7 @@ void openMenu_Widget(iWidget *d, iInt2 windowCoord) { static void updateMenuItemFonts_Widget_(iWidget *d) { const iBool isPortraitPhone = (deviceType_App() == phone_AppDeviceType && isPortrait_App()); + const iBool isMobile = (deviceType_App() != desktop_AppDeviceType); const iBool isSlidePanel = (flags_Widget(d) & horizontalOffset_WidgetFlag) != 0; iForEach(ObjectList, i, children_Widget(d)) { if (isInstance_Object(i.object, &Class_LabelWidget)) { @@ -895,14 +892,14 @@ static void updateMenuItemFonts_Widget_(iWidget *d) { if (deviceType_App() == desktop_AppDeviceType) { setFont_LabelWidget(label, isCaution ? uiLabelBold_FontId : uiLabel_FontId); } - else if (isPortraitPhone) { - if (!isSlidePanel) { - setFont_LabelWidget(label, isCaution ? uiLabelBigBold_FontId : uiLabelBig_FontId); - } - } - else { - setFont_LabelWidget(label, isCaution ? uiContentBold_FontId : uiContent_FontId); + else { //if (isPortraitPhone) { + //if (!isSlidePanel) { + setFont_LabelWidget(label, isCaution ? uiLabelBigBold_FontId : uiLabelBig_FontId); + // } } +// else { +// setFont_LabelWidget(label, isCaution ? uiContentBold_FontId : uiContent_FontId); +// } } else if (childCount_Widget(i.object)) { updateMenuItemFonts_Widget_(i.object); @@ -1034,6 +1031,12 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) { setFlags_Widget(d, hidden_WidgetFlag, iFalse); setFlags_Widget(d, commandOnMouseMiss_WidgetFlag, iTrue); setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iFalse); + if (!isPortraitPhone) { + setFrameColor_Widget(d, uiBackgroundSelected_ColorId); + } + else { + setFrameColor_Widget(d, none_ColorId); + } arrange_Widget(d); /* need to know the height */ iBool allowOverflow = iFalse; /* A vertical offset determined by a possible selected label in the menu. */ @@ -1104,13 +1107,22 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) { } #endif raise_Widget(d); - if (isPortraitPhone) { - setFlags_Widget(d, arrangeWidth_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag, iFalse); - setFlags_Widget(d, resizeWidthOfChildren_WidgetFlag | drawBackgroundToBottom_WidgetFlag, iTrue); - if (!isSlidePanel) { - setFlags_Widget(d, borderTop_WidgetFlag, iTrue); + if (deviceType_App() != desktop_AppDeviceType) { + setFlags_Widget(d, arrangeWidth_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag, + !isPortraitPhone); + setFlags_Widget(d, + resizeWidthOfChildren_WidgetFlag | drawBackgroundToBottom_WidgetFlag | + drawBackgroundToVerticalSafeArea_WidgetFlag, + isPortraitPhone); + if (isPortraitPhone) { + if (!isSlidePanel) { + setFlags_Widget(d, borderTop_WidgetFlag, iTrue); + } + d->rect.size.x = rootSize.x; + } + else { + d->rect.size.x = 0; } - d->rect.size.x = rootSize.x; } updateMenuItemFonts_Widget_(d); arrange_Widget(d); @@ -2458,7 +2470,7 @@ iWidget *makePreferences_Widget(void) { { "title id:heading.settings" }, { "panel text:" gear_Icon " ${heading.prefs.general}", 0, 0, (const void *) generalPanelItems }, { "panel icon:0x1f5a7 id:heading.prefs.network", 0, 0, (const void *) networkPanelItems }, - { "panel text:" person_Icon " ${sidebar.identities}", 0, 0, (const void *) identityPanelItems }, + { "panel noscroll:1 text:" person_Icon " ${sidebar.identities}", 0, 0, (const void *) identityPanelItems }, { "padding" }, { "panel icon:0x1f4f1 id:heading.prefs.interface", 0, 0, (const void *) uiPanelItems }, { "panel icon:0x1f3a8 id:heading.prefs.colors", 0, 0, (const void *) colorPanelItems }, diff --git a/src/ui/widget.c b/src/ui/widget.c index cedda461..254c2590 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "util.h" #include "window.h" +#include "labelwidget.h" + #include #include #include @@ -836,6 +838,12 @@ static void arrange_Widget_(iWidget *d) { } static void resetArrangement_Widget_(iWidget *d) { + if (d->flags & resizeToParentWidth_WidgetFlag) { + d->rect.size.x = 0; + } + if (d->flags & resizeToParentHeight_WidgetFlag) { + d->rect.size.y = 0; + } iForEach(ObjectList, i, children_Widget(d)) { iWidget *child = as_Widget(i.object); resetArrangement_Widget_(child); @@ -847,6 +855,14 @@ static void resetArrangement_Widget_(iWidget *d) { ~child->flags & fixedWidth_WidgetFlag) { child->rect.size.x = 0; } + if (d->flags & resizeChildrenToWidestChild_WidgetFlag) { + if (isInstance_Object(child, &Class_LabelWidget)) { + updateSize_LabelWidget((iLabelWidget *) child); + } + else { + child->rect.size.x = 0; + } + } if (d->flags & arrangeVertical_WidgetFlag) { child->rect.pos.y = 0; } -- cgit v1.2.3 From 6e917280380316eba77b1dfa983daf488510e70f Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Fri, 3 Dec 2021 07:46:16 +0200 Subject: Mobile: Manage Identities via Settings --- po/en.po | 5 ++- res/lang/cs.bin | Bin 31054 -> 31087 bytes res/lang/de.bin | Bin 30061 -> 30094 bytes res/lang/en.bin | Bin 26158 -> 26191 bytes res/lang/eo.bin | Bin 25112 -> 25145 bytes res/lang/es.bin | Bin 29885 -> 29918 bytes res/lang/es_MX.bin | Bin 27217 -> 27250 bytes res/lang/fi.bin | Bin 29718 -> 29751 bytes res/lang/fr.bin | Bin 30865 -> 30898 bytes res/lang/gl.bin | Bin 29070 -> 29103 bytes res/lang/hu.bin | Bin 30890 -> 30923 bytes res/lang/ia.bin | Bin 28217 -> 28250 bytes res/lang/ie.bin | Bin 28805 -> 28838 bytes res/lang/isv.bin | Bin 24878 -> 24911 bytes res/lang/pl.bin | Bin 29493 -> 29526 bytes res/lang/ru.bin | Bin 44253 -> 44286 bytes res/lang/sk.bin | Bin 25214 -> 25247 bytes res/lang/sr.bin | Bin 43679 -> 43712 bytes res/lang/tok.bin | Bin 26927 -> 26960 bytes res/lang/tr.bin | Bin 29111 -> 29144 bytes res/lang/uk.bin | Bin 43598 -> 43631 bytes res/lang/zh_Hans.bin | Bin 25112 -> 25145 bytes res/lang/zh_Hant.bin | Bin 25310 -> 25343 bytes src/app.c | 8 +++++ src/ui/labelwidget.c | 17 ++++++---- src/ui/labelwidget.h | 1 + src/ui/mobile.c | 11 ++++--- src/ui/mobile.h | 1 + src/ui/root.c | 88 +++++++++++++++++++++++++++++++++++-------------- src/ui/sidebarwidget.c | 20 ++++++----- src/ui/uploadwidget.c | 7 +++- src/ui/util.c | 9 +++++ src/ui/util.h | 3 +- src/ui/widget.c | 10 +++--- 34 files changed, 129 insertions(+), 51 deletions(-) (limited to 'src/ui/widget.c') diff --git a/po/en.po b/po/en.po index c6fa98be..4e013941 100644 --- a/po/en.po +++ b/po/en.po @@ -395,6 +395,9 @@ msgstr "New Identity…" msgid "menu.identity.import" msgstr "Import…" +msgid "menu.identities" +msgstr "Manage Identities" + msgid "menu.identity.notactive" msgstr "No Active Identity" @@ -988,7 +991,7 @@ msgid "upload.id" msgstr "Identity:" msgid "heading.upload.id" -msgstr "Identification" +msgstr "Authorization" msgid "dlg.upload.id.none" msgstr "None" diff --git a/res/lang/cs.bin b/res/lang/cs.bin index 8f8b3a6f..7c08bcfe 100644 Binary files a/res/lang/cs.bin and b/res/lang/cs.bin differ diff --git a/res/lang/de.bin b/res/lang/de.bin index 2df7f11f..e3f45a34 100644 Binary files a/res/lang/de.bin and b/res/lang/de.bin differ diff --git a/res/lang/en.bin b/res/lang/en.bin index 0129d019..0c65ffd3 100644 Binary files a/res/lang/en.bin and b/res/lang/en.bin differ diff --git a/res/lang/eo.bin b/res/lang/eo.bin index 4acb5f16..9edecafe 100644 Binary files a/res/lang/eo.bin and b/res/lang/eo.bin differ diff --git a/res/lang/es.bin b/res/lang/es.bin index 5d04443c..9e7d0585 100644 Binary files a/res/lang/es.bin and b/res/lang/es.bin differ diff --git a/res/lang/es_MX.bin b/res/lang/es_MX.bin index 3fcecd44..1dd95a4e 100644 Binary files a/res/lang/es_MX.bin and b/res/lang/es_MX.bin differ diff --git a/res/lang/fi.bin b/res/lang/fi.bin index 53449c30..1d5e4624 100644 Binary files a/res/lang/fi.bin and b/res/lang/fi.bin differ diff --git a/res/lang/fr.bin b/res/lang/fr.bin index 2ccda4da..c0202489 100644 Binary files a/res/lang/fr.bin and b/res/lang/fr.bin differ diff --git a/res/lang/gl.bin b/res/lang/gl.bin index 9f37b384..34d16341 100644 Binary files a/res/lang/gl.bin and b/res/lang/gl.bin differ diff --git a/res/lang/hu.bin b/res/lang/hu.bin index 4de98a70..2ab5484b 100644 Binary files a/res/lang/hu.bin and b/res/lang/hu.bin differ diff --git a/res/lang/ia.bin b/res/lang/ia.bin index f9e134fc..c43aec10 100644 Binary files a/res/lang/ia.bin and b/res/lang/ia.bin differ diff --git a/res/lang/ie.bin b/res/lang/ie.bin index 3324bb69..8a1d71e4 100644 Binary files a/res/lang/ie.bin and b/res/lang/ie.bin differ diff --git a/res/lang/isv.bin b/res/lang/isv.bin index 6b98e1f8..e9978815 100644 Binary files a/res/lang/isv.bin and b/res/lang/isv.bin differ diff --git a/res/lang/pl.bin b/res/lang/pl.bin index 33ed890b..b6de49f1 100644 Binary files a/res/lang/pl.bin and b/res/lang/pl.bin differ diff --git a/res/lang/ru.bin b/res/lang/ru.bin index 82c43ffc..7f153025 100644 Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ diff --git a/res/lang/sk.bin b/res/lang/sk.bin index 6dbeb129..35fdb2b1 100644 Binary files a/res/lang/sk.bin and b/res/lang/sk.bin differ diff --git a/res/lang/sr.bin b/res/lang/sr.bin index 7f058106..bd9ca450 100644 Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ diff --git a/res/lang/tok.bin b/res/lang/tok.bin index 206fe02c..cb34ada6 100644 Binary files a/res/lang/tok.bin and b/res/lang/tok.bin differ diff --git a/res/lang/tr.bin b/res/lang/tr.bin index 430ab02c..99dc6431 100644 Binary files a/res/lang/tr.bin and b/res/lang/tr.bin differ diff --git a/res/lang/uk.bin b/res/lang/uk.bin index 49d58f42..edcafb7e 100644 Binary files a/res/lang/uk.bin and b/res/lang/uk.bin differ diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin index cfa284be..488cc64f 100644 Binary files a/res/lang/zh_Hans.bin and b/res/lang/zh_Hans.bin differ diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin index f0f6fe97..edab200b 100644 Binary files a/res/lang/zh_Hant.bin and b/res/lang/zh_Hant.bin differ diff --git a/src/app.c b/src/app.c index 540c46d8..5b2e88bf 100644 --- a/src/app.c +++ b/src/app.c @@ -2667,6 +2667,9 @@ iBool handleCommand_App(const char *cmd) { if (!urlArg) { return iTrue; /* invalid command */ } + if (findWidget_App("prefs")) { + postCommand_App("prefs.dismiss"); + } iString *url = collectNewCStr_String(urlArg); const iBool noProxy = argLabel_Command(cmd, "noproxy") != 0; const iBool fromSidebar = argLabel_Command(cmd, "fromsidebar") != 0; @@ -2979,6 +2982,11 @@ iBool handleCommand_App(const char *cmd) { showTabPage_Widget(tabs, tabPage_Widget(tabs, d->prefs.dialogTab)); } setCommandHandler_Widget(dlg, handlePrefsCommands_); + if (argLabel_Command(cmd, "idents") && deviceType_App() != desktop_AppDeviceType) { + iWidget *idPanel = panel_Mobile(dlg, 2); + iWidget *button = findUserData_Widget(findChild_Widget(dlg, "panel.top"), idPanel); + postCommand_Widget(button, "panel.open"); + } } else if (equal_Command(cmd, "navigate.home")) { /* Look for bookmarks tagged "homepage". */ diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 947d5daa..d00733e1 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -36,6 +36,7 @@ struct Impl_LabelWidget { iWidget widget; iString srcLabel; iString label; + iInt2 labelOffset; int font; int key; int kmods; @@ -362,10 +363,6 @@ static void draw_LabelWidget_(const iLabelWidget *d) { } setClip_Paint(&p, rect); const int iconPad = iconPadding_LabelWidget_(d); -// const int iconColor = isCaution ? uiTextCaution_ColorId -// : flags & (disabled_WidgetFlag | pressed_WidgetFlag) ? fg -// : isHover ? uiIconHover_ColorId -// : uiIcon_ColorId; if (d->icon && d->icon != 0x20) { /* no need to draw an empty icon */ iString str; initUnicodeN_String(&str, &d->icon, 1); @@ -427,8 +424,11 @@ static void draw_LabelWidget_(const iLabelWidget *d) { else { drawCenteredOutline_Text( d->font, - adjusted_Rect(bounds, init_I2(iconPad * (flags & tight_WidgetFlag ? 1.0f : 1.5f), 0), - init_I2(-iconPad * (flags & tight_WidgetFlag ? 0.5f : 1.0f), 0)), + moved_Rect( + adjusted_Rect(bounds, + init_I2(iconPad * (flags & tight_WidgetFlag ? 1.0f : 1.5f), 0), + init_I2(-iconPad * (flags & tight_WidgetFlag ? 0.5f : 1.0f), 0)), + d->labelOffset), d->flags.alignVisual, d->flags.drawAsOutline ? fg : none_ColorId, d->flags.drawAsOutline ? d->widget.bgColor : fg, @@ -523,6 +523,7 @@ void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { d->font = uiLabel_FontId; d->forceFg = none_ColorId; d->icon = 0; + d->labelOffset = zero_I2(); initCStr_String(&d->srcLabel, label); initCopy_String(&d->label, &d->srcLabel); replaceVariables_LabelWidget_(d); @@ -623,6 +624,10 @@ void setRemoveTrailingColon_LabelWidget(iLabelWidget *d, iBool removeTrailingCol } } +void setTextOffset_LabelWidget(iLabelWidget *d, iInt2 offset) { + d->labelOffset = offset; +} + void updateText_LabelWidget(iLabelWidget *d, const iString *text) { set_String(&d->label, text); set_String(&d->srcLabel, text); diff --git a/src/ui/labelwidget.h b/src/ui/labelwidget.h index 6f1b7902..4f605d6b 100644 --- a/src/ui/labelwidget.h +++ b/src/ui/labelwidget.h @@ -38,6 +38,7 @@ void setWrap_LabelWidget (iLabelWidget *, iBool wrap); void setOutline_LabelWidget (iLabelWidget *, iBool drawAsOutline); void setAllCaps_LabelWidget (iLabelWidget *, iBool allCaps); void setRemoveTrailingColon_LabelWidget (iLabelWidget *, iBool removeTrailingColon); +void setTextOffset_LabelWidget (iLabelWidget *, iInt2 offset); void setFont_LabelWidget (iLabelWidget *, int fontId); void setTextColor_LabelWidget (iLabelWidget *, int color); void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */ diff --git a/src/ui/mobile.c b/src/ui/mobile.c index 5382cbce..ab282a86 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c @@ -180,13 +180,16 @@ size_t currentPanelIndex_Mobile(const iWidget *panels) { return iInvalidPos; } +iWidget *panel_Mobile(const iWidget *panels, size_t index) { + return child_Widget(findChild_Widget(panels, "detailstack"), index); +} + static iBool topPanelHandler_(iWidget *topPanel, const char *cmd) { const iBool isPortrait = !isSideBySideLayout_(); if (equal_Command(cmd, "panel.open")) { - iWidget *button = pointer_Command(cmd); + /* This command is sent by the button that opens the panel. */ + iWidget *button = pointer_Command(cmd); iWidget *panel = userData_Object(button); -// openMenu_Widget(panel, innerToWindow_Widget(panel, zero_I2())); -// setFlags_Widget(panel, hidden_WidgetFlag, iFalse); unselectAllPanelButtons_(topPanel); int panelIndex = -1; size_t childIndex = 0; @@ -208,8 +211,6 @@ static iBool topPanelHandler_(iWidget *topPanel, const char *cmd) { setText_LabelWidget(detailTitle, text_LabelWidget((iLabelWidget *) findTitleLabel_(panel))); setFlags_Widget(button, selected_WidgetFlag, iTrue); postCommand_Widget(topPanel, "panel.changed arg:%d", panelIndex); - //printTree_Widget(findDetailStack_(topPanel)); -// updateVisible_ListWidget(findChild_Widget(findDetailStack_(topPanel), "certlist")); updateCertListHeight_(findDetailStack_(topPanel)); return iTrue; } diff --git a/src/ui/mobile.h b/src/ui/mobile.h index 9d7ac8e4..06955945 100644 --- a/src/ui/mobile.h +++ b/src/ui/mobile.h @@ -39,6 +39,7 @@ void initPanels_Mobile (iWidget *panels, iWidget *parentWidget, const iMenuItem *itemsNullTerminated, const iMenuItem *actions, size_t numActions); +iWidget * panel_Mobile (const iWidget *panels, size_t index); size_t currentPanelIndex_Mobile (const iWidget *panels); enum iTransitionFlags { diff --git a/src/ui/root.c b/src/ui/root.c index b7a2e5c8..5df4b36f 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -333,19 +333,28 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { } else if (equal_Command(cmd, "identmenu.open")) { iWidget *toolBar = findWidget_Root("toolbar"); - iWidget *button = findWidget_Root(toolBar ? "toolbar.ident" : "navbar.ident"); + iWidget *button = findWidget_Root(toolBar && isPortraitPhone_App() ? "toolbar.ident" : "navbar.ident"); iArray items; init_Array(&items, sizeof(iMenuItem)); /* Current identity. */ const iString *docUrl = url_DocumentWidget(document_App()); const iGmIdentity *ident = identityForUrl_GmCerts(certs_App(), docUrl); const iString *fp = ident ? collect_String(hexEncode_Block(&ident->fingerprint)) : NULL; - pushBackN_Array(&items, - (iMenuItem[]){ { format_CStr("///" uiHeading_ColorEscape "%s", - ident ? cstr_String(name_GmIdentity(ident)) - : "${menu.identity.notactive}") }, - { "---" } }, - 2); + iString *str = NULL; + if (ident) { + str = copy_String(name_GmIdentity(ident)); + if (!isEmpty_String(&ident->notes)) { + appendFormat_String(str, "\n%s%s", escape_Color(uiAnnotation_ColorId), + cstr_String(&ident->notes)); + } + } + pushBackN_Array( + &items, + (iMenuItem[]){ { format_CStr("///" uiHeading_ColorEscape "%s", + str ? cstr_String(str) : "${menu.identity.notactive}") }, + { "---" } }, + 2); + delete_String(str); /* Alternate identities. */ if (ident) { const iString *site = collectNewRange_String(urlRoot_String(docUrl)); @@ -385,8 +394,8 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { : leftHalf_Icon " ${menu.show.identities}", 0, 0, - deviceType_App() == phone_AppDeviceType ? "toolbar.showident" - : "sidebar.mode arg:3 toggle:1" }); + //deviceType_App() == phone_AppDeviceType ? "toolbar.showident" + "sidebar.mode arg:3 toggle:1" }); } else { pushBack_Array(&items, &(iMenuItem){ gear_Icon " ${menu.identities}", 0, 0, @@ -517,9 +526,21 @@ static void updateNavBarIdentity_(iWidget *navBar) { iLabelWidget *toolName = findWidget_App("toolbar.name"); if (toolName) { setOutline_LabelWidget(toolButton, ident == NULL); - updateTextCStr_LabelWidget(toolName, subjectName ? cstr_String(subjectName) : ""); + /* Fit the name in the widget. */ + if (subjectName) { + const char *endPos; + tryAdvanceNoWrap_Text(uiLabelTiny_FontId, range_String(subjectName), width_Widget(toolName), + &endPos); + updateText_LabelWidget( + toolName, + collectNewRange_String((iRangecc){ constBegin_String(subjectName), endPos })); + } + else { + updateTextCStr_LabelWidget(toolName, ""); + } setFont_LabelWidget(toolButton, subjectName ? uiLabelMedium_FontId : uiLabelLarge_FontId); - arrange_Widget(parent_Widget(toolButton)); + setTextOffset_LabelWidget(toolButton, init_I2(0, subjectName ? -1.5f * gap_UI : 0)); + arrange_Widget(parent_Widget(toolButton)); } } @@ -604,11 +625,13 @@ void updateToolbarColors_Root(iRoot *d) { tmBannerBackground_ColorId; setBackgroundColor_Widget(toolBar, bg); iForEach(ObjectList, i, children_Widget(toolBar)) { - iLabelWidget *btn = i.object; +// iLabelWidget *btn = i.object; setTextColor_LabelWidget(i.object, isSidebarVisible ? uiTextDim_ColorId : tmBannerIcon_ColorId); setBackgroundColor_Widget(i.object, bg); /* using noBackground, but ident has outline */ } + setTextColor_LabelWidget(findChild_Widget(toolBar, "toolbar.name"), + isSidebarVisible ? uiTextDim_ColorId : tmBannerIcon_ColorId); } #else iUnused(d); @@ -1014,8 +1037,13 @@ static iBool handleToolBarCommands_(iWidget *toolBar, const char *cmd) { return iTrue; } else if (equal_Command(cmd, "toolbar.showident")) { - /* TODO: Clean this up. */ iWidget *sidebar = findWidget_App("sidebar"); + if (isVisible_Widget(sidebar)) { + postCommandf_App("sidebar.toggle"); + } + postCommand_App("preferences idents:1"); +#if 0 + /* TODO: Clean this up. */ iWidget *sidebar2 = findWidget_App("sidebar2"); //dismissSidebar_(sidebar, "toolbar.view"); if (isVisible_Widget(sidebar)) { @@ -1036,6 +1064,7 @@ static iBool handleToolBarCommands_(iWidget *toolBar, const char *cmd) { setVisualOffset_Widget(sidebar2, offset, 0, 0); setVisualOffset_Widget(sidebar2, 0, 400, easeOut_AnimFlag | softer_AnimFlag); } +#endif return iTrue; } else if (equal_Command(cmd, "sidebar.mode.changed")) { @@ -1099,15 +1128,16 @@ void updateMetrics_Root(iRoot *d) { const iWidget *toolBar = findChild_Widget(d->widget, "toolbar"); const iWidget *viewButton = findChild_Widget(d->widget, "toolbar.view"); const iWidget *idButton = findChild_Widget(toolBar, "toolbar.ident"); - const int font = uiLabelTiny_FontId; - setFont_LabelWidget(idName, font); - setPos_Widget(as_Widget(idName), +// const int font = uiLabelTiny_FontId; + setFixedSize_Widget(as_Widget(idName), init_I2(-1, 2 * gap_UI + lineHeight_Text(uiLabelTiny_FontId))); +// setFont_LabelWidget(idName, font); + /*setPos_Widget(as_Widget(idName), windowToLocal_Widget(as_Widget(idName), init_I2(left_Rect(bounds_Widget(idButton)), bottom_Rect(bounds_Widget(viewButton)) - lineHeight_Text(font) - gap_UI / 2))); setFixedSize_Widget(as_Widget(idName), init_I2(width_Widget(idButton), - lineHeight_Text(font))); + lineHeight_Text(font)));*/ } } postRefresh_App(); @@ -1413,15 +1443,17 @@ void createUserInterface_Root(iRoot *d) { iWidget *content = findChild_Widget(root, "tabs.content"); iSidebarWidget *sidebar1 = new_SidebarWidget(left_SidebarSide); addChildPos_Widget(content, iClob(sidebar1), front_WidgetAddPos); - iSidebarWidget *sidebar2 = new_SidebarWidget(right_SidebarSide); if (deviceType_App() != phone_AppDeviceType) { + iSidebarWidget *sidebar2 = new_SidebarWidget(right_SidebarSide); addChildPos_Widget(content, iClob(sidebar2), back_WidgetAddPos); } +#if 0 else { /* The identities sidebar is always in the main area. */ addChild_Widget(findChild_Widget(root, "stack"), iClob(sidebar2)); setFlags_Widget(as_Widget(sidebar2), hidden_WidgetFlag, iTrue); } +#endif } /* Lookup results. */ { iLookupWidget *lookup = new_LookupWidget(); @@ -1481,23 +1513,29 @@ void createUserInterface_Root(iRoot *d) { iClob(newLargeIcon_LabelWidget(forwardArrow_Icon, "navigate.forward")), frameless_WidgetFlag), "toolbar.forward"); - setId_Widget(addChildFlags_Widget(toolBar, - iClob(newLargeIcon_LabelWidget("\U0001f464", "identmenu.open")), - frameless_WidgetFlag), + iWidget *identButton; + setId_Widget(identButton = addChildFlags_Widget( + toolBar, + iClob(newLargeIcon_LabelWidget("\U0001f464", "identmenu.open")), + frameless_WidgetFlag | fixedHeight_WidgetFlag), "toolbar.ident"); setId_Widget(addChildFlags_Widget(toolBar, iClob(newLargeIcon_LabelWidget(book_Icon, "toolbar.showview arg:-1")), frameless_WidgetFlag | commandOnClick_WidgetFlag), "toolbar.view"); - setId_Widget(addChildFlags_Widget(toolBar, - iClob(new_LabelWidget("", "toolbar.showident")), + iLabelWidget *idName; + setId_Widget(addChildFlags_Widget(identButton, + iClob(idName = new_LabelWidget("", NULL)), frameless_WidgetFlag | noBackground_WidgetFlag | - fixedPosition_WidgetFlag | + moveToParentBottomEdge_WidgetFlag | + resizeToParentWidth_WidgetFlag + /*fixedPosition_WidgetFlag | fixedSize_WidgetFlag | ignoreForParentWidth_WidgetFlag | - ignoreForParentHeight_WidgetFlag), + ignoreForParentHeight_WidgetFlag*/), "toolbar.name"); + setFont_LabelWidget(idName, uiLabelTiny_FontId); iLabelWidget *menuButton = makeMenuButton_LabelWidget(menu_Icon, phoneNavMenuItems_, iElemCount(phoneNavMenuItems_)); setFont_LabelWidget(menuButton, uiLabelLarge_FontId); diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 674e2b7c..9b94f4d9 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c @@ -608,8 +608,10 @@ iBool setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { } void setClosedFolders_SidebarWidget(iSidebarWidget *d, const iIntSet *closedFolders) { - delete_IntSet(d->closedFolders); - d->closedFolders = copy_IntSet(closedFolders); + if (d) { + delete_IntSet(d->closedFolders); + d->closedFolders = copy_IntSet(closedFolders); + } } enum iSidebarMode mode_SidebarWidget(const iSidebarWidget *d) { @@ -625,7 +627,7 @@ float width_SidebarWidget(const iSidebarWidget *d) { } const iIntSet *closedFolders_SidebarWidget(const iSidebarWidget *d) { - return d->closedFolders; + return d ? d->closedFolders : collect_IntSet(new_IntSet()); } static const char *normalModeLabels_[max_SidebarMode] = { @@ -710,7 +712,8 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) { setId_Widget(buttons, "buttons"); setDrawBufferEnabled_Widget(buttons, iTrue); for (int i = 0; i < max_SidebarMode; i++) { - if (deviceType_App() == phone_AppDeviceType && i == identities_SidebarMode) { + if (i == identities_SidebarMode && deviceType_App() != desktop_AppDeviceType) { + /* On mobile, identities are managed via Settings. */ continue; } d->modeButtons[i] = addChildFlags_Widget( @@ -911,6 +914,7 @@ static void checkModeButtonLayout_SidebarWidget_(iSidebarWidget *d) { } void setWidth_SidebarWidget(iSidebarWidget *d, float widthAsGaps) { + if (!d) return; iWidget *w = as_Widget(d); const iBool isFixedWidth = deviceType_App() == phone_AppDeviceType; int width = widthAsGaps * gap_UI; /* in pixels */ @@ -1148,10 +1152,10 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) } } } - else if (deviceType_App() == tablet_AppDeviceType && equal_Command(cmd, "toolbar.showident")) { - postCommandf_App("sidebar.mode arg:%d toggle:1", identities_SidebarMode); - return iTrue; - } +// else if (deviceType_App() == tablet_AppDeviceType && equal_Command(cmd, "toolbar.showident")) { +// postCommandf_App("sidebar.mode arg:%d toggle:1", identities_SidebarMode); +// return iTrue; +// } else if (isPortraitPhone_App() && isVisible_Widget(w) && d->side == left_SidebarSide && equal_Command(cmd, "swipe.forward")) { postCommand_App("sidebar.toggle"); diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c index c22bfe86..89376633 100644 --- a/src/ui/uploadwidget.c +++ b/src/ui/uploadwidget.c @@ -123,9 +123,14 @@ static const iArray *makeIdentityItems_UploadWidget_(const iUploadWidget *d) { pushBack_Array(items, &(iMenuItem){ "---" }); iConstForEach(PtrArray, i, listIdentities_GmCerts(certs_App(), NULL, NULL)) { const iGmIdentity *id = i.ptr; + iString *str = collect_String(copy_String(name_GmIdentity(id))); + if (!isEmpty_String(&id->notes)) { + appendFormat_String( + str, "\n%s%s", escape_Color(uiAnnotation_ColorId), cstr_String(&id->notes)); + } pushBack_Array( items, - &(iMenuItem){ cstr_String(name_GmIdentity(id)), 0, 0, + &(iMenuItem){ cstr_String(str), 0, 0, format_CStr("upload.setid fp:%s", cstrCollect_String(hexEncode_Block(&id->fingerprint))) }); } diff --git a/src/ui/util.c b/src/ui/util.c index 61d3e9bb..de838769 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -1215,6 +1215,15 @@ iLabelWidget *findMenuItem_Widget(iWidget *menu, const char *command) { return NULL; } +iWidget *findUserData_Widget(iWidget *d, void *userData) { + iForEach(ObjectList, i, children_Widget(d)) { + if (userData_Object(i.object) == userData) { + return i.object; + } + } + return NULL; +} + void setMenuItemDisabled_Widget(iWidget *menu, const char *command, iBool disable) { if (flags_Widget(menu) & nativeMenu_WidgetFlag) { setDisabled_NativeMenuItem(findNativeMenuItem_Widget(menu, command), disable); diff --git a/src/ui/util.h b/src/ui/util.h index 81fb1cbd..7ee94f1d 100644 --- a/src/ui/util.h +++ b/src/ui/util.h @@ -249,7 +249,8 @@ void setMenuItemDisabled_Widget (iWidget *menu, const char *comm void setMenuItemDisabledByIndex_Widget(iWidget *menu, size_t index, iBool disable); void setMenuItemLabel_Widget (iWidget *menu, const char *command, const char *newLabel); void setMenuItemLabelByIndex_Widget (iWidget *menu, size_t index, const char *newLabel); -void setNativeMenuItems_Widget (iWidget *, const iMenuItem *items, size_t n); +void setNativeMenuItems_Widget (iWidget *menu, const iMenuItem *items, size_t n); +iWidget * findUserData_Widget (iWidget *, void *userData); int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */ diff --git a/src/ui/widget.c b/src/ui/widget.c index 254c2590..210fe899 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -271,10 +271,12 @@ void setMinSize_Widget(iWidget *d, iInt2 minSize) { } void setPadding_Widget(iWidget *d, int left, int top, int right, int bottom) { - d->padding[0] = left; - d->padding[1] = top; - d->padding[2] = right; - d->padding[3] = bottom; + if (d) { + d->padding[0] = left; + d->padding[1] = top; + d->padding[2] = right; + d->padding[3] = bottom; + } } iWidget *root_Widget(const iWidget *d) { -- cgit v1.2.3 From 723fcbf263bd2f5ff6c259a47091ebf685b50723 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sat, 4 Dec 2021 07:40:56 +0200 Subject: Mobile: Sidebar is now a vertically sliding panel Switched the phone sidebar to use the iOS half/full-height sliding sheet design. This is better for finger reachability and for retaining access to the current page. --- po/en.po | 3 + res/lang/cs.bin | Bin 31081 -> 31100 bytes res/lang/de.bin | Bin 30088 -> 30107 bytes res/lang/en.bin | Bin 26185 -> 26204 bytes res/lang/eo.bin | Bin 25139 -> 25158 bytes res/lang/es.bin | Bin 29912 -> 29931 bytes res/lang/es_MX.bin | Bin 27244 -> 27263 bytes res/lang/fi.bin | Bin 29745 -> 29764 bytes res/lang/fr.bin | Bin 30892 -> 30911 bytes res/lang/gl.bin | Bin 29097 -> 29116 bytes res/lang/hu.bin | Bin 30917 -> 30936 bytes res/lang/ia.bin | Bin 28244 -> 28263 bytes res/lang/ie.bin | Bin 28832 -> 28851 bytes res/lang/isv.bin | Bin 24905 -> 24924 bytes res/lang/pl.bin | Bin 29520 -> 29539 bytes res/lang/ru.bin | Bin 44280 -> 44299 bytes res/lang/sk.bin | Bin 25241 -> 25260 bytes res/lang/sr.bin | Bin 43706 -> 43725 bytes res/lang/tok.bin | Bin 26954 -> 26973 bytes res/lang/tr.bin | Bin 29138 -> 29157 bytes res/lang/uk.bin | Bin 43625 -> 43644 bytes res/lang/zh_Hans.bin | Bin 25139 -> 25158 bytes res/lang/zh_Hant.bin | Bin 25337 -> 25356 bytes src/ui/documentwidget.c | 6 +- src/ui/listwidget.c | 35 ++++++- src/ui/listwidget.h | 8 ++ src/ui/root.c | 106 ++++++++----------- src/ui/sidebarwidget.c | 271 ++++++++++++++++++++++++++++++++++++++---------- src/ui/sidebarwidget.h | 1 + src/ui/touch.c | 37 +++++-- src/ui/touch.h | 1 + src/ui/widget.c | 1 + src/ui/widget.h | 5 + 33 files changed, 343 insertions(+), 131 deletions(-) (limited to 'src/ui/widget.c') diff --git a/po/en.po b/po/en.po index 6b604d61..6996d28c 100644 --- a/po/en.po +++ b/po/en.po @@ -401,6 +401,9 @@ msgstr "Manage Identities" msgid "menu.identity.notactive" msgstr "No Active Identity" +msgid "sidebar.close" +msgstr "Done" + msgid "sidebar.bookmarks" msgstr "Bookmarks" diff --git a/res/lang/cs.bin b/res/lang/cs.bin index cf37c7de..a8981bd4 100644 Binary files a/res/lang/cs.bin and b/res/lang/cs.bin differ diff --git a/res/lang/de.bin b/res/lang/de.bin index a9d497d7..6d17ff3b 100644 Binary files a/res/lang/de.bin and b/res/lang/de.bin differ diff --git a/res/lang/en.bin b/res/lang/en.bin index 5e24ab94..4749f358 100644 Binary files a/res/lang/en.bin and b/res/lang/en.bin differ diff --git a/res/lang/eo.bin b/res/lang/eo.bin index 789c01c2..b3e06797 100644 Binary files a/res/lang/eo.bin and b/res/lang/eo.bin differ diff --git a/res/lang/es.bin b/res/lang/es.bin index 7ca8e297..2265ddf1 100644 Binary files a/res/lang/es.bin and b/res/lang/es.bin differ diff --git a/res/lang/es_MX.bin b/res/lang/es_MX.bin index 43a5bb77..810bc543 100644 Binary files a/res/lang/es_MX.bin and b/res/lang/es_MX.bin differ diff --git a/res/lang/fi.bin b/res/lang/fi.bin index 5a0ec586..ccc61bd4 100644 Binary files a/res/lang/fi.bin and b/res/lang/fi.bin differ diff --git a/res/lang/fr.bin b/res/lang/fr.bin index 329cae2b..355073bd 100644 Binary files a/res/lang/fr.bin and b/res/lang/fr.bin differ diff --git a/res/lang/gl.bin b/res/lang/gl.bin index 527de83b..30c5fb5f 100644 Binary files a/res/lang/gl.bin and b/res/lang/gl.bin differ diff --git a/res/lang/hu.bin b/res/lang/hu.bin index 82257541..90f32f47 100644 Binary files a/res/lang/hu.bin and b/res/lang/hu.bin differ diff --git a/res/lang/ia.bin b/res/lang/ia.bin index 5f1d7ab2..a9672e07 100644 Binary files a/res/lang/ia.bin and b/res/lang/ia.bin differ diff --git a/res/lang/ie.bin b/res/lang/ie.bin index 0d866d47..058ab7ff 100644 Binary files a/res/lang/ie.bin and b/res/lang/ie.bin differ diff --git a/res/lang/isv.bin b/res/lang/isv.bin index d30dcf4f..ccf1f206 100644 Binary files a/res/lang/isv.bin and b/res/lang/isv.bin differ diff --git a/res/lang/pl.bin b/res/lang/pl.bin index e9fd8460..d49b1fdd 100644 Binary files a/res/lang/pl.bin and b/res/lang/pl.bin differ diff --git a/res/lang/ru.bin b/res/lang/ru.bin index f8a69f51..cb2baebc 100644 Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ diff --git a/res/lang/sk.bin b/res/lang/sk.bin index 9d0e9f04..50ee11ce 100644 Binary files a/res/lang/sk.bin and b/res/lang/sk.bin differ diff --git a/res/lang/sr.bin b/res/lang/sr.bin index bbaba1e9..d27c1c48 100644 Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ diff --git a/res/lang/tok.bin b/res/lang/tok.bin index 517194d1..89e9526c 100644 Binary files a/res/lang/tok.bin and b/res/lang/tok.bin differ diff --git a/res/lang/tr.bin b/res/lang/tr.bin index e0aef190..ef7f8f61 100644 Binary files a/res/lang/tr.bin and b/res/lang/tr.bin differ diff --git a/res/lang/uk.bin b/res/lang/uk.bin index 0c261c00..cff8fb7d 100644 Binary files a/res/lang/uk.bin and b/res/lang/uk.bin differ diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin index d31b280b..e8dafce4 100644 Binary files a/res/lang/zh_Hans.bin and b/res/lang/zh_Hans.bin differ diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin index e06f4339..898bbddc 100644 Binary files a/res/lang/zh_Hant.bin and b/res/lang/zh_Hant.bin differ diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 95286566..0ef80690 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -2620,9 +2620,9 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { /* The temporary "swipeIn" will display the previous page until the finger is lifted. */ iDocumentWidget *swipeIn = findChild_Widget(swipeParent, "swipein"); if (!swipeIn) { - const iBool sidebarSwipe = (isPortraitPhone_App() && + const iBool sidebarSwipe = iFalse; /* && (isPortraitPhone_App() && d->flags & openedFromSidebar_DocumentWidgetFlag && - !isVisible_Widget(findWidget_App("sidebar"))); + !isVisible_Widget(findWidget_App("sidebar"))); */ swipeIn = new_DocumentWidget(); setId_Widget(as_Widget(swipeIn), "swipein"); setFlags_Widget(as_Widget(swipeIn), @@ -3235,6 +3235,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) return iTrue; } else if (equal_Command(cmd, "navigate.back") && document_App() == d) { +#if 0 if (isPortraitPhone_App()) { if (d->flags & openedFromSidebar_DocumentWidgetFlag && !isVisible_Widget(findWidget_App("sidebar"))) { @@ -3247,6 +3248,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) } d->flags &= ~openedFromSidebar_DocumentWidgetFlag; } +#endif if (d->request) { postCommandf_Root(w->root, "document.request.cancelled doc:%p url:%s", d, cstr_String(d->mod.url)); diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c index 82e4e451..d12afc4c 100644 --- a/src/ui/listwidget.c +++ b/src/ui/listwidget.c @@ -81,6 +81,7 @@ void init_ListWidget(iListWidget *d) { setThumb_ScrollWidget(d->scroll, 0, 0); init_SmoothScroll(&d->scrollY, w, scrollBegan_ListWidget_); d->itemHeight = 0; + d->scrollMode = normal_ScrollMode; d->noHoverWhileScrolling = iFalse; init_PtrArray(&d->items); d->hoverItem = iInvalidPos; @@ -187,6 +188,10 @@ void setScrollPos_ListWidget(iListWidget *d, int pos) { refresh_Widget(as_Widget(d)); } +void setScrollMode_ListWidget(iListWidget *d, enum iScrollMode mode) { + d->scrollMode = mode; +} + void scrollOffset_ListWidget(iListWidget *d, int offset) { moveSpan_SmoothScroll(&d->scrollY, offset, 0); } @@ -366,12 +371,28 @@ static iBool endDrag_ListWidget_(iListWidget *d, iInt2 endPos) { return iTrue; } +static iBool isScrollDisabled_ListWidget_(const iListWidget *d, const SDL_Event *ev) { + int dir = 0; + if (ev->type == SDL_MOUSEWHEEL) { + dir = iSign(ev->wheel.y); + } + switch (d->scrollMode) { + case disabledAtTopBothDirections_ScrollMode: + return scrollPos_ListWidget(d) <= 0; + case disabledAtTopUpwards_ScrollMode: + return scrollPos_ListWidget(d) <= 0 && dir > 0; + default: + break; + } + return iFalse; +} + static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { iWidget *w = as_Widget(d); if (isMetricsChange_UserEvent(ev)) { invalidate_ListWidget(d); } - else if (processEvent_SmoothScroll(&d->scrollY, ev)) { + else if (!isScrollDisabled_ListWidget_(d, ev) && processEvent_SmoothScroll(&d->scrollY, ev)) { return iTrue; } else if (isCommand_SDLEvent(ev)) { @@ -420,6 +441,18 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) { } } if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { + if (isScrollDisabled_ListWidget_(d, ev)) { + if (ev->wheel.which == SDL_TOUCH_MOUSEID) { + /* TODO: Could generalize this selection of the scrollable parent. */ + extern iWidgetClass Class_SidebarWidget; + iWidget *sidebar = findParentClass_Widget(w, &Class_SidebarWidget); + if (sidebar) { + transferAffinity_Touch(w, sidebar); + d->noHoverWhileScrolling = iTrue; + } + } + return iFalse; + } int amount = -ev->wheel.y; if (isPerPixel_MouseWheelEvent(&ev->wheel)) { stop_Anim(&d->scrollY.pos); diff --git a/src/ui/listwidget.h b/src/ui/listwidget.h index 7e6624a0..081109e8 100644 --- a/src/ui/listwidget.h +++ b/src/ui/listwidget.h @@ -51,6 +51,12 @@ iDeclareObjectConstruction(ListWidget) iDeclareType(VisBuf) +enum iScrollMode { + normal_ScrollMode, + disabledAtTopBothDirections_ScrollMode, + disabledAtTopUpwards_ScrollMode, +}; + struct Impl_ListWidget { iWidget widget; iScrollWidget *scroll; @@ -63,6 +69,7 @@ struct Impl_ListWidget { iClick click; iIntSet invalidItems; iVisBuf *visBuf; + enum iScrollMode scrollMode; iBool noHoverWhileScrolling; }; @@ -82,6 +89,7 @@ int itemHeight_ListWidget (const iListWidget *); int scrollPos_ListWidget (const iListWidget *); void setScrollPos_ListWidget (iListWidget *, int pos); +void setScrollMode_ListWidget (iListWidget *, enum iScrollMode mode); void scrollToItem_ListWidget (iListWidget *, size_t index, uint32_t span); void scrollOffset_ListWidget (iListWidget *, int offset); void scrollOffsetSpan_ListWidget (iListWidget *, int offset, uint32_t span); diff --git a/src/ui/root.c b/src/ui/root.c index f722df94..65fc11d1 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -487,11 +487,23 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { else if (deviceType_App() == phone_AppDeviceType && equal_Command(cmd, "window.resized")) { /* Place the sidebar next to or under doctabs depending on orientation. */ iSidebarWidget *sidebar = findChild_Widget(root, "sidebar"); - iSidebarWidget *sidebar2 = findChild_Widget(root, "sidebar2"); removeChild_Widget(parent_Widget(sidebar), sidebar); - // setBackgroundColor_Widget(findChild_Widget(as_Widget(sidebar), "buttons"), - // isPortrait_App() ? uiBackgroundUnfocusedSelection_ColorId - // : uiBackgroundSidebar_ColorId); + if (isLandscape_App()) { + addChildPos_Widget(findChild_Widget(root, "tabs.content"), iClob(sidebar), front_WidgetAddPos); + setWidth_SidebarWidget(sidebar, 73.0f); + setFlags_Widget(as_Widget(sidebar), fixedHeight_WidgetFlag, iFalse); + } + else { + addChild_Widget(root, iClob(sidebar)); + setWidth_SidebarWidget(sidebar, (float) width_Widget(root) / (float) gap_UI); + const int midHeight = height_Widget(root) / 2;// + lineHeight_Text(uiLabelLarge_FontId); + setMidHeight_SidebarWidget(sidebar, midHeight); + setFixedSize_Widget(as_Widget(sidebar), init_I2(-1, midHeight)); + setPos_Widget(as_Widget(sidebar), init_I2(0, height_Widget(root) - midHeight)); + } +#if 0 + iSidebarWidget *sidebar = findChild_Widget(root, "sidebar"); + iSidebarWidget *sidebar2 = findChild_Widget(root, "sidebar2"); setFlags_Widget(findChild_Widget(as_Widget(sidebar), "buttons"), borderTop_WidgetFlag, isPortrait_App()); @@ -507,6 +519,7 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { setWidth_SidebarWidget(sidebar, (float) width_Widget(root) / (float) gap_UI); setWidth_SidebarWidget(sidebar2, (float) width_Widget(root) / (float) gap_UI); } +#endif return iFalse; } else if (handleCommand_App(cmd)) { @@ -609,14 +622,14 @@ void updatePadding_Root(iRoot *d) { } } #endif - if (toolBar) { +// 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->widget, "sidebar"), 0, 0, 0, sidebarBottomPad); - setPadding_Widget(findChild_Widget(d->widget, "sidebar2"), 0, 0, 0, sidebarBottomPad); +// const int sidebarBottomPad = isPortrait_App() ? 11 * gap_UI + bottom : 0; +// 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. */ - } +// } /* Note that `handleNavBarCommands_` also adjusts padding and spacing. */ } @@ -1015,30 +1028,17 @@ static iBool handleToolBarCommands_(iWidget *toolBar, const char *cmd) { } else if (equal_Command(cmd, "toolbar.showview")) { /* TODO: Clean this up. */ - iWidget *sidebar = findWidget_App("sidebar"); - iWidget *sidebar2 = findWidget_App("sidebar2"); - dismissSidebar_(sidebar2, "toolbar.ident"); - const iBool isVisible = isVisible_Widget(sidebar); - // setFlags_Widget(findChild_Widget(toolBar, "toolbar.view"), noBackground_WidgetFlag, - // isVisible); +// iWidget *sidebar = findWidget_App("sidebar"); +// iWidget *sidebar2 = findWidget_App("sidebar2"); +// dismissSidebar_(sidebar2, "toolbar.ident"); +// const iBool isVisible = isVisible_Widget(sidebar); /* If a sidebar hasn't been shown yet, it's height is zero. */ - const int viewHeight = size_Root(get_Root()).y; +// const int viewHeight = size_Root(get_Root()).y; if (arg_Command(cmd) >= 0) { postCommandf_App("sidebar.mode arg:%d show:1", arg_Command(cmd)); -// if (!isVisible) { -// setVisualOffset_Widget(sidebar, viewHeight, 0, 0); -// setVisualOffset_Widget(sidebar, 0, 400, easeOut_AnimFlag | softer_AnimFlag); -// } } else { postCommandf_App("sidebar.toggle"); -// if (isVisible) { -// setVisualOffset_Widget(sidebar, height_Widget(sidebar), 250, easeIn_AnimFlag); -// } -// else { -// setVisualOffset_Widget(sidebar, viewHeight, 0, 0); -// setVisualOffset_Widget(sidebar, 0, 400, easeOut_AnimFlag | softer_AnimFlag); -// } } return iTrue; } @@ -1110,41 +1110,22 @@ void updateMetrics_Root(iRoot *d) { setFixedSize_Widget(appClose, appMin->rect.size); setFixedSize_Widget(appIcon, init_I2(appIconSize_Root(), appMin->rect.size.y)); } - iWidget *navBar = findChild_Widget(d->widget, "navbar"); -// iWidget *lock = findChild_Widget(navBar, "navbar.lock"); - iWidget *url = findChild_Widget(d->widget, "url"); - iWidget *rightEmbed = findChild_Widget(navBar, "url.rightembed"); - iWidget *embedPad = findChild_Widget(navBar, "url.embedpad"); - iWidget *urlButtons = findChild_Widget(navBar, "url.buttons"); + iWidget *navBar = findChild_Widget(d->widget, "navbar"); + iWidget *url = findChild_Widget(d->widget, "url"); + iWidget *rightEmbed = findChild_Widget(navBar, "url.rightembed"); + iWidget *embedPad = findChild_Widget(navBar, "url.embedpad"); + iWidget *urlButtons = findChild_Widget(navBar, "url.buttons"); + iLabelWidget *idName = findChild_Widget(d->widget, "toolbar.name"); setPadding_Widget(as_Widget(url), 0, gap_UI, 0, gap_UI); navBar->rect.size.y = 0; /* recalculate height based on children (FIXME: shouldn't be needed) */ -// updateSize_LabelWidget((iLabelWidget *) lock); -// updateSize_LabelWidget((iLabelWidget *) findChild_Widget(navBar, "reload")); -// arrange_Widget(urlButtons); setFixedSize_Widget(embedPad, init_I2(width_Widget(urlButtons) + gap_UI / 2, 1)); -// setContentPadding_InputWidget((iInputWidget *) url, width_Widget(lock) * 0.75, -// width_Widget(lock) * 0.75); rightEmbed->rect.pos.y = gap_UI; updatePadding_Root(d); arrange_Widget(d->widget); updateUrlInputContentPadding_(navBar); - /* Position the toolbar identity name label manually. */ { - iLabelWidget *idName = findChild_Widget(d->widget, "toolbar.name"); - if (idName) { - const iWidget *toolBar = findChild_Widget(d->widget, "toolbar"); - const iWidget *viewButton = findChild_Widget(d->widget, "toolbar.view"); - const iWidget *idButton = findChild_Widget(toolBar, "toolbar.ident"); -// const int font = uiLabelTiny_FontId; - setFixedSize_Widget(as_Widget(idName), init_I2(-1, 2 * gap_UI + lineHeight_Text(uiLabelTiny_FontId))); -// setFont_LabelWidget(idName, font); - /*setPos_Widget(as_Widget(idName), - windowToLocal_Widget(as_Widget(idName), - init_I2(left_Rect(bounds_Widget(idButton)), - bottom_Rect(bounds_Widget(viewButton)) - - lineHeight_Text(font) - gap_UI / 2))); - setFixedSize_Widget(as_Widget(idName), init_I2(width_Widget(idButton), - lineHeight_Text(font)));*/ - } + if (idName) { + setFixedSize_Widget(as_Widget(idName), + init_I2(-1, 2 * gap_UI + lineHeight_Text(uiLabelTiny_FontId))); } postRefresh_App(); } @@ -1168,11 +1149,9 @@ void createUserInterface_Root(iRoot *d) { setFlags_Widget( root, resizeChildren_WidgetFlag | fixedSize_WidgetFlag | focusRoot_WidgetFlag, iTrue); setCommandHandler_Widget(root, handleRootCommands_); - iWidget *div = makeVDiv_Widget(); setId_Widget(div, "navdiv"); addChild_Widget(root, iClob(div)); - #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) /* Window title bar. */ if (prefs_App()->customFrame) { @@ -1446,20 +1425,19 @@ void createUserInterface_Root(iRoot *d) { "newtab"); } /* Sidebars. */ { - iWidget *content = findChild_Widget(root, "tabs.content"); iSidebarWidget *sidebar1 = new_SidebarWidget(left_SidebarSide); - addChildPos_Widget(content, iClob(sidebar1), front_WidgetAddPos); if (deviceType_App() != phone_AppDeviceType) { + /* Sidebars are next to the tab content. */ + iWidget *content = findChild_Widget(root, "tabs.content"); + addChildPos_Widget(content, iClob(sidebar1), front_WidgetAddPos); iSidebarWidget *sidebar2 = new_SidebarWidget(right_SidebarSide); addChildPos_Widget(content, iClob(sidebar2), back_WidgetAddPos); } -#if 0 else { - /* The identities sidebar is always in the main area. */ - addChild_Widget(findChild_Widget(root, "stack"), iClob(sidebar2)); - setFlags_Widget(as_Widget(sidebar2), hidden_WidgetFlag, iTrue); + /* Sidebar is a slide-over. */ + addChild_Widget(/*findChild_Widget(root, "stack")*/ root, iClob(sidebar1)); + setFlags_Widget(as_Widget(sidebar1), hidden_WidgetFlag, iTrue); } -#endif } /* Lookup results. */ { iLookupWidget *lookup = new_LookupWidget(); diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 13fc33b1..401c5d25 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c @@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "paint.h" #include "root.h" #include "scrollwidget.h" +#include "touch.h" #include "util.h" #include "visited.h" @@ -99,13 +100,15 @@ struct Impl_SidebarWidget { iListWidget * list; iCertListWidget * certList; iWidget * actions; /* below the list, area for buttons */ + int midHeight; /* on portrait phone, the height for the middle state */ + iBool isBeingDraggedVertically; /* on portrait phone, sidebar can be dragged up/down */ int modeScroll[max_SidebarMode]; iLabelWidget * modeButtons[max_SidebarMode]; int maxButtonLabelWidth; float widthAsGaps; int buttonFont; int itemFonts[2]; - size_t numUnreadEntries; + size_t numUnreadEntries; iWidget * resizer; iWidget * menu; /* context menu for an item */ iWidget * modeMenu; /* context menu for the sidebar mode (no item) */ @@ -194,9 +197,9 @@ static iLabelWidget *addActionButton_SidebarWidget_(iSidebarWidget *d, const cha //(deviceType_App() != desktop_AppDeviceType ? // extraPadding_WidgetFlag : 0) | flags); - setFont_LabelWidget(btn, deviceType_App() == phone_AppDeviceType && d->side == right_SidebarSide - ? uiLabelBig_FontId - : d->buttonFont); + setFont_LabelWidget(btn, /*deviceType_App() == phone_AppDeviceType && d->side == right_SidebarSide + ? uiLabelBig_FontId : */ + d->buttonFont); checkIcon_LabelWidget(btn); return btn; } @@ -211,7 +214,12 @@ static iBool isBookmarkFolded_SidebarWidget_(const iSidebarWidget *d, const iBoo return iFalse; } +static iBool isSlidingSheet_SidebarWidget_(const iSidebarWidget *d) { + return isPortraitPhone_App();// && scrollPos_ListWidget(d->list) <= 0; +} + static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepActions) { + const iBool isMobile = (deviceType_App() != desktop_AppDeviceType); clear_ListWidget(d->list); releaseChildren_Widget(d->blank); if (!keepActions) { @@ -299,9 +307,10 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct } /* Actions. */ if (!keepActions) { - addActionButton_SidebarWidget_( - d, check_Icon " ${sidebar.action.feeds.markallread}", "feeds.markallread", expand_WidgetFlag | - tight_WidgetFlag); + addActionButton_SidebarWidget_(d, + check_Icon " ${sidebar.action.feeds.markallread}", + "feeds.markallread", + expand_WidgetFlag | tight_WidgetFlag); updateSize_LabelWidget(addChildFlags_Widget(d->actions, iClob(new_LabelWidget("${sidebar.action.show}", NULL)), frameless_WidgetFlag | tight_WidgetFlag)); @@ -617,6 +626,10 @@ void setClosedFolders_SidebarWidget(iSidebarWidget *d, const iIntSet *closedFold } } +void setMidHeight_SidebarWidget(iSidebarWidget *d, int midHeight) { + d->midHeight = midHeight; +} + enum iSidebarMode mode_SidebarWidget(const iSidebarWidget *d) { return d ? d->mode : 0; } @@ -686,6 +699,8 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) { d->side = side; d->mode = -1; d->feedsMode = all_FeedsMode; + d->midHeight = 0; + d->isBeingDraggedVertically = iFalse; d->numUnreadEntries = 0; d->buttonFont = uiLabel_FontId; /* wiil be changed later */ d->itemFonts[0] = uiContent_FontId; @@ -703,15 +718,24 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) { iWidget *vdiv = makeVDiv_Widget(); addChildFlags_Widget(w, vdiv, resizeToParentWidth_WidgetFlag | resizeToParentHeight_WidgetFlag); iZap(d->modeButtons); - d->resizer = NULL; - d->list = NULL; - d->certList = NULL; - d->actions = NULL; + d->resizer = NULL; + d->list = NULL; + d->certList = NULL; + d->actions = NULL; d->closedFolders = new_IntSet(); /* On a phone, the right sidebar is not used. */ - const iBool isPhone = deviceType_App() == phone_AppDeviceType; - //if (!isPhone || d->side == left_SidebarSide) { - iWidget *buttons = new_Widget(); + const iBool isPhone = (deviceType_App() == phone_AppDeviceType); + if (isPhone) { + iLabelWidget *closeButton = + addChildFlags_Widget(vdiv, + iClob(new_LabelWidget("${sidebar.close}", "sidebar.toggle")), + collapse_WidgetFlag | alignRight_WidgetFlag | + extraPadding_WidgetFlag | frameless_WidgetFlag); + as_Widget(closeButton)->flags2 |= slidingSheetDraggable_WidgetFlag2; /* phone */ + setId_Widget(as_Widget(closeButton), "sidebar.close"); + setFont_LabelWidget(closeButton, uiLabelBigBold_FontId); + } + iWidget *buttons = new_Widget(); setId_Widget(buttons, "buttons"); setDrawBufferEnabled_Widget(buttons, iTrue); for (int i = 0; i < max_SidebarMode; i++) { @@ -725,28 +749,14 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) { tightModeLabels_[i], format_CStr("%s.mode arg:%d", cstr_String(id_Widget(w)), i))), frameless_WidgetFlag | noBackground_WidgetFlag); + as_Widget(d->modeButtons[i])->flags2 |= slidingSheetDraggable_WidgetFlag2; /* phone */ } setButtonFont_SidebarWidget(d, isPhone ? uiLabelBig_FontId : uiLabel_FontId); addChildFlags_Widget(vdiv, iClob(buttons), - arrangeHorizontal_WidgetFlag | - resizeWidthOfChildren_WidgetFlag | - arrangeHeight_WidgetFlag | resizeToParentWidth_WidgetFlag); // | -// drawBackgroundToHorizontalSafeArea_WidgetFlag); + arrangeHorizontal_WidgetFlag | resizeWidthOfChildren_WidgetFlag | + arrangeHeight_WidgetFlag | resizeToParentWidth_WidgetFlag); setBackgroundColor_Widget(buttons, uiBackgroundSidebar_ColorId); -// } -#if 0 - else { - iLabelWidget *heading = new_LabelWidget(person_Icon " ${sidebar.identities}", NULL); - checkIcon_LabelWidget(heading); - setBackgroundColor_Widget(as_Widget(heading), uiBackgroundSidebar_ColorId); - setTextColor_LabelWidget(heading, uiTextSelected_ColorId); - setFont_LabelWidget(addChildFlags_Widget(vdiv, iClob(heading), borderTop_WidgetFlag | - alignLeft_WidgetFlag | frameless_WidgetFlag | - drawBackgroundToHorizontalSafeArea_WidgetFlag), - uiLabelLargeBold_FontId); - } -#endif iWidget *content = new_Widget(); setFlags_Widget(content, resizeChildren_WidgetFlag, iTrue); iWidget *listAndActions = makeVDiv_Widget(); @@ -756,15 +766,17 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) { d->list = new_ListWidget(); setPadding_Widget(as_Widget(d->list), 0, gap_UI, 0, gap_UI); addChild_Widget(listArea, iClob(d->list)); - d->certList = new_CertListWidget(); - setPadding_Widget(as_Widget(d->certList), 0, gap_UI, 0, gap_UI); - addChild_Widget(listArea, iClob(d->certList)); + if (!isPhone) { + d->certList = new_CertListWidget(); + setPadding_Widget(as_Widget(d->certList), 0, gap_UI, 0, gap_UI); + addChild_Widget(listArea, iClob(d->certList)); + } addChildFlags_Widget(listAndActions, iClob(listArea), expand_WidgetFlag); // | drawBackgroundToHorizontalSafeArea_WidgetFlag); setId_Widget(addChildPosFlags_Widget(listAndActions, iClob(d->actions = new_Widget()), - isPhone ? front_WidgetAddPos : back_WidgetAddPos, + /*isPhone ? front_WidgetAddPos :*/ back_WidgetAddPos, arrangeHorizontal_WidgetFlag | arrangeHeight_WidgetFlag | resizeWidthOfChildren_WidgetFlag), // | // drawBackgroundToHorizontalSafeArea_WidgetFlag), @@ -891,7 +903,7 @@ static void checkModeButtonLayout_SidebarWidget_(iSidebarWidget *d) { // updateMetrics_SidebarWidget_(d); updateItemHeight_SidebarWidget_(d); } - setButtonFont_SidebarWidget(d, isPortrait_App() ? uiLabelBig_FontId : uiLabel_FontId); + setButtonFont_SidebarWidget(d, isPortrait_App() ? uiLabelMedium_FontId : uiLabel_FontId); } const iBool isTight = (width_Rect(bounds_Widget(as_Widget(d->modeButtons[0]))) < d->maxButtonLabelWidth); @@ -982,6 +994,52 @@ iBool handleBookmarkEditorCommands_SidebarWidget_(iWidget *editor, const char *c return iFalse; } +static void animateSlidingSheetHeight_SidebarWidget_(iAny *sidebar) { + iWidget *d = sidebar; + const int oldSize = d->rect.size.y; + const int newSize = bottom_Rect(safeRect_Root(d->root)) - top_Rect(bounds_Widget(d)); + if (oldSize != newSize) { + d->rect.size.y = newSize; + arrange_Widget(d); + } +// printf("[%p] %u: %d animating %d\n", d, window_Widget(d)->frameTime, +// (flags_Widget(sidebar) & visualOffset_WidgetFlag) != 0, +// newSize); + if (!isFinished_Anim(&d->visualOffset)) { + addTicker_App(animateSlidingSheetHeight_SidebarWidget_, sidebar); + } +} + +enum iSlidingSheetPos { + top_SlidingSheetPos, + middle_SlidingSheetPos, + bottom_SlidingSheetPos, +}; + +static void setSlidingSheetPos_SidebarWidget_(iSidebarWidget *d, enum iSlidingSheetPos slide) { + iWidget *w = as_Widget(d); + const int pos = w->rect.pos.y; + const iRect safeRect = safeRect_Root(w->root); + if (slide == top_SlidingSheetPos) { + w->rect.pos.y = top_Rect(safeRect); + w->rect.size.y = height_Rect(safeRect); + setVisualOffset_Widget(w, pos - w->rect.pos.y, 0, 0); + setVisualOffset_Widget(w, 0, 200, easeOut_AnimFlag | softer_AnimFlag); + setScrollMode_ListWidget(d->list, disabledAtTopUpwards_ScrollMode); + } + else if (slide == bottom_SlidingSheetPos) { + postCommand_Widget(w, "sidebar.toggle"); + } + else { + w->rect.size.y = d->midHeight; + w->rect.pos.y = height_Rect(safeRect) - w->rect.size.y; + setVisualOffset_Widget(w, pos - w->rect.pos.y, 0, 0); + setVisualOffset_Widget(w, 0, 200, easeOut_AnimFlag | softer_AnimFlag); + setScrollMode_ListWidget(d->list, disabledAtTopBothDirections_ScrollMode); + } + animateSlidingSheetHeight_SidebarWidget_(d); +} + static iBool handleSidebarCommand_SidebarWidget_(iSidebarWidget *d, const char *cmd) { iWidget *w = as_Widget(d); if (equal_Command(cmd, "width")) { @@ -1011,35 +1069,58 @@ static iBool handleSidebarCommand_SidebarWidget_(iSidebarWidget *d, const char * argLabel_Command(cmd, "noanim") == 0 && (d->side == left_SidebarSide || deviceType_App() != phone_AppDeviceType); int visX = 0; + int visY = 0; if (isVisible_Widget(w)) { visX = left_Rect(bounds_Widget(w)) - left_Rect(w->root->widget->rect); + visY = top_Rect(bounds_Widget(w)) - top_Rect(w->root->widget->rect); } - setFlags_Widget(w, hidden_WidgetFlag, isVisible_Widget(w)); + const iBool isHiding = isVisible_Widget(w); + setFlags_Widget(w, hidden_WidgetFlag, isHiding); /* Safe area inset for mobile. */ const int safePad = (d->side == left_SidebarSide ? left_Rect(safeRect_Root(w->root)) : 0); - if (isVisible_Widget(w)) { - setFlags_Widget(w, keepOnTop_WidgetFlag, iFalse); - w->rect.size.x = d->widthAsGaps * gap_UI; - invalidate_ListWidget(d->list); - if (isAnimated) { + const int animFlags = easeOut_AnimFlag | softer_AnimFlag; + if (!isPortraitPhone_App()) { + if (!isHiding) { + setFlags_Widget(w, keepOnTop_WidgetFlag, iFalse); + w->rect.size.x = d->widthAsGaps * gap_UI; + invalidate_ListWidget(d->list); + if (isAnimated) { + setFlags_Widget(w, horizontalOffset_WidgetFlag, iTrue); + setVisualOffset_Widget( + w, (d->side == left_SidebarSide ? -1 : 1) * (w->rect.size.x + safePad), 0, 0); + setVisualOffset_Widget(w, 0, 300, animFlags); + } + } + else if (isAnimated) { setFlags_Widget(w, horizontalOffset_WidgetFlag, iTrue); - setVisualOffset_Widget( - w, (d->side == left_SidebarSide ? -1 : 1) * (w->rect.size.x + safePad), 0, 0); - setVisualOffset_Widget(w, 0, 300, easeOut_AnimFlag | softer_AnimFlag); + if (d->side == right_SidebarSide) { + setVisualOffset_Widget(w, visX, 0, 0); + setVisualOffset_Widget( + w, visX + w->rect.size.x + safePad, 300, animFlags); + } + else { + setFlags_Widget(w, keepOnTop_WidgetFlag, iTrue); + setVisualOffset_Widget( + w, -w->rect.size.x - safePad, 300, animFlags); + } } + setScrollMode_ListWidget(d->list, normal_ScrollMode); } - 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 + safePad, 300, easeOut_AnimFlag | softer_AnimFlag); + else { + /* Portrait phone sidebar works differently: it slides up from the bottom. */ + setFlags_Widget(w, horizontalOffset_WidgetFlag, iFalse); + if (!isHiding) { + invalidate_ListWidget(d->list); + w->rect.pos.y = height_Rect(safeRect_Root(w->root)) - d->midHeight; + setVisualOffset_Widget(w, bottom_Rect(rect_Root(w->root)) - w->rect.pos.y, 0, 0); + setVisualOffset_Widget(w, 0, 300, animFlags); + animateSlidingSheetHeight_SidebarWidget_(d); + setScrollMode_ListWidget(d->list, disabledAtTopBothDirections_ScrollMode); } else { - setFlags_Widget(w, keepOnTop_WidgetFlag, iTrue); - setVisualOffset_Widget( - w, -w->rect.size.x - safePad, 300, easeOut_AnimFlag | softer_AnimFlag); + setVisualOffset_Widget(w, bottom_Rect(rect_Root(w->root)) - w->rect.pos.y, 300, animFlags); } + showToolbar_Root(w->root, isHiding); } updateToolbarColors_Root(w->root); arrange_Widget(w->parent); @@ -1097,13 +1178,32 @@ static size_t numBookmarks_(const iPtrArray *bmList) { return num; } +static iRangei SlidingSheetMiddleRegion_SidebarWidget_(const iSidebarWidget *d) { + const iWidget *w = constAs_Widget(d); + const iRect safeRect = safeRect_Root(w->root); + const int midY = bottom_Rect(safeRect) - d->midHeight; + const int topHalf = (top_Rect(safeRect) + midY) / 2; + const int bottomHalf = (bottom_Rect(safeRect) + midY * 2) / 3; + return (iRangei){ topHalf, bottomHalf }; +} + +static void gotoNearestSlidingSheetPos_SidebarWidget_(iSidebarWidget *d) { + const iRangei midRegion = SlidingSheetMiddleRegion_SidebarWidget_(d); + const int pos = top_Rect(d->widget.rect); + setSlidingSheetPos_SidebarWidget_(d, pos < midRegion.start + ? top_SlidingSheetPos + : pos > midRegion.end ? bottom_SlidingSheetPos + : middle_SlidingSheetPos); +} + static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) { iWidget *w = as_Widget(d); /* Handle commands. */ if (isResize_UserEvent(ev)) { checkModeButtonLayout_SidebarWidget_(d); - if (deviceType_App() == phone_AppDeviceType && d->side == left_SidebarSide) { - setFlags_Widget(w, rightEdgeDraggable_WidgetFlag, isPortrait_App()); + if (deviceType_App() == phone_AppDeviceType) { // && d->side == left_SidebarSide) { +// setFlags_Widget(w, rightEdgeDraggable_WidgetFlag, isPortrait_App()); + setFlags_Widget(findChild_Widget(w, "sidebar.close"), hidden_WidgetFlag, isLandscape_App()); /* In landscape, visibility of the toolbar is controlled separately. */ if (isVisible_Widget(w)) { postCommand_Widget(w, "sidebar.toggle"); @@ -1117,6 +1217,10 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) setFlags_Widget(as_Widget(d->list), drawBackgroundToHorizontalSafeArea_WidgetFlag, isLandscape_App()); + setFlags_Widget(w, + drawBackgroundToBottom_WidgetFlag, + isPortrait_App()); + setBackgroundColor_Widget(w, isPortrait_App() ? uiBackgroundSidebar_ColorId : none_ColorId); return iFalse; } } @@ -1572,6 +1676,61 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) return iTrue; } } + if (isSlidingSheet_SidebarWidget_(d)) { + if (ev->type == SDL_MOUSEWHEEL) { + enum iWidgetTouchMode touchMode = widgetMode_Touch(w); + if (touchMode == momentum_WidgetTouchMode) { + /* We don't do momentum. */ + float swipe = stopWidgetMomentum_Touch(w); +// printf("swipe: %f\n", swipe); + const iRangei midRegion = SlidingSheetMiddleRegion_SidebarWidget_(d); + const int pos = top_Rect(w->rect); + if (swipe < 500) { + gotoNearestSlidingSheetPos_SidebarWidget_(d); + } + else if (swipe > 6500 && ev->wheel.y > 0) { + /* Fast swipe down will dismiss. */ + setSlidingSheetPos_SidebarWidget_(d, bottom_SlidingSheetPos); + } + else if (ev->wheel.y < 0) { + setSlidingSheetPos_SidebarWidget_(d, top_SlidingSheetPos); + } + else if (pos < (midRegion.start + midRegion.end) / 2) { + setSlidingSheetPos_SidebarWidget_(d, middle_SlidingSheetPos); + } + else { + setSlidingSheetPos_SidebarWidget_(d, bottom_SlidingSheetPos); + } + } + else if (touchMode == touch_WidgetTouchMode) { + /* Move with the finger. */ + adjustEdges_Rect(&w->rect, ev->wheel.y, 0, 0, 0); + /* Upon reaching the top, scrolling is switched back to the list. */ + const iRect rootRect = safeRect_Root(w->root); + const int top = top_Rect(rootRect); + if (w->rect.pos.y < top) { + setScrollMode_ListWidget(d->list, disabledAtTopUpwards_ScrollMode); + setScrollPos_ListWidget(d->list, top - w->rect.pos.y); + transferAffinity_Touch(w, as_Widget(d->list)); + w->rect.pos.y = top; + w->rect.size.y = height_Rect(rootRect); + } + else { + setScrollMode_ListWidget(d->list, disabledAtTopBothDirections_ScrollMode); + } + arrange_Widget(w); + refresh_Widget(w); + } + else { + return iFalse; + } + return iTrue; + } + if (ev->type == SDL_USEREVENT && ev->user.code == widgetTouchEnds_UserEventCode) { + gotoNearestSlidingSheetPos_SidebarWidget_(d); + return iTrue; + } + } if (ev->type == SDL_MOUSEBUTTONDOWN && contains_Widget(as_Widget(d->list), init_I2(ev->button.x, ev->button.y))) { if (hoverItem_ListWidget(d->list) || isVisible_Widget(d->menu)) { diff --git a/src/ui/sidebarwidget.h b/src/ui/sidebarwidget.h index 81c6681f..2a930a60 100644 --- a/src/ui/sidebarwidget.h +++ b/src/ui/sidebarwidget.h @@ -54,6 +54,7 @@ iBool setMode_SidebarWidget (iSidebarWidget *, enum iSidebar void setWidth_SidebarWidget (iSidebarWidget *, float widthAsGaps); iBool setButtonFont_SidebarWidget (iSidebarWidget *, int font); void setClosedFolders_SidebarWidget (iSidebarWidget *, const iIntSet *closedFolders); +void setMidHeight_SidebarWidget (iSidebarWidget *, int midHeight); /* phone layout */ enum iSidebarMode mode_SidebarWidget (const iSidebarWidget *); enum iFeedsMode feedsMode_SidebarWidget (const iSidebarWidget *); diff --git a/src/ui/touch.c b/src/ui/touch.c index 195d1dff..aee5a383 100644 --- a/src/ui/touch.c +++ b/src/ui/touch.c @@ -589,9 +589,18 @@ iBool processEvent_Touch(const SDL_Event *ev) { divvf_F3(&touch->accum, 6); divfv_I2(&pixels, 6); /* Allow scrolling a scrollable widget. */ - iWidget *flow = findOverflowScrollable_Widget(touch->affinity); - if (flow) { - touch->affinity = flow; + if (touch->affinity && touch->affinity->flags2 & slidingSheetDraggable_WidgetFlag2) { + extern iWidgetClass Class_SidebarWidget; /* The only type of sliding sheet for now. */ + iWidget *slider = findParentClass_Widget(touch->affinity, &Class_SidebarWidget); + if (slider) { + touch->affinity = slider; + } + } + else { + iWidget *flow = findOverflowScrollable_Widget(touch->affinity); + if (flow) { + touch->affinity = flow; + } } } else { @@ -617,11 +626,13 @@ iBool processEvent_Touch(const SDL_Event *ev) { if (touch->axis == y_TouchAxis) { pixels.x = 0; } -// printf("%p (%s) py: %i wy: %f acc: %f edge: %d\n", -// touch->affinity, -// class_Widget(touch->affinity)->name, -// pixels.y, y_F3(amount), y_F3(touch->accum), -// touch->edge); +#if 0 + printf("%p (%s) py: %i wy: %f acc: %f edge: %d\n", + touch->affinity, + class_Widget(touch->affinity)->name, + pixels.y, y_F3(amount), y_F3(touch->accum), + touch->edge); +#endif if (pixels.x || pixels.y) { //setFocus_Widget(NULL); dispatchMotion_Touch_(touch->startPos /*pos[0]*/, 0); @@ -801,6 +812,16 @@ void widgetDestroyed_Touch(iWidget *widget) { } } +void transferAffinity_Touch(iWidget *src, iWidget *dst) { + iTouchState *d = touchState_(); + iForEach(Array, i, d->touches) { + iTouch *touch = i.value; + if (touch->affinity == src) { + touch->affinity = dst; + } + } +} + iInt2 latestPosition_Touch(void) { return touchState_()->currentTouchPos; } diff --git a/src/ui/touch.h b/src/ui/touch.h index e048224a..c9c76d86 100644 --- a/src/ui/touch.h +++ b/src/ui/touch.h @@ -39,6 +39,7 @@ void update_Touch (void); float stopWidgetMomentum_Touch (const iWidget *widget); enum iWidgetTouchMode widgetMode_Touch (const iWidget *widget); void widgetDestroyed_Touch (iWidget *widget); +void transferAffinity_Touch (iWidget *src, iWidget *dst); iInt2 latestPosition_Touch (void); /* valid during processing of current event */ iBool isHovering_Touch (void); /* stationary touch or a long-press drag ongoing */ diff --git a/src/ui/widget.c b/src/ui/widget.c index 210fe899..0d20cca9 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -124,6 +124,7 @@ void init_Widget(iWidget *d) { init_String(&d->id); d->root = get_Root(); /* never changes after this */ d->flags = 0; + d->flags2 = 0; d->rect = zero_Rect(); d->minSize = zero_I2(); d->sizeRef = NULL; diff --git a/src/ui/widget.h b/src/ui/widget.h index 4025f5c5..35be1bcb 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -123,6 +123,10 @@ enum iWidgetFlag { #define refChildrenOffset_WidgetFlag iBit64(63) /* visual offset determined by the offset of referenced children */ #define nativeMenu_WidgetFlag iBit64(64) +enum iWidgetFlag2 { + slidingSheetDraggable_WidgetFlag2 = iBit(1), +}; + enum iWidgetAddPos { back_WidgetAddPos, front_WidgetAddPos, @@ -139,6 +143,7 @@ struct Impl_Widget { iObject object; iString id; int64_t flags; + int flags2; iRect rect; iInt2 minSize; iWidget * sizeRef; -- cgit v1.2.3 From 8c0ce575d06e10ac9f2ec60c0816443005533d53 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sat, 4 Dec 2021 19:08:36 +0200 Subject: iOS: Position system input controls during animation --- src/app.c | 12 +++++++++++- src/ui/inputwidget.c | 12 ++++++++++++ src/ui/root.c | 8 ++++++++ src/ui/root.h | 7 +++++++ src/ui/widget.c | 1 + 5 files changed, 39 insertions(+), 1 deletion(-) (limited to 'src/ui/widget.c') diff --git a/src/app.c b/src/app.c index 587efd00..52072d39 100644 --- a/src/app.c +++ b/src/app.c @@ -1455,11 +1455,17 @@ backToMainLoop:; static void runTickers_App_(iApp *d) { const uint32_t now = SDL_GetTicks(); d->elapsedSinceLastTicker = (d->lastTickerTime ? now - d->lastTickerTime : 0); - d->lastTickerTime = now; + d->lastTickerTime = now; if (isEmpty_SortedArray(&d->tickers)) { d->lastTickerTime = 0; return; } + iForIndices(i, d->window->base.roots) { + iRoot *root = d->window->base.roots[i]; + if (root) { + root->didAnimateVisualOffsets = iFalse; + } + } /* Tickers may add themselves again, so we'll run off a copy. */ iSortedArray *pending = copy_SortedArray(&d->tickers); clear_SortedArray(&d->tickers); @@ -1476,6 +1482,10 @@ static void runTickers_App_(iApp *d) { if (isEmpty_SortedArray(&d->tickers)) { d->lastTickerTime = 0; } + iForIndices(i, d->window->base.roots) { + iRoot *root = d->window->base.roots[i]; + notifyVisualOffsetChange_Root(root); + } } static int resizeWatcher_(void *user, SDL_Event *event) { diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index bb3851df..e72ed361 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c @@ -756,6 +756,16 @@ void deinit_InputWidget(iInputWidget *d) { deinit_Array(&d->lines); } +#if defined (LAGRANGE_ENABLE_SYSTEM_INPUT) +static void updateAfterVisualOffsetChange_InputWidget_(iInputWidget *d, iRoot *root) { + iAssert(as_Widget(d)->root == root); + iUnused(root); + if (d->sysCtrl) { + setRect_SystemTextInput(d->sysCtrl, contentBounds_InputWidget_(d)); + } +} +#endif + void setFont_InputWidget(iInputWidget *d, int fontId) { d->font = fontId; updateMetrics_InputWidget_(d); @@ -1047,6 +1057,7 @@ void begin_InputWidget(iInputWidget *d) { setRect_SystemTextInput(d->sysCtrl, contentBounds_InputWidget_(d)); setText_SystemTextInput(d->sysCtrl, &d->oldText); setTextChangedFunc_SystemTextInput(d->sysCtrl, systemInputChanged_InputWidget_, d); + iConnect(Root, w->root, visualOffsetsChanged, d, updateAfterVisualOffsetChange_InputWidget_); return; #endif if (d->mode == overwrite_InputMode) { @@ -1080,6 +1091,7 @@ void end_InputWidget(iInputWidget *d, iBool accept) { return; } if (d->sysCtrl) { + iDisconnect(Root, w->root, visualOffsetsChanged, d, updateAfterVisualOffsetChange_InputWidget_); if (accept) { splitToLines_(text_SystemTextInput(d->sysCtrl), &d->lines); } diff --git a/src/ui/root.c b/src/ui/root.c index 0e949246..5a579eb4 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -241,6 +241,7 @@ static int loadAnimIndex_ = 0; static iRoot * activeRoot_ = NULL; iDefineTypeConstruction(Root) +iDefineAudienceGetter(Root, visualOffsetsChanged) void init_Root(iRoot *d) { iZap(*d); @@ -250,6 +251,7 @@ void deinit_Root(iRoot *d) { iReleasePtr(&d->widget); delete_PtrArray(d->onTop); delete_PtrSet(d->pendingDestruction); + delete_Audience(d->visualOffsetsChanged); } void setCurrent_Root(iRoot *root) { @@ -658,6 +660,12 @@ void updateToolbarColors_Root(iRoot *d) { #endif } +void notifyVisualOffsetChange_Root(iRoot *d) { + if (d && d->didAnimateVisualOffsets) { + iNotifyAudience(d, visualOffsetsChanged, RootVisualOffsetsChanged); + } +} + void dismissPortraitPhoneSidebars_Root(iRoot *d) { if (deviceType_App() == phone_AppDeviceType && isPortrait_App()) { iWidget *sidebar = findChild_Widget(d->widget, "sidebar"); diff --git a/src/ui/root.h b/src/ui/root.h index 851d927d..2419b599 100644 --- a/src/ui/root.h +++ b/src/ui/root.h @@ -2,11 +2,15 @@ #include "widget.h" #include "color.h" +#include #include #include iDeclareType(Root) +iDeclareNotifyFunc(Root, VisualOffsetsChanged) +iDeclareAudienceGetter(Root, visualOffsetsChanged) + struct Impl_Root { iWidget * widget; iWindow * window; @@ -14,6 +18,8 @@ struct Impl_Root { iPtrSet * pendingDestruction; iBool pendingArrange; int loadAnimTimer; + iBool didAnimateVisualOffsets; + iAudience *visualOffsetsChanged; /* called after running tickers */ iColor tmPalette[tmMax_ColorId]; /* theme-specific palette */ }; @@ -36,6 +42,7 @@ void updatePadding_Root (iRoot *); /* TODO: is part of m void dismissPortraitPhoneSidebars_Root (iRoot *); void showToolbar_Root (iRoot *, iBool show); void updateToolbarColors_Root (iRoot *); +void notifyVisualOffsetChange_Root (iRoot *); iInt2 size_Root (const iRoot *); iRect rect_Root (const iRoot *); diff --git a/src/ui/widget.c b/src/ui/widget.c index 0d20cca9..225c0480 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -142,6 +142,7 @@ void init_Widget(iWidget *d) { static void visualOffsetAnimation_Widget_(void *ptr) { iWidget *d = ptr; postRefresh_App(); + d->root->didAnimateVisualOffsets = iTrue; if (!isFinished_Anim(&d->visualOffset)) { addTicker_App(visualOffsetAnimation_Widget_, ptr); } -- cgit v1.2.3 From 14e4bd38636f7dccd8a22d868cf82134592a98db Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sun, 5 Dec 2021 18:31:52 +0200 Subject: Mobile: Fixed issues with overflow-scrolling --- src/app.c | 12 +++++++++++- src/ui/root.c | 2 +- src/ui/root.h | 1 + src/ui/widget.c | 5 ++++- 4 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src/ui/widget.c') diff --git a/src/app.c b/src/app.c index 52072d39..5a76ba45 100644 --- a/src/app.c +++ b/src/app.c @@ -1484,7 +1484,9 @@ static void runTickers_App_(iApp *d) { } iForIndices(i, d->window->base.roots) { iRoot *root = d->window->base.roots[i]; - notifyVisualOffsetChange_Root(root); + if (root) { + notifyVisualOffsetChange_Root(root); + } } } @@ -1558,6 +1560,14 @@ void refresh_App(void) { iConstForEach(PtrArray, j, &windows) { iWindow *win = j.ptr; setCurrent_Window(win); + iForIndices(i, win->roots) { + iRoot *root = win->roots[i]; + if (root && root->didOverflowScroll) { + /* Some widgets may need a just-in-time visual update. */ + notifyVisualOffsetChange_Root(root); + root->didOverflowScroll = iFalse; + } + } switch (win->type) { case main_WindowType: // iTime draw; diff --git a/src/ui/root.c b/src/ui/root.c index e2706898..28aa4b92 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -661,7 +661,7 @@ void updateToolbarColors_Root(iRoot *d) { } void notifyVisualOffsetChange_Root(iRoot *d) { - if (d && d->didAnimateVisualOffsets) { + if (d && (d->didAnimateVisualOffsets || d->didOverflowScroll)) { iNotifyAudience(d, visualOffsetsChanged, RootVisualOffsetsChanged); } } diff --git a/src/ui/root.h b/src/ui/root.h index 2419b599..2f0d72c9 100644 --- a/src/ui/root.h +++ b/src/ui/root.h @@ -19,6 +19,7 @@ struct Impl_Root { iBool pendingArrange; int loadAnimTimer; iBool didAnimateVisualOffsets; + iBool didOverflowScroll; iAudience *visualOffsetsChanged; /* called after running tickers */ iColor tmPalette[tmMax_ColorId]; /* theme-specific palette */ }; diff --git a/src/ui/widget.c b/src/ui/widget.c index 225c0480..bb3a39f1 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -1203,6 +1203,9 @@ iBool scrollOverflow_Widget(iWidget *d, int delta) { bounds.pos.y = iMin(bounds.pos.y, validPosRange.end); } // printf("range: %d ... %d\n", range.start, range.end); + if (delta) { + d->root->didOverflowScroll = iTrue; /* ensure that widgets update if needed */ + } } else { bounds.pos.y = iClamp(bounds.pos.y, validPosRange.start, validPosRange.end); @@ -1871,7 +1874,7 @@ iAny *findParentClass_Widget(const iWidget *d, const iAnyClass *class) { } iAny *findOverflowScrollable_Widget(iWidget *d) { - const iRect rootRect = rect_Root(d->root); + const iRect rootRect = visibleRect_Root(d->root); for (iWidget *w = d; w; w = parent_Widget(w)) { if (flags_Widget(w) & overflowScrollable_WidgetFlag) { const iRect bounds = boundsWithoutVisualOffset_Widget(w); -- cgit v1.2.3 From e5464259ffe9a6834ee1f4913965089112e9eecb Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sun, 5 Dec 2021 22:04:44 +0200 Subject: Widget: Added flag to always fade the background --- src/ui/root.c | 4 ++++ src/ui/widget.c | 3 ++- src/ui/widget.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/ui/widget.c') diff --git a/src/ui/root.c b/src/ui/root.c index 28aa4b92..18a71200 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -490,6 +490,7 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { /* Place the sidebar next to or under doctabs depending on orientation. */ iSidebarWidget *sidebar = findChild_Widget(root, "sidebar"); removeChild_Widget(parent_Widget(sidebar), sidebar); + iChangeFlags(as_Widget(sidebar)->flags2, fadeBackground_WidgetFlag2, isPortrait_App()); if (isLandscape_App()) { setVisualOffset_Widget(as_Widget(sidebar), 0, 0, 0); addChildPos_Widget(findChild_Widget(root, "tabs.content"), iClob(sidebar), front_WidgetAddPos); @@ -829,6 +830,8 @@ static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) { } else if (equal_Command(cmd, "navbar.clear")) { iInputWidget *url = findChild_Widget(navBar, "url"); + setText_InputWidget(url, collectNew_String()); +#if 0 selectAll_InputWidget(url); /* Emulate a Backspace keypress. */ class_InputWidget(url)->processEvent( @@ -837,6 +840,7 @@ static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) { .timestamp = SDL_GetTicks(), .state = SDL_PRESSED, .keysym = { .sym = SDLK_BACKSPACE } }); +#endif return iTrue; } else if (equal_Command(cmd, "navbar.cancel")) { diff --git a/src/ui/widget.c b/src/ui/widget.c index bb3a39f1..9f1c8640 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -1393,7 +1393,8 @@ void drawLayerEffects_Widget(const iWidget *d) { shadowBorder = iFalse; } } - const iBool isFaded = fadeBackground && ~d->flags & noFadeBackground_WidgetFlag; + const iBool isFaded = (fadeBackground && ~d->flags & noFadeBackground_WidgetFlag) || + (d->flags2 & fadeBackground_WidgetFlag2); if (shadowBorder && ~d->flags & noShadowBorder_WidgetFlag) { iPaint p; init_Paint(&p); diff --git a/src/ui/widget.h b/src/ui/widget.h index 35be1bcb..9c4c44fb 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -125,6 +125,7 @@ enum iWidgetFlag { enum iWidgetFlag2 { slidingSheetDraggable_WidgetFlag2 = iBit(1), + fadeBackground_WidgetFlag2 = iBit(2), }; enum iWidgetAddPos { -- cgit v1.2.3 From d3595f9c51adf498e9d3b3cec4e9a3849bf56311 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 14 Dec 2021 15:06:38 +0200 Subject: Widget: Checking if visual offset applies --- src/ui/widget.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/ui/widget.c') diff --git a/src/ui/widget.c b/src/ui/widget.c index 9f1c8640..0c3b1c8a 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -1980,6 +1980,9 @@ iBool isAffectedByVisualOffset_Widget(const iWidget *d) { if (w->flags & visualOffset_WidgetFlag) { return iTrue; } + if (visualOffsetByReference_Widget(w) != 0) { + return iTrue; + } } return iFalse; } -- cgit v1.2.3 From 0ea78766ba6d189cb70c94acc798c4f4c74be935 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 14 Dec 2021 16:43:10 +0200 Subject: Widget: More efficient size change notifications Only notify once, after the arrangement is done. --- src/ui/widget.c | 26 ++++++++++++++++++++------ src/ui/widget.h | 1 + 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'src/ui/widget.c') diff --git a/src/ui/widget.c b/src/ui/widget.c index 0c3b1c8a..8cb2cf02 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -126,6 +126,7 @@ void init_Widget(iWidget *d) { d->flags = 0; d->flags2 = 0; d->rect = zero_Rect(); + d->oldSize = zero_I2(); d->minSize = zero_I2(); d->sizeRef = NULL; d->offsetRef = NULL; @@ -420,9 +421,10 @@ static iBool setWidth_Widget_(iWidget *d, int width) { if (d->rect.size.x != width) { d->rect.size.x = width; TRACE(d, "width has changed to %d", width); - if (class_Widget(d)->sizeChanged) { - class_Widget(d)->sizeChanged(d); - } +// if (~d->flags2 & undefinedWidth_WidgetFlag2 && class_Widget(d)->sizeChanged) { +// class_Widget(d)->sizeChanged(d); +// } +// d->flags2 &= ~undefinedWidth_WidgetFlag2; return iTrue; } } @@ -443,9 +445,10 @@ static iBool setHeight_Widget_(iWidget *d, int height) { 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); - } +// if (~d->flags2 & undefinedHeight_WidgetFlag2 && class_Widget(d)->sizeChanged) { +// class_Widget(d)->sizeChanged(d); +// } +// d->flags2 &= ~undefinedHeight_WidgetFlag2; return iTrue; } } @@ -842,6 +845,7 @@ static void arrange_Widget_(iWidget *d) { } static void resetArrangement_Widget_(iWidget *d) { + d->oldSize = d->rect.size; if (d->flags & resizeToParentWidth_WidgetFlag) { d->rect.size.x = 0; } @@ -878,6 +882,15 @@ static void resetArrangement_Widget_(iWidget *d) { } } +static void notifySizeChanged_Widget_(iWidget *d) { + if (class_Widget(d)->sizeChanged && !isEqual_I2(d->rect.size, d->oldSize)) { + class_Widget(d)->sizeChanged(d); + } + iForEach(ObjectList, child, d->children) { + notifySizeChanged_Widget_(child.object); + } +} + void arrange_Widget(iWidget *d) { if (d) { #if !defined (NDEBUG) @@ -887,6 +900,7 @@ void arrange_Widget(iWidget *d) { #endif resetArrangement_Widget_(d); /* back to initial default sizes */ arrange_Widget_(d); + notifySizeChanged_Widget_(d); } } diff --git a/src/ui/widget.h b/src/ui/widget.h index 9c4c44fb..4ab8d602 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -146,6 +146,7 @@ struct Impl_Widget { int64_t flags; int flags2; iRect rect; + iInt2 oldSize; /* in previous arrangement; for notification */ iInt2 minSize; iWidget * sizeRef; iWidget * offsetRef; -- cgit v1.2.3 From 4dee43aa5c460850268c1acea263d4ff510e7c15 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 14 Dec 2021 21:43:08 +0200 Subject: iOS: Fixed input positioning (non-animated widget) If there were no entry animation, the native UI control would not be correctly placed. --- src/ui/root.c | 2 +- src/ui/root.h | 2 +- src/ui/widget.c | 3 ++- src/ui/window.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/ui/widget.c') diff --git a/src/ui/root.c b/src/ui/root.c index a9bc7feb..04586bac 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -688,7 +688,7 @@ void updateToolbarColors_Root(iRoot *d) { } void notifyVisualOffsetChange_Root(iRoot *d) { - if (d && (d->didAnimateVisualOffsets || d->didOverflowScroll)) { + if (d && (d->didAnimateVisualOffsets || d->didChangeArrangement)) { iNotifyAudience(d, visualOffsetsChanged, RootVisualOffsetsChanged); } } diff --git a/src/ui/root.h b/src/ui/root.h index 2f0d72c9..7e831be3 100644 --- a/src/ui/root.h +++ b/src/ui/root.h @@ -19,7 +19,7 @@ struct Impl_Root { iBool pendingArrange; int loadAnimTimer; iBool didAnimateVisualOffsets; - iBool didOverflowScroll; + iBool didChangeArrangement; iAudience *visualOffsetsChanged; /* called after running tickers */ iColor tmPalette[tmMax_ColorId]; /* theme-specific palette */ }; diff --git a/src/ui/widget.c b/src/ui/widget.c index 8cb2cf02..df74a744 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -901,6 +901,7 @@ void arrange_Widget(iWidget *d) { resetArrangement_Widget_(d); /* back to initial default sizes */ arrange_Widget_(d); notifySizeChanged_Widget_(d); + d->root->didChangeArrangement = iTrue; } } @@ -1218,7 +1219,7 @@ iBool scrollOverflow_Widget(iWidget *d, int delta) { } // printf("range: %d ... %d\n", range.start, range.end); if (delta) { - d->root->didOverflowScroll = iTrue; /* ensure that widgets update if needed */ + d->root->didChangeArrangement = iTrue; /* ensure that widgets update if needed */ } } else { diff --git a/src/ui/window.c b/src/ui/window.c index 76dd1105..a4929f51 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -1265,7 +1265,7 @@ void draw_MainWindow(iMainWindow *d) { if (root) { /* Some widgets may need a just-in-time visual update. */ notifyVisualOffsetChange_Root(root); - root->didOverflowScroll = iFalse; + root->didChangeArrangement = iFalse; } } if (isExposed_Window(w)) { -- cgit v1.2.3 From 8298f3fc47d2c859ffd1cd72f6b4b0c480565bcf Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Fri, 17 Dec 2021 07:04:07 +0200 Subject: DocumentWidget: Swipe animation glitches Most crucially, sometimes the swipe placeholders would not get deleted at all because the visual offset animation was not finishing as expected. This would cause a number of problems with the document behavior. --- src/ui/documentwidget.c | 30 ++++++++++++++++++++++-------- src/ui/widget.c | 12 +++++++++++- 2 files changed, 33 insertions(+), 9 deletions(-) (limited to 'src/ui/widget.c') diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index f4e56d63..d0a9a55d 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -445,6 +445,8 @@ void cancelAllRequests_DocumentWidget(iDocumentWidget *d) { } void deinit_DocumentWidget(iDocumentWidget *d) { +// printf("\n* * * * * * * *\nDEINIT DOCUMENT: %s\n* * * * * * * *\n\n", +// cstr_String(&d->widget.id)); fflush(stdout); cancelAllRequests_DocumentWidget(d); pauseAllPlayers_Media(media_GmDocument(d->doc), iTrue); removeTicker_App(animate_DocumentWidget_, d); @@ -2690,12 +2692,17 @@ static void setupSwipeOverlay_DocumentWidget_(iDocumentWidget *d, iWidget *overl const int toPos = width_Widget(overlay); setVisualOffset_Widget(overlay, fromPos, 0, 0); /* Bigger screen, faster swipes. */ - const float devFactor = (deviceType_App() == phone_AppDeviceType ? 1.0f : 2.0f); - float swipe = iClamp(d->swipeSpeed, devFactor * 400, devFactor * 1000) * gap_UI; - uint32_t span = ((toPos - fromPos) / swipe) * 1000; -// printf("from:%d to:%d swipe:%f span:%u\n", fromPos, toPos, d->swipeSpeed, span); - setVisualOffset_Widget(overlay, toPos, span, deviceType_App() == tablet_AppDeviceType ? - easeOut_AnimFlag : 0); + if (deviceType_App() == desktop_AppDeviceType) { + setVisualOffset_Widget(overlay, toPos, 250, easeOut_AnimFlag | softer_AnimFlag); + } + else { + const float devFactor = (deviceType_App() == phone_AppDeviceType ? 1.0f : 2.0f); + float swipe = iClamp(d->swipeSpeed, devFactor * 400, devFactor * 1000) * gap_UI; + uint32_t span = ((toPos - fromPos) / swipe) * 1000; + // printf("from:%d to:%d swipe:%f span:%u\n", fromPos, toPos, d->swipeSpeed, span); + setVisualOffset_Widget(overlay, toPos, span, deviceType_App() == tablet_AppDeviceType ? + easeOut_AnimFlag : 0); + } setVisualOffset_Widget(w, 0, 0, 0); } @@ -2722,9 +2729,12 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { return iTrue; } iWidget *swipeParent = swipeParent_DocumentWidget_(d); + if (findChild_Widget(swipeParent, "swipeout")) { + return iTrue; /* too fast, previous animation hasn't finished */ + } /* The temporary "swipein" will display the previous page until the finger is lifted. */ iDocumentWidget *swipeIn = findChild_Widget(swipeParent, "swipein"); - if (!swipeIn) { + if (!swipeIn) { swipeIn = new_DocumentWidget(); swipeIn->flags |= animationPlaceholder_DocumentWidgetFlag; setId_Widget(as_Widget(swipeIn), "swipein"); @@ -2761,12 +2771,15 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { if (offset < -get_Window()->pixelRatio * 10) { int animSpan = 10; if (!atNewest_History(d->mod.history) && ~flags_Widget(w) & dragged_WidgetFlag) { + iWidget *swipeParent = swipeParent_DocumentWidget_(d); + if (findChild_Widget(swipeParent, "swipeout")) { + return iTrue; /* too fast, previous animation hasn't finished */ + } /* Setup the drag. `d` will be moving with the finger. */ animSpan = 0; postCommand_Widget(d, "navigate.forward"); setFlags_Widget(w, dragged_WidgetFlag, iTrue); /* Set up the swipe dummy. */ - iWidget *swipeParent = swipeParent_DocumentWidget_(d); iDocumentWidget *target = new_DocumentWidget(); target->flags |= animationPlaceholder_DocumentWidgetFlag; setId_Widget(as_Widget(target), "swipeout"); @@ -2820,6 +2833,7 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { // setupSwipeOverlay_DocumentWidget_(d, as_Widget(swipeOut)); return iTrue; } + iAssert(~d->flags & animationPlaceholder_DocumentWidgetFlag); setFlags_Widget(w, dragged_WidgetFlag, iFalse); setVisualOffset_Widget(w, 0, 250, easeOut_AnimFlag | softer_AnimFlag); return iTrue; diff --git a/src/ui/widget.c b/src/ui/widget.c index df74a744..1b90378a 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -144,8 +144,10 @@ static void visualOffsetAnimation_Widget_(void *ptr) { iWidget *d = ptr; postRefresh_App(); d->root->didAnimateVisualOffsets = iTrue; +// printf("'%s' visoffanim: fin:%d val:%f\n", cstr_String(&d->id), +// isFinished_Anim(&d->visualOffset), value_Anim(&d->visualOffset)); fflush(stdout); if (!isFinished_Anim(&d->visualOffset)) { - addTicker_App(visualOffsetAnimation_Widget_, ptr); + addTickerRoot_App(visualOffsetAnimation_Widget_, d->root, ptr); } else { d->flags &= ~visualOffset_WidgetFlag; @@ -919,6 +921,14 @@ int visualOffsetByReference_Widget(const iWidget *d) { // const float factor = width_Widget(d) / (float) size_Root(d->root).x; const int invOff = width_Widget(d) - iRound(value_Anim(&child->visualOffset)); offX -= invOff / 4; +#if 0 + if (invOff) { + printf(" [%p] %s (%p, fin:%d visoff:%d drag:%d): invOff %d\n", d, cstr_String(&child->id), child, + isFinished_Anim(&child->visualOffset), + (child->flags & visualOffset_WidgetFlag) != 0, + (child->flags & dragged_WidgetFlag) != 0, invOff); fflush(stdout); + } +#endif } } return offX; -- cgit v1.2.3 From 27e60fdf26c031db7a967742f1870c3bdcf3f769 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Fri, 17 Dec 2021 10:52:25 +0200 Subject: Mobile: Fixed phone sidebar background fade --- src/ui/mobile.c | 1 + src/ui/widget.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src/ui/widget.c') diff --git a/src/ui/mobile.c b/src/ui/mobile.c index df2a661a..bffc2177 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c @@ -739,6 +739,7 @@ void initPanels_Mobile(iWidget *panels, iWidget *parentWidget, horizontalOffset_WidgetFlag | /*overflowScrollable_WidgetFlag |*/ leftEdgeDraggable_WidgetFlag, iTrue); + panels->flags2 |= fadeBackground_WidgetFlag2; setFlags_Widget(panels, overflowScrollable_WidgetFlag, iFalse); /* The top-level split between main and detail panels. */ iWidget *mainDetailSplit = makeHDiv_Widget(); { diff --git a/src/ui/widget.c b/src/ui/widget.c index 1b90378a..1ac4326a 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -1430,9 +1430,19 @@ void drawLayerEffects_Widget(const iWidget *d) { init_Paint(&p); p.alpha = 0x50; if (flags_Widget(d) & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { - const float area = d->rect.size.x * d->rect.size.y; + const float area = d->rect.size.x * d->rect.size.y; + const float rootArea = area_Rect(rect_Root(d->root)); const float visibleArea = area_Rect(intersect_Rect(bounds_Widget(d), rect_Root(d->root))); - p.alpha *= (area > 0 ? visibleArea / area : 0.0f); + if (isPortraitPhone_App() && !cmp_String(&d->id, "sidebar")) { + p.alpha *= iClamp(visibleArea / rootArea * 2, 0.0f, 1.0f); + } + else if (area > 0) { + p.alpha *= visibleArea / area; + } + else { + p.alpha = 0; + } + //printf("area:%f visarea:%f alpha:%d\n", rootArea, visibleArea, p.alpha); } SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); fillRect_Paint(&p, rect_Root(d->root), backgroundFadeColor_Widget()); -- cgit v1.2.3