summaryrefslogtreecommitdiff
path: root/src/ui/documentwidget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r--src/ui/documentwidget.c144
1 files changed, 142 insertions, 2 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 936c3cb7..70201d7b 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -315,6 +315,10 @@ void init_DocumentWidget(iDocumentWidget *d) {
315 init_Widget(w); 315 init_Widget(w);
316 setId_Widget(w, format_CStr("document%03d", ++docEnum_)); 316 setId_Widget(w, format_CStr("document%03d", ++docEnum_));
317 setFlags_Widget(w, hover_WidgetFlag | noBackground_WidgetFlag, iTrue); 317 setFlags_Widget(w, hover_WidgetFlag | noBackground_WidgetFlag, iTrue);
318 if (deviceType_App() != desktop_AppDeviceType) {
319 setFlags_Widget(w, leftEdgeDraggable_WidgetFlag | rightEdgeDraggable_WidgetFlag |
320 horizontalOffset_WidgetFlag, iTrue);
321 }
318 init_PersistentDocumentState(&d->mod); 322 init_PersistentDocumentState(&d->mod);
319 d->flags = 0; 323 d->flags = 0;
320 d->phoneToolbar = NULL; 324 d->phoneToolbar = NULL;
@@ -977,6 +981,9 @@ static void updateTimestampBuf_DocumentWidget_(const iDocumentWidget *d) {
977} 981}
978 982
979static void invalidate_DocumentWidget_(iDocumentWidget *d) { 983static void invalidate_DocumentWidget_(iDocumentWidget *d) {
984 if (flags_Widget(as_Widget(d)) & destroyPending_WidgetFlag) {
985 return;
986 }
980 invalidate_VisBuf(d->visBuf); 987 invalidate_VisBuf(d->visBuf);
981 clear_PtrSet(d->invalidRuns); 988 clear_PtrSet(d->invalidRuns);
982} 989}
@@ -2237,6 +2244,133 @@ static iBool handlePinch_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2237 return iTrue; 2244 return iTrue;
2238} 2245}
2239 2246
2247static void swap_DocumentWidget_(iDocumentWidget *d, iGmDocument *doc,
2248 iDocumentWidget *swapBuffersWith) {
2249 if (doc) {
2250 iAssert(isInstance_Object(doc, &Class_GmDocument));
2251 iGmDocument *copy = ref_Object(doc);
2252 iRelease(d->doc);
2253 d->doc = copy;
2254 d->scrollY = swapBuffersWith->scrollY;
2255 updateVisible_DocumentWidget_(d);
2256 iSwap(iVisBuf *, d->visBuf, swapBuffersWith->visBuf);
2257 iSwap(iVisBufMeta *, d->visBufMeta, swapBuffersWith->visBufMeta);
2258 iSwap(iDrawBufs *, d->drawBufs, swapBuffersWith->drawBufs);
2259 invalidate_DocumentWidget_(swapBuffersWith);
2260 }
2261}
2262
2263static iWidget *swipeParent_DocumentWidget_(iDocumentWidget *d) {
2264 return findChild_Widget(as_Widget(d)->root->widget, "doctabs");
2265}
2266
2267static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2268 iWidget *w = as_Widget(d);
2269 if (equal_Command(cmd, "edgeswipe.moved")) {
2270 as_Widget(d)->offsetRef = NULL;
2271 const int side = argLabel_Command(cmd, "side");
2272 const int offset = arg_Command(cmd);
2273 if (side == 1) {
2274 if (atOldest_History(d->mod.history)) {
2275 return iTrue;
2276 }
2277 iWidget *swipeParent = swipeParent_DocumentWidget_(d);
2278 /* The temporary "swipeIn" will display the previous page until the finger is lifted. */
2279 iDocumentWidget *swipeIn = findChild_Widget(swipeParent, "swipein");
2280 if (!swipeIn) {
2281 swipeIn = new_DocumentWidget();
2282 setId_Widget(as_Widget(swipeIn), "swipein");
2283 setFlags_Widget(as_Widget(swipeIn),
2284 disabled_WidgetFlag | refChildrenOffset_WidgetFlag |
2285 fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue);
2286 swipeIn->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos));
2287 swipeIn->widget.rect.size = d->widget.rect.size;
2288 swipeIn->widget.offsetRef = w;
2289 iRecentUrl *recent = new_RecentUrl();
2290 preceding_History(d->mod.history, recent);
2291 if (recent->cachedDoc) {
2292 iChangeRef(swipeIn->doc, recent->cachedDoc);
2293 updateScrollMax_DocumentWidget_(d);
2294 setValue_Anim(&swipeIn->scrollY.pos, size_GmDocument(swipeIn->doc).y * recent->normScrollY, 0);
2295 updateVisible_DocumentWidget_(swipeIn);
2296 }
2297 delete_RecentUrl(recent);
2298 addChildPos_Widget(swipeParent, iClob(swipeIn), front_WidgetAddPos);
2299 }
2300 }
2301 if (side == 2) {
2302 if (offset < -get_Window()->pixelRatio * 10) {
2303 if (!atLatest_History(d->mod.history) &&
2304 ~flags_Widget(w) & dragged_WidgetFlag) {
2305 postCommand_Widget(d, "navigate.forward");
2306 setFlags_Widget(w, dragged_WidgetFlag, iTrue);
2307 /* Set up the swipe dummy. */
2308 iWidget *swipeParent = swipeParent_DocumentWidget_(d);
2309 iDocumentWidget *target = new_DocumentWidget();
2310 setId_Widget(as_Widget(target), "swipeout");
2311 /* The target takes the old document and jumps on top. */
2312 target->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos));
2313 target->widget.rect.size = d->widget.rect.size;
2314 setFlags_Widget(as_Widget(target), fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue);
2315 swap_DocumentWidget_(target, d->doc, d);
2316 addChildPos_Widget(swipeParent, iClob(target), front_WidgetAddPos);
2317 setFlags_Widget(as_Widget(target), refChildrenOffset_WidgetFlag, iTrue);
2318 as_Widget(target)->offsetRef = parent_Widget(w);
2319 destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */
2320 }
2321 if (flags_Widget(w) & dragged_WidgetFlag) {
2322 setVisualOffset_Widget(w, width_Widget(w) + offset, 10, 0);
2323 }
2324 else {
2325 setVisualOffset_Widget(w, offset / 4, 10, 0);
2326 }
2327 }
2328 return iTrue;
2329 }
2330 }
2331 if (equal_Command(cmd, "edgeswipe.ended") && argLabel_Command(cmd, "side") == 2) {
2332 if (argLabel_Command(cmd, "abort") && flags_Widget(w) & dragged_WidgetFlag) {
2333 postCommand_Widget(d, "navigate.back");
2334 }
2335 setFlags_Widget(w, dragged_WidgetFlag, iFalse);
2336 setVisualOffset_Widget(w, 0, 100, 0);
2337 return iTrue;
2338 }
2339 if (equal_Command(cmd, "edgeswipe.ended") && argLabel_Command(cmd, "side") == 1) {
2340 iWidget *swipeParent = swipeParent_DocumentWidget_(d);
2341 iWidget *swipeIn = findChild_Widget(swipeParent, "swipein");
2342 if (swipeIn) {
2343 swipeIn->offsetRef = NULL;
2344 destroy_Widget(swipeIn);
2345 }
2346 }
2347 if (equal_Command(cmd, "swipe.back")) {
2348 if (atOldest_History(d->mod.history)) {
2349 setVisualOffset_Widget(w, 0, 100, 0);
2350 return iTrue;
2351 }
2352 iWidget *swipeParent = swipeParent_DocumentWidget_(d);
2353 iDocumentWidget *target = new_DocumentWidget();
2354 setId_Widget(as_Widget(target), "swipeout");
2355 /* The target takes the old document and jumps on top. */
2356 target->widget.rect.pos = windowToInner_Widget(swipeParent, innerToWindow_Widget(w, zero_I2()));
2357 /* Note: `innerToWindow_Widget` does not apply visual offset. */
2358 target->widget.rect.size = w->rect.size;
2359 setFlags_Widget(as_Widget(target), fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue);
2360 swap_DocumentWidget_(target, d->doc, d);
2361 addChildPos_Widget(swipeParent, iClob(target), back_WidgetAddPos);
2362 setFlags_Widget(as_Widget(d), refChildrenOffset_WidgetFlag, iTrue);
2363 as_Widget(d)->offsetRef = swipeParent;
2364 setVisualOffset_Widget(as_Widget(target), value_Anim(&w->visualOffset), 0, 0);
2365 setVisualOffset_Widget(as_Widget(target), width_Widget(target), 150, 0);
2366 destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */
2367 setVisualOffset_Widget(w, 0, 0, 0);
2368 postCommand_Widget(d, "navigate.back");
2369 return iTrue;
2370 }
2371 return iFalse;
2372}
2373
2240static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { 2374static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2241 iWidget *w = as_Widget(d); 2375 iWidget *w = as_Widget(d);
2242 if (equal_Command(cmd, "document.openurls.changed")) { 2376 if (equal_Command(cmd, "document.openurls.changed")) {
@@ -2842,7 +2976,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2842 uiHeading_ColorEscape "${heading.import.bookmarks}", 2976 uiHeading_ColorEscape "${heading.import.bookmarks}",
2843 formatCStrs_Lang("dlg.import.found.n", count), 2977 formatCStrs_Lang("dlg.import.found.n", count),
2844 (iMenuItem[]){ { "${cancel}", 0, 0, NULL }, 2978 (iMenuItem[]){ { "${cancel}", 0, 0, NULL },
2845 { format_CStr(cstrCount_Lang("dlg.import.add.n", count), 2979 { format_CStr(cstrCount_Lang("dlg.import.add.n", (int) count),
2846 uiTextAction_ColorEscape, 2980 uiTextAction_ColorEscape,
2847 count), 2981 count),
2848 0, 2982 0,
@@ -2901,6 +3035,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2901 else if (startsWith_CStr(cmd, "pinch.") && document_Command(cmd) == d) { 3035 else if (startsWith_CStr(cmd, "pinch.") && document_Command(cmd) == d) {
2902 return handlePinch_DocumentWidget_(d, cmd); 3036 return handlePinch_DocumentWidget_(d, cmd);
2903 } 3037 }
3038 else if ((startsWith_CStr(cmd, "edgeswipe.") || startsWith_CStr(cmd, "swipe.")) &&
3039 document_App() == d) {
3040 return handleSwipe_DocumentWidget_(d, cmd);
3041 }
2904 return iFalse; 3042 return iFalse;
2905} 3043}
2906 3044
@@ -4306,7 +4444,8 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx,
4306 /* Swap buffers around to have room available both before and after the visible region. */ 4444 /* Swap buffers around to have room available both before and after the visible region. */
4307 allocVisBuffer_DocumentWidget_(d); 4445 allocVisBuffer_DocumentWidget_(d);
4308 reposition_VisBuf(visBuf, vis); 4446 reposition_VisBuf(visBuf, vis);
4309 /* Redraw the invalid ranges. */ { 4447 /* Redraw the invalid ranges. */
4448 if (~flags_Widget(constAs_Widget(d)) & destroyPending_WidgetFlag) {
4310 iPaint *p = &ctx->paint; 4449 iPaint *p = &ctx->paint;
4311 init_Paint(p); 4450 init_Paint(p);
4312 iForIndices(i, visBuf->buffers) { 4451 iForIndices(i, visBuf->buffers) {
@@ -4490,6 +4629,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
4490 .vis = vis, 4629 .vis = vis,
4491 .showLinkNumbers = (d->flags & showLinkNumbers_DocumentWidgetFlag) != 0, 4630 .showLinkNumbers = (d->flags & showLinkNumbers_DocumentWidgetFlag) != 0,
4492 }; 4631 };
4632 init_Paint(&ctx.paint);
4493 render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); 4633 render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */);
4494 setClip_Paint(&ctx.paint, bounds); 4634 setClip_Paint(&ctx.paint, bounds);
4495 int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); 4635 int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY);