wallpaper-engine-dsh 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -2
- package/README.zh.md +10 -2
- package/lib/client.js +105 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,11 +8,11 @@ A DSH bundle that turns your local **Wallpaper Engine** library into the live ba
|
|
|
8
8
|
|
|
9
9
|
**The library, rendered live.** The grid lists every wallpaper the browser can genuinely render — video and web wallpapers. Scene and application wallpapers are Wallpaper Engine's private `.pkg` scene packages; since no browser can execute them, they are filtered out rather than offered as degraded stills. Everything listed plays for real, badged Video or Web, and a search box narrows large libraries by title or workshop id instantly.
|
|
10
10
|
|
|
11
|
-
**Legibility on any wallpaper.** Text stays readable by construction, not by luck. The veil always opposes the text colour — black in the dark theme, white in the light theme — so neither a pitch-black nor a pure-white wallpaper can swallow the UI. On top of that, a Smart veil samples the wallpaper's brightness every few seconds and automatically strengthens the veil when a scene drifts too bright (or too dark) for the current theme (web wallpapers' pixels are unreadable inside the sandbox, so their preview still stands in as the sample)
|
|
11
|
+
**Legibility on any wallpaper.** Text stays readable by construction, not by luck. The veil always opposes the text colour — black in the dark theme, white in the light theme — so neither a pitch-black nor a pure-white wallpaper can swallow the UI. On top of that, a Smart veil samples the wallpaper's brightness every few seconds and automatically strengthens the veil when a scene drifts too bright (or too dark) for the current theme (web wallpapers' pixels are unreadable inside the sandbox, so their preview still stands in as the sample). While a wallpaper is active, dropdown menus, the slash-command popup, the queue-dock panel, the settings dialog, and the image lightbox all render as frosted glass: the shell's own menu primitive carries an isolation property that silently kills its internal blur layer, so the plugin applies the blur on the surface element itself and deepens the menu fill, keeping overlay text readable over any wallpaper. Everything reverts to the host look when the wallpaper is off.
|
|
12
12
|
|
|
13
13
|
**Manual framing.** Pick a base layout — Cover, Contain, Stretch, Original, or Free — then frame the shot yourself. **Adjust** opens the live wallpaper fullscreen: scroll to zoom, drag to pan. In the first four layouts the crop is clamped so the image always fills the screen with no exposed edges; **Free** places the wallpaper at natural size on a black canvas where it can be dragged anywhere, zoomed from 0.1× to 4×, and rotated to any angle (±90° buttons or Alt+drag), with just enough kept on screen that it can never be dragged out of sight. **Mirror** flips the wallpaper horizontally and works in every layout — a flip never exposes an edge. Esc or Done finishes, the framing persists, and **Reset crop** restores the default in one click. Web wallpapers take the same select and the same zoom/pan/rotate framing — the transform applies to the iframe directly.
|
|
14
14
|
|
|
15
|
-
**Four live sliders.** Wallpaper blur, Scrim, Borders, and Glass — every change lands instantly and persists. Blur renders in place: composition, layout, and crop stay identical at every blur level, and within one blur radius of the screen edge the picture fades softly into the veil beneath the UI chrome. A whisper of dither noise keeps smooth gradients band-free; at zero blur the media bypasses the filter pipeline entirely for bit-exact pixels.
|
|
15
|
+
**Four live sliders.** Wallpaper blur, Scrim, Borders, and Glass — every change lands instantly and persists. Blur renders in place: composition, layout, and crop stay identical at every blur level, and within one blur radius of the screen edge the picture fades softly into the veil beneath the UI chrome. A whisper of dither noise keeps smooth gradients band-free; at zero blur the media bypasses the filter pipeline entirely for bit-exact pixels. The Glass slider's colour melt is anchored to the shell's own menu material: at the 40px ceiling it reproduces the host recipe blur(40px) saturate(150%) exactly, so full glass reads as one system with the shell's native frost.
|
|
16
16
|
|
|
17
17
|
**Rotation lists.** Build any number of carousel lists, each with its own wallpapers, interval (1–120 min), and order (sequence or random). Auto-rotate arms once the active list holds at least two usable wallpapers; the status row always reports whether rotation is actually running. Your first playable Wallpaper Engine playlist is imported automatically on first run; any other playlist can be imported into any list.
|
|
18
18
|
|
|
@@ -48,6 +48,14 @@ Restart `dsh web`, then open **Settings → General → Wallpaper Engine**.
|
|
|
48
48
|
|
|
49
49
|
Your selection and every knob persist in the browser's `localStorage`.
|
|
50
50
|
|
|
51
|
+
## Desktop
|
|
52
|
+
|
|
53
|
+
The desktop shell and the browser share the same frontend and the same injection pipeline; the `platform: "web"` declaration works as-is, with no separate desktop package.
|
|
54
|
+
|
|
55
|
+
- **Windows**: the main window is opaque and the wallpaper renders at the DOM layer. The window-controls strip at the top is an opaque host-owned overlay; the plugin blends the wallpaper into it with a short fade in the overlay's own colour, and the fade switches off in fullscreen.
|
|
56
|
+
- **macOS**: the shell sidebar is the system's native vibrant material, so what shows behind the wallpaper there is the system material rather than the wallpaper itself — host behaviour.
|
|
57
|
+
- **With system transparency effects off** (`prefers-reduced-transparency`), all glass and blur falls back to solid surfaces; the wallpaper stays, and legibility is carried by the veil and the solids.
|
|
58
|
+
|
|
51
59
|
## How it works
|
|
52
60
|
|
|
53
61
|
The bundle has two halves:
|
package/README.zh.md
CHANGED
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
**只列出能真实播放的壁纸。** 网格中列出浏览器可以真实渲染的全部类型——视频与网页壁纸。场景/应用壁纸是 Wallpaper Engine 私有的 `.pkg` 场景包,浏览器无法执行,因此直接过滤,不以降级的静态图代替。列出的每张壁纸都真实播放,并按 视频/网页 标注类型;搜索框可按标题或创意工坊 ID 筛选较大的壁纸库。
|
|
10
10
|
|
|
11
|
-
**任何壁纸上文字都可读。** 遮罩颜色始终与文字颜色相反:深色主题用黑色遮罩,浅色主题用白色遮罩,因此过亮或过暗的壁纸都不会盖住文字。在此基础上,「智能可视」每隔几秒采样一次壁纸亮度,亮度过高或过低时自动加强遮罩(网页壁纸的像素在沙箱中读不到,改用其预览图作为采样依据)
|
|
11
|
+
**任何壁纸上文字都可读。** 遮罩颜色始终与文字颜色相反:深色主题用黑色遮罩,浅色主题用白色遮罩,因此过亮或过暗的壁纸都不会盖住文字。在此基础上,「智能可视」每隔几秒采样一次壁纸亮度,亮度过高或过低时自动加强遮罩(网页壁纸的像素在沙箱中读不到,改用其预览图作为采样依据)。壁纸激活时,下拉菜单、斜杠命令提示框、队列面板、设置弹窗与图片灯箱统一为磨砂玻璃:外壳的菜单原语自身带隔离属性,其内部模糊层在宿主原样下并不生效,插件改为在 surface 元素上施加模糊,并把菜单底色加深,保证浮层文字在任意壁纸上可读;关闭壁纸后恢复宿主原样。
|
|
12
12
|
|
|
13
13
|
**手动取景。** 先选基础排布(填充、适应、拉伸、原始、自由),再手动调整画面:点「调整画面」将壁纸全屏展开,滚轮缩放,拖动平移。前四种排布下裁剪范围经过限制,画面始终铺满屏幕,不露出边缘;「自由」把壁纸按原始大小放在黑色画布上,可拖动到任意位置,缩放范围 0.1–4×,并可旋转任意角度(±90° 按钮或 Alt+拖动),同时始终保留一小块在屏幕内,不会拖丢。「镜像」水平翻转壁纸,所有排布下都可用——翻转不会破坏铺满。按 Esc 或点「完成」退出,取景设置会保存,「重置裁剪」可一键恢复默认。网页壁纸使用相同的排布下拉与缩放/平移/旋转取景(变换直接作用于 iframe)。
|
|
14
14
|
|
|
15
|
-
**四个实时滑杆。**
|
|
15
|
+
**四个实时滑杆。** 壁纸模糊、暗化、边框、玻璃,每一步调节立即生效并保存。模糊在原位渲染:任意模糊度下,画面的比例、排布与取景完全一致;屏幕边缘一个模糊半径内的画面向遮罩过渡,被界面边饰覆盖,通常不可见。模糊时叠加轻微噪声,消除渐变色带;模糊为零时媒体完全绕过滤镜管线,像素保持不变。玻璃滑杆的「色彩熔融」在 40px 满档时正好等于外壳官方菜单材质的配方(blur(40px) saturate(150%)),满档玻璃与外壳原生磨砂观感一致。
|
|
16
16
|
|
|
17
17
|
**轮播列表。** 可以创建任意多个列表,各自指定壁纸集合、切换间隔(1–120 分钟)与顺序(顺序/随机)。当前列表至少有两张可用壁纸时才会自动轮转;状态行始终显示轮转是否正在运行。首次运行会自动导入第一个可播放的 Wallpaper Engine 播放列表,其他播放列表也可随时导入到任意列表。
|
|
18
18
|
|
|
@@ -48,6 +48,14 @@ dsh plugin --profile web add link:<克隆文件夹的绝对路径>
|
|
|
48
48
|
|
|
49
49
|
你的选择与每一项调节都持久化在浏览器的 `localStorage` 中。
|
|
50
50
|
|
|
51
|
+
## 桌面端
|
|
52
|
+
|
|
53
|
+
桌面端与浏览器共用同一前端和同一注入管道,`platform: "web"` 声明即可生效,无需单独的桌面包。
|
|
54
|
+
|
|
55
|
+
- **Windows**:主窗口不透明,壁纸渲染在 DOM 层。顶部窗口控制按钮条是宿主维护的实色 overlay,插件用一条与 overlay 同色的短渐变把壁纸衔接过去,弱化接缝;进入全屏时自动关闭。
|
|
56
|
+
- **macOS**:外壳侧栏为系统原生 vibrant 材质,壁纸在其后播放时透出的是系统材质而非壁纸本身,为外壳既定行为。
|
|
57
|
+
- **系统关闭透明效果**(`prefers-reduced-transparency`)时,玻璃与模糊全部退为实色表面,壁纸保留,可读性由遮罩与实色表面保证。
|
|
58
|
+
|
|
51
59
|
## 工作原理
|
|
52
60
|
|
|
53
61
|
bundle 分为两半:
|
package/lib/client.js
CHANGED
|
@@ -10,10 +10,11 @@ window.__ModuleLoader__.load({
|
|
|
10
10
|
const SETTINGS_KEY = "wallpaper-engine-dsh:selection";
|
|
11
11
|
const INVENTORY_URL = "/we-background/inventory";
|
|
12
12
|
const ACTIVE_ATTR = "data-webg-wallpaper";
|
|
13
|
-
// Plugin-owned dark-theme signal for CSS. The shell's
|
|
14
|
-
// attribute
|
|
15
|
-
//
|
|
16
|
-
//
|
|
13
|
+
// Plugin-owned dark-theme signal for CSS. The shell's own dark-mode body
|
|
14
|
+
// attribute still exists in 0.2.1-rc.5 (its writer moved to the layout
|
|
15
|
+
// theme presenter), but the stylesheet never keys off host DOM internals:
|
|
16
|
+
// the client derives dark from the shell's theme service and mirrors it
|
|
17
|
+
// here, so a host-side restructure can never silently break the glass.
|
|
17
18
|
const DARK_ATTR = "data-webg-dark";
|
|
18
19
|
const LAYER_ID = "wallpaper-engine-dsh-layer";
|
|
19
20
|
const SCRIM_ID = "wallpaper-engine-dsh-scrim";
|
|
@@ -1203,9 +1204,22 @@ window.__ModuleLoader__.load({
|
|
|
1203
1204
|
s.setProperty("--webg-scrim-color", veilColor);
|
|
1204
1205
|
s.setProperty("--webg-border-alpha", String(selection.border));
|
|
1205
1206
|
s.setProperty("--webg-blur", selection.blur + "px");
|
|
1206
|
-
// The glass "colour melt"
|
|
1207
|
-
s
|
|
1207
|
+
// The glass "colour melt" anchors at the shell's own menu material: the
|
|
1208
|
+
// slider's 40px ceiling reproduces the host recipe blur(40px) saturate(150%)
|
|
1209
|
+
// exactly, so full glass and the host's frosted chrome read as one system.
|
|
1210
|
+
s.setProperty("--webg-saturate", String(1 + selection.blur * 0.0125));
|
|
1208
1211
|
s.setProperty("--webg-glass-brightness", "1.04");
|
|
1212
|
+
// Modal masks (settings dialog, image lightbox) read the shell's mask-blur
|
|
1213
|
+
// token — wire it to the glass slider so modals frost the app behind them
|
|
1214
|
+
// instead of showing the wallpaper sharply through a translucent mask.
|
|
1215
|
+
// Capped: a 40px blur on a full-viewport backdrop costs more GPU than the
|
|
1216
|
+
// effect is worth.
|
|
1217
|
+
// Gated on an active selection: this is a HOST token, so masks must not
|
|
1218
|
+
// blur the app while no wallpaper runs. At 0 blur: none - no layer, no cost.
|
|
1219
|
+
s.setProperty("--dsw-mask-blur",
|
|
1220
|
+
selection.id && selection.blur > 0
|
|
1221
|
+
? "blur(" + Math.min(selection.blur, 20) + "px)"
|
|
1222
|
+
: "none");
|
|
1209
1223
|
// At 0 blur, keep the media OUT of the filter pipeline entirely: even
|
|
1210
1224
|
// blur(0px) forces an extra raster/compositing pass, and the noise overlay
|
|
1211
1225
|
// would still occupy a layer at opacity 0. filter:none + display:none keep
|
|
@@ -1243,6 +1257,7 @@ window.__ModuleLoader__.load({
|
|
|
1243
1257
|
s.removeProperty("--webg-scrim-color");
|
|
1244
1258
|
s.removeProperty("--webg-border-alpha");
|
|
1245
1259
|
s.removeProperty("--webg-blur");
|
|
1260
|
+
s.removeProperty("--dsw-mask-blur"); // restore the host's own mask token
|
|
1246
1261
|
s.removeProperty("--webg-saturate");
|
|
1247
1262
|
s.removeProperty("--webg-glass-brightness");
|
|
1248
1263
|
s.removeProperty("--webg-media-filter");
|
|
@@ -1952,14 +1967,91 @@ window.__ModuleLoader__.load({
|
|
|
1952
1967
|
}
|
|
1953
1968
|
body[${ACTIVE_ATTR}] [data-composer-card],
|
|
1954
1969
|
body[${ACTIVE_ATTR}] [class*="_bubble"] {
|
|
1955
|
-
background-image: linear-gradient(
|
|
1956
|
-
-webkit-backdrop-filter: blur(var(--webg-blur, 16px)) saturate(var(--webg-saturate, 1.
|
|
1957
|
-
backdrop-filter: blur(var(--webg-blur, 16px)) saturate(var(--webg-saturate, 1.
|
|
1970
|
+
background-image: linear-gradient(165deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.06) 32%, rgba(255, 255, 255, 0.02));
|
|
1971
|
+
-webkit-backdrop-filter: blur(var(--webg-blur, 16px)) saturate(var(--webg-saturate, 1.2)) brightness(var(--webg-glass-brightness, 1.04)) contrast(1.01);
|
|
1972
|
+
backdrop-filter: blur(var(--webg-blur, 16px)) saturate(var(--webg-saturate, 1.2)) brightness(var(--webg-glass-brightness, 1.04)) contrast(1.01);
|
|
1958
1973
|
box-shadow:
|
|
1959
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.
|
|
1960
|
-
inset 0 -1px 0 rgba(255, 255, 255, 0.
|
|
1961
|
-
inset 0 0 0 0.5px rgba(255, 255, 255, 0.
|
|
1962
|
-
0 12px 40px rgba(0, 0, 0, 0.
|
|
1974
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.36),
|
|
1975
|
+
inset 0 -1px 0 rgba(255, 255, 255, 0.10),
|
|
1976
|
+
inset 0 0 0 0.5px rgba(255, 255, 255, 0.10),
|
|
1977
|
+
0 12px 40px rgba(0, 0, 0, 0.14);
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
/* Menu + queue-dock surface repair (wallpaper active). The shell's
|
|
1981
|
+
menu primitive parks fill and blur on a child layer while the
|
|
1982
|
+
surface element itself is isolated - an isolated ancestor forms
|
|
1983
|
+
a backdrop root, so the blur only samples the panel interior.
|
|
1984
|
+
Same on the queue dock panel (:before carries the blur). With a
|
|
1985
|
+
wallpaper active, menus showed sharp content through a 45% fill.
|
|
1986
|
+
An element's OWN backdrop-filter ignores its own isolation, so
|
|
1987
|
+
the filter moves onto the surface element; fill deepened 72%. */
|
|
1988
|
+
body[${ACTIVE_ATTR}] { --dsw-menu-surface-fill: rgba(67, 69, 74, 0.72); }
|
|
1989
|
+
body[${ACTIVE_ATTR}]:not([${DARK_ATTR}]) { --dsw-menu-surface-fill: rgba(248, 249, 250, 0.72); }
|
|
1990
|
+
body[${ACTIVE_ATTR}] [data-menu-material],
|
|
1991
|
+
body[${ACTIVE_ATTR}] [data-composer-dock] [class*="_panel"] {
|
|
1992
|
+
-webkit-backdrop-filter: blur(var(--webg-blur, 16px)) saturate(var(--webg-saturate, 1.2)) brightness(var(--webg-glass-brightness, 1.04)) contrast(1.01);
|
|
1993
|
+
backdrop-filter: blur(var(--webg-blur, 16px)) saturate(var(--webg-saturate, 1.2)) brightness(var(--webg-glass-brightness, 1.04)) contrast(1.01);
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
/* Settings modal and sibling dialogs: the shell paints dialogs on
|
|
1997
|
+
an opaque layer-2 panel. While a wallpaper is active, dialogs
|
|
1998
|
+
join the glass system - the mask behind them already frosts the
|
|
1999
|
+
app (the mask blur token is wired to the glass slider in
|
|
2000
|
+
applyEffects). color-mix keeps the host hue at 80% opacity.
|
|
2001
|
+
[class*="_dialog_"] matches only the module-suffix panel class;
|
|
2002
|
+
compounds like _dialogHeader lack the underscore segment. */
|
|
2003
|
+
body[${ACTIVE_ATTR}] [class*="_dialog_"] {
|
|
2004
|
+
background-color: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 80%, transparent);
|
|
2005
|
+
-webkit-backdrop-filter: blur(var(--webg-blur, 16px)) saturate(var(--webg-saturate, 1.2)) brightness(var(--webg-glass-brightness, 1.04)) contrast(1.01);
|
|
2006
|
+
backdrop-filter: blur(var(--webg-blur, 16px)) saturate(var(--webg-saturate, 1.2)) brightness(var(--webg-glass-brightness, 1.04)) contrast(1.01);
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
/* Windows desktop: the window-controls strip is an opaque host
|
|
2010
|
+
overlay (titleBarOverlay colour, fed from the renderer-measured
|
|
2011
|
+
palette). Blend the wallpaper up into it with a short fade from
|
|
2012
|
+
the overlay's own colour (dark #1b1b1c / light #f9fafb), scoped
|
|
2013
|
+
to the desktop marker html[data-windows-titlebar] (absent in
|
|
2014
|
+
browsers) and off in fullscreen. Pure CSS: the fill var flips
|
|
2015
|
+
with the plugin dark mirror attribute, no JS involved. */
|
|
2016
|
+
body[${DARK_ATTR}] { --webg-titlebar-fill: #1b1b1c; }
|
|
2017
|
+
body:not([${DARK_ATTR}]) { --webg-titlebar-fill: #f9fafb; }
|
|
2018
|
+
html[data-windows-titlebar]:not([data-fullscreen]) body[${ACTIVE_ATTR}] .webg-scrim::before {
|
|
2019
|
+
content: ""; position: absolute; top: 0; left: 0; right: 0;
|
|
2020
|
+
height: var(--dsh-windows-titlebar-height, 40px);
|
|
2021
|
+
background: linear-gradient(var(--webg-titlebar-fill, #1b1b1c), transparent);
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
/* Accessibility: prefers-reduced-transparency (Windows transparency
|
|
2025
|
+
effects off, macOS Reduce transparency). Glass off, surfaces back
|
|
2026
|
+
to solid fills; the wallpaper stays, legibility carried by the
|
|
2027
|
+
veil and the solids. Selectors mirror the glass rules above so
|
|
2028
|
+
this block wins by document order. */
|
|
2029
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
2030
|
+
body[${ACTIVE_ATTR}] {
|
|
2031
|
+
--dsw-specific-input-major: #26272c;
|
|
2032
|
+
--dsw-specific-bubble: #26272c;
|
|
2033
|
+
--dsw-menu-surface-fill: #43454a;
|
|
2034
|
+
--dsw-mask-blur: none !important;
|
|
2035
|
+
}
|
|
2036
|
+
body[${ACTIVE_ATTR}]:not([${DARK_ATTR}]) {
|
|
2037
|
+
--dsw-specific-input-major: #f8f9fa;
|
|
2038
|
+
--dsw-specific-bubble: #f4f5f6;
|
|
2039
|
+
--dsw-menu-surface-fill: #f8f9fa;
|
|
2040
|
+
--dsw-mask-blur: none !important;
|
|
2041
|
+
}
|
|
2042
|
+
body[${ACTIVE_ATTR}] [data-composer-card],
|
|
2043
|
+
body[${ACTIVE_ATTR}] [class*="_bubble"],
|
|
2044
|
+
body[${ACTIVE_ATTR}] [data-menu-material],
|
|
2045
|
+
body[${ACTIVE_ATTR}] [data-composer-dock] [class*="_panel"],
|
|
2046
|
+
body[${ACTIVE_ATTR}] [class*="_dialog_"] {
|
|
2047
|
+
-webkit-backdrop-filter: none;
|
|
2048
|
+
backdrop-filter: none;
|
|
2049
|
+
background-image: none;
|
|
2050
|
+
box-shadow: var(--dsw-elevation-soft, 0 3px 8px rgba(0, 0, 0, 0.08));
|
|
2051
|
+
}
|
|
2052
|
+
body[${ACTIVE_ATTR}] [class*="_dialog_"] {
|
|
2053
|
+
background-color: var(--dsw-alias-bg-layer-2);
|
|
2054
|
+
}
|
|
1963
2055
|
}
|
|
1964
2056
|
|
|
1965
2057
|
/* ── Picker chrome (token-driven, theme-aware) ── */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wallpaper-engine-dsh",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Wallpaper Engine library as the DSH web GUI background — video/web/still wallpapers, rotation lists, search, resource monitor, bilingual UI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|