Lagrange [release]

Added a second sidebar; removed hover outline

=> c8089179f84a2cabd84a47a800aaadd9af8bd9b8

diff --git a/src/app.c b/src/app.c
index b799b627..cf8a7119 100644
--- a/src/app.c
+++ b/src/app.c
@@ -139,7 +139,8 @@ const iString *dateStr_(const iDate *date) {
 
 static iString *serializePrefs_App_(const iApp *d) {
     iString *str = new_String();
-    const iSidebarWidget *sidebar = findWidget_App("sidebar");
+    const iSidebarWidget *sidebar  = findWidget_App("sidebar");
+    const iSidebarWidget *sidebar2 = findWidget_App("sidebar2");
     appendFormat_String(str, "window.retain arg:%d\n", d->prefs.retainWindowSize);
     if (d->prefs.retainWindowSize) {
         const iBool isMaximized = (SDL_GetWindowFlags(d->window->win) & SDL_WINDOW_MAXIMIZED) != 0;
@@ -150,6 +151,7 @@ static iString *serializePrefs_App_(const iApp *d) {
         h = d->window->lastRect.size.y;
         appendFormat_String(str, "window.setrect width:%d height:%d coord:%d %d\n", w, h, x, y);
         appendFormat_String(str, "sidebar.width arg:%d\n", width_SidebarWidget(sidebar));
+        appendFormat_String(str, "sidebar2.width arg:%d\n", width_SidebarWidget(sidebar2));
         /* On macOS, maximization should be applied at creation time or the window will take
            a moment to animate to its maximized size. */
 #if !defined (iPlatformApple)
@@ -160,10 +162,16 @@ static iString *serializePrefs_App_(const iApp *d) {
         iUnused(isMaximized);
 #endif
     }
-    if (isVisible_Widget(sidebar)) {
-        appendCStr_String(str, "sidebar.toggle\n");
+    /* Sidebars. */ {
+        if (isVisible_Widget(sidebar)) {
+            appendCStr_String(str, "sidebar.toggle\n");
+        }
+        appendFormat_String(str, "sidebar.mode arg:%d\n", mode_SidebarWidget(sidebar));
+        if (isVisible_Widget(sidebar2)) {
+            appendCStr_String(str, "sidebar2.toggle\n");
+        }
+        appendFormat_String(str, "sidebar2.mode arg:%d\n", mode_SidebarWidget(sidebar2));
     }
-    appendFormat_String(str, "sidebar.mode arg:%d\n", mode_SidebarWidget(sidebar));
     appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window));
     appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab);
     appendFormat_String(str, "font.set arg:%d\n", d->prefs.font);
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index a6cc8187..0d931080 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -2909,6 +2909,7 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
                             iMax(0, scrollMax_DocumentWidget_(d) - value_Anim(&d->scrollY)))),
             tmQuoteIcon_ColorId);
     }
+#if 0
     /* Outline on the right side. */
     const float outlineOpacity = value_Anim(&d->outlineOpacity);
     if (prefs_App()->hoverOutline && !isEmpty_Array(&d->outline) && outlineOpacity > 0.0f) {
@@ -2964,8 +2965,9 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
         setOpacity_Text(1.0f);
         SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE);
     }
+#endif
     unsetClip_Paint(&p);
