diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | res/about/version.gmi | 12 | ||||
-rw-r--r-- | res/fi.skyjake.Lagrange.appdata.xml | 2 | ||||
-rw-r--r-- | res/lang/fi.bin | bin | 24879 -> 24893 bytes | |||
-rw-r--r-- | res/lang/ie.bin | bin | 24133 -> 24247 bytes | |||
-rw-r--r-- | res/lang/sr.bin | bin | 35978 -> 36801 bytes | |||
-rw-r--r-- | res/lang/tok.bin | bin | 22702 -> 22683 bytes | |||
-rw-r--r-- | src/app.c | 1 | ||||
-rw-r--r-- | src/gmcerts.h | 10 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 113 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 128 | ||||
-rw-r--r-- | src/ui/inputwidget.h | 3 | ||||
-rw-r--r-- | src/ui/root.c | 9 | ||||
-rw-r--r-- | src/ui/uploadwidget.c | 2 | ||||
-rw-r--r-- | src/ui/visbuf.c | 8 |
16 files changed, 174 insertions, 122 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index aac03046..c9037986 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -18,7 +18,7 @@ | |||
18 | cmake_minimum_required (VERSION 3.9) | 18 | cmake_minimum_required (VERSION 3.9) |
19 | 19 | ||
20 | project (Lagrange | 20 | project (Lagrange |
21 | VERSION 1.6.2 | 21 | VERSION 1.6.3 |
22 | DESCRIPTION "A Beautiful Gemini Client" | 22 | DESCRIPTION "A Beautiful Gemini Client" |
23 | LANGUAGES C | 23 | LANGUAGES C |
24 | ) | 24 | ) |
@@ -49,16 +49,16 @@ The required tools are a C11 compiler (e.g., Clang or GCC), CMake and `pkg-confi | |||
49 | 49 | ||
50 | ### Unicode text rendering | 50 | ### Unicode text rendering |
51 | 51 | ||
52 | Lagrange relies on the [HarfBuzz](https://harfbuzz.github.io) and [GNU FriBidi](https://github.com/fribidi/fribidi/) libraries for handling complex scripts and bidirectional text. This repository includes these two libraries as submodules. By default, HarfBuzz and GNU FriBidi will be compiled as part of the app, without any additional dependencies. This allows the app to be built on systems where these libraries are not readily available. | 52 | Lagrange relies on the [HarfBuzz](https://harfbuzz.github.io) and [GNU FriBidi](https://github.com/fribidi/fribidi/) libraries for handling complex scripts and bidirectional text. This repository includes these two libraries as submodules. By default, if HarfBuzz and GNU FriBidi are not available on the system, they will be compiled as part of the app without any additional dependencies. |
53 | 53 | ||
54 | Note that compiling these libraries has the following requirements: | 54 | Note that compiling these libraries has the following requirements: |
55 | 55 | ||
56 | * HarfBuzz requires a C++ compiler. | 56 | * HarfBuzz requires a C++ compiler. |
57 | * GNU FriBidi cannot be compiled with CMake; you need to have [Meson](https://mesonbuild.com) and [Ninja](https://ninja-build.org). | 57 | * GNU FriBidi cannot be compiled with CMake; you need to have [Meson](https://mesonbuild.com) and [Ninja](https://ninja-build.org). |
58 | 58 | ||
59 | If these requirements cannot be met, or you would prefer the use the system-provided HarfBuzz and GNU FriBidi, the build options can be changed. See the table below for `ENABLE_HARFBUZZ_MINIMAL` and `ENABLE_FRIBIDI_BUILD` (set both to **NO**). Note that a system-provided HarfBuzz likely has dependencies to other libraries, such as FreeType and GLib. | 59 | If these requirements cannot be met, or you would prefer the use the system-provided HarfBuzz and GNU FriBidi, please refer to the list of build options below: `ENABLE_HARFBUZZ_MINIMAL` and `ENABLE_FRIBIDI_BUILD` should both be set to **NO**. Note that a system-provided HarfBuzz likely has dependencies to other libraries, such as FreeType and GLib. |
60 | 60 | ||
61 | You also may disable HarfBuzz and/or GNU FriBidi entirely. The old text renderer that supports only non-complex left-to-right scripts is then used. | 61 | You also may disable HarfBuzz and/or GNU FriBidi entirely. The old text renderer that only supports non-complex left-to-right scripts is then used. |
62 | 62 | ||
63 | ### Installing to a custom directory | 63 | ### Installing to a custom directory |
64 | 64 | ||
diff --git a/res/about/version.gmi b/res/about/version.gmi index c06868c3..c45a8853 100644 --- a/res/about/version.gmi +++ b/res/about/version.gmi | |||
@@ -6,6 +6,16 @@ | |||
6 | ``` | 6 | ``` |
7 | # Release notes | 7 | # Release notes |
8 | 8 | ||
9 | ## 1.6.3 | ||
10 | * Select all text in an input field using Shift+Ctrl+A (macOS: ⌘A). | ||
11 | * Input fields do not lose focus when the window becomes inactive, making it easier to resume input afterwards. | ||
12 | * Fixed delay after switching to split view mode. | ||
13 | * Fixed what gets drawn in an empty tab, before a document is available for rendering (e.g., after switching to split view mode). | ||
14 | * Fixed highlighting the domain name in URL input fields. | ||
15 | * Fixed hiding the Gemini URL scheme in input fields when the window is narrow. | ||
16 | * Fixed the line break key modifier inadvertently affecting URL input fields, where line breaks are not allowed. | ||
17 | * Fixed the line break key modifier affecting the upload dialog's text field. | ||
18 | |||
9 | ## 1.6.2 | 19 | ## 1.6.2 |
10 | * Added `--tab-url` to print currently active tab's URL. | 20 | * Added `--tab-url` to print currently active tab's URL. |
11 | * Upload dialog expands to full window height when the entered text is long. | 21 | * Upload dialog expands to full window height when the entered text is long. |
@@ -16,7 +26,7 @@ | |||
16 | * Fixed incorrect behavior in input fields when typing or deleting text while holding down the Shift key. | 26 | * Fixed incorrect behavior in input fields when typing or deleting text while holding down the Shift key. |
17 | * Fixed crash in Upload dialog if server responds with a redirect. | 27 | * Fixed crash in Upload dialog if server responds with a redirect. |
18 | * Fixed buffered graphics (UI, fonts) getting lost under rare circumstances. | 28 | * Fixed buffered graphics (UI, fonts) getting lost under rare circumstances. |
19 | * Fixed drawing of wrapped text when the app is compiled with HarfBuzz. | 29 | * Fixed drawing of wrapped text when the app is compiled without HarfBuzz. |
20 | * macOS: Fixed UI not updating when system dark mode is toggled while the window is hidden. | 30 | * macOS: Fixed UI not updating when system dark mode is toggled while the window is hidden. |
21 | 31 | ||
22 | ## 1.6.1 | 32 | ## 1.6.1 |
diff --git a/res/fi.skyjake.Lagrange.appdata.xml b/res/fi.skyjake.Lagrange.appdata.xml index 247d2f0b..1db2717c 100644 --- a/res/fi.skyjake.Lagrange.appdata.xml +++ b/res/fi.skyjake.Lagrange.appdata.xml | |||
@@ -70,8 +70,6 @@ | |||
70 | redirect.</li> | 70 | redirect.</li> |
71 | <li>Fixed buffered graphics (UI, fonts) getting lost under rare | 71 | <li>Fixed buffered graphics (UI, fonts) getting lost under rare |
72 | circumstances.</li> | 72 | circumstances.</li> |
73 | <li>Fixed drawing of wrapped text when the app is compiled with | ||
74 | HarfBuzz.</li> | ||
75 | <li>macOS: Fixed UI not updating when system dark mode is toggled | 73 | <li>macOS: Fixed UI not updating when system dark mode is toggled |
76 | while the window is hidden.</li> | 74 | while the window is hidden.</li> |
77 | </ul> | 75 | </ul> |
diff --git a/res/lang/fi.bin b/res/lang/fi.bin index 7b7b6c28..2f1bb18f 100644 --- a/res/lang/fi.bin +++ b/res/lang/fi.bin | |||
Binary files differ | |||
diff --git a/res/lang/ie.bin b/res/lang/ie.bin index 97c02a90..a8bce39d 100644 --- a/res/lang/ie.bin +++ b/res/lang/ie.bin | |||
Binary files differ | |||
diff --git a/res/lang/sr.bin b/res/lang/sr.bin index 4a299323..df8e532b 100644 --- a/res/lang/sr.bin +++ b/res/lang/sr.bin | |||
Binary files differ | |||
diff --git a/res/lang/tok.bin b/res/lang/tok.bin index 4cd4212d..f2b59891 100644 --- a/res/lang/tok.bin +++ b/res/lang/tok.bin | |||
Binary files differ | |||
@@ -1992,6 +1992,7 @@ iBool handleCommand_App(const char *cmd) { | |||
1992 | (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1); | 1992 | (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1); |
1993 | const char *url = suffixPtr_Command(cmd, "url"); | 1993 | const char *url = suffixPtr_Command(cmd, "url"); |
1994 | setCStr_String(get_Window()->pendingSplitUrl, url ? url : ""); | 1994 | setCStr_String(get_Window()->pendingSplitUrl, url ? url : ""); |
1995 | postRefresh_App(); | ||
1995 | return iTrue; | 1996 | return iTrue; |
1996 | } | 1997 | } |
1997 | else if (equal_Command(cmd, "window.retain")) { | 1998 | else if (equal_Command(cmd, "window.retain")) { |
diff --git a/src/gmcerts.h b/src/gmcerts.h index 1a9480f7..02a41c14 100644 --- a/src/gmcerts.h +++ b/src/gmcerts.h | |||
@@ -60,9 +60,10 @@ iDeclareTypeConstructionArgs(GmCerts, const char *saveDir) | |||
60 | 60 | ||
61 | typedef iBool (*iGmCertsIdentityFilterFunc)(void *context, const iGmIdentity *); | 61 | typedef iBool (*iGmCertsIdentityFilterFunc)(void *context, const iGmIdentity *); |
62 | 62 | ||
63 | iBool checkTrust_GmCerts (iGmCerts *, iRangecc domain, uint16_t port, const iTlsCertificate *cert); | 63 | iBool checkTrust_GmCerts (iGmCerts *, iRangecc domain, uint16_t port, |
64 | void setTrusted_GmCerts (iGmCerts *, iRangecc domain, uint16_t port, const iBlock *fingerprint, | 64 | const iTlsCertificate *cert); |
65 | const iDate *validUntil); | 65 | void setTrusted_GmCerts (iGmCerts *, iRangecc domain, uint16_t port, |
66 | const iBlock *fingerprint, const iDate *validUntil); | ||
66 | iTime domainValidUntil_GmCerts(const iGmCerts *, iRangecc domain, uint16_t port); | 67 | iTime domainValidUntil_GmCerts(const iGmCerts *, iRangecc domain, uint16_t port); |
67 | 68 | ||
68 | /** | 69 | /** |
@@ -81,7 +82,8 @@ iGmIdentity * newIdentity_GmCerts (iGmCerts *, int flags, iDate validU | |||
81 | const iString *userId, const iString *domain, | 82 | const iString *userId, const iString *domain, |
82 | const iString *org, const iString *country); | 83 | const iString *org, const iString *country); |
83 | 84 | ||
84 | void importIdentity_GmCerts (iGmCerts *, iTlsCertificate *cert, const iString *notes); /* takes ownership */ | 85 | void importIdentity_GmCerts (iGmCerts *, iTlsCertificate *cert, |
86 | const iString *notes); /* takes ownership */ | ||
85 | void deleteIdentity_GmCerts (iGmCerts *, iGmIdentity *identity); | 87 | void deleteIdentity_GmCerts (iGmCerts *, iGmIdentity *identity); |
86 | void saveIdentities_GmCerts (const iGmCerts *); | 88 | void saveIdentities_GmCerts (const iGmCerts *); |
87 | 89 | ||
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index e1be27c2..703d1d13 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -493,7 +493,7 @@ static int documentWidth_DocumentWidget_(const iDocumentWidget *d) { | |||
493 | const iPrefs * prefs = prefs_App(); | 493 | const iPrefs * prefs = prefs_App(); |
494 | const int minWidth = 50 * gap_UI; /* lines must fit a word at least */ | 494 | const int minWidth = 50 * gap_UI; /* lines must fit a word at least */ |
495 | const float adjust = iClamp((float) bounds.size.x / gap_UI / 11 - 12, | 495 | const float adjust = iClamp((float) bounds.size.x / gap_UI / 11 - 12, |
496 | -2.0f, 10.0f); /* adapt to width */ | 496 | -1.0f, 10.0f); /* adapt to width */ |
497 | //printf("%f\n", adjust); fflush(stdout); | 497 | //printf("%f\n", adjust); fflush(stdout); |
498 | return iMini(iMax(minWidth, bounds.size.x - gap_UI * (d->pageMargin + adjust) * 2), | 498 | return iMini(iMax(minWidth, bounds.size.x - gap_UI * (d->pageMargin + adjust) * 2), |
499 | fontSize_UI * prefs->lineWidth * prefs->zoomPercent / 100); | 499 | fontSize_UI * prefs->lineWidth * prefs->zoomPercent / 100); |
@@ -4796,64 +4796,67 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4796 | }; | 4796 | }; |
4797 | init_Paint(&ctx.paint); | 4797 | init_Paint(&ctx.paint); |
4798 | render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); | 4798 | render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); |
4799 | setClip_Paint(&ctx.paint, clipBounds); | 4799 | int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); |
4800 | int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); | 4800 | const iBool isDocEmpty = size_GmDocument(d->doc).y == 0; |
4801 | draw_VisBuf(d->visBuf, init_I2(bounds.pos.x, yTop), ySpan_Rect(bounds)); | ||
4802 | /* Text markers. */ | ||
4803 | const iBool isTouchSelecting = (flags_Widget(w) & touchDrag_WidgetFlag) != 0; | 4801 | const iBool isTouchSelecting = (flags_Widget(w) & touchDrag_WidgetFlag) != 0; |
4804 | if (!isEmpty_Range(&d->foundMark) || !isEmpty_Range(&d->selectMark)) { | 4802 | if (!isDocEmpty) { |
4805 | SDL_Renderer *render = renderer_Window(get_Window()); | 4803 | setClip_Paint(&ctx.paint, clipBounds); |
4806 | ctx.firstMarkRect = zero_Rect(); | 4804 | draw_VisBuf(d->visBuf, init_I2(bounds.pos.x, yTop), ySpan_Rect(bounds)); |
4807 | ctx.lastMarkRect = zero_Rect(); | 4805 | /* Text markers. */ |
4808 | SDL_SetRenderDrawBlendMode(render, | 4806 | if (!isEmpty_Range(&d->foundMark) || !isEmpty_Range(&d->selectMark)) { |
4809 | isDark_ColorTheme(colorTheme_App()) ? SDL_BLENDMODE_ADD | 4807 | SDL_Renderer *render = renderer_Window(get_Window()); |
4810 | : SDL_BLENDMODE_BLEND); | 4808 | ctx.firstMarkRect = zero_Rect(); |
4811 | ctx.viewPos = topLeft_Rect(docBounds); | 4809 | ctx.lastMarkRect = zero_Rect(); |
4812 | /* Marker starting outside the visible range? */ | 4810 | SDL_SetRenderDrawBlendMode(render, |
4813 | if (d->visibleRuns.start) { | 4811 | isDark_ColorTheme(colorTheme_App()) ? SDL_BLENDMODE_ADD |
4814 | if (!isEmpty_Range(&d->selectMark) && | 4812 | : SDL_BLENDMODE_BLEND); |
4815 | d->selectMark.start < d->visibleRuns.start->text.start && | 4813 | ctx.viewPos = topLeft_Rect(docBounds); |
4816 | d->selectMark.end > d->visibleRuns.start->text.start) { | 4814 | /* Marker starting outside the visible range? */ |
4817 | ctx.inSelectMark = iTrue; | 4815 | if (d->visibleRuns.start) { |
4816 | if (!isEmpty_Range(&d->selectMark) && | ||
4817 | d->selectMark.start < d->visibleRuns.start->text.start && | ||
4818 | d->selectMark.end > d->visibleRuns.start->text.start) { | ||
4819 | ctx.inSelectMark = iTrue; | ||
4820 | } | ||
4821 | if (isEmpty_Range(&d->foundMark) && | ||
4822 | d->foundMark.start < d->visibleRuns.start->text.start && | ||
4823 | d->foundMark.end > d->visibleRuns.start->text.start) { | ||
4824 | ctx.inFoundMark = iTrue; | ||
4825 | } | ||
4818 | } | 4826 | } |
4819 | if (isEmpty_Range(&d->foundMark) && | 4827 | render_GmDocument(d->doc, vis, drawMark_DrawContext_, &ctx); |
4820 | d->foundMark.start < d->visibleRuns.start->text.start && | 4828 | SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_NONE); |
4821 | d->foundMark.end > d->visibleRuns.start->text.start) { | 4829 | /* Selection range pins. */ |
4822 | ctx.inFoundMark = iTrue; | 4830 | if (isTouchSelecting) { |
4831 | drawPin_(&ctx.paint, ctx.firstMarkRect, 0); | ||
4832 | drawPin_(&ctx.paint, ctx.lastMarkRect, 1); | ||
4823 | } | 4833 | } |
4824 | } | 4834 | } |
4825 | render_GmDocument(d->doc, vis, drawMark_DrawContext_, &ctx); | 4835 | drawMedia_DocumentWidget_(d, &ctx.paint); |
4826 | SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_NONE); | 4836 | /* Fill the top and bottom, in case the document is short. */ |
4827 | /* Selection range pins. */ | 4837 | if (yTop > top_Rect(bounds)) { |
4828 | if (isTouchSelecting) { | 4838 | fillRect_Paint(&ctx.paint, |
4829 | drawPin_(&ctx.paint, ctx.firstMarkRect, 0); | 4839 | (iRect){ bounds.pos, init_I2(bounds.size.x, yTop - top_Rect(bounds)) }, |
4830 | drawPin_(&ctx.paint, ctx.lastMarkRect, 1); | 4840 | hasSiteBanner_GmDocument(d->doc) ? tmBannerBackground_ColorId |
4831 | } | 4841 | : tmBackground_ColorId); |
4832 | } | 4842 | } |
4833 | drawMedia_DocumentWidget_(d, &ctx.paint); | 4843 | const int yBottom = yTop + size_GmDocument(d->doc).y + 1; |
4834 | /* Fill the top and bottom, in case the document is short. */ | 4844 | if (yBottom < bottom_Rect(bounds)) { |
4835 | if (yTop > top_Rect(bounds)) { | 4845 | fillRect_Paint(&ctx.paint, |
4836 | fillRect_Paint(&ctx.paint, | 4846 | init_Rect(bounds.pos.x, yBottom, bounds.size.x, bottom_Rect(bounds) - yBottom), |
4837 | (iRect){ bounds.pos, init_I2(bounds.size.x, yTop - top_Rect(bounds)) }, | 4847 | tmBackground_ColorId); |
4838 | hasSiteBanner_GmDocument(d->doc) ? tmBannerBackground_ColorId | 4848 | } |
4839 | : tmBackground_ColorId); | 4849 | unsetClip_Paint(&ctx.paint); |
4840 | } | 4850 | drawSideElements_DocumentWidget_(d); |
4841 | const int yBottom = yTop + size_GmDocument(d->doc).y + 1; | 4851 | if (prefs_App()->hoverLink && d->hoverLink) { |
4842 | if (yBottom < bottom_Rect(bounds)) { | 4852 | const int font = uiLabel_FontId; |
4843 | fillRect_Paint(&ctx.paint, | 4853 | const iRangecc linkUrl = range_String(linkUrl_GmDocument(d->doc, d->hoverLink->linkId)); |
4844 | init_Rect(bounds.pos.x, yBottom, bounds.size.x, bottom_Rect(bounds) - yBottom), | 4854 | const iInt2 size = measureRange_Text(font, linkUrl).bounds.size; |
4845 | tmBackground_ColorId); | 4855 | const iRect linkRect = { addY_I2(bottomLeft_Rect(bounds), -size.y), |
4846 | } | 4856 | addX_I2(size, 2 * gap_UI) }; |
4847 | unsetClip_Paint(&ctx.paint); | 4857 | fillRect_Paint(&ctx.paint, linkRect, tmBackground_ColorId); |
4848 | drawSideElements_DocumentWidget_(d); | 4858 | drawRange_Text(font, addX_I2(topLeft_Rect(linkRect), gap_UI), tmParagraph_ColorId, linkUrl); |
4849 | if (prefs_App()->hoverLink && d->hoverLink) { | 4859 | } |
4850 | const int font = uiLabel_FontId; | ||
4851 | const iRangecc linkUrl = range_String(linkUrl_GmDocument(d->doc, d->hoverLink->linkId)); | ||
4852 | const iInt2 size = measureRange_Text(font, linkUrl).bounds.size; | ||
4853 | const iRect linkRect = { addY_I2(bottomLeft_Rect(bounds), -size.y), | ||
4854 | addX_I2(size, 2 * gap_UI) }; | ||
4855 | fillRect_Paint(&ctx.paint, linkRect, tmBackground_ColorId); | ||
4856 | drawRange_Text(font, addX_I2(topLeft_Rect(linkRect), gap_UI), tmParagraph_ColorId, linkUrl); | ||
4857 | } | 4860 | } |
4858 | if (colorTheme_App() == pureWhite_ColorTheme) { | 4861 | if (colorTheme_App() == pureWhite_ColorTheme) { |
4859 | drawHLine_Paint(&ctx.paint, topLeft_Rect(bounds), width_Rect(bounds), uiSeparator_ColorId); | 4862 | drawHLine_Paint(&ctx.paint, topLeft_Rect(bounds), width_Rect(bounds), uiSeparator_ColorId); |
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index bd6927a6..9f233345 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -188,9 +188,9 @@ enum iInputWidgetFlag { | |||
188 | markWords_InputWidgetFlag = iBit(8), | 188 | markWords_InputWidgetFlag = iBit(8), |
189 | needUpdateBuffer_InputWidgetFlag = iBit(9), | 189 | needUpdateBuffer_InputWidgetFlag = iBit(9), |
190 | enterKeyEnabled_InputWidgetFlag = iBit(10), | 190 | enterKeyEnabled_InputWidgetFlag = iBit(10), |
191 | enterKeyInsertsLineFeed_InputWidgetFlag | 191 | lineBreaksEnabled_InputWidgetFlag= iBit(11), |
192 | = iBit(11), | ||
193 | needBackup_InputWidgetFlag = iBit(12), | 192 | needBackup_InputWidgetFlag = iBit(12), |
193 | useReturnKeyBehavior_InputWidgetFlag = iBit(13), | ||
194 | }; | 194 | }; |
195 | 195 | ||
196 | /*----------------------------------------------------------------------------------------------*/ | 196 | /*----------------------------------------------------------------------------------------------*/ |
@@ -567,6 +567,28 @@ static void updateAllLinesAndResizeHeight_InputWidget_(iInputWidget *d) { | |||
567 | } | 567 | } |
568 | } | 568 | } |
569 | 569 | ||
570 | static uint32_t cursorTimer_(uint32_t interval, void *w) { | ||
571 | iInputWidget *d = w; | ||
572 | if (d->cursorVis > 1) { | ||
573 | d->cursorVis--; | ||
574 | } | ||
575 | else { | ||
576 | d->cursorVis ^= 1; | ||
577 | } | ||
578 | refresh_Widget(w); | ||
579 | return interval; | ||
580 | } | ||
581 | |||
582 | static void startOrStopCursorTimer_InputWidget_(iInputWidget *d, iBool doStart) { | ||
583 | if (doStart && !d->timer) { | ||
584 | d->timer = SDL_AddTimer(refreshInterval_InputWidget_, cursorTimer_, d); | ||
585 | } | ||
586 | else if (!doStart && d->timer) { | ||
587 | SDL_RemoveTimer(d->timer); | ||
588 | d->timer = 0; | ||
589 | } | ||
590 | } | ||
591 | |||
570 | void init_InputWidget(iInputWidget *d, size_t maxLen) { | 592 | void init_InputWidget(iInputWidget *d, size_t maxLen) { |
571 | iWidget *w = &d->widget; | 593 | iWidget *w = &d->widget; |
572 | init_Widget(w); | 594 | init_Widget(w); |
@@ -588,10 +610,11 @@ void init_InputWidget(iInputWidget *d, size_t maxLen) { | |||
588 | d->cursor = zero_I2(); | 610 | d->cursor = zero_I2(); |
589 | d->prevCursor = zero_I2(); | 611 | d->prevCursor = zero_I2(); |
590 | d->lastUpdateWidth = 0; | 612 | d->lastUpdateWidth = 0; |
591 | d->inFlags = eatEscape_InputWidgetFlag | enterKeyEnabled_InputWidgetFlag; | 613 | d->inFlags = eatEscape_InputWidgetFlag | enterKeyEnabled_InputWidgetFlag | |
592 | if (deviceType_App() != desktop_AppDeviceType) { | 614 | lineBreaksEnabled_InputWidgetFlag | useReturnKeyBehavior_InputWidgetFlag; |
593 | d->inFlags |= enterKeyInsertsLineFeed_InputWidgetFlag; | 615 | // if (deviceType_App() != desktop_AppDeviceType) { |
594 | } | 616 | // d->inFlags |= enterKeyInsertsLineFeed_InputWidgetFlag; |
617 | // } | ||
595 | iZap(d->mark); | 618 | iZap(d->mark); |
596 | setMaxLen_InputWidget(d, maxLen); | 619 | setMaxLen_InputWidget(d, maxLen); |
597 | d->visWrapLines.start = 0; | 620 | d->visWrapLines.start = 0; |
@@ -627,9 +650,7 @@ void deinit_InputWidget(iInputWidget *d) { | |||
627 | delete_TextBuf(d->buffered); | 650 | delete_TextBuf(d->buffered); |
628 | clearUndo_InputWidget_(d); | 651 | clearUndo_InputWidget_(d); |
629 | deinit_Array(&d->undoStack); | 652 | deinit_Array(&d->undoStack); |
630 | if (d->timer) { | 653 | startOrStopCursorTimer_InputWidget_(d, iFalse); |
631 | SDL_RemoveTimer(d->timer); | ||
632 | } | ||
633 | deinit_String(&d->srcHint); | 654 | deinit_String(&d->srcHint); |
634 | deinit_String(&d->hint); | 655 | deinit_String(&d->hint); |
635 | deinit_String(&d->oldText); | 656 | deinit_String(&d->oldText); |
@@ -670,7 +691,6 @@ void setMode_InputWidget(iInputWidget *d, enum iInputMode mode) { | |||
670 | d->mode = mode; | 691 | d->mode = mode; |
671 | } | 692 | } |
672 | 693 | ||
673 | #if 0 | ||
674 | static void restoreDefaultScheme_(iString *url) { | 694 | static void restoreDefaultScheme_(iString *url) { |
675 | iUrl parts; | 695 | iUrl parts; |
676 | init_Url(&parts, url); | 696 | init_Url(&parts, url); |
@@ -685,17 +705,14 @@ static const iString *omitDefaultScheme_(iString *url) { | |||
685 | } | 705 | } |
686 | return url; | 706 | return url; |
687 | } | 707 | } |
688 | #endif | ||
689 | 708 | ||
690 | const iString *text_InputWidget(const iInputWidget *d) { | 709 | const iString *text_InputWidget(const iInputWidget *d) { |
691 | if (d) { | 710 | if (d) { |
692 | iString *text = collect_String(text_InputWidget_(d)); | 711 | iString *text = collect_String(text_InputWidget_(d)); |
693 | #if 0 | ||
694 | if (d->inFlags & isUrl_InputWidgetFlag) { | 712 | if (d->inFlags & isUrl_InputWidgetFlag) { |
695 | /* Add the "gemini" scheme back if one is omitted. */ | 713 | /* Add the "gemini" scheme back if one is omitted. */ |
696 | restoreDefaultScheme_(text); | 714 | restoreDefaultScheme_(text); |
697 | } | 715 | } |
698 | #endif | ||
699 | return text; | 716 | return text; |
700 | } | 717 | } |
701 | return collectNew_String(); | 718 | return collectNew_String(); |
@@ -732,14 +749,18 @@ void setValidator_InputWidget(iInputWidget *d, iInputWidgetValidatorFunc validat | |||
732 | d->validatorContext = context; | 749 | d->validatorContext = context; |
733 | } | 750 | } |
734 | 751 | ||
735 | void setEnterInsertsLF_InputWidget(iInputWidget *d, iBool enterInsertsLF) { | 752 | void setLineBreaksEnabled_InputWidget(iInputWidget *d, iBool lineBreaksEnabled) { |
736 | iChangeFlags(d->inFlags, enterKeyInsertsLineFeed_InputWidgetFlag, enterInsertsLF); | 753 | iChangeFlags(d->inFlags, lineBreaksEnabled_InputWidgetFlag, lineBreaksEnabled); |
737 | } | 754 | } |
738 | 755 | ||
739 | void setEnterKeyEnabled_InputWidget(iInputWidget *d, iBool enterKeyEnabled) { | 756 | void setEnterKeyEnabled_InputWidget(iInputWidget *d, iBool enterKeyEnabled) { |
740 | iChangeFlags(d->inFlags, enterKeyEnabled_InputWidgetFlag, enterKeyEnabled); | 757 | iChangeFlags(d->inFlags, enterKeyEnabled_InputWidgetFlag, enterKeyEnabled); |
741 | } | 758 | } |
742 | 759 | ||
760 | void setUseReturnKeyBehavior_InputWidget(iInputWidget *d, iBool useReturnKeyBehavior) { | ||
761 | iChangeFlags(d->inFlags, useReturnKeyBehavior_InputWidgetFlag, useReturnKeyBehavior); | ||
762 | } | ||
763 | |||
743 | void setHint_InputWidget(iInputWidget *d, const char *hintText) { | 764 | void setHint_InputWidget(iInputWidget *d, const char *hintText) { |
744 | /* Keep original for retranslations. */ | 765 | /* Keep original for retranslations. */ |
745 | setCStr_String(&d->srcHint, hintText); | 766 | setCStr_String(&d->srcHint, hintText); |
@@ -795,6 +816,22 @@ static void updateBuffered_InputWidget_(iInputWidget *d) { | |||
795 | for (int i = visRange.start; i < visRange.end; i++) { | 816 | for (int i = visRange.start; i < visRange.end; i++) { |
796 | append_String(visText, &line_InputWidget_(d, i)->text); | 817 | append_String(visText, &line_InputWidget_(d, i)->text); |
797 | } | 818 | } |
819 | if (d->inFlags & isUrl_InputWidgetFlag) { | ||
820 | /* Highlight the host name. */ | ||
821 | iUrl parts; | ||
822 | init_Url(&parts, visText); | ||
823 | if (!isEmpty_Range(&parts.host)) { | ||
824 | const char *cstr = cstr_String(visText); | ||
825 | insertData_Block(&visText->chars, | ||
826 | parts.host.end - cstr, | ||
827 | restore_ColorEscape, | ||
828 | strlen(restore_ColorEscape)); | ||
829 | insertData_Block(&visText->chars, | ||
830 | parts.host.start - cstr, | ||
831 | uiTextStrong_ColorEscape, | ||
832 | strlen(uiTextStrong_ColorEscape)); | ||
833 | } | ||
834 | } | ||
798 | iWrapText wt = wrap_InputWidget_(d, 0); | 835 | iWrapText wt = wrap_InputWidget_(d, 0); |
799 | wt.text = range_String(visText); | 836 | wt.text = range_String(visText); |
800 | const int fg = uiInputText_ColorId; | 837 | const int fg = uiInputText_ColorId; |
@@ -828,12 +865,10 @@ void setText_InputWidget(iInputWidget *d, const iString *text) { | |||
828 | punyEncodeUrlHost_String(enc); | 865 | punyEncodeUrlHost_String(enc); |
829 | text = enc; | 866 | text = enc; |
830 | } | 867 | } |
831 | #if 0 | ||
832 | /* Omit the default (Gemini) scheme if there isn't much space. */ | 868 | /* Omit the default (Gemini) scheme if there isn't much space. */ |
833 | if (isNarrow_Root(as_Widget(d)->root)) { | 869 | if (isNarrow_Root(as_Widget(d)->root)) { |
834 | text = omitDefaultScheme_(collect_String(copy_String(text))); | 870 | text = omitDefaultScheme_(collect_String(copy_String(text))); |
835 | } | 871 | } |
836 | #endif | ||
837 | } | 872 | } |
838 | clearUndo_InputWidget_(d); | 873 | clearUndo_InputWidget_(d); |
839 | iString *nfcText = collect_String(copy_String(text)); | 874 | iString *nfcText = collect_String(copy_String(text)); |
@@ -848,10 +883,6 @@ void setText_InputWidget(iInputWidget *d, const iString *text) { | |||
848 | if (!isFocused_Widget(d)) { | 883 | if (!isFocused_Widget(d)) { |
849 | iZap(d->mark); | 884 | iZap(d->mark); |
850 | } | 885 | } |
851 | // else { | ||
852 | // d->cursor.y = iMin(d->cursor.y, (int) size_Array(&d->lines) - 1); | ||
853 | // d->cursor.x = iMin(d->cursor.x, size_String(&cursorLine_InputWidget_(d)->text)); | ||
854 | // } | ||
855 | if (!isFocused_Widget(d)) { | 886 | if (!isFocused_Widget(d)) { |
856 | d->inFlags |= needUpdateBuffer_InputWidgetFlag; | 887 | d->inFlags |= needUpdateBuffer_InputWidgetFlag; |
857 | } | 888 | } |
@@ -866,18 +897,6 @@ void setTextCStr_InputWidget(iInputWidget *d, const char *cstr) { | |||
866 | delete_String(str); | 897 | delete_String(str); |
867 | } | 898 | } |
868 | 899 | ||
869 | static uint32_t cursorTimer_(uint32_t interval, void *w) { | ||
870 | iInputWidget *d = w; | ||
871 | if (d->cursorVis > 1) { | ||
872 | d->cursorVis--; | ||
873 | } | ||
874 | else { | ||
875 | d->cursorVis ^= 1; | ||
876 | } | ||
877 | refresh_Widget(w); | ||
878 | return interval; | ||
879 | } | ||
880 | |||
881 | static size_t cursorToIndex_InputWidget_(const iInputWidget *d, iInt2 pos) { | 900 | static size_t cursorToIndex_InputWidget_(const iInputWidget *d, iInt2 pos) { |
882 | if (pos.y < 0) { | 901 | if (pos.y < 0) { |
883 | return 0; | 902 | return 0; |
@@ -930,7 +949,7 @@ void begin_InputWidget(iInputWidget *d) { | |||
930 | setFlags_Widget(w, selected_WidgetFlag, iTrue); | 949 | setFlags_Widget(w, selected_WidgetFlag, iTrue); |
931 | showCursor_InputWidget_(d); | 950 | showCursor_InputWidget_(d); |
932 | refresh_Widget(w); | 951 | refresh_Widget(w); |
933 | d->timer = SDL_AddTimer(refreshInterval_InputWidget_, cursorTimer_, d); | 952 | startOrStopCursorTimer_InputWidget_(d, iTrue); |
934 | d->inFlags &= ~enterPressed_InputWidgetFlag; | 953 | d->inFlags &= ~enterPressed_InputWidgetFlag; |
935 | if (d->inFlags & selectAllOnFocus_InputWidgetFlag) { | 954 | if (d->inFlags & selectAllOnFocus_InputWidgetFlag) { |
936 | d->mark = (iRanges){ 0, lastLine_InputWidget_(d)->range.end }; | 955 | d->mark = (iRanges){ 0, lastLine_InputWidget_(d)->range.end }; |
@@ -955,8 +974,7 @@ void end_InputWidget(iInputWidget *d, iBool accept) { | |||
955 | splitToLines_(&d->oldText, &d->lines); | 974 | splitToLines_(&d->oldText, &d->lines); |
956 | } | 975 | } |
957 | d->inFlags |= needUpdateBuffer_InputWidgetFlag; | 976 | d->inFlags |= needUpdateBuffer_InputWidgetFlag; |
958 | SDL_RemoveTimer(d->timer); | 977 | startOrStopCursorTimer_InputWidget_(d, iFalse); |
959 | d->timer = 0; | ||
960 | SDL_StopTextInput(); | 978 | SDL_StopTextInput(); |
961 | setFlags_Widget(w, selected_WidgetFlag | keepOnTop_WidgetFlag, iFalse); | 979 | setFlags_Widget(w, selected_WidgetFlag | keepOnTop_WidgetFlag, iFalse); |
962 | const char *id = cstr_String(id_Widget(as_Widget(d))); | 980 | const char *id = cstr_String(id_Widget(as_Widget(d))); |
@@ -1383,17 +1401,29 @@ static iBool isArrowUpDownConsumed_InputWidget_(const iInputWidget *d) { | |||
1383 | return d->maxWrapLines > 1; | 1401 | return d->maxWrapLines > 1; |
1384 | } | 1402 | } |
1385 | 1403 | ||
1404 | static iBool checkLineBreakMods_InputWidget_(const iInputWidget *d, int mods) { | ||
1405 | if (d->inFlags & useReturnKeyBehavior_InputWidgetFlag) { | ||
1406 | return mods == lineBreakKeyMod_ReturnKeyBehavior(prefs_App()->returnKey); | ||
1407 | } | ||
1408 | return mods == 0; | ||
1409 | } | ||
1410 | |||
1411 | static iBool checkAcceptMods_InputWidget_(const iInputWidget *d, int mods) { | ||
1412 | if (d->inFlags & useReturnKeyBehavior_InputWidgetFlag) { | ||
1413 | return mods == acceptKeyMod_ReturnKeyBehavior(prefs_App()->returnKey); | ||
1414 | } | ||
1415 | return mods == 0; | ||
1416 | } | ||
1417 | |||
1386 | static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | 1418 | static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { |
1387 | iWidget *w = as_Widget(d); | 1419 | iWidget *w = as_Widget(d); |
1388 | /* Resize according to width immediately. */ | 1420 | /* Resize according to width immediately. */ |
1389 | if (d->lastUpdateWidth != w->rect.size.x) { | 1421 | if (d->lastUpdateWidth != w->rect.size.x) { |
1390 | d->inFlags |= needUpdateBuffer_InputWidgetFlag; | 1422 | d->inFlags |= needUpdateBuffer_InputWidgetFlag; |
1391 | #if 0 | ||
1392 | if (d->inFlags & isUrl_InputWidgetFlag) { | 1423 | if (d->inFlags & isUrl_InputWidgetFlag) { |
1393 | /* Restore/omit the default scheme if necessary. */ | 1424 | /* Restore/omit the default scheme if necessary. */ |
1394 | setText_InputWidget(d, text_InputWidget(d)); | 1425 | setText_InputWidget(d, text_InputWidget(d)); |
1395 | } | 1426 | } |
1396 | #endif | ||
1397 | updateAllLinesAndResizeHeight_InputWidget_(d); | 1427 | updateAllLinesAndResizeHeight_InputWidget_(d); |
1398 | d->lastUpdateWidth = w->rect.size.x; | 1428 | d->lastUpdateWidth = w->rect.size.x; |
1399 | } | 1429 | } |
@@ -1401,6 +1431,13 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1401 | begin_InputWidget(d); | 1431 | begin_InputWidget(d); |
1402 | return iFalse; | 1432 | return iFalse; |
1403 | } | 1433 | } |
1434 | else if (isEditing_InputWidget_(d) && (isCommand_UserEvent(ev, "window.focus.lost") || | ||
1435 | isCommand_UserEvent(ev, "window.focus.gained"))) { | ||
1436 | startOrStopCursorTimer_InputWidget_(d, isCommand_UserEvent(ev, "window.focus.gained")); | ||
1437 | d->cursorVis = 1; | ||
1438 | refresh_Widget(d); | ||
1439 | return iFalse; | ||
1440 | } | ||
1404 | else if (isCommand_UserEvent(ev, "keyroot.changed")) { | 1441 | else if (isCommand_UserEvent(ev, "keyroot.changed")) { |
1405 | d->inFlags |= needUpdateBuffer_InputWidgetFlag; | 1442 | d->inFlags |= needUpdateBuffer_InputWidgetFlag; |
1406 | } | 1443 | } |
@@ -1614,10 +1651,10 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1614 | return iTrue; | 1651 | return iTrue; |
1615 | case SDLK_RETURN: | 1652 | case SDLK_RETURN: |
1616 | case SDLK_KP_ENTER: | 1653 | case SDLK_KP_ENTER: |
1617 | if (~d->inFlags & isSensitive_InputWidgetFlag && d->maxLen == 0) { | 1654 | if (~d->inFlags & isSensitive_InputWidgetFlag && |
1618 | if (mods == lineBreakKeyMod_ReturnKeyBehavior(prefs_App()->returnKey) || | 1655 | ~d->inFlags & isUrl_InputWidgetFlag && |
1619 | (~d->inFlags & isUrl_InputWidgetFlag && | 1656 | d->inFlags & lineBreaksEnabled_InputWidgetFlag && d->maxLen == 0) { |
1620 | d->inFlags & enterKeyInsertsLineFeed_InputWidgetFlag)) { | 1657 | if (checkLineBreakMods_InputWidget_(d, mods)) { |
1621 | pushUndo_InputWidget_(d); | 1658 | pushUndo_InputWidget_(d); |
1622 | deleteMarked_InputWidget_(d); | 1659 | deleteMarked_InputWidget_(d); |
1623 | insertChar_InputWidget_(d, '\n'); | 1660 | insertChar_InputWidget_(d, '\n'); |
@@ -1626,7 +1663,8 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1626 | } | 1663 | } |
1627 | } | 1664 | } |
1628 | if (d->inFlags & enterKeyEnabled_InputWidgetFlag && | 1665 | if (d->inFlags & enterKeyEnabled_InputWidgetFlag && |
1629 | mods == acceptKeyMod_ReturnKeyBehavior(prefs_App()->returnKey)) { | 1666 | (checkAcceptMods_InputWidget_(d, mods) || |
1667 | (~d->inFlags & lineBreaksEnabled_InputWidgetFlag))) { | ||
1630 | d->inFlags |= enterPressed_InputWidgetFlag; | 1668 | d->inFlags |= enterPressed_InputWidgetFlag; |
1631 | setFocus_Widget(NULL); | 1669 | setFocus_Widget(NULL); |
1632 | return iTrue; | 1670 | return iTrue; |
@@ -1728,6 +1766,9 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1728 | case SDLK_a: | 1766 | case SDLK_a: |
1729 | #if defined (iPlatformApple) | 1767 | #if defined (iPlatformApple) |
1730 | if (mods == KMOD_PRIMARY) { | 1768 | if (mods == KMOD_PRIMARY) { |
1769 | #else | ||
1770 | if (mods == (KMOD_PRIMARY | KMOD_SHIFT)) { | ||
1771 | #endif | ||
1731 | selectAll_InputWidget(d); | 1772 | selectAll_InputWidget(d); |
1732 | d->mark.start = 0; | 1773 | d->mark.start = 0; |
1733 | d->mark.end = cursorToIndex_InputWidget_(d, curMax); | 1774 | d->mark.end = cursorToIndex_InputWidget_(d, curMax); |
@@ -1736,7 +1777,6 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1736 | refresh_Widget(w); | 1777 | refresh_Widget(w); |
1737 | return iTrue; | 1778 | return iTrue; |
1738 | } | 1779 | } |
1739 | #endif | ||
1740 | /* fall through for Emacs-style Home/End */ | 1780 | /* fall through for Emacs-style Home/End */ |
1741 | case SDLK_e: | 1781 | case SDLK_e: |
1742 | if (mods == KMOD_CTRL || mods == (KMOD_CTRL | KMOD_SHIFT)) { | 1782 | if (mods == KMOD_CTRL || mods == (KMOD_CTRL | KMOD_SHIFT)) { |
diff --git a/src/ui/inputwidget.h b/src/ui/inputwidget.h index a94291ed..0d327ca6 100644 --- a/src/ui/inputwidget.h +++ b/src/ui/inputwidget.h | |||
@@ -50,8 +50,9 @@ void setFont_InputWidget (iInputWidget *, int fontId); | |||
50 | void setContentPadding_InputWidget (iInputWidget *, int left, int right); /* only affects the text entry */ | 50 | void setContentPadding_InputWidget (iInputWidget *, int left, int right); /* only affects the text entry */ |
51 | void setLineLimits_InputWidget (iInputWidget *, int minLines, int maxLines); | 51 | void setLineLimits_InputWidget (iInputWidget *, int minLines, int maxLines); |
52 | void setValidator_InputWidget (iInputWidget *, iInputWidgetValidatorFunc validator, void *context); | 52 | void setValidator_InputWidget (iInputWidget *, iInputWidgetValidatorFunc validator, void *context); |
53 | void setEnterInsertsLF_InputWidget (iInputWidget *, iBool enterInsertsLF); | 53 | void setLineBreaksEnabled_InputWidget(iInputWidget *, iBool lineBreaksEnabled); |
54 | void setEnterKeyEnabled_InputWidget (iInputWidget *, iBool enterKeyEnabled); | 54 | void setEnterKeyEnabled_InputWidget (iInputWidget *, iBool enterKeyEnabled); |
55 | void setUseReturnKeyBehavior_InputWidget(iInputWidget *, iBool useReturnKeyBehavior); | ||
55 | void setBackupFileName_InputWidget (iInputWidget *, const char *fileName); | 56 | void setBackupFileName_InputWidget (iInputWidget *, const char *fileName); |
56 | void begin_InputWidget (iInputWidget *); | 57 | void begin_InputWidget (iInputWidget *); |
57 | void end_InputWidget (iInputWidget *, iBool accept); | 58 | void end_InputWidget (iInputWidget *, iBool accept); |
diff --git a/src/ui/root.c b/src/ui/root.c index 9d92c44e..a8b9f998 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -358,9 +358,9 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { | |||
358 | return iTrue; | 358 | return iTrue; |
359 | } | 359 | } |
360 | else if (equal_Command(cmd, "window.focus.lost")) { | 360 | else if (equal_Command(cmd, "window.focus.lost")) { |
361 | #if !defined (iPlatformMobile) /* apps don't share input focus on mobile */ | 361 | //#if !defined (iPlatformMobile) /* apps don't share input focus on mobile */ |
362 | setFocus_Widget(NULL); | 362 | // setFocus_Widget(NULL); |
363 | #endif | 363 | //#endif |
364 | setTextColor_LabelWidget(findWidget_App("winbar.app"), uiAnnotation_ColorId); | 364 | setTextColor_LabelWidget(findWidget_App("winbar.app"), uiAnnotation_ColorId); |
365 | setTextColor_LabelWidget(findWidget_App("winbar.title"), uiAnnotation_ColorId); | 365 | setTextColor_LabelWidget(findWidget_App("winbar.title"), uiAnnotation_ColorId); |
366 | return iFalse; | 366 | return iFalse; |
@@ -1077,6 +1077,7 @@ void createUserInterface_Root(iRoot *d) { | |||
1077 | setSelectAllOnFocus_InputWidget(url, iTrue); | 1077 | setSelectAllOnFocus_InputWidget(url, iTrue); |
1078 | setId_Widget(as_Widget(url), "url"); | 1078 | setId_Widget(as_Widget(url), "url"); |
1079 | setLineLimits_InputWidget(url, 1, 1); /* just one line while not focused */ | 1079 | setLineLimits_InputWidget(url, 1, 1); /* just one line while not focused */ |
1080 | setLineBreaksEnabled_InputWidget(url, iFalse); | ||
1080 | setUrlContent_InputWidget(url, iTrue); | 1081 | setUrlContent_InputWidget(url, iTrue); |
1081 | setNotifyEdits_InputWidget(url, iTrue); | 1082 | setNotifyEdits_InputWidget(url, iTrue); |
1082 | setTextCStr_InputWidget(url, "gemini://"); | 1083 | setTextCStr_InputWidget(url, "gemini://"); |
@@ -1272,7 +1273,7 @@ void createUserInterface_Root(iRoot *d) { | |||
1272 | setHint_InputWidget(input, "${hint.findtext}"); | 1273 | setHint_InputWidget(input, "${hint.findtext}"); |
1273 | setSelectAllOnFocus_InputWidget(input, iTrue); | 1274 | setSelectAllOnFocus_InputWidget(input, iTrue); |
1274 | setEatEscape_InputWidget(input, iFalse); /* unfocus and close with one keypress */ | 1275 | setEatEscape_InputWidget(input, iFalse); /* unfocus and close with one keypress */ |
1275 | setEnterInsertsLF_InputWidget(input, iFalse); | 1276 | setLineBreaksEnabled_InputWidget(input, iFalse); |
1276 | setId_Widget(addChildFlags_Widget(searchBar, iClob(input), expand_WidgetFlag), | 1277 | setId_Widget(addChildFlags_Widget(searchBar, iClob(input), expand_WidgetFlag), |
1277 | "find.input"); | 1278 | "find.input"); |
1278 | addChild_Widget(searchBar, iClob(newIcon_LabelWidget(" \u2b9f ", 'g', KMOD_PRIMARY, "find.next"))); | 1279 | addChild_Widget(searchBar, iClob(newIcon_LabelWidget(" \u2b9f ", 'g', KMOD_PRIMARY, "find.next"))); |
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c index 7bfa73bd..57b6b6b7 100644 --- a/src/ui/uploadwidget.c +++ b/src/ui/uploadwidget.c | |||
@@ -116,8 +116,8 @@ void init_UploadWidget(iUploadWidget *d) { | |||
116 | setId_Widget(as_Widget(d->input), "upload.text"); | 116 | setId_Widget(as_Widget(d->input), "upload.text"); |
117 | setFont_InputWidget(d->input, monospace_FontId); | 117 | setFont_InputWidget(d->input, monospace_FontId); |
118 | setLineLimits_InputWidget(d->input, 7, 20); | 118 | setLineLimits_InputWidget(d->input, 7, 20); |
119 | setUseReturnKeyBehavior_InputWidget(d->input, iFalse); /* traditional text editor */ | ||
119 | setHint_InputWidget(d->input, "${hint.upload.text}"); | 120 | setHint_InputWidget(d->input, "${hint.upload.text}"); |
120 | setEnterInsertsLF_InputWidget(d->input, iTrue); | ||
121 | setFixedSize_Widget(as_Widget(d->input), init_I2(120 * gap_UI, -1)); | 121 | setFixedSize_Widget(as_Widget(d->input), init_I2(120 * gap_UI, -1)); |
122 | addChild_Widget(page, iClob(d->input)); | 122 | addChild_Widget(page, iClob(d->input)); |
123 | appendFramelessTabPage_Widget(tabs, iClob(page), "${heading.upload.text}", '1', 0); | 123 | appendFramelessTabPage_Widget(tabs, iClob(page), "${heading.upload.text}", '1', 0); |
diff --git a/src/ui/visbuf.c b/src/ui/visbuf.c index 88a5fd60..503d0a2f 100644 --- a/src/ui/visbuf.c +++ b/src/ui/visbuf.c | |||
@@ -58,18 +58,14 @@ void alloc_VisBuf(iVisBuf *d, const iInt2 size, int granularity) { | |||
58 | if (tex->texture) { | 58 | if (tex->texture) { |
59 | SDL_DestroyTexture(tex->texture); | 59 | SDL_DestroyTexture(tex->texture); |
60 | } | 60 | } |
61 | SDL_Renderer *rend = renderer_Window(get_Window()); | ||
61 | tex->texture = | 62 | tex->texture = |
62 | SDL_CreateTexture(renderer_Window(get_Window()), | 63 | SDL_CreateTexture(rend, |
63 | SDL_PIXELFORMAT_RGBA8888, | 64 | SDL_PIXELFORMAT_RGBA8888, |
64 | SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, | 65 | SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, |
65 | texSize.x, | 66 | texSize.x, |
66 | texSize.y); | 67 | texSize.y); |
67 | SDL_SetTextureBlendMode(tex->texture, SDL_BLENDMODE_NONE); | 68 | SDL_SetTextureBlendMode(tex->texture, SDL_BLENDMODE_NONE); |
68 | // tex->origin = i * texSize.y; | ||
69 | // iZap(tex->validRange); | ||
70 | // if (d->invalidUserData) { | ||
71 | // d->invalidUserData(i, d->buffers[i].user); | ||
72 | // } | ||
73 | } | 69 | } |
74 | invalidate_VisBuf(d); | 70 | invalidate_VisBuf(d); |
75 | } | 71 | } |