summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app.c10
-rw-r--r--src/ipc.c2
-rw-r--r--src/ui/color.c9
-rw-r--r--src/ui/documentwidget.c2
-rw-r--r--src/ui/inputwidget.c140
-rw-r--r--src/ui/inputwidget.h3
-rw-r--r--src/ui/root.c9
-rw-r--r--src/ui/uploadwidget.c2
8 files changed, 129 insertions, 48 deletions
diff --git a/src/app.c b/src/app.c
index abfd584a..8318eee4 100644
--- a/src/app.c
+++ b/src/app.c
@@ -581,6 +581,9 @@ static void communicateWithRunningInstance_App_(iApp *d, iProcessId instance,
581 else if (equal_CommandLineConstIterator(&i, "close-tab")) { 581 else if (equal_CommandLineConstIterator(&i, "close-tab")) {
582 appendCStr_String(cmds, "tabs.close\n"); 582 appendCStr_String(cmds, "tabs.close\n");
583 } 583 }
584 else if (equal_CommandLineConstIterator(&i, "tab-url")) {
585 appendFormat_String(cmds, "ipc.active.url pid:%d\n", pid);
586 }
584 else if (equal_CommandLineConstIterator(&i, listTabUrls_CommandLineOption)) { 587 else if (equal_CommandLineConstIterator(&i, listTabUrls_CommandLineOption)) {
585 appendFormat_String(cmds, "ipc.list.urls pid:%d\n", pid); 588 appendFormat_String(cmds, "ipc.list.urls pid:%d\n", pid);
586 } 589 }
@@ -658,6 +661,7 @@ static void init_App_(iApp *d, int argc, char **argv) {
658 defineValues_CommandLine(&d->args, listTabUrls_CommandLineOption, 0); 661 defineValues_CommandLine(&d->args, listTabUrls_CommandLineOption, 0);
659 defineValues_CommandLine(&d->args, openUrlOrSearch_CommandLineOption, 1); 662 defineValues_CommandLine(&d->args, openUrlOrSearch_CommandLineOption, 1);
660 defineValuesN_CommandLine(&d->args, "new-tab", 0, 1); 663 defineValuesN_CommandLine(&d->args, "new-tab", 0, 1);
664 defineValues_CommandLine(&d->args, "tab-url", 0);
661 defineValues_CommandLine(&d->args, "sw", 0); 665 defineValues_CommandLine(&d->args, "sw", 0);
662 defineValues_CommandLine(&d->args, "version;V", 0); 666 defineValues_CommandLine(&d->args, "version;V", 0);
663 } 667 }
@@ -2772,6 +2776,12 @@ iBool handleCommand_App(const char *cmd) {
2772 } 2776 }
2773 return iTrue; 2777 return iTrue;
2774 } 2778 }
2779 else if (equal_Command(cmd, "ipc.active.url")) {
2780 write_Ipc(argLabel_Command(cmd, "pid"),
2781 collectNewFormat_String("%s\n", cstr_String(url_DocumentWidget(document_App()))),
2782 response_IpcWrite);
2783 return iTrue;
2784 }
2775 else if (equal_Command(cmd, "ipc.signal")) { 2785 else if (equal_Command(cmd, "ipc.signal")) {
2776 if (argLabel_Command(cmd, "raise")) { 2786 if (argLabel_Command(cmd, "raise")) {
2777 if (d->window && d->window->win) { 2787 if (d->window && d->window->win) {
diff --git a/src/ipc.c b/src/ipc.c
index ce98b6cf..e4c95c50 100644
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -172,6 +172,7 @@ static void handleSignal_IpcResponse_(int sig) {
172} 172}
173 173
174iBool write_Ipc(iProcessId pid, const iString *input, enum iIpcWrite type) { 174iBool write_Ipc(iProcessId pid, const iString *input, enum iIpcWrite type) {
175 if (!pid) return iFalse;
175 iBool ok = iFalse; 176 iBool ok = iFalse;
176 iFile *f = newCStr_File(inputFilePath_(&ipc_, pid)); 177 iFile *f = newCStr_File(inputFilePath_(&ipc_, pid));
177 if (open_File(f, text_FileMode | append_FileMode)) { 178 if (open_File(f, text_FileMode | append_FileMode)) {
@@ -281,6 +282,7 @@ void listen_Ipc(void) {
281} 282}
282 283
283iBool write_Ipc(iProcessId pid, const iString *input, enum iIpcWrite type) { 284iBool write_Ipc(iProcessId pid, const iString *input, enum iIpcWrite type) {
285 if (!pid) return iFalse;
284 iUnused(type); 286 iUnused(type);
285 HANDLE slot = CreateFile(slotName_(pid), 287 HANDLE slot = CreateFile(slotName_(pid),
286 GENERIC_WRITE, 288 GENERIC_WRITE,
diff --git a/src/ui/color.c b/src/ui/color.c
index 05ec1f6f..656de6f0 100644
--- a/src/ui/color.c
+++ b/src/ui/color.c
@@ -85,6 +85,7 @@ void setThemePalette_Color(enum iColorTheme theme) {
85 const int accentLo = (prefs->accent == cyan_ColorAccent ? teal_ColorId : brown_ColorId); 85 const int accentLo = (prefs->accent == cyan_ColorAccent ? teal_ColorId : brown_ColorId);
86 const int altAccentHi = (prefs->accent == cyan_ColorAccent ? orange_ColorId : cyan_ColorId); 86 const int altAccentHi = (prefs->accent == cyan_ColorAccent ? orange_ColorId : cyan_ColorId);
87 const int altAccentLo = (prefs->accent == cyan_ColorAccent ? brown_ColorId : teal_ColorId); 87 const int altAccentLo = (prefs->accent == cyan_ColorAccent ? brown_ColorId : teal_ColorId);
88 const iColor altAccentMid = mix_Color(get_Color(altAccentHi), get_Color(altAccentLo), 0.5f);
88 switch (theme) { 89 switch (theme) {
89 case pureBlack_ColorTheme: { 90 case pureBlack_ColorTheme: {
90 copy_(uiBackground_ColorId, black_ColorId); 91 copy_(uiBackground_ColorId, black_ColorId);
@@ -123,7 +124,7 @@ void setThemePalette_Color(enum iColorTheme theme) {
123 copy_(uiInputTextFocused_ColorId, white_ColorId); 124 copy_(uiInputTextFocused_ColorId, white_ColorId);
124 copy_(uiInputFrame_ColorId, gray25_ColorId); 125 copy_(uiInputFrame_ColorId, gray25_ColorId);
125 copy_(uiInputFrameHover_ColorId, accentHi); 126 copy_(uiInputFrameHover_ColorId, accentHi);
126 copy_(uiInputFrameFocused_ColorId, altAccentHi); 127 set_Color(uiInputFrameFocused_ColorId, altAccentMid);
127 copy_(uiInputCursor_ColorId, altAccentHi); 128 copy_(uiInputCursor_ColorId, altAccentHi);
128 copy_(uiInputCursorText_ColorId, black_ColorId); 129 copy_(uiInputCursorText_ColorId, black_ColorId);
129 copy_(uiHeading_ColorId, accentHi); 130 copy_(uiHeading_ColorId, accentHi);
@@ -171,10 +172,12 @@ void setThemePalette_Color(enum iColorTheme theme) {
171 mix_Color(get_Color(black_ColorId), get_Color(gray25_ColorId), 0.7f)); 172 mix_Color(get_Color(black_ColorId), get_Color(gray25_ColorId), 0.7f));
172 copy_(uiInputBackgroundFocused_ColorId, black_ColorId); 173 copy_(uiInputBackgroundFocused_ColorId, black_ColorId);
173 copy_(uiInputText_ColorId, gray75_ColorId); 174 copy_(uiInputText_ColorId, gray75_ColorId);
174 copy_(uiInputTextFocused_ColorId, white_ColorId); 175 //copy_(uiInputTextFocused_ColorId, white_ColorId);
176 set_Color(uiInputTextFocused_ColorId, mix_Color(get_Color(white_ColorId),
177 get_Color(altAccentHi), 0.15f));
175 copy_(uiInputFrame_ColorId, uiInputBackground_ColorId); 178 copy_(uiInputFrame_ColorId, uiInputBackground_ColorId);
176 copy_(uiInputFrameHover_ColorId, accentHi); 179 copy_(uiInputFrameHover_ColorId, accentHi);
177 copy_(uiInputFrameFocused_ColorId, altAccentHi); 180 set_Color(uiInputFrameFocused_ColorId, altAccentMid);
178 copy_(uiInputCursor_ColorId, altAccentHi); 181 copy_(uiInputCursor_ColorId, altAccentHi);
179 copy_(uiInputCursorText_ColorId, black_ColorId); 182 copy_(uiInputCursorText_ColorId, black_ColorId);
180 copy_(uiHeading_ColorId, accentHi); 183 copy_(uiHeading_ColorId, accentHi);
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 8de1162f..674b0352 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);
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c
index 8ed52022..f1f368b6 100644
--- a/src/ui/inputwidget.c
+++ b/src/ui/inputwidget.c
@@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
39# include "macos.h" 39# include "macos.h"
40#endif 40#endif
41 41
42static const int refreshInterval_InputWidget_ = 256; 42static const int refreshInterval_InputWidget_ = 512;
43static const size_t maxUndo_InputWidget_ = 64; 43static const size_t maxUndo_InputWidget_ = 64;
44static const int unlimitedWidth_InputWidget_ = 1000000; /* TODO: WrapText disables some functionality if maxWidth==0 */ 44static const int unlimitedWidth_InputWidget_ = 1000000; /* TODO: WrapText disables some functionality if maxWidth==0 */
45 45
@@ -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/*----------------------------------------------------------------------------------------------*/
@@ -216,6 +216,7 @@ struct Impl_InputWidget {
216 iArray undoStack; 216 iArray undoStack;
217 int font; 217 int font;
218 iClick click; 218 iClick click;
219 int wheelAccum;
219 int cursorVis; 220 int cursorVis;
220 uint32_t timer; 221 uint32_t timer;
221 iTextBuf * buffered; /* pre-rendered static text */ 222 iTextBuf * buffered; /* pre-rendered static text */
@@ -566,6 +567,28 @@ static void updateAllLinesAndResizeHeight_InputWidget_(iInputWidget *d) {
566 } 567 }
567} 568}
568 569
570static 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
582static 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
569void init_InputWidget(iInputWidget *d, size_t maxLen) { 592void init_InputWidget(iInputWidget *d, size_t maxLen) {
570 iWidget *w = &d->widget; 593 iWidget *w = &d->widget;
571 init_Widget(w); 594 init_Widget(w);
@@ -587,10 +610,11 @@ void init_InputWidget(iInputWidget *d, size_t maxLen) {
587 d->cursor = zero_I2(); 610 d->cursor = zero_I2();
588 d->prevCursor = zero_I2(); 611 d->prevCursor = zero_I2();
589 d->lastUpdateWidth = 0; 612 d->lastUpdateWidth = 0;
590 d->inFlags = eatEscape_InputWidgetFlag | enterKeyEnabled_InputWidgetFlag; 613 d->inFlags = eatEscape_InputWidgetFlag | enterKeyEnabled_InputWidgetFlag |
591 if (deviceType_App() != desktop_AppDeviceType) { 614 lineBreaksEnabled_InputWidgetFlag | useReturnKeyBehavior_InputWidgetFlag;
592 d->inFlags |= enterKeyInsertsLineFeed_InputWidgetFlag; 615 // if (deviceType_App() != desktop_AppDeviceType) {
593 } 616 // d->inFlags |= enterKeyInsertsLineFeed_InputWidgetFlag;
617 // }
594 iZap(d->mark); 618 iZap(d->mark);
595 setMaxLen_InputWidget(d, maxLen); 619 setMaxLen_InputWidget(d, maxLen);
596 d->visWrapLines.start = 0; 620 d->visWrapLines.start = 0;
@@ -600,6 +624,7 @@ void init_InputWidget(iInputWidget *d, size_t maxLen) {
600 splitToLines_(&iStringLiteral(""), &d->lines); 624 splitToLines_(&iStringLiteral(""), &d->lines);
601 setFlags_Widget(w, fixedHeight_WidgetFlag, iTrue); /* resizes its own height */ 625 setFlags_Widget(w, fixedHeight_WidgetFlag, iTrue); /* resizes its own height */
602 init_Click(&d->click, d, SDL_BUTTON_LEFT); 626 init_Click(&d->click, d, SDL_BUTTON_LEFT);
627 d->wheelAccum = 0;
603 d->timer = 0; 628 d->timer = 0;
604 d->cursorVis = 0; 629 d->cursorVis = 0;
605 d->buffered = NULL; 630 d->buffered = NULL;
@@ -625,9 +650,7 @@ void deinit_InputWidget(iInputWidget *d) {
625 delete_TextBuf(d->buffered); 650 delete_TextBuf(d->buffered);
626 clearUndo_InputWidget_(d); 651 clearUndo_InputWidget_(d);
627 deinit_Array(&d->undoStack); 652 deinit_Array(&d->undoStack);
628 if (d->timer) { 653 startOrStopCursorTimer_InputWidget_(d, iFalse);
629 SDL_RemoveTimer(d->timer);
630 }
631 deinit_String(&d->srcHint); 654 deinit_String(&d->srcHint);
632 deinit_String(&d->hint); 655 deinit_String(&d->hint);
633 deinit_String(&d->oldText); 656 deinit_String(&d->oldText);
@@ -730,14 +753,18 @@ void setValidator_InputWidget(iInputWidget *d, iInputWidgetValidatorFunc validat
730 d->validatorContext = context; 753 d->validatorContext = context;
731} 754}
732 755
733void setEnterInsertsLF_InputWidget(iInputWidget *d, iBool enterInsertsLF) { 756void setLineBreaksEnabled_InputWidget(iInputWidget *d, iBool lineBreaksEnabled) {
734 iChangeFlags(d->inFlags, enterKeyInsertsLineFeed_InputWidgetFlag, enterInsertsLF); 757 iChangeFlags(d->inFlags, lineBreaksEnabled_InputWidgetFlag, lineBreaksEnabled);
735} 758}
736 759
737void setEnterKeyEnabled_InputWidget(iInputWidget *d, iBool enterKeyEnabled) { 760void setEnterKeyEnabled_InputWidget(iInputWidget *d, iBool enterKeyEnabled) {
738 iChangeFlags(d->inFlags, enterKeyEnabled_InputWidgetFlag, enterKeyEnabled); 761 iChangeFlags(d->inFlags, enterKeyEnabled_InputWidgetFlag, enterKeyEnabled);
739} 762}
740 763
764void setUseReturnKeyBehavior_InputWidget(iInputWidget *d, iBool useReturnKeyBehavior) {
765 iChangeFlags(d->inFlags, useReturnKeyBehavior_InputWidgetFlag, useReturnKeyBehavior);
766}
767
741void setHint_InputWidget(iInputWidget *d, const char *hintText) { 768void setHint_InputWidget(iInputWidget *d, const char *hintText) {
742 /* Keep original for retranslations. */ 769 /* Keep original for retranslations. */
743 setCStr_String(&d->srcHint, hintText); 770 setCStr_String(&d->srcHint, hintText);
@@ -864,18 +891,6 @@ void setTextCStr_InputWidget(iInputWidget *d, const char *cstr) {
864 delete_String(str); 891 delete_String(str);
865} 892}
866 893
867static uint32_t cursorTimer_(uint32_t interval, void *w) {
868 iInputWidget *d = w;
869 if (d->cursorVis > 1) {
870 d->cursorVis--;
871 }
872 else {
873 d->cursorVis ^= 1;
874 }
875 refresh_Widget(w);
876 return interval;
877}
878
879static size_t cursorToIndex_InputWidget_(const iInputWidget *d, iInt2 pos) { 894static size_t cursorToIndex_InputWidget_(const iInputWidget *d, iInt2 pos) {
880 if (pos.y < 0) { 895 if (pos.y < 0) {
881 return 0; 896 return 0;
@@ -928,7 +943,7 @@ void begin_InputWidget(iInputWidget *d) {
928 setFlags_Widget(w, selected_WidgetFlag, iTrue); 943 setFlags_Widget(w, selected_WidgetFlag, iTrue);
929 showCursor_InputWidget_(d); 944 showCursor_InputWidget_(d);
930 refresh_Widget(w); 945 refresh_Widget(w);
931 d->timer = SDL_AddTimer(refreshInterval_InputWidget_, cursorTimer_, d); 946 startOrStopCursorTimer_InputWidget_(d, iTrue);
932 d->inFlags &= ~enterPressed_InputWidgetFlag; 947 d->inFlags &= ~enterPressed_InputWidgetFlag;
933 if (d->inFlags & selectAllOnFocus_InputWidgetFlag) { 948 if (d->inFlags & selectAllOnFocus_InputWidgetFlag) {
934 d->mark = (iRanges){ 0, lastLine_InputWidget_(d)->range.end }; 949 d->mark = (iRanges){ 0, lastLine_InputWidget_(d)->range.end };
@@ -953,8 +968,7 @@ void end_InputWidget(iInputWidget *d, iBool accept) {
953 splitToLines_(&d->oldText, &d->lines); 968 splitToLines_(&d->oldText, &d->lines);
954 } 969 }
955 d->inFlags |= needUpdateBuffer_InputWidgetFlag; 970 d->inFlags |= needUpdateBuffer_InputWidgetFlag;
956 SDL_RemoveTimer(d->timer); 971 startOrStopCursorTimer_InputWidget_(d, iFalse);
957 d->timer = 0;
958 SDL_StopTextInput(); 972 SDL_StopTextInput();
959 setFlags_Widget(w, selected_WidgetFlag | keepOnTop_WidgetFlag, iFalse); 973 setFlags_Widget(w, selected_WidgetFlag | keepOnTop_WidgetFlag, iFalse);
960 const char *id = cstr_String(id_Widget(as_Widget(d))); 974 const char *id = cstr_String(id_Widget(as_Widget(d)));
@@ -1381,6 +1395,20 @@ static iBool isArrowUpDownConsumed_InputWidget_(const iInputWidget *d) {
1381 return d->maxWrapLines > 1; 1395 return d->maxWrapLines > 1;
1382} 1396}
1383 1397
1398static iBool checkLineBreakMods_InputWidget_(const iInputWidget *d, int mods) {
1399 if (d->inFlags & useReturnKeyBehavior_InputWidgetFlag) {
1400 return mods == lineBreakKeyMod_ReturnKeyBehavior(prefs_App()->returnKey);
1401 }
1402 return mods == 0;
1403}
1404
1405static iBool checkAcceptMods_InputWidget_(const iInputWidget *d, int mods) {
1406 if (d->inFlags & useReturnKeyBehavior_InputWidgetFlag) {
1407 return mods == acceptKeyMod_ReturnKeyBehavior(prefs_App()->returnKey);
1408 }
1409 return mods == 0;
1410}
1411
1384static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { 1412static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
1385 iWidget *w = as_Widget(d); 1413 iWidget *w = as_Widget(d);
1386 /* Resize according to width immediately. */ 1414 /* Resize according to width immediately. */
@@ -1399,6 +1427,13 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
1399 begin_InputWidget(d); 1427 begin_InputWidget(d);
1400 return iFalse; 1428 return iFalse;
1401 } 1429 }
1430 else if (isEditing_InputWidget_(d) && (isCommand_UserEvent(ev, "window.focus.lost") ||
1431 isCommand_UserEvent(ev, "window.focus.gained"))) {
1432 startOrStopCursorTimer_InputWidget_(d, isCommand_UserEvent(ev, "window.focus.gained"));
1433 d->cursorVis = 1;
1434 refresh_Widget(d);
1435 return iFalse;
1436 }
1402 else if (isCommand_UserEvent(ev, "keyroot.changed")) { 1437 else if (isCommand_UserEvent(ev, "keyroot.changed")) {
1403 d->inFlags |= needUpdateBuffer_InputWidgetFlag; 1438 d->inFlags |= needUpdateBuffer_InputWidgetFlag;
1404 } 1439 }
@@ -1467,6 +1502,31 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
1467 ? SDL_SYSTEM_CURSOR_IBEAM 1502 ? SDL_SYSTEM_CURSOR_IBEAM
1468 : SDL_SYSTEM_CURSOR_ARROW); 1503 : SDL_SYSTEM_CURSOR_ARROW);
1469 } 1504 }
1505 if (ev->type == SDL_MOUSEWHEEL && contains_Widget(w, coord_MouseWheelEvent(&ev->wheel))) {
1506 const int lineHeight = lineHeight_Text(d->font);
1507 if (isPerPixel_MouseWheelEvent(&ev->wheel)) {
1508 d->wheelAccum -= ev->wheel.y;
1509 }
1510 else {
1511 d->wheelAccum -= ev->wheel.y * 3 * lineHeight;
1512 }
1513 int lineDelta = d->wheelAccum / lineHeight;
1514 if (lineDelta < 0) {
1515 lineDelta = iMax(lineDelta, -d->visWrapLines.start);
1516 if (!lineDelta) d->wheelAccum = 0;
1517 }
1518 else if (lineDelta > 0) {
1519 lineDelta = iMin(lineDelta,
1520 lastLine_InputWidget_(d)->wrapLines.end - d->visWrapLines.end);
1521 if (!lineDelta) d->wheelAccum = 0;
1522 }
1523 d->wheelAccum -= lineDelta * lineHeight;
1524 d->visWrapLines.start += lineDelta;
1525 d->visWrapLines.end += lineDelta;
1526 d->inFlags |= needUpdateBuffer_InputWidgetFlag;
1527 refresh_Widget(d);
1528 return iTrue;
1529 }
1470 switch (processEvent_Click(&d->click, ev)) { 1530 switch (processEvent_Click(&d->click, ev)) {
1471 case none_ClickResult: 1531 case none_ClickResult:
1472 break; 1532 break;
@@ -1497,6 +1557,7 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
1497 selectAll_InputWidget(d); 1557 selectAll_InputWidget(d);
1498 } 1558 }
1499 } 1559 }
1560 refresh_Widget(d);
1500 return iTrue; 1561 return iTrue;
1501 } 1562 }
1502 case aborted_ClickResult: 1563 case aborted_ClickResult:
@@ -1586,10 +1647,10 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
1586 return iTrue; 1647 return iTrue;
1587 case SDLK_RETURN: 1648 case SDLK_RETURN:
1588 case SDLK_KP_ENTER: 1649 case SDLK_KP_ENTER:
1589 if (~d->inFlags & isSensitive_InputWidgetFlag && d->maxLen == 0) { 1650 if (~d->inFlags & isSensitive_InputWidgetFlag &&
1590 if (mods == lineBreakKeyMod_ReturnKeyBehavior(prefs_App()->returnKey) || 1651 ~d->inFlags & isUrl_InputWidgetFlag &&
1591 (~d->inFlags & isUrl_InputWidgetFlag && 1652 d->inFlags & lineBreaksEnabled_InputWidgetFlag && d->maxLen == 0) {
1592 d->inFlags & enterKeyInsertsLineFeed_InputWidgetFlag)) { 1653 if (checkLineBreakMods_InputWidget_(d, mods)) {
1593 pushUndo_InputWidget_(d); 1654 pushUndo_InputWidget_(d);
1594 deleteMarked_InputWidget_(d); 1655 deleteMarked_InputWidget_(d);
1595 insertChar_InputWidget_(d, '\n'); 1656 insertChar_InputWidget_(d, '\n');
@@ -1598,7 +1659,8 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
1598 } 1659 }
1599 } 1660 }
1600 if (d->inFlags & enterKeyEnabled_InputWidgetFlag && 1661 if (d->inFlags & enterKeyEnabled_InputWidgetFlag &&
1601 mods == acceptKeyMod_ReturnKeyBehavior(prefs_App()->returnKey)) { 1662 (checkAcceptMods_InputWidget_(d, mods) ||
1663 (~d->inFlags & lineBreaksEnabled_InputWidgetFlag))) {
1602 d->inFlags |= enterPressed_InputWidgetFlag; 1664 d->inFlags |= enterPressed_InputWidgetFlag;
1603 setFocus_Widget(NULL); 1665 setFocus_Widget(NULL);
1604 return iTrue; 1666 return iTrue;
@@ -1700,6 +1762,9 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
1700 case SDLK_a: 1762 case SDLK_a:
1701#if defined (iPlatformApple) 1763#if defined (iPlatformApple)
1702 if (mods == KMOD_PRIMARY) { 1764 if (mods == KMOD_PRIMARY) {
1765#else
1766 if (mods == (KMOD_PRIMARY | KMOD_SHIFT)) {
1767#endif
1703 selectAll_InputWidget(d); 1768 selectAll_InputWidget(d);
1704 d->mark.start = 0; 1769 d->mark.start = 0;
1705 d->mark.end = cursorToIndex_InputWidget_(d, curMax); 1770 d->mark.end = cursorToIndex_InputWidget_(d, curMax);
@@ -1708,7 +1773,6 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
1708 refresh_Widget(w); 1773 refresh_Widget(w);
1709 return iTrue; 1774 return iTrue;
1710 } 1775 }
1711#endif
1712 /* fall through for Emacs-style Home/End */ 1776 /* fall through for Emacs-style Home/End */
1713 case SDLK_e: 1777 case SDLK_e:
1714 if (mods == KMOD_CTRL || mods == (KMOD_CTRL | KMOD_SHIFT)) { 1778 if (mods == KMOD_CTRL || mods == (KMOD_CTRL | KMOD_SHIFT)) {
@@ -1889,12 +1953,11 @@ static void draw_InputWidget_(const iInputWidget *d) {
1889 wrapText.wrapFunc = NULL; 1953 wrapText.wrapFunc = NULL;
1890 wrapText.context = NULL; 1954 wrapText.context = NULL;
1891 } 1955 }
1892 unsetClip_Paint(&p);
1893 /* Draw the insertion point. */ 1956 /* Draw the insertion point. */
1894 if (isFocused && d->cursorVis) { 1957 if (isFocused && d->cursorVis && contains_Range(&visLines, d->cursor.y)) {
1895 iInt2 curSize; 1958 iInt2 curSize;
1896 iRangecc cursorChar = iNullRange; 1959 iRangecc cursorChar = iNullRange;
1897 int visWrapsAbove = 0; 1960 int visWrapsAbove = 0;
1898 for (int i = d->cursor.y - 1; i >= visLines.start; i--) { 1961 for (int i = d->cursor.y - 1; i >= visLines.start; i--) {
1899 const iInputLine *line = constAt_Array(&d->lines, i); 1962 const iInputLine *line = constAt_Array(&d->lines, i);
1900 visWrapsAbove += numWrapLines_InputLine_(line); 1963 visWrapsAbove += numWrapLines_InputLine_(line);
@@ -1938,6 +2001,7 @@ static void draw_InputWidget_(const iInputWidget *d) {
1938 cursorChar); 2001 cursorChar);
1939 } 2002 }
1940 } 2003 }
2004 unsetClip_Paint(&p);
1941 drawChildren_Widget(w); 2005 drawChildren_Widget(w);
1942} 2006}
1943 2007
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);
50void setContentPadding_InputWidget (iInputWidget *, int left, int right); /* only affects the text entry */ 50void setContentPadding_InputWidget (iInputWidget *, int left, int right); /* only affects the text entry */
51void setLineLimits_InputWidget (iInputWidget *, int minLines, int maxLines); 51void setLineLimits_InputWidget (iInputWidget *, int minLines, int maxLines);
52void setValidator_InputWidget (iInputWidget *, iInputWidgetValidatorFunc validator, void *context); 52void setValidator_InputWidget (iInputWidget *, iInputWidgetValidatorFunc validator, void *context);
53void setEnterInsertsLF_InputWidget (iInputWidget *, iBool enterInsertsLF); 53void setLineBreaksEnabled_InputWidget(iInputWidget *, iBool lineBreaksEnabled);
54void setEnterKeyEnabled_InputWidget (iInputWidget *, iBool enterKeyEnabled); 54void setEnterKeyEnabled_InputWidget (iInputWidget *, iBool enterKeyEnabled);
55void setUseReturnKeyBehavior_InputWidget(iInputWidget *, iBool useReturnKeyBehavior);
55void setBackupFileName_InputWidget (iInputWidget *, const char *fileName); 56void setBackupFileName_InputWidget (iInputWidget *, const char *fileName);
56void begin_InputWidget (iInputWidget *); 57void begin_InputWidget (iInputWidget *);
57void end_InputWidget (iInputWidget *, iBool accept); 58void 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);