background: fix clock going out of the screen vertically

This commit is contained in:
end-4 2025-08-12 16:24:45 +07:00
parent 10b2cf2662
commit 3eb1dd3180
3 changed files with 72 additions and 26 deletions

View file

@ -120,6 +120,7 @@ Variants {
leastBusyRegionProc.horizontalPadding = bgRoot.movableXSpace + 100
leastBusyRegionProc.verticalPadding = bgRoot.movableYSpace + 100
leastBusyRegionProc.running = false;
console.log(leastBusyRegionProc.command.join(" "))
leastBusyRegionProc.running = true;
}
Process {
@ -130,13 +131,14 @@ Variants {
property int horizontalPadding: bgRoot.movableXSpace
property int verticalPadding: bgRoot.movableYSpace
command: [Quickshell.shellPath("scripts/images/least_busy_region.py"),
"--screen-width", bgRoot.screen.width,
"--screen-height", bgRoot.screen.height,
"--screen-width", Math.round(bgRoot.screen.width / bgRoot.effectiveWallpaperScale),
"--screen-height", Math.round(bgRoot.screen.height / bgRoot.effectiveWallpaperScale),
"--width", contentWidth,
"--height", contentHeight,
"--horizontal-padding", horizontalPadding,
"--vertical-padding", verticalPadding,
path
path,
"--visual-output",
]
stdout: StdioCollector {
id: leastBusyRegionOutputCollector
@ -145,8 +147,8 @@ Variants {
console.log("[Background] Least busy region output:", output)
if (output.length === 0) return;
const parsedContent = JSON.parse(output)
bgRoot.clockX = parsedContent.center_x
bgRoot.clockY = parsedContent.center_y
bgRoot.clockX = parsedContent.center_x * bgRoot.effectiveWallpaperScale
bgRoot.clockY = parsedContent.center_y * bgRoot.effectiveWallpaperScale
bgRoot.dominantColor = parsedContent.dominant_color || Appearance.colors.colPrimary
}
}
@ -195,8 +197,8 @@ Variants {
anchors {
left: wallpaper.left
top: wallpaper.top
leftMargin: ((root.fixedClockPosition ? root.fixedClockX : bgRoot.clockX * bgRoot.effectiveWallpaperScale) - implicitWidth / 2)
topMargin: ((root.fixedClockPosition ? root.fixedClockY : bgRoot.clockY * bgRoot.effectiveWallpaperScale) - implicitHeight / 2)
leftMargin: bgRoot.movableXSpace + ((root.fixedClockPosition ? root.fixedClockX : bgRoot.clockX * bgRoot.effectiveWallpaperScale) - implicitWidth / 2)
topMargin: bgRoot.movableYSpace + ((root.fixedClockPosition ? root.fixedClockY : bgRoot.clockY * bgRoot.effectiveWallpaperScale) - implicitHeight / 2)
Behavior on leftMargin {
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}

View file

@ -116,10 +116,7 @@ Scope {
bottom: Appearance.sizes.barHeight
left: (mediaControlsRoot.screen.width / 2) - (osdWidth / 2) - widgetWidth
}
implicitWidth: {
console.log(root.widgetWidth)
return root.widgetWidth
}
implicitWidth: root.widgetWidth
implicitHeight: playerColumnLayout.implicitHeight
color: "transparent"
WlrLayershell.namespace: "quickshell:mediaControls"

View file

@ -44,10 +44,30 @@ def find_least_busy_region(image_path, region_width=300, region_height=200, scre
print(f"Using original image size: {orig_w}x{orig_h}")
arr = img.astype(np.float64)
h, w = arr.shape
# Validate & adjust stride
stride = max(1, int(stride) if stride else 1)
# Adjust region size if it does not fit given padding
if horizontal_padding * 2 >= w or vertical_padding * 2 >= h:
# Reduce padding to fit at least a 1x1 region
horizontal_padding = max(0, min(horizontal_padding, (w - 1) // 2))
vertical_padding = max(0, min(vertical_padding, (h - 1) // 2))
max_region_w = w - 2 * horizontal_padding
max_region_h = h - 2 * vertical_padding
if max_region_w <= 0 or max_region_h <= 0:
raise ValueError("Image too small for the specified padding.")
if region_width > max_region_w:
if verbose:
print(f"Requested region_width {region_width} too large; clamping to {max_region_w}")
region_width = max_region_w
if region_height > max_region_h:
if verbose:
print(f"Requested region_height {region_height} too large; clamping to {max_region_h}")
region_height = max_region_h
# Use OpenCV's integral for fast computation
integral = cv2.integral(arr, sdepth=cv2.CV_64F)[1:,1:]
integral_sq = cv2.integral(arr**2, sdepth=cv2.CV_64F)[1:,1:]
def region_sum(ii, x1, y1, x2, y2):
# Assume bounds have been checked before calling
total = ii[y2, x2]
if x1 > 0:
total -= ii[y2, x1-1]
@ -57,16 +77,22 @@ def find_least_busy_region(image_path, region_width=300, region_height=200, scre
total += ii[y1-1, x1-1]
return total
min_var = None
min_coords = (0, 0)
min_coords = (horizontal_padding, vertical_padding)
area = region_width * region_height
x_start = horizontal_padding
y_start = vertical_padding
x_end = w - region_width - horizontal_padding + 1
y_end = h - region_height - vertical_padding + 1
for y in range(y_start, max(y_end, y_start+1), stride):
for x in range(x_start, max(x_end, x_start+1), stride):
if x_end < x_start:
x_end = x_start
if y_end < y_start:
y_end = y_start
for y in range(y_start, y_end + 1, stride):
for x in range(x_start, x_end + 1, stride):
x1, y1 = x, y
x2, y2 = x + region_width - 1, y + region_height - 1
if x2 >= w or y2 >= h:
continue # Skip out-of-bounds window
s = region_sum(integral, x1, y1, x2, y2)
s2 = region_sum(integral_sq, x1, y1, x2, y2)
mean = s / area
@ -81,6 +107,7 @@ def find_largest_region(image_path, screen_width=None, screen_height=None, verbo
if img is None:
raise FileNotFoundError(f"Image not found: {image_path}")
orig_h, orig_w = img.shape
# ...existing scaling logic...
scale = 1.0
if screen_width is not None and screen_height is not None:
scale_w = screen_width / orig_w
@ -102,6 +129,12 @@ def find_largest_region(image_path, screen_width=None, screen_height=None, verbo
print(f"Using original image size: {orig_w}x{orig_h}")
arr = img.astype(np.float64)
h, w = arr.shape
stride = max(1, int(stride) if stride else 1)
threshold = max(0.0, float(threshold))
# Adjust padding if image too small
if horizontal_padding * 2 >= w or vertical_padding * 2 >= h:
horizontal_padding = max(0, min(horizontal_padding, (w - 1) // 2))
vertical_padding = max(0, min(vertical_padding, (h - 1) // 2))
# Use OpenCV's integral for fast computation
integral = cv2.integral(arr, sdepth=cv2.CV_64F)[1:,1:]
integral_sq = cv2.integral(arr**2, sdepth=cv2.CV_64F)[1:,1:]
@ -115,29 +148,44 @@ def find_largest_region(image_path, screen_width=None, screen_height=None, verbo
total += ii[y1-1, x1-1]
return total
min_size = 10
max_size = min(h, int(w / aspect_ratio)) if aspect_ratio >= 1.0 else min(int(h * aspect_ratio), w)
# Determine maximum feasible size respecting padding
effective_w = w - 2 * horizontal_padding
effective_h = h - 2 * vertical_padding
if effective_w <= 0 or effective_h <= 0:
return None, (0, 0), None
# Largest square-ish dimension given aspect ratio and effective space
if aspect_ratio >= 1.0:
max_size = min(effective_h, int(effective_w / aspect_ratio))
else:
max_size = min(int(effective_h * aspect_ratio), effective_w)
if max_size < min_size:
min_size = 1
max_size = max(1, max_size)
best = None
best_size = min_size
while min_size <= max_size:
mid = (min_size + max_size) // 2
if aspect_ratio >= 1.0:
region_h = mid
region_w = int(mid * aspect_ratio)
region_w = int(round(mid * aspect_ratio))
else:
region_w = mid
region_h = int(mid / aspect_ratio)
if region_w > w or region_h > h:
region_h = int(round(mid / aspect_ratio if aspect_ratio != 0 else mid))
if region_w <= 0 or region_h <= 0:
break
if region_w > effective_w or region_h > effective_h:
max_size = mid - 1
continue
found = False
x_start = horizontal_padding
y_start = vertical_padding
x_end = w - region_w - horizontal_padding + 1
y_end = h - region_h - vertical_padding + 1
for y in range(y_start, max(y_end, y_start+1), stride):
for x in range(x_start, max(x_end, x_start+1), stride):
x_end = w - region_w - horizontal_padding
y_end = h - region_h - vertical_padding
for y in range(y_start, y_end + 1, stride):
for x in range(x_start, x_end + 1, stride):
x1, y1 = x, y
x2, y2 = x + region_w - 1, y + region_h - 1
if x2 >= w or y2 >= h:
continue
s = region_sum(integral, x1, y1, x2, y2)
s2 = region_sum(integral_sq, x1, y1, x2, y2)
area = region_w * region_h
@ -150,7 +198,6 @@ def find_largest_region(image_path, screen_width=None, screen_height=None, verbo
if found:
break
if found:
best_size = mid
min_size = mid + 1
else:
max_size = mid - 1
@ -181,7 +228,7 @@ def draw_region(image_path, coords, region_width=300, region_height=200, output_
x, y = coords
cv2.rectangle(img, (x, y), (x+region_width-1, y+region_height-1), (0,0,255), 3)
cv2.imwrite(output_path, img)
print(f"Saved output image with rectangle at {output_path}")
# print removed for quieter operation
def draw_largest_region(image_path, center, size, output_path='output.png', screen_width=None, screen_height=None, screen_mode="fill"):
img = cv2.imread(image_path)
@ -207,7 +254,7 @@ def draw_largest_region(image_path, center, size, output_path='output.png', scre
y2 = cy + region_h // 2 - 1
cv2.rectangle(img, (x1, y1), (x2, y2), (255,0,0), 3)
cv2.imwrite(output_path, img)
print(f"Saved output image with largest region at {output_path}")
# print removed for quieter operation
def get_dominant_color(image_path, x, y, w, h, screen_width=None, screen_height=None, screen_mode="fill"):
img = cv2.imread(image_path)