diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-09-12 21:00:44 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-09-12 21:00:44 +0300 |
commit | 0e7060d5306fef1f585982cc78223250d3ee8551 (patch) | |
tree | d21bb496f85cd275707db85ebac17e7e5f2a9adf /src/ui/widget.c | |
parent | 12262e7642489f1764018ef23b4913c203ddd9ab (diff) |
Mobile: Better Settings tap targets; fixed safe area drawing
Diffstat (limited to 'src/ui/widget.c')
-rw-r--r-- | src/ui/widget.c | 75 |
1 files changed, 64 insertions, 11 deletions
diff --git a/src/ui/widget.c b/src/ui/widget.c index 7665c5bc..0765bf9f 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -89,7 +89,7 @@ static void release_WidgetDrawBuffer(iWidgetDrawBuffer *d) { | |||
89 | static iRect boundsForDraw_Widget_(const iWidget *d) { | 89 | static iRect boundsForDraw_Widget_(const iWidget *d) { |
90 | iRect bounds = bounds_Widget(d); | 90 | iRect bounds = bounds_Widget(d); |
91 | if (d->flags & drawBackgroundToBottom_WidgetFlag) { | 91 | if (d->flags & drawBackgroundToBottom_WidgetFlag) { |
92 | bounds.size.y = iMaxi(bounds.size.y, size_Root(d->root).y - top_Rect(bounds)); | 92 | bounds.size.y = iMax(bounds.size.y, size_Root(d->root).y); |
93 | } | 93 | } |
94 | return bounds; | 94 | return bounds; |
95 | } | 95 | } |
@@ -1218,7 +1218,7 @@ iLocalDef iBool isDrawn_Widget_(const iWidget *d) { | |||
1218 | return ~d->flags & hidden_WidgetFlag || d->flags & visualOffset_WidgetFlag; | 1218 | return ~d->flags & hidden_WidgetFlag || d->flags & visualOffset_WidgetFlag; |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | static void drawLayerEffects_Widget_(const iWidget *d) { | 1221 | void drawLayerEffects_Widget(const iWidget *d) { |
1222 | /* Layered effects are not buffered, so they are drawn here separately. */ | 1222 | /* Layered effects are not buffered, so they are drawn here separately. */ |
1223 | iAssert(isDrawn_Widget_(d)); | 1223 | iAssert(isDrawn_Widget_(d)); |
1224 | iBool shadowBorder = (d->flags & keepOnTop_WidgetFlag && ~d->flags & mouseModal_WidgetFlag) != 0; | 1224 | iBool shadowBorder = (d->flags & keepOnTop_WidgetFlag && ~d->flags & mouseModal_WidgetFlag) != 0; |
@@ -1248,6 +1248,48 @@ static void drawLayerEffects_Widget_(const iWidget *d) { | |||
1248 | fillRect_Paint(&p, rect_Root(d->root), backgroundFadeColor_Widget()); | 1248 | fillRect_Paint(&p, rect_Root(d->root), backgroundFadeColor_Widget()); |
1249 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); | 1249 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); |
1250 | } | 1250 | } |
1251 | #if defined (iPlatformAppleMobile) | ||
1252 | if (d->bgColor >= 0 && d->flags & (drawBackgroundToHorizontalSafeArea_WidgetFlag | | ||
1253 | drawBackgroundToVerticalSafeArea_WidgetFlag)) { | ||
1254 | iPaint p; | ||
1255 | init_Paint(&p); | ||
1256 | const iRect rect = bounds_Widget(d); | ||
1257 | const iInt2 rootSize = size_Root(d->root); | ||
1258 | const iInt2 center = divi_I2(rootSize, 2); | ||
1259 | int top = 0, right = 0, bottom = 0, left = 0; | ||
1260 | if (d->flags & drawBackgroundToHorizontalSafeArea_WidgetFlag) { | ||
1261 | const iBool isWide = width_Rect(rect) > rootSize.x * 9 / 10; | ||
1262 | if (isWide || mid_Rect(rect).x < center.x) { | ||
1263 | left = -left_Rect(rect); | ||
1264 | } | ||
1265 | if (isWide || mid_Rect(rect).x > center.x) { | ||
1266 | right = rootSize.x - right_Rect(rect); | ||
1267 | } | ||
1268 | } | ||
1269 | if (d->flags & drawBackgroundToVerticalSafeArea_WidgetFlag) { | ||
1270 | if (top_Rect(rect) > center.y) { | ||
1271 | bottom = rootSize.y - bottom_Rect(rect); | ||
1272 | } | ||
1273 | if (bottom_Rect(rect) < center.y) { | ||
1274 | top = -top_Rect(rect); | ||
1275 | } | ||
1276 | } | ||
1277 | if (top < 0) { | ||
1278 | fillRect_Paint(&p, (iRect){ init_I2(left_Rect(rect), 0), | ||
1279 | init_I2(width_Rect(rect), top_Rect(rect)) }, | ||
1280 | d->bgColor); | ||
1281 | } | ||
1282 | if (left < 0) { | ||
1283 | fillRect_Paint(&p, (iRect){ init_I2(0, top_Rect(rect)), | ||
1284 | init_I2(left_Rect(rect), height_Rect(rect)) }, d->bgColor); | ||
1285 | } | ||
1286 | if (right > 0) { | ||
1287 | fillRect_Paint(&p, (iRect){ init_I2(right_Rect(rect), top_Rect(rect)), | ||
1288 | init_I2(right, height_Rect(rect)) }, d->bgColor); | ||
1289 | } | ||
1290 | // adjustEdges_Rect(&rect, iMin(0, top), iMax(0, right), iMax(0, bottom), iMin(0, left)); | ||
1291 | } | ||
1292 | #endif | ||
1251 | } | 1293 | } |
1252 | 1294 | ||
1253 | void drawBackground_Widget(const iWidget *d) { | 1295 | void drawBackground_Widget(const iWidget *d) { |
@@ -1261,12 +1303,13 @@ void drawBackground_Widget(const iWidget *d) { | |||
1261 | if (d->bgColor >= 0 || d->frameColor >= 0) { | 1303 | if (d->bgColor >= 0 || d->frameColor >= 0) { |
1262 | iRect rect = bounds_Widget(d); | 1304 | iRect rect = bounds_Widget(d); |
1263 | if (d->flags & drawBackgroundToBottom_WidgetFlag) { | 1305 | if (d->flags & drawBackgroundToBottom_WidgetFlag) { |
1264 | rect.size.y = iMax(rect.size.y, size_Root(d->root).y - top_Rect(rect)); | 1306 | rect.size.y += size_Root(d->root).y; // = iMax(rect.size.y, size_Root(d->root).y - top_Rect(rect)); |
1265 | } | 1307 | } |
1266 | iPaint p; | 1308 | iPaint p; |
1267 | init_Paint(&p); | 1309 | init_Paint(&p); |
1268 | if (d->bgColor >= 0) { | 1310 | if (d->bgColor >= 0) { |
1269 | #if defined (iPlatformAppleMobile) | 1311 | #if 0 && defined (iPlatformAppleMobile) |
1312 | /* TODO: This is part of the unbuffered draw (layer effects). */ | ||
1270 | if (d->flags & (drawBackgroundToHorizontalSafeArea_WidgetFlag | | 1313 | if (d->flags & (drawBackgroundToHorizontalSafeArea_WidgetFlag | |
1271 | drawBackgroundToVerticalSafeArea_WidgetFlag)) { | 1314 | drawBackgroundToVerticalSafeArea_WidgetFlag)) { |
1272 | const iInt2 rootSize = size_Root(d->root); | 1315 | const iInt2 rootSize = size_Root(d->root); |
@@ -1289,7 +1332,7 @@ void drawBackground_Widget(const iWidget *d) { | |||
1289 | top = -top_Rect(rect); | 1332 | top = -top_Rect(rect); |
1290 | } | 1333 | } |
1291 | } | 1334 | } |
1292 | adjustEdges_Rect(&rect, top, right, bottom, left); | 1335 | adjustEdges_Rect(&rect, iMin(0, top), iMax(0, right), iMax(0, bottom), iMin(0, left)); |
1293 | } | 1336 | } |
1294 | #endif | 1337 | #endif |
1295 | fillRect_Paint(&p, rect, d->bgColor); | 1338 | fillRect_Paint(&p, rect, d->bgColor); |
@@ -1339,7 +1382,7 @@ static void addToPotentiallyVisible_Widget_(const iWidget *d, iPtrArray *pvs, iR | |||
1339 | if (isDrawn_Widget_(d)) { | 1382 | if (isDrawn_Widget_(d)) { |
1340 | iRect bounds = bounds_Widget(d); | 1383 | iRect bounds = bounds_Widget(d); |
1341 | if (d->flags & drawBackgroundToBottom_WidgetFlag) { | 1384 | if (d->flags & drawBackgroundToBottom_WidgetFlag) { |
1342 | bounds.size.y = size_Root(d->root).y - top_Rect(bounds); | 1385 | bounds.size.y += size_Root(d->root).y; // iMax(bounds.size.y, size_Root(d->root).y - top_Rect(bounds)); |
1343 | } | 1386 | } |
1344 | if (isFullyContainedByOther_Rect(bounds, *fullyMasked)) { | 1387 | if (isFullyContainedByOther_Rect(bounds, *fullyMasked)) { |
1345 | return; /* can't be seen */ | 1388 | return; /* can't be seen */ |
@@ -1411,14 +1454,21 @@ void setDrawBufferEnabled_Widget(iWidget *d, iBool enable) { | |||
1411 | 1454 | ||
1412 | static void beginBufferDraw_Widget_(const iWidget *d) { | 1455 | static void beginBufferDraw_Widget_(const iWidget *d) { |
1413 | if (d->drawBuf) { | 1456 | if (d->drawBuf) { |
1414 | // printf("[%p] drawbuffer update %d\n", d, d->drawBuf->isValid); | 1457 | printf("[%p] drawbuffer update %d\n", d, d->drawBuf->isValid); |
1458 | if (d->drawBuf->isValid) { | ||
1459 | iAssert(!isEqual_I2(d->drawBuf->size, boundsForDraw_Widget_(d).size)); | ||
1460 | // printf(" drawBuf:%dx%d boundsForDraw:%dx%d\n", | ||
1461 | // d->drawBuf->size.x, d->drawBuf->size.y, | ||
1462 | // boundsForDraw_Widget_(d).size.x, | ||
1463 | // boundsForDraw_Widget_(d).size.y); | ||
1464 | } | ||
1415 | const iRect bounds = bounds_Widget(d); | 1465 | const iRect bounds = bounds_Widget(d); |
1416 | SDL_Renderer *render = renderer_Window(get_Window()); | 1466 | SDL_Renderer *render = renderer_Window(get_Window()); |
1417 | d->drawBuf->oldTarget = SDL_GetRenderTarget(render); | 1467 | d->drawBuf->oldTarget = SDL_GetRenderTarget(render); |
1418 | d->drawBuf->oldOrigin = origin_Paint; | 1468 | d->drawBuf->oldOrigin = origin_Paint; |
1419 | realloc_WidgetDrawBuffer(d->drawBuf, render, boundsForDraw_Widget_(d).size); | 1469 | realloc_WidgetDrawBuffer(d->drawBuf, render, boundsForDraw_Widget_(d).size); |
1420 | SDL_SetRenderTarget(render, d->drawBuf->texture); | 1470 | SDL_SetRenderTarget(render, d->drawBuf->texture); |
1421 | //SDL_SetRenderDrawColor(render, 255, 0, 0, 128); | 1471 | // SDL_SetRenderDrawColor(render, 255, 0, 0, 128); |
1422 | SDL_SetRenderDrawColor(render, 0, 0, 0, 0); | 1472 | SDL_SetRenderDrawColor(render, 0, 0, 0, 0); |
1423 | SDL_RenderClear(render); | 1473 | SDL_RenderClear(render); |
1424 | origin_Paint = neg_I2(bounds.pos); /* with current visual offset */ | 1474 | origin_Paint = neg_I2(bounds.pos); /* with current visual offset */ |
@@ -1445,7 +1495,7 @@ void draw_Widget(const iWidget *d) { | |||
1445 | } | 1495 | } |
1446 | return; | 1496 | return; |
1447 | } | 1497 | } |
1448 | drawLayerEffects_Widget_(d); | 1498 | drawLayerEffects_Widget(d); |
1449 | if (!d->drawBuf || !checkDrawBuffer_Widget_(d)) { | 1499 | if (!d->drawBuf || !checkDrawBuffer_Widget_(d)) { |
1450 | beginBufferDraw_Widget_(d); | 1500 | beginBufferDraw_Widget_(d); |
1451 | drawBackground_Widget(d); | 1501 | drawBackground_Widget(d); |
@@ -1755,7 +1805,9 @@ iWidget *focus_Widget(void) { | |||
1755 | } | 1805 | } |
1756 | 1806 | ||
1757 | void setHover_Widget(iWidget *d) { | 1807 | void setHover_Widget(iWidget *d) { |
1758 | get_Window()->hover = d; | 1808 | iWindow *win = get_Window(); |
1809 | iAssert(win); | ||
1810 | win->hover = d; | ||
1759 | } | 1811 | } |
1760 | 1812 | ||
1761 | iWidget *hover_Widget(void) { | 1813 | iWidget *hover_Widget(void) { |
@@ -1850,7 +1902,8 @@ void postCommand_Widget(const iAnyObject *d, const char *cmd, ...) { | |||
1850 | deinit_String(&str); | 1902 | deinit_String(&str); |
1851 | } | 1903 | } |
1852 | 1904 | ||
1853 | void refresh_Widget(const iAnyObject *d) { | 1905 | void refresh_Widget(const iAnyObject *d) { |
1906 | if (!d) return; | ||
1854 | /* TODO: Could be widget specific, if parts of the tree are cached. */ | 1907 | /* TODO: Could be widget specific, if parts of the tree are cached. */ |
1855 | /* TODO: The visbuffer in DocumentWidget and ListWidget could be moved to be a general | 1908 | /* TODO: The visbuffer in DocumentWidget and ListWidget could be moved to be a general |
1856 | purpose feature of Widget. */ | 1909 | purpose feature of Widget. */ |