-    }
+}
 
 static void drawPlayers_DocumentWidget_(const iDocumentWidget *d, iPaint *p) {
     iConstForEach(PtrArray, i, &d->visiblePlayers) {
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 5baa08f7..121e9a7c 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -84,7 +84,9 @@ iDefineObjectConstruction(SidebarItem)
 
 struct Impl_SidebarWidget {
     iWidget           widget;
+    enum iSidebarSide side;
     enum iSidebarMode mode;
+    iString           cmdPrefix;
     iWidget *         blank;
     iListWidget *     list;
     int               modeScroll[max_SidebarMode];
@@ -92,12 +94,11 @@ struct Impl_SidebarWidget {
     int               maxButtonLabelWidth;
     int               width;
     iWidget *         resizer;
-    SDL_Cursor *      resizeCursor;
     iWidget *         menu;
     iSidebarItem *    contextItem; /* list item accessed in the context menu */
 };
 
-iDefineObjectConstruction(SidebarWidget)
+iDefineObjectConstructionArgs(SidebarWidget, (enum iSidebarSide side), side)
 
 static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) {
     return (flags_Widget(d->resizer) & pressed_WidgetFlag) != 0;
@@ -408,16 +409,19 @@ static const char *tightModeLabels_[max_SidebarMode] = {
     "\U0001f5b9",
 };
 
-void init_SidebarWidget(iSidebarWidget *d) {
+void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) {
     iWidget *w = as_Widget(d);
     init_Widget(w);
-    setId_Widget(w, "sidebar");
+    setId_Widget(w, side == left_SideBarSide ? "sidebar" : "sidebar2");
+    initCopy_String(&d->cmdPrefix, id_Widget(w));
+    appendChar_String(&d->cmdPrefix, '.');
     setBackgroundColor_Widget(w, none_ColorId);
     setFlags_Widget(w,
                     collapse_WidgetFlag | hidden_WidgetFlag | arrangeHorizontal_WidgetFlag |
                         resizeWidthOfChildren_WidgetFlag,
                     iTrue);
     iZap(d->modeScroll);
+    d->side = side;
     d->mode  = -1;
     d->width = 60 * gap_UI;
     setFlags_Widget(w, fixedWidth_WidgetFlag, iTrue);
@@ -428,8 +432,9 @@ void init_SidebarWidget(iSidebarWidget *d) {
     for (int i = 0; i < max_SidebarMode; i++) {
         d->modeButtons[i] = addChildFlags_Widget(
             buttons,
-            iClob(
-                new_LabelWidget(tightModeLabels_[i], format_CStr("sidebar.mode arg:%d", i))),
+            iClob(new_LabelWidget(
+                tightModeLabels_[i],
+                format_CStr("%s.mode arg:%d", cstr_String(id_Widget(w)), i))),
             frameless_WidgetFlag);
         d->maxButtonLabelWidth =
             iMaxi(d->maxButtonLabelWidth,
@@ -448,21 +453,22 @@ void init_SidebarWidget(iSidebarWidget *d) {
     addChildFlags_Widget(content, iClob(d->blank), resizeChildren_WidgetFlag);
     addChildFlags_Widget(vdiv, iClob(content), expand_WidgetFlag);
     setMode_SidebarWidget(d, bookmarks_SidebarMode);
-    d->resizer = addChildFlags_Widget(
-        w,
-        iClob(new_Widget()),
-        hover_WidgetFlag | commandOnClick_WidgetFlag | fixedWidth_WidgetFlag |
-            resizeToParentHeight_WidgetFlag | moveToParentRightEdge_WidgetFlag);
-    setId_Widget(d->resizer, "sidebar.grab");
+    d->resizer =
+        addChildFlags_Widget(w,
+                             iClob(new_Widget()),
+                             hover_WidgetFlag | commandOnClick_WidgetFlag | fixedWidth_WidgetFlag |
+                                 resizeToParentHeight_WidgetFlag |
+                                 (side == left_SideBarSide ? moveToParentRightEdge_WidgetFlag
+                                                           : moveToParentLeftEdge_WidgetFlag));
+    setId_Widget(d->resizer, side == left_SideBarSide ? "sidebar.grab" : "sidebar2.grab");
     d->resizer->rect.size.x = gap_UI;
     setBackgroundColor_Widget(d->resizer, none_ColorId);
-    d->resizeCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
     d->menu = NULL;
     addAction_Widget(w, SDLK_r, KMOD_PRIMARY | KMOD_SHIFT, "feeds.refresh");
 }
 
 void deinit_SidebarWidget(iSidebarWidget *d) {
-    SDL_FreeCursor(d->resizeCursor);
+    deinit_String(&d->cmdPrefix);
 }
 
 static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) {
@@ -594,6 +600,43 @@ iBool handleBookmarkEditorCommands_SidebarWidget_(iWidget *editor, const char *c
     return iFalse;
 }
 
+static iBool handleSidebarCommand_SidebarWidget_(iSidebarWidget *d, const char *cmd) {
+    iWidget *w = as_Widget(d);
+    if (equal_Command(cmd, "width")) {
+        setWidth_SidebarWidget(d, arg_Command(cmd));
+        return iTrue;
+    }
+    else if (equal_Command(cmd, "mode")) {
+        const iBool wasChanged = setMode_SidebarWidget(d, arg_Command(cmd));
+        updateItems_SidebarWidget_(d);
+        if ((argLabel_Command(cmd, "show") && !isVisible_Widget(w)) ||
+            (argLabel_Command(cmd, "toggle") && (!isVisible_Widget(w) || !wasChanged))) {
+            postCommandf_App("%s.toggle", cstr_String(id_Widget(w)));
+        }
+        scrollOffset_ListWidget(d->list, 0);
+        return iTrue;
+    }
+    else if (equal_Command(cmd, "toggle")) {
+        if (arg_Command(cmd) && isVisible_Widget(w)) {
+            return iTrue;
+        }
+        setFlags_Widget(w, hidden_WidgetFlag, isVisible_Widget(w));
+        if (isVisible_Widget(w)) {
+            w->rect.size.x = d->width;
+            invalidate_ListWidget(d->list);
+        }
+        arrange_Widget(w->parent);
+        updateSize_DocumentWidget(document_App());
+        if (isVisible_Widget(w)) {
+            updateItems_SidebarWidget_(d);
+            scrollOffset_ListWidget(d->list, 0);
+        }
+        refresh_Widget(w->parent);
+        return iTrue;
+    }
+    return iFalse;
+}
+
 static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) {
     iWidget *w = as_Widget(d);
     /* Handle commands. */
@@ -602,7 +645,27 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
     }
     else if (ev->type == SDL_USEREVENT && ev->user.code == command_UserEventCode) {
         const char *cmd = command_UserEvent(ev);
-        if (isCommand_Widget(w, ev, "mouse.clicked")) {
+        if (equal_Command(cmd, "tabs.changed") || equal_Command(cmd, "document.changed")) {
+            updateItems_SidebarWidget_(d);
+            scrollOffset_ListWidget(d->list, 0);
+        }
+        else if (equal_Command(cmd, "visited.changed") &&
+                 (d->mode == history_SidebarMode || d->mode == feeds_SidebarMode)) {
+            updateItems_SidebarWidget_(d);
+        }
+        else if (equal_Command(cmd, "bookmarks.changed") && (d->mode == bookmarks_SidebarMode ||
+                                                             d->mode == feeds_SidebarMode)) {
+            updateItems_SidebarWidget_(d);
+        }
+        else if (equal_Command(cmd, "idents.changed") && d->mode == identities_SidebarMode) {
+            updateItems_SidebarWidget_(d);
+        }
+        else if (startsWith_CStr(cmd, cstr_String(&d->cmdPrefix))) {
+            if (handleSidebarCommand_SidebarWidget_(d, cmd + size_String(&d->cmdPrefix))) {
+                return iTrue;
+            }
+        }
+        else if (isCommand_Widget(w, ev, "mouse.clicked")) {
             if (argLabel_Command(cmd, "button") == SDL_BUTTON_LEFT) {
                 if (arg_Command(cmd)) {
                     setFlags_Widget(d->resizer, pressed_WidgetFlag, iTrue);
@@ -624,7 +687,13 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
         else if (isCommand_Widget(w, ev, "mouse.moved")) {
             if (isResizing_SidebarWidget_(d)) {
                 const iInt2 local = localCoord_Widget(w, coord_Command(cmd));
-                setWidth_SidebarWidget(d, local.x + d->resizer->rect.size.x / 2);
+                const int resMid = d->resizer->rect.size.x / 2;
+                setWidth_SidebarWidget(
+                    d,
+                    (d->side == left_SideBarSide
+                         ? local.x
+                         : (rootSize_Window(get_Window()).x - coord_Command(cmd).x)) +
+                        resMid);
             }
             return iTrue;
         }
@@ -638,50 +707,14 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
         else if (isCommand_Widget(w, ev, "menu.closed")) {
             setFlags_Widget(as_Widget(d->list), disabled_WidgetFlag, iFalse);
         }
-        else if (equal_Command(cmd, "sidebar.width")) {
-            setWidth_SidebarWidget(d, arg_Command(cmd));
-            return iTrue;
-        }
-        else if (equal_Command(cmd, "sidebar.mode")) {
-            const iBool wasChanged = setMode_SidebarWidget(d, arg_Command(cmd));
-            updateItems_SidebarWidget_(d);
-            if ((argLabel_Command(cmd, "show") && !isVisible_Widget(w)) ||
-                (argLabel_Command(cmd, "toggle") && (!isVisible_Widget(w) || !wasChanged))) {
-                postCommand_App("sidebar.toggle");
-            }
-            scrollOffset_ListWidget(d->list, 0);
-            return iTrue;
-        }
-        else if (equal_Command(cmd, "sidebar.toggle")) {
-            if (arg_Command(cmd) && isVisible_Widget(w)) {
-                return iTrue;
-            }
-            setFlags_Widget(w, hidden_WidgetFlag, isVisible_Widget(w));
-            if (isVisible_Widget(w)) {
-                w->rect.size.x = d->width;
-                invalidate_ListWidget(d->list);
-            }
-            arrange_Widget(w->parent);
-            updateSize_DocumentWidget(document_App());
-            if (isVisible_Widget(w)) {
-                updateItems_SidebarWidget_(d);
-                scrollOffset_ListWidget(d->list, 0);
-            }
-            refresh_Widget(w->parent);
-            return iTrue;
-        }
-        else if (equal_Command(cmd, "tabs.changed") || equal_Command(cmd, "document.changed")) {
-            updateItems_SidebarWidget_(d);
-            scrollOffset_ListWidget(d->list, 0);
-        }
-        else if (equal_Command(cmd, "bookmark.copy")) {
+        else if (isCommand_Widget(w, ev, "bookmark.copy")) {
             const iSidebarItem *item = d->contextItem;
             if (d->mode == bookmarks_SidebarMode && item) {
                 SDL_SetClipboardText(cstr_String(&item->url));
             }
             return iTrue;
         }
-        else if (equal_Command(cmd, "bookmark.edit")) {
+        else if (isCommand_Widget(w, ev, "bookmark.edit")) {
             const iSidebarItem *item = d->contextItem;
             if (d->mode == bookmarks_SidebarMode && item) {
                 setFlags_Widget(w, disabled_WidgetFlag, iTrue);
@@ -695,7 +728,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
             }
             return iTrue;
         }
-        else if (equal_Command(cmd, "bookmark.tag")) {
+        else if (isCommand_Widget(w, ev, "bookmark.tag")) {
             const iSidebarItem *item = d->contextItem;
             if (d->mode == bookmarks_SidebarMode && item) {
                 const char *tag = cstr_String(string_Command(cmd, "tag"));
@@ -713,7 +746,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
             }
             return iTrue;
         }
-        else if (equal_Command(cmd, "bookmark.delete")) {
+        else if (isCommand_Widget(w, ev, "bookmark.delete")) {
             const iSidebarItem *item = d->contextItem;
             if (d->mode == bookmarks_SidebarMode && item && remove_Bookmarks(bookmarks_App(), item->id)) {
                 removeEntries_Feeds(item->id);
@@ -721,10 +754,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
             }
             return iTrue;
         }
-        else if (equal_Command(cmd, "visited.changed") &&
-                 (d->mode == history_SidebarMode || d->mode == feeds_SidebarMode)) {
-            updateItems_SidebarWidget_(d);
-        }
         else if (equal_Command(cmd, "feeds.update.finished") && d->mode == feeds_SidebarMode) {
             updateItems_SidebarWidget_(d);
         }
@@ -742,11 +771,11 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
         else if (startsWith_CStr(cmd, "feed.entry.") && d->mode == feeds_SidebarMode) {
             const iSidebarItem *item = d->contextItem;
             if (item) {
-                if (equal_Command(cmd, "feed.entry.opentab")) {
+                if (isCommand_Widget(w, ev, "feed.entry.opentab")) {
                     postCommandf_App("open newtab:1 url:%s", cstr_String(&item->url));
                     return iTrue;
                 }
-                if (equal_Command(cmd, "feed.entry.toggleread")) {
+                if (isCommand_Widget(w, ev, "feed.entry.toggleread")) {
                     iVisited *vis = visited_App();
                     if (containsUrl_Visited(vis, &item->url)) {
                         removeUrl_Visited(vis, &item->url);
@@ -757,18 +786,18 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
                     postCommand_App("visited.changed");
                     return iTrue;
                 }
-                if (equal_Command(cmd, "feed.entry.bookmark")) {
+                if (isCommand_Widget(w, ev, "feed.entry.bookmark")) {
                     makeBookmarkCreation_Widget(&item->url, &item->label, item->icon);
                     postCommand_App("focus.set id:bmed.title");
                     return iTrue;
                 }
                 iBookmark *feedBookmark = get_Bookmarks(bookmarks_App(), item->id);
                 if (feedBookmark) {
-                    if (equal_Command(cmd, "feed.entry.openfeed")) {
+                    if (isCommand_Widget(w, ev, "feed.entry.openfeed")) {
                         postCommandf_App("open url:%s", cstr_String(&feedBookmark->url));
                         return iTrue;
                     }
-                    if (equal_Command(cmd, "feed.entry.edit")) {
+                    if (isCommand_Widget(w, ev, "feed.entry.edit")) {
                         setFlags_Widget(w, disabled_WidgetFlag, iTrue);
                         iWidget *dlg = makeBookmarkEditor_Widget();
                         setText_InputWidget(findChild_Widget(dlg, "bmed.title"), &feedBookmark->title);
@@ -778,7 +807,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
                         setFocus_Widget(findChild_Widget(dlg, "bmed.title"));
                         return iTrue;
                     }
-                    if (equal_Command(cmd, "feed.entry.unsubscribe")) {
+                    if (isCommand_Widget(w, ev, "feed.entry.unsubscribe")) {
                         if (arg_Command(cmd)) {
                             removeTag_Bookmark(feedBookmark, "subscribed");
                             removeEntries_Feeds(id_Bookmark(feedBookmark));
@@ -791,7 +820,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
                                             cstr_String(&feedBookmark->title)),
                                 (const char *[]){ "Cancel",
                                                   uiTextCaution_ColorEscape "Unsubscribe" },
-                                (const char *[]){ "cancel", "feed.entry.unsubscribe arg:1" },
+                                (const char *[]){ "cancel", "feed.entry.unsubscribe arg:1" }, /* FIXME: which sidebar */
                                 2);
                         }
                         return iTrue;
@@ -799,13 +828,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
                 }
             }
         }
-        else if (equal_Command(cmd, "bookmarks.changed") && (d->mode == bookmarks_SidebarMode ||
-                                                             d->mode == feeds_SidebarMode)) {
-            updateItems_SidebarWidget_(d);
-        }
-        else if (equal_Command(cmd, "idents.changed") && d->mode == identities_SidebarMode) {
-            updateItems_SidebarWidget_(d);
-        }
         else if (isCommand_Widget(w, ev, "ident.use")) {
             iGmIdentity *  ident  = menuIdentity_SidebarWidget_(d);
             const iString *tabUrl = url_DocumentWidget(document_App());
@@ -843,7 +865,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
             }
             return iTrue;
         }
-        else if (equal_Command(cmd, "ident.setnotes")) {
+        else if (isCommand_Widget(w, ev, "ident.setnotes")) {
             iGmIdentity *ident = pointerLabel_Command(cmd, "ident");
             if (ident) {
                 setCStr_String(&ident->notes, suffixPtr_Command(cmd, "value"));
@@ -864,7 +886,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
             }
             return iTrue;
         }
-        else if (equal_Command(cmd, "ident.delete")) {
+        else if (isCommand_Widget(w, ev, "ident.delete")) {
             iSidebarItem *item = d->contextItem;
             if (argLabel_Command(cmd, "confirm")) {
                 makeQuestion_Widget(uiTextCaution_ColorEscape "DELETE IDENTITY",
@@ -876,7 +898,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
                                     (const char *[]){ "Cancel",
                                                       uiTextCaution_ColorEscape
                                                       "Delete Identity and Files" },
-                                    (const char *[]){ "cancel", "ident.delete confirm:0" },
+                                    (const char *[]){ "cancel", "ident.delete confirm:0" }, /* FIXME: which sidebar */
                                     2);
                 return iTrue;
             }
@@ -884,7 +906,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
             updateItems_SidebarWidget_(d);
             return iTrue;
         }
-        else if (equal_Command(cmd, "history.delete")) {
+        else if (isCommand_Widget(w, ev, "history.delete")) {
             if (d->contextItem && !isEmpty_String(&d->contextItem->url)) {
                 removeUrl_Visited(visited_App(), &d->contextItem->url);
                 updateItems_SidebarWidget_(d);
@@ -892,14 +914,14 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
             }
             return iTrue;
         }
-        else if (equal_Command(cmd, "history.copy")) {
+        else if (isCommand_Widget(w, ev, "history.copy")) {
             const iSidebarItem *item = d->contextItem;
             if (item && !isEmpty_String(&item->url)) {
                 SDL_SetClipboardText(cstr_String(&item->url));
             }
             return iTrue;
         }
-        else if (equal_Command(cmd, "history.addbookmark")) {
+        else if (isCommand_Widget(w, ev, "history.addbookmark")) {
             const iSidebarItem *item = d->contextItem;
             if (!isEmpty_String(&item->url)) {
                 makeBookmarkCreation_Widget(
diff --git a/src/ui/sidebarwidget.h b/src/ui/sidebarwidget.h
index 0d4ed9c8..fa74e049 100644
--- a/src/ui/sidebarwidget.h
+++ b/src/ui/sidebarwidget.h
@@ -33,8 +33,13 @@ enum iSidebarMode {
     max_SidebarMode
 };
 
+enum iSidebarSide {
+    left_SideBarSide,
+    right_SideBarSide,
+};
+
 iDeclareWidgetClass(SidebarWidget)
-iDeclareObjectConstruction(SidebarWidget)
+iDeclareObjectConstructionArgs(SidebarWidget, enum iSidebarSide side)
 
 iBool               setMode_SidebarWidget   (iSidebarWidget *, enum iSidebarMode mode);
 
diff --git a/src/ui/util.c b/src/ui/util.c
index d9997004..ef69b5f1 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -1031,8 +1031,8 @@ iWidget *makePreferences_Widget(void) {
         appendTwoColumnPage_(tabs, "General", '1', &headings, &values);
         addChild_Widget(headings, iClob(makeHeading_Widget("Downloads folder:")));
         setId_Widget(addChild_Widget(values, iClob(new_InputWidget(0))), "prefs.downloads");
-        addChild_Widget(headings, iClob(makeHeading_Widget("Outline on scrollbar:")));
-        addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoveroutline")));
+        /*addChild_Widget(headings, iClob(makeHeading_Widget("Outline on scrollbar:")));
+        addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoveroutline")));*/
         addChild_Widget(headings, iClob(makeHeading_Widget("Smooth scrolling:")));
         addChild_Widget(values, iClob(makeToggle_Widget("prefs.smoothscroll")));
         addChild_Widget(headings, iClob(makeHeading_Widget("Load image on scroll:")));
diff --git a/src/ui/widget.c b/src/ui/widget.c
index 4d50da38..f3e73ee7 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -263,10 +263,13 @@ void arrange_Widget(iWidget *d) {
         setFlags_Widget(d, wasCollapsed_WidgetFlag, iTrue);
         return;
     }
-    if (d->flags & moveToParentRightEdge_WidgetFlag) {
+    if (d->flags & moveToParentLeftEdge_WidgetFlag) {
+        d->rect.pos.x = d->padding[0];
+    }
+    else if (d->flags & moveToParentRightEdge_WidgetFlag) {
         d->rect.pos.x = width_Rect(innerRect_Widget_(d->parent)) - width_Rect(d->rect);
     }
-    if (d->flags & centerHorizontal_WidgetFlag) {
+    else if (d->flags & centerHorizontal_WidgetFlag) {
         centerHorizontal_Widget_(d);
     }
     if (d->flags & resizeToParentWidth_WidgetFlag) {
@@ -388,7 +391,8 @@ void arrange_Widget(iWidget *d) {
             continue;
         }
         if (d->flags & (arrangeHorizontal_WidgetFlag | arrangeVertical_WidgetFlag)) {
-            if (child->flags & moveToParentRightEdge_WidgetFlag) {
+            if (child->flags &
+                (moveToParentLeftEdge_WidgetFlag | moveToParentRightEdge_WidgetFlag)) {
                 continue; /* Not part of the sequential arrangement .*/
             }
             child->rect.pos = pos;
@@ -422,7 +426,8 @@ void arrange_Widget(iWidget *d) {
             iForEach(ObjectList, j, d->children) {
                 iWidget *child = as_Widget(j.object);
                 if (child->flags &
-                    (resizeToParentWidth_WidgetFlag | moveToParentRightEdge_WidgetFlag)) {
+                    (resizeToParentWidth_WidgetFlag | moveToParentLeftEdge_WidgetFlag |
+                     moveToParentRightEdge_WidgetFlag)) {
                     arrange_Widget(child);
                 }
             }
diff --git a/src/ui/widget.h b/src/ui/widget.h
index 278ae081..f06a6607 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -85,10 +85,11 @@ enum iWidgetFlag {
 /* 64-bit extended flags */
 #define wasCollapsed_WidgetFlag             iBit64(32)
 #define centerHorizontal_WidgetFlag         iBit64(33)
-#define moveToParentRightEdge_WidgetFlag    iBit64(34)
-#define wrapText_WidgetFlag                 iBit64(35)
-#define borderTop_WidgetFlag                iBit64(36)
-#define overflowScrollable_WidgetFlag       iBit64(37)
+#define moveToParentLeftEdge_WidgetFlag     iBit64(34)
+#define moveToParentRightEdge_WidgetFlag    iBit64(35)
+#define wrapText_WidgetFlag                 iBit64(36)
+#define borderTop_WidgetFlag                iBit64(37)
+#define overflowScrollable_WidgetFlag       iBit64(38)
 
 enum iWidgetAddPos {
     back_WidgetAddPos,
diff --git a/src/ui/window.c b/src/ui/window.c
index 199e35a7..53300d24 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -109,7 +109,8 @@ static const iMenuItem navMenuItems_[] = {
     { "---", 0, 0, NULL },
     { "Show Feed Entries", 0, 0, "!open url:about:feeds" },
     { "---", 0, 0, NULL },
-    { "Toggle Sidebar", SDLK_l, KMOD_PRIMARY | KMOD_SHIFT, "sidebar.toggle" },
+    { "Toggle Left Sidebar", SDLK_l, KMOD_PRIMARY | KMOD_SHIFT, "sidebar.toggle" },
+    { "Toggle Right Sidebar", SDLK_p, KMOD_PRIMARY | KMOD_SHIFT, "sidebar2.toggle" },
     { "Zoom In", SDLK_EQUALS, KMOD_PRIMARY, "zoom.delta arg:10" },
     { "Zoom Out", SDLK_MINUS, KMOD_PRIMARY, "zoom.delta arg:-10" },
     { "Reset Zoom", SDLK_0, KMOD_PRIMARY, "zoom.set arg:100" },
@@ -144,7 +145,8 @@ static const iMenuItem viewMenuItems_[] = {
     { "Show History", '3', KMOD_PRIMARY, "sidebar.mode arg:2 toggle:1" },
     { "Show Identities", '4', KMOD_PRIMARY, "sidebar.mode arg:3 toggle:1" },
     { "Show Page Outline", '5', KMOD_PRIMARY, "sidebar.mode arg:4 toggle:1" },
-    { "Toggle Sidebar", SDLK_l, KMOD_PRIMARY | KMOD_SHIFT, "sidebar.toggle" },
+    { "Toggle Left Sidebar", SDLK_l, KMOD_PRIMARY | KMOD_SHIFT, "sidebar.toggle" },
+    { "Toggle Right Sidebar", SDLK_p, KMOD_PRIMARY | KMOD_SHIFT, "sidebar2.toggle" },
     { "---", 0, 0, NULL },
     { "Go Back", SDLK_LEFTBRACKET, KMOD_PRIMARY, "navigate.back" },
     { "Go Forward", SDLK_RIGHTBRACKET, KMOD_PRIMARY, "navigate.forward" },
@@ -459,10 +461,12 @@ static void setupUserInterface_Window(iWindow *d) {
             addChild_Widget(buttons, iClob(newIcon_LabelWidget("\u2795", 0, 0, "tabs.new"))),
             "newtab");
     }
-    /* Side bar. */ {
+    /* Side bars. */ {
         iWidget *content = findChild_Widget(d->root, "tabs.content");
-        iSidebarWidget *sidebar = new_SidebarWidget();
-        addChildPos_Widget(content, iClob(sidebar), front_WidgetAddPos);
+        iSidebarWidget *sidebar1 = new_SidebarWidget(left_SideBarSide);
+        addChildPos_Widget(content, iClob(sidebar1), front_WidgetAddPos);
+        iSidebarWidget *sidebar2 = new_SidebarWidget(right_SideBarSide);
+        addChildPos_Widget(content, iClob(sidebar2), back_WidgetAddPos);
     }
     /* Lookup results. */ {
         iLookupWidget *lookup = new_LookupWidget();
Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/release/cdiff/c8089179f84a2cabd84a47a800aaadd9af8bd9b8
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
86.829157 milliseconds
Gemini-to-HTML Time
1.557473 milliseconds

This content has been proxied by September (3851b).