Theseus: the favorites form and menu float over the page
Opening Add a page… or the favorites right-click menu made the bars taller, which pushed the page down and left an empty band under the favorites row. The bars keep their height now; only their view grows over the page, transparent below the bars, and the page stays where it was.
This commit is contained in:
parent
eac7020820
commit
3611a037c2
3 changed files with 48 additions and 19 deletions
46
chrome.html
46
chrome.html
|
|
@ -36,6 +36,12 @@
|
|||
content means scrollHeight is the natural chrome height, and syncHeight
|
||||
shrinks correctly after every menu-close. */
|
||||
body { margin: 0; background: var(--bg); color: var(--ink); user-select: none; overflow: hidden; }
|
||||
/* While a prompt or menu floats over the page this view is taller than the
|
||||
bars and transparent below them: the background is painted only behind
|
||||
the bars (--bars-h), so the page shows through the rest. */
|
||||
html.overlaying body { background: transparent; }
|
||||
html.overlaying body::before { content: ""; position: absolute; left: 0; top: 0; right: 0;
|
||||
height: var(--bars-h, 0px); background: var(--bg); z-index: -1; }
|
||||
/* The tab row doubles as the window's title bar on Windows (main.js hides
|
||||
the native frame): the row is a drag region, everything clickable in it
|
||||
opts out, and --wco-reserve keeps tabs clear of the native minimise /
|
||||
|
|
@ -568,13 +574,23 @@
|
|||
// Coalesced with a zero timeout, not requestAnimationFrame: frames stop
|
||||
// whenever the window is occluded, and a height change queued then (a
|
||||
// prompt closing, a row hiding) would only land when the window came back.
|
||||
let syncHeightTimer = 0;
|
||||
// Prompts and menus that reach below the bars no longer make the bars
|
||||
// taller (that pushed the page down and left an empty band under the
|
||||
// favorites row): main grows only this view, transparent below the bars,
|
||||
// over the page. A prompt takes the whole window so its backdrop dims it.
|
||||
let syncHeightTimer = 0, overlayShown = 0;
|
||||
function syncHeight() {
|
||||
clearTimeout(syncHeightTimer);
|
||||
syncHeightTimer = setTimeout(() => {
|
||||
let h = document.body.scrollHeight;
|
||||
const box = document.querySelector(".promptmask .promptbox");
|
||||
if (box) h = Math.max(h, Math.ceil(box.getBoundingClientRect().height) + 56);
|
||||
const h = document.body.scrollHeight;
|
||||
let over = 0;
|
||||
if (document.querySelector(".promptmask")) over = 4000; // main clamps to the window
|
||||
else for (const m of document.querySelectorAll(".ctxmenu, .grouppop")) over = Math.max(over, Math.ceil(m.getBoundingClientRect().bottom) + 4);
|
||||
if (over <= h) over = 0;
|
||||
const root = document.documentElement;
|
||||
if (over) { root.style.setProperty("--bars-h", h + "px"); root.classList.add("overlaying"); }
|
||||
else root.classList.remove("overlaying");
|
||||
if (over !== overlayShown) { overlayShown = over; T.setChromeOverlay(over); }
|
||||
T.setChromeHeight(h);
|
||||
}, 0);
|
||||
}
|
||||
|
|
@ -1321,7 +1337,7 @@
|
|||
// - On a specific bookmark: Open / Edit title / Remove
|
||||
// - On empty area OR the placeholder text: Add current page (or Remove
|
||||
// if the page is already bookmarked), and Add a page… by hand
|
||||
function closeBmMenu() { const m = document.getElementById("bmMenu"); if (m) m.remove(); }
|
||||
function closeBmMenu() { const m = document.getElementById("bmMenu"); if (m) { m.remove(); syncHeight(); } }
|
||||
function openBmMenu(x, y, ctx) {
|
||||
closeBmMenu();
|
||||
const items = [];
|
||||
|
|
@ -1352,9 +1368,12 @@
|
|||
).join("");
|
||||
document.body.appendChild(m);
|
||||
const r = m.getBoundingClientRect();
|
||||
const vw = document.documentElement.clientWidth, vh = document.documentElement.clientHeight;
|
||||
const vw = document.documentElement.clientWidth;
|
||||
m.style.left = Math.min(x, vw - r.width - 6) + "px";
|
||||
m.style.top = Math.min(y, vh - r.height - 6) + "px";
|
||||
// Opens downward over the page (syncHeight floats this view), so it is
|
||||
// never squeezed into the height of the bars.
|
||||
m.style.top = y + "px";
|
||||
growChromeForMenu();
|
||||
m.querySelectorAll(".mi").forEach((el) => {
|
||||
const it = items[Number(el.dataset.i)];
|
||||
if (it.disabled) return;
|
||||
|
|
@ -1866,17 +1885,8 @@
|
|||
if (r.right > window.innerWidth) m.style.left = Math.max(4, window.innerWidth - r.width - 4) + "px";
|
||||
growChromeForMenu();
|
||||
}
|
||||
function growChromeForMenu() {
|
||||
// Wait a frame so all newly-added overlays contribute to the bounding box.
|
||||
requestAnimationFrame(() => {
|
||||
let needed = document.body.scrollHeight;
|
||||
for (const m of document.querySelectorAll(".ctxmenu, .grouppop")) {
|
||||
const r = m.getBoundingClientRect();
|
||||
needed = Math.max(needed, Math.ceil(r.bottom) + 4);
|
||||
}
|
||||
T.setChromeHeight(needed);
|
||||
});
|
||||
}
|
||||
// A menu that reaches below the bars floats over the page (see syncHeight).
|
||||
function growChromeForMenu() { syncHeight(); }
|
||||
function openGroupSubmenu(x, y, t) {
|
||||
document.querySelectorAll(".ctxmenu.sub2").forEach((m) => m.remove());
|
||||
const m = document.createElement("div");
|
||||
|
|
|
|||
20
main.js
20
main.js
|
|
@ -2429,6 +2429,7 @@ let win, chrome;
|
|||
// The window can be gone while tabs and app windows still fire events.
|
||||
const winAlive = () => !!win && !win.isDestroyed();
|
||||
let CHROME_H = 84; // grows when an extra bar (Tor notice / BCNR offer) is shown
|
||||
let CHROME_OVERLAY_H = 0; // > 0 while a chrome.html prompt floats over the page
|
||||
// Site-info popover: a floating overlay VIEW on top of the page content, so it
|
||||
// never pushes the page down. Positioned under the address-bar badge on demand.
|
||||
let popover, popVisible = false, popPos = { x: 8, y: 90 };
|
||||
|
|
@ -3561,7 +3562,11 @@ function layout() {
|
|||
const fsTab = fsTabId != null ? tabs.find((t) => t.id === fsTabId) : null;
|
||||
if (!fsTab && fsTabId != null) fsTabId = null;
|
||||
const chromeH = fsTab ? 0 : CHROME_H;
|
||||
chrome.setBounds({ x: 0, y: 0, width, height: chromeH });
|
||||
// A prompt open in chrome.html (Add a page…, rename) floats over the page:
|
||||
// only the chrome view grows, transparent below its bars, and every other
|
||||
// view keeps y = chromeH, so the page neither moves nor leaves a gap.
|
||||
const chromeViewH = fsTab ? 0 : Math.min(height, Math.max(chromeH, CHROME_OVERLAY_H));
|
||||
chrome.setBounds({ x: 0, y: 0, width, height: chromeViewH });
|
||||
const bodyH = Math.max(0, height - chromeH);
|
||||
// Quick-links strip on the LEFT edge (optional, 44px). Hidden in HTML
|
||||
// fullscreen so a video truly fills the window. The strip spans the full
|
||||
|
|
@ -8861,6 +8866,19 @@ ipcMain.handle("set-chrome-height", (_e, h) => {
|
|||
const next = Math.max(74, Math.min(260, Math.round(h) || 84));
|
||||
if (next !== CHROME_H) { CHROME_H = next; layout(); }
|
||||
});
|
||||
// Height a chrome.html prompt needs over the page (0 = none). While it is set
|
||||
// the chrome view is transparent below its bars and sits above every other
|
||||
// view, so the prompt and its dimmed backdrop draw over the page.
|
||||
ipcMain.handle("set-chrome-overlay", (e, h) => {
|
||||
if (!chrome || e.sender !== chrome.webContents) throw new Error("set-chrome-overlay: untrusted sender");
|
||||
const next = Math.max(0, Math.min(4000, Math.round(h) || 0));
|
||||
if (next === CHROME_OVERLAY_H) return;
|
||||
CHROME_OVERLAY_H = next;
|
||||
try { chrome.setBackgroundColor(next ? "#00000000" : (nativeTheme.shouldUseDarkColors ? "#0f1420" : "#e6e8ec")); } catch {}
|
||||
// Re-adding a child view moves it to the top of the stack.
|
||||
if (next) try { win.contentView.addChildView(chrome); } catch {}
|
||||
layout();
|
||||
});
|
||||
ipcMain.handle("switch-to-bcnr", () => {
|
||||
const t = activeTab(); if (!t || !t.bcnrOffer) return;
|
||||
const { host, rest, tld } = t.bcnrOffer;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ contextBridge.exposeInMainWorld("theseus", {
|
|||
toggleSiteInfo: (rect) => ipcRenderer.invoke("toggle-site-info", rect),
|
||||
switchToBcnr: () => ipcRenderer.invoke("switch-to-bcnr"),
|
||||
setChromeHeight: (h) => ipcRenderer.invoke("set-chrome-height", h),
|
||||
setChromeOverlay: (h) => ipcRenderer.invoke("set-chrome-overlay", h),
|
||||
getSearchEngines: () => ipcRenderer.invoke("search-engines"),
|
||||
setSearchEngine: (id) => ipcRenderer.invoke("set-search-engine", id),
|
||||
addEngine: (eng) => ipcRenderer.invoke("add-engine", eng),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue