summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-02-02 14:17:00 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-02-02 14:17:00 +0200
commit6d885dee5e3a9fc7316c901542eec21e39ae1f12 (patch)
tree2b8a2acb393329317e975d4294f28a5a34967d9a
parentec82863a833d3533381dddbb170a8505a24e159d (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.gmi1
-rw-r--r--src/app.c4
-rw-r--r--src/ui/inputwidget.c4
-rw-r--r--src/ui/util.c6
-rw-r--r--src/ui/widget.c16
-rw-r--r--src/ui/widget.h1
-rw-r--r--src/ui/window.c1
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.
diff --git a/src/app.c b/src/app.c
index 29d88c2b..f44fdf4f 100644
--- a/src/app.c
+++ b/src/app.c
@@ -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
333static void insertChar_InputWidget_(iInputWidget *d, iChar chr) { 333static 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
880static 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
880iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusDir) { 893iAny *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
94enum iWidgetAddPos { 95enum 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;