Files
bbedward 076288604e widgets: share the lock editor with the desktop, adjust overlapping
face, share desktop clock widget with lock screen
2026-10-04 22:23:14 -04:00

97 lines
3.4 KiB
QML

import QtQuick
import QtQuick.Window
import "../../Common/WidgetPlacement.js" as Placement
Item {
id: root
required property Item sourceItem
property string renderKey: ""
property bool ready: false
property bool busy: false
property string capturedKey: ""
property var capture: null
readonly property size sourceSize: Qt.size(sourceItem.width, sourceItem.height)
readonly property real sampleScale: 128 / Math.max(1, sourceItem.width, sourceItem.height)
readonly property int sampleWidth: Math.max(1, Math.round(sourceItem.width * sampleScale))
readonly property int sampleHeight: Math.max(1, Math.round(sourceItem.height * sampleScale))
readonly property bool sourceVisible: sourceItem.visible && (sourceItem.Window.window?.visible ?? false)
signal sampled(var luminances, int sampleWidth, int sampleHeight)
signal failed
onRenderKeyChanged: schedule.restart()
onReadyChanged: schedule.restart()
onSourceVisibleChanged: schedule.restart()
onSourceSizeChanged: schedule.restart()
Component.onCompleted: schedule.restart()
function finish() {
if (capture)
canvas.unloadImage(capture.url);
capture = null;
busy = false;
if (capturedKey !== renderKey)
schedule.restart();
}
Timer {
id: schedule
interval: 0
onTriggered: {
if (!root.ready || !root.sourceVisible || root.busy || !canvas.available || root.sourceItem.width <= 0 || root.sourceItem.height <= 0)
return;
root.capturedKey = root.renderKey;
root.busy = true;
const started = root.sourceItem.grabToImage(result => {
if (!root.ready || root.capturedKey !== root.renderKey) {
root.finish();
return;
}
root.capture = result;
canvas.loadImage(result.url);
if (canvas.isImageLoaded(result.url))
canvas.requestPaint();
}, Qt.size(root.sampleWidth, root.sampleHeight));
if (!started) {
root.finish();
root.failed();
}
}
}
Canvas {
id: canvas
width: root.sampleWidth
height: root.sampleHeight
opacity: 0
onAvailableChanged: schedule.restart()
onImageLoaded: requestPaint()
onPaint: {
if (!root.capture)
return;
if (isImageError(root.capture.url)) {
root.finish();
root.failed();
return;
}
if (!root.ready || root.capturedKey !== root.renderKey) {
root.finish();
return;
}
if (!isImageLoaded(root.capture.url))
return;
const context = getContext("2d");
context.clearRect(0, 0, width, height);
context.drawImage(root.capture.url, 0, 0, width, height);
const pixels = context.getImageData(0, 0, width, height).data;
const luminances = [];
for (let i = 0; i < pixels.length; i += 4)
luminances.push(Placement.luminance(pixels[i] / 255, pixels[i + 1] / 255, pixels[i + 2] / 255));
context.clearRect(0, 0, width, height);
root.finish();
root.sampled(luminances, width, height);
}
}
}