77cfc90b4fb2166b9ae955ad40a067549d6d5881
max
  Tue Sep 15 05:29:56 2026 -0700
hgc share-a-link: force the enclosing superTrack to show

The hgc details-page "Share a link" button strips the hgsid and links straight
to the page, but a track nested in a superTrack draws nothing on a fresh load
of that link since superTracks default to hide. Add tdbTopSuperTrack() so the
per-track JSON carries the enclosing superTrack's name, and have the share
dialog force <superTrack>=show onto the URL when there is one.

diff --git src/hg/hgTracks/imageV2.c src/hg/hgTracks/imageV2.c
index 9564d622927..8b4cc643d0d 100644
--- src/hg/hgTracks/imageV2.c
+++ src/hg/hgTracks/imageV2.c
@@ -215,30 +215,44 @@
 }
 
 char* tdbTopParent(struct trackDb *tdb)
 /* return the name of the top-most parent, so the parent of a composite or the name of the superTrack for
  * a composite in a superTrack. Or return NULL if this is already a top-level track. */
 {
     if (!tdb->parent)
         return NULL;
 
     while (tdb->parent) {
         tdb = tdb->parent;
     }
     return tdb->track;
 }
 
+char* tdbTopSuperTrack(struct trackDb *tdb)
+/* Like tdbTopParent, but only returns a name if the top-most ancestor is itself a superTrack
+ * (as opposed to a plain top-level composite/folder). Used so the client can restore the
+ * superTrack's visibility (which defaults to hide) when linking directly to one of its
+ * descendants, e.g. the hgc "Share a link" button. Returns NULL otherwise. */
+{
+    struct trackDb *top = tdb;
+    while (top->parent)
+        top = top->parent;
+    if (top != tdb && tdbIsSuperTrack(top))
+        return top->track;
+    return NULL;
+}
+
 /////////////////////////
 // JSON support.  Eventually the whole imgTbl could be written out as JSON
 
 
 static void jsonTdbSettingsInit(struct jsonElement *settings)
 // Inititializes trackDbJson
 {
 struct jsonElement *ele = newJsonObject(newHash(8));
 jsonObjectAdd(ele, "shortLabel", newJsonString("ruler"));
 jsonObjectAdd(ele, "type", newJsonString("ruler"));
 jsonObjectAdd(ele, "longLabel", newJsonString("Base Position Controls"));
 jsonObjectAdd(ele, "canPack", newJsonNumber(0));
 jsonObjectAdd(ele, "visibility", newJsonNumber(rulerMode));
 jsonObjectAdd(ele, "configureBy", newJsonString("popup"));
 jsonObjectAdd(ele, "kindOfParent", newJsonNumber(0));
@@ -251,30 +265,37 @@
 struct jsonElement *ele = newJsonObject(newHash(8));
 jsonObjectAdd(settings, track->track, (struct jsonElement *) ele);
 // track name and type
 jsonObjectAdd(ele, "type", newJsonString(track->tdb->type));
 
 // Tell which kind of parent and which kind of child
 enum kindOfParent kindOfParent = tdbKindOfParent(track->tdb);
 enum kindOfChild  kindOfChild  = tdbKindOfChild(track->tdb);
 jsonObjectAdd(ele, "kindOfParent", newJsonNumber(kindOfParent));
 jsonObjectAdd(ele, "kindOfChild", newJsonNumber(kindOfChild));
 
 char* topParent = tdbTopParent(track->tdb);
 if (topParent)
     jsonObjectAdd(ele, "topParent", newJsonString(topParent));
 
+// Name of the enclosing superTrack, if any, so a direct link to this track (e.g. the hgc
+// "Share a link" popup) can also turn the superTrack's own visibility to "show" -- superTracks
+// default to hide, so without this the track would not appear when the link is opened fresh.
+char* superTrack = tdbTopSuperTrack(track->tdb);
+if (superTrack)
+    jsonObjectAdd(ele, "superTrack", newJsonString(superTrack));
+
 // Tell something about the parent and/or children
 if (kindOfChild != kocOrphan)
     {
     struct trackDb *parentTdb = (kindOfChild == kocFolderContent ? track->tdb->parent
                                                                  : tdbGetContainer(track->tdb));
     jsonObjectAdd(ele, "parentTrack", newJsonString(parentTdb->track));
     jsonObjectAdd(ele, "parentLabel", newJsonString(parentTdb->shortLabel));
     if (kindOfChild != kocFolderContent && !track->canPack)
         {
         jsonObjectAdd(ele, "shouldPack", newJsonNumber(0)); // default vis is full,
         track->canPack = rTdbTreeCanPack(parentTdb);        // but pack is an option
         }
     }
 
 boolean isCustomComposite = trackDbSettingOn(track->tdb, CUSTOM_COMPOSITE_SETTING);