diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 39 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/resources.c | 20 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 4 | ||||
-rw-r--r-- | src/ui/text.c | 4 | ||||
-rw-r--r-- | src/ui/text_simple.c | 7 | ||||
-rw-r--r-- | src/ui/touch.c | 4 | ||||
-rw-r--r-- | src/ui/window.c | 10 |
8 files changed, 75 insertions, 17 deletions
@@ -92,7 +92,10 @@ static const char *defaultDataDir_App_ = "~/Library/Application Support"; | |||
92 | #define EMB_BIN "../resources.lgr" | 92 | #define EMB_BIN "../resources.lgr" |
93 | static const char *defaultDataDir_App_ = "~/AppData/Roaming/fi.skyjake.Lagrange"; | 93 | static const char *defaultDataDir_App_ = "~/AppData/Roaming/fi.skyjake.Lagrange"; |
94 | #endif | 94 | #endif |
95 | #if defined (iPlatformLinux) || defined (iPlatformOther) | 95 | #if defined (iPlatformAndroidMobile) |
96 | #define EMB_BIN "resources.lgr" /* loaded from assets with SDL_rwops */ | ||
97 | static const char *defaultDataDir_App_ = NULL; /* will ask SDL */ | ||
98 | #elif defined (iPlatformLinux) || defined (iPlatformOther) | ||
96 | #define EMB_BIN "../../share/lagrange/resources.lgr" | 99 | #define EMB_BIN "../../share/lagrange/resources.lgr" |
97 | #define EMB_BIN2 "../../../share/lagrange/resources.lgr" | 100 | #define EMB_BIN2 "../../../share/lagrange/resources.lgr" |
98 | static const char *defaultDataDir_App_ = "~/.config/lagrange"; | 101 | static const char *defaultDataDir_App_ = "~/.config/lagrange"; |
@@ -137,6 +140,9 @@ struct Impl_App { | |||
137 | int autoReloadTimer; | 140 | int autoReloadTimer; |
138 | iPeriodic periodic; | 141 | iPeriodic periodic; |
139 | int warmupFrames; /* forced refresh just after resuming from background; FIXME: shouldn't be needed */ | 142 | int warmupFrames; /* forced refresh just after resuming from background; FIXME: shouldn't be needed */ |
143 | #if defined (iPlatformAndroidMobile) | ||
144 | float displayDensity; | ||
145 | #endif | ||
140 | /* Preferences: */ | 146 | /* Preferences: */ |
141 | iBool commandEcho; /* --echo */ | 147 | iBool commandEcho; /* --echo */ |
142 | iBool forceSoftwareRender; /* --sw */ | 148 | iBool forceSoftwareRender; /* --sw */ |
@@ -300,7 +306,10 @@ static const char *dataDir_App_(void) { | |||
300 | return userDir; | 306 | return userDir; |
301 | } | 307 | } |
302 | #endif | 308 | #endif |
303 | return defaultDataDir_App_; | 309 | if (defaultDataDir_App_) { |
310 | return defaultDataDir_App_; | ||
311 | } | ||
312 | return SDL_GetPrefPath("Jaakko Keränen", "fi.skyjake.lagrange"); | ||
304 | } | 313 | } |
305 | 314 | ||
306 | static const char *downloadDir_App_(void) { | 315 | static const char *downloadDir_App_(void) { |
@@ -698,7 +707,7 @@ static iBool hasCommandLineOpenableScheme_(const iRangecc uri) { | |||
698 | } | 707 | } |
699 | 708 | ||
700 | static void init_App_(iApp *d, int argc, char **argv) { | 709 | static void init_App_(iApp *d, int argc, char **argv) { |
701 | #if defined (iPlatformLinux) | 710 | #if defined (iPlatformLinux) && !defined (iPlatformAndroid) |
702 | d->isRunningUnderWindowSystem = !iCmpStr(SDL_GetCurrentVideoDriver(), "x11") || | 711 | d->isRunningUnderWindowSystem = !iCmpStr(SDL_GetCurrentVideoDriver(), "x11") || |
703 | !iCmpStr(SDL_GetCurrentVideoDriver(), "wayland"); | 712 | !iCmpStr(SDL_GetCurrentVideoDriver(), "wayland"); |
704 | #else | 713 | #else |
@@ -745,6 +754,8 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
745 | } | 754 | } |
746 | } | 755 | } |
747 | init_Lang(); | 756 | init_Lang(); |
757 | iStringList *openCmds = new_StringList(); | ||
758 | #if !defined (iPlatformAndroidMobile) | ||
748 | /* Configure the valid command line options. */ { | 759 | /* Configure the valid command line options. */ { |
749 | defineValues_CommandLine(&d->args, "close-tab", 0); | 760 | defineValues_CommandLine(&d->args, "close-tab", 0); |
750 | defineValues_CommandLine(&d->args, "echo;E", 0); | 761 | defineValues_CommandLine(&d->args, "echo;E", 0); |
@@ -759,7 +770,6 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
759 | defineValues_CommandLine(&d->args, "sw", 0); | 770 | defineValues_CommandLine(&d->args, "sw", 0); |
760 | defineValues_CommandLine(&d->args, "version;V", 0); | 771 | defineValues_CommandLine(&d->args, "version;V", 0); |
761 | } | 772 | } |
762 | iStringList *openCmds = new_StringList(); | ||
763 | /* Handle command line options. */ { | 773 | /* Handle command line options. */ { |
764 | if (contains_CommandLine(&d->args, "help")) { | 774 | if (contains_CommandLine(&d->args, "help")) { |
765 | puts(cstr_Block(&blobArghelp_Resources)); | 775 | puts(cstr_Block(&blobArghelp_Resources)); |
@@ -808,6 +818,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
808 | } | 818 | } |
809 | } | 819 | } |
810 | } | 820 | } |
821 | #endif | ||
811 | #if defined (LAGRANGE_ENABLE_IPC) | 822 | #if defined (LAGRANGE_ENABLE_IPC) |
812 | /* Only one instance is allowed to run at a time; the runtime files (bookmarks, etc.) | 823 | /* Only one instance is allowed to run at a time; the runtime files (bookmarks, etc.) |
813 | are not shareable. */ { | 824 | are not shareable. */ { |
@@ -842,7 +853,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
842 | /* Must scale by UI scaling factor. */ | 853 | /* Must scale by UI scaling factor. */ |
843 | mulfv_I2(&d->initialWindowRect.size, desktopDPI_Win32()); | 854 | mulfv_I2(&d->initialWindowRect.size, desktopDPI_Win32()); |
844 | #endif | 855 | #endif |
845 | #if defined (iPlatformLinux) | 856 | #if defined (iPlatformLinux) && !defined (iPlatformAndroid) |
846 | /* Scale by the primary (?) monitor DPI. */ | 857 | /* Scale by the primary (?) monitor DPI. */ |
847 | if (isRunningUnderWindowSystem_App()) { | 858 | if (isRunningUnderWindowSystem_App()) { |
848 | float vdpi; | 859 | float vdpi; |
@@ -1301,6 +1312,15 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1301 | } | 1312 | } |
1302 | ev.key.keysym.mod = mapMods_Keys(ev.key.keysym.mod & ~KMOD_CAPS); | 1313 | ev.key.keysym.mod = mapMods_Keys(ev.key.keysym.mod & ~KMOD_CAPS); |
1303 | } | 1314 | } |
1315 | #if defined (iPlatformAndroidMobile) | ||
1316 | /* Ignore all mouse events; just use touch. */ | ||
1317 | if (ev.type == SDL_MOUSEBUTTONDOWN || | ||
1318 | ev.type == SDL_MOUSEBUTTONUP || | ||
1319 | ev.type == SDL_MOUSEMOTION || | ||
1320 | ev.type == SDL_MOUSEWHEEL) { | ||
1321 | continue; | ||
1322 | } | ||
1323 | #endif | ||
1304 | /* Scroll events may be per-pixel or mouse wheel steps. */ | 1324 | /* Scroll events may be per-pixel or mouse wheel steps. */ |
1305 | if (ev.type == SDL_MOUSEWHEEL) { | 1325 | if (ev.type == SDL_MOUSEWHEEL) { |
1306 | #if defined (iPlatformAppleDesktop) | 1326 | #if defined (iPlatformAppleDesktop) |
@@ -1759,6 +1779,8 @@ enum iAppDeviceType deviceType_App(void) { | |||
1759 | return tablet_AppDeviceType; | 1779 | return tablet_AppDeviceType; |
1760 | #elif defined (iPlatformAppleMobile) | 1780 | #elif defined (iPlatformAppleMobile) |
1761 | return isPhone_iOS() ? phone_AppDeviceType : tablet_AppDeviceType; | 1781 | return isPhone_iOS() ? phone_AppDeviceType : tablet_AppDeviceType; |
1782 | #elif defined (iPlatformAndroidMobile) | ||
1783 | return phone_AppDeviceType; /* TODO: Java side could tell us via cmdline if this is a tablet. */ | ||
1762 | #else | 1784 | #else |
1763 | return desktop_AppDeviceType; | 1785 | return desktop_AppDeviceType; |
1764 | #endif | 1786 | #endif |
@@ -3350,3 +3372,10 @@ void closePopups_App(void) { | |||
3350 | } | 3372 | } |
3351 | } | 3373 | } |
3352 | } | 3374 | } |
3375 | |||
3376 | #if defined (iPlatformAndroidMobile) | ||
3377 | float displayDensity_Android(void) { | ||
3378 | iApp *d = &app_; | ||
3379 | return toFloat_String(at_CommandLine(&d->args, 1)); | ||
3380 | } | ||
3381 | #endif | ||
@@ -67,9 +67,11 @@ int main(int argc, char **argv) { | |||
67 | "ECDHE-RSA-AES128-GCM-SHA256:" | 67 | "ECDHE-RSA-AES128-GCM-SHA256:" |
68 | "DHE-RSA-AES256-GCM-SHA384"); | 68 | "DHE-RSA-AES256-GCM-SHA384"); |
69 | SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1"); | 69 | SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1"); |
70 | SDL_SetHint(SDL_HINT_MAC_BACKGROUND_APP, "1"); | ||
70 | SDL_SetHint(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, "1"); | 71 | SDL_SetHint(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, "1"); |
72 | #if SDL_VERSION_ATLEAST(2, 0, 8) | ||
71 | SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); | 73 | SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); |
72 | SDL_SetHint(SDL_HINT_MAC_BACKGROUND_APP, "1"); | 74 | #endif |
73 | #if 0 | 75 | #if 0 |
74 | SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "1"); /* debugging! */ | 76 | SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "1"); /* debugging! */ |
75 | #endif | 77 | #endif |
diff --git a/src/resources.c b/src/resources.c index c60a2916..5c7e41ea 100644 --- a/src/resources.c +++ b/src/resources.c | |||
@@ -25,6 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
25 | #include <the_Foundation/archive.h> | 25 | #include <the_Foundation/archive.h> |
26 | #include <the_Foundation/version.h> | 26 | #include <the_Foundation/version.h> |
27 | 27 | ||
28 | #include <SDL_rwops.h> | ||
29 | |||
28 | static iArchive *archive_; | 30 | static iArchive *archive_; |
29 | 31 | ||
30 | iBlock blobAbout_Resources; | 32 | iBlock blobAbout_Resources; |
@@ -96,7 +98,23 @@ static struct { | |||
96 | 98 | ||
97 | iBool init_Resources(const char *path) { | 99 | iBool init_Resources(const char *path) { |
98 | archive_ = new_Archive(); | 100 | archive_ = new_Archive(); |
99 | if (openFile_Archive(archive_, collectNewCStr_String(path))) { | 101 | iBool ok = iFalse; |
102 | #if defined (iPlatformAndroidMobile) | ||
103 | /* Resources are bundled as assets so they cannot be loaded as a regular file. | ||
104 | Fortunately, SDL implements a file wrapper. */ | ||
105 | SDL_RWops *io = SDL_RWFromFile(path, "rb"); | ||
106 | if (io) { | ||
107 | iBlock buf; | ||
108 | init_Block(&buf, (size_t) SDL_RWsize(io)); | ||
109 | SDL_RWread(io, data_Block(&buf), size_Block(&buf), 1); | ||
110 | SDL_RWclose(io); | ||
111 | ok = openData_Archive(archive_, &buf); | ||
112 | deinit_Block(&buf); | ||
113 | } | ||
114 | #else | ||
115 | ok = openFile_Archive(archive_, collectNewCStr_String(path)); | ||
116 | #endif | ||
117 | if (ok) { | ||
100 | iVersion appVer; | 118 | iVersion appVer; |
101 | init_Version(&appVer, range_CStr(LAGRANGE_APP_VERSION)); | 119 | init_Version(&appVer, range_CStr(LAGRANGE_APP_VERSION)); |
102 | iVersion resVer; | 120 | iVersion resVer; |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 746e03e0..46af5fcd 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1224,10 +1224,6 @@ static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode | |||
1224 | case tooManyRedirects_GmStatusCode: | 1224 | case tooManyRedirects_GmStatusCode: |
1225 | appendFormat_String(src, "=> %s\n", cstr_String(meta)); | 1225 | appendFormat_String(src, "=> %s\n", cstr_String(meta)); |
1226 | break; | 1226 | break; |
1227 | case tlsFailure_GmStatusCode: | ||
1228 | // useBanner = iFalse; /* valid data wasn't received from host */ | ||
1229 | // appendFormat_String(src, ">%s\n", cstr_String(meta)); | ||
1230 | break; | ||
1231 | case tlsServerCertificateExpired_GmStatusCode: | 1227 | case tlsServerCertificateExpired_GmStatusCode: |
1232 | makeFooterButtons_DocumentWidget_( | 1228 | makeFooterButtons_DocumentWidget_( |
1233 | d, | 1229 | d, |
diff --git a/src/ui/text.c b/src/ui/text.c index 977cac9c..4a4b3776 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -1871,7 +1871,7 @@ iInt2 tryAdvance_Text(int fontId, iRangecc text, int width, const char **endPos) | |||
1871 | } | 1871 | } |
1872 | 1872 | ||
1873 | iInt2 tryAdvanceNoWrap_Text(int fontId, iRangecc text, int width, const char **endPos) { | 1873 | iInt2 tryAdvanceNoWrap_Text(int fontId, iRangecc text, int width, const char **endPos) { |
1874 | if (width <= 1) { | 1874 | if (width && width <= 1) { |
1875 | *endPos = text.start; | 1875 | *endPos = text.start; |
1876 | return zero_I2(); | 1876 | return zero_I2(); |
1877 | } | 1877 | } |
@@ -2070,7 +2070,7 @@ iTextMetrics draw_WrapText(iWrapText *d, int fontId, iInt2 pos, int color) { | |||
2070 | const int width = d->mode == word_WrapTextMode | 2070 | const int width = d->mode == word_WrapTextMode |
2071 | ? tryAdvance_Text(fontId, text, d->maxWidth, &endPos).x | 2071 | ? tryAdvance_Text(fontId, text, d->maxWidth, &endPos).x |
2072 | : tryAdvanceNoWrap_Text(fontId, text, d->maxWidth, &endPos).x; | 2072 | : tryAdvanceNoWrap_Text(fontId, text, d->maxWidth, &endPos).x; |
2073 | notify_WrapText_(d, endPos, (iTextAttrib){ .colorId = color }, 0, width); | 2073 | notify_WrapText_(d, endPos, (iTextAttrib){ .fgColorId = color }, 0, width); |
2074 | drawRange_Text(fontId, pos, color, (iRangecc){ text.start, endPos }); | 2074 | drawRange_Text(fontId, pos, color, (iRangecc){ text.start, endPos }); |
2075 | text.start = endPos; | 2075 | text.start = endPos; |
2076 | pos.y += lineHeight_Text(fontId); | 2076 | pos.y += lineHeight_Text(fontId); |
diff --git a/src/ui/text_simple.c b/src/ui/text_simple.c index 81fb94a5..8560c138 100644 --- a/src/ui/text_simple.c +++ b/src/ui/text_simple.c | |||
@@ -61,7 +61,7 @@ static iRect runSimple_Font_(iFont *d, const iRunArgs *args) { | |||
61 | and other non-complex LTR scripts. Composed glyphs are not supported (must rely on text | 61 | and other non-complex LTR scripts. Composed glyphs are not supported (must rely on text |
62 | being in a pre-composed form). This algorithm is used if HarfBuzz is not available. */ | 62 | being in a pre-composed form). This algorithm is used if HarfBuzz is not available. */ |
63 | const iInt2 orig = args->pos; | 63 | const iInt2 orig = args->pos; |
64 | iTextAttrib attrib = { .colorId = args->color }; | 64 | iTextAttrib attrib = { .fgColorId = args->color }; |
65 | iRect bounds = { orig, init_I2(0, d->height) }; | 65 | iRect bounds = { orig, init_I2(0, d->height) }; |
66 | float xpos = orig.x; | 66 | float xpos = orig.x; |
67 | float xposMax = xpos; | 67 | float xposMax = xpos; |
@@ -118,8 +118,9 @@ static iRect runSimple_Font_(iFont *d, const iRunArgs *args) { | |||
118 | if (match_RegExp(activeText_->ansiEscape, chPos, args->text.end - chPos, &m)) { | 118 | if (match_RegExp(activeText_->ansiEscape, chPos, args->text.end - chPos, &m)) { |
119 | if (mode & draw_RunMode && ~mode & permanentColorFlag_RunMode) { | 119 | if (mode & draw_RunMode && ~mode & permanentColorFlag_RunMode) { |
120 | /* Change the color. */ | 120 | /* Change the color. */ |
121 | const iColor clr = | 121 | iColor clr; |
122 | ansiForeground_Color(capturedRange_RegExpMatch(&m, 1), tmParagraph_ColorId); | 122 | ansiColors_Color(capturedRange_RegExpMatch(&m, 1), tmParagraph_ColorId, |
123 | none_ColorId, &clr, NULL); | ||
123 | SDL_SetTextureColorMod(activeText_->cache, clr.r, clr.g, clr.b); | 124 | SDL_SetTextureColorMod(activeText_->cache, clr.r, clr.g, clr.b); |
124 | if (args->mode & fillBackground_RunMode) { | 125 | if (args->mode & fillBackground_RunMode) { |
125 | SDL_SetRenderDrawColor(activeText_->render, clr.r, clr.g, clr.b, 0); | 126 | SDL_SetRenderDrawColor(activeText_->render, clr.r, clr.g, clr.b, 0); |
diff --git a/src/ui/touch.c b/src/ui/touch.c index 195d1dff..d6846572 100644 --- a/src/ui/touch.c +++ b/src/ui/touch.c | |||
@@ -42,7 +42,11 @@ iDeclareType(TouchState) | |||
42 | 42 | ||
43 | static const uint32_t longPressSpanMs_ = 500; | 43 | static const uint32_t longPressSpanMs_ = 500; |
44 | static const uint32_t shortPressSpanMs_ = 250; | 44 | static const uint32_t shortPressSpanMs_ = 250; |
45 | #if defined (iPlatformAndroidMobile) | ||
46 | static const int tapRadiusPt_ = 30; /* inaccurate sensors? */ | ||
47 | #else | ||
45 | static const int tapRadiusPt_ = 10; | 48 | static const int tapRadiusPt_ = 10; |
49 | #endif | ||
46 | 50 | ||
47 | enum iTouchEdge { | 51 | enum iTouchEdge { |
48 | none_TouchEdge, | 52 | none_TouchEdge, |
diff --git a/src/ui/window.c b/src/ui/window.c index 0bbe588c..9f12cabf 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -263,6 +263,10 @@ static float pixelRatio_Window_(const iWindow *d) { | |||
263 | # define baseDPI_Window 96.0f | 263 | # define baseDPI_Window 96.0f |
264 | #endif | 264 | #endif |
265 | 265 | ||
266 | #if defined (iPlatformAndroidMobile) | ||
267 | float displayDensity_Android(void); | ||
268 | #endif | ||
269 | |||
266 | static float displayScale_Window_(const iWindow *d) { | 270 | static float displayScale_Window_(const iWindow *d) { |
267 | /* The environment variable LAGRANGE_OVERRIDE_DPI can be used to override the automatic | 271 | /* The environment variable LAGRANGE_OVERRIDE_DPI can be used to override the automatic |
268 | display DPI detection. If not set, or is an empty string, ignore it. | 272 | display DPI detection. If not set, or is an empty string, ignore it. |
@@ -289,6 +293,8 @@ static float displayScale_Window_(const iWindow *d) { | |||
289 | #elif defined (iPlatformMsys) | 293 | #elif defined (iPlatformMsys) |
290 | iUnused(d); | 294 | iUnused(d); |
291 | return desktopDPI_Win32(); | 295 | return desktopDPI_Win32(); |
296 | #elif defined (iPlatformAndroidMobile) | ||
297 | return displayDensity_Android(); | ||
292 | #else | 298 | #else |
293 | if (isRunningUnderWindowSystem_App()) { | 299 | if (isRunningUnderWindowSystem_App()) { |
294 | float vdpi = 0.0f; | 300 | float vdpi = 0.0f; |
@@ -457,7 +463,7 @@ void init_Window(iWindow *d, enum iWindowType type, iRect rect, uint32_t flags) | |||
457 | d->mouseGrab = NULL; | 463 | d->mouseGrab = NULL; |
458 | d->focus = NULL; | 464 | d->focus = NULL; |
459 | d->pendingCursor = NULL; | 465 | d->pendingCursor = NULL; |
460 | d->isExposed = iFalse; | 466 | d->isExposed = (deviceType_App() != desktop_AppDeviceType); |
461 | d->isMinimized = iFalse; | 467 | d->isMinimized = iFalse; |
462 | d->isInvalidated = iFalse; /* set when posting event, to avoid repeated events */ | 468 | d->isInvalidated = iFalse; /* set when posting event, to avoid repeated events */ |
463 | d->isMouseInside = iTrue; | 469 | d->isMouseInside = iTrue; |
@@ -541,6 +547,8 @@ void init_MainWindow(iMainWindow *d, iRect rect) { | |||
541 | SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal"); | 547 | SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal"); |
542 | flags |= SDL_WINDOW_METAL; | 548 | flags |= SDL_WINDOW_METAL; |
543 | d->base.isExposed = iTrue; | 549 | d->base.isExposed = iTrue; |
550 | #elif defined (iPlatformAndroidMobile) | ||
551 | d->base.isExposed = iTrue; | ||
544 | #else | 552 | #else |
545 | if (!forceSoftwareRender_App()) { | 553 | if (!forceSoftwareRender_App()) { |
546 | flags |= SDL_WINDOW_OPENGL; | 554 | flags |= SDL_WINDOW_OPENGL; |