diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-06-14 15:36:48 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-06-14 15:36:48 +0300 |
commit | fe238b29132b43f07aa88cf6bb60bec1ff0d3f8d (patch) | |
tree | 34d08228270960a73f5586ae907a12d7adb7b393 /src | |
parent | 203426a88b2d94ed56f7d3f8f8eb18a7457cab11 (diff) |
Swiping and sidebar; various tweaks
When a page is opened from the sidebar, swiping back will now reopen the sidebar. Another swipe will dismiss the sidebar and navigate back as usual.
Attempted to cache theme colors in GmDocument, but there were issues with theme changes.
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 7 | ||||
-rw-r--r-- | src/defs.h | 3 | ||||
-rw-r--r-- | src/gmdocument.c | 18 | ||||
-rw-r--r-- | src/gmdocument.h | 2 | ||||
-rw-r--r-- | src/gmutil.c | 4 | ||||
-rw-r--r-- | src/history.c | 31 | ||||
-rw-r--r-- | src/history.h | 6 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 103 | ||||
-rw-r--r-- | src/ui/documentwidget.h | 8 | ||||
-rw-r--r-- | src/ui/sidebarwidget.c | 14 | ||||
-rw-r--r-- | src/ui/text.c | 4 | ||||
-rw-r--r-- | src/ui/touch.c | 49 | ||||
-rw-r--r-- | src/ui/widget.c | 55 | ||||
-rw-r--r-- | src/ui/widget.h | 9 |
14 files changed, 207 insertions, 106 deletions
@@ -2244,7 +2244,8 @@ iBool handleCommand_App(const char *cmd) { | |||
2244 | } | 2244 | } |
2245 | else if (equal_Command(cmd, "open")) { | 2245 | else if (equal_Command(cmd, "open")) { |
2246 | iString *url = collectNewCStr_String(suffixPtr_Command(cmd, "url")); | 2246 | iString *url = collectNewCStr_String(suffixPtr_Command(cmd, "url")); |
2247 | const iBool noProxy = argLabel_Command(cmd, "noproxy"); | 2247 | const iBool noProxy = argLabel_Command(cmd, "noproxy") != 0; |
2248 | const iBool fromSidebar = argLabel_Command(cmd, "fromsidebar") != 0; | ||
2248 | iUrl parts; | 2249 | iUrl parts; |
2249 | init_Url(&parts, url); | 2250 | init_Url(&parts, url); |
2250 | if (argLabel_Command(cmd, "default") || equalCase_Rangecc(parts.scheme, "mailto") || | 2251 | if (argLabel_Command(cmd, "default") || equalCase_Rangecc(parts.scheme, "mailto") || |
@@ -2295,7 +2296,9 @@ iBool handleCommand_App(const char *cmd) { | |||
2295 | else { | 2296 | else { |
2296 | urlEncodePath_String(url); | 2297 | urlEncodePath_String(url); |
2297 | } | 2298 | } |
2298 | setUrlFromCache_DocumentWidget(doc, url, isHistory); | 2299 | setUrlFlags_DocumentWidget(doc, url, |
2300 | (isHistory ? useCachedContentIfAvailable_DocumentWidgetSetUrlFlag : 0) | | ||
2301 | (fromSidebar ? openedFromSidebar_DocumentWidgetSetUrlFlag : 0)); | ||
2299 | /* Optionally, jump to a text in the document. This will only work if the document | 2302 | /* Optionally, jump to a text in the document. This will only work if the document |
2300 | is already available, e.g., it's from "about:" or restored from cache. */ | 2303 | is already available, e.g., it's from "about:" or restored from cache. */ |
2301 | const iRangecc gotoHeading = range_Command(cmd, "gotoheading"); | 2304 | const iRangecc gotoHeading = range_Command(cmd, "gotoheading"); |
@@ -35,9 +35,10 @@ enum iFileVersion { | |||
35 | addedResponseTimestamps_FileVersion = 1, | 35 | addedResponseTimestamps_FileVersion = 1, |
36 | multipleRoots_FileVersion = 2, | 36 | multipleRoots_FileVersion = 2, |
37 | serializedSidebarState_FileVersion = 3, | 37 | serializedSidebarState_FileVersion = 3, |
38 | addedRecentUrlFlags_FileVersion = 4, | ||
38 | /* meta */ | 39 | /* meta */ |
39 | idents_FileVersion = 1, /* version used by GmCerts/idents.lgr */ | 40 | idents_FileVersion = 1, /* version used by GmCerts/idents.lgr */ |
40 | latest_FileVersion = 3, | 41 | latest_FileVersion = 4, |
41 | }; | 42 | }; |
42 | 43 | ||
43 | /* Icons */ | 44 | /* Icons */ |
diff --git a/src/gmdocument.c b/src/gmdocument.c index 5d02ee05..0ab09604 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -92,6 +92,8 @@ struct Impl_GmDocument { | |||
92 | iChar siteIcon; | 92 | iChar siteIcon; |
93 | iMedia * media; | 93 | iMedia * media; |
94 | iStringSet *openURLs; /* currently open URLs for highlighting links */ | 94 | iStringSet *openURLs; /* currently open URLs for highlighting links */ |
95 | iBool isPaletteValid; | ||
96 | iColor palette[tmMax_ColorId]; /* copy of the color palette */ | ||
95 | }; | 97 | }; |
96 | 98 | ||
97 | iDefineObjectConstruction(GmDocument) | 99 | iDefineObjectConstruction(GmDocument) |
@@ -889,6 +891,8 @@ void init_GmDocument(iGmDocument *d) { | |||
889 | d->siteIcon = 0; | 891 | d->siteIcon = 0; |
890 | d->media = new_Media(); | 892 | d->media = new_Media(); |
891 | d->openURLs = NULL; | 893 | d->openURLs = NULL; |
894 | d->isPaletteValid = iFalse; | ||
895 | iZap(d->palette); | ||
892 | } | 896 | } |
893 | 897 | ||
894 | void deinit_GmDocument(iGmDocument *d) { | 898 | void deinit_GmDocument(iGmDocument *d) { |
@@ -1401,6 +1405,20 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | |||
1401 | } | 1405 | } |
1402 | printf("---\n"); | 1406 | printf("---\n"); |
1403 | #endif | 1407 | #endif |
1408 | /* Color functions operate on the global palette for convenience, but we may need to switch | ||
1409 | palettes on the fly if more than one GmDocument is being displayed simultaneously. */ | ||
1410 | memcpy(d->palette, get_Root()->tmPalette, sizeof(d->palette)); | ||
1411 | d->isPaletteValid = iTrue; | ||
1412 | } | ||
1413 | |||
1414 | void makePaletteGlobal_GmDocument(const iGmDocument *d) { | ||
1415 | if (d->isPaletteValid) { | ||
1416 | memcpy(get_Root()->tmPalette, d->palette, sizeof(d->palette)); | ||
1417 | } | ||
1418 | } | ||
1419 | |||
1420 | void invalidatePalette_GmDocument(iGmDocument *d) { | ||
1421 | d->isPaletteValid = iFalse; | ||
1404 | } | 1422 | } |
1405 | 1423 | ||
1406 | void setFormat_GmDocument(iGmDocument *d, enum iSourceFormat format) { | 1424 | void setFormat_GmDocument(iGmDocument *d, enum iSourceFormat format) { |
diff --git a/src/gmdocument.h b/src/gmdocument.h index 943a408c..221e5c00 100644 --- a/src/gmdocument.h +++ b/src/gmdocument.h | |||
@@ -170,6 +170,8 @@ void setUrl_GmDocument (iGmDocument *, const iString *url); | |||
170 | void setSource_GmDocument (iGmDocument *, const iString *source, int width, | 170 | void setSource_GmDocument (iGmDocument *, const iString *source, int width, |
171 | enum iGmDocumentUpdate updateType); | 171 | enum iGmDocumentUpdate updateType); |
172 | void foldPre_GmDocument (iGmDocument *, uint16_t preId); | 172 | void foldPre_GmDocument (iGmDocument *, uint16_t preId); |
173 | void invalidatePalette_GmDocument(iGmDocument *); | ||
174 | void makePaletteGlobal_GmDocument(const iGmDocument *); /* copies document colors to the global palette */ | ||
173 | 175 | ||
174 | //void reset_GmDocument (iGmDocument *); /* free images */ | 176 | //void reset_GmDocument (iGmDocument *); /* free images */ |
175 | 177 | ||
diff --git a/src/gmutil.c b/src/gmutil.c index 3ca93901..7a1ae938 100644 --- a/src/gmutil.c +++ b/src/gmutil.c | |||
@@ -556,7 +556,7 @@ const iString *feedEntryOpenCommand_String(const iString *url, int newTab) { | |||
556 | iString *head = newRange_String( | 556 | iString *head = newRange_String( |
557 | (iRangecc){ constBegin_String(url) + fragPos + 1, constEnd_String(url) }); | 557 | (iRangecc){ constBegin_String(url) + fragPos + 1, constEnd_String(url) }); |
558 | format_String(cmd, | 558 | format_String(cmd, |
559 | "open newtab:%d gotourlheading:%s url:%s", | 559 | "open fromsidebar:1 newtab:%d gotourlheading:%s url:%s", |
560 | newTab, | 560 | newTab, |
561 | cstr_String(head), | 561 | cstr_String(head), |
562 | cstr_Rangecc((iRangecc){ constBegin_String(url), | 562 | cstr_Rangecc((iRangecc){ constBegin_String(url), |
@@ -564,7 +564,7 @@ const iString *feedEntryOpenCommand_String(const iString *url, int newTab) { | |||
564 | delete_String(head); | 564 | delete_String(head); |
565 | } | 565 | } |
566 | else { | 566 | else { |
567 | format_String(cmd, "open newtab:%d url:%s", newTab, cstr_String(url)); | 567 | format_String(cmd, "open fromsidebar:1 newtab:%d url:%s", newTab, cstr_String(url)); |
568 | } | 568 | } |
569 | return cmd; | 569 | return cmd; |
570 | } | 570 | } |
diff --git a/src/history.c b/src/history.c index d23fb290..c592838e 100644 --- a/src/history.c +++ b/src/history.c | |||
@@ -37,6 +37,7 @@ void init_RecentUrl(iRecentUrl *d) { | |||
37 | d->normScrollY = 0; | 37 | d->normScrollY = 0; |
38 | d->cachedResponse = NULL; | 38 | d->cachedResponse = NULL; |
39 | d->cachedDoc = NULL; | 39 | d->cachedDoc = NULL; |
40 | d->flags.openedFromSidebar = iFalse; | ||
40 | } | 41 | } |
41 | 42 | ||
42 | void deinit_RecentUrl(iRecentUrl *d) { | 43 | void deinit_RecentUrl(iRecentUrl *d) { |
@@ -53,6 +54,7 @@ iRecentUrl *copy_RecentUrl(const iRecentUrl *d) { | |||
53 | copy->normScrollY = d->normScrollY; | 54 | copy->normScrollY = d->normScrollY; |
54 | copy->cachedResponse = d->cachedResponse ? copy_GmResponse(d->cachedResponse) : NULL; | 55 | copy->cachedResponse = d->cachedResponse ? copy_GmResponse(d->cachedResponse) : NULL; |
55 | copy->cachedDoc = ref_Object(d->cachedDoc); | 56 | copy->cachedDoc = ref_Object(d->cachedDoc); |
57 | copy->flags = d->flags; | ||
56 | return copy; | 58 | return copy; |
57 | } | 59 | } |
58 | 60 | ||
@@ -171,6 +173,7 @@ void serialize_History(const iHistory *d, iStream *outs) { | |||
171 | const iRecentUrl *item = i.value; | 173 | const iRecentUrl *item = i.value; |
172 | serialize_String(&item->url, outs); | 174 | serialize_String(&item->url, outs); |
173 | write32_Stream(outs, item->normScrollY * 1.0e6f); | 175 | write32_Stream(outs, item->normScrollY * 1.0e6f); |
176 | writeU16_Stream(outs, item->flags.openedFromSidebar ? iBit(1) : 0); | ||
174 | if (item->cachedResponse) { | 177 | if (item->cachedResponse) { |
175 | write8_Stream(outs, 1); | 178 | write8_Stream(outs, 1); |
176 | serialize_GmResponse(item->cachedResponse, outs); | 179 | serialize_GmResponse(item->cachedResponse, outs); |
@@ -192,6 +195,12 @@ void deserialize_History(iHistory *d, iStream *ins) { | |||
192 | init_RecentUrl(&item); | 195 | init_RecentUrl(&item); |
193 | deserialize_String(&item.url, ins); | 196 | deserialize_String(&item.url, ins); |
194 | item.normScrollY = (float) read32_Stream(ins) / 1.0e6f; | 197 | item.normScrollY = (float) read32_Stream(ins) / 1.0e6f; |
198 | if (version_Stream(ins) >= addedRecentUrlFlags_FileVersion) { | ||
199 | uint16_t flags = readU16_Stream(ins); | ||
200 | if (flags & iBit(1)) { | ||
201 | item.flags.openedFromSidebar = iTrue; | ||
202 | } | ||
203 | } | ||
195 | if (read8_Stream(ins)) { | 204 | if (read8_Stream(ins)) { |
196 | item.cachedResponse = new_GmResponse(); | 205 | item.cachedResponse = new_GmResponse(); |
197 | deserialize_GmResponse(item.cachedResponse, ins); | 206 | deserialize_GmResponse(item.cachedResponse, ins); |
@@ -378,12 +387,15 @@ void setCachedResponse_History(iHistory *d, const iGmResponse *response) { | |||
378 | unlock_Mutex(d->mtx); | 387 | unlock_Mutex(d->mtx); |
379 | } | 388 | } |
380 | 389 | ||
381 | void setCachedDocument_History(iHistory *d, iGmDocument *doc) { | 390 | void setCachedDocument_History(iHistory *d, iGmDocument *doc, iBool openedFromSidebar) { |
382 | lock_Mutex(d->mtx); | 391 | lock_Mutex(d->mtx); |
383 | iRecentUrl *item = mostRecentUrl_History(d); | 392 | iRecentUrl *item = mostRecentUrl_History(d); |
384 | if (item && item->cachedDoc != doc) { | 393 | if (item) { |
385 | iRelease(item->cachedDoc); | 394 | item->flags.openedFromSidebar = openedFromSidebar; |
386 | item->cachedDoc = ref_Object(doc); | 395 | if (item->cachedDoc != doc) { |
396 | iRelease(item->cachedDoc); | ||
397 | item->cachedDoc = ref_Object(doc); | ||
398 | } | ||
387 | } | 399 | } |
388 | unlock_Mutex(d->mtx); | 400 | unlock_Mutex(d->mtx); |
389 | } | 401 | } |
@@ -487,6 +499,17 @@ size_t pruneLeastImportantMemory_History(iHistory *d) { | |||
487 | return delta; | 499 | return delta; |
488 | } | 500 | } |
489 | 501 | ||
502 | void invalidateTheme_History(iHistory *d) { | ||
503 | lock_Mutex(d->mtx); | ||
504 | iForEach(Array, i, &d->recent) { | ||
505 | iRecentUrl *r = i.value; | ||
506 | if (r->cachedDoc) { | ||
507 | invalidatePalette_GmDocument(r->cachedDoc); | ||
508 | } | ||
509 | } | ||
510 | unlock_Mutex(d->mtx); | ||
511 | } | ||
512 | |||
490 | const iStringArray *searchContents_History(const iHistory *d, const iRegExp *pattern) { | 513 | const iStringArray *searchContents_History(const iHistory *d, const iRegExp *pattern) { |
491 | iStringArray *urls = iClob(new_StringArray()); | 514 | iStringArray *urls = iClob(new_StringArray()); |
492 | lock_Mutex(d->mtx); | 515 | lock_Mutex(d->mtx); |
diff --git a/src/history.h b/src/history.h index 838ca9ef..7dad72df 100644 --- a/src/history.h +++ b/src/history.h | |||
@@ -39,6 +39,9 @@ struct Impl_RecentUrl { | |||
39 | float normScrollY; /* normalized to document height */ | 39 | float normScrollY; /* normalized to document height */ |
40 | iGmResponse *cachedResponse; /* kept in memory for quicker back navigation */ | 40 | iGmResponse *cachedResponse; /* kept in memory for quicker back navigation */ |
41 | iGmDocument *cachedDoc; /* cached copy of the presentation: layout and media (not serialized) */ | 41 | iGmDocument *cachedDoc; /* cached copy of the presentation: layout and media (not serialized) */ |
42 | struct { | ||
43 | uint8_t openedFromSidebar : 1; | ||
44 | } flags; | ||
42 | }; | 45 | }; |
43 | 46 | ||
44 | iDeclareType(MemInfo) | 47 | iDeclareType(MemInfo) |
@@ -60,7 +63,7 @@ void clear_History (iHistory *); | |||
60 | void add_History (iHistory *, const iString *url); | 63 | void add_History (iHistory *, const iString *url); |
61 | void replace_History (iHistory *, const iString *url); | 64 | void replace_History (iHistory *, const iString *url); |
62 | void setCachedResponse_History (iHistory *, const iGmResponse *response); | 65 | void setCachedResponse_History (iHistory *, const iGmResponse *response); |
63 | void setCachedDocument_History (iHistory *, iGmDocument *doc); | 66 | void setCachedDocument_History (iHistory *, iGmDocument *doc, iBool openedFromSidebar); |
64 | iBool goBack_History (iHistory *); | 67 | iBool goBack_History (iHistory *); |
65 | iBool goForward_History (iHistory *); | 68 | iBool goForward_History (iHistory *); |
66 | iBool preceding_History (iHistory *d, iRecentUrl *recent_out); | 69 | iBool preceding_History (iHistory *d, iRecentUrl *recent_out); |
@@ -72,6 +75,7 @@ iRecentUrl *findUrl_History (iHistory *, const iString *url); | |||
72 | void clearCache_History (iHistory *); | 75 | void clearCache_History (iHistory *); |
73 | size_t pruneLeastImportant_History (iHistory *); | 76 | size_t pruneLeastImportant_History (iHistory *); |
74 | size_t pruneLeastImportantMemory_History (iHistory *); | 77 | size_t pruneLeastImportantMemory_History (iHistory *); |
78 | void invalidateTheme_History (iHistory *); /* theme has changed, cached contents need updating */ | ||
75 | 79 | ||
76 | iBool atLatest_History (const iHistory *); | 80 | iBool atLatest_History (const iHistory *); |
77 | iBool atOldest_History (const iHistory *); | 81 | iBool atOldest_History (const iHistory *); |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index eae5d713..3fc22bdf 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -130,7 +130,8 @@ void deinit_PersistentDocumentState(iPersistentDocumentState *d) { | |||
130 | 130 | ||
131 | void serialize_PersistentDocumentState(const iPersistentDocumentState *d, iStream *outs) { | 131 | void serialize_PersistentDocumentState(const iPersistentDocumentState *d, iStream *outs) { |
132 | serialize_String(d->url, outs); | 132 | serialize_String(d->url, outs); |
133 | writeU16_Stream(outs, d->reloadInterval & 7); | 133 | uint16_t params = d->reloadInterval & 7; |
134 | writeU16_Stream(outs, params); | ||
134 | serialize_History(d->history, outs); | 135 | serialize_History(d->history, outs); |
135 | } | 136 | } |
136 | 137 | ||
@@ -223,6 +224,7 @@ enum iDocumentWidgetFlag { | |||
223 | movingSelectMarkEnd_DocumentWidgetFlag = iBit(11), | 224 | movingSelectMarkEnd_DocumentWidgetFlag = iBit(11), |
224 | otherRootByDefault_DocumentWidgetFlag = iBit(12), /* links open to other root by default */ | 225 | otherRootByDefault_DocumentWidgetFlag = iBit(12), /* links open to other root by default */ |
225 | urlChanged_DocumentWidgetFlag = iBit(13), | 226 | urlChanged_DocumentWidgetFlag = iBit(13), |
227 | openedFromSidebar_DocumentWidgetFlag = iBit(14), | ||
226 | }; | 228 | }; |
227 | 229 | ||
228 | enum iDocumentLinkOrdinalMode { | 230 | enum iDocumentLinkOrdinalMode { |
@@ -1606,7 +1608,8 @@ static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float n | |||
1606 | format_String(&d->sourceHeader, cstr_Lang("pageinfo.header.cached")); | 1608 | format_String(&d->sourceHeader, cstr_Lang("pageinfo.header.cached")); |
1607 | set_Block(&d->sourceContent, &resp->body); | 1609 | set_Block(&d->sourceContent, &resp->body); |
1608 | updateDocument_DocumentWidget_(d, resp, cachedDoc, iTrue); | 1610 | updateDocument_DocumentWidget_(d, resp, cachedDoc, iTrue); |
1609 | setCachedDocument_History(d->mod.history, d->doc); | 1611 | setCachedDocument_History(d->mod.history, d->doc, |
1612 | (d->flags & openedFromSidebar_DocumentWidgetFlag) != 0); | ||
1610 | } | 1613 | } |
1611 | d->state = ready_RequestState; | 1614 | d->state = ready_RequestState; |
1612 | postProcessRequestContent_DocumentWidget_(d, iTrue); | 1615 | postProcessRequestContent_DocumentWidget_(d, iTrue); |
@@ -1626,6 +1629,9 @@ static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float n | |||
1626 | static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) { | 1629 | static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) { |
1627 | const iRecentUrl *recent = findUrl_History(d->mod.history, withSpacesEncoded_String(d->mod.url)); | 1630 | const iRecentUrl *recent = findUrl_History(d->mod.history, withSpacesEncoded_String(d->mod.url)); |
1628 | if (recent && recent->cachedResponse) { | 1631 | if (recent && recent->cachedResponse) { |
1632 | iChangeFlags(d->flags, | ||
1633 | openedFromSidebar_DocumentWidgetFlag, | ||
1634 | recent->flags.openedFromSidebar); | ||
1629 | updateFromCachedResponse_DocumentWidget_( | 1635 | updateFromCachedResponse_DocumentWidget_( |
1630 | d, recent->normScrollY, recent->cachedResponse, recent->cachedDoc); | 1636 | d, recent->normScrollY, recent->cachedResponse, recent->cachedDoc); |
1631 | return iTrue; | 1637 | return iTrue; |
@@ -2282,6 +2288,9 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | |||
2282 | /* The temporary "swipeIn" will display the previous page until the finger is lifted. */ | 2288 | /* The temporary "swipeIn" will display the previous page until the finger is lifted. */ |
2283 | iDocumentWidget *swipeIn = findChild_Widget(swipeParent, "swipein"); | 2289 | iDocumentWidget *swipeIn = findChild_Widget(swipeParent, "swipein"); |
2284 | if (!swipeIn) { | 2290 | if (!swipeIn) { |
2291 | const iBool sidebarSwipe = (isPortraitPhone_App() && | ||
2292 | d->flags & openedFromSidebar_DocumentWidgetFlag && | ||
2293 | !isVisible_Widget(findWidget_App("sidebar"))); | ||
2285 | swipeIn = new_DocumentWidget(); | 2294 | swipeIn = new_DocumentWidget(); |
2286 | setId_Widget(as_Widget(swipeIn), "swipein"); | 2295 | setId_Widget(as_Widget(swipeIn), "swipein"); |
2287 | setFlags_Widget(as_Widget(swipeIn), | 2296 | setFlags_Widget(as_Widget(swipeIn), |
@@ -2290,16 +2299,18 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | |||
2290 | swipeIn->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos)); | 2299 | swipeIn->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos)); |
2291 | swipeIn->widget.rect.size = d->widget.rect.size; | 2300 | swipeIn->widget.rect.size = d->widget.rect.size; |
2292 | swipeIn->widget.offsetRef = parent_Widget(w); | 2301 | swipeIn->widget.offsetRef = parent_Widget(w); |
2293 | iRecentUrl *recent = new_RecentUrl(); | 2302 | if (!sidebarSwipe) { |
2294 | preceding_History(d->mod.history, recent); | 2303 | iRecentUrl *recent = new_RecentUrl(); |
2295 | if (recent->cachedDoc) { | 2304 | preceding_History(d->mod.history, recent); |
2296 | iChangeRef(swipeIn->doc, recent->cachedDoc); | 2305 | if (recent->cachedDoc) { |
2297 | updateScrollMax_DocumentWidget_(d); | 2306 | iChangeRef(swipeIn->doc, recent->cachedDoc); |
2298 | setValue_Anim(&swipeIn->scrollY.pos, size_GmDocument(swipeIn->doc).y * recent->normScrollY, 0); | 2307 | updateScrollMax_DocumentWidget_(d); |
2299 | updateVisible_DocumentWidget_(swipeIn); | 2308 | setValue_Anim(&swipeIn->scrollY.pos, size_GmDocument(swipeIn->doc).y * recent->normScrollY, 0); |
2300 | swipeIn->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag; | 2309 | updateVisible_DocumentWidget_(swipeIn); |
2310 | swipeIn->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag; | ||
2311 | } | ||
2312 | delete_RecentUrl(recent); | ||
2301 | } | 2313 | } |
2302 | delete_RecentUrl(recent); | ||
2303 | addChildPos_Widget(swipeParent, iClob(swipeIn), front_WidgetAddPos); | 2314 | addChildPos_Widget(swipeParent, iClob(swipeIn), front_WidgetAddPos); |
2304 | } | 2315 | } |
2305 | } | 2316 | } |
@@ -2326,7 +2337,9 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | |||
2326 | destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */ | 2337 | destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */ |
2327 | } | 2338 | } |
2328 | if (flags_Widget(w) & dragged_WidgetFlag) { | 2339 | if (flags_Widget(w) & dragged_WidgetFlag) { |
2329 | setVisualOffset_Widget(w, width_Widget(w) + offset, animSpan, 0); | 2340 | setVisualOffset_Widget(w, width_Widget(w) + |
2341 | width_Widget(d) * offset / size_Root(w->root).x, | ||
2342 | animSpan, 0); | ||
2330 | } | 2343 | } |
2331 | else { | 2344 | else { |
2332 | setVisualOffset_Widget(w, offset / 4, animSpan, 0); | 2345 | setVisualOffset_Widget(w, offset / 4, animSpan, 0); |
@@ -2426,6 +2439,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2426 | return iFalse; | 2439 | return iFalse; |
2427 | } | 2440 | } |
2428 | else if (equal_Command(cmd, "theme.changed") && document_App() == d) { | 2441 | else if (equal_Command(cmd, "theme.changed") && document_App() == d) { |
2442 | // invalidateTheme_History(d->mod.history); /* cached colors */ | ||
2429 | updateTheme_DocumentWidget_(d); | 2443 | updateTheme_DocumentWidget_(d); |
2430 | updateVisible_DocumentWidget_(d); | 2444 | updateVisible_DocumentWidget_(d); |
2431 | updateTrust_DocumentWidget_(d, NULL); | 2445 | updateTrust_DocumentWidget_(d, NULL); |
@@ -2691,7 +2705,8 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2691 | (startsWithCase_String(meta_GmRequest(d->request), "text/") || | 2705 | (startsWithCase_String(meta_GmRequest(d->request), "text/") || |
2692 | !cmp_String(&d->sourceMime, mimeType_Gempub))) { | 2706 | !cmp_String(&d->sourceMime, mimeType_Gempub))) { |
2693 | setCachedResponse_History(d->mod.history, lockResponse_GmRequest(d->request)); | 2707 | setCachedResponse_History(d->mod.history, lockResponse_GmRequest(d->request)); |
2694 | setCachedDocument_History(d->mod.history, d->doc); /* keeps a ref */ | 2708 | setCachedDocument_History(d->mod.history, d->doc, /* keeps a ref */ |
2709 | (d->flags & openedFromSidebar_DocumentWidgetFlag) != 0); | ||
2695 | unlockResponse_GmRequest(d->request); | 2710 | unlockResponse_GmRequest(d->request); |
2696 | } | 2711 | } |
2697 | } | 2712 | } |
@@ -2821,6 +2836,15 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2821 | return iTrue; | 2836 | return iTrue; |
2822 | } | 2837 | } |
2823 | else if (equal_Command(cmd, "navigate.back") && document_App() == d) { | 2838 | else if (equal_Command(cmd, "navigate.back") && document_App() == d) { |
2839 | if (isPortraitPhone_App()) { | ||
2840 | if (d->flags & openedFromSidebar_DocumentWidgetFlag && | ||
2841 | !isVisible_Widget(findWidget_App("sidebar"))) { | ||
2842 | postCommand_App("sidebar.toggle"); | ||
2843 | showToolbars_Root(get_Root(), iTrue); | ||
2844 | return iTrue; | ||
2845 | } | ||
2846 | d->flags &= ~openedFromSidebar_DocumentWidgetFlag; | ||
2847 | } | ||
2824 | if (d->request) { | 2848 | if (d->request) { |
2825 | postCommandf_Root(w->root, | 2849 | postCommandf_Root(w->root, |
2826 | "document.request.cancelled doc:%p url:%s", d, cstr_String(d->mod.url)); | 2850 | "document.request.cancelled doc:%p url:%s", d, cstr_String(d->mod.url)); |
@@ -3499,7 +3523,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
3499 | pushBack_Array( | 3523 | pushBack_Array( |
3500 | &items, | 3524 | &items, |
3501 | &(iMenuItem){ delete_Icon " " uiTextCaution_ColorEscape | 3525 | &(iMenuItem){ delete_Icon " " uiTextCaution_ColorEscape |
3502 | " ${link.file.delete}", | 3526 | "${link.file.delete}", |
3503 | 0, | 3527 | 0, |
3504 | 0, | 3528 | 0, |
3505 | format_CStr("!file.delete confirm:1 path:%s", | 3529 | format_CStr("!file.delete confirm:1 path:%s", |
@@ -4366,7 +4390,7 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) { | |||
4366 | iDrawBufs * dbuf = d->drawBufs; | 4390 | iDrawBufs * dbuf = d->drawBufs; |
4367 | iPaint p; | 4391 | iPaint p; |
4368 | init_Paint(&p); | 4392 | init_Paint(&p); |
4369 | setClip_Paint(&p, bounds); | 4393 | setClip_Paint(&p, boundsWithoutVisualOffset_Widget(w)); |
4370 | /* Side icon and current heading. */ | 4394 | /* Side icon and current heading. */ |
4371 | if (prefs_App()->sideIcon && opacity > 0 && dbuf->sideIconBuf) { | 4395 | if (prefs_App()->sideIcon && opacity > 0 && dbuf->sideIconBuf) { |
4372 | const iInt2 texSize = size_SDLTexture(dbuf->sideIconBuf); | 4396 | const iInt2 texSize = size_SDLTexture(dbuf->sideIconBuf); |
@@ -4616,12 +4640,17 @@ static void prerender_DocumentWidget_(iAny *context) { | |||
4616 | } | 4640 | } |
4617 | 4641 | ||
4618 | static void draw_DocumentWidget_(const iDocumentWidget *d) { | 4642 | static void draw_DocumentWidget_(const iDocumentWidget *d) { |
4619 | const iWidget *w = constAs_Widget(d); | 4643 | const iWidget *w = constAs_Widget(d); |
4620 | const iRect bounds = bounds_Widget(w); | 4644 | const iRect bounds = bounds_Widget(w); |
4645 | const iRect boundsWithoutVisOff = boundsWithoutVisualOffset_Widget(w); | ||
4646 | const iRect clipBounds = intersect_Rect(bounds, boundsWithoutVisOff); | ||
4621 | if (width_Rect(bounds) <= 0) { | 4647 | if (width_Rect(bounds) <= 0) { |
4622 | return; | 4648 | return; |
4623 | } | 4649 | } |
4624 | // draw_Widget(w); | 4650 | /* TODO: Come up with a better palette caching system. |
4651 | It should be able to recompute cached colors in `History` when the theme has changed. | ||
4652 | Cache the theme seed in `GmDocument`? */ | ||
4653 | // makePaletteGlobal_GmDocument(d->doc); | ||
4625 | if (d->drawBufs->flags & updateTimestampBuf_DrawBufsFlag) { | 4654 | if (d->drawBufs->flags & updateTimestampBuf_DrawBufsFlag) { |
4626 | updateTimestampBuf_DocumentWidget_(d); | 4655 | updateTimestampBuf_DocumentWidget_(d); |
4627 | } | 4656 | } |
@@ -4638,7 +4667,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4638 | }; | 4667 | }; |
4639 | init_Paint(&ctx.paint); | 4668 | init_Paint(&ctx.paint); |
4640 | render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); | 4669 | render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); |
4641 | setClip_Paint(&ctx.paint, bounds); | 4670 | setClip_Paint(&ctx.paint, clipBounds); |
4642 | int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); | 4671 | int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); |
4643 | draw_VisBuf(d->visBuf, init_I2(bounds.pos.x, yTop), ySpan_Rect(bounds)); | 4672 | draw_VisBuf(d->visBuf, init_I2(bounds.pos.x, yTop), ySpan_Rect(bounds)); |
4644 | /* Text markers. */ | 4673 | /* Text markers. */ |
@@ -4673,7 +4702,6 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4673 | } | 4702 | } |
4674 | } | 4703 | } |
4675 | drawMedia_DocumentWidget_(d, &ctx.paint); | 4704 | drawMedia_DocumentWidget_(d, &ctx.paint); |
4676 | unsetClip_Paint(&ctx.paint); | ||
4677 | /* Fill the top and bottom, in case the document is short. */ | 4705 | /* Fill the top and bottom, in case the document is short. */ |
4678 | if (yTop > top_Rect(bounds)) { | 4706 | if (yTop > top_Rect(bounds)) { |
4679 | fillRect_Paint(&ctx.paint, | 4707 | fillRect_Paint(&ctx.paint, |
@@ -4687,6 +4715,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4687 | init_Rect(bounds.pos.x, yBottom, bounds.size.x, bottom_Rect(bounds) - yBottom), | 4715 | init_Rect(bounds.pos.x, yBottom, bounds.size.x, bottom_Rect(bounds) - yBottom), |
4688 | tmBackground_ColorId); | 4716 | tmBackground_ColorId); |
4689 | } | 4717 | } |
4718 | unsetClip_Paint(&ctx.paint); | ||
4690 | drawSideElements_DocumentWidget_(d); | 4719 | drawSideElements_DocumentWidget_(d); |
4691 | if (prefs_App()->hoverLink && d->hoverLink) { | 4720 | if (prefs_App()->hoverLink && d->hoverLink) { |
4692 | const int font = uiLabel_FontId; | 4721 | const int font = uiLabel_FontId; |
@@ -4748,6 +4777,23 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4748 | drawCentered_Text(uiLabelBold_FontId, rect, iFalse, uiBackground_ColorId, "%zu bytes selected", | 4777 | drawCentered_Text(uiLabelBold_FontId, rect, iFalse, uiBackground_ColorId, "%zu bytes selected", |
4749 | size_Range(&mark)); | 4778 | size_Range(&mark)); |
4750 | } | 4779 | } |
4780 | if (w->offsetRef) { | ||
4781 | const int offX = visualOffsetByReference_Widget(w); | ||
4782 | if (offX) { | ||
4783 | setClip_Paint(&ctx.paint, clipBounds); | ||
4784 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); | ||
4785 | ctx.paint.alpha = iAbs(offX) / (float) get_Window()->size.x * 300; | ||
4786 | fillRect_Paint(&ctx.paint, bounds, backgroundFadeColor_Widget()); | ||
4787 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); | ||
4788 | unsetClip_Paint(&ctx.paint); | ||
4789 | } | ||
4790 | else { | ||
4791 | /* TODO: Should have a better place to do this; drawing is supposed to be immutable. */ | ||
4792 | iWidget *mut = iConstCast(iWidget *, w); | ||
4793 | mut->offsetRef = NULL; | ||
4794 | mut->flags &= ~refChildrenOffset_WidgetFlag; | ||
4795 | } | ||
4796 | } | ||
4751 | } | 4797 | } |
4752 | 4798 | ||
4753 | /*----------------------------------------------------------------------------------------------*/ | 4799 | /*----------------------------------------------------------------------------------------------*/ |
@@ -4814,10 +4860,13 @@ static void setUrl_DocumentWidget_(iDocumentWidget *d, const iString *url) { | |||
4814 | if (!equal_String(d->mod.url, url)) { | 4860 | if (!equal_String(d->mod.url, url)) { |
4815 | d->flags |= urlChanged_DocumentWidgetFlag; | 4861 | d->flags |= urlChanged_DocumentWidgetFlag; |
4816 | set_String(d->mod.url, url); | 4862 | set_String(d->mod.url, url); |
4817 | } | 4863 | } |
4818 | } | 4864 | } |
4819 | 4865 | ||
4820 | void setUrlFromCache_DocumentWidget(iDocumentWidget *d, const iString *url, iBool isFromCache) { | 4866 | void setUrlFlags_DocumentWidget(iDocumentWidget *d, const iString *url, int setUrlFlags) { |
4867 | iChangeFlags(d->flags, openedFromSidebar_DocumentWidgetFlag, | ||
4868 | (setUrlFlags & openedFromSidebar_DocumentWidgetSetUrlFlag) != 0); | ||
4869 | const iBool isFromCache = (setUrlFlags & useCachedContentIfAvailable_DocumentWidgetSetUrlFlag) != 0; | ||
4821 | setLinkNumberMode_DocumentWidget_(d, iFalse); | 4870 | setLinkNumberMode_DocumentWidget_(d, iFalse); |
4822 | setUrl_DocumentWidget_(d, urlFragmentStripped_String(url)); | 4871 | setUrl_DocumentWidget_(d, urlFragmentStripped_String(url)); |
4823 | /* See if there a username in the URL. */ | 4872 | /* See if there a username in the URL. */ |
@@ -4829,6 +4878,7 @@ void setUrlFromCache_DocumentWidget(iDocumentWidget *d, const iString *url, iBoo | |||
4829 | 4878 | ||
4830 | void setUrlAndSource_DocumentWidget(iDocumentWidget *d, const iString *url, const iString *mime, | 4879 | void setUrlAndSource_DocumentWidget(iDocumentWidget *d, const iString *url, const iString *mime, |
4831 | const iBlock *source) { | 4880 | const iBlock *source) { |
4881 | d->flags &= ~openedFromSidebar_DocumentWidgetFlag; | ||
4832 | setLinkNumberMode_DocumentWidget_(d, iFalse); | 4882 | setLinkNumberMode_DocumentWidget_(d, iFalse); |
4833 | setUrl_DocumentWidget_(d, url); | 4883 | setUrl_DocumentWidget_(d, url); |
4834 | parseUser_DocumentWidget_(d); | 4884 | parseUser_DocumentWidget_(d); |
@@ -4846,12 +4896,12 @@ iDocumentWidget *duplicate_DocumentWidget(const iDocumentWidget *orig) { | |||
4846 | delete_History(d->mod.history); | 4896 | delete_History(d->mod.history); |
4847 | d->initNormScrollY = normScrollPos_DocumentWidget_(d); | 4897 | d->initNormScrollY = normScrollPos_DocumentWidget_(d); |
4848 | d->mod.history = copy_History(orig->mod.history); | 4898 | d->mod.history = copy_History(orig->mod.history); |
4849 | setUrlFromCache_DocumentWidget(d, orig->mod.url, iTrue); | 4899 | setUrlFlags_DocumentWidget(d, orig->mod.url, useCachedContentIfAvailable_DocumentWidgetSetUrlFlag); |
4850 | return d; | 4900 | return d; |
4851 | } | 4901 | } |
4852 | 4902 | ||
4853 | void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { | 4903 | void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { |
4854 | setUrlFromCache_DocumentWidget(d, url, iFalse); | 4904 | setUrlFlags_DocumentWidget(d, url, 0); |
4855 | } | 4905 | } |
4856 | 4906 | ||
4857 | void setInitialScroll_DocumentWidget(iDocumentWidget *d, float normScrollY) { | 4907 | void setInitialScroll_DocumentWidget(iDocumentWidget *d, float normScrollY) { |
@@ -4862,6 +4912,11 @@ void setRedirectCount_DocumentWidget(iDocumentWidget *d, int count) { | |||
4862 | d->redirectCount = count; | 4912 | d->redirectCount = count; |
4863 | } | 4913 | } |
4864 | 4914 | ||
4915 | void setOpenedFromSidebar_DocumentWidget(iDocumentWidget *d, iBool fromSidebar) { | ||
4916 | iChangeFlags(d->flags, openedFromSidebar_DocumentWidgetFlag, fromSidebar); | ||
4917 | setCachedDocument_History(d->mod.history, d->doc, fromSidebar); | ||
4918 | } | ||
4919 | |||
4865 | iBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) { | 4920 | iBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) { |
4866 | return d->request != NULL; | 4921 | return d->request != NULL; |
4867 | } | 4922 | } |
diff --git a/src/ui/documentwidget.h b/src/ui/documentwidget.h index c038f981..1921b25a 100644 --- a/src/ui/documentwidget.h +++ b/src/ui/documentwidget.h | |||
@@ -45,11 +45,17 @@ const iString * bookmarkTitle_DocumentWidget (const iDocumentWidget *); | |||
45 | const iString * feedTitle_DocumentWidget (const iDocumentWidget *); | 45 | const iString * feedTitle_DocumentWidget (const iDocumentWidget *); |
46 | int documentWidth_DocumentWidget (const iDocumentWidget *); | 46 | int documentWidth_DocumentWidget (const iDocumentWidget *); |
47 | 47 | ||
48 | enum iDocumentWidgetSetUrlFlags { | ||
49 | useCachedContentIfAvailable_DocumentWidgetSetUrlFlag = iBit(1), | ||
50 | openedFromSidebar_DocumentWidgetSetUrlFlag = iBit(2), | ||
51 | }; | ||
52 | |||
48 | void setUrl_DocumentWidget (iDocumentWidget *, const iString *url); | 53 | void setUrl_DocumentWidget (iDocumentWidget *, const iString *url); |
49 | void setUrlFromCache_DocumentWidget (iDocumentWidget *, const iString *url, iBool isFromCache); | 54 | void setUrlFlags_DocumentWidget (iDocumentWidget *, const iString *url, int setUrlFlags); |
50 | void setUrlAndSource_DocumentWidget (iDocumentWidget *, const iString *url, const iString *mime, const iBlock *source); | 55 | void setUrlAndSource_DocumentWidget (iDocumentWidget *, const iString *url, const iString *mime, const iBlock *source); |
51 | void setInitialScroll_DocumentWidget (iDocumentWidget *, float normScrollY); /* set after content received */ | 56 | void setInitialScroll_DocumentWidget (iDocumentWidget *, float normScrollY); /* set after content received */ |
52 | void setRedirectCount_DocumentWidget (iDocumentWidget *, int count); | 57 | void setRedirectCount_DocumentWidget (iDocumentWidget *, int count); |
53 | void setSource_DocumentWidget (iDocumentWidget *, const iString *sourceText); | 58 | void setSource_DocumentWidget (iDocumentWidget *, const iString *sourceText); |
59 | void setOpenedFromSidebar_DocumentWidget(iDocumentWidget *, iBool fromSidebar); | ||
54 | 60 | ||
55 | void updateSize_DocumentWidget (iDocumentWidget *); | 61 | void updateSize_DocumentWidget (iDocumentWidget *); |
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 4f3ea637..f7181037 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -773,6 +773,7 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, si | |||
773 | const iGmHeading *head = constAt_Array(headings_GmDocument(doc), item->id); | 773 | const iGmHeading *head = constAt_Array(headings_GmDocument(doc), item->id); |
774 | postCommandf_App("document.goto loc:%p", head->text.start); | 774 | postCommandf_App("document.goto loc:%p", head->text.start); |
775 | dismissPortraitPhoneSidebars_Root(as_Widget(d)->root); | 775 | dismissPortraitPhoneSidebars_Root(as_Widget(d)->root); |
776 | setOpenedFromSidebar_DocumentWidget(document_App(), iTrue); | ||
776 | break; | 777 | break; |
777 | } | 778 | } |
778 | case feeds_SidebarMode: { | 779 | case feeds_SidebarMode: { |
@@ -783,7 +784,7 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, si | |||
783 | case bookmarks_SidebarMode: | 784 | case bookmarks_SidebarMode: |
784 | case history_SidebarMode: { | 785 | case history_SidebarMode: { |
785 | if (!isEmpty_String(&item->url)) { | 786 | if (!isEmpty_String(&item->url)) { |
786 | postCommandf_Root(get_Root(), "open newtab:%d url:%s", | 787 | postCommandf_Root(get_Root(), "open fromsidebar:1 newtab:%d url:%s", |
787 | openTabMode_Sym(modState_Keys()), | 788 | openTabMode_Sym(modState_Keys()), |
788 | cstr_String(&item->url)); | 789 | cstr_String(&item->url)); |
789 | } | 790 | } |
@@ -944,13 +945,16 @@ static iBool handleSidebarCommand_SidebarWidget_(iSidebarWidget *d, const char * | |||
944 | visX = left_Rect(bounds_Widget(w)) - left_Rect(w->root->widget->rect); | 945 | visX = left_Rect(bounds_Widget(w)) - left_Rect(w->root->widget->rect); |
945 | } | 946 | } |
946 | setFlags_Widget(w, hidden_WidgetFlag, isVisible_Widget(w)); | 947 | setFlags_Widget(w, hidden_WidgetFlag, isVisible_Widget(w)); |
948 | /* Safe area inset for mobile. */ | ||
949 | const int safePad = (d->side == left_SidebarSide ? left_Rect(safeRect_Root(w->root)) : 0); | ||
947 | if (isVisible_Widget(w)) { | 950 | if (isVisible_Widget(w)) { |
948 | setFlags_Widget(w, keepOnTop_WidgetFlag, iFalse); | 951 | setFlags_Widget(w, keepOnTop_WidgetFlag, iFalse); |
949 | w->rect.size.x = d->widthAsGaps * gap_UI; | 952 | w->rect.size.x = d->widthAsGaps * gap_UI; |
950 | invalidate_ListWidget(d->list); | 953 | invalidate_ListWidget(d->list); |
951 | if (isAnimated) { | 954 | if (isAnimated) { |
952 | setFlags_Widget(w, horizontalOffset_WidgetFlag, iTrue); | 955 | setFlags_Widget(w, horizontalOffset_WidgetFlag, iTrue); |
953 | setVisualOffset_Widget(w, (d->side == left_SidebarSide ? -1 : 1) * w->rect.size.x, 0, 0); | 956 | setVisualOffset_Widget( |
957 | w, (d->side == left_SidebarSide ? -1 : 1) * (w->rect.size.x + safePad), 0, 0); | ||
954 | setVisualOffset_Widget(w, 0, 300, easeOut_AnimFlag | softer_AnimFlag); | 958 | setVisualOffset_Widget(w, 0, 300, easeOut_AnimFlag | softer_AnimFlag); |
955 | } | 959 | } |
956 | } | 960 | } |
@@ -958,11 +962,13 @@ static iBool handleSidebarCommand_SidebarWidget_(iSidebarWidget *d, const char * | |||
958 | setFlags_Widget(w, horizontalOffset_WidgetFlag, iTrue); | 962 | setFlags_Widget(w, horizontalOffset_WidgetFlag, iTrue); |
959 | if (d->side == right_SidebarSide) { | 963 | if (d->side == right_SidebarSide) { |
960 | setVisualOffset_Widget(w, visX, 0, 0); | 964 | setVisualOffset_Widget(w, visX, 0, 0); |
961 | setVisualOffset_Widget(w, visX + w->rect.size.x, 300, easeOut_AnimFlag | softer_AnimFlag); | 965 | setVisualOffset_Widget( |
966 | w, visX + w->rect.size.x + safePad, 300, easeOut_AnimFlag | softer_AnimFlag); | ||
962 | } | 967 | } |
963 | else { | 968 | else { |
964 | setFlags_Widget(w, keepOnTop_WidgetFlag, iTrue); | 969 | setFlags_Widget(w, keepOnTop_WidgetFlag, iTrue); |
965 | setVisualOffset_Widget(w, -w->rect.size.x, 300, easeOut_AnimFlag | softer_AnimFlag); | 970 | setVisualOffset_Widget( |
971 | w, -w->rect.size.x - safePad, 300, easeOut_AnimFlag | softer_AnimFlag); | ||
966 | } | 972 | } |
967 | } | 973 | } |
968 | arrange_Widget(w->parent); | 974 | arrange_Widget(w->parent); |
diff --git a/src/ui/text.c b/src/ui/text.c index ffe08fca..8a2a9ff8 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -389,7 +389,9 @@ static void initCache_Text_(iText *d) { | |||
389 | d->cacheRowAllocStep = iMax(2, textSize / 6); | 389 | d->cacheRowAllocStep = iMax(2, textSize / 6); |
390 | /* Allocate initial (empty) rows. These will be assigned actual locations in the cache | 390 | /* Allocate initial (empty) rows. These will be assigned actual locations in the cache |
391 | once at least one glyph is stored. */ | 391 | once at least one glyph is stored. */ |
392 | for (int h = d->cacheRowAllocStep; h <= 2 * textSize + d->cacheRowAllocStep; h += d->cacheRowAllocStep) { | 392 | for (int h = d->cacheRowAllocStep; |
393 | h <= 2.5 * textSize + d->cacheRowAllocStep; | ||
394 | h += d->cacheRowAllocStep) { | ||
393 | pushBack_Array(&d->cacheRows, &(iCacheRow){ .height = 0 }); | 395 | pushBack_Array(&d->cacheRows, &(iCacheRow){ .height = 0 }); |
394 | } | 396 | } |
395 | d->cacheBottom = 0; | 397 | d->cacheBottom = 0; |
diff --git a/src/ui/touch.c b/src/ui/touch.c index 36bac267..dac1152e 100644 --- a/src/ui/touch.c +++ b/src/ui/touch.c | |||
@@ -65,6 +65,7 @@ struct Impl_Touch { | |||
65 | iBool isLeftDown; | 65 | iBool isLeftDown; |
66 | iBool isTouchDrag; | 66 | iBool isTouchDrag; |
67 | iBool isTapAndHold; | 67 | iBool isTapAndHold; |
68 | iBool didPostEdgeMove; | ||
68 | iBool didBeginOnTouchDrag; | 69 | iBool didBeginOnTouchDrag; |
69 | int pinchId; | 70 | int pinchId; |
70 | enum iTouchEdge edge; | 71 | enum iTouchEdge edge; |
@@ -391,6 +392,12 @@ static void checkNewPinch_TouchState_(iTouchState *d, iTouch *newTouch) { | |||
391 | pinch.touchIds[1] = other->id; | 392 | pinch.touchIds[1] = other->id; |
392 | newTouch->pinchId = other->pinchId = pinch.id; | 393 | newTouch->pinchId = other->pinchId = pinch.id; |
393 | clearWidgetMomentum_TouchState_(d, affinity); | 394 | clearWidgetMomentum_TouchState_(d, affinity); |
395 | if (other->edge && other->didPostEdgeMove) { | ||
396 | postCommandf_App("edgeswipe.ended abort:1 side:%d id:%llu", other->edge, other->id); | ||
397 | other->didPostEdgeMove = iFalse; | ||
398 | } | ||
399 | other->edge = none_TouchEdge; | ||
400 | newTouch->edge = none_TouchEdge; | ||
394 | /* Remember current positions to determine pinch amount. */ | 401 | /* Remember current positions to determine pinch amount. */ |
395 | newTouch->startPos = newTouch->pos[0]; | 402 | newTouch->startPos = newTouch->pos[0]; |
396 | other->startPos = other->pos[0]; | 403 | other->startPos = other->pos[0]; |
@@ -476,7 +483,6 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
476 | } | 483 | } |
477 | else if (x > rootSize.x - edgeWidth) { | 484 | else if (x > rootSize.x - edgeWidth) { |
478 | edge = right_TouchEdge; | 485 | edge = right_TouchEdge; |
479 | // puts("DOWN on right edge"); | ||
480 | } | 486 | } |
481 | iWidget *aff = hitChild_Window(window, init_I2(iRound(x), iRound(y_F3(pos)))); | 487 | iWidget *aff = hitChild_Window(window, init_I2(iRound(x), iRound(y_F3(pos)))); |
482 | #if 0 | 488 | #if 0 |
@@ -523,6 +529,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
523 | (int) (x_F3(pos) - x_F3(touch->startPos)), | 529 | (int) (x_F3(pos) - x_F3(touch->startPos)), |
524 | touch->edge, | 530 | touch->edge, |
525 | touch->id); | 531 | touch->id); |
532 | touch->didPostEdgeMove = iTrue; | ||
526 | return iTrue; | 533 | return iTrue; |
527 | } | 534 | } |
528 | if (touch && touch->affinity) { | 535 | if (touch && touch->affinity) { |
@@ -595,39 +602,6 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
595 | } | 602 | } |
596 | } | 603 | } |
597 | iAssert(touch->edge == none_TouchEdge); | 604 | iAssert(touch->edge == none_TouchEdge); |
598 | #if 0 | ||
599 | /* Edge swipe aborted? */ | ||
600 | if (touch->edge == left_TouchEdge) { | ||
601 | if (fing->dx < 0 && x_F3(touch->pos[0]) < tapRadiusPt_ * window->pixelRatio) { | ||
602 | touch->edge = none_TouchEdge; | ||
603 | if (touch->edgeDragging) { | ||
604 | setFlags_Widget(touch->edgeDragging, dragged_WidgetFlag, iFalse); | ||
605 | setVisualOffset_Widget(touch->edgeDragging, 0, 200, easeOut_AnimFlag); | ||
606 | touch->edgeDragging = NULL; | ||
607 | } | ||
608 | } | ||
609 | else if (touch->edgeDragging) { | ||
610 | setVisualOffset_Widget(touch->edgeDragging, x_F3(pos) - x_F3(touch->startPos), 10, 0); | ||
611 | } | ||
612 | } | ||
613 | if (touch->edge == right_TouchEdge) { | ||
614 | if (fing->dx > 0 && x_F3(touch->pos[0]) > window->size.x - tapRadiusPt_ * window->pixelRatio) { | ||
615 | puts("touch->edge==right returned to right edge, aborted"); | ||
616 | touch->edge = none_TouchEdge; | ||
617 | if (touch->edgeDragging) { | ||
618 | setFlags_Widget(touch->edgeDragging, dragged_WidgetFlag, iFalse); | ||
619 | setVisualOffset_Widget(touch->edgeDragging, 0, 200, easeOut_AnimFlag); | ||
620 | touch->edgeDragging = NULL; | ||
621 | } | ||
622 | } | ||
623 | else if (touch->edgeDragging) { | ||
624 | setVisualOffset_Widget(touch->edgeDragging, x_F3(pos) - x_F3(touch->startPos), 10, 0); | ||
625 | } | ||
626 | } | ||
627 | if (touch->edge) { | ||
628 | pixels.y = 0; | ||
629 | } | ||
630 | #endif | ||
631 | if (touch->axis == x_TouchAxis) { | 605 | if (touch->axis == x_TouchAxis) { |
632 | pixels.y = 0; | 606 | pixels.y = 0; |
633 | } | 607 | } |
@@ -671,7 +645,12 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
671 | } | 645 | } |
672 | #endif | 646 | #endif |
673 | if (touch->edge && !isStationary_Touch_(touch)) { | 647 | if (touch->edge && !isStationary_Touch_(touch)) { |
674 | postCommandf_App("edgeswipe.ended side:%d id:%llu", touch->edge, touch->id); | 648 | const iFloat3 gesture = gestureVector_Touch_(touch); |
649 | const float pixel = window->pixelRatio; | ||
650 | const int moveDir = x_F3(gesture) < -pixel ? -1 : x_F3(gesture) > pixel ? +1 : 0; | ||
651 | const int didAbort = (touch->edge == left_TouchEdge && moveDir < 0) || | ||
652 | (touch->edge == right_TouchEdge && moveDir > 0); | ||
653 | postCommandf_App("edgeswipe.ended abort:%d side:%d id:%llu", didAbort, touch->edge, touch->id); | ||
675 | remove_ArrayIterator(&i); | 654 | remove_ArrayIterator(&i); |
676 | continue; | 655 | continue; |
677 | } | 656 | } |
diff --git a/src/ui/widget.c b/src/ui/widget.c index 11ec1b07..85672c04 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -760,16 +760,24 @@ void arrange_Widget(iWidget *d) { | |||
760 | } | 760 | } |
761 | 761 | ||
762 | iBool isBeingVisuallyOffsetByReference_Widget(const iWidget *d) { | 762 | iBool isBeingVisuallyOffsetByReference_Widget(const iWidget *d) { |
763 | if (d->flags & refChildrenOffset_WidgetFlag) { | 763 | return visualOffsetByReference_Widget(d) != 0; |
764 | } | ||
765 | |||
766 | int visualOffsetByReference_Widget(const iWidget *d) { | ||
767 | if (d->offsetRef && d->flags & refChildrenOffset_WidgetFlag) { | ||
768 | int offX = 0; | ||
764 | iConstForEach(ObjectList, i, children_Widget(d->offsetRef)) { | 769 | iConstForEach(ObjectList, i, children_Widget(d->offsetRef)) { |
765 | const iWidget *child = i.object; | 770 | const iWidget *child = i.object; |
766 | if (child == d) continue; | 771 | if (child == d) continue; |
767 | if (child->flags & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { | 772 | if (child->flags & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { |
768 | return iTrue; | 773 | // const float factor = width_Widget(d) / (float) size_Root(d->root).x; |
774 | const int invOff = width_Widget(d) - iRound(value_Anim(&child->visualOffset)); | ||
775 | offX -= invOff / 4; | ||
769 | } | 776 | } |
770 | } | 777 | } |
778 | return offX; | ||
771 | } | 779 | } |
772 | return iFalse; | 780 | return 0; |
773 | } | 781 | } |
774 | 782 | ||
775 | static void applyVisualOffset_Widget_(const iWidget *d, iInt2 *pos) { | 783 | static void applyVisualOffset_Widget_(const iWidget *d, iInt2 *pos) { |
@@ -786,14 +794,7 @@ static void applyVisualOffset_Widget_(const iWidget *d, iInt2 *pos) { | |||
786 | pos->y -= value_Anim(d->animOffsetRef); | 794 | pos->y -= value_Anim(d->animOffsetRef); |
787 | } | 795 | } |
788 | if (d->flags & refChildrenOffset_WidgetFlag) { | 796 | if (d->flags & refChildrenOffset_WidgetFlag) { |
789 | iConstForEach(ObjectList, i, children_Widget(d->offsetRef)) { | 797 | pos->x += visualOffsetByReference_Widget(d); |
790 | const iWidget *child = i.object; | ||
791 | if (child == d) continue; | ||
792 | if (child->flags & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { | ||
793 | const int invOff = size_Root(d->root).x - iRound(value_Anim(&child->visualOffset)); | ||
794 | pos->x -= invOff / 4; | ||
795 | } | ||
796 | } | ||
797 | } | 798 | } |
798 | } | 799 | } |
799 | 800 | ||
@@ -1081,7 +1082,9 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) { | |||
1081 | if (~d->flags & dragged_WidgetFlag) { | 1082 | if (~d->flags & dragged_WidgetFlag) { |
1082 | setFlags_Widget(d, dragged_WidgetFlag, iTrue); | 1083 | setFlags_Widget(d, dragged_WidgetFlag, iTrue); |
1083 | } | 1084 | } |
1084 | setVisualOffset_Widget(d, arg_Command(command_UserEvent(ev)), 10, 0); | 1085 | setVisualOffset_Widget(d, arg_Command(command_UserEvent(ev)) * |
1086 | width_Widget(d) / size_Root(d->root).x, | ||
1087 | 10, 0); | ||
1085 | return iTrue; | 1088 | return iTrue; |
1086 | } | 1089 | } |
1087 | } | 1090 | } |
@@ -1129,6 +1132,17 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) { | |||
1129 | return iFalse; | 1132 | return iFalse; |
1130 | } | 1133 | } |
1131 | 1134 | ||
1135 | int backgroundFadeColor_Widget(void) { | ||
1136 | switch (colorTheme_App()) { | ||
1137 | case light_ColorTheme: | ||
1138 | return gray25_ColorId; | ||
1139 | case pureWhite_ColorTheme: | ||
1140 | return gray50_ColorId; | ||
1141 | default: | ||
1142 | return black_ColorId; | ||
1143 | } | ||
1144 | } | ||
1145 | |||
1132 | void drawBackground_Widget(const iWidget *d) { | 1146 | void drawBackground_Widget(const iWidget *d) { |
1133 | if (d->flags & noBackground_WidgetFlag) { | 1147 | if (d->flags & noBackground_WidgetFlag) { |
1134 | return; | 1148 | return; |
@@ -1151,8 +1165,7 @@ void drawBackground_Widget(const iWidget *d) { | |||
1151 | drawSoftShadow_Paint(&p, bounds_Widget(d), 12 * gap_UI, black_ColorId, 30); | 1165 | drawSoftShadow_Paint(&p, bounds_Widget(d), 12 * gap_UI, black_ColorId, 30); |
1152 | } | 1166 | } |
1153 | const iBool isFaded = fadeBackground && | 1167 | const iBool isFaded = fadeBackground && |
1154 | ~d->flags & noFadeBackground_WidgetFlag;/* && | 1168 | ~d->flags & noFadeBackground_WidgetFlag; |
1155 | ~d->flags & destroyPending_WidgetFlag;*/ | ||
1156 | if (isFaded) { | 1169 | if (isFaded) { |
1157 | iPaint p; | 1170 | iPaint p; |
1158 | init_Paint(&p); | 1171 | init_Paint(&p); |
@@ -1163,19 +1176,7 @@ void drawBackground_Widget(const iWidget *d) { | |||
1163 | p.alpha *= (area > 0 ? visibleArea / area : 0.0f); | 1176 | p.alpha *= (area > 0 ? visibleArea / area : 0.0f); |
1164 | } | 1177 | } |
1165 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); | 1178 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); |
1166 | int fadeColor; | 1179 | fillRect_Paint(&p, rect_Root(d->root), backgroundFadeColor_Widget()); |
1167 | switch (colorTheme_App()) { | ||
1168 | default: | ||
1169 | fadeColor = black_ColorId; | ||
1170 | break; | ||
1171 | case light_ColorTheme: | ||
1172 | fadeColor = gray25_ColorId; | ||
1173 | break; | ||
1174 | case pureWhite_ColorTheme: | ||
1175 | fadeColor = gray50_ColorId; | ||
1176 | break; | ||
1177 | } | ||
1178 | fillRect_Paint(&p, rect_Root(d->root), fadeColor); | ||
1179 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); | 1180 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); |
1180 | } | 1181 | } |
1181 | if (d->bgColor >= 0 || d->frameColor >= 0) { | 1182 | if (d->bgColor >= 0 || d->frameColor >= 0) { |
diff --git a/src/ui/widget.h b/src/ui/widget.h index b2310f21..acb8fa9d 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h | |||
@@ -242,10 +242,9 @@ iBool isSelected_Widget (const iAnyObject *); | |||
242 | iBool isUnderKeyRoot_Widget (const iAnyObject *); | 242 | iBool isUnderKeyRoot_Widget (const iAnyObject *); |
243 | iBool isCommand_Widget (const iWidget *d, const SDL_Event *ev, const char *cmd); | 243 | iBool isCommand_Widget (const iWidget *d, const SDL_Event *ev, const char *cmd); |
244 | iBool hasParent_Widget (const iWidget *d, const iWidget *someParent); | 244 | iBool hasParent_Widget (const iWidget *d, const iWidget *someParent); |
245 | iBool isAffectedByVisualOffset_Widget | 245 | iBool isAffectedByVisualOffset_Widget (const iWidget *); |
246 | (const iWidget *); | 246 | iBool isBeingVisuallyOffsetByReference_Widget (const iWidget *); |
247 | iBool isBeingVisuallyOffsetByReference_Widget | 247 | int visualOffsetByReference_Widget (const iWidget *); |
248 | (const iWidget *); | ||
249 | void setId_Widget (iWidget *, const char *id); | 248 | void setId_Widget (iWidget *, const char *id); |
250 | void setFlags_Widget (iWidget *, int64_t flags, iBool set); | 249 | void setFlags_Widget (iWidget *, int64_t flags, iBool set); |
251 | void setPos_Widget (iWidget *, iInt2 pos); | 250 | void setPos_Widget (iWidget *, iInt2 pos); |
@@ -278,6 +277,8 @@ void refresh_Widget (const iAnyObject *); | |||
278 | 277 | ||
279 | iBool equalWidget_Command (const char *cmd, const iWidget *widget, const char *checkCommand); | 278 | iBool equalWidget_Command (const char *cmd, const iWidget *widget, const char *checkCommand); |
280 | 279 | ||
280 | int backgroundFadeColor_Widget (void); | ||
281 | |||
281 | void setFocus_Widget (iWidget *); | 282 | void setFocus_Widget (iWidget *); |
282 | iWidget * focus_Widget (void); | 283 | iWidget * focus_Widget (void); |
283 | void setHover_Widget (iWidget *); | 284 | void setHover_Widget (iWidget *); |