Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions windows/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

### 新增

- Windows 系统托盘新增「壁纸透出」滑杆;100% 时视频保持原始画面,整页主题蒙层降为零,并随当前主题持久化;拖动滑杆不会重新传输整段视频。
- Windows 主题仓库与托盘支持本地 MP4/WebM 动态壁纸;视频静音循环、页面隐藏时暂停,并可像图片主题一样保存和切换。
- 视频采用上限 128 MB、单块 512 KiB 的 CDP 分块传输,在 renderer 内组装为 Blob URL,避免把完整视频塞进 early bootstrap payload;换主题、暂停和清理时会释放播放器与 Blob URL。
- MP4/WebM 导入会校验扩展名、最小容器签名、大小、受管目录边界和 reparse point,伪造扩展名或越界路径会在复制前拒绝。

### 修复

- 浅色与深色外观现在都为原生应用菜单提供稳定的半透明可读性层,并强制菜单文字与图标使用完整主题前景色;动态视频模式还会单独保护第二层 Codex 工具栏,避免画面逐帧变化导致顶栏内容失去对比度。
- 兼容新版 Codex 不再提供 `[role="main"]` 的任务页面:回退到 `main.main-surface` 承载任务背景,收起左侧边栏后也不会清除皮肤。
- 任务页回退模式保留原生固定顶栏,并移除顶栏半透明底色与主区顶部渐隐造成的横向断层。
- 托盘右键菜单允许从空的 `ToolStripItemCollection` 开始填充,避免首次展开时触发参数绑定异常。
Expand Down
1 change: 1 addition & 0 deletions windows/README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Next, use the generated screenshot to check horizontal overflow and text contras
Open `Codex Dream Skin - Tray` to:

- Import a PNG, JPEG, or WebP background, or an MP4/WebM animated wallpaper.
- Adjust wallpaper reveal: at 100% the video stays at its original opacity while the full-window theme veil reaches zero; the value persists with the theme.
- Save the active theme and switch through saved themes.
- Pause or resume the skin.
- Reapply the theme or fully restore Codex.
Expand Down
1 change: 1 addition & 0 deletions windows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\verify-dream-s
打开 `Codex Dream Skin - Tray` 后可以:

