diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-06 22:45:15 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-06 22:45:15 +0300 |
commit | a364d9456dfdfd8181904fca6308e9c36eefd10a (patch) | |
tree | f355ded227cf52053784b991f5d8441a5502e447 /src/ui/inputwidget.c | |
parent | 52a1652536e4e27751ac121009f85113e72afe7d (diff) |
LookupWidget: Keyboard focus and cursor
Diffstat (limited to 'src/ui/inputwidget.c')
-rw-r--r-- | src/ui/inputwidget.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 16db6bf5..8f5a0656 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -54,6 +54,7 @@ struct Impl_InputWidget { | |||
54 | iBool isSensitive; | 54 | iBool isSensitive; |
55 | iBool enterPressed; | 55 | iBool enterPressed; |
56 | iBool selectAllOnFocus; | 56 | iBool selectAllOnFocus; |
57 | iBool notifyEdits; | ||
57 | size_t maxLen; | 58 | size_t maxLen; |
58 | iArray text; /* iChar[] */ | 59 | iArray text; /* iChar[] */ |
59 | iArray oldText; /* iChar[] */ | 60 | iArray oldText; /* iChar[] */ |
@@ -97,6 +98,7 @@ void init_InputWidget(iInputWidget *d, size_t maxLen) { | |||
97 | d->isSensitive = iFalse; | 98 | d->isSensitive = iFalse; |
98 | d->enterPressed = iFalse; | 99 | d->enterPressed = iFalse; |
99 | d->selectAllOnFocus = iFalse; | 100 | d->selectAllOnFocus = iFalse; |
101 | d->notifyEdits = iFalse; | ||
100 | iZap(d->mark); | 102 | iZap(d->mark); |
101 | setMaxLen_InputWidget(d, maxLen); | 103 | setMaxLen_InputWidget(d, maxLen); |
102 | /* Caller must arrange the width, but the height is fixed. */ | 104 | /* Caller must arrange the width, but the height is fixed. */ |
@@ -300,10 +302,20 @@ void setSelectAllOnFocus_InputWidget(iInputWidget *d, iBool selectAllOnFocus) { | |||
300 | d->selectAllOnFocus = selectAllOnFocus; | 302 | d->selectAllOnFocus = selectAllOnFocus; |
301 | } | 303 | } |
302 | 304 | ||
305 | void setNotifyEdits_InputWidget(iInputWidget *d, iBool notifyEdits) { | ||
306 | d->notifyEdits = notifyEdits; | ||
307 | } | ||
308 | |||
303 | static iRanges mark_InputWidget_(const iInputWidget *d) { | 309 | static iRanges mark_InputWidget_(const iInputWidget *d) { |
304 | return (iRanges){ iMin(d->mark.start, d->mark.end), iMax(d->mark.start, d->mark.end) }; | 310 | return (iRanges){ iMin(d->mark.start, d->mark.end), iMax(d->mark.start, d->mark.end) }; |
305 | } | 311 | } |
306 | 312 | ||
313 | static void contentsWereChanged_InputWidget_(iInputWidget *d) { | ||
314 | if (d->notifyEdits) { | ||
315 | postCommand_Widget(d, "input.edited id:%s", cstr_String(id_Widget(constAs_Widget(d)))); | ||
316 | } | ||
317 | } | ||
318 | |||
307 | static iBool deleteMarked_InputWidget_(iInputWidget *d) { | 319 | static iBool deleteMarked_InputWidget_(iInputWidget *d) { |
308 | const iRanges m = mark_InputWidget_(d); | 320 | const iRanges m = mark_InputWidget_(d); |
309 | if (!isEmpty_Range(&m)) { | 321 | if (!isEmpty_Range(&m)) { |
@@ -481,6 +493,7 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
481 | if (key == 'x') { | 493 | if (key == 'x') { |
482 | pushUndo_InputWidget_(d); | 494 | pushUndo_InputWidget_(d); |
483 | deleteMarked_InputWidget_(d); | 495 | deleteMarked_InputWidget_(d); |
496 | contentsWereChanged_InputWidget_(d); | ||
484 | } | 497 | } |
485 | } | 498 | } |
486 | return iTrue; | 499 | return iTrue; |
@@ -494,11 +507,13 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
494 | iConstForEach(String, i, paste) { | 507 | iConstForEach(String, i, paste) { |
495 | insertChar_InputWidget_(d, i.value); | 508 | insertChar_InputWidget_(d, i.value); |
496 | } | 509 | } |
510 | contentsWereChanged_InputWidget_(d); | ||
497 | } | 511 | } |
498 | return iTrue; | 512 | return iTrue; |
499 | case 'z': | 513 | case 'z': |
500 | if (popUndo_InputWidget_(d)) { | 514 | if (popUndo_InputWidget_(d)) { |
501 | refresh_Widget(w); | 515 | refresh_Widget(w); |
516 | contentsWereChanged_InputWidget_(d); | ||
502 | } | 517 | } |
503 | return iTrue; | 518 | return iTrue; |
504 | } | 519 | } |
@@ -518,16 +533,19 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
518 | if (!isEmpty_Range(&d->mark)) { | 533 | if (!isEmpty_Range(&d->mark)) { |
519 | pushUndo_InputWidget_(d); | 534 | pushUndo_InputWidget_(d); |
520 | deleteMarked_InputWidget_(d); | 535 | deleteMarked_InputWidget_(d); |
536 | contentsWereChanged_InputWidget_(d); | ||
521 | } | 537 | } |
522 | else if (mods & KMOD_ALT) { | 538 | else if (mods & KMOD_ALT) { |
523 | pushUndo_InputWidget_(d); | 539 | pushUndo_InputWidget_(d); |
524 | d->mark.start = d->cursor; | 540 | d->mark.start = d->cursor; |
525 | d->mark.end = skipWord_InputWidget_(d, d->cursor, -1); | 541 | d->mark.end = skipWord_InputWidget_(d, d->cursor, -1); |
526 | deleteMarked_InputWidget_(d); | 542 | deleteMarked_InputWidget_(d); |
543 | contentsWereChanged_InputWidget_(d); | ||
527 | } | 544 | } |
528 | else if (d->cursor > 0) { | 545 | else if (d->cursor > 0) { |
529 | pushUndo_InputWidget_(d); | 546 | pushUndo_InputWidget_(d); |
530 | remove_Array(&d->text, --d->cursor); | 547 | remove_Array(&d->text, --d->cursor); |
548 | contentsWereChanged_InputWidget_(d); | ||
531 | } | 549 | } |
532 | showCursor_InputWidget_(d); | 550 | showCursor_InputWidget_(d); |
533 | refresh_Widget(w); | 551 | refresh_Widget(w); |
@@ -538,16 +556,19 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
538 | if (!isEmpty_Range(&d->mark)) { | 556 | if (!isEmpty_Range(&d->mark)) { |
539 | pushUndo_InputWidget_(d); | 557 | pushUndo_InputWidget_(d); |
540 | deleteMarked_InputWidget_(d); | 558 | deleteMarked_InputWidget_(d); |
559 | contentsWereChanged_InputWidget_(d); | ||
541 | } | 560 | } |
542 | else if (mods & KMOD_ALT) { | 561 | else if (mods & KMOD_ALT) { |
543 | pushUndo_InputWidget_(d); | 562 | pushUndo_InputWidget_(d); |
544 | d->mark.start = d->cursor; | 563 | d->mark.start = d->cursor; |
545 | d->mark.end = skipWord_InputWidget_(d, d->cursor, +1); | 564 | d->mark.end = skipWord_InputWidget_(d, d->cursor, +1); |
546 | deleteMarked_InputWidget_(d); | 565 | deleteMarked_InputWidget_(d); |
566 | contentsWereChanged_InputWidget_(d); | ||
547 | } | 567 | } |
548 | else if (d->cursor < size_Array(&d->text)) { | 568 | else if (d->cursor < size_Array(&d->text)) { |
549 | pushUndo_InputWidget_(d); | 569 | pushUndo_InputWidget_(d); |
550 | remove_Array(&d->text, d->cursor); | 570 | remove_Array(&d->text, d->cursor); |
571 | contentsWereChanged_InputWidget_(d); | ||
551 | } | 572 | } |
552 | showCursor_InputWidget_(d); | 573 | showCursor_InputWidget_(d); |
553 | refresh_Widget(w); | 574 | refresh_Widget(w); |
@@ -557,10 +578,12 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
557 | if (!isEmpty_Range(&d->mark)) { | 578 | if (!isEmpty_Range(&d->mark)) { |
558 | pushUndo_InputWidget_(d); | 579 | pushUndo_InputWidget_(d); |
559 | deleteMarked_InputWidget_(d); | 580 | deleteMarked_InputWidget_(d); |
581 | contentsWereChanged_InputWidget_(d); | ||
560 | } | 582 | } |
561 | else { | 583 | else { |
562 | pushUndo_InputWidget_(d); | 584 | pushUndo_InputWidget_(d); |
563 | removeN_Array(&d->text, d->cursor, size_Array(&d->text) - d->cursor); | 585 | removeN_Array(&d->text, d->cursor, size_Array(&d->text) - d->cursor); |
586 | contentsWereChanged_InputWidget_(d); | ||
564 | } | 587 | } |
565 | showCursor_InputWidget_(d); | 588 | showCursor_InputWidget_(d); |
566 | refresh_Widget(w); | 589 | refresh_Widget(w); |
@@ -612,6 +635,7 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
612 | return iTrue; | 635 | return iTrue; |
613 | } | 636 | } |
614 | case SDLK_TAB: | 637 | case SDLK_TAB: |
638 | case SDLK_DOWN: /* for moving to lookup from url entry */ | ||
615 | /* Allow focus switching. */ | 639 | /* Allow focus switching. */ |
616 | return processEvent_Widget(as_Widget(d), ev); | 640 | return processEvent_Widget(as_Widget(d), ev); |
617 | } | 641 | } |
@@ -627,6 +651,7 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
627 | iConstForEach(String, i, uni) { | 651 | iConstForEach(String, i, uni) { |
628 | insertChar_InputWidget_(d, i.value); | 652 | insertChar_InputWidget_(d, i.value); |
629 | } | 653 | } |
654 | contentsWereChanged_InputWidget_(d); | ||
630 | return iTrue; | 655 | return iTrue; |
631 | } | 656 | } |
632 | return processEvent_Widget(w, ev); | 657 | return processEvent_Widget(w, ev); |
@@ -643,7 +668,6 @@ static iBool isWhite_(const iString *str) { | |||
643 | 668 | ||
644 | static void draw_InputWidget_(const iInputWidget *d) { | 669 | static void draw_InputWidget_(const iInputWidget *d) { |
645 | const iWidget *w = constAs_Widget(d); | 670 | const iWidget *w = constAs_Widget(d); |
646 | const uint32_t time = frameTime_Window(get_Window()); | ||
647 | iRect bounds = adjusted_Rect(bounds_Widget(w), padding_(), neg_I2(padding_())); | 671 | iRect bounds = adjusted_Rect(bounds_Widget(w), padding_(), neg_I2(padding_())); |
648 | iBool isHint = iFalse; | 672 | iBool isHint = iFalse; |
649 | const iBool isFocused = isFocused_Widget(w); | 673 | const iBool isFocused = isFocused_Widget(w); |