Lagrange [work/v1.12]

iOS: Adjusted idle sleep; input fields; mobile UI layout

=> afd4e60c6a13a417964945396ebf252a4ba9b8ae

diff --git a/src/app.c b/src/app.c
index 50fd0db2..15c26736 100644
--- a/src/app.c
+++ b/src/app.c
@@ -140,6 +140,7 @@ struct Impl_App {
     iBool        isSuspended;
 #if defined (LAGRANGE_ENABLE_IDLE_SLEEP)
     iBool        isIdling;
+    unsigned int idleSleepDelayMs;
     uint32_t     lastEventTime;
     int          sleepTimer;
 #endif
@@ -1098,9 +1099,20 @@ static void init_App_(iApp *d, int argc, char **argv) {
     d->autoReloadTimer = SDL_AddTimer(60 * 1000, postAutoReloadCommand_App_, NULL);
     postCommand_Root(NULL, "document.autoreload");
 #if defined (LAGRANGE_ENABLE_IDLE_SLEEP)
-    d->isIdling      = iFalse;
-    d->lastEventTime = 0;
-    d->sleepTimer    = SDL_AddTimer(1000, checkAsleep_App_, d);
+    /* Initialize idle sleep. */ {
+        d->isIdling      = iFalse;
+        d->lastEventTime = 0;
+        d->sleepTimer    = SDL_AddTimer(1000, checkAsleep_App_, d);
+        SDL_DisplayMode dispMode;
+        SDL_GetWindowDisplayMode(d->window->base.win, &dispMode);
+        if (dispMode.refresh_rate) {
+            d->idleSleepDelayMs = 1000 / dispMode.refresh_rate;
+        }
+        else {
+            d->idleSleepDelayMs = 1000 / 60;
+        }
+        d->idleSleepDelayMs *= 0.9f;
+    }
 #endif
     d->isFinishedLaunching = iTrue;
     /* Run any commands that were pending completion of launch. */ {
@@ -1686,10 +1698,10 @@ void processEvents_App(enum iAppEventMode eventMode) {
     deinit_PtrArray(&windows);
 #if defined (LAGRANGE_ENABLE_IDLE_SLEEP)
     if (d->isIdling && !gotEvents) {
-        /* This is where we spend most of our time when idle. 30 Hz still quite a lot but we
-           can't wait too long after the user tries to interact again with the app. In any
-           case, on iOS SDL_WaitEvent() seems to use 10x more CPU time than sleeping (2.0.18). */
-        SDL_Delay(1000 / 30);
+        /* This is where we spend most of our time when idle. The sleep delay depends on the
+           display refresh rate. iOS SDL_WaitEvent() seems to use 10x more CPU time compared to
+           just sleeping (2.0.18). */
+        SDL_Delay(d->idleSleepDelayMs);
     }
 #endif
 backToMainLoop:;
diff --git a/src/ios.m b/src/ios.m
index eff970ef..6c64a854 100644
--- a/src/ios.m
+++ b/src/ios.m
@@ -168,6 +168,7 @@ API_AVAILABLE(ios(13.0))
     iString *fileBeingSaved;
     iString *pickFileCommand;
     iSystemTextInput *sysCtrl;
+    float sysCtrlLineSpacing;
 }
 @property (nonatomic, assign) BOOL isHapticsAvailable;
 @property (nonatomic, strong) NSObject *haptic;
@@ -183,23 +184,10 @@ static UIScrollView *statusBarTapper_; /* dummy scroll view just for getting not
     fileBeingSaved = NULL;
     pickFileCommand = NULL;
     sysCtrl = NULL;
+    sysCtrlLineSpacing = 0.0f;
     return self;
 }
 
--(void)setSystemTextInput:(iSystemTextInput *)sys {
-    sysCtrl = sys;
-}
-
--(iSystemTextInput *)systemTextInput {
-    return sysCtrl;
-}
-
-- (CGFloat)layoutManager:(NSLayoutManager *)layoutManager
-        lineSpacingAfterGlyphAtIndex:(NSUInteger)glyphIndex
-        withProposedLineFragmentRect:(CGRect)rect {
-    return lineHeight_Text(default_FontId) / get_MainWindow()->base.pixelRatio * 0.3f;
-}
-
 -(void)setPickFileCommand:(const char *)command {
     if (!pickFileCommand) {
         pickFileCommand = new_String();
@@ -262,6 +250,11 @@ didPickDocumentsAtURLs:(NSArray *)urls {
     }
 }
 
+- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
+    postCommand_App("scroll.top smooth:1");
+    return NO;
+}
+
 -(void)keyboardOnScreen:(NSNotification *)notification {
     NSDictionary *info   = notification.userInfo;
     NSValue      *value  = info[UIKeyboardFrameEndUserInfoKey];
@@ -295,6 +288,24 @@ static void sendReturnKeyPress_(void) {
     return NO;
 }
 
+-(void)setSystemTextInput:(iSystemTextInput *)sys {
+    sysCtrl = sys;
+}
+
+-(void)setSystemTextLineSpacing:(float)height {
+    sysCtrlLineSpacing = height;
+}
+
+-(iSystemTextInput *)systemTextInput {
+    return sysCtrl;
+}
+
+- (CGFloat)layoutManager:(NSLayoutManager *)layoutManager
+        lineSpacingAfterGlyphAtIndex:(NSUInteger)glyphIndex
+        withProposedLineFragmentRect:(CGRect)rect {
+    return sysCtrlLineSpacing / get_MainWindow()->base.pixelRatio;
+}
+
 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
 replacementString:(NSString *)string {
     iSystemTextInput *sysCtrl = [appState_ systemTextInput];
@@ -318,11 +329,6 @@ replacementString:(NSString *)string {
     notifyChange_SystemTextInput_(sysCtrl);
 }
 
-- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
-    postCommand_App("scroll.top smooth:1");
-    return NO;
-}
-
 @end
 
 /*----------------------------------------------------------------------------------------------*/
@@ -751,17 +757,17 @@ static CGRect convertToCGRect_(const iRect *rect, iBool expanded) {
     CGRect frame;
     // TODO: Convert coordinates properly!
     frame.origin.x = rect->pos.x / win->pixelRatio;
-    frame.origin.y = (rect->pos.y - gap_UI + 1) / win->pixelRatio;
+    frame.origin.y = (rect->pos.y - gap_UI * 0.875f) / win->pixelRatio;
     frame.size.width = rect->size.x / win->pixelRatio;
     frame.size.height = rect->size.y / win->pixelRatio;
     /* Some padding to account for insets. If we just zero out the insets, the insertion point
        may be clipped at the edges. */
+    const float inset = gap_UI / get_Window()->pixelRatio;
     if (expanded) {
-        const float inset = gap_UI / get_Window()->pixelRatio;
-        frame.origin.x -= inset + 1;
-        frame.origin.y -= inset / 2;
-        frame.size.width += 2 * inset + 3;
-        frame.size.height += inset + 1 + inset;
+        frame.origin.x -= 2 * inset;
+        frame.origin.y -= inset;
+        frame.size.width += 4 * inset;
+        frame.size.height += 2.5f * inset;
     }
     return frame;
 }
@@ -812,14 +818,16 @@ void init_SystemTextInput(iSystemTextInput *d, iRect rect, int flags) {
             [REF_d_view setTextAlignment:NSTextAlignmentRight];
         }
     }
-    UIColor *textColor = makeUIColor_(uiInputTextFocused_ColorId);
+    UIColor *textColor       = makeUIColor_(uiInputTextFocused_ColorId);
     UIColor *backgroundColor = makeUIColor_(uiInputBackgroundFocused_ColorId);
-    UIColor *tintColor = makeUIColor_(uiInputCursor_ColorId);
+    UIColor *tintColor       = makeUIColor_(uiInputCursor_ColorId);
     [appState_ setSystemTextInput:d];
+    const float inset = gap_UI / get_Window()->pixelRatio;
     if (d->field) {
         UITextField *field = REF_d_field;
         [field setTextColor:textColor];
         [field setTintColor:tintColor];
+//        [field setBackgroundColor:[UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:0.5f]];
         [field setDelegate:appState_];
         [field becomeFirstResponder];
     }
@@ -827,10 +835,14 @@ void init_SystemTextInput(iSystemTextInput *d, iRect rect, int flags) {
         UITextView *view = REF_d_view;
         [[view layoutManager] setDelegate:appState_];
         [view setBackgroundColor:[UIColor colorWithWhite:1.0f alpha:0.0f]];
+//        [view setBackgroundColor:[UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:0.5f]];
         [view setTextColor:textColor];
         [view setTintColor:tintColor];
         if (flags & extraPadding_SystemTextInputFlag) {
-            [view setContentInset:(UIEdgeInsets){ 0, 0, 3 * gap_UI / get_Window()->pixelRatio, 0}];
+            [view setContentInset:(UIEdgeInsets){ -inset * 0.125f, inset * 0.875f, 3 * inset, 0}];
+        }
+        else {
+            [view setContentInset:(UIEdgeInsets){ inset / 2, inset * 0.875f, -inset / 2, inset / 2 }];
         }
         [view setEditable:YES];
         [view setDelegate:appState_];
@@ -912,9 +924,11 @@ void setFont_SystemTextInput(iSystemTextInput *d, int fontId) {
 //            printf("fontname: %s\n", [name cStringUsingEncoding:NSUTF8StringEncoding]);
 //        }
         font = [UIFont fontWithName:@"Iosevka-Term-Extended" size:height * 0.82f];
+        [appState_ setSystemTextLineSpacing:0.0f];
     }
     else {
         font = [UIFont fontWithName:@"Roboto-Regular" size:height * 0.66f];
+        [appState_ setSystemTextLineSpacing:height * 0.66f];
     }
     if (d->field) {
         [REF_d_field setFont:font];
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c
index e2dbd5b8..7a627188 100644
--- a/src/ui/listwidget.c
+++ b/src/ui/listwidget.c
@@ -664,6 +664,7 @@ static void draw_ListWidget_(const iListWidget *d) {
         SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE);
     }
     unsetClip_Paint(&p);
+    drawBorders_Widget(w); /* background overdraws the normal borders */
     drawChildren_Widget(w);
 }
 
diff --git a/src/ui/mobile.c b/src/ui/mobile.c
index 1b5e6a63..dfa02422 100644
--- a/src/ui/mobile.c
+++ b/src/ui/mobile.c
@@ -749,6 +749,7 @@ void makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) {
         iListWidget *list = (iListWidget *) certList;
         setBackgroundColor_Widget(as_Widget(list), uiBackgroundSidebar_ColorId);
         widget = as_Widget(certList);
+        setFlags_Widget(widget, borderTop_WidgetFlag | borderBottom_WidgetFlag, iTrue);
         updateItems_CertListWidget(certList);
         invalidate_ListWidget(list);
     }
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c
index cb1c7c83..3286ad71 100644
--- a/src/ui/uploadwidget.c
+++ b/src/ui/uploadwidget.c
@@ -184,6 +184,7 @@ void init_UploadWidget(iUploadWidget *d) {
         const iMenuItem fileItems[] = {
             { "navi.action text:${dlg.upload.send}", 0, 0, "upload.accept" },
             { "title id:heading.upload.file" },
+            { "padding arg:0.667" },
             { "button text:" uiTextAction_ColorEscape "${dlg.upload.pickfile}", 0, 0, "upload.pickfile" },            
             { "heading id:upload.file.name" },
             { "label id:upload.filepathlabel text:\u2014" },
@@ -196,16 +197,16 @@ void init_UploadWidget(iUploadWidget *d) {
         };
         initPanels_Mobile(w, NULL, (iMenuItem[]){                                                  
             { "title id:heading.upload" },
+            { "heading id:upload.content" },
+            { "panel id:dlg.upload.text icon:0x1f5b9 noscroll:1", 0, 0, (const void *) textItems },
+            { "panel id:dlg.upload.file icon:0x1f4c1", 0, 0, (const void *) fileItems },
+            { "heading text:${heading.upload.id}" },
+            { "dropdown id:upload.id icon:0x1f464 text:", 0, 0, constData_Array(makeIdentityItems_UploadWidget_(d)) },
+            { "input id:upload.token hint:hint.upload.token.long icon:0x1f516 text:" },
             { "heading id:upload.url" },
             { format_CStr("label id:upload.info font:%d",
                           deviceType_App() == phone_AppDeviceType ? uiLabelBig_FontId : uiLabelMedium_FontId) },
             { "input id:upload.path hint:hint.upload.path noheading:1 url:1 text:" },
-            { "heading text:${heading.upload.id}" },
-            { "dropdown id:upload.id icon:0x1f464 text:", 0, 0, constData_Array(makeIdentityItems_UploadWidget_(d)) },
-            { "input id:upload.token hint:hint.upload.token.long icon:0x1f516 text:" },
-            { "heading id:upload.content" },
-            { "panel id:dlg.upload.text icon:0x1f5b9 noscroll:1", 0, 0, (const void *) textItems },
-            { "panel id:dlg.upload.file icon:0x1f4c1", 0, 0, (const void *) fileItems },
             { NULL }
         }, actions, iElemCount(actions) - 1 /* no Accept button on main panel */);
         d->info          = findChild_Widget(w, "upload.info");
diff --git a/src/ui/widget.c b/src/ui/widget.c
index 6ad6f8de..dbf992aa 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -1536,6 +1536,26 @@ void drawLayerEffects_Widget(const iWidget *d) {
 #endif
 }
 
+void drawBorders_Widget(const iWidget *d) {
+    if (d->flags & (borderTop_WidgetFlag | borderBottom_WidgetFlag)) {
+        const iRect rect = bounds_Widget(d);
+        iPaint p;
+        init_Paint(&p);
+        const int hgt = gap_UI / 4;
+        const int borderColor = uiSeparator_ColorId; /* TODO: Add a property to customize? */
+        if (d->flags & borderTop_WidgetFlag) {
+            fillRect_Paint(&p, (iRect){ topLeft_Rect(rect),
+                                        init_I2(width_Rect(rect), hgt) },
+                            borderColor);
+        }
+        if (d->flags & borderBottom_WidgetFlag) {
+            fillRect_Paint(&p, (iRect) { addY_I2(bottomLeft_Rect(rect), -hgt),
+                                         init_I2(width_Rect(rect), hgt) },
+                            borderColor);
+        }
+    }
+}
+
 void drawBackground_Widget(const iWidget *d) {
     if (d->flags & noBackground_WidgetFlag) {
         return;
@@ -1559,23 +1579,7 @@ void drawBackground_Widget(const iWidget *d) {
                                     gap_UI / 4, d->frameColor);
         }
     }
-    if (d->flags & (borderTop_WidgetFlag | borderBottom_WidgetFlag)) {
-        const iRect rect = bounds_Widget(d);
-        iPaint p;
-        init_Paint(&p);
-        const int hgt = gap_UI / 4;
-        const int borderColor = uiSeparator_ColorId; /* TODO: Add a property to customize? */
-        if (d->flags & borderTop_WidgetFlag) {
-            fillRect_Paint(&p, (iRect){ topLeft_Rect(rect),
-                                        init_I2(width_Rect(rect), hgt) },
-                            borderColor);
-        }
-        if (d->flags & borderBottom_WidgetFlag) {
-            fillRect_Paint(&p, (iRect) { addY_I2(bottomLeft_Rect(rect), -hgt),
-                                         init_I2(width_Rect(rect), hgt) },
-                            borderColor);
-        }
-    }
+    drawBorders_Widget(d);
 }
 
 int drawCount_;
diff --git a/src/ui/widget.h b/src/ui/widget.h
index 9d05d8db..1ea198ad 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -218,6 +218,7 @@ size_t  childCount_Widget               (const iWidget *);
 void    draw_Widget                     (const iWidget *);
 void    drawLayerEffects_Widget         (const iWidget *);
 void    drawBackground_Widget           (const iWidget *);
+void    drawBorders_Widget              (const iWidget *); /* called by `drawBackground` */
 void    drawChildren_Widget             (const iWidget *);
 void    drawRoot_Widget                 (const iWidget *); /* root only */
 void    setDrawBufferEnabled_Widget     (iWidget *, iBool enable);
Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/work%2Fv1.12/cdiff/afd4e60c6a13a417964945396ebf252a4ba9b8ae
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
68.625823 milliseconds
Gemini-to-HTML Time
0.542273 milliseconds

This content has been proxied by September (ba2dc).