Use applet geometry for panel scroll margins

This commit is contained in:
ajp_anton
2026-09-09 22:12:24 +00:00
parent f5988605c8
commit 787231cb03
8 changed files with 177 additions and 22 deletions
@@ -2,32 +2,70 @@
.pragma library
// Task Manager fills unused panel space. Only delegates are task buttons.
function hasTaskAt(item, x, y) {
if (!item.visible || !item.contains(item.mapFromItem(null, x, y))) return false;
function hasTaskAt(item, x, y, vertical) {
if (!item.visible) return false;
const point = item.mapFromItem(null, x, y);
if (vertical === undefined) {
if (!item.contains(point)) return false;
} else if (item.width <= 0 || item.height <= 0
|| (vertical ? point.y < 0 || point.y > item.height : point.x < 0 || point.x > item.width)) {
return false;
}
if (item.tasksRoot !== undefined && item.isWindow !== undefined && item.index !== undefined) return true;
for (const child of item.children) {
if (hasTaskAt(child, x, y)) return true;
if (hasTaskAt(child, x, y, vertical)) return true;
}
return false;
}
function appletArea(child, x, y, vertical) {
const applet = child.applet;
const name = applet?.plasmoid?.pluginName;
if (!name) return "other";
if (name === "org.kde.plasma.taskmanager" || name === "org.kde.plasma.icontasks") {
return hasTaskAt(applet, x, y, vertical) ? "tasks" : "empty";
}
if (name === "se.ajpanton.panelactions" || name === "org.kde.plasma.panelspacer"
|| name === "org.kde.plasma.marginsseparator") return "empty";
if (name === "org.kde.plasma.systemtray") return "tray";
if (name === "org.kde.plasma.digitalclock" || name === "org.kde.plasma.analogclock") return "clock";
if (name === "org.kde.plasma.kickoff" || name === "org.kde.plasma.kicker"
|| name === "org.kde.plasma.kickerdash") return "launcher";
return "other";
}
function areaAt(panelLayout, x, y) {
if (!panelLayout) return "";
for (const child of panelLayout.children) {
if (!child.visible || !child.contains(child.mapFromItem(null, x, y))) continue;
const applet = child.applet;
const name = applet?.plasmoid?.pluginName;
if (!name) return "other";
if (name === "org.kde.plasma.taskmanager" || name === "org.kde.plasma.icontasks") {
return hasTaskAt(applet, x, y) ? "tasks" : "empty";
if (child.visible && child.contains(child.mapFromItem(null, x, y))) {
return appletArea(child, x, y);
}
if (name === "se.ajpanton.panelactions" || name === "org.kde.plasma.panelspacer"
|| name === "org.kde.plasma.marginsseparator") return "empty";
if (name === "org.kde.plasma.systemtray") return "tray";
if (name === "org.kde.plasma.digitalclock" || name === "org.kde.plasma.analogclock") return "clock";
if (name === "org.kde.plasma.kickoff" || name === "org.kde.plasma.kicker"
|| name === "org.kde.plasma.kickerdash") return "launcher";
return "other";
}
return "empty";
}
// Scrolling owns the full panel thickness and its outer end padding. Interior
// gaps and explicit spacers remain empty; clicks keep their exact hit testing.
function scrollAreaAt(panelLayout, x, y, vertical) {
if (!panelLayout) return "";
const point = panelLayout.mapFromItem(null, x, y);
const along = vertical ? point.y : point.x;
let first = null;
let last = null;
for (const child of panelLayout.children) {
if (!child.visible || child.width <= 0 || child.height <= 0) continue;
const a = child.mapToItem(panelLayout, 0, 0);
const b = child.mapToItem(panelLayout, child.width, child.height);
const start = vertical ? Math.min(a.y, b.y) : Math.min(a.x, b.x);
const end = vertical ? Math.max(a.y, b.y) : Math.max(a.x, b.x);
if (end <= start) continue;
if (along >= start && along < end) return appletArea(child, x, y, vertical);
if (!first || start < first.start) first = {child, start};
if (!last || end > last.end) last = {child, end};
}
const edge = first && along < first.start ? first : last && along >= last.end ? last : null;
if (!edge) return "empty";
const boundary = edge === first ? first.start : last.end;
const projected = panelLayout.mapToItem(null, vertical ? point.x : boundary, vertical ? boundary : point.y);
return appletArea(edge.child, projected.x, projected.y, vertical);
}