From e39721581f082a20f1ef3a6f81b83c5e489cf7c7 Mon Sep 17 00:00:00 2001

From: =?UTF-8?q?Jaakko=20Ker=C3=A4nen?= jaakko.keranen@iki.fi

Date: Mon, 13 Dec 2021 10:58:59 +0200

Subject: [PATCH 1/1] Android: Various fixes to get things up and running

Resource paths, runtime data, ignore mouse events. Assume that

the Java side tells us the display pixel density via a command

line argument.


src/app.c | 39 ++++++++++++++++++++---

src/resources.c | 20 ++++++++++--

src/ui/documentwidget.c | 68 ++++++++++++++++++++---------------------

src/ui/touch.c | 4 +++

src/ui/window.c | 10 +++++-

5 files changed, 99 insertions(+), 42 deletions(-)

diff --git a/src/app.c b/src/app.c

index eea3689f..3ee2345c 100644

--- a/src/app.c

+++ b/src/app.c

@@ -92,7 +92,10 @@ static const char *defaultDataDir_App_ = "~/Library/Application Support";

#define EMB_BIN "../resources.lgr"

static const char *defaultDataDir_App_ = "~/AppData/Roaming/fi.skyjake.Lagrange";

#endif

-#if defined (iPlatformLinux) || defined (iPlatformOther)

+#if defined (iPlatformAndroidMobile)

+#define EMB_BIN "resources.lgr" /* loaded from assets with SDL_rwops */

+static const char defaultDataDir_App_ = NULL; / will ask SDL */

+#elif defined (iPlatformLinux) || defined (iPlatformOther)

#define EMB_BIN "../../share/lagrange/resources.lgr"

#define EMB_BIN2 "../../../share/lagrange/resources.lgr"

static const char *defaultDataDir_App_ = "~/.config/lagrange";

@@ -139,6 +142,9 @@ struct Impl_App {

 int          autoReloadTimer;

 iPeriodic    periodic;

 int          warmupFrames; /* forced refresh just after resuming from background; FIXME: shouldn't be needed */

+#if defined (iPlatformAndroidMobile)

+#endif

 /* Preferences: */

 iBool        commandEcho;         /* --echo */

 iBool        forceSoftwareRender; /* --sw */

@@ -307,7 +313,10 @@ static const char *dataDir_App_(void) {

     return userDir;

 }

#endif

}

