summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/documentwidget.c37
-rw-r--r--src/ui/lookupwidget.c3
-rw-r--r--src/ui/root.c33
-rw-r--r--src/ui/root.h2
-rw-r--r--src/ui/text.c2
-rw-r--r--src/ui/util.c7
-rw-r--r--src/ui/widget.c32
-rw-r--r--src/ui/window.c6
8 files changed, 85 insertions, 37 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 8c24d4a9..f2553632 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -1107,12 +1107,11 @@ static void documentWasChanged_DocumentWidget_(iDocumentWidget *d) {
1107 1107
1108void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) { 1108void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) {
1109 setUrl_GmDocument(d->doc, d->mod.url); 1109 setUrl_GmDocument(d->doc, d->mod.url);
1110 const int docWidth = documentWidth_DocumentWidget_(d); 1110 const int docWidth = documentWidth_DocumentWidget_(d);
1111 const int outsideMargin = (width_Widget(d) - docWidth) / 2;
1112 setSource_GmDocument(d->doc, 1111 setSource_GmDocument(d->doc,
1113 source, 1112 source,
1114 docWidth, 1113 docWidth,
1115 outsideMargin, 1114 width_Widget(d),
1116 isFinished_GmRequest(d->request) ? final_GmDocumentUpdate 1115 isFinished_GmRequest(d->request) ? final_GmDocumentUpdate
1117 : partial_GmDocumentUpdate); 1116 : partial_GmDocumentUpdate);
1118 setWidth_Banner(d->banner, docWidth); 1117 setWidth_Banner(d->banner, docWidth);
@@ -1196,6 +1195,7 @@ static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode
1196// iBool useBanner = iTrue; 1195// iBool useBanner = iTrue;
1197 destroy_Widget(d->footerButtons); 1196 destroy_Widget(d->footerButtons);
1198 d->footerButtons = NULL; 1197 d->footerButtons = NULL;
1198 const iString *serverErrorMsg = NULL;
1199 if (meta) { 1199 if (meta) {
1200 switch (code) { 1200 switch (code) {
1201 case schemeChangeRedirect_GmStatusCode: 1201 case schemeChangeRedirect_GmStatusCode:
@@ -1254,12 +1254,13 @@ static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode
1254 "document.save" }); 1254 "document.save" });
1255 makeFooterButtons_DocumentWidget_(d, data_Array(&items), size_Array(&items)); 1255 makeFooterButtons_DocumentWidget_(d, data_Array(&items), size_Array(&items));
1256 deinit_Array(&items); 1256 deinit_Array(&items);
1257 serverErrorMsg = collectNewFormat_String("%s (%s)", msg->title, cstr_String(meta));
1257 break; 1258 break;
1258 } 1259 }
1259 default: 1260 default:
1260// if (!isEmpty_String(meta)) { 1261 if (!isEmpty_String(meta)) {
1261// appendFormat_String(src, "\n\n${error.server.msg}\n> %s", cstr_String(meta)); 1262 serverErrorMsg = meta;
1262// } 1263 }
1263 break; 1264 break;
1264 } 1265 }
1265 } 1266 }
@@ -1277,7 +1278,7 @@ static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode
1277 replaceDocument_DocumentWidget_(d, errorDoc); 1278 replaceDocument_DocumentWidget_(d, errorDoc);
1278 iRelease(errorDoc); 1279 iRelease(errorDoc);
1279 clear_Banner(d->banner); 1280 clear_Banner(d->banner);
1280 add_Banner(d->banner, error_BannerType, code, meta, NULL); 1281 add_Banner(d->banner, error_BannerType, code, serverErrorMsg, NULL);
1281 d->state = ready_RequestState; 1282 d->state = ready_RequestState;
1282 setSource_DocumentWidget(d, src); 1283 setSource_DocumentWidget(d, src);
1283 updateTheme_DocumentWidget_(d); 1284 updateTheme_DocumentWidget_(d);
@@ -2081,6 +2082,13 @@ static void inputQueryValidator_(iInputWidget *input, void *context) {
2081 arrange_Widget(findChild_Widget(dlg, "dialogbuttons")); 2082 arrange_Widget(findChild_Widget(dlg, "dialogbuttons"));
2082} 2083}
2083 2084
2085static const char *humanReadableStatusCode_(enum iGmStatusCode code) {
2086 if (code <= 0) {
2087 return "";
2088 }
2089 return format_CStr("%d ", code);
2090}
2091
2084static void checkResponse_DocumentWidget_(iDocumentWidget *d) { 2092static void checkResponse_DocumentWidget_(iDocumentWidget *d) {
2085 if (!d->request) { 2093 if (!d->request) {
2086 return; 2094 return;
@@ -2105,8 +2113,8 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) {
2105 init_Anim(&d->sideOpacity, 0); 2113 init_Anim(&d->sideOpacity, 0);
2106 init_Anim(&d->altTextOpacity, 0); 2114 init_Anim(&d->altTextOpacity, 0);
2107 format_String(&d->sourceHeader, 2115 format_String(&d->sourceHeader,
2108 "%d %s", 2116 "%s%s",
2109 statusCode, 2117 humanReadableStatusCode_(statusCode),
2110 isEmpty_String(&resp->meta) && !isSuccess_GmStatusCode(statusCode) 2118 isEmpty_String(&resp->meta) && !isSuccess_GmStatusCode(statusCode)
2111 ? get_GmError(statusCode)->title 2119 ? get_GmError(statusCode)->title
2112 : cstr_String(&resp->meta)); 2120 : cstr_String(&resp->meta));
@@ -2835,9 +2843,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2835 const char *unchecked = red_ColorEscape "\u2610"; 2843 const char *unchecked = red_ColorEscape "\u2610";
2836 const char *checked = green_ColorEscape "\u2611"; 2844 const char *checked = green_ColorEscape "\u2611";
2837 const iBool haveFingerprint = (d->certFlags & haveFingerprint_GmCertFlag) != 0; 2845 const iBool haveFingerprint = (d->certFlags & haveFingerprint_GmCertFlag) != 0;
2838 const iBool canTrust = 2846 const int requiredForTrust = (available_GmCertFlag | haveFingerprint_GmCertFlag |
2839 (d->certFlags == (available_GmCertFlag | haveFingerprint_GmCertFlag | 2847 timeVerified_GmCertFlag);
2840 timeVerified_GmCertFlag | domainVerified_GmCertFlag)); 2848 const iBool canTrust = ~d->certFlags & trusted_GmCertFlag &&
2849 ((d->certFlags & requiredForTrust) == requiredForTrust);
2841 const iRecentUrl *recent = findUrl_History(d->mod.history, d->mod.url); 2850 const iRecentUrl *recent = findUrl_History(d->mod.history, d->mod.url);
2842 const iString *meta = &d->sourceMime; 2851 const iString *meta = &d->sourceMime;
2843 if (recent && recent->cachedResponse) { 2852 if (recent && recent->cachedResponse) {
@@ -3030,8 +3039,8 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
3030 if (!isSuccess_GmStatusCode(status_GmRequest(d->request))) { 3039 if (!isSuccess_GmStatusCode(status_GmRequest(d->request))) {
3031 /* TODO: Why is this here? Can it be removed? */ 3040 /* TODO: Why is this here? Can it be removed? */
3032 format_String(&d->sourceHeader, 3041 format_String(&d->sourceHeader,
3033 "%d %s", 3042 "%s%s",
3034 status_GmRequest(d->request), 3043 humanReadableStatusCode_(status_GmRequest(d->request)),
3035 cstr_String(meta_GmRequest(d->request))); 3044 cstr_String(meta_GmRequest(d->request)));
3036 } 3045 }
3037 updateFetchProgress_DocumentWidget_(d); 3046 updateFetchProgress_DocumentWidget_(d);
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c
index e57a5fdc..da0113ce 100644
--- a/src/ui/lookupwidget.c
+++ b/src/ui/lookupwidget.c
@@ -665,8 +665,9 @@ static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) {
665 (bottom_Rect(rect_Root(root)) - bottom_Rect(navBarBounds)) / 2)); 665 (bottom_Rect(rect_Root(root)) - bottom_Rect(navBarBounds)) / 2));
666 setPos_Widget(w, windowToLocal_Widget(w, bottomLeft_Rect(bounds_Widget(url)))); 666 setPos_Widget(w, windowToLocal_Widget(w, bottomLeft_Rect(bounds_Widget(url))));
667#if defined (iPlatformAppleMobile) 667#if defined (iPlatformAppleMobile)
668 /* TODO: Check this again. */
668 /* Adjust height based on keyboard size. */ { 669 /* Adjust height based on keyboard size. */ {
669 w->rect.size.y = visibleSize_Root(root).y - top_Rect(bounds_Widget(w)); 670 w->rect.size.y = bottom_Rect(visibleRect_Root(root)) - top_Rect(bounds_Widget(w));
670 if (deviceType_App() == phone_AppDeviceType) { 671 if (deviceType_App() == phone_AppDeviceType) {
671 float l, r; 672 float l, r;
672 safeAreaInsets_iOS(&l, NULL, &r, NULL); 673 safeAreaInsets_iOS(&l, NULL, &r, NULL);
diff --git a/src/ui/root.c b/src/ui/root.c
index 114ab040..4849d0c7 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -1532,6 +1532,35 @@ iRect safeRect_Root(const iRoot *d) {
1532 return rect; 1532 return rect;
1533} 1533}
1534 1534
1535iInt2 visibleSize_Root(const iRoot *d) { 1535iRect visibleRect_Root(const iRoot *d) {
1536 return addY_I2(size_Root(d), -get_MainWindow()->keyboardHeight); 1536 iRect visRect = rect_Root(d);
1537#if defined (iPlatformAppleMobile)
1538 /* TODO: Check this on device... Maybe DisplayUsableBounds would be good here, too? */
1539 float left, top, right, bottom;
1540 safeAreaInsets_iOS(&left, &top, &right, &bottom);
1541 visRect.pos.x = (int) left;
1542 visRect.size.x -= (int) (left + right);
1543 visRect.pos.y = (int) top;
1544 visRect.size.y -= (int) (top + bottom);
1545#endif
1546#if defined (iPlatformDesktop)
1547 /* Apply the usable bounds of the display. */
1548 SDL_Rect usable; {
1549 const float ratio = d->window->pixelRatio;
1550 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->window->win), &usable);
1551 iInt2 winPos;
1552 SDL_GetWindowPosition(d->window->win, &winPos.x, &winPos.y);
1553 mulfv_I2(&winPos, ratio);
1554 usable.x *= ratio;
1555 usable.y *= ratio;
1556 usable.w *= ratio;
1557 usable.h *= ratio;
1558 /* Make it relative to the window. */
1559 usable.x -= winPos.x;
1560 usable.y -= winPos.y;
1561 visRect = intersect_Rect(visRect, init_Rect(usable.x, usable.y, usable.w, usable.h));
1562 }
1563#endif
1564 adjustEdges_Rect(&visRect, 0, 0, -get_MainWindow()->keyboardHeight, 0);
1565 return visRect;
1537} 1566}
diff --git a/src/ui/root.h b/src/ui/root.h
index 04dd5e16..851d927d 100644
--- a/src/ui/root.h
+++ b/src/ui/root.h
@@ -40,6 +40,6 @@ void updateToolbarColors_Root (iRoot *);
40iInt2 size_Root (const iRoot *); 40iInt2 size_Root (const iRoot *);
41iRect rect_Root (const iRoot *); 41iRect rect_Root (const iRoot *);
42iRect safeRect_Root (const iRoot *); 42iRect safeRect_Root (const iRoot *);
43iInt2 visibleSize_Root (const iRoot *); /* may be obstructed by software keyboard */ 43iRect visibleRect_Root (const iRoot *); /* may be obstructed by software keyboard */
44iBool isNarrow_Root (const iRoot *); 44iBool isNarrow_Root (const iRoot *);
45int appIconSize_Root (void); 45int appIconSize_Root (void);
diff --git a/src/ui/text.c b/src/ui/text.c
index 3805c666..91633f27 100644
--- a/src/ui/text.c
+++ b/src/ui/text.c
@@ -338,7 +338,7 @@ static void initFonts_Text_(iText *d) {
338 } 338 }
339 } 339 }
340#if !defined (NDEBUG) 340#if !defined (NDEBUG)
341 printf("[Text] %zu fonts ready\n", size_Array(&d->fonts)); 341 printf("[Text] %zu font variants ready\n", size_Array(&d->fonts));
342#endif 342#endif
343 gap_Text = iRound(gap_UI * d->contentFontSize); 343 gap_Text = iRound(gap_UI * d->contentFontSize);
344} 344}
diff --git a/src/ui/util.c b/src/ui/util.c
index 5a58551b..88348ff8 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -1038,7 +1038,7 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) {
1038 iRect displayRect = zero_Rect(); 1038 iRect displayRect = zero_Rect();
1039 for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) { 1039 for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
1040 SDL_Rect dispBounds; 1040 SDL_Rect dispBounds;
1041 SDL_GetDisplayBounds(i, &dispBounds); 1041 SDL_GetDisplayUsableBounds(i, &dispBounds);
1042 displayRect = union_Rect( 1042 displayRect = union_Rect(
1043 displayRect, init_Rect(dispBounds.x, dispBounds.y, dispBounds.w, dispBounds.h)); 1043 displayRect, init_Rect(dispBounds.x, dispBounds.y, dispBounds.w, dispBounds.h));
1044 } 1044 }
@@ -1070,7 +1070,7 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) {
1070 iInt2 menuPos = add_I2(winPos, 1070 iInt2 menuPos = add_I2(winPos,
1071 divf_I2(sub_I2(windowCoord, divi_I2(gap2_UI, 2)), pixelRatio)); 1071 divf_I2(sub_I2(windowCoord, divi_I2(gap2_UI, 2)), pixelRatio));
1072 /* Check display bounds. */ { 1072 /* Check display bounds. */ {
1073 const iInt2 menuSize = divf_I2(d->rect.size, pixelRatio); 1073 iInt2 menuSize = divf_I2(d->rect.size, pixelRatio);
1074 if (menuOpenFlags & center_MenuOpenFlags) { 1074 if (menuOpenFlags & center_MenuOpenFlags) {
1075 iInt2 winSize; 1075 iInt2 winSize;
1076 SDL_GetWindowSize(sdlWin, &winSize.x, &winSize.y); 1076 SDL_GetWindowSize(sdlWin, &winSize.x, &winSize.y);
@@ -2199,7 +2199,8 @@ iWidget *makeDialog_Widget(const char *id,
2199 2199
2200iWidget *makePreferences_Widget(void) { 2200iWidget *makePreferences_Widget(void) {
2201 /* Common items. */ 2201 /* Common items. */
2202 const iMenuItem langItems[] = { { "${lang.de} - de", 0, 0, "uilang id:de" }, 2202 const iMenuItem langItems[] = { { "${lang.cs} - cs", 0, 0, "uilang id:cs" },
2203 { "${lang.de} - de", 0, 0, "uilang id:de" },
2203 { "${lang.en} - en", 0, 0, "uilang id:en" }, 2204 { "${lang.en} - en", 0, 0, "uilang id:en" },
2204 { "${lang.es} - es", 0, 0, "uilang id:es" }, 2205 { "${lang.es} - es", 0, 0, "uilang id:es" },
2205 { "${lang.es.mx} - es", 0, 0, "uilang id:es_MX" }, 2206 { "${lang.es.mx} - es", 0, 0, "uilang id:es_MX" },
diff --git a/src/ui/widget.c b/src/ui/widget.c
index b509cbe2..1ab16b4f 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -1142,11 +1142,9 @@ static iBool isOverflowScrollPossible_Widget_(const iWidget *d, int delta) {
1142 return iFalse; 1142 return iFalse;
1143 } 1143 }
1144 iRect bounds = boundsWithoutVisualOffset_Widget(d); 1144 iRect bounds = boundsWithoutVisualOffset_Widget(d);
1145 const iRect winRect = adjusted_Rect(safeRect_Root(d->root), 1145 const iRect winRect = visibleRect_Root(d->root);
1146 zero_I2(), 1146 const int yTop = top_Rect(winRect);
1147 init_I2(0, -get_MainWindow()->keyboardHeight)); 1147 const int yBottom = bottom_Rect(winRect);
1148 const int yTop = top_Rect(winRect);
1149 const int yBottom = bottom_Rect(winRect);
1150 if (delta == 0) { 1148 if (delta == 0) {
1151 if (top_Rect(bounds) >= yTop && bottom_Rect(bounds) <= yBottom) { 1149 if (top_Rect(bounds) >= yTop && bottom_Rect(bounds) <= yBottom) {
1152 return iFalse; /* fits inside just fine */ 1150 return iFalse; /* fits inside just fine */
@@ -1162,11 +1160,9 @@ iBool scrollOverflow_Widget(iWidget *d, int delta) {
1162 if (!isOverflowScrollPossible_Widget_(d, delta)) { 1160 if (!isOverflowScrollPossible_Widget_(d, delta)) {
1163 return iFalse; 1161 return iFalse;
1164 } 1162 }
1165 iRect bounds = boundsWithoutVisualOffset_Widget(d); 1163 iRect bounds = boundsWithoutVisualOffset_Widget(d);
1166 const iRect winRect = adjusted_Rect(safeRect_Root(d->root), 1164 const iRect winRect = visibleRect_Root(d->root);
1167 zero_I2(), 1165 iRangei validPosRange = { bottom_Rect(winRect) - height_Rect(bounds), top_Rect(winRect) };
1168 init_I2(0, -get_MainWindow()->keyboardHeight));
1169 iRangei validPosRange = { bottom_Rect(winRect) - height_Rect(bounds), top_Rect(winRect) };
1170 if (validPosRange.start > validPosRange.end) { 1166 if (validPosRange.start > validPosRange.end) {
1171 validPosRange.start = validPosRange.end; /* no room to scroll */ 1167 validPosRange.start = validPosRange.end; /* no room to scroll */
1172 } 1168 }
@@ -1244,18 +1240,26 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) {
1244 /* TODO: Motion events occur frequently. Maybe it would help if these were handled 1240 /* TODO: Motion events occur frequently. Maybe it would help if these were handled
1245 via audiences that specifically register to listen for motion, to minimize the 1241 via audiences that specifically register to listen for motion, to minimize the
1246 number of widgets that need to process them. */ 1242 number of widgets that need to process them. */
1247 const int hoverScrollLimit = 2 * lineHeight_Text(default_FontId); 1243 const int hoverScrollLimit = 1.5f * lineHeight_Text(default_FontId);
1248 float speed = 0.0f; 1244 float speed = 0.0f;
1249 if (ev->motion.y < hoverScrollLimit) { 1245 if (ev->motion.y < hoverScrollLimit) {
1250 speed = (hoverScrollLimit - ev->motion.y) / (float) hoverScrollLimit; 1246 speed = (hoverScrollLimit - ev->motion.y) / (float) hoverScrollLimit;
1251 } 1247 }
1252 else { 1248 else {
1253 const int bottomLimit = bottom_Rect(rect_Root(d->root)) - hoverScrollLimit; 1249 const iWindow *win = window_Widget(d);
1254 if (ev->motion.y > bottomLimit ) { 1250 SDL_Rect usable;
1251 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(win->win),
1252 &usable);
1253 const int bottomLimit =
1254 iMin(bottom_Rect(rect_Root(d->root)), usable.h * win->pixelRatio) -
1255 hoverScrollLimit;
1256 if (ev->motion.y > bottomLimit) {
1255 speed = -(ev->motion.y - bottomLimit) / (float) hoverScrollLimit; 1257 speed = -(ev->motion.y - bottomLimit) / (float) hoverScrollLimit;
1256 } 1258 }
1257 } 1259 }
1258 if (speed != 0.0f && isOverflowScrollPossible_Widget_(d, speed > 0 ? 1 : -1)) { 1260 const int dir = speed > 0 ? 1 : -1;
1261 if (speed != 0.0f && isOverflowScrollPossible_Widget_(d, dir)) {
1262// speed = dir * powf(speed, 1.5f);
1259 const uint32_t nowTime = SDL_GetTicks(); 1263 const uint32_t nowTime = SDL_GetTicks();
1260 uint32_t elapsed = nowTime - lastHoverOverflowMotionTime_; 1264 uint32_t elapsed = nowTime - lastHoverOverflowMotionTime_;
1261 if (elapsed > 100) { 1265 if (elapsed > 100) {
diff --git a/src/ui/window.c b/src/ui/window.c
index 8016e8ef..2f6fe430 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1676,9 +1676,13 @@ iWindow *newPopup_Window(iInt2 screenPos, iWidget *rootWidget) {
1676#if !defined (iPlatformApple) 1676#if !defined (iPlatformApple)
1677 setForceSoftwareRender_App(iTrue); 1677 setForceSoftwareRender_App(iTrue);
1678#endif 1678#endif
1679 SDL_Rect usableRect;
1680 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(get_MainWindow()->base.win),
1681 &usableRect);
1679 iWindow *win = 1682 iWindow *win =
1680 new_Window(popup_WindowType, 1683 new_Window(popup_WindowType,
1681 (iRect){ screenPos, divf_I2(rootWidget->rect.size, get_Window()->pixelRatio) }, 1684 (iRect){ screenPos, min_I2(divf_I2(rootWidget->rect.size, get_Window()->pixelRatio),
1685 init_I2(usableRect.w, usableRect.h)) },
1682 SDL_WINDOW_ALWAYS_ON_TOP | 1686 SDL_WINDOW_ALWAYS_ON_TOP |
1683#if !defined (iPlatformAppleDesktop) 1687#if !defined (iPlatformAppleDesktop)
1684 SDL_WINDOW_BORDERLESS | 1688 SDL_WINDOW_BORDERLESS |