summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-09-18 08:26:31 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-09-18 08:26:31 +0300
commit95941a8fca886ba258716c535d51d0d68d075993 (patch)
tree0be54cd99abf2da1bbc426485c6a980546a6a3a9
parentdaaf3e72b472e05a4378a7789c6ebedd9b0e9b6e (diff)
Tracking hover widget; cleanup
The hover widget may get deleted during event processing, so Window keeps track of it for refreshing. TODO: Random crash when a destroyed menu is still in the onTop array (?).
-rw-r--r--src/app.c20
-rw-r--r--src/ui/inputwidget.c1
-rw-r--r--src/ui/mobile.c6
-rw-r--r--src/ui/mobile.h2
-rw-r--r--src/ui/root.c4
-rw-r--r--src/ui/touch.c6
-rw-r--r--src/ui/widget.c22
-rw-r--r--src/ui/window.c6
-rw-r--r--src/ui/window.h2
9 files changed, 31 insertions, 38 deletions
diff --git a/src/app.c b/src/app.c
index ed72c450..e06a32ce 100644
--- a/src/app.c
+++ b/src/app.c
@@ -1069,11 +1069,6 @@ iLocalDef iBool isWaitingAllowed_App_(iApp *d) {
1069 return iFalse; 1069 return iFalse;
1070 } 1070 }
1071#endif 1071#endif
1072//#if defined (iPlatformMobile)
1073// if (!isFinished_Anim(&d->window->rootOffset)) {
1074// return iFalse;
1075// }
1076//#endif
1077 return !value_Atomic(&d->pendingRefresh) && isEmpty_SortedArray(&d->tickers); 1072 return !value_Atomic(&d->pendingRefresh) && isEmpty_SortedArray(&d->tickers);
1078} 1073}
1079 1074
@@ -1273,7 +1268,7 @@ void processEvents_App(enum iAppEventMode eventMode) {
1273 } 1268 }
1274 } 1269 }
1275#endif 1270#endif
1276 const iWidget *oldHover = d->window->hover; 1271 d->window->lastHover = d->window->hover;
1277 iBool wasUsed = processEvent_Window(d->window, &ev); 1272 iBool wasUsed = processEvent_Window(d->window, &ev);
1278 if (!wasUsed) { 1273 if (!wasUsed) {
1279 /* There may be a key bindings for this. */ 1274 /* There may be a key bindings for this. */
@@ -1309,8 +1304,8 @@ void processEvents_App(enum iAppEventMode eventMode) {
1309 free(ev.user.data1); 1304 free(ev.user.data1);
1310 } 1305 }
1311 /* Update when hover has changed. */ 1306 /* Update when hover has changed. */
1312 if (oldHover != d->window->hover) { 1307 if (d->window->lastHover != d->window->hover) {
1313 refresh_Widget(oldHover); 1308 refresh_Widget(d->window->lastHover);
1314 refresh_Widget(d->window->hover); 1309 refresh_Widget(d->window->hover);
1315 } 1310 }
1316 break; 1311 break;
@@ -1318,7 +1313,7 @@ void processEvents_App(enum iAppEventMode eventMode) {
1318 } 1313 }
1319 } 1314 }
1320#if defined (LAGRANGE_ENABLE_IDLE_SLEEP) 1315#if defined (LAGRANGE_ENABLE_IDLE_SLEEP)
1321 if (d->isIdling && !gotEvents /*&& isFinished_Anim(&d->window->rootOffset)*/) { 1316 if (d->isIdling && !gotEvents) {
1322 /* This is where we spend most of our time when idle. 60 Hz still quite a lot but we 1317 /* This is where we spend most of our time when idle. 60 Hz still quite a lot but we
1323 can't wait too long after the user tries to interact again with the app. In any 1318 can't wait too long after the user tries to interact again with the app. In any
1324 case, on macOS SDL_WaitEvent() seems to use 10x more CPU time than sleeping. */ 1319 case, on macOS SDL_WaitEvent() seems to use 10x more CPU time than sleeping. */
@@ -1410,10 +1405,7 @@ void refresh_App(void) {
1410 } 1405 }
1411#endif 1406#endif
1412 if (!exchange_Atomic(&d->pendingRefresh, iFalse)) { 1407 if (!exchange_Atomic(&d->pendingRefresh, iFalse)) {
1413 /* Refreshing wasn't pending. */ 1408 return;
1414// if (isFinished_Anim(&d->window->rootOffset)) {
1415 return;
1416// }
1417 } 1409 }
1418// iTime draw; 1410// iTime draw;
1419// initCurrent_Time(&draw); 1411// initCurrent_Time(&draw);
@@ -2746,7 +2738,7 @@ iBool handleCommand_App(const char *cmd) {
2746 else if (equal_Command(cmd, "feeds.update.finished")) { 2738 else if (equal_Command(cmd, "feeds.update.finished")) {
2747 showCollapsed_Widget(findWidget_Root("feeds.progress"), iFalse); 2739 showCollapsed_Widget(findWidget_Root("feeds.progress"), iFalse);
2748 refreshFinished_Feeds(); 2740 refreshFinished_Feeds();
2749 postRefresh_App(); 2741 refresh_Widget(findWidget_App("url"));
2750 return iFalse; 2742 return iFalse;
2751 } 2743 }
2752 else if (equal_Command(cmd, "visited.changed")) { 2744 else if (equal_Command(cmd, "visited.changed")) {
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c
index d078593a..a561d5bd 100644
--- a/src/ui/inputwidget.c
+++ b/src/ui/inputwidget.c
@@ -1916,6 +1916,7 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
1916 } 1916 }
1917 return iFalse; 1917 return iFalse;
1918 } 1918 }
1919 /* TODO: Scroll to keep widget visible when keyboard appears. */
1919// else if (isCommand_UserEvent(ev, "keyboard.changed")) { 1920// else if (isCommand_UserEvent(ev, "keyboard.changed")) {
1920// if (isFocused_Widget(d) && arg_Command(command_UserEvent(ev))) { 1921// if (isFocused_Widget(d) && arg_Command(command_UserEvent(ev))) {
1921// iRect rect = bounds_Widget(w); 1922// iRect rect = bounds_Widget(w);
diff --git a/src/ui/mobile.c b/src/ui/mobile.c
index e04e8d20..3cb6e631 100644
--- a/src/ui/mobile.c
+++ b/src/ui/mobile.c
@@ -425,10 +425,10 @@ static iWidget *addChildPanel_(iWidget *parent, iLabelWidget *panelButton,
425 return panel; 425 return panel;
426} 426}
427 427
428void finalizeSheet_Mobile(iWidget *sheet) { 428//void finalizeSheet_Mobile(iWidget *sheet) {
429 arrange_Widget(sheet); 429// arrange_Widget(sheet);
430// postRefresh_App(); 430// postRefresh_App();
431} 431//}
432 432
433static size_t countItems_(const iMenuItem *itemsNullTerminated) { 433static size_t countItems_(const iMenuItem *itemsNullTerminated) {
434 size_t num = 0; 434 size_t num = 0;
diff --git a/src/ui/mobile.h b/src/ui/mobile.h
index 957c0e42..9d7ac8e4 100644
--- a/src/ui/mobile.h
+++ b/src/ui/mobile.h
@@ -55,5 +55,3 @@ enum iTransitionDir {
55 55
56void setupMenuTransition_Mobile (iWidget *menu, iBool isIncoming); 56void setupMenuTransition_Mobile (iWidget *menu, iBool isIncoming);
57void setupSheetTransition_Mobile (iWidget *sheet, int flags); 57void setupSheetTransition_Mobile (iWidget *sheet, int flags);
58
59void finalizeSheet_Mobile (iWidget *sheet);
diff --git a/src/ui/root.c b/src/ui/root.c
index 71f53af4..21bed366 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -271,13 +271,15 @@ void destroyPending_Root(iRoot *d) {
271 setCurrent_Root(d); 271 setCurrent_Root(d);
272 iForEach(PtrSet, i, d->pendingDestruction) { 272 iForEach(PtrSet, i, d->pendingDestruction) {
273 iWidget *widget = *i.value; 273 iWidget *widget = *i.value;
274 iAssert(widget->root == d);
274 if (!isFinished_Anim(&widget->visualOffset) || 275 if (!isFinished_Anim(&widget->visualOffset) ||
275 isBeingVisuallyOffsetByReference_Widget(widget)) { 276 isBeingVisuallyOffsetByReference_Widget(widget)) {
276 continue; 277 continue;
277 } 278 }
278 if (widget->flags & keepOnTop_WidgetFlag) { 279 if (widget->flags & keepOnTop_WidgetFlag) {
279 removeOne_PtrArray(onTop_Root(widget->root), widget); 280 removeOne_PtrArray(d->onTop, widget);
280 } 281 }
282 iAssert(indexOf_PtrArray(d->onTop, widget) == iInvalidPos);
281 if (widget->parent) { 283 if (widget->parent) {
282 removeChild_Widget(widget->parent, widget); 284 removeChild_Widget(widget->parent, widget);
283 } 285 }
diff --git a/src/ui/touch.c b/src/ui/touch.c
index 5130149b..613f2c0d 100644
--- a/src/ui/touch.c
+++ b/src/ui/touch.c
@@ -472,13 +472,9 @@ iBool processEvent_Touch(const SDL_Event *ev) {
472 } 472 }
473 iTouchState *d = touchState_(); 473 iTouchState *d = touchState_();
474 iWindow *window = get_Window(); 474 iWindow *window = get_Window();
475// if (!isFinished_Anim(&window->rootOffset)) {
476// return iFalse;
477// }
478 const iInt2 rootSize = size_Window(window); 475 const iInt2 rootSize = size_Window(window);
479 const SDL_TouchFingerEvent *fing = &ev->tfinger; 476 const SDL_TouchFingerEvent *fing = &ev->tfinger;
480 const iFloat3 pos = add_F3(init_F3(fing->x * rootSize.x, fing->y * rootSize.y, 0), /* pixels */ 477 const iFloat3 pos = init_F3(fing->x * rootSize.x, fing->y * rootSize.y, 0); /* pixels */
481 init_F3(0, 0 /*-value_Anim(&window->rootOffset)*/, 0));
482 const uint32_t nowTime = SDL_GetTicks(); 478 const uint32_t nowTime = SDL_GetTicks();
483 if (ev->type == SDL_FINGERDOWN) { 479 if (ev->type == SDL_FINGERDOWN) {
484 /* Register the new touch. */ 480 /* Register the new touch. */
diff --git a/src/ui/widget.c b/src/ui/widget.c
index 25142691..184ce2a3 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -163,11 +163,15 @@ static void aboutToBeDestroyed_Widget_(iWidget *d) {
163 d->flags |= destroyPending_WidgetFlag; 163 d->flags |= destroyPending_WidgetFlag;
164 if (isFocused_Widget(d)) { 164 if (isFocused_Widget(d)) {
165 setFocus_Widget(NULL); 165 setFocus_Widget(NULL);
166 return; 166 //return; /* TODO: Why?! */
167 } 167 }
168 remove_Periodic(periodic_App(), d); 168 remove_Periodic(periodic_App(), d);
169 iWindow *win = get_Window();
169 if (isHover_Widget(d)) { 170 if (isHover_Widget(d)) {
170 get_Window()->hover = NULL; 171 win->hover = NULL;
172 }
173 if (win->lastHover == d) {
174 win->lastHover = NULL;
171 } 175 }
172 iForEach(ObjectList, i, d->children) { 176 iForEach(ObjectList, i, d->children) {
173 aboutToBeDestroyed_Widget_(as_Widget(i.object)); 177 aboutToBeDestroyed_Widget_(as_Widget(i.object));
@@ -214,6 +218,7 @@ void setFlags_Widget(iWidget *d, int64_t flags, iBool set) {
214 } 218 }
215 else { 219 else {
216 removeOne_PtrArray(onTop, d); 220 removeOne_PtrArray(onTop, d);
221 iAssert(indexOf_PtrArray(onTop, d) == iInvalidPos);
217 } 222 }
218 } 223 }
219 if (d->flags & arrangeWidth_WidgetFlag && 224 if (d->flags & arrangeWidth_WidgetFlag &&
@@ -880,9 +885,6 @@ iInt2 localToWindow_Widget(const iWidget *d, iInt2 localCoord) {
880 applyVisualOffset_Widget_(w, &pos); 885 applyVisualOffset_Widget_(w, &pos);
881 addv_I2(&window, pos); 886 addv_I2(&window, pos);
882 } 887 }
883//#if defined (iPlatformMobile)
884// window.y += value_Anim(&get_Window()->rootOffset);
885//#endif
886 return window; 888 return window;
887} 889}
888 890
@@ -962,7 +964,11 @@ static iBool filterEvent_Widget_(const iWidget *d, const SDL_Event *ev) {
962} 964}
963 965
964void unhover_Widget(void) { 966void unhover_Widget(void) {
965 get_Window()->hover = NULL; 967 iWidget **hover = &get_Window()->hover;
968 if (*hover) {
969 refresh_Widget(*hover);
970 }
971 *hover = NULL;
966} 972}
967 973
968iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { 974iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
@@ -1415,7 +1421,9 @@ static void findPotentiallyVisible_Widget_(const iWidget *d, iPtrArray *pvs) {
1415 iRect fullyMasked = zero_Rect(); 1421 iRect fullyMasked = zero_Rect();
1416 if (isRoot_Widget_(d)) { 1422 if (isRoot_Widget_(d)) {
1417 iReverseConstForEach(PtrArray, i, onTop_Root(d->root)) { 1423 iReverseConstForEach(PtrArray, i, onTop_Root(d->root)) {
1418 addToPotentiallyVisible_Widget_(i.ptr, pvs, &fullyMasked); 1424 const iWidget *top = i.ptr;
1425 iAssert(top->parent);
1426 addToPotentiallyVisible_Widget_(top, pvs, &fullyMasked);
1419 } 1427 }
1420 } 1428 }
1421 iReverseConstForEach(ObjectList, i, d->children) { 1429 iReverseConstForEach(ObjectList, i, d->children) {
diff --git a/src/ui/window.c b/src/ui/window.c
index ed2ec024..0dd248e6 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -405,6 +405,7 @@ void init_Window(iWindow *d, iRect rect) {
405 d->splitMode = d->pendingSplitMode = 0; 405 d->splitMode = d->pendingSplitMode = 0;
406 d->pendingSplitUrl = new_String(); 406 d->pendingSplitUrl = new_String();
407 d->hover = NULL; 407 d->hover = NULL;
408 d->lastHover = NULL;
408 d->mouseGrab = NULL; 409 d->mouseGrab = NULL;
409 d->focus = NULL; 410 d->focus = NULL;
410 iZap(d->cursors); 411 iZap(d->cursors);
@@ -421,7 +422,6 @@ void init_Window(iWindow *d, iRect rect) {
421 d->ignoreClick = iFalse; 422 d->ignoreClick = iFalse;
422 d->focusGainedAt = 0; 423 d->focusGainedAt = 0;
423 d->keyboardHeight = 0; 424 d->keyboardHeight = 0;
424// init_Anim(&d->rootOffset, 0.0f);
425 uint32_t flags = 0; 425 uint32_t flags = 0;
426#if defined (iPlatformAppleDesktop) 426#if defined (iPlatformAppleDesktop)
427 SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl"); 427 SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl");
@@ -1215,10 +1215,6 @@ iBool isOpenGLRenderer_Window(void) {
1215void setKeyboardHeight_Window(iWindow *d, int height) { 1215void setKeyboardHeight_Window(iWindow *d, int height) {
1216 if (d->keyboardHeight != height) { 1216 if (d->keyboardHeight != height) {
1217 d->keyboardHeight = height; 1217 d->keyboardHeight = height;
1218// if (height == 0) {
1219// setFlags_Anim(&d->rootOffset, easeBoth_AnimFlag, iTrue);
1220// setValue_Anim(&d->rootOffset, 0, 250);
1221// }
1222 postCommandf_App("keyboard.changed arg:%d", height); 1218 postCommandf_App("keyboard.changed arg:%d", height);
1223 postRefresh_App(); 1219 postRefresh_App();
1224 } 1220 }
diff --git a/src/ui/window.h b/src/ui/window.h
index a5b8f137..282e1682 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -86,6 +86,7 @@ struct Impl_Window {
86 iRoot * roots[2]; /* root widget and UI state; second one is for split mode */ 86 iRoot * roots[2]; /* root widget and UI state; second one is for split mode */
87 iRoot * keyRoot; /* root that has the current keyboard input focus */ 87 iRoot * keyRoot; /* root that has the current keyboard input focus */
88 iWidget * hover; 88 iWidget * hover;
89 iWidget * lastHover; /* cleared if deleted */
89 iWidget * mouseGrab; 90 iWidget * mouseGrab;
90 iWidget * focus; 91 iWidget * focus;
91 float pixelRatio; /* conversion between points and pixels, e.g., coords, window size */ 92 float pixelRatio; /* conversion between points and pixels, e.g., coords, window size */
@@ -98,7 +99,6 @@ struct Impl_Window {
98 SDL_Cursor * cursors[SDL_NUM_SYSTEM_CURSORS]; 99 SDL_Cursor * cursors[SDL_NUM_SYSTEM_CURSORS];
99 SDL_Cursor * pendingCursor; 100 SDL_Cursor * pendingCursor;
100 int loadAnimTimer; 101 int loadAnimTimer;
101// iAnim rootOffset;
102 int keyboardHeight; /* mobile software keyboards */ 102 int keyboardHeight; /* mobile software keyboards */
103}; 103};
104 104