summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-11-21 11:48:07 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-11-21 11:48:07 +0200
commit0b2b40a233c014e684f6efed0298efda02e7abf4 (patch)
treea1bc3a095b57279cd27b5ef65498b7c9a0fcf457 /src/ui
parentc651680715f7549a0cdbdbb10d535cba2272d9d0 (diff)
Added option to load image instead of scrolling
One can now read through a page and load all inline images simply by repeatedly pressing Space or cursor down. Key repeat events do not trigger image loads.
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/documentwidget.c44
-rw-r--r--src/ui/keys.c67
-rw-r--r--src/ui/keys.h1
-rw-r--r--src/ui/util.c2
4 files changed, 79 insertions, 35 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 59f5a92c..0fc969ba 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -1151,10 +1151,8 @@ static iMediaRequest *findMediaRequest_DocumentWidget_(const iDocumentWidget *d,
1151 1151
1152static iBool requestMedia_DocumentWidget_(iDocumentWidget *d, iGmLinkId linkId) { 1152static iBool requestMedia_DocumentWidget_(iDocumentWidget *d, iGmLinkId linkId) {
1153 if (!findMediaRequest_DocumentWidget_(d, linkId)) { 1153 if (!findMediaRequest_DocumentWidget_(d, linkId)) {
1154 pushBack_ObjectList( 1154 const iString *imageUrl = absoluteUrl_String(d->mod.url, linkUrl_GmDocument(d->doc, linkId));
1155 d->media, 1155 pushBack_ObjectList(d->media, iClob(new_MediaRequest(d, linkId, imageUrl)));
1156 iClob(new_MediaRequest(
1157 d, linkId, absoluteUrl_String(d->mod.url, linkUrl_GmDocument(d->doc, linkId)))));
1158 invalidate_DocumentWidget_(d); 1156 invalidate_DocumentWidget_(d);
1159 return iTrue; 1157 return iTrue;
1160 } 1158 }
@@ -1235,6 +1233,22 @@ static void allocVisBuffer_DocumentWidget_(const iDocumentWidget *d) {
1235 } 1233 }
1236} 1234}
1237 1235
1236static iBool fetchNextUnfetchedImage_DocumentWidget_(iDocumentWidget *d) {
1237 iConstForEach(PtrArray, i, &d->visibleLinks) {
1238 const iGmRun *run = i.ptr;
1239 if (run->linkId && !run->imageId && ~run->flags & decoration_GmRunFlag) {
1240 const int linkFlags = linkFlags_GmDocument(d->doc, run->linkId);
1241 if (isMediaLink_GmDocument(d->doc, run->linkId) &&
1242 ~linkFlags & content_GmLinkFlag && ~linkFlags & permanent_GmLinkFlag ) {
1243 if (requestMedia_DocumentWidget_(d, run->linkId)) {
1244 return iTrue;
1245 }
1246 }
1247 }
1248 }
1249 return iFalse;
1250}
1251
1238static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { 1252static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
1239 iWidget *w = as_Widget(d); 1253 iWidget *w = as_Widget(d);
1240 if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "font.changed")) { 1254 if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "font.changed")) {
@@ -1572,13 +1586,16 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1572 return iTrue; 1586 return iTrue;
1573 } 1587 }
1574 else if (equal_Command(cmd, "scroll.page") && document_App() == d) { 1588 else if (equal_Command(cmd, "scroll.page") && document_App() == d) {
1575 if (argLabel_Command(cmd, "repeat")) { 1589 const int dir = arg_Command(cmd);
1576 /* TODO: Adjust scroll animation to be linear during repeated scroll? */ 1590 if (!argLabel_Command(cmd, "repeat") && prefs_App()->loadImageInsteadOfScrolling &&
1591 dir > 0) {
1592 if (fetchNextUnfetchedImage_DocumentWidget_(d)) {
1593 return iTrue;
1594 }
1577 } 1595 }
1578 smoothScroll_DocumentWidget_(d, 1596 smoothScroll_DocumentWidget_(d,
1579 arg_Command(cmd) * 1597 dir * (0.5f * height_Rect(documentBounds_DocumentWidget_(d)) -
1580 (0.5f * height_Rect(documentBounds_DocumentWidget_(d)) - 1598 0 * lineHeight_Text(paragraph_FontId)),
1581 0 * lineHeight_Text(paragraph_FontId)),
1582 smoothDuration_DocumentWidget_); 1599 smoothDuration_DocumentWidget_);
1583 return iTrue; 1600 return iTrue;
1584 } 1601 }
@@ -1599,8 +1616,15 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1599 return iTrue; 1616 return iTrue;
1600 } 1617 }
1601 else if (equal_Command(cmd, "scroll.step") && document_App() == d) { 1618 else if (equal_Command(cmd, "scroll.step") && document_App() == d) {
1619 const int dir = arg_Command(cmd);
1620 if (!argLabel_Command(cmd, "repeat") && prefs_App()->loadImageInsteadOfScrolling &&
1621 dir > 0) {
1622 if (fetchNextUnfetchedImage_DocumentWidget_(d)) {
1623 return iTrue;
1624 }
1625 }
1602 smoothScroll_DocumentWidget_(d, 1626 smoothScroll_DocumentWidget_(d,
1603 3 * lineHeight_Text(paragraph_FontId) * arg_Command(cmd), 1627 3 * lineHeight_Text(paragraph_FontId) * dir,
1604 smoothDuration_DocumentWidget_); 1628 smoothDuration_DocumentWidget_);
1605 return iTrue; 1629 return iTrue;
1606 } 1630 }
diff --git a/src/ui/keys.c b/src/ui/keys.c
index 5b88bfcf..ea874343 100644
--- a/src/ui/keys.c
+++ b/src/ui/keys.c
@@ -56,25 +56,46 @@ static void clear_Keys_(iKeys *d) {
56 } 56 }
57} 57}
58 58
59enum iBindFlag {
60 argRepeat_BindFlag = iBit(1),
61};
62
59/* TODO: This indirection could be used for localization, although all UI strings 63/* TODO: This indirection could be used for localization, although all UI strings
60 would need to be similarly handled. */ 64 would need to be similarly handled. */
61static const struct { int id; iMenuItem bind; } defaultBindings_[] = { 65static const struct { int id; iMenuItem bind; int flags; } defaultBindings_[] = {
62 { 1, { "Jump to top", SDLK_HOME, 0, "scroll.top" } }, 66 { 1, { "Jump to top", SDLK_HOME, 0, "scroll.top" }, 0 },
63 { 2, { "Jump to bottom", SDLK_END, 0, "scroll.bottom" } }, 67 { 2, { "Jump to bottom", SDLK_END, 0, "scroll.bottom" }, 0 },
64 { 10, { "Scroll up", SDLK_UP, 0, "scroll.step arg:-1" } }, 68 { 10, { "Scroll up", SDLK_UP, 0, "scroll.step arg:-1" }, argRepeat_BindFlag },
65 { 11, { "Scroll down", SDLK_DOWN, 0, "scroll.step arg:1" } }, 69 { 11, { "Scroll down", SDLK_DOWN, 0, "scroll.step arg:1" }, argRepeat_BindFlag },
66 { 20, { "Scroll up half a page", SDLK_PAGEUP, 0, "scroll.page arg:-1" } }, 70 { 20, { "Scroll up half a page", SDLK_PAGEUP, 0, "scroll.page arg:-1" }, argRepeat_BindFlag },
67 { 21, { "Scroll down half a page", SDLK_PAGEDOWN, 0, "scroll.page arg:1" } }, 71 { 21, { "Scroll down half a page", SDLK_PAGEDOWN, 0, "scroll.page arg:1" }, argRepeat_BindFlag },
68 { 30, { "Go back", navigateBack_KeyShortcut, "navigate.back" } }, 72 { 30, { "Go back", navigateBack_KeyShortcut, "navigate.back" }, 0 },
69 { 31, { "Go forward", navigateForward_KeyShortcut, "navigate.forward" } }, 73 { 31, { "Go forward", navigateForward_KeyShortcut, "navigate.forward" }, 0 },
70 { 32, { "Go to parent directory", navigateParent_KeyShortcut, "navigate.parent" } }, 74 { 32, { "Go to parent directory", navigateParent_KeyShortcut, "navigate.parent" }, 0 },
71 { 33, { "Go to site root", navigateRoot_KeyShortcut, "navigate.root" } }, 75 { 33, { "Go to site root", navigateRoot_KeyShortcut, "navigate.root" }, 0 },
72 { 40, { "Open link via keyboard", 'f', 0, "document.linkkeys"} }, 76 { 40, { "Open link via keyboard", 'f', 0, "document.linkkeys" }, 0 },
73 /* The following cannot currently be changed (built-in duplicates). */ 77 /* The following cannot currently be changed (built-in duplicates). */
74 { 1000, { NULL, SDLK_SPACE, KMOD_SHIFT, "scroll.page arg:-1" } }, 78 { 1000, { NULL, SDLK_SPACE, KMOD_SHIFT, "scroll.page arg:-1" }, argRepeat_BindFlag },
75 { 1001, { NULL, SDLK_SPACE, 0, "scroll.page arg:1" } }, 79 { 1001, { NULL, SDLK_SPACE, 0, "scroll.page arg:1" }, argRepeat_BindFlag },
76}; 80};
77 81
82static iBinding *findId_Keys_(iKeys *d, int id) {
83 iForEach(Array, i, &d->bindings) {
84 iBinding *bind = i.value;
85 if (bind->id == id) {
86 return bind;
87 }
88 }
89 return NULL;
90}
91
92static void setFlags_Keys_(int id, int bindFlags) {
93 iBinding *bind = findId_Keys_(&keys_, id);
94 if (bind) {
95 bind->flags = bindFlags;
96 }
97}
98
78static void bindDefaults_(void) { 99static void bindDefaults_(void) {
79 iForIndices(i, defaultBindings_) { 100 iForIndices(i, defaultBindings_) {
80 const int id = defaultBindings_[i].id; 101 const int id = defaultBindings_[i].id;
@@ -83,6 +104,7 @@ static void bindDefaults_(void) {
83 if (bind.label) { 104 if (bind.label) {
84 setLabel_Keys(id, bind.label); 105 setLabel_Keys(id, bind.label);
85 } 106 }
107 setFlags_Keys_(id, defaultBindings_[i].flags);
86 } 108 }
87} 109}
88 110
@@ -95,16 +117,6 @@ static iBinding *find_Keys_(iKeys *d, int key, int mods) {
95 return NULL; 117 return NULL;
96} 118}
97 119
98static iBinding *findId_Keys_(iKeys *d, int id) {
99 iForEach(Array, i, &d->bindings) {
100 iBinding *bind = i.value;
101 if (bind->id == id) {
102 return bind;
103 }
104 }
105 return NULL;
106}
107
108static iBinding *findCommand_Keys_(iKeys *d, const char *command) { 120static iBinding *findCommand_Keys_(iKeys *d, const char *command) {
109 /* Note: O(n) */ 121 /* Note: O(n) */
110 iForEach(Array, i, &d->bindings) { 122 iForEach(Array, i, &d->bindings) {
@@ -259,7 +271,12 @@ iBool processEvent_Keys(const SDL_Event *ev) {
259 if (ev->type == SDL_KEYDOWN) { 271 if (ev->type == SDL_KEYDOWN) {
260 const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod)); 272 const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod));
261 if (bind) { 273 if (bind) {
262 postCommandString_App(&bind->command); 274 if (ev->key.repeat && (bind->flags & argRepeat_BindFlag)) {
275 postCommandf_App("%s repeat:1", cstr_String(&bind->command));
276 }
277 else {
278 postCommandString_App(&bind->command);
279 }
263 return iTrue; 280 return iTrue;
264 } 281 }
265 } 282 }
diff --git a/src/ui/keys.h b/src/ui/keys.h
index 0cd97e2a..1e676c59 100644
--- a/src/ui/keys.h
+++ b/src/ui/keys.h
@@ -52,6 +52,7 @@ iDeclareType(Binding)
52 52
53struct Impl_Binding { 53struct Impl_Binding {
54 int id; 54 int id;
55 int flags;
55 int key; 56 int key;
56 int mods; 57 int mods;
57 iString command; 58 iString command;
diff --git a/src/ui/util.c b/src/ui/util.c
index 85d3562f..559c5381 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -1013,6 +1013,8 @@ iWidget *makePreferences_Widget(void) {
1013 addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoveroutline"))); 1013 addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoveroutline")));
1014 addChild_Widget(headings, iClob(makeHeading_Widget("Smooth scrolling:"))); 1014 addChild_Widget(headings, iClob(makeHeading_Widget("Smooth scrolling:")));
1015 addChild_Widget(values, iClob(makeToggle_Widget("prefs.smoothscroll"))); 1015 addChild_Widget(values, iClob(makeToggle_Widget("prefs.smoothscroll")));
1016 addChild_Widget(headings, iClob(makeHeading_Widget("Load image on scroll:")));
1017 addChild_Widget(values, iClob(makeToggle_Widget("prefs.imageloadscroll")));
1016 } 1018 }
1017 /* Window. */ { 1019 /* Window. */ {
1018 appendTwoColumnPage_(tabs, "Window", '2', &headings, &values); 1020 appendTwoColumnPage_(tabs, "Window", '2', &headings, &values);