diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-02-02 14:17:00 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-02-02 14:17:00 +0200 |
commit | 6d885dee5e3a9fc7316c901542eec21e39ae1f12 (patch) | |
tree | 2b8a2acb393329317e975d4294f28a5a34967d9a | |
parent | ec82863a833d3533381dddbb170a8505a24e159d (diff) |
Improved focus switching for dialogs
Widgets can now be defined as being the "focus root", i.e., the topmost
widget under which focus switching happens. Normally this is the window
root widget, but dialogs use this flag to confine focus switching
inside the dialog.
InputWidget in Overwrite mode will focus switch to the next focusable
widget when the text field becomes full.
-rw-r--r-- | res/about/version.gmi | 1 | ||||
-rw-r--r-- | src/app.c | 4 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 4 | ||||
-rw-r--r-- | src/ui/util.c | 6 | ||||
-rw-r--r-- | src/ui/widget.c | 16 | ||||
-rw-r--r-- | src/ui/widget.h | 1 | ||||
-rw-r--r-- | src/ui/window.c | 1 |
7 files changed, 27 insertions, 6 deletions
diff --git a/res/about/version.gmi b/res/about/version.gmi index a76769db..021db644 100644 --- a/res/about/version.gmi +++ b/res/about/version.gmi | |||
@@ -7,6 +7,7 @@ | |||
7 | # Release notes | 7 | # Release notes |
8 | 8 | ||
9 | ## 1.1.1 | 9 | ## 1.1.1 |
10 | * Fixed focus cycling inside dialogs. Widgets outside a dialog are not allowed to be focused. | ||
10 | * Fixed missing cursor in the New Identity "Valid until" field. | 11 | * Fixed missing cursor in the New Identity "Valid until" field. |
11 | * Fixed word wrapping issue in unread feed entry titles. | 12 | * Fixed word wrapping issue in unread feed entry titles. |
12 | * Fixed "Import Links as Bookmarks" so it can be used to import local copies of remote bookmarks when viewing the remote source page. | 13 | * Fixed "Import Links as Bookmarks" so it can be used to import local copies of remote bookmarks when viewing the remote source page. |
@@ -1008,7 +1008,7 @@ static iBool handleIdentityCreationCommands_(iWidget *dlg, const char *cmd) { | |||
1008 | sscanf(cstr_String(text_InputWidget(findChild_Widget(dlg, "ident.until"))), | 1008 | sscanf(cstr_String(text_InputWidget(findChild_Widget(dlg, "ident.until"))), |
1009 | "%04u-%u-%u %u:%u:%u", | 1009 | "%04u-%u-%u %u:%u:%u", |
1010 | &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]); | 1010 | &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]); |
1011 | if (n <= 0 || val[0] < (unsigned) today.year) { | 1011 | if (n <= 0) { |
1012 | makeMessage_Widget(orange_ColorEscape "INVALID DATE", | 1012 | makeMessage_Widget(orange_ColorEscape "INVALID DATE", |
1013 | "Please check the \"Valid until\" date. Examples:\n" | 1013 | "Please check the \"Valid until\" date. Examples:\n" |
1014 | "\u2022 2030\n" | 1014 | "\u2022 2030\n" |
@@ -1022,6 +1022,7 @@ static iBool handleIdentityCreationCommands_(iWidget *dlg, const char *cmd) { | |||
1022 | until.hour = n >= 4 ? val[3] : 0; | 1022 | until.hour = n >= 4 ? val[3] : 0; |
1023 | until.minute = n >= 5 ? val[4] : 0; | 1023 | until.minute = n >= 5 ? val[4] : 0; |
1024 | until.second = n == 6 ? val[5] : 0; | 1024 | until.second = n == 6 ? val[5] : 0; |
1025 | until.gmtOffsetSeconds = today.gmtOffsetSeconds; | ||
1025 | /* In the past? */ { | 1026 | /* In the past? */ { |
1026 | iTime now, t; | 1027 | iTime now, t; |
1027 | initCurrent_Time(&now); | 1028 | initCurrent_Time(&now); |
@@ -1471,6 +1472,7 @@ iBool handleCommand_App(const char *cmd) { | |||
1471 | } | 1472 | } |
1472 | else if (equal_Command(cmd, "ident.new")) { | 1473 | else if (equal_Command(cmd, "ident.new")) { |
1473 | iWidget *dlg = makeIdentityCreation_Widget(); | 1474 | iWidget *dlg = makeIdentityCreation_Widget(); |
1475 | setFocus_Widget(findChild_Widget(dlg, "ident.until")); | ||
1474 | setCommandHandler_Widget(dlg, handleIdentityCreationCommands_); | 1476 | setCommandHandler_Widget(dlg, handleIdentityCreationCommands_); |
1475 | return iTrue; | 1477 | return iTrue; |
1476 | } | 1478 | } |
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index ae73c9c9..3f799e3c 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -331,6 +331,7 @@ void end_InputWidget(iInputWidget *d, iBool accept) { | |||
331 | } | 331 | } |
332 | 332 | ||
333 | static void insertChar_InputWidget_(iInputWidget *d, iChar chr) { | 333 | static void insertChar_InputWidget_(iInputWidget *d, iChar chr) { |
334 | iWidget *w = as_Widget(d); | ||
334 | if (d->mode == insert_InputMode) { | 335 | if (d->mode == insert_InputMode) { |
335 | insert_Array(&d->text, d->cursor, &chr); | 336 | insert_Array(&d->text, d->cursor, &chr); |
336 | d->cursor++; | 337 | d->cursor++; |
@@ -341,7 +342,8 @@ static void insertChar_InputWidget_(iInputWidget *d, iChar chr) { | |||
341 | } | 342 | } |
342 | set_Array(&d->text, d->cursor++, &chr); | 343 | set_Array(&d->text, d->cursor++, &chr); |
343 | if (d->maxLen && d->cursor == d->maxLen) { | 344 | if (d->maxLen && d->cursor == d->maxLen) { |
344 | setFocus_Widget(NULL); | 345 | iWidget *nextFocus = findFocusable_Widget(w, forward_WidgetFocusDir); |
346 | setFocus_Widget(nextFocus == w ? NULL : nextFocus); | ||
345 | } | 347 | } |
346 | } | 348 | } |
347 | showCursor_InputWidget_(d); | 349 | showCursor_InputWidget_(d); |
diff --git a/src/ui/util.c b/src/ui/util.c index 91945db8..4d5ed916 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -764,9 +764,9 @@ iWidget *makeSheet_Widget(const char *id) { | |||
764 | setFrameColor_Widget(sheet, uiSeparator_ColorId); | 764 | setFrameColor_Widget(sheet, uiSeparator_ColorId); |
765 | setBackgroundColor_Widget(sheet, uiBackground_ColorId); | 765 | setBackgroundColor_Widget(sheet, uiBackground_ColorId); |
766 | setFlags_Widget(sheet, | 766 | setFlags_Widget(sheet, |
767 | mouseModal_WidgetFlag | keepOnTop_WidgetFlag | arrangeVertical_WidgetFlag | | 767 | focusRoot_WidgetFlag | mouseModal_WidgetFlag | keepOnTop_WidgetFlag | |
768 | arrangeSize_WidgetFlag | centerHorizontal_WidgetFlag | | 768 | arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag | |
769 | overflowScrollable_WidgetFlag, | 769 | centerHorizontal_WidgetFlag | overflowScrollable_WidgetFlag, |
770 | iTrue); | 770 | iTrue); |
771 | return sheet; | 771 | return sheet; |
772 | } | 772 | } |
diff --git a/src/ui/widget.c b/src/ui/widget.c index e2d0f922..ddb3f092 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -877,8 +877,22 @@ static const iWidget *findFocusable_Widget_(const iWidget *d, const iWidget *sta | |||
877 | return NULL; | 877 | return NULL; |
878 | } | 878 | } |
879 | 879 | ||
880 | static const iWidget *findFocusRoot_Widget_(const iWidget *d) { | ||
881 | iForEach(ObjectList, i, d->children) { | ||
882 | const iWidget *root = findFocusRoot_Widget_(constAs_Widget(i.object)); | ||
883 | if (root) { | ||
884 | return root; | ||
885 | } | ||
886 | } | ||
887 | if (d->flags & focusRoot_WidgetFlag) { | ||
888 | return d; | ||
889 | } | ||
890 | return NULL; | ||
891 | } | ||
892 | |||
880 | iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusDir) { | 893 | iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusDir) { |
881 | iWidget *root = get_Window()->root; | 894 | const iWidget *root = findFocusRoot_Widget_(get_Window()->root); |
895 | iAssert(root != NULL); | ||
882 | iBool getNext = (startFrom ? iFalse : iTrue); | 896 | iBool getNext = (startFrom ? iFalse : iTrue); |
883 | const iWidget *found = findFocusable_Widget_(root, startFrom, &getNext, focusDir); | 897 | const iWidget *found = findFocusable_Widget_(root, startFrom, &getNext, focusDir); |
884 | if (!found && startFrom) { | 898 | if (!found && startFrom) { |
diff --git a/src/ui/widget.h b/src/ui/widget.h index e40b333b..79f68b3c 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h | |||
@@ -90,6 +90,7 @@ enum iWidgetFlag { | |||
90 | #define wrapText_WidgetFlag iBit64(36) | 90 | #define wrapText_WidgetFlag iBit64(36) |
91 | #define borderTop_WidgetFlag iBit64(37) | 91 | #define borderTop_WidgetFlag iBit64(37) |
92 | #define overflowScrollable_WidgetFlag iBit64(38) | 92 | #define overflowScrollable_WidgetFlag iBit64(38) |
93 | #define focusRoot_WidgetFlag iBit64(39) | ||
93 | 94 | ||
94 | enum iWidgetAddPos { | 95 | enum iWidgetAddPos { |
95 | back_WidgetAddPos, | 96 | back_WidgetAddPos, |
diff --git a/src/ui/window.c b/src/ui/window.c index 66994e79..8df92706 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -781,6 +781,7 @@ void init_Window(iWindow *d, iRect rect) { | |||
781 | } | 781 | } |
782 | #endif | 782 | #endif |
783 | d->root = new_Widget(); | 783 | d->root = new_Widget(); |
784 | setFlags_Widget(d->root, focusRoot_WidgetFlag, iTrue); | ||
784 | d->presentTime = 0.0; | 785 | d->presentTime = 0.0; |
785 | d->frameTime = SDL_GetTicks(); | 786 | d->frameTime = SDL_GetTicks(); |
786 | d->loadAnimTimer = 0; | 787 | d->loadAnimTimer = 0; |