- 更换 PNG、JPEG、WebP 背景图,或 MP4、WebM 动态壁纸。
- 使用「壁纸透出」滑杆调整覆盖在壁纸上的主题面板:100% 时视频保持原始画面,整页主题蒙层为零;设置会随主题持久化。
- 保存当前主题并从「已保存主题」切换。
- 暂停或继续显示皮肤。
- 重新应用主题,或完整恢复 Codex。
Expand Down
100 changes: 72 additions & 28 deletions windows/assets/dream-skin.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,28 @@
--dream-accent-hover: color-mix(in oklab, var(--dream-accent) 20%, var(--dream-surface));
--dream-hero-shade: color-mix(in oklab, var(--dream-surface) 93%, transparent);
--dream-ambient-opacity: .18;
--dream-wallpaper-reveal: 1;
--dream-wallpaper-cover: 0%;
--dream-media-overlay: color-mix(in oklab, var(--dream-canvas) var(--dream-wallpaper-cover), transparent);
--dream-shadow: 0 16px 42px color-mix(in oklab, var(--dream-accent) 9%, transparent);
--dream-immersive-edge: color-mix(in oklab, var(--dream-surface) 46%, transparent);
--dream-immersive-mid: color-mix(in oklab, var(--dream-surface) 28%, transparent);
--dream-immersive-far: color-mix(in oklab, var(--dream-surface) 14%, transparent);
--dream-immersive-sidebar: color-mix(in oklab, var(--dream-sidebar) 50%, transparent);
--dream-task-immersive-sidebar: color-mix(in oklab, var(--dream-sidebar) 72%, transparent);
--dream-immersive-edge-base: color-mix(in oklab, var(--dream-surface) 46%, transparent);
--dream-immersive-mid-base: color-mix(in oklab, var(--dream-surface) 28%, transparent);
--dream-immersive-far-base: color-mix(in oklab, var(--dream-surface) 14%, transparent);
--dream-immersive-sidebar-base: color-mix(in oklab, var(--dream-sidebar) 50%, transparent);
--dream-task-immersive-sidebar-base: color-mix(in oklab, var(--dream-sidebar) 72%, transparent);
--dream-task-immersive-edge-base: color-mix(in oklab, var(--dream-surface) 86%, transparent);
--dream-task-immersive-mid-base: color-mix(in oklab, var(--dream-surface) 78%, transparent);
--dream-task-immersive-far-base: color-mix(in oklab, var(--dream-surface) 66%, transparent);
--dream-immersive-edge: color-mix(in oklab, var(--dream-immersive-edge-base) var(--dream-wallpaper-cover), transparent);
--dream-immersive-mid: color-mix(in oklab, var(--dream-immersive-mid-base) var(--dream-wallpaper-cover), transparent);
--dream-immersive-far: color-mix(in oklab, var(--dream-immersive-far-base) var(--dream-wallpaper-cover), transparent);
--dream-immersive-sidebar: color-mix(in oklab, var(--dream-immersive-sidebar-base) var(--dream-wallpaper-cover), transparent);
--dream-task-immersive-sidebar: color-mix(in oklab, var(--dream-task-immersive-sidebar-base) var(--dream-wallpaper-cover), transparent);
--dream-task-immersive-edge: color-mix(in oklab, var(--dream-task-immersive-edge-base) var(--dream-wallpaper-cover), transparent);
--dream-task-immersive-mid: color-mix(in oklab, var(--dream-task-immersive-mid-base) var(--dream-wallpaper-cover), transparent);
--dream-task-immersive-far: color-mix(in oklab, var(--dream-task-immersive-far-base) var(--dream-wallpaper-cover), transparent);
--dream-immersive-composer: color-mix(in oklab, var(--dream-surface-raised) 76%, var(--dream-accent) 4%);
--dream-immersive-line: color-mix(in oklab, var(--dream-line) 76%, transparent);
--dream-task-immersive-edge: color-mix(in oklab, var(--dream-surface) 86%, transparent);
--dream-task-immersive-mid: color-mix(in oklab, var(--dream-surface) 78%, transparent);
--dream-task-immersive-far: color-mix(in oklab, var(--dream-surface) 66%, transparent);
}

:root.codex-dream-skin.dream-theme-dark {
Expand All @@ -43,16 +54,16 @@
--dream-hero-shade: color-mix(in oklab, var(--dream-surface) 91%, transparent);
--dream-ambient-opacity: .22;
--dream-shadow: 0 18px 48px color-mix(in oklab, oklch(0.06 0.01 245) 72%, transparent);
--dream-immersive-edge: color-mix(in oklab, var(--dream-surface) 43%, transparent);
--dream-immersive-mid: color-mix(in oklab, var(--dream-surface) 27%, transparent);
--dream-immersive-far: color-mix(in oklab, var(--dream-surface) 16%, transparent);
--dream-immersive-sidebar: color-mix(in oklab, var(--dream-sidebar) 48%, transparent);
--dream-task-immersive-sidebar: color-mix(in oklab, var(--dream-sidebar) 70%, transparent);
--dream-immersive-edge-base: color-mix(in oklab, var(--dream-surface) 43%, transparent);
--dream-immersive-mid-base: color-mix(in oklab, var(--dream-surface) 27%, transparent);
--dream-immersive-far-base: color-mix(in oklab, var(--dream-surface) 16%, transparent);
--dream-immersive-sidebar-base: color-mix(in oklab, var(--dream-sidebar) 48%, transparent);
--dream-task-immersive-sidebar-base: color-mix(in oklab, var(--dream-sidebar) 70%, transparent);
--dream-task-immersive-edge-base: color-mix(in oklab, var(--dream-surface) 82%, transparent);
--dream-task-immersive-mid-base: color-mix(in oklab, var(--dream-surface) 74%, transparent);
--dream-task-immersive-far-base: color-mix(in oklab, var(--dream-surface) 60%, transparent);
--dream-immersive-composer: color-mix(in oklab, var(--dream-surface-raised) 88%, var(--dream-accent) 5%);
--dream-immersive-line: color-mix(in oklab, var(--dream-line) 82%, transparent);
--dream-task-immersive-edge: color-mix(in oklab, var(--dream-surface) 82%, transparent);
--dream-task-immersive-mid: color-mix(in oklab, var(--dream-surface) 74%, transparent);
--dream-task-immersive-far: color-mix(in oklab, var(--dream-surface) 60%, transparent);
}

