diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-15 07:44:49 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-15 07:44:49 +0300 |
commit | a308db056515f8fb30be36d6ff028b788626465c (patch) | |
tree | 8ace58b91bebc7fcca27d0d2a09816cb198d05c8 /src | |
parent | a0ebaca4600d38df843244bda5f54a75d7c59d83 (diff) |
Init and scroll position improvements
Scroll positions are saved as normalized positions so they don’t get affected by zoom differences.
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 3 | ||||
-rw-r--r-- | src/history.c | 16 | ||||
-rw-r--r-- | src/history.h | 2 | ||||
-rw-r--r-- | src/ui/command.c | 9 | ||||
-rw-r--r-- | src/ui/command.h | 1 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 36 | ||||
-rw-r--r-- | src/ui/documentwidget.h | 2 |
7 files changed, 47 insertions, 22 deletions
@@ -255,6 +255,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
255 | #endif | 255 | #endif |
256 | d->window = new_Window(d->initialWindowRect); | 256 | d->window = new_Window(d->initialWindowRect); |
257 | /* Widget state init. */ | 257 | /* Widget state init. */ |
258 | processEvents_App(postedEventsOnly_AppEventMode); | ||
258 | if (!loadState_App_(d)) { | 259 | if (!loadState_App_(d)) { |
259 | postCommand_App("navigate.home"); | 260 | postCommand_App("navigate.home"); |
260 | } | 261 | } |
@@ -512,7 +513,7 @@ iBool handleCommand_App(const char *cmd) { | |||
512 | } | 513 | } |
513 | } | 514 | } |
514 | visitUrl_Visited(d->visited, url); | 515 | visitUrl_Visited(d->visited, url); |
515 | setInitialScroll_DocumentWidget(doc, argLabel_Command(cmd, "scroll") * gap_UI); | 516 | setInitialScroll_DocumentWidget(doc, argfLabel_Command(cmd, "scroll")); |
516 | setUrlFromCache_DocumentWidget(doc, url, isHistory); | 517 | setUrlFromCache_DocumentWidget(doc, url, isHistory); |
517 | } | 518 | } |
518 | else if (equal_Command(cmd, "document.request.cancelled")) { | 519 | else if (equal_Command(cmd, "document.request.cancelled")) { |
diff --git a/src/history.c b/src/history.c index 9779795a..24912d81 100644 --- a/src/history.c +++ b/src/history.c | |||
@@ -8,7 +8,7 @@ static const size_t maxStack_History_ = 50; /* back/forward navigable items */ | |||
8 | 8 | ||
9 | void init_RecentUrl(iRecentUrl *d) { | 9 | void init_RecentUrl(iRecentUrl *d) { |
10 | init_String(&d->url); | 10 | init_String(&d->url); |
11 | d->scrollY = 0; | 11 | d->normScrollY = 0; |
12 | d->cachedResponse = NULL; | 12 | d->cachedResponse = NULL; |
13 | } | 13 | } |
14 | 14 | ||
@@ -22,7 +22,7 @@ iDefineTypeConstruction(RecentUrl) | |||
22 | iRecentUrl *copy_RecentUrl(const iRecentUrl *d) { | 22 | iRecentUrl *copy_RecentUrl(const iRecentUrl *d) { |
23 | iRecentUrl *copy = new_RecentUrl(); | 23 | iRecentUrl *copy = new_RecentUrl(); |
24 | set_String(©->url, &d->url); | 24 | set_String(©->url, &d->url); |
25 | copy->scrollY = d->scrollY; | 25 | copy->normScrollY = d->normScrollY; |
26 | copy->cachedResponse = d->cachedResponse ? copy_GmResponse(d->cachedResponse) : NULL; | 26 | copy->cachedResponse = d->cachedResponse ? copy_GmResponse(d->cachedResponse) : NULL; |
27 | return copy; | 27 | return copy; |
28 | } | 28 | } |
@@ -61,7 +61,7 @@ void serialize_History(const iHistory *d, iStream *outs) { | |||
61 | iConstForEach(Array, i, &d->recent) { | 61 | iConstForEach(Array, i, &d->recent) { |
62 | const iRecentUrl *item = i.value; | 62 | const iRecentUrl *item = i.value; |
63 | serialize_String(&item->url, outs); | 63 | serialize_String(&item->url, outs); |
64 | write32_Stream(outs, item->scrollY); | 64 | write32_Stream(outs, item->normScrollY * 1.0e6f); |
65 | if (item->cachedResponse) { | 65 | if (item->cachedResponse) { |
66 | write8_Stream(outs, 1); | 66 | write8_Stream(outs, 1); |
67 | serialize_GmResponse(item->cachedResponse, outs); | 67 | serialize_GmResponse(item->cachedResponse, outs); |
@@ -80,7 +80,7 @@ void deserialize_History(iHistory *d, iStream *ins) { | |||
80 | iRecentUrl item; | 80 | iRecentUrl item; |
81 | init_RecentUrl(&item); | 81 | init_RecentUrl(&item); |
82 | deserialize_String(&item.url, ins); | 82 | deserialize_String(&item.url, ins); |
83 | item.scrollY = read32_Stream(ins); | 83 | item.normScrollY = (float) read32_Stream(ins) / 1.0e6f; |
84 | if (read8_Stream(ins)) { | 84 | if (read8_Stream(ins)) { |
85 | item.cachedResponse = new_GmResponse(); | 85 | item.cachedResponse = new_GmResponse(); |
86 | deserialize_GmResponse(item.cachedResponse, ins); | 86 | deserialize_GmResponse(item.cachedResponse, ins); |
@@ -166,8 +166,8 @@ void add_History(iHistory *d, const iString *url ){ | |||
166 | iBool goBack_History(iHistory *d) { | 166 | iBool goBack_History(iHistory *d) { |
167 | if (d->recentPos < size_Array(&d->recent) - 1) { | 167 | if (d->recentPos < size_Array(&d->recent) - 1) { |
168 | d->recentPos++; | 168 | d->recentPos++; |
169 | postCommandf_App("open history:1 scroll:%d url:%s", | 169 | postCommandf_App("open history:1 scroll:%f url:%s", |
170 | mostRecentUrl_History(d)->scrollY, | 170 | mostRecentUrl_History(d)->normScrollY, |
171 | cstr_String(url_History(d, d->recentPos))); | 171 | cstr_String(url_History(d, d->recentPos))); |
172 | return iTrue; | 172 | return iTrue; |
173 | } | 173 | } |
@@ -177,7 +177,9 @@ iBool goBack_History(iHistory *d) { | |||
177 | iBool goForward_History(iHistory *d) { | 177 | iBool goForward_History(iHistory *d) { |
178 | if (d->recentPos > 0) { | 178 | if (d->recentPos > 0) { |
179 | d->recentPos--; | 179 | d->recentPos--; |
180 | postCommandf_App("open history:1 url:%s", cstr_String(url_History(d, d->recentPos))); | 180 | postCommandf_App("open history:1 scroll:%f url:%s", |
181 | mostRecentUrl_History(d)->normScrollY, | ||
182 | cstr_String(url_History(d, d->recentPos))); | ||
181 | return iTrue; | 183 | return iTrue; |
182 | } | 184 | } |
183 | return iFalse; | 185 | return iFalse; |
diff --git a/src/history.h b/src/history.h index 6ccfd199..cf3a46be 100644 --- a/src/history.h +++ b/src/history.h | |||
@@ -11,7 +11,7 @@ iDeclareTypeConstruction(RecentUrl) | |||
11 | 11 | ||
12 | struct Impl_RecentUrl { | 12 | struct Impl_RecentUrl { |
13 | iString url; | 13 | iString url; |
14 | int scrollY; /* unit is gap_UI */ | 14 | float normScrollY; /* normalized to document height */ |
15 | iGmResponse *cachedResponse; /* kept in memory for quicker back navigation */ | 15 | iGmResponse *cachedResponse; /* kept in memory for quicker back navigation */ |
16 | }; | 16 | }; |
17 | 17 | ||
diff --git a/src/ui/command.c b/src/ui/command.c index c0828343..19228e46 100644 --- a/src/ui/command.c +++ b/src/ui/command.c | |||
@@ -28,6 +28,15 @@ int arg_Command(const char *cmd) { | |||
28 | return argLabel_Command(cmd, "arg"); | 28 | return argLabel_Command(cmd, "arg"); |
29 | } | 29 | } |
30 | 30 | ||
31 | float argfLabel_Command(const char *cmd, const char *label) { | ||
32 | const iString *tok = tokenString_(label); | ||
33 | const char *ptr = strstr(cmd, cstr_String(tok)); | ||
34 | if (ptr) { | ||
35 | return strtof(ptr + size_String(tok), NULL); | ||
36 | } | ||
37 | return 0.0f; | ||
38 | } | ||
39 | |||
31 | float argf_Command(const char *cmd) { | 40 | float argf_Command(const char *cmd) { |
32 | const char *ptr = strstr(cmd, " arg:"); | 41 | const char *ptr = strstr(cmd, " arg:"); |
33 | if (ptr) { | 42 | if (ptr) { |
diff --git a/src/ui/command.h b/src/ui/command.h index aed4a0f2..2124d527 100644 --- a/src/ui/command.h +++ b/src/ui/command.h | |||
@@ -7,6 +7,7 @@ iBool equal_Command (const char *commandWithArgs, const char *comman | |||
7 | int arg_Command (const char *); /* arg: */ | 7 | int arg_Command (const char *); /* arg: */ |
8 | float argf_Command (const char *); /* arg: */ | 8 | float argf_Command (const char *); /* arg: */ |
9 | int argLabel_Command (const char *, const char *label); | 9 | int argLabel_Command (const char *, const char *label); |
10 | float argfLabel_Command (const char *, const char *label); | ||
10 | void * pointer_Command (const char *); /* ptr: */ | 11 | void * pointer_Command (const char *); /* ptr: */ |
11 | void * pointerLabel_Command (const char *, const char *label); | 12 | void * pointerLabel_Command (const char *, const char *label); |
12 | iInt2 coord_Command (const char *); | 13 | iInt2 coord_Command (const char *); |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index a04e1216..d425b8a9 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -131,7 +131,7 @@ struct Impl_DocumentWidget { | |||
131 | const iGmRun *hoverLink; | 131 | const iGmRun *hoverLink; |
132 | iBool noHoverWhileScrolling; | 132 | iBool noHoverWhileScrolling; |
133 | iClick click; | 133 | iClick click; |
134 | int initialScrollY; | 134 | float initialNormScrollY; |
135 | int scrollY; | 135 | int scrollY; |
136 | iScrollWidget *scroll; | 136 | iScrollWidget *scroll; |
137 | iWidget *menu; | 137 | iWidget *menu; |
@@ -157,7 +157,7 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
157 | d->isRequestUpdated = iFalse; | 157 | d->isRequestUpdated = iFalse; |
158 | d->media = new_ObjectList(); | 158 | d->media = new_ObjectList(); |
159 | d->doc = new_GmDocument(); | 159 | d->doc = new_GmDocument(); |
160 | d->initialScrollY = 0; | 160 | d->initialNormScrollY = 0; |
161 | d->scrollY = 0; | 161 | d->scrollY = 0; |
162 | d->selecting = iFalse; | 162 | d->selecting = iFalse; |
163 | d->selectMark = iNullRange; | 163 | d->selectMark = iNullRange; |
@@ -262,6 +262,14 @@ static void addVisibleLink_DocumentWidget_(void *context, const iGmRun *run) { | |||
262 | } | 262 | } |
263 | } | 263 | } |
264 | 264 | ||
265 | static float normScrollPos_DocumentWidget_(const iDocumentWidget *d) { | ||
266 | const int docSize = size_GmDocument(d->doc).y; | ||
267 | if (docSize) { | ||
268 | return (float) d->scrollY / (float) docSize; | ||
269 | } | ||
270 | return 0; | ||
271 | } | ||
272 | |||
265 | static int scrollMax_DocumentWidget_(const iDocumentWidget *d) { | 273 | static int scrollMax_DocumentWidget_(const iDocumentWidget *d) { |
266 | return size_GmDocument(d->doc).y - height_Rect(bounds_Widget(constAs_Widget(d))) + | 274 | return size_GmDocument(d->doc).y - height_Rect(bounds_Widget(constAs_Widget(d))) + |
267 | 2 * d->pageMargin * gap_UI; | 275 | 2 * d->pageMargin * gap_UI; |
@@ -307,8 +315,8 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) { | |||
307 | updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window())); | 315 | updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window())); |
308 | /* Remember scroll positions of recently visited pages. */ { | 316 | /* Remember scroll positions of recently visited pages. */ { |
309 | iRecentUrl *recent = mostRecentUrl_History(d->mod.history); | 317 | iRecentUrl *recent = mostRecentUrl_History(d->mod.history); |
310 | if (recent) { | 318 | if (recent && docSize && d->state == ready_RequestState) { |
311 | recent->scrollY = d->scrollY / gap_UI; | 319 | recent->normScrollY = normScrollPos_DocumentWidget_(d); |
312 | } | 320 | } |
313 | } | 321 | } |
314 | } | 322 | } |
@@ -505,7 +513,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse | |||
505 | return; | 513 | return; |
506 | } | 514 | } |
507 | /* Convert the source to UTF-8 if needed. */ | 515 | /* Convert the source to UTF-8 if needed. */ |
508 | if (!equal_Rangecc(&charset, "utf-8")) { | 516 | if (!equalCase_Rangecc(&charset, "utf-8")) { |
509 | set_String(&str, | 517 | set_String(&str, |
510 | collect_String(decode_Block(&str.chars, cstr_Rangecc(charset)))); | 518 | collect_String(decode_Block(&str.chars, cstr_Rangecc(charset)))); |
511 | } | 519 | } |
@@ -577,11 +585,13 @@ static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) { | |||
577 | if (recent && recent->cachedResponse) { | 585 | if (recent && recent->cachedResponse) { |
578 | const iGmResponse *resp = recent->cachedResponse; | 586 | const iGmResponse *resp = recent->cachedResponse; |
579 | d->state = fetching_RequestState; | 587 | d->state = fetching_RequestState; |
588 | d->initialNormScrollY = recent->normScrollY; | ||
580 | /* Use the cached response data. */ | 589 | /* Use the cached response data. */ |
581 | d->scrollY = d->initialScrollY = recent->scrollY * gap_UI; | ||
582 | updateTrust_DocumentWidget_(d, resp); | 590 | updateTrust_DocumentWidget_(d, resp); |
583 | updateDocument_DocumentWidget_(d, resp); | 591 | updateDocument_DocumentWidget_(d, resp); |
592 | d->scrollY = d->initialNormScrollY * size_GmDocument(d->doc).y; | ||
584 | d->state = ready_RequestState; | 593 | d->state = ready_RequestState; |
594 | updateVisible_DocumentWidget_(d); | ||
585 | postCommandf_App("document.changed doc:%p url:%s", d, cstr_String(d->mod.url)); | 595 | postCommandf_App("document.changed doc:%p url:%s", d, cstr_String(d->mod.url)); |
586 | return iTrue; | 596 | return iTrue; |
587 | } | 597 | } |
@@ -621,8 +631,8 @@ void setUrlFromCache_DocumentWidget(iDocumentWidget *d, const iString *url, iBoo | |||
621 | iDocumentWidget *duplicate_DocumentWidget(const iDocumentWidget *orig) { | 631 | iDocumentWidget *duplicate_DocumentWidget(const iDocumentWidget *orig) { |
622 | iDocumentWidget *d = new_DocumentWidget(); | 632 | iDocumentWidget *d = new_DocumentWidget(); |
623 | delete_History(d->mod.history); | 633 | delete_History(d->mod.history); |
624 | d->initialScrollY = orig->scrollY; | 634 | d->initialNormScrollY = normScrollPos_DocumentWidget_(d); |
625 | d->mod.history = copy_History(orig->mod.history); | 635 | d->mod.history = copy_History(orig->mod.history); |
626 | setUrlFromCache_DocumentWidget(d, orig->mod.url, iTrue); | 636 | setUrlFromCache_DocumentWidget(d, orig->mod.url, iTrue); |
627 | return d; | 637 | return d; |
628 | } | 638 | } |
@@ -631,8 +641,8 @@ void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { | |||
631 | setUrlFromCache_DocumentWidget(d, url, iFalse); | 641 | setUrlFromCache_DocumentWidget(d, url, iFalse); |
632 | } | 642 | } |
633 | 643 | ||
634 | void setInitialScroll_DocumentWidget (iDocumentWidget *d, int scrollY) { | 644 | void setInitialScroll_DocumentWidget(iDocumentWidget *d, float normScrollY) { |
635 | d->initialScrollY = scrollY; | 645 | d->initialNormScrollY = normScrollY; |
636 | } | 646 | } |
637 | 647 | ||
638 | iBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) { | 648 | iBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) { |
@@ -691,7 +701,7 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) { | |||
691 | break; | 701 | break; |
692 | } | 702 | } |
693 | case categorySuccess_GmStatusCode: | 703 | case categorySuccess_GmStatusCode: |
694 | d->scrollY = d->initialScrollY; | 704 | d->scrollY = 0; |
695 | reset_GmDocument(d->doc); /* new content incoming */ | 705 | reset_GmDocument(d->doc); /* new content incoming */ |
696 | updateDocument_DocumentWidget_(d, response_GmRequest(d->request)); | 706 | updateDocument_DocumentWidget_(d, response_GmRequest(d->request)); |
697 | break; | 707 | break; |
@@ -944,9 +954,11 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
944 | else if (equalWidget_Command(cmd, w, "document.request.finished") && | 954 | else if (equalWidget_Command(cmd, w, "document.request.finished") && |
945 | pointerLabel_Command(cmd, "request") == d->request) { | 955 | pointerLabel_Command(cmd, "request") == d->request) { |
946 | checkResponse_DocumentWidget_(d); | 956 | checkResponse_DocumentWidget_(d); |
957 | d->scrollY = d->initialNormScrollY * size_GmDocument(d->doc).y; | ||
947 | d->state = ready_RequestState; | 958 | d->state = ready_RequestState; |
948 | setCachedResponse_History(d->mod.history, response_GmRequest(d->request)); | 959 | setCachedResponse_History(d->mod.history, response_GmRequest(d->request)); |
949 | iReleasePtr(&d->request); | 960 | iReleasePtr(&d->request); |
961 | updateVisible_DocumentWidget_(d); | ||
950 | postCommandf_App("document.changed url:%s", cstr_String(d->mod.url)); | 962 | postCommandf_App("document.changed url:%s", cstr_String(d->mod.url)); |
951 | return iFalse; | 963 | return iFalse; |
952 | } | 964 | } |
@@ -971,7 +983,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
971 | return handleMediaCommand_DocumentWidget_(d, cmd); | 983 | return handleMediaCommand_DocumentWidget_(d, cmd); |
972 | } | 984 | } |
973 | else if (equal_Command(cmd, "document.reload") && document_App() == d) { | 985 | else if (equal_Command(cmd, "document.reload") && document_App() == d) { |
974 | d->initialScrollY = d->scrollY; | 986 | d->initialNormScrollY = normScrollPos_DocumentWidget_(d); |
975 | fetch_DocumentWidget_(d); | 987 | fetch_DocumentWidget_(d); |
976 | return iTrue; | 988 | return iTrue; |
977 | } | 989 | } |
diff --git a/src/ui/documentwidget.h b/src/ui/documentwidget.h index 98591901..074516c3 100644 --- a/src/ui/documentwidget.h +++ b/src/ui/documentwidget.h | |||
@@ -22,6 +22,6 @@ const iString * bookmarkTitle_DocumentWidget (const iDocumentWidget *); | |||
22 | 22 | ||
23 | void setUrl_DocumentWidget (iDocumentWidget *, const iString *url); | 23 | void setUrl_DocumentWidget (iDocumentWidget *, const iString *url); |
24 | void setUrlFromCache_DocumentWidget (iDocumentWidget *, const iString *url, iBool isFromCache); | 24 | void setUrlFromCache_DocumentWidget (iDocumentWidget *, const iString *url, iBool isFromCache); |
25 | void setInitialScroll_DocumentWidget (iDocumentWidget *, int scrollY); /* set after content received */ | 25 | void setInitialScroll_DocumentWidget (iDocumentWidget *, float normScrollY); /* set after content received */ |
26 | 26 | ||
27 | void updateSize_DocumentWidget (iDocumentWidget *); | 27 | void updateSize_DocumentWidget (iDocumentWidget *); |