diff options
-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 *); |