static const char *downloadDir_App_(void) {

@@ -715,7 +724,7 @@ static iBool hasCommandLineOpenableScheme_(const iRangecc uri) {

}

static void init_App_(iApp *d, int argc, char **argv) {

-#if defined (iPlatformLinux)

+#if defined (iPlatformLinux) && !defined (iPlatformAndroid)

 d->isRunningUnderWindowSystem = !iCmpStr(SDL_GetCurrentVideoDriver(), "x11") ||

                                 !iCmpStr(SDL_GetCurrentVideoDriver(), "wayland");

#else

@@ -763,6 +772,8 @@ static void init_App_(iApp *d, int argc, char **argv) {

     }

 }

 init_Lang();

+#if !defined (iPlatformAndroidMobile)

 /* Configure the valid command line options. */ {

     defineValues_CommandLine(&d->args, "close-tab", 0);

     defineValues_CommandLine(&d->args, "echo;E", 0);

@@ -777,7 +788,6 @@ static void init_App_(iApp *d, int argc, char **argv) {

     defineValues_CommandLine(&d->args, "sw", 0);

     defineValues_CommandLine(&d->args, "version;V", 0);

 }

 /* Handle command line options. */ {

     if (contains_CommandLine(&d->args, "help")) {

         puts(cstr_Block(&blobArghelp_Resources));

@@ -826,6 +836,7 @@ static void init_App_(iApp *d, int argc, char **argv) {

         }

     }

 }

+#endif

#if defined (LAGRANGE_ENABLE_IPC)

 /* Only one instance is allowed to run at a time; the runtime files (bookmarks, etc.)

    are not shareable. */ {

@@ -860,7 +871,7 @@ static void init_App_(iApp *d, int argc, char **argv) {

 /* Must scale by UI scaling factor. */

 mulfv_I2(&d->initialWindowRect.size, desktopDPI_Win32());

#endif

-#if defined (iPlatformLinux)

+#if defined (iPlatformLinux) && !defined (iPlatformAndroid)

 /* Scale by the primary (?) monitor DPI. */

 if (isRunningUnderWindowSystem_App()) {

     float vdpi;

@@ -1325,6 +1336,15 @@ void processEvents_App(enum iAppEventMode eventMode) {

                 }

                 ev.key.keysym.mod = mapMods_Keys(ev.key.keysym.mod & ~KMOD_CAPS);

             }

+#if defined (iPlatformAndroidMobile)

+#endif

             /* Scroll events may be per-pixel or mouse wheel steps. */

             if (ev.type == SDL_MOUSEWHEEL) {

#if defined (iPlatformMsys)

@@ -1773,6 +1793,8 @@ enum iAppDeviceType deviceType_App(void) {

 return tablet_AppDeviceType;

#elif defined (iPlatformAppleMobile)

 return isPhone_iOS() ? phone_AppDeviceType : tablet_AppDeviceType;

+#elif defined (iPlatformAndroidMobile)

#else

 return desktop_AppDeviceType;

#endif

@@ -3408,3 +3430,10 @@ void closePopups_App(void) {

     }

 }

}

+#if defined (iPlatformAndroidMobile)

+float displayDensity_Android(void) {

+}

+#endif

diff --git a/src/resources.c b/src/resources.c

index bb601cca..e3d92946 100644

--- a/src/resources.c

+++ b/src/resources.c

@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

#include <the_Foundation/version.h>

static iArchive *archive_;

iBlock blobAbout_Resources;

iBlock blobHelp_Resources;

iBlock blobLagrange_Resources;

@@ -101,7 +101,23 @@ static struct {

iBool init_Resources(const char *path) {

 archive_ = new_Archive();

+#if defined (iPlatformAndroidMobile)

+#else

+#endif

     iVersion appVer;

     init_Version(&appVer, range_CStr(LAGRANGE_APP_VERSION));

     iVersion resVer;

diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c

index e93fb586..b20ae672 100644

--- a/src/ui/documentwidget.c

+++ b/src/ui/documentwidget.c

@@ -225,7 +225,7 @@ enum iDocumentWidgetFlag {

 animationPlaceholder_DocumentWidgetFlag  = iBit(16), /* avoid slow operations */

 invalidationPending_DocumentWidgetFlag   = iBit(17), /* invalidate as soon as convenient */

 leftWheelSwipe_DocumentWidgetFlag        = iBit(18), /* swipe state flags are used on desktop */

 eitherWheelSwipe_DocumentWidgetFlag      = leftWheelSwipe_DocumentWidgetFlag |

                                            rightWheelSwipe_DocumentWidgetFlag,

};

@@ -242,8 +242,8 @@ enum iWheelSwipeState {

/* TODO: DocumentView is supposed to be useful on its own; move to a separate source file. */

iDeclareType(DocumentView)

-struct Impl_DocumentView {

+struct Impl_DocumentView {

 iDocumentWidget *owner; /* TODO: Convert to an abstract provider of metrics? */

 iGmDocument *  doc;

 int            pageMargin;

@@ -253,7 +253,7 @@ struct Impl_DocumentView {

 iGmRunRange    visibleRuns;

 iPtrArray      visibleLinks;

 iPtrArray      visiblePre;

 iPtrArray      visibleWideRuns; /* scrollable blocks; TODO: merge into `visiblePre` */

 const iGmRun * hoverPre;    /* for clicking */

 const iGmRun * hoverAltPre; /* for drawing alt text */

@@ -263,7 +263,7 @@ struct Impl_DocumentView {

 uint16_t       animWideRunId;

 iGmRunRange    animWideRunRange;

 iDrawBufs *    drawBufs; /* dynamic state for drawing */

 iVisBufMeta *  visBufMeta;

 iGmRunRange    renderRuns;

 iPtrSet *      invalidRuns;

@@ -272,7 +272,7 @@ struct Impl_DocumentView {

struct Impl_DocumentWidget {

 iWidget        widget;

 int            flags; /* internal behavior, see enum iDocumentWidgetFlag */

 /* User interface: */

 enum iDocumentLinkOrdinalMode ordinalMode;

 size_t         ordinalBase;

@@ -293,7 +293,7 @@ struct Impl_DocumentWidget {

 enum iWheelSwipeState wheelSwipeState;

 iString        pendingGotoHeading;

 iString        linePrecedingLink;

 /* Network request: */

 enum iRequestState state;

 iGmRequest *   request;

@@ -304,7 +304,7 @@ struct Impl_DocumentWidget {

 iString *      certSubject;

 int            redirectCount;

 iObjectList *  media; /* inline media requests */

 /* Document: */

 iPersistentDocumentState mod;

 iString *      titleUser;

@@ -316,12 +316,12 @@ struct Impl_DocumentWidget {

 iGempub *      sourceGempub; /* NULL unless the page is Gempub content */

 iBanner *      banner;

 float          initNormScrollY;

 /* Rendering: */

 iDocumentView  view;

 iLinkInfo *    linkInfo;

 iScrollWidget *scroll;

 iWidget *      footerButtons;

 iWidget *      menu;

@@ -332,7 +332,7 @@ struct Impl_DocumentWidget {

};

iDefineObjectConstruction(DocumentWidget)

/* Sorted by proximity to F and J. */

static const int homeRowKeys_[] = {

 'f', 'd', 's', 'a',

@@ -344,7 +344,7 @@ static const int homeRowKeys_[] = {

 'g', 'h',

 'b',

 't', 'y',

-};

+};

static int docEnum_ = 0;

static void animate_DocumentWidget_ (void *ticker);

@@ -909,7 +909,7 @@ static void updateTimestampBuf_DocumentView_(const iDocumentView *d) {

static void invalidate_DocumentView_(iDocumentView *d) {

 invalidate_VisBuf(d->visBuf);

}

static void documentRunsInvalidated_DocumentView_(iDocumentView *d) {

@@ -928,11 +928,11 @@ static void resetScroll_DocumentView_(iDocumentView *d) {

}

static void updateWidth_DocumentView_(iDocumentView *d) {

}

static void updateWidthAndRedoLayout_DocumentView_(iDocumentView *d) {

}

static void clampScroll_DocumentView_(iDocumentView *d) {

@@ -1025,7 +1025,7 @@ static iRangecc sourceLoc_DocumentView_(const iDocumentView *d, iInt2 pos) {

}

iDeclareType(MiddleRunParams)

struct Impl_MiddleRunParams {

 int midY;

 const iGmRun *closest;

@@ -1126,7 +1126,7 @@ static iRect runRect_DocumentView_(const iDocumentView *d, const iGmRun *run) {

}

iDeclareType(DrawContext)

struct Impl_DrawContext {

 const iDocumentView *view;

 iRect widgetBounds;

@@ -1260,7 +1260,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {

         isInlineImageCaption = iFalse;

     }

#endif

        is open: the image itself is the indication. */

     const iBool isInlineImageCaption = iFalse;

     if (run->linkId && (linkFlags & isOpen_GmLinkFlag || isInlineImageCaption)) {

@@ -1285,7 +1285,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {

         }

         fillRect_Paint(&d->paint, wideRect, bg);

     }

         /* Normal background for other runs. There are cases when runs get drawn multiple times,

            e.g., at the buffer boundary, and there are slightly overlapping characters in

            monospace blocks. Clearing the background here ensures a cleaner visual appearance

@@ -2095,7 +2095,7 @@ static void invalidate_DocumentWidget_(iDocumentWidget *d) {

}

static iRangecc siteText_DocumentWidget_(const iDocumentWidget *d) {

                                     : range_String(d->titleUser);

}

@@ -2161,7 +2161,7 @@ static void updateBanner_DocumentWidget_(iDocumentWidget *d) {

static void updateTheme_DocumentWidget_(iDocumentWidget *d) {

 if (document_App() != d || category_GmStatusCode(d->sourceStatus) == categoryInput_GmStatusCode) {

     return;

 d->view.drawBufs->flags |= updateTimestampBuf_DrawBufsFlag;

 updateBanner_DocumentWidget_(d);

}

@@ -2620,7 +2620,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d,

                     appendFormat_String(&str,

                                         cstr_Lang("doc.archive"),

                                         cstr_Rangecc(baseName_Path(d->mod.url)));

                 }

                 appendCStr_String(&str, "\n");

                 iString *localPath = localFilePathFromUrl_String(d->mod.url);

@@ -2768,7 +2768,7 @@ static void updateTrust_DocumentWidget_(iDocumentWidget *d, const iGmResponse *r

 }

 else if (~d->certFlags & timeVerified_GmCertFlag) {

     updateTextCStr_LabelWidget(lock, isDarkMode ? orange_ColorEscape warning_Icon

 }

 else {

     updateTextCStr_LabelWidget(lock, green_ColorEscape closedLock_Icon);

@@ -3067,7 +3067,7 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) {

                it is only displayed as an input dialog. */

             visitUrl_Visited(visited_App(), d->mod.url, transient_VisitedUrlFlag);

             iUrl parts;

             iWidget *dlg = makeValueInput_Widget(

                 as_Widget(d),

                 NULL,

@@ -3132,7 +3132,7 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) {

                     setFont_LabelWidget(menu, font_LabelWidget((iLabelWidget *) lastChild_Widget(buttons)));

                     setTextColor_LabelWidget(menu, uiTextAction_ColorId);

                 }

             setValidator_InputWidget(findChild_Widget(dlg, "input"), inputQueryValidator_, d);

             setSensitiveContent_InputWidget(findChild_Widget(dlg, "input"),

                                             statusCode == sensitiveInput_GmStatusCode);

@@ -3491,7 +3491,7 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {

         }

         /* The temporary "swipein" will display the previous page until the finger is lifted. */

         iDocumentWidget *swipeIn = findChild_Widget(swipeParent, "swipein");

             swipeIn = new_DocumentWidget();

             swipeIn->flags |= animationPlaceholder_DocumentWidgetFlag;

             setId_Widget(as_Widget(swipeIn), "swipein");

@@ -3531,7 +3531,7 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {

                 iWidget *swipeParent = swipeParent_DocumentWidget_(d);

                 if (findChild_Widget(swipeParent, "swipeout")) {

                     return iTrue; /* too fast, previous animation hasn't finished */

                 /* Setup the drag. `d` will be moving with the finger. */

                 animSpan = 0;

                 postCommand_Widget(d, "navigate.forward");

@@ -3694,7 +3694,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)

 else if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "font.changed") ||

          equal_Command(cmd, "keyroot.changed")) {

     if (equal_Command(cmd, "font.changed")) {

     }

     /* Alt/Option key may be involved in window size changes. */

     setLinkNumberMode_DocumentWidget_(d, iFalse);

@@ -4056,7 +4056,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)

     }

     return wasHandled;

 }

     if (findChild_Widget(root_Widget(w), "upload")) {

         return iTrue; /* already open */

     }

@@ -4124,7 +4124,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)

     if (equalCase_Rangecc(urlScheme_String(d->mod.url), "titan")) {

         /* Reopen so the Upload dialog gets shown. */

         postCommandf_App("open url:%s", cstr_String(d->mod.url));

     }

     fetch_DocumentWidget_(d);

     return iTrue;

@@ -4416,7 +4416,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)

     if (argLabel_Command(cmd, "ttf")) {

         iAssert(!cmp_String(&d->sourceMime, "font/ttf"));

         installFontFile_Fonts(collect_String(suffix_Command(cmd, "name")), &d->sourceContent);

     }

     else {

         const iString *id = idFromUrl_FontPack(d->mod.url);

@@ -5435,7 +5435,7 @@ void init_DocumentWidget(iDocumentWidget *d) {

 init_Widget(w);

 setId_Widget(w, format_CStr("document%03d", ++docEnum_));

 setFlags_Widget(w, hover_WidgetFlag | noBackground_WidgetFlag, iTrue);

-#if defined (iPlatformAppleDesktop)

+#if defined (iPlatformAppleDesktop)

 iBool enableSwipeNavigation = iTrue; /* swipes on the trackpad */

#else

 iBool enableSwipeNavigation = (deviceType_App() != desktop_AppDeviceType);

@@ -5671,7 +5671,7 @@ iBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) {

void takeRequest_DocumentWidget(iDocumentWidget *d, iGmRequest *finishedRequest) {

 cancelRequest_DocumentWidget_(d, iFalse /* don't post anything */);

 const iString *url = url_GmRequest(finishedRequest);

 add_History(d->mod.history, url);

 setUrl_DocumentWidget_(d, url);

 d->state = fetching_RequestState;

diff --git a/src/ui/touch.c b/src/ui/touch.c

index 0749bc7c..3d318dfb 100644

--- a/src/ui/touch.c

+++ b/src/ui/touch.c

@@ -42,7 +42,11 @@ iDeclareType(TouchState)

static const uint32_t longPressSpanMs_ = 500;

static const uint32_t shortPressSpanMs_ = 250;

+#if defined (iPlatformAndroidMobile)

+static const int tapRadiusPt_ = 30; /* inaccurate sensors? */

+#else

static const int tapRadiusPt_ = 10;

+#endif

enum iTouchEdge {

 none_TouchEdge,

diff --git a/src/ui/window.c b/src/ui/window.c

index 0e13a57f..7f3371c8 100644

--- a/src/ui/window.c

+++ b/src/ui/window.c

@@ -263,6 +263,10 @@ static float pixelRatio_Window_(const iWindow *d) {

define baseDPI_Window 96.0f

#endif

+#if defined (iPlatformAndroidMobile)

+float displayDensity_Android(void);

+#endif

static float displayScale_Window_(const iWindow *d) {

 /* The environment variable LAGRANGE_OVERRIDE_DPI can be used to override the automatic

    display DPI detection. If not set, or is an empty string, ignore it.

@@ -289,6 +293,8 @@ static float displayScale_Window_(const iWindow *d) {

#elif defined (iPlatformMsys)

 iUnused(d);

 return desktopDPI_Win32();

+#elif defined (iPlatformAndroidMobile)

#else

 if (isRunningUnderWindowSystem_App()) {

     float vdpi = 0.0f;

@@ -457,7 +463,7 @@ void init_Window(iWindow *d, enum iWindowType type, iRect rect, uint32_t flags)

 d->mouseGrab     = NULL;

 d->focus         = NULL;

 d->pendingCursor = NULL;

 d->isMinimized   = iFalse;

 d->isInvalidated = iFalse; /* set when posting event, to avoid repeated events */

 d->isMouseInside = iTrue;

@@ -541,6 +547,8 @@ void init_MainWindow(iMainWindow *d, iRect rect) {

 SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal");

 flags |= SDL_WINDOW_METAL;

 d->base.isExposed = iTrue;

+#elif defined (iPlatformAndroidMobile)

#else

 if (!forceSoftwareRender_App()) {

     flags |= SDL_WINDOW_OPENGL;

--

2.25.1

Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/work%2Fv1.10/patch/e39721581f082a20f1ef3a6f81b83c5e489cf7c7.patch
Status Code
Success (20)
Meta
text/plain
Capsule Response Time
85.07339 milliseconds
Gemini-to-HTML Time
14.940054 milliseconds

This content has been proxied by September (3851b).