add Windows background material customisation (#4230)

This commit is contained in:
V 2026-05-18 04:28:46 +02:00 • committed by GitHub
parent 9b94e49622
commit b8a515dff5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 183 additions and 112 deletions

View file

@ -55,6 +55,7 @@ window.VencordNative = {
native: {
getVersions: () => ({}),
supportsWindowsMaterial: () => false,
openExternal: async (url) => void open(url, "_blank"),
getRendererCss: async () => {
if (IS_USERSCRIPT)

View file

@ -78,6 +78,7 @@ export default {
native: {
getVersions: () => process.versions as Partial<NodeJS.ProcessVersions>,
supportsWindowsMaterial: () => sendSync<boolean>(IpcEvents.SUPPORTS_WINDOWS_MATERIAL),
openExternal: (url: string) => invoke<void>(IpcEvents.OPEN_EXTERNAL, url),
getRendererCss: () => invoke<string>(IpcEvents.GET_RENDERER_CSS),
onRendererCssUpdate: (cb: (newCss: string) => void) => {

View file

@ -62,6 +62,7 @@ export interface Settings {
| "under-page"
| "window"
| undefined;
windowsMaterial: "none" | "mica" | "tabbed" | "acrylic";
disableMinSize: boolean;
winNativeTitleBar: boolean;
plugins: {
@ -103,6 +104,7 @@ const DefaultSettings: Settings = {
transparent: false,
winCtrlQ: false,
macosVibrancyStyle: undefined,
windowsMaterial: "none",
disableMinSize: false,
winNativeTitleBar: false,
plugins: {},

View file

@ -6,79 +6,80 @@
import { useSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary";
import { IS_MAC } from "@utils/constants";
import { Margins } from "@utils/margins";
import { identity } from "@utils/misc";
import { Forms, Select } from "@webpack/common";
export function VibrancySettings() {
export function MacOSVibrancySettings() {
const settings = useSettings(["macosVibrancyStyle"]);
if (!IS_MAC || IS_WEB) return null;
return (
<>
<Forms.FormTitle tag="h5">Window vibrancy style (requires restart)</Forms.FormTitle>
<ErrorBoundary noop>
<Select
className={Margins.bottom20}
placeholder="Window vibrancy style"
options={[
// Sorted from most opaque to most transparent
{
label: "No vibrancy", value: undefined
},
{
label: "Under Page (window tinting)",
value: "under-page"
},
{
label: "Content",
value: "content"
},
{
label: "Window",
value: "window"
},
{
label: "Selection",
value: "selection"
},
{
label: "Titlebar",
value: "titlebar"
},
{
label: "Header",
value: "header"
},
{
label: "Sidebar",
value: "sidebar"
},
{
label: "Tooltip",
value: "tooltip"
},
{
label: "Menu",
value: "menu"
},
{
label: "Popover",
value: "popover"
},
{
label: "Fullscreen UI (transparent but slightly muted)",
value: "fullscreen-ui"
},
{
label: "HUD (Most transparent)",
value: "hud"
},
]}
select={v => settings.macosVibrancyStyle = v}
isSelected={v => settings.macosVibrancyStyle === v}
serialize={identity}
/>
</ErrorBoundary>
</>
<ErrorBoundary noop>
<Forms.FormTitle tag="h5">MacOS Window vibrancy style (requires restart)</Forms.FormTitle>
<Select
className={Margins.bottom20}
placeholder="Window vibrancy style"
options={[
// Sorted from most opaque to most transparent
{
label: "No vibrancy", value: undefined
},
{
label: "Under Page (window tinting)",
value: "under-page"
},
{
label: "Content",
value: "content"
},
{
label: "Window",
value: "window"
},
{
label: "Selection",
value: "selection"
},
{
label: "Titlebar",
value: "titlebar"
},
{
label: "Header",
value: "header"
},
{
label: "Sidebar",
value: "sidebar"
},
{
label: "Tooltip",
value: "tooltip"
},
{
label: "Menu",
value: "menu"
},
{
label: "Popover",
value: "popover"
},
{
label: "Fullscreen UI (transparent but slightly muted)",
value: "fullscreen-ui"
},
{
label: "HUD (Most transparent)",
value: "hud"
},
]}
select={v => settings.macosVibrancyStyle = v}
isSelected={v => settings.macosVibrancyStyle === v}
serialize={identity}
/>
</ErrorBoundary>
);
}

View file

@ -0,0 +1,55 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2026 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { useSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Heading } from "@components/Heading";
import { Margins } from "@components/margins";
import { Paragraph } from "@components/Paragraph";
import { IS_WINDOWS } from "@utils/constants";
import { Select } from "@webpack/common";
export function WindowsMaterialSettings() {
const settings = useSettings(["windowsMaterial"]);
if (!IS_WINDOWS || IS_WEB || !VencordNative.native.supportsWindowsMaterial()) return null;
return (
<ErrorBoundary noop>
<Heading tag="h5">Background Material</Heading>
<Paragraph className={Margins.bottom8}>
Windows transparent background effects. You need a theme that supports transparency or this will do nothing. A restart is required after changing this setting.
</Paragraph>
<Select
placeholder="None"
options={[
{
label: "None",
value: "none",
default: true
},
{
label: "Mica (incorporates system theme + desktop wallpaper to paint the background)",
value: "mica"
},
{
label: "Tabbed (variant of Mica with stronger background tinting)",
value: "tabbed"
},
{
label: "Acrylic (blurs the window behind Vesktop for a translucent background)",
value: "acrylic"
}
]}
closeOnSelect={true}
select={v => (settings.windowsMaterial = v)}
isSelected={v => v === settings.windowsMaterial}
serialize={s => s}
/>
</ErrorBoundary>
);
}

View file

@ -28,15 +28,16 @@ import { openContributorModal } from "@components/settings/tabs/plugins/Contribu
import { openPluginModal } from "@components/settings/tabs/plugins/PluginModal";
import SettingsPlugin from "@plugins/_core/settings";
import { gitRemote } from "@shared/vencordUserAgent";
import { IS_MAC, IS_WINDOWS } from "@utils/constants";
import { IS_WINDOWS } from "@utils/constants";
import { Margins } from "@utils/margins";
import { isPluginDev } from "@utils/misc";
import { relaunch } from "@utils/native";
import { ConfirmModal,Forms, openModal, React, useMemo, UserStore } from "@webpack/common";
import { ConfirmModal, Forms, openModal, React, useMemo, UserStore } from "@webpack/common";
import { DonateButtonComponent, isDonor } from "./DonateButton";
import { VibrancySettings } from "./MacVibrancySettings";
import { MacOSVibrancySettings } from "./MacVibrancySettings";
import { NotificationSection } from "./NotificationSettings";
import { WindowsMaterialSettings } from "./WindowsMaterialSettings";
const DEFAULT_DONATE_IMAGE = "https://cdn.discordapp.com/emojis/1026533090627174460.png";
const SHIGGY_DONATE_IMAGE = "https://media.discordapp.net/stickers/1039992459209490513.png";
@ -135,8 +136,6 @@ function VencordSettings() {
[]
);
const needsVibrancySettings = IS_DISCORD_DESKTOP && IS_MAC;
const user = UserStore?.getCurrentUser();
return (
@ -231,7 +230,8 @@ function VencordSettings() {
</section>
{needsVibrancySettings && <VibrancySettings />}
<MacOSVibrancySettings />
<WindowsMaterialSettings />
<NotificationSection />
</SettingsTab>

View file

@ -26,6 +26,7 @@ import { BrowserWindow, ipcMain, nativeTheme, shell, systemPreferences } from "e
import monacoHtml from "file://monacoWin.html?minify&base64";
import { FSWatcher, mkdirSync, readFileSync, watch, writeFileSync } from "fs";
import { open, readdir, readFile } from "fs/promises";
import { release } from "os";
import { join, normalize } from "path";
import { registerCspIpcHandlers } from "./csp/manager";
@ -176,3 +177,7 @@ if (IS_DISCORD_DESKTOP) {
e.returnValue = readFileSync(join(__dirname, "renderer.js"), "utf-8");
});
}
ipcMain.on(IpcEvents.SUPPORTS_WINDOWS_MATERIAL, e => {
e.returnValue = process.platform === "win32" && Number(release().split(".")[2]) >= 22621;
});

View file

@ -68,47 +68,51 @@ if (!IS_VANILLA) {
class BrowserWindow extends electron.BrowserWindow {
constructor(options: BrowserWindowConstructorOptions) {
if (options?.webPreferences?.preload && options.title) {
const original = options.webPreferences.preload;
options.webPreferences.preload = join(__dirname, "preload.js");
options.webPreferences.sandbox = false;
// work around discord unloading when in background
options.webPreferences.backgroundThrottling = false;
if (settings.frameless) {
options.frame = false;
} else if (process.platform === "win32" && settings.winNativeTitleBar) {
delete options.frame;
}
if (settings.transparent) {
options.transparent = true;
options.backgroundColor = "#00000000";
}
if (settings.disableMinSize) {
options.minWidth = 0;
options.minHeight = 0;
}
const needsVibrancy = process.platform === "darwin" && settings.macosVibrancyStyle;
if (needsVibrancy) {
options.backgroundColor = "#00000000";
if (settings.macosVibrancyStyle) {
options.vibrancy = settings.macosVibrancyStyle;
}
}
process.env.DISCORD_PRELOAD = original;
if (!options?.webPreferences?.preload || !options.title) {
super(options);
return;
}
if (settings.disableMinSize) {
// Disable the Electron call entirely so that Discord can't dynamically change the size
this.setMinimumSize = (width: number, height: number) => { };
}
} else super(options);
const { frameless, winNativeTitleBar, disableMinSize, transparent, macosVibrancyStyle, windowsMaterial } = settings;
const original = options.webPreferences.preload;
options.webPreferences.preload = join(__dirname, "preload.js");
options.webPreferences.sandbox = false;
// work around discord unloading when in background
options.webPreferences.backgroundThrottling = false;
if (frameless) {
options.frame = false;
} else if (process.platform === "win32" && winNativeTitleBar) {
delete options.frame;
}
if (disableMinSize) {
options.minWidth = 0;
options.minHeight = 0;
}
if (transparent) {
options.transparent = true;
options.backgroundColor = "#00000000";
}
if (process.platform === "darwin" && macosVibrancyStyle) {
options.vibrancy = macosVibrancyStyle;
options.backgroundColor = "#00000000";
}
if (process.platform === "win32" && windowsMaterial && windowsMaterial !== "none") {
options.backgroundMaterial = windowsMaterial;
options.backgroundColor = "#00000000";
}
process.env.DISCORD_PRELOAD = original;
super(options);
if (disableMinSize) {
// Disable the Electron call entirely so that Discord can't dynamically change the size
this.setMinimumSize = (_width: number, _height: number) => { };
}
}
}
Object.assign(BrowserWindow, electron.BrowserWindow);

View file

@ -53,4 +53,6 @@ export const enum IpcEvents {
GET_RENDERER_CSS = "VencordGetRendererCss",
RENDERER_CSS_UPDATE = "VencordRendererCssUpdate",
PRELOAD_GET_RENDERER_JS = "VencordPreloadGetRendererJs",
SUPPORTS_WINDOWS_MATERIAL = "VencordSupportsWindowsMaterial",
}