=> 4cf52f29b926a924d838a3158d5c78b3337ee0ee
[1mdiff --git a/po/en.po b/po/en.po[m [1mindex 546a9489..96026528 100644[m [1m--- a/po/en.po[m [1m+++ b/po/en.po[m [36m@@ -273,6 +273,18 @@[m [mmsgstr "Copy"[m msgid "menu.paste"[m msgstr "Paste"[m [m [32m+[m[32m# keep this short (3x1 horiz layout)[m [32m+[m[32mmsgid "menu.selectall"[m [32m+[m[32mmsgstr "Select All"[m [32m+[m [32m+[m[32m# keep this short (3x1 horiz layout)[m [32m+[m[32mmsgid "menu.delete"[m [32m+[m[32mmsgstr "Delete"[m [32m+[m [32m+[m[32m# keep this short (3x1 horiz layout)[m [32m+[m[32mmsgid "menu.undo"[m [32m+[m[32mmsgstr "Undo"[m [32m+[m msgid "menu.select.clear"[m msgstr "Clear Selection"[m [m [1mdiff --git a/res/lang/de.bin b/res/lang/de.bin[m [1mindex ba87d002..f5a6b07e 100644[m Binary files a/res/lang/de.bin and b/res/lang/de.bin differ [1mdiff --git a/res/lang/en.bin b/res/lang/en.bin[m [1mindex a7dfb866..df3c4025 100644[m Binary files a/res/lang/en.bin and b/res/lang/en.bin differ [1mdiff --git a/res/lang/es.bin b/res/lang/es.bin[m [1mindex 7e7398d6..9f5a169f 100644[m Binary files a/res/lang/es.bin and b/res/lang/es.bin differ [1mdiff --git a/res/lang/fi.bin b/res/lang/fi.bin[m [1mindex 607e52fd..ac3b99ef 100644[m Binary files a/res/lang/fi.bin and b/res/lang/fi.bin differ [1mdiff --git a/res/lang/fr.bin b/res/lang/fr.bin[m [1mindex 955695ed..7d40e32c 100644[m Binary files a/res/lang/fr.bin and b/res/lang/fr.bin differ [1mdiff --git a/res/lang/ia.bin b/res/lang/ia.bin[m [1mindex 61a18efc..d10ab85e 100644[m Binary files a/res/lang/ia.bin and b/res/lang/ia.bin differ [1mdiff --git a/res/lang/ie.bin b/res/lang/ie.bin[m [1mindex 06ea7979..14349637 100644[m Binary files a/res/lang/ie.bin and b/res/lang/ie.bin differ [1mdiff --git a/res/lang/pl.bin b/res/lang/pl.bin[m [1mindex 5fc5e24a..9ddd137f 100644[m Binary files a/res/lang/pl.bin and b/res/lang/pl.bin differ [1mdiff --git a/res/lang/ru.bin b/res/lang/ru.bin[m [1mindex 1718f647..366c6ee5 100644[m Binary files a/res/lang/ru.bin and b/res/lang/ru.bin differ [1mdiff --git a/res/lang/sr.bin b/res/lang/sr.bin[m [1mindex 60b7b600..870b0950 100644[m Binary files a/res/lang/sr.bin and b/res/lang/sr.bin differ [1mdiff --git a/res/lang/tok.bin b/res/lang/tok.bin[m [1mindex 3298f0e8..dac5fb33 100644[m Binary files a/res/lang/tok.bin and b/res/lang/tok.bin differ [1mdiff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin[m [1mindex 8c32a0c5..3407c485 100644[m Binary files a/res/lang/zh_Hans.bin and b/res/lang/zh_Hans.bin differ [1mdiff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin[m [1mindex 68f7d3bc..b9001e2d 100644[m Binary files a/res/lang/zh_Hant.bin and b/res/lang/zh_Hant.bin differ [1mdiff --git a/src/app.c b/src/app.c[m [1mindex fa601ac3..37f9c804 100644[m [1m--- a/src/app.c[m [1m+++ b/src/app.c[m [36m@@ -1069,11 +1069,11 @@[m [miLocalDef iBool isWaitingAllowed_App_(iApp *d) {[m return iFalse;[m }[m #endif[m [31m-#if defined (iPlatformMobile)[m [31m- if (!isFinished_Anim(&d->window->rootOffset)) {[m [31m- return iFalse;[m [31m- }[m [31m-#endif[m [32m+[m[32m//#if defined (iPlatformMobile)[m [32m+[m[32m// if (!isFinished_Anim(&d->window->rootOffset)) {[m [32m+[m[32m// return iFalse;[m [32m+[m[32m// }[m [32m+[m[32m//#endif[m return !value_Atomic(&d->pendingRefresh) && isEmpty_SortedArray(&d->tickers);[m }[m [m [36m@@ -1318,7 +1318,7 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m }[m }[m #if defined (LAGRANGE_ENABLE_IDLE_SLEEP)[m [31m- if (d->isIdling && !gotEvents && isFinished_Anim(&d->window->rootOffset)) {[m [32m+[m[32m if (d->isIdling && !gotEvents /*&& isFinished_Anim(&d->window->rootOffset)*/) {[m /* This is where we spend most of our time when idle. 60 Hz still quite a lot but we[m can't wait too long after the user tries to interact again with the app. In any[m case, on macOS SDL_WaitEvent() seems to use 10x more CPU time than sleeping. */[m [36m@@ -1411,9 +1411,9 @@[m [mvoid refresh_App(void) {[m #endif[m if (!exchange_Atomic(&d->pendingRefresh, iFalse)) {[m /* Refreshing wasn't pending. */[m [31m- if (isFinished_Anim(&d->window->rootOffset)) {[m [32m+[m[32m// if (isFinished_Anim(&d->window->rootOffset)) {[m return;[m [31m- }[m [32m+[m[32m// }[m }[m // iTime draw;[m // initCurrent_Time(&draw);[m [1mdiff --git a/src/defs.h b/src/defs.h[m [1mindex 6b12c86c..c3a23596 100644[m [1m--- a/src/defs.h[m [1m+++ b/src/defs.h[m [36m@@ -151,6 +151,8 @@[m [miLocalDef int acceptKeyMod_ReturnKeyBehavior(int behavior) {[m #define magnifyingGlass_Icon "\U0001f50d"[m #define midEllipsis_Icon "\u00b7\u00b7\u00b7"[m #define return_Icon "\u23ce"[m [32m+[m[32m#define undo_Icon "\u23ea"[m [32m+[m[32m#define select_Icon "\u2b1a"[m [m #if defined (iPlatformApple)[m # define shift_Icon "\u21e7"[m [1mdiff --git a/src/ui/color.h b/src/ui/color.h[m [1mindex 37ec49eb..a1d863dc 100644[m [1m--- a/src/ui/color.h[m [1m+++ b/src/ui/color.h[m [36m@@ -183,6 +183,7 @@[m [miLocalDef iBool isRegularText_ColorId(enum iColorId d) {[m #define mask_ColorId 0x7f[m #define permanent_ColorId 0x80 /* cannot be changed via escapes */[m #define fillBackground_ColorId 0x100 /* fill background with same color, but alpha 0 */[m [32m+[m[32m#define opaque_ColorId 0x200[m [m #define asciiBase_ColorEscape 33[m #define asciiExtended_ColorEscape (128 - asciiBase_ColorEscape)[m [1mdiff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c[m [1mindex 4b3c2db0..8ea695d5 100644[m [1m--- a/src/ui/documentwidget.c[m [1m+++ b/src/ui/documentwidget.c[m [36m@@ -4597,23 +4597,6 @@[m [mstatic void drawMedia_DocumentWidget_(const iDocumentWidget *d, iPaint *p) {[m }[m }[m [m [31m-static void drawPin_(iPaint *p, iRect rangeRect, int dir) {[m [31m- const int pinColor = tmQuote_ColorId;[m [31m- const int height = height_Rect(rangeRect);[m [31m- iRect pin;[m [31m- if (dir == 0) {[m [31m- pin = (iRect){ add_I2(topLeft_Rect(rangeRect), init_I2(-gap_UI / 4, -gap_UI)),[m [31m- init_I2(gap_UI / 2, height + gap_UI) };[m [31m- }[m [31m- else {[m [31m- pin = (iRect){ addX_I2(topRight_Rect(rangeRect), -gap_UI / 4),[m [31m- init_I2(gap_UI / 2, height + gap_UI) };[m [31m- }[m [31m- fillRect_Paint(p, pin, pinColor);[m [31m- fillRect_Paint(p, initCentered_Rect(dir == 0 ? topMid_Rect(pin) : bottomMid_Rect(pin),[m [31m- init1_I2(gap_UI * 2)), pinColor);[m [31m-}[m [31m-[m static void extend_GmRunRange_(iGmRunRange *runs) {[m if (runs->start) {[m runs->start--;[m [36m@@ -4857,8 +4840,8 @@[m [mstatic void draw_DocumentWidget_(const iDocumentWidget *d) {[m SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_NONE);[m /* Selection range pins. */[m if (isTouchSelecting) {[m [31m- drawPin_(&ctx.paint, ctx.firstMarkRect, 0);[m [31m- drawPin_(&ctx.paint, ctx.lastMarkRect, 1);[m [32m+[m[32m drawPin_Paint(&ctx.paint, ctx.firstMarkRect, 0, tmQuote_ColorId);[m [32m+[m[32m drawPin_Paint(&ctx.paint, ctx.lastMarkRect, 1, tmQuote_ColorId);[m }[m }[m drawMedia_DocumentWidget_(d, &ctx.paint);[m [1mdiff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c[m [1mindex ad630223..12eb490d 100644[m [1m--- a/src/ui/inputwidget.c[m [1m+++ b/src/ui/inputwidget.c[m [36m@@ -179,19 +179,23 @@[m [mstatic void deinit_InputUndo_(iInputUndo *d) {[m }[m [m enum iInputWidgetFlag {[m [31m- isSensitive_InputWidgetFlag = iBit(1),[m [31m- isUrl_InputWidgetFlag = iBit(2), /* affected by decoding preference */[m [31m- enterPressed_InputWidgetFlag = iBit(3),[m [31m- selectAllOnFocus_InputWidgetFlag = iBit(4),[m [31m- notifyEdits_InputWidgetFlag = iBit(5),[m [31m- eatEscape_InputWidgetFlag = iBit(6),[m [31m- isMarking_InputWidgetFlag = iBit(7),[m [31m- markWords_InputWidgetFlag = iBit(8),[m [31m- needUpdateBuffer_InputWidgetFlag = iBit(9),[m [31m- enterKeyEnabled_InputWidgetFlag = iBit(10),[m [31m- lineBreaksEnabled_InputWidgetFlag= iBit(11),[m [31m- needBackup_InputWidgetFlag = iBit(12),[m [32m+[m[32m isSensitive_InputWidgetFlag = iBit(1),[m [32m+[m[32m isUrl_InputWidgetFlag = iBit(2), /* affected by decoding preference */[m [32m+[m[32m enterPressed_InputWidgetFlag = iBit(3),[m [32m+[m[32m selectAllOnFocus_InputWidgetFlag = iBit(4),[m [32m+[m[32m notifyEdits_InputWidgetFlag = iBit(5),[m [32m+[m[32m eatEscape_InputWidgetFlag = iBit(6),[m [32m+[m[32m isMarking_InputWidgetFlag = iBit(7),[m [32m+[m[32m markWords_InputWidgetFlag = iBit(8),[m [32m+[m[32m needUpdateBuffer_InputWidgetFlag = iBit(9),[m [32m+[m[32m enterKeyEnabled_InputWidgetFlag = iBit(10),[m [32m+[m[32m lineBreaksEnabled_InputWidgetFlag = iBit(11),[m [32m+[m[32m needBackup_InputWidgetFlag = iBit(12),[m useReturnKeyBehavior_InputWidgetFlag = iBit(13),[m [32m+[m[32m //touchBehavior_InputWidgetFlag = iBit(14), /* different behavior depending on interaction method */[m [32m+[m[32m dragCursor_InputWidgetFlag = iBit(14),[m [32m+[m[32m dragMarkerStart_InputWidgetFlag = iBit(15),[m [32m+[m[32m dragMarkerEnd_InputWidgetFlag = iBit(16),[m };[m [m /*----------------------------------------------------------------------------------------------*/[m [36m@@ -217,6 +221,10 @@[m [mstruct Impl_InputWidget {[m iArray undoStack;[m int font;[m iClick click;[m [32m+[m[32m uint32_t tapStartTime;[m [32m+[m[32m uint32_t lastTapTime;[m [32m+[m[32m iInt2 lastTapPos;[m [32m+[m[32m int tapCount;[m int wheelAccum;[m int cursorVis;[m uint32_t timer;[m [36m@@ -460,14 +468,18 @@[m [mstatic iWrapText wrap_InputWidget_(const iInputWidget *d, int y) {[m };[m }[m [m [31m-static iInt2 relativeCursorCoord_InputWidget_(const iInputWidget *d) {[m [32m+[m[32mstatic iInt2 relativeCoord_InputWidget_(const iInputWidget *d, iInt2 pos) {[m /* Relative to the start of the line on which the cursor is. */[m [31m- iWrapText wt = wrap_InputWidget_(d, d->cursor.y);[m [31m- wt.hitChar = wt.text.start + d->cursor.x;[m [32m+[m[32m iWrapText wt = wrap_InputWidget_(d, pos.y);[m [32m+[m[32m wt.hitChar = wt.text.start + pos.x;[m measure_WrapText(&wt, d->font);[m return wt.hitAdvance_out;[m }[m [m [32m+[m[32mstatic iInt2 relativeCursorCoord_InputWidget_(const iInputWidget *d) {[m [32m+[m[32m return relativeCoord_InputWidget_(d, d->cursor);[m [32m+[m[32m}[m [32m+[m static void updateVisible_InputWidget_(iInputWidget *d) {[m const int totalWraps = numWrapLines_InputWidget_(d);[m const int visWraps = iClamp(totalWraps, d->minWrapLines, d->maxWrapLines);[m [36m@@ -632,7 +644,7 @@[m [mvoid init_InputWidget(iInputWidget *d, size_t maxLen) {[m init_Widget(w);[m d->validator = NULL;[m d->validatorContext = NULL;[m [31m- setFlags_Widget(w, focusable_WidgetFlag | hover_WidgetFlag | touchDrag_WidgetFlag, iTrue);[m [32m+[m[32m setFlags_Widget(w, focusable_WidgetFlag | hover_WidgetFlag, iTrue);[m #if defined (iPlatformMobile)[m setFlags_Widget(w, extraPadding_WidgetFlag, iTrue);[m #endif[m [36m@@ -662,6 +674,8 @@[m [mvoid init_InputWidget(iInputWidget *d, size_t maxLen) {[m splitToLines_(&iStringLiteral(""), &d->lines);[m setFlags_Widget(w, fixedHeight_WidgetFlag, iTrue); /* resizes its own height */[m init_Click(&d->click, d, SDL_BUTTON_LEFT);[m [32m+[m[32m d->lastTapTime = 0;[m [32m+[m[32m d->tapCount = 0;[m d->wheelAccum = 0;[m d->timer = 0;[m d->cursorVis = 0;[m [36m@@ -993,7 +1007,7 @@[m [mvoid begin_InputWidget(iInputWidget *d) {[m d->mark = (iRanges){ 0, lastLine_InputWidget_(d)->range.end };[m d->cursor = cursorMax_InputWidget_(d);[m }[m [31m- else {[m [32m+[m[32m else if (~d->inFlags & isMarking_InputWidgetFlag) {[m iZap(d->mark);[m }[m enableEditorKeysInMenus_(iFalse);[m [36m@@ -1013,9 +1027,10 @@[m [mvoid end_InputWidget(iInputWidget *d, iBool accept) {[m splitToLines_(&d->oldText, &d->lines);[m }[m d->inFlags |= needUpdateBuffer_InputWidgetFlag;[m [32m+[m[32m d->inFlags &= ~isMarking_InputWidgetFlag;[m startOrStopCursorTimer_InputWidget_(d, iFalse);[m SDL_StopTextInput();[m [31m- setFlags_Widget(w, selected_WidgetFlag | keepOnTop_WidgetFlag, iFalse);[m [32m+[m[32m setFlags_Widget(w, selected_WidgetFlag | keepOnTop_WidgetFlag | touchDrag_WidgetFlag, iFalse);[m const char *id = cstr_String(id_Widget(as_Widget(d)));[m if (!*id) id = "_";[m refresh_Widget(w);[m [36m@@ -1445,88 +1460,31 @@[m [mstatic iBool checkAcceptMods_InputWidget_(const iInputWidget *d, int mods) {[m return mods == 0;[m }[m [m [31m-static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {[m [31m- iWidget *w = as_Widget(d);[m [31m- /* Resize according to width immediately. */[m [31m- if (d->lastUpdateWidth != w->rect.size.x) {[m [31m- d->inFlags |= needUpdateBuffer_InputWidgetFlag;[m [31m- if (d->inFlags & isUrl_InputWidgetFlag) {[m [31m- /* Restore/omit the default scheme if necessary. */[m [31m- setText_InputWidget(d, text_InputWidget(d));[m [31m- }[m [31m- updateAllLinesAndResizeHeight_InputWidget_(d);[m [31m- d->lastUpdateWidth = w->rect.size.x;[m [31m- }[m [31m- if (isCommand_Widget(w, ev, "focus.gained")) {[m [31m- begin_InputWidget(d);[m [31m- return iFalse;[m [31m- }[m [31m- else if (isEditing_InputWidget_(d) && (isCommand_UserEvent(ev, "window.focus.lost") ||[m [31m- isCommand_UserEvent(ev, "window.focus.gained"))) {[m [31m- startOrStopCursorTimer_InputWidget_(d, isCommand_UserEvent(ev, "window.focus.gained"));[m [31m- d->cursorVis = 1;[m [31m- refresh_Widget(d);[m [31m- return iFalse;[m [31m- }[m [31m- else if (isCommand_UserEvent(ev, "keyroot.changed")) {[m [31m- d->inFlags |= needUpdateBuffer_InputWidgetFlag;[m [31m- }[m [31m- else if (isCommand_UserEvent(ev, "lang.changed")) {[m [31m- set_String(&d->hint, &d->srcHint);[m [31m- translate_Lang(&d->hint);[m [31m- return iFalse;[m [31m- }[m [31m- else if (isCommand_Widget(w, ev, "focus.lost")) {[m [31m- end_InputWidget(d, iTrue);[m [31m- return iFalse;[m [31m- }[m [31m- else if ((isCommand_UserEvent(ev, "copy") || isCommand_UserEvent(ev, "input.copy")) &&[m [31m- isEditing_InputWidget_(d)) {[m [31m- copy_InputWidget_(d, argLabel_Command(command_UserEvent(ev), "cut"));[m [31m- return iTrue;[m [31m- }[m [31m- else if (isCommand_UserEvent(ev, "input.paste") && isEditing_InputWidget_(d)) {[m [31m- paste_InputWidget_(d);[m [31m- return iTrue;[m [31m- }[m [31m- else if (isCommand_UserEvent(ev, "theme.changed")) {[m [31m- if (d->buffered) {[m [31m- d->inFlags |= needUpdateBuffer_InputWidgetFlag;[m [31m- }[m [31m- return iFalse;[m [31m- }[m [31m- else if (isCommand_UserEvent(ev, "keyboard.changed")) {[m [31m- if (isFocused_Widget(d) && arg_Command(command_UserEvent(ev))) {[m [31m- iRect rect = bounds_Widget(w);[m [31m- rect.pos.y -= value_Anim(&get_Window()->rootOffset);[m [31m- const iInt2 visRoot = visibleSize_Root(w->root);[m [31m- if (bottom_Rect(rect) > visRoot.y) {[m [31m- setValue_Anim(&get_Window()->rootOffset, -(bottom_Rect(rect) - visRoot.y), 250);[m [31m- }[m [31m- }[m [31m- return iFalse;[m [31m- }[m [31m- else if (isCommand_UserEvent(ev, "text.insert")) {[m [31m- pushUndo_InputWidget_(d);[m [31m- deleteMarked_InputWidget_(d);[m [31m- insertChar_InputWidget_(d, arg_Command(command_UserEvent(ev)));[m [31m- contentsWereChanged_InputWidget_(d);[m [31m- return iTrue;[m [31m- }[m [31m- else if (isCommand_Widget(w, ev, "input.backup")) {[m [31m- if (d->inFlags & needBackup_InputWidgetFlag) {[m [31m- saveBackup_InputWidget_(d);[m [31m- }[m [31m- return iTrue;[m [31m- }[m [31m- else if (isMetricsChange_UserEvent(ev)) {[m [31m- updateMetrics_InputWidget_(d);[m [31m- // updateLinesAndResize_InputWidget_(d);[m [32m+[m[32menum iEventResult {[m [32m+[m[32m ignored_EventResult = 0, /* event was not processed */[m [32m+[m[32m false_EventResult = 1, /* event was processed but other widgets can still process it, too*/[m [32m+[m[32m true_EventResult = 2, /* event was processed and should not be passed on */[m [32m+[m[32m};[m [32m+[m [32m+[m[32mstatic void markWordAtCursor_InputWidget_(iInputWidget *d) {[m [32m+[m[32m d->mark.start = d->mark.end = cursorToIndex_InputWidget_(d, d->cursor);[m [32m+[m[32m extendRange_InputWidget_(d, &d->mark.start, -1);[m [32m+[m[32m extendRange_InputWidget_(d, &d->mark.end, +1);[m [32m+[m[32m d->initialMark = d->mark;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic void showClipMenu_(iInt2 coord) {[m [32m+[m[32m iWidget *clipMenu = findWidget_App("clipmenu");[m [32m+[m[32m if (isVisible_Widget(clipMenu)) {[m [32m+[m[32m closeMenu_Widget(clipMenu);[m }[m [31m- else if (isFocused_Widget(d) && isCommand_UserEvent(ev, "copy")) {[m [31m- copy_InputWidget_(d, iFalse);[m [31m- return iTrue;[m [32m+[m[32m else {[m [32m+[m[32m openMenuFlags_Widget(clipMenu, coord, iFalse);[m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic enum iEventResult processPointerEvents_InputWidget_(iInputWidget *d, const SDL_Event *ev) {[m [32m+[m[32m iWidget *w = as_Widget(d);[m if (ev->type == SDL_MOUSEMOTION && (isHover_Widget(d) || flags_Widget(w) & keepOnTop_WidgetFlag)) {[m const iInt2 coord = init_I2(ev->motion.x, ev->motion.y);[m const iInt2 inner = windowToInner_Widget(w, coord);[m [36m@@ -1559,10 +1517,15 @@[m [mstatic iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {[m d->visWrapLines.start += lineDelta;[m d->visWrapLines.end += lineDelta;[m d->inFlags |= needUpdateBuffer_InputWidgetFlag;[m [31m- refresh_Widget(d); [m [31m- return iTrue;[m [32m+[m[32m refresh_Widget(d);[m [32m+[m[32m return true_EventResult;[m }[m [31m- return iFalse;[m [32m+[m[32m return false_EventResult;[m [32m+[m[32m }[m [32m+[m[32m if (ev->type == SDL_MOUSEBUTTONDOWN && ev->button.button == SDL_BUTTON_RIGHT &&[m [32m+[m[32m contains_Widget(w, init_I2(ev->button.x, ev->button.y))) {[m [32m+[m[32m showClipMenu_(mouseCoord_Window(get_Window(), ev->button.which));[m [32m+[m[32m return iTrue;[m }[m switch (processEvent_Click(&d->click, ev)) {[m case none_ClickResult:[m [36m@@ -1584,10 +1547,7 @@[m [mstatic iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {[m d->inFlags &= ~(isMarking_InputWidgetFlag | markWords_InputWidgetFlag);[m if (d->click.count == 2) {[m d->inFlags |= isMarking_InputWidgetFlag | markWords_InputWidgetFlag;[m [31m- d->mark.start = d->mark.end = cursorToIndex_InputWidget_(d, d->cursor);[m [31m- extendRange_InputWidget_(d, &d->mark.start, -1);[m [31m- extendRange_InputWidget_(d, &d->mark.end, +1);[m [31m- d->initialMark = d->mark;[m [32m+[m[32m markWordAtCursor_InputWidget_(d);[m refresh_Widget(w);[m }[m if (d->click.count == 3) {[m [36m@@ -1595,11 +1555,11 @@[m [mstatic iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {[m }[m }[m refresh_Widget(d);[m [31m- return iTrue;[m [32m+[m[32m return true_EventResult;[m }[m case aborted_ClickResult:[m d->inFlags &= ~isMarking_InputWidgetFlag;[m [31m- return iTrue;[m [32m+[m[32m return true_EventResult;[m case drag_ClickResult:[m d->cursor = coordCursor_InputWidget_(d, pos_Click(&d->click));[m showCursor_InputWidget_(d);[m [36m@@ -1614,30 +1574,374 @@[m [mstatic iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {[m d->mark.start = isFwd ? d->initialMark.start : d->initialMark.end;[m }[m refresh_Widget(w);[m [31m- return iTrue;[m [32m+[m[32m return true_EventResult;[m case finished_ClickResult:[m d->inFlags &= ~isMarking_InputWidgetFlag;[m [31m- return iTrue;[m [32m+[m[32m return true_EventResult;[m }[m if (ev->type == SDL_MOUSEMOTION && flags_Widget(w) & keepOnTop_WidgetFlag) {[m const iInt2 coord = init_I2(ev->motion.x, ev->motion.y);[m if (contains_Click(&d->click, coord)) {[m [31m- return iTrue;[m [32m+[m[32m return true_EventResult;[m }[m }[m [31m- if (ev->type == SDL_MOUSEBUTTONDOWN && ev->button.button == SDL_BUTTON_RIGHT &&[m [31m- contains_Widget(w, init_I2(ev->button.x, ev->button.y))) {[m [31m- iWidget *clipMenu = findWidget_App("clipmenu");[m [31m- if (isVisible_Widget(clipMenu)) {[m [31m- closeMenu_Widget(clipMenu);[m [32m+[m[32m return ignored_EventResult;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic iInt2 touchCoordCursor_InputWidget_(const iInputWidget *d, iInt2 coord) {[m [32m+[m[32m /* Clamp to the bounds so the cursor doesn't wrap at the ends. */[m [32m+[m[32m iRect bounds = shrunk_Rect(contentBounds_InputWidget_(d), one_I2());[m [32m+[m[32m bounds.size.y = iMini(numWrapLines_InputWidget_(d), d->maxWrapLines) * lineHeight_Text(d->font) - 2;[m [32m+[m[32m return coordCursor_InputWidget_(d, min_I2(bottomRight_Rect(bounds),[m [32m+[m[32m max_I2(coord, topLeft_Rect(bounds))));[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic iBool isInsideMark_InputWidget_(const iInputWidget *d, size_t pos) {[m [32m+[m[32m const iRanges mark = mark_InputWidget_(d);[m [32m+[m[32m return contains_Range(&mark, pos);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic int distanceToPos_InputWidget_(const iInputWidget *d, iInt2 uiCoord, iInt2 textPos) {[m [32m+[m[32m const iInt2 a = addY_I2(relativeCoord_InputWidget_(d, textPos), lineHeight_Text(d->font) / 2);[m [32m+[m[32m const iInt2 b = sub_I2(uiCoord, topLeft_Rect(contentBounds_InputWidget_(d)));[m [32m+[m[32m return dist_I2(a, b);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic enum iEventResult processTouchEvents_InputWidget_(iInputWidget *d, const SDL_Event *ev) {[m [32m+[m[32m iWidget *w = as_Widget(d);[m [32m+[m[32m /*[m [32m+[m[32m + first tap to focus & select all/place cursor[m [32m+[m[32m + focused tap to place cursor[m [32m+[m[32m - drag cursor to move it[m [32m+[m[32m - double-click to select a word[m [32m+[m[32m - drag to move selection handles[m [32m+[m[32m - long-press for context menu: copy, paste, delete, select all, deselect[m [32m+[m[32m - double-click and hold to select words[m [32m+[m[32m - triple-click to select all[m [32m+[m[32m - drag/wheel elsewhere to scroll (contents or overflow), no change in focus[m [32m+[m[32m */[m [32m+[m[32m// if (ev->type != SDL_MOUSEBUTTONUP && ev->type != SDL_MOUSEBUTTONDOWN &&[m [32m+[m[32m// ev->type != SDL_MOUSEWHEEL && ev->type != SDL_MOUSEMOTION &&[m [32m+[m[32m// !(ev->type == SDL_USEREVENT && ev->user.code == widgetTapBegins_UserEventCode) &&[m [32m+[m[32m// !(ev->type == SDL_USEREVENT && ev->user.code == widgetTouchEnds_UserEventCode)) {[m [32m+[m[32m// return ignored_EventResult;[m [32m+[m[32m// }[m [32m+[m[32m if (isFocused_Widget(w)) {[m [32m+[m[32m if (ev->type == SDL_USEREVENT && ev->user.code == widgetTapBegins_UserEventCode) {[m [32m+[m[32m d->lastTapTime = d->tapStartTime;[m [32m+[m[32m d->tapStartTime = SDL_GetTicks();[m [32m+[m[32m const int tapDist = dist_I2(latestPosition_Touch(), d->lastTapPos);[m [32m+[m[32m d->lastTapPos = latestPosition_Touch();[m [32m+[m[32m printf("[%p] tap start time: %u (%u) %d\n", w, d->tapStartTime, d->tapStartTime - d->lastTapTime, tapDist);[m [32m+[m[32m if (d->tapStartTime - d->lastTapTime < 400 && tapDist < gap_UI * 4) {[m [32m+[m[32m d->tapCount++;[m [32m+[m[32m printf("[%p] >> tap count: %d\n", w, d->tapCount);[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m d->tapCount = 0;[m [32m+[m[32m }[m [32m+[m[32m if (!isEmpty_Range(&d->mark)) {[m [32m+[m[32m const int dist[2] = {[m [32m+[m[32m distanceToPos_InputWidget_(d, latestPosition_Touch(),[m [32m+[m[32m indexToCursor_InputWidget_(d, d->mark.start)),[m [32m+[m[32m distanceToPos_InputWidget_(d, latestPosition_Touch(),[m [32m+[m[32m indexToCursor_InputWidget_(d, d->mark.end))[m [32m+[m[32m };[m [32m+[m[32m if (dist[0] < dist[1]) {[m [32m+[m[32m printf("[%p] begin marker start drag\n", w);[m [32m+[m[32m d->inFlags |= dragMarkerStart_InputWidgetFlag;[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m printf("[%p] begin marker end drag\n", w);[m [32m+[m[32m d->inFlags |= dragMarkerEnd_InputWidgetFlag;[m [32m+[m[32m }[m [32m+[m[32m d->inFlags |= isMarking_InputWidgetFlag;[m [32m+[m[32m setFlags_Widget(w, touchDrag_WidgetFlag, iTrue);[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m const int dist = distanceToPos_InputWidget_(d, latestPosition_Touch(), d->cursor);[m [32m+[m[32m printf("[%p] tap dist: %d\n", w, dist);[m [32m+[m[32m if (dist < gap_UI * 10) {[m [32m+[m[32m printf("[%p] begin cursor drag\n", w);[m [32m+[m[32m setFlags_Widget(w, touchDrag_WidgetFlag, iTrue);[m [32m+[m[32m d->inFlags |= dragCursor_InputWidgetFlag;[m [32m+[m[32m// d->inFlags |= touchBehavior_InputWidgetFlag;[m [32m+[m[32m// setMouseGrab_Widget(w);[m [32m+[m[32m// return iTrue;[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m// if (~d->inFlags & selectAllOnFocus_InputWidgetFlag) {[m [32m+[m[32m// d->cursor = coordCursor_InputWidget_(d, pos_Click(&d->click));[m [32m+[m[32m// showCursor_InputWidget_(d);[m [32m+[m[32m// }[m [32m+[m[32m return true_EventResult;[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m#if 0[m [32m+[m[32m else if (isFocused_Widget(w)) {[m [32m+[m[32m if (ev->type == SDL_MOUSEMOTION) {[m [32m+[m[32m if (~d->inFlags & touchBehavior_InputWidgetFlag) {[m [32m+[m[32m const iInt2 curPos = relativeCursorCoord_InputWidget_(d);[m [32m+[m[32m const iInt2 relClick = sub_I2(pos_Click(&d->click),[m [32m+[m[32m topLeft_Rect(contentBounds_InputWidget_(d)));[m [32m+[m[32m if (dist_I2(curPos, relClick) < gap_UI * 8) {[m [32m+[m[32m printf("tap on cursor!\n");[m [32m+[m[32m setFlags_Widget(w, touchDrag_WidgetFlag, iTrue);[m [32m+[m[32m d->inFlags |= touchBehavior_InputWidgetFlag;[m [32m+[m[32m printf("[Input] begin cursor drag\n");[m [32m+[m[32m setMouseGrab_Widget(w);[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m else if (ev->motion.x > 0 && ev->motion.y > 0) {[m [32m+[m[32m printf("[Input] cursor being dragged\n");[m [32m+[m[32m iRect bounds = shrunk_Rect(contentBounds_InputWidget_(d), one_I2());[m [32m+[m[32m bounds.size.y = iMini(numWrapLines_InputWidget_(d), d->maxWrapLines) * lineHeight_Text(d->font) - 2;[m [32m+[m[32m iInt2 mpos = init_I2(ev->motion.x, ev->motion.y);[m [32m+[m[32m mpos = min_I2(bottomRight_Rect(bounds), max_I2(mpos, topLeft_Rect(bounds)));[m [32m+[m[32m d->cursor = coordCursor_InputWidget_(d, mpos);[m [32m+[m[32m showCursor_InputWidget_(d);[m [32m+[m[32m refresh_Widget(w);[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m }[m [31m- else {[m [31m- openMenuFlags_Widget(clipMenu,[m [31m- mouseCoord_Window(get_Window(), ev->button.which),[m [31m- iFalse);[m [32m+[m[32m if (d->inFlags & touchBehavior_InputWidgetFlag) {[m [32m+[m[32m if (ev->type == SDL_MOUSEBUTTONUP ||[m [32m+[m[32m (ev->type == SDL_USEREVENT && ev->user.code == widgetTouchEnds_UserEventCode)) {[m [32m+[m[32m d->inFlags &= ~touchBehavior_InputWidgetFlag;[m [32m+[m[32m setFlags_Widget(w, touchDrag_WidgetFlag, iFalse);[m [32m+[m[32m setMouseGrab_Widget(NULL);[m [32m+[m[32m printf("[Input] touch ends\n");[m [32m+[m[32m return iFalse;[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m#endif[m [32m+[m[32m#if 1[m [32m+[m[32m if ((ev->type == SDL_MOUSEBUTTONDOWN || ev->type == SDL_MOUSEBUTTONUP) &&[m [32m+[m[32m ev->button.button == SDL_BUTTON_RIGHT && contains_Widget(w, latestPosition_Touch())) {[m [32m+[m[32m if (ev->type == SDL_MOUSEBUTTONDOWN) {[m [32m+[m[32m /*if (isFocused_Widget(w)) {[m [32m+[m[32m d->inFlags |= isMarking_InputWidgetFlag;[m [32m+[m[32m d->cursor = touchCoordCursor_InputWidget_(d, latestPosition_Touch());[m [32m+[m[32m markWordAtCursor_InputWidget_(d);[m [32m+[m[32m refresh_Widget(d);[m [32m+[m[32m return true_EventResult;[m [32m+[m[32m }*/[m [32m+[m[32m setFocus_Widget(w);[m [32m+[m[32m d->inFlags |= isMarking_InputWidgetFlag;[m [32m+[m[32m d->cursor = touchCoordCursor_InputWidget_(d, latestPosition_Touch());[m [32m+[m[32m markWordAtCursor_InputWidget_(d);[m [32m+[m[32m d->cursor = indexToCursor_InputWidget_(d, d->mark.end);[m [32m+[m[32m refresh_Widget(d);[m [32m+[m[32m }[m [32m+[m[32m return true_EventResult;[m [32m+[m[32m }[m [32m+[m[32m switch (processEvent_Click(&d->click, ev)) {[m [32m+[m[32m case none_ClickResult:[m [32m+[m[32m break;[m [32m+[m[32m case started_ClickResult: {[m [32m+[m[32m printf("[%p] started\n", w);[m [32m+[m[32m /*[m [32m+[m[32m const iInt2 curPos = relativeCursorCoord_InputWidget_(d);[m [32m+[m[32m const iInt2 relClick = sub_I2(pos_Click(&d->click),[m [32m+[m[32m topLeft_Rect(contentBounds_InputWidget_(d)));[m [32m+[m[32m if (dist_I2(curPos, relClick) < gap_UI * 8) {[m [32m+[m[32m printf("tap on cursor!\n");[m [32m+[m[32m setFlags_Widget(w, touchDrag_WidgetFlag, iTrue);[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m printf("tap elsewhere\n");[m [32m+[m[32m }*/[m [32m+[m[32m return true_EventResult;[m [32m+[m[32m }[m [32m+[m[32m case drag_ClickResult:[m [32m+[m[32m printf("[%p] drag %d,%d\n", w, pos_Click(&d->click).x, pos_Click(&d->click).y);[m [32m+[m[32m if (d->inFlags & dragCursor_InputWidgetFlag) {[m [32m+[m[32m iZap(d->mark);[m [32m+[m[32m d->cursor = touchCoordCursor_InputWidget_(d, pos_Click(&d->click));[m [32m+[m[32m showCursor_InputWidget_(d);[m [32m+[m[32m refresh_Widget(w);[m [32m+[m[32m }[m [32m+[m[32m else if (d->inFlags & dragMarkerStart_InputWidgetFlag) {[m [32m+[m[32m d->mark.start = cursorToIndex_InputWidget_(d, touchCoordCursor_InputWidget_(d, pos_Click(&d->click)));[m [32m+[m[32m refresh_Widget(w);[m [32m+[m[32m }[m [32m+[m[32m else if (d->inFlags & dragMarkerEnd_InputWidgetFlag) {[m [32m+[m[32m d->mark.end = cursorToIndex_InputWidget_(d, touchCoordCursor_InputWidget_(d, pos_Click(&d->click)));[m [32m+[m[32m refresh_Widget(w);[m [32m+[m[32m }[m [32m+[m[32m return true_EventResult;[m [32m+[m[32m // printf("[%p] aborted\n", w);[m [32m+[m[32m// d->inFlags &= ~touchBehavior_InputWidgetFlag;[m [32m+[m[32m// setFlags_Widget(w, touchDrag_WidgetFlag, iFalse);[m [32m+[m[32m// return true_EventResult;[m [32m+[m[32m case finished_ClickResult:[m [32m+[m[32m case aborted_ClickResult:[m [32m+[m[32m printf("[%p] ended\n", w);[m [32m+[m[32m uint32_t tapElapsed = SDL_GetTicks() - d->tapStartTime;[m [32m+[m[32m printf("tapElapsed: %u\n", tapElapsed);[m [32m+[m[32m if (!isFocused_Widget(w)) {[m [32m+[m[32m setFocus_Widget(w);[m [32m+[m[32m d->lastTapPos = latestPosition_Touch();[m [32m+[m[32m d->tapStartTime = SDL_GetTicks();[m [32m+[m[32m d->tapCount = 0;[m [32m+[m[32m d->cursor = touchCoordCursor_InputWidget_(d, pos_Click(&d->click));[m [32m+[m[32m showCursor_InputWidget_(d);[m [32m+[m[32m }[m [32m+[m[32m else if (!isEmpty_Range(&d->mark) && !isMoved_Click(&d->click)) {[m [32m+[m[32m if (isInsideMark_InputWidget_(d, cursorToIndex_InputWidget_(d, touchCoordCursor_InputWidget_(d, latestPosition_Touch())))) {[m [32m+[m[32m showClipMenu_(latestPosition_Touch());[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m iZap(d->mark);[m [32m+[m[32m d->cursor = touchCoordCursor_InputWidget_(d, pos_Click(&d->click));[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m else if (SDL_GetTicks() - d->lastTapTime > 1000 &&[m [32m+[m[32m d->tapCount == 0 && isEmpty_Range(&d->mark) && !isMoved_Click(&d->click) &&[m [32m+[m[32m distanceToPos_InputWidget_(d, latestPosition_Touch(), d->cursor) < gap_UI * 5) {[m [32m+[m[32m showClipMenu_(latestPosition_Touch());[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m if (~d->inFlags & isMarking_InputWidgetFlag) {[m [32m+[m[32m iZap(d->mark);[m [32m+[m[32m d->cursor = touchCoordCursor_InputWidget_(d, pos_Click(&d->click));[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m if (d->inFlags & (dragCursor_InputWidgetFlag | dragMarkerStart_InputWidgetFlag |[m [32m+[m[32m dragMarkerEnd_InputWidgetFlag)) {[m [32m+[m[32m printf("[%p] finished cursor/marker drag\n", w);[m [32m+[m[32m d->inFlags &= ~(dragCursor_InputWidgetFlag |[m [32m+[m[32m dragMarkerStart_InputWidgetFlag |[m [32m+[m[32m dragMarkerEnd_InputWidgetFlag);[m [32m+[m[32m setFlags_Widget(w, touchDrag_WidgetFlag, iFalse);[m [32m+[m[32m }[m [32m+[m[32m d->inFlags &= ~isMarking_InputWidgetFlag;[m [32m+[m[32m showCursor_InputWidget_(d);[m [32m+[m[32m refresh_Widget(w);[m [32m+[m[32m#if 0[m [32m+[m[32m d->inFlags &= ~touchBehavior_InputWidgetFlag;[m [32m+[m[32m if (flags_Widget(w) & touchDrag_WidgetFlag) {[m [32m+[m[32m setFlags_Widget(w, touchDrag_WidgetFlag, iFalse);[m [32m+[m[32m return true_EventResult;[m [32m+[m[32m }[m [32m+[m[32m if (!isMoved_Click(&d->click)) {[m [32m+[m[32m if (!isFocused_Widget(w)) {[m [32m+[m[32m setFocus_Widget(w);[m [32m+[m[32m if (~d->inFlags & selectAllOnFocus_InputWidgetFlag) {[m [32m+[m[32m d->cursor = coordCursor_InputWidget_(d, pos_Click(&d->click));[m [32m+[m[32m showCursor_InputWidget_(d);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m iZap(d->mark);[m [32m+[m[32m d->cursor = coordCursor_InputWidget_(d, pos_Click(&d->click));[m [32m+[m[32m showCursor_InputWidget_(d);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m#endif[m [32m+[m[32m return true_EventResult;[m [32m+[m[32m }[m [32m+[m[32m#endif[m [32m+[m[32m// if ((ev->type == SDL_MOUSEBUTTONDOWN || ev->type == SDL_MOUSEBUTTONUP) &&[m [32m+[m[32m// contains_Widget(w, init_I2(ev->button.x, ev->button.y))) {[m [32m+[m[32m// /* Eat all mouse clicks on the widget. */[m [32m+[m[32m// return true_EventResult;[m [32m+[m[32m// }[m [32m+[m[32m return ignored_EventResult;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {[m [32m+[m[32m iWidget *w = as_Widget(d);[m [32m+[m[32m /* Resize according to width immediately. */[m [32m+[m[32m if (d->lastUpdateWidth != w->rect.size.x) {[m [32m+[m[32m d->inFlags |= needUpdateBuffer_InputWidgetFlag;[m [32m+[m[32m if (d->inFlags & isUrl_InputWidgetFlag) {[m [32m+[m[32m /* Restore/omit the default scheme if necessary. */[m [32m+[m[32m setText_InputWidget(d, text_InputWidget(d));[m }[m [32m+[m[32m updateAllLinesAndResizeHeight_InputWidget_(d);[m [32m+[m[32m d->lastUpdateWidth = w->rect.size.x;[m [32m+[m[32m }[m [32m+[m[32m if (isCommand_Widget(w, ev, "focus.gained")) {[m [32m+[m[32m begin_InputWidget(d);[m [32m+[m[32m return iFalse;[m [32m+[m[32m }[m [32m+[m[32m else if (isEditing_InputWidget_(d) && (isCommand_UserEvent(ev, "window.focus.lost") ||[m [32m+[m[32m isCommand_UserEvent(ev, "window.focus.gained"))) {[m [32m+[m[32m startOrStopCursorTimer_InputWidget_(d, isCommand_UserEvent(ev, "window.focus.gained"));[m [32m+[m[32m d->cursorVis = 1;[m [32m+[m[32m refresh_Widget(d);[m [32m+[m[32m return iFalse;[m [32m+[m[32m }[m [32m+[m[32m else if (isCommand_UserEvent(ev, "keyroot.changed")) {[m [32m+[m[32m d->inFlags |= needUpdateBuffer_InputWidgetFlag;[m [32m+[m[32m }[m [32m+[m[32m else if (isCommand_UserEvent(ev, "lang.changed")) {[m [32m+[m[32m set_String(&d->hint, &d->srcHint);[m [32m+[m[32m translate_Lang(&d->hint);[m [32m+[m[32m return iFalse;[m [32m+[m[32m }[m [32m+[m[32m else if (isCommand_Widget(w, ev, "focus.lost")) {[m [32m+[m[32m end_InputWidget(d, iTrue);[m [32m+[m[32m return iFalse;[m [32m+[m[32m }[m [32m+[m[32m else if ((isCommand_UserEvent(ev, "copy") || isCommand_UserEvent(ev, "input.copy")) &&[m [32m+[m[32m isEditing_InputWidget_(d)) {[m [32m+[m[32m copy_InputWidget_(d, argLabel_Command(command_UserEvent(ev), "cut"));[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m [32m+[m[32m else if (isCommand_UserEvent(ev, "input.paste") && isEditing_InputWidget_(d)) {[m [32m+[m[32m paste_InputWidget_(d);[m return iTrue;[m }[m [32m+[m[32m else if (isCommand_UserEvent(ev, "theme.changed")) {[m [32m+[m[32m if (d->buffered) {[m [32m+[m[32m d->inFlags |= needUpdateBuffer_InputWidgetFlag;[m [32m+[m[32m }[m [32m+[m[32m return iFalse;[m [32m+[m[32m }[m [32m+[m[32m// else if (isCommand_UserEvent(ev, "keyboard.changed")) {[m [32m+[m[32m// if (isFocused_Widget(d) && arg_Command(command_UserEvent(ev))) {[m [32m+[m[32m// iRect rect = bounds_Widget(w);[m [32m+[m[32m// rect.pos.y -= value_Anim(&get_Window()->rootOffset);[m [32m+[m[32m// const iInt2 visRoot = visibleSize_Root(w->root);[m [32m+[m[32m// if (bottom_Rect(rect) > visRoot.y) {[m [32m+[m[32m// setValue_Anim(&get_Window()->rootOffset, -(bottom_Rect(rect) - visRoot.y), 250);[m [32m+[m[32m// }[m [32m+[m[32m// }[m [32m+[m[32m// return iFalse;[m [32m+[m[32m// }[m [32m+[m[32m else if (isCommand_UserEvent(ev, "text.insert")) {[m [32m+[m[32m pushUndo_InputWidget_(d);[m [32m+[m[32m deleteMarked_InputWidget_(d);[m [32m+[m[32m insertChar_InputWidget_(d, arg_Command(command_UserEvent(ev)));[m [32m+[m[32m contentsWereChanged_InputWidget_(d);[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m [32m+[m[32m else if (isCommand_Widget(w, ev, "input.backup")) {[m [32m+[m[32m if (d->inFlags & needBackup_InputWidgetFlag) {[m [32m+[m[32m saveBackup_InputWidget_(d);[m [32m+[m[32m }[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m [32m+[m[32m else if (isMetricsChange_UserEvent(ev)) {[m [32m+[m[32m updateMetrics_InputWidget_(d);[m [32m+[m[32m // updateLinesAndResize_InputWidget_(d);[m [32m+[m[32m }[m [32m+[m[32m else if (isFocused_Widget(d) && isCommand_UserEvent(ev, "copy")) {[m [32m+[m[32m copy_InputWidget_(d, iFalse);[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m [32m+[m[32m /* Click behavior depends on device type. */ {[m [32m+[m[32m const int mbResult = (deviceType_App() == desktop_AppDeviceType[m [32m+[m[32m ? processPointerEvents_InputWidget_(d, ev)[m [32m+[m[32m : processTouchEvents_InputWidget_(d, ev));[m [32m+[m[32m if (mbResult) {[m [32m+[m[32m return mbResult >> 1;[m [32m+[m[32m }[m [32m+[m[32m }[m if (ev->type == SDL_KEYUP && isFocused_Widget(w)) {[m return iTrue;[m }[m [36m@@ -1884,6 +2188,8 @@[m [mstruct Impl_MarkPainter {[m const iInputLine * line;[m iInt2 pos;[m iRanges mark;[m [32m+[m[32m iRect firstMarkRect;[m [32m+[m[32m iRect lastMarkRect;[m };[m [m static iBool draw_MarkPainter_(iWrapText *wrapText, iRangecc wrappedText, int origin, int advance,[m [36m@@ -1922,7 +2228,11 @@[m [mstatic iBool draw_MarkPainter_(iWrapText *wrapText, iRangecc wrappedText, int or[m }[m rect.size.x = iMax(gap_UI / 3, rect.size.x);[m mp->pos.y += lineHeight_Text(mp->d->font);[m [31m- fillRect_Paint(mp->paint, rect, uiMarked_ColorId);[m [32m+[m[32m fillRect_Paint(mp->paint, rect, uiMarked_ColorId | opaque_ColorId);[m [32m+[m[32m if (deviceType_App() != desktop_AppDeviceType) {[m [32m+[m[32m if (isEmpty_Rect(mp->firstMarkRect)) mp->firstMarkRect = rect;[m [32m+[m[32m mp->lastMarkRect = rect;[m [32m+[m[32m }[m return iTrue;[m }[m [m [36m@@ -1962,6 +2272,7 @@[m [mstatic void draw_InputWidget_(const iInputWidget *d) {[m };[m const iRangei visLines = visibleLineRange_InputWidget_(d);[m const int visLineOffsetY = visLineOffsetY_InputWidget_(d);[m [32m+[m[32m iRect markerRects[2];[m /* If buffered, just draw the buffered copy. */[m if (d->buffered && !isFocused) {[m /* Most input widgets will use this, since only one is focused at a time. */[m [36m@@ -1977,7 +2288,7 @@[m [mstatic void draw_InputWidget_(const iInputWidget *d) {[m .paint = &p,[m .d = d,[m .contentBounds = contentBounds,[m [31m- .mark = mark_InputWidget_(d)[m [32m+[m[32m .mark = mark_InputWidget_(d),[m };[m wrapText.context = ▮[m wrapText.wrapFunc = isFocused ? draw_MarkPainter_ : NULL; /* mark is drawn under each line of text */[m [36m@@ -1988,11 +2299,14 @@[m [mstatic void draw_InputWidget_(const iInputWidget *d) {[m marker.pos = drawPos;[m addv_I2(&drawPos, draw_WrapText(&wrapText, d->font, drawPos, fg).advance); /* lines end with \n */[m }[m [32m+[m[32m markerRects[0] = marker.firstMarkRect;[m [32m+[m[32m markerRects[1] = marker.lastMarkRect;[m wrapText.wrapFunc = NULL;[m wrapText.context = NULL;[m }[m /* Draw the insertion point. */[m [31m- if (isFocused && d->cursorVis && contains_Range(&visLines, d->cursor.y)) {[m [32m+[m[32m if (isFocused && d->cursorVis && contains_Range(&visLines, d->cursor.y) &&[m [32m+[m[32m isEmpty_Range(&d->mark)) {[m iInt2 curSize;[m iRangecc cursorChar = iNullRange;[m int visWrapsAbove = 0;[m [36m@@ -2040,6 +2354,11 @@[m [mstatic void draw_InputWidget_(const iInputWidget *d) {[m }[m }[m unsetClip_Paint(&p);[m [32m+[m[32m if (!isEmpty_Rect(markerRects[0])) {[m [32m+[m[32m for (int i = 0; i < 2; ++i) {[m [32m+[m[32m drawPin_Paint(&p, markerRects[i], i, uiTextCaution_ColorId);[m [32m+[m[32m }[m [32m+[m[32m }[m drawChildren_Widget(w);[m }[m [m [1mdiff --git a/src/ui/paint.c b/src/ui/paint.c[m [1mindex 71ebb81d..89de47d4 100644[m [1m--- a/src/ui/paint.c[m [1m+++ b/src/ui/paint.c[m [36m@@ -33,7 +33,8 @@[m [miLocalDef SDL_Renderer *renderer_Paint_(const iPaint *d) {[m [m static void setColor_Paint_(const iPaint *d, int color) {[m const iColor clr = get_Color(color & mask_ColorId);[m [31m- SDL_SetRenderDrawColor(renderer_Paint_(d), clr.r, clr.g, clr.b, clr.a * d->alpha / 255);[m [32m+[m[32m SDL_SetRenderDrawColor(renderer_Paint_(d), clr.r, clr.g, clr.b,[m [32m+[m[32m (color & opaque_ColorId ? 255 : clr.a) * d->alpha / 255);[m }[m [m void init_Paint(iPaint *d) {[m [36m@@ -186,6 +187,22 @@[m [mvoid drawLines_Paint(const iPaint *d, const iInt2 *points, size_t n, int color)[m free(offsetPoints);[m }[m [m [32m+[m[32mvoid drawPin_Paint(iPaint *d, iRect rangeRect, int dir, int pinColor) {[m [32m+[m[32m const int height = height_Rect(rangeRect);[m [32m+[m[32m iRect pin;[m [32m+[m[32m if (dir == 0) {[m [32m+[m[32m pin = (iRect){ add_I2(topLeft_Rect(rangeRect), init_I2(-gap_UI / 4, -gap_UI)),[m [32m+[m[32m init_I2(gap_UI / 2, height + gap_UI) };[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m pin = (iRect){ addX_I2(topRight_Rect(rangeRect), -gap_UI / 4),[m [32m+[m[32m init_I2(gap_UI / 2, height + gap_UI) };[m [32m+[m[32m }[m [32m+[m[32m fillRect_Paint(d, pin, pinColor);[m [32m+[m[32m fillRect_Paint(d, initCentered_Rect(dir == 0 ? topMid_Rect(pin) : bottomMid_Rect(pin),[m [32m+[m[32m init1_I2(gap_UI * 2)), pinColor);[m [32m+[m[32m}[m [32m+[m iInt2 size_SDLTexture(SDL_Texture *d) {[m iInt2 size;[m SDL_QueryTexture(d, NULL, NULL, &size.x, &size.y);[m [1mdiff --git a/src/ui/paint.h b/src/ui/paint.h[m [1mindex e6701635..e894b62f 100644[m [1m--- a/src/ui/paint.h[m [1m+++ b/src/ui/paint.h[m [36m@@ -63,4 +63,6 @@[m [miLocalDef void drawVLine_Paint(const iPaint *d, iInt2 pos, int len, int color) {[m drawLine_Paint(d, pos, addY_I2(pos, len), color);[m }[m [m [32m+[m[32mvoid drawPin_Paint (iPaint *, iRect rangeRect, int dir, int pinColor);[m [32m+[m iInt2 size_SDLTexture (SDL_Texture *);[m [1mdiff --git a/src/ui/root.c b/src/ui/root.c[m [1mindex 59f98aa4..91f9fbb3 100644[m [1m--- a/src/ui/root.c[m [1m+++ b/src/ui/root.c[m [36m@@ -1401,23 +1401,38 @@[m [mvoid createUserInterface_Root(iRoot *d) {[m { "${menu.closetab.other}", 0, 0, "tabs.close toleft:1 toright:1" },[m { barLeftArrow_Icon " ${menu.closetab.left}", 0, 0, "tabs.close toleft:1" },[m { barRightArrow_Icon " ${menu.closetab.right}", 0, 0, "tabs.close toright:1" },[m [31m- },[m [32m+[m[32m },[m 6);[m iWidget *barMenu =[m makeMenu_Widget(root,[m (iMenuItem[]){[m { leftHalf_Icon " ${menu.sidebar.left}", 0, 0, "sidebar.toggle" },[m { rightHalf_Icon " ${menu.sidebar.right}", 0, 0, "sidebar2.toggle" },[m [31m- },[m [32m+[m[32m },[m deviceType_App() == phone_AppDeviceType ? 1 : 2);[m iWidget *clipMenu = makeMenu_Widget(root,[m [31m- (iMenuItem[]){[m [31m- { scissor_Icon " ${menu.cut}", 0, 0, "input.copy cut:1" },[m [31m- { clipCopy_Icon " ${menu.copy}", 0, 0, "input.copy" },[m [31m- { "---" },[m [31m- { clipboard_Icon " ${menu.paste}", 0, 0, "input.paste" },[m [31m- },[m [31m- 4);[m [32m+[m[32m#if defined (iPlatformMobile)[m [32m+[m[32m (iMenuItem[]){[m [32m+[m[32m { ">>>" scissor_Icon " ${menu.cut}", 0, 0, "input.copy cut:1" },[m [32m+[m[32m { ">>>" clipCopy_Icon " ${menu.copy}", 0, 0, "input.copy" },[m [32m+[m[32m { ">>>" clipboard_Icon " ${menu.paste}", 0, 0, "input.paste" },[m [32m+[m[32m { "---" },[m [32m+[m[32m { ">>>" delete_Icon " " uiTextCaution_ColorEscape "${menu.delete}", 0, 0, "input.delete" },[m [32m+[m[32m { ">>>" select_Icon " ${menu.selectall}", 0, 0, "input.selectall" },[m [32m+[m[32m { ">>>" undo_Icon " ${menu.undo}", 0, 0, "input.undo" },[m [32m+[m[32m }, 7);[m [32m+[m[32m#else[m [32m+[m[32m (iMenuItem[]){[m [32m+[m[32m { scissor_Icon " ${menu.cut}", 0, 0, "input.copy cut:1" },[m [32m+[m[32m { clipCopy_Icon " ${menu.copy}", 0, 0, "input.copy" },[m [32m+[m[32m { clipboard_Icon " ${menu.paste}", 0, 0, "input.paste" },[m [32m+[m[32m { "---" },[m [32m+[m[32m { delete_Icon " " uiTextCaution_ColorEscape "${menu.delete}", 0, 0, "input.delete" },[m [32m+[m[32m { undo_Icon " ${menu.undo}", 0, 0, "input.undo" },[m [32m+[m[32m { "---" },[m [32m+[m[32m { select_Icon " ${menu.selectall}", 0, 0, "input.selectall" },[m [32m+[m[32m }, 8);[m [32m+[m[32m#endif[m iWidget *splitMenu = makeMenu_Widget(root, (iMenuItem[]){[m { "${menu.split.merge}", '1', 0, "ui.split arg:0" },[m { "${menu.split.swap}", SDLK_x, 0, "ui.split swap:1" },[m [1mdiff --git a/src/ui/touch.c b/src/ui/touch.c[m [1mindex 5fc8f245..61882739 100644[m [1m--- a/src/ui/touch.c[m [1m+++ b/src/ui/touch.c[m [36m@@ -293,6 +293,7 @@[m [mstatic void update_TouchState_(void *ptr) {[m }[m if (elapsed > 50 && !touch->isTapBegun) {[m /* Looks like a possible tap. */[m [32m+[m[32m touchState_()->currentTouchPos = initF3_I2(touch->pos[0]);[m dispatchNotification_Touch_(touch, widgetTapBegins_UserEventCode);[m dispatchMotion_Touch_(touch->pos[0], 0);[m refresh_Widget(touch->affinity);[m [36m@@ -471,13 +472,13 @@[m [miBool processEvent_Touch(const SDL_Event *ev) {[m }[m iTouchState *d = touchState_();[m iWindow *window = get_Window(); [m [31m- if (!isFinished_Anim(&window->rootOffset)) {[m [31m- return iFalse;[m [31m- }[m [32m+[m[32m// if (!isFinished_Anim(&window->rootOffset)) {[m [32m+[m[32m// return iFalse;[m [32m+[m[32m// }[m const iInt2 rootSize = size_Window(window);[m const SDL_TouchFingerEvent *fing = &ev->tfinger;[m const iFloat3 pos = add_F3(init_F3(fing->x * rootSize.x, fing->y * rootSize.y, 0), /* pixels */[m [31m- init_F3(0, -value_Anim(&window->rootOffset), 0));[m [32m+[m[32m init_F3(0, 0 /*-value_Anim(&window->rootOffset)*/, 0));[m const uint32_t nowTime = SDL_GetTicks();[m if (ev->type == SDL_FINGERDOWN) {[m /* Register the new touch. */[m [1mdiff --git a/src/ui/util.c b/src/ui/util.c[m [1mindex 48ed41a6..cfa8152c 100644[m [1m--- a/src/ui/util.c[m [1m+++ b/src/ui/util.c[m [36m@@ -706,23 +706,36 @@[m [miWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {[m setFrameColor_Widget(menu, uiSeparator_ColorId);[m }[m iBool haveIcons = iFalse;[m [32m+[m[32m iWidget *horizGroup = NULL;[m for (size_t i = 0; i < n; ++i) {[m const iMenuItem *item = &items[i];[m if (!item->label) {[m break;[m }[m [31m- if (equal_CStr(item->label, "---")) {[m [32m+[m[32m const char *labelText = item->label;[m [32m+[m[32m if (!startsWith_CStr(labelText, ">>>")) {[m [32m+[m[32m horizGroup = NULL;[m [32m+[m[32m }[m [32m+[m[32m if (equal_CStr(labelText, "---")) {[m addChild_Widget(menu, iClob(makeMenuSeparator_()));[m }[m else {[m iBool isInfo = iFalse;[m [31m- const char *labelText = item->label;[m [32m+[m[32m if (startsWith_CStr(labelText, ">>>")) {[m [32m+[m[32m labelText += 3;[m [32m+[m[32m if (!horizGroup) {[m [32m+[m[32m horizGroup = makeHDiv_Widget();[m [32m+[m[32m setFlags_Widget(horizGroup, resizeHeightOfChildren_WidgetFlag, iFalse);[m [32m+[m[32m setFlags_Widget(horizGroup, arrangeHeight_WidgetFlag, iTrue);[m [32m+[m[32m addChild_Widget(menu, iClob(horizGroup));[m [32m+[m[32m }[m [32m+[m[32m }[m if (startsWith_CStr(labelText, "```")) {[m labelText += 3;[m isInfo = iTrue;[m }[m iLabelWidget *label = addChildFlags_Widget([m [31m- menu,[m [32m+[m[32m horizGroup ? horizGroup : menu,[m iClob(newKeyMods_LabelWidget(labelText, item->key, item->kmods, item->command)),[m noBackground_WidgetFlag | frameless_WidgetFlag | alignLeft_WidgetFlag |[m drawKey_WidgetFlag | itemFlags);[m [36m@@ -766,6 +779,34 @@[m [mvoid openMenu_Widget(iWidget *d, iInt2 windowCoord) {[m openMenuFlags_Widget(d, windowCoord, iTrue);[m }[m [m [32m+[m[32mstatic void updateMenuItemFonts_Widget_(iWidget *d) {[m [32m+[m[32m const iBool isPortraitPhone = (deviceType_App() == phone_AppDeviceType && isPortrait_App());[m [32m+[m[32m const iBool isSlidePanel = (flags_Widget(d) & horizontalOffset_WidgetFlag) != 0;[m [32m+[m[32m iForEach(ObjectList, i, children_Widget(d)) {[m [32m+[m[32m if (isInstance_Object(i.object, &Class_LabelWidget)) {[m [32m+[m[32m iLabelWidget *label = i.object;[m [32m+[m[32m const iBool isCaution = startsWith_String(text_LabelWidget(label), uiTextCaution_ColorEscape);[m [32m+[m[32m if (isWrapped_LabelWidget(label)) {[m [32m+[m[32m continue;[m [32m+[m[32m }[m [32m+[m[32m if (deviceType_App() == desktop_AppDeviceType) {[m [32m+[m[32m setFont_LabelWidget(label, isCaution ? uiLabelBold_FontId : uiLabel_FontId);[m [32m+[m[32m }[m [32m+[m[32m else if (isPortraitPhone) {[m [32m+[m[32m if (!isSlidePanel) {[m [32m+[m[32m setFont_LabelWidget(label, isCaution ? defaultBigBold_FontId : defaultBig_FontId);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m setFont_LabelWidget(label, isCaution ? uiContentBold_FontId : uiContent_FontId);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m else if (childCount_Widget(i.object)) {[m [32m+[m[32m updateMenuItemFonts_Widget_(i.object);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) {[m const iRect rootRect = rect_Root(d->root);[m const iInt2 rootSize = rootRect.size;[m [36m@@ -788,28 +829,7 @@[m [mvoid openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) {[m }[m d->rect.size.x = rootSize.x;[m }[m [31m- /* Update item fonts. */ {[m [31m- iForEach(ObjectList, i, children_Widget(d)) {[m [31m- if (isInstance_Object(i.object, &Class_LabelWidget)) {[m [31m- iLabelWidget *label = i.object;[m [31m- const iBool isCaution = startsWith_String(text_LabelWidget(label), uiTextCaution_ColorEscape);[m [31m- if (isWrapped_LabelWidget(label)) {[m [31m- continue;[m [31m- }[m [31m- if (deviceType_App() == desktop_AppDeviceType) {[m [31m- setFont_LabelWidget(label, isCaution ? uiLabelBold_FontId : uiLabel_FontId);[m [31m- }[m [31m- else if (isPortraitPhone) {[m [31m- if (!isSlidePanel) {[m [31m- setFont_LabelWidget(label, isCaution ? defaultBigBold_FontId : defaultBig_FontId);[m [31m- }[m [31m- }[m [31m- else {[m [31m- setFont_LabelWidget(label, isCaution ? uiContentBold_FontId : uiContent_FontId);[m [31m- }[m [31m- }[m [31m- }[m [31m- }[m [32m+[m[32m updateMenuItemFonts_Widget_(d);[m arrange_Widget(d);[m if (isPortraitPhone) {[m if (isSlidePanel) {[m [1mdiff --git a/src/ui/widget.c b/src/ui/widget.c[m [1mindex 0765bf9f..1c0fb271 100644[m [1m--- a/src/ui/widget.c[m [1m+++ b/src/ui/widget.c[m [36m@@ -880,9 +880,9 @@[m [miInt2 localToWindow_Widget(const iWidget *d, iInt2 localCoord) {[m applyVisualOffset_Widget_(w, &pos);[m addv_I2(&window, pos);[m }[m [31m-#if defined (iPlatformMobile)[m [31m- window.y += value_Anim(&get_Window()->rootOffset);[m [31m-#endif[m [32m+[m[32m//#if defined (iPlatformMobile)[m [32m+[m[32m// window.y += value_Anim(&get_Window()->rootOffset);[m [32m+[m[32m//#endif[m return window;[m }[m [m [36m@@ -1072,23 +1072,33 @@[m [miBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {[m }[m [m iBool scrollOverflow_Widget(iWidget *d, int delta) {[m [31m- iRect bounds = boundsWithoutVisualOffset_Widget(d);[m [31m- const iInt2 rootSize = size_Root(d->root);[m [31m- const iRect winRect = safeRect_Root(d->root);[m [31m- const int yTop = top_Rect(winRect);[m [31m- const int yBottom = bottom_Rect(winRect);[m [32m+[m[32m iRect bounds = boundsWithoutVisualOffset_Widget(d);[m [32m+[m[32m// const iInt2 rootSize = size_Root(d->root);[m [32m+[m[32m const iRect winRect = adjusted_Rect(safeRect_Root(d->root),[m [32m+[m[32m zero_I2(),[m [32m+[m[32m init_I2(0, -get_Window()->keyboardHeight));[m [32m+[m[32m const int yTop = top_Rect(winRect);[m [32m+[m[32m const int yBottom = bottom_Rect(winRect);[m if (top_Rect(bounds) >= yTop && bottom_Rect(bounds) < yBottom) {[m return iFalse; /* fits inside just fine */[m }[m //const int safeBottom = rootSize.y - yBottom;[m [31m- bounds.pos.y += delta;[m [31m- const iRangei range = { bottom_Rect(winRect) - height_Rect(bounds), yTop };[m [32m+[m[32m iRangei validPosRange = { bottom_Rect(winRect) - height_Rect(bounds), yTop };[m [32m+[m[32m if (validPosRange.start > validPosRange.end) {[m [32m+[m[32m validPosRange.start = validPosRange.end; /* no room to scroll */[m [32m+[m[32m }[m [32m+[m[32m if (delta) {[m [32m+[m[32m if (delta < 0 && bounds.pos.y < validPosRange.start) {[m [32m+[m[32m delta = 0;[m [32m+[m[32m }[m [32m+[m[32m if (delta > 0 && bounds.pos.y > validPosRange.end) {[m [32m+[m[32m delta = 0;[m [32m+[m[32m }[m [32m+[m[32m bounds.pos.y += delta;[m // printf("range: %d ... %d\n", range.start, range.end);[m [31m- if (range.start >= range.end) {[m [31m- bounds.pos.y = range.end;[m }[m else {[m [31m- bounds.pos.y = iClamp(bounds.pos.y, range.start, range.end);[m [32m+[m[32m bounds.pos.y = iClamp(bounds.pos.y, validPosRange.start, validPosRange.end);[m }[m // if (delta >= 0) {[m // bounds.pos.y = iMin(bounds.pos.y, yTop);[m [36m@@ -1454,7 +1464,7 @@[m [mvoid setDrawBufferEnabled_Widget(iWidget *d, iBool enable) {[m [m static void beginBufferDraw_Widget_(const iWidget *d) {[m if (d->drawBuf) {[m [31m- printf("[%p] drawbuffer update %d\n", d, d->drawBuf->isValid);[m [32m+[m[32m// printf("[%p] drawbuffer update %d\n", d, d->drawBuf->isValid);[m if (d->drawBuf->isValid) {[m iAssert(!isEqual_I2(d->drawBuf->size, boundsForDraw_Widget_(d).size));[m // printf(" drawBuf:%dx%d boundsForDraw:%dx%d\n",[m [36m@@ -1503,7 +1513,7 @@[m [mvoid draw_Widget(const iWidget *d) {[m endBufferDraw_Widget_(d);[m }[m if (d->drawBuf) {[m [31m- iAssert(d->drawBuf->isValid);[m [32m+[m[32m //iAssert(d->drawBuf->isValid);[m const iRect bounds = bounds_Widget(d);[m SDL_RenderCopy(renderer_Window(get_Window()), d->drawBuf->texture, NULL,[m &(SDL_Rect){ bounds.pos.x, bounds.pos.y,[m [1mdiff --git a/src/ui/window.c b/src/ui/window.c[m [1mindex 8034d858..ed2ec024 100644[m [1m--- a/src/ui/window.c[m [1m+++ b/src/ui/window.c[m [36m@@ -421,7 +421,7 @@[m [mvoid init_Window(iWindow *d, iRect rect) {[m d->ignoreClick = iFalse;[m d->focusGainedAt = 0;[m d->keyboardHeight = 0;[m [31m- init_Anim(&d->rootOffset, 0.0f);[m [32m+[m[32m// init_Anim(&d->rootOffset, 0.0f);[m uint32_t flags = 0;[m #if defined (iPlatformAppleDesktop)[m SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl");[m [36m@@ -1215,10 +1215,10 @@[m [miBool isOpenGLRenderer_Window(void) {[m void setKeyboardHeight_Window(iWindow *d, int height) {[m if (d->keyboardHeight != height) {[m d->keyboardHeight = height;[m [31m- if (height == 0) {[m [31m- setFlags_Anim(&d->rootOffset, easeBoth_AnimFlag, iTrue);[m [31m- setValue_Anim(&d->rootOffset, 0, 250);[m [31m- }[m [32m+[m[32m// if (height == 0) {[m [32m+[m[32m// setFlags_Anim(&d->rootOffset, easeBoth_AnimFlag, iTrue);[m [32m+[m[32m// setValue_Anim(&d->rootOffset, 0, 250);[m [32m+[m[32m// }[m postCommandf_App("keyboard.changed arg:%d", height);[m postRefresh_App();[m }[m [1mdiff --git a/src/ui/window.h b/src/ui/window.h[m [1mindex 63f7e5f2..a5b8f137 100644[m [1m--- a/src/ui/window.h[m [1m+++ b/src/ui/window.h[m [36m@@ -98,7 +98,7 @@[m [mstruct Impl_Window {[m SDL_Cursor * cursors[SDL_NUM_SYSTEM_CURSORS];[m SDL_Cursor * pendingCursor;[m int loadAnimTimer;[m [31m- iAnim rootOffset;[m [32m+[m[32m// iAnim rootOffset;[m int keyboardHeight; /* mobile software keyboards */[m };[m [m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).