html.codex-dream-skin body {
Expand Down Expand Up @@ -114,20 +125,28 @@ html.codex-dream-skin main.main-surface > header.app-header-tint {
backdrop-filter: blur(12px) saturate(1.05) !important;
}

/* Wide art also reaches the native application menu, which sits outside the
main surface and needs its own dark-theme legibility layer. */
html.codex-dream-skin.dream-theme-dark [class~="group/application-menu-top-bar"] {
/* The native application menu sits outside the main surface. Give both shell
appearances a stable readability layer because media behind it can change
from bright to dark independently of Codex's light or dark preference. */
html.codex-dream-skin [class~="group/application-menu-top-bar"] {
color: var(--dream-text) !important;
background: color-mix(in oklab, var(--dream-sidebar) 90%, transparent) !important;
background: color-mix(in oklab,
color-mix(in oklab, var(--dream-sidebar) 88%, transparent)
var(--dream-wallpaper-cover), transparent) !important;
border-bottom: 1px solid var(--dream-line-soft) !important;
box-shadow: 0 1px 12px color-mix(in oklab, var(--dream-canvas) 72%, transparent) !important;
backdrop-filter: blur(16px) saturate(.9) !important;
backdrop-filter: blur(18px) saturate(.88) !important;
}

html.codex-dream-skin.dream-art-video [class~="group/application-menu-top-bar"] {
background: color-mix(in oklab,
color-mix(in oklab, var(--dream-sidebar) 94%, transparent)
var(--dream-wallpaper-cover), transparent) !important;
}

html.codex-dream-skin.dream-theme-dark [class~="group/application-menu-top-bar"] button,
html.codex-dream-skin.dream-theme-dark [class~="group/application-menu-top-bar"] svg {
html.codex-dream-skin [class~="group/application-menu-top-bar"] button,
html.codex-dream-skin [class~="group/application-menu-top-bar"] svg {
color: var(--dream-text) !important;
text-shadow: 0 1px 2px color-mix(in oklab, var(--dream-canvas) 82%, transparent) !important;
}

#codex-dream-skin-chrome {
Expand All @@ -144,6 +163,7 @@ html.codex-dream-skin.dream-theme-dark [class~="group/application-menu-top-bar"]
border: 0;
object-fit: cover;
object-position: var(--dream-art-position);
opacity: 1;
pointer-events: none;
}

Expand All @@ -170,7 +190,7 @@ html.codex-dream-skin .dream-task::before {
z-index: 0;
inset: 0;
pointer-events: none;
opacity: var(--dream-ambient-opacity);
opacity: calc(var(--dream-ambient-opacity) * var(--dream-wallpaper-reveal));
background-image: var(--dream-art);
background-repeat: no-repeat;
background-position: var(--dream-art-position);
Expand All @@ -192,7 +212,7 @@ html.codex-dream-skin.dream-art-wide:not(.dream-task-banner) .dream-task::before
html.codex-dream-skin.dream-task-banner .dream-task::before {
bottom: auto;
height: min(46vh, 520px);
opacity: calc(var(--dream-ambient-opacity) * 1.8);
opacity: calc(var(--dream-ambient-opacity) * var(--dream-wallpaper-reveal) * 1.8);
mask-image: linear-gradient(to bottom, oklch(0 0 0) 0, oklch(0 0 0 / .9) 52%, transparent 100%);
}

Expand Down Expand Up @@ -254,7 +274,9 @@ html.codex-dream-skin .dream-home {
overflow: hidden !important;
border: 1px solid var(--dream-line) !important;
border-radius: 20px !important;
background-image: var(--dream-art) !important;
background-image:
linear-gradient(var(--dream-media-overlay), var(--dream-media-overlay)),
var(--dream-art) !important;
background-repeat: no-repeat !important;
background-size: cover !important;
background-position: var(--dream-art-position) !important;
Expand Down Expand Up @@ -426,7 +448,9 @@ html.codex-dream-skin article {
html.codex-dream-skin.dream-art-wide:has(main.main-surface.dream-home-shell) body,
html.codex-dream-skin.dream-art-wide:is(.dream-task-ambient, .dream-task-banner):has(main.main-surface:not(.dream-home-shell)) body {
background-color: var(--dream-canvas) !important;
background-image: var(--dream-art) !important;
background-image:
linear-gradient(var(--dream-media-overlay), var(--dream-media-overlay)),
var(--dream-art) !important;
background-position: var(--dream-art-position) !important;
background-size: cover !important;
background-repeat: no-repeat !important;
Expand Down Expand Up @@ -499,6 +523,26 @@ html.codex-dream-skin.dream-art-wide main.main-surface > header.app-header-tint
filter: drop-shadow(0 1px 2px color-mix(in oklab, var(--dream-canvas) 72%, transparent));
}

/* Unlike a static image, a video can invalidate foreground contrast on every
frame. Keep the secondary Codex toolbar translucent but independently
readable instead of relying on text shadows over the moving media. */
html.codex-dream-skin.dream-art-video main.main-surface > header.app-header-tint {
color: var(--dream-text) !important;
background: color-mix(in oklab,
color-mix(in oklab, var(--dream-surface) 86%, transparent)
var(--dream-wallpaper-cover), transparent) !important;
border-bottom: 1px solid var(--dream-line-soft) !important;
box-shadow: 0 1px 12px color-mix(in oklab, var(--dream-canvas) 44%, transparent) !important;
backdrop-filter: blur(16px) saturate(.9) !important;
text-shadow: 0 1px 2px color-mix(in oklab, var(--dream-canvas) 86%, transparent),
0 0 8px color-mix(in oklab, var(--dream-canvas) 58%, transparent) !important;
}

html.codex-dream-skin.dream-art-video main.main-surface > header.app-header-tint svg {
color: var(--dream-text) !important;
filter: drop-shadow(0 1px 2px color-mix(in oklab, var(--dream-canvas) 72%, transparent));
}

html.codex-dream-skin.dream-art-wide main.main-surface [role="main"] {
background: transparent !important;
}
Expand Down
20 changes: 19 additions & 1 deletion windows/assets/renderer-inject.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
"--dream-accent",
"--dream-accent-ink",
"--dream-image-luma",
"--dream-wallpaper-reveal",
"--dream-wallpaper-cover",
];
const HOME_UTILITY_CLASS = "dream-home-utility";
const installToken = {};
Expand Down Expand Up @@ -84,6 +86,9 @@
const playbackRate = Number.isFinite(Number(media.playbackRate))
? clamp(Number(media.playbackRate), .25, 2)
: 1;
const wallpaperReveal = Number.isFinite(Number(media.opacity))
? clamp(Number(media.opacity))
: 1;
const metadataRatio = Number(config?.artMetadata?.ratio);
return {
appearance,
Expand All @@ -97,6 +102,7 @@
mediaMime,
mediaSize,
playbackRate,
wallpaperReveal,
};
};

Expand Down Expand Up @@ -352,6 +358,18 @@
root.style.setProperty("--dream-accent", accent);
root.style.setProperty("--dream-accent-ink", accentInk);
root.style.setProperty("--dream-image-luma", profile.luma.toFixed(3));
root.style.setProperty("--dream-wallpaper-reveal", config.wallpaperReveal.toFixed(2));
root.style.setProperty("--dream-wallpaper-cover", `${Math.round((1 - config.wallpaperReveal) * 100)}%`);
};

const setWallpaperReveal = (value) => {
const numeric = Number(value);
if (!Number.isFinite(numeric) || numeric < 0 || numeric > 1) return null;
config.wallpaperReveal = numeric;
const root = document.documentElement;
root?.style.setProperty("--dream-wallpaper-reveal", numeric.toFixed(2));
root?.style.setProperty("--dream-wallpaper-cover", `${Math.round((1 - numeric) * 100)}%`);
return numeric;
};

const syncMediaElement = () => {
Expand Down Expand Up @@ -528,7 +546,7 @@
document.addEventListener?.("visibilitychange", visibilityHandler);
window[STATE_KEY] = {
ensure, cleanup, observer, timer, scheduler, artUrl, mediaUrl, beginMedia, appendMedia, commitMedia,
visibilityHandler, profile, config, installToken, version: "1.2.0",
setWallpaperReveal, visibilityHandler, profile, config, installToken, version: "1.2.0",
};
ensure();
analyzeArt().then((result) => {
Expand Down
Loading
Loading