diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-11-21 11:48:07 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-11-21 11:48:07 +0200 |
commit | 0b2b40a233c014e684f6efed0298efda02e7abf4 (patch) | |
tree | a1bc3a095b57279cd27b5ef65498b7c9a0fcf457 /src/ui | |
parent | c651680715f7549a0cdbdbb10d535cba2272d9d0 (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.c | 44 | ||||
-rw-r--r-- | src/ui/keys.c | 67 | ||||
-rw-r--r-- | src/ui/keys.h | 1 | ||||
-rw-r--r-- | src/ui/util.c | 2 |
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 | ||
1152 | static iBool requestMedia_DocumentWidget_(iDocumentWidget *d, iGmLinkId linkId) { | 1152 | static 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 | ||
1236 | static 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 | |||
1238 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | 1252 | static 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 | ||
59 | enum 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. */ |
61 | static const struct { int id; iMenuItem bind; } defaultBindings_[] = { | 65 | static 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 | ||
82 | static 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 | |||
92 | static void setFlags_Keys_(int id, int bindFlags) { | ||
93 | iBinding *bind = findId_Keys_(&keys_, id); | ||
94 | if (bind) { | ||
95 | bind->flags = bindFlags; | ||
96 | } | ||
97 | } | ||
98 | |||
78 | static void bindDefaults_(void) { | 99 | static 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 | ||
98 | static 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 | |||
108 | static iBinding *findCommand_Keys_(iKeys *d, const char *command) { | 120 | static 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 | ||
53 | struct Impl_Binding { | 53 | struct 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); |