OpenRGB dedup fix, device card URL badge overflow fix

- Replace threshold-based dedup with exact equality check in OpenRGB client;
  threshold dedup caused animation stutter at low software brightness
- Add brightness_control capability to OpenRGB provider (software simulated)
- Fix device card URL/COM badge overlapping close button: badge stays inside
  card-title flex container, both name and badge truncate with ellipsis

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-17 01:36:36 +03:00
parent 29b43b028d
commit bcba5f33fc
3 changed files with 14 additions and 5 deletions

View File

@@ -96,7 +96,7 @@ class OpenRGBLEDClient(LEDClient):
self._send_pending: Optional[Tuple[np.ndarray, int]] = None # (pixels, brightness)
self._send_thread: Optional[threading.Thread] = None
self._send_stop = threading.Event()
self._last_sent_pixels: Optional[np.ndarray] = None # for change-threshold dedup
self._last_sent_pixels: Optional[np.ndarray] = None
async def connect(self) -> bool:
"""Connect to OpenRGB server and access the target device."""
@@ -295,10 +295,10 @@ class OpenRGBLEDClient(LEDClient):
# Change-threshold dedup — compare RAW pixels before brightness scaling
# so low brightness doesn't crush differences below the threshold.
# GPU I2C/SMBus writes cause system-wide stalls; minimizing writes is critical.
# Exact-match dedup — skip only if pixels are identical to last sent frame.
# Threshold-based dedup caused stutter at low brightness.
if self._last_sent_pixels is not None and self._last_sent_pixels.shape == pixel_array.shape:
diff = np.mean(np.abs(pixel_array.astype(np.int16) - self._last_sent_pixels.astype(np.int16)))
if diff < 2.0:
if np.array_equal(pixel_array, self._last_sent_pixels):
return
self._last_sent_pixels = pixel_array.copy()

View File

@@ -451,6 +451,15 @@ body.cs-drag-active .card-drag-handle {
font-family: monospace;
text-decoration: none;
transition: background 0.2s;
white-space: nowrap;
flex-shrink: 1;
overflow: hidden;
min-width: 0;
}
.device-url-text {
overflow: hidden;
text-overflow: ellipsis;
}
.device-url-badge:hover {

View File

@@ -156,7 +156,7 @@ export function createDeviceCard(device) {
<div class="card-header">
<div class="card-title" title="${escapeHtml(device.name || device.id)}">
<span class="health-dot ${healthClass}" title="${healthTitle}"></span>
${device.name || device.id}
<span class="card-title-text">${device.name || device.id}</span>
${device.url && device.url.startsWith('http') ? `<a class="device-url-badge" href="${device.url}" target="_blank" rel="noopener" title="${t('device.button.webui')}"><span class="device-url-text">${escapeHtml(device.url.replace(/^https?:\/\//, ''))}</span><span class="device-url-icon">${ICON_WEB}</span></a>` : (device.url && !device.url.startsWith('mock://') && !device.url.startsWith('ws://') && !device.url.startsWith('openrgb://') && !device.url.startsWith('http') ? `<span class="device-url-badge"><span class="device-url-text">${escapeHtml(device.url)}</span></span>` : '')}
${healthLabel}
</div>