try fix win10 drag delay

This commit is contained in:
EYHN 2021-01-04 23:48:10 +08:00
parent 636565fdba
commit da3dd1eb9d
32 changed files with 3540 additions and 1202 deletions

355
.gitignore vendored
View File

@ -5,357 +5,4 @@ test
firstload.lock
*.vsix
yarn.lock
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
/build

39
binding.gyp Normal file
View File

@ -0,0 +1,39 @@
{
"targets": [
{
"target_name": "vibrancy",
"conditions":[
["OS=='win'", {
"sources": [
"native/vibrancy.cc"
]
}]
],
"cflags": [
"-O3"
],
"include_dirs": [
"<!@(node -p \"require('node-addon-api').include\")"
],
"defines": [
"NAPI_DISABLE_CPP_EXCEPTIONS"
]
},
{
"target_name": "displayconfig",
"cflags!": ["-fno-exceptions"],
"cflags_cc!": ["-fno-exceptions"],
"conditions": [
["OS=='win'", {
"sources": ["native/displayconfig.cc"]
}],
],
"include_dirs": [
"<!@(node -p \"require('node-addon-api').include\")"
],
'defines': [
'NAPI_DISABLE_CPP_EXCEPTIONS'
],
}
]
}

20
extension/i18n.js Normal file
View File

@ -0,0 +1,20 @@
var fs = require('mz/fs');
var vscode = require('vscode');
var path = require('path');
const i18nMessages = {
'en': JSON.parse(fs.readFileSync(path.join(__dirname, '../package.nls.json'))),
'zh-cn': JSON.parse(fs.readFileSync(path.join(__dirname, '../package.nls.zh-CN.json'))),
'ja': JSON.parse(fs.readFileSync(path.join(__dirname, '../package.nls.ja.json')))
};
const defaultLocale = 'en';
const locale = (vscode.env.language || defaultLocale).toLowerCase();
const localize = (info) => {
if (locale in i18nMessages && info in i18nMessages[locale]) {
return i18nMessages[locale][info]
} else {
return i18nMessages[defaultLocale][info]
}
}
module.exports = localize;

View File

@ -1,397 +1,276 @@
var vscode = require('vscode');
var fs = require('mz/fs');
var path = require('path');
var lockPath = path.join(__dirname, '../firstload.lock');
const i18nMessages = {
'en': JSON.parse(fs.readFileSync(path.join(__dirname, 'extension.nls.json'))),
'zh-cn': JSON.parse(fs.readFileSync(path.join(__dirname, 'extension.nls.zh-CN.json'))),
'ja': JSON.parse(fs.readFileSync(path.join(__dirname, 'extension.nls.ja.json')))
};
const defaultLocale = 'en';
const locale = (vscode.env.language || defaultLocale).toLowerCase();
const localize = (info) => {
if (locale in i18nMessages && info in i18nMessages[locale]) {
return i18nMessages[locale][info]
} else {
return i18nMessages[defaultLocale][info]
}
}
let os = 'macos';
if (/^win/.test(process.platform)) {
if (require('os').release().split(".").map(Number)[0] === 10) {
os = 'win10';
} else {
os = 'win7';
}
}
var themeStylePaths = {
'Default Dark': '../themes/Default Dark.css',
'Dark (Only Subbar)': '../themes/Dark (Only Subbar).css',
'Default Light': '../themes/Default Light.css',
}
const themeConfigPaths = {
'Default Dark': '../themes/Default Dark.json',
'Dark (Only Subbar)': '../themes/Dark (Only Subbar).json',
'Default Light': '../themes/Default Light.json',
}
var defaultTheme = 'Default Dark';
function getCurrentTheme(config) {
return config.theme in themeStylePaths ? config.theme : defaultTheme;
}
async function changeTerminalRendererType() {
// This is a hacky way to display the restart prompt
let v = vscode.workspace.getConfiguration().inspect("terminal.integrated.rendererType");
if (v !== undefined) {
if (!v.globalValue) {
await vscode.workspace.getConfiguration().update("terminal.integrated.rendererType", "dom", vscode.ConfigurationTarget.Global);
}
}
}
// async function promptRestart() {
// let v = vscode.workspace.getConfiguration().inspect("window.titleBarStyle");
// if (v !== undefined) {
// let value = vscode.workspace.getConfiguration().get("window.titleBarStyle");
// vscode.workspace.getConfiguration().update("window.titleBarStyle", value === "native" ? "custom" : "native", vscode.ConfigurationTarget.Global);
// vscode.workspace.getConfiguration().update("window.titleBarStyle", v.globalValue, vscode.ConfigurationTarget.Global);
// }
// }
async function checkColorTheme() {
const currentTheme = getCurrentTheme(vscode.workspace.getConfiguration("vscode_vibrancy"));
const themeConfig = require(path.join(__dirname, themeConfigPaths[currentTheme]));
const target = themeConfig.colorTheme;
const currentColorTheme = vscode.workspace.getConfiguration().get("workbench.colorTheme");
if (target !== currentColorTheme) {
const message = localize('messages.recommendedColorTheme').replace('%1', currentColorTheme).replace('%2', target);
await vscode.window.showInformationMessage(message, localize('messages.changeColorThemeIde'), localize('messages.noIde'))
.then(async (msg) => {
if (msg === localize('messages.changeColorThemeIde')) {
await vscode.workspace.getConfiguration().update("workbench.colorTheme", target, vscode.ConfigurationTarget.Global);
}
});
}
}
function deepEqual(obj1, obj2) {
if(obj1 === obj2) // it's just the same object. No need to compare.
return true;
if(isPrimitive(obj1) && isPrimitive(obj2)) // compare primitives
return obj1 === obj2;
if(Object.keys(obj1).length !== Object.keys(obj2).length)
return false;
// compare objects with same number of keys
for(let key in obj1)
{
if(!(key in obj2)) return false; //other object doesn't have this prop
if(!deepEqual(obj1[key], obj2[key])) return false;
}
return true;
}
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
//check if value is primitive
function isPrimitive(obj)
{
return (obj !== Object(obj));
}
function isFirstload() {
try {
fs.readFileSync(lockPath);
return false
} catch (err) {
return true
}
}
function lockFirstload() {
fs.writeFileSync(lockPath, '', () => {});
}
function injectHTML(config, currentTheme, themeConfig) {
var type = config.type;
if (type === 'auto') {
type = themeConfig.type[os];
}
let opacity = config.opacity;
if (opacity < 0) {
opacity = themeConfig.opacity[os]
}
if (os === 'win10') {
opacity = 0;
}
const backgroundRGB = hexToRgb(themeConfig.background);
const HTML = [
`
<style>
html {
background: rgba(${backgroundRGB.r},${backgroundRGB.g},${backgroundRGB.b},${opacity}) !important;
}
</style>
`,
...config.imports.map(function (x) {
if (!x) return;
if (typeof x === 'string') {
x = x.replace('%theme-style%', path.join(__dirname, themeStylePaths[currentTheme]));
x = x.replace('$theme-style$', path.join(__dirname, themeStylePaths[currentTheme]));
x = new URL(x, 'file://').href;
if (!x.startsWith('file://')) {
x = 'file://' + x;
}
if (/^.*\.js$/.test(x)) return '<script src="' + x + '"></script>';
if (/^.*\.css$/.test(x)) return '<link rel="stylesheet" href="' + x + '"/>';
}
})
]
return HTML.join('')
}
const macosType = [
"appearance-based",
"light",
"dark",
"titlebar",
"selection",
"menu",
"popover",
"sidebar",
"medium-light",
"ultra-dark"
];
const windowsType = [
"dwm",
"acrylic"
];
function injectJS(config, currentTheme, themeConfig) {
var type = config.type;
if (type !== 'auto') {
if (os === 'win10' || os === 'win7' && !windowsType.includes(type)) type = 'auto';
if (os === 'macos' && !macosType.includes(type)) type = 'auto';
}
if (type === 'auto') {
type = themeConfig.type[os];
}
let opacity = config.opacity;
if (opacity < 0) {
opacity = themeConfig.opacity[os]
}
return `
const electron = require('electron');
electron.app.on('browser-window-created', (event, window) => {
window.webContents.on('dom-ready', () => {
window.setBackgroundColor('#00000000');
${os !== 'macos' ?
`require("child_process")
.spawn(${JSON.stringify(__dirname + '\\blur-cli.exe')}, [new Uint32Array(window.getNativeWindowHandle().buffer)[0], '--type', ${JSON.stringify(type)}, '--enable', 'true', '--color', '${themeConfig.background}', '--opacity', ${JSON.stringify(opacity)}]);` :
`window.setVibrancy(${JSON.stringify(type)});`
}
// hack
const width = window.getBounds().width;
window.setBounds({
width: width + 1,
});
window.setBounds({
width,
});
window.webContents.executeJavaScript(${JSON.stringify("document.body.innerHTML += " + JSON.stringify(injectHTML(config, currentTheme, themeConfig)))})
});
})
`
}
function activate(context) {
console.log('vscode-vibrancy is active!');
process.on('uncaughtException', function (err) {
if (/ENOENT|EACCES|EPERM/.test(err.code)) {
vscode.window.showInformationMessage(localize('messages.admin'));
return;
}
});
var isWin = /^win/.test(process.platform);
var appDir = path.dirname(require.main.filename);
var HTMLFile = appDir + (isWin ? '\\vs\\code\\electron-browser\\workbench\\workbench.html' : '/vs/code/electron-browser/workbench/workbench.html');
var JSFile = appDir + (isWin ? '\\main.js' : '/main.js');
async function installJS() {
const config = vscode.workspace.getConfiguration("vscode_vibrancy");
const currentTheme = getCurrentTheme(config);
const themeConfig = require(path.join(__dirname, themeConfigPaths[currentTheme]));
const JS = await fs.readFile(JSFile, 'utf-8');
const newJS = JS.replace(/\/\* !! VSCODE-VIBRANCY-START !! \*\/[\s\S]*?\/\* !! VSCODE-VIBRANCY-END !! \*\//, '')
+ '\n/* !! VSCODE-VIBRANCY-START !! */\n(function(){' + injectJS(config, currentTheme, themeConfig) + '})()\n/* !! VSCODE-VIBRANCY-END !! */\n';
await fs.writeFile(JSFile, newJS, 'utf-8');
}
async function uninstallJS() {
const JS = await fs.readFile(JSFile, 'utf-8');
const needClean = /\/\* !! VSCODE-VIBRANCY-START !! \*\/[\s\S]*?\/\* !! VSCODE-VIBRANCY-END !! \*\//.test(JS);
if (needClean) {
const newJS = JS
.replace(/\/\* !! VSCODE-VIBRANCY-START !! \*\/[\s\S]*?\/\* !! VSCODE-VIBRANCY-END !! \*\//, '')
await fs.writeFile(JSFile, newJS, 'utf-8');
}
}
async function uninstallHTML() {
const HTML = await fs.readFile(HTMLFile, 'utf-8');
const needClean = /<!-- !! VSCODE-VIBRANCY-START !! -->[\s\S]*?<!-- !! VSCODE-VIBRANCY-END !! -->/.test(HTML);
if (needClean) {
const newHTML = HTML
.replace(/<!-- !! VSCODE-VIBRANCY-START !! -->[\s\S]*?<!-- !! VSCODE-VIBRANCY-END !! -->/, '')
.replace(/<meta.*http-equiv="Content-Security-Policy".*>/, '');
await fs.writeFile(HTMLFile, newHTML, 'utf-8');
}
}
function enabledRestart() {
vscode.window.showInformationMessage(localize('messages.enabled'), { title: localize('messages.reloadIde') })
// .then(function (msg) {
// msg && promptRestart();
// });
}
function disabledRestart() {
vscode.window.showInformationMessage(localize('messages.disabled'), { title: localize('messages.restartIde') })
// .then(function (msg) {
// msg && promptRestart();
// });
}
// #### main commands ######################################################
async function Install(autoreload) {
try {
await fs.stat(JSFile);
await changeTerminalRendererType()
} catch (error) {
vscode.window.showInformationMessage(localize('messages.smthingwrong') + error);
throw error;
}
try {
await installJS();
} catch (error) {
vscode.window.showInformationMessage(localize('messages.admin'));
throw error;
}
}
async function Uninstall() {
try {
await fs.stat(JSFile);
await fs.stat(HTMLFile);
} catch(error) {
vscode.window.showInformationMessage(localize('messages.smthingwrong') + error);
throw error;
}
try {
await uninstallHTML();
await uninstallJS();
} catch(error) {
vscode.window.showInformationMessage(localize('messages.admin'));
throw error;
}
}
async function Update() {
await Uninstall();
await Install();
}
var installVibrancy = vscode.commands.registerCommand('extension.installVibrancy', async () => {
await Install();
enabledRestart();
});
var uninstallVibrancy = vscode.commands.registerCommand('extension.uninstallVibrancy', async () => {
await Uninstall()
disabledRestart();
});
var updateVibrancy = vscode.commands.registerCommand('extension.updateVibrancy', async () => {
await Update();
enabledRestart();
});
context.subscriptions.push(installVibrancy);
context.subscriptions.push(uninstallVibrancy);
context.subscriptions.push(updateVibrancy);
if (isFirstload()) {
vscode.window.showInformationMessage(localize('messages.firstload'), { title: localize('messages.installIde') })
.then(async (msg) => {
if (msg) {
await Update();
await checkColorTheme();
enabledRestart();
}
});
lockFirstload();
}
var lastConfig = vscode.workspace.getConfiguration("vscode_vibrancy");
vscode.workspace.onDidChangeConfiguration(() => {
newConfig = vscode.workspace.getConfiguration("vscode_vibrancy");
if (!deepEqual(lastConfig, newConfig)) {
lastConfig = newConfig;
vscode.window.showInformationMessage(localize('messages.configupdate'), { title: localize('messages.reloadIde') })
.then(async (msg) => {
if (msg) {
await Update();
if (newConfig.theme !== vscode.workspace.getConfiguration("vscode_vibrancy")) {
await checkColorTheme();
}
promptRestart();
}
});
lockFirstload();
}
});
}
exports.activate = activate;
// this method is called when your extension is deactivated
function deactivate() { }
exports.deactivate = deactivate;
var vscode = require('vscode');
var fs = require('mz/fs');
var fsExtra = require('fs-extra');
var path = require('path');
var lockPath = path.join(__dirname, '../firstload.lock');
/**
* @type {(info: string) => string}
*/
const localize = require('./i18n');
/**
* @type {'unknown' | 'win10' | 'macos'}
*/
const os = require('./platform');
var themeStylePaths = {
'Default Dark': '../themes/Default Dark.css',
'Dark (Only Subbar)': '../themes/Dark (Only Subbar).css',
'Default Light': '../themes/Default Light.css',
}
const themeConfigPaths = {
'Default Dark': '../themes/Default Dark.json',
'Dark (Only Subbar)': '../themes/Dark (Only Subbar).json',
'Default Light': '../themes/Default Light.json',
}
var defaultTheme = 'Default Dark';
function getCurrentTheme(config) {
return config.theme in themeStylePaths ? config.theme : defaultTheme;
}
async function changeTerminalRendererType() {
let v = vscode.workspace.getConfiguration().inspect("terminal.integrated.rendererType");
if (v !== undefined) {
if (!v.globalValue) {
await vscode.workspace.getConfiguration().update("terminal.integrated.rendererType", "dom", vscode.ConfigurationTarget.Global);
}
}
}
async function checkColorTheme() {
const currentTheme = getCurrentTheme(vscode.workspace.getConfiguration("vscode_vibrancy"));
const themeConfig = require(path.join(__dirname, themeConfigPaths[currentTheme]));
const target = themeConfig.colorTheme;
const currentColorTheme = vscode.workspace.getConfiguration().get("workbench.colorTheme");
if (target !== currentColorTheme) {
const message = localize('messages.recommendedColorTheme').replace('%1', currentColorTheme).replace('%2', target);
await vscode.window.showInformationMessage(message, localize('messages.changeColorThemeIde'), localize('messages.noIde'))
.then(async (msg) => {
if (msg === localize('messages.changeColorThemeIde')) {
await vscode.workspace.getConfiguration().update("workbench.colorTheme", target, vscode.ConfigurationTarget.Global);
}
});
}
}
function deepEqual(obj1, obj2) {
if (obj1 === obj2) // it's just the same object. No need to compare.
return true;
if (isPrimitive(obj1) && isPrimitive(obj2)) // compare primitives
return obj1 === obj2;
if (Object.keys(obj1).length !== Object.keys(obj2).length)
return false;
// compare objects with same number of keys
for (let key in obj1) {
if (!(key in obj2)) return false; //other object doesn't have this prop
if (!deepEqual(obj1[key], obj2[key])) return false;
}
return true;
}
//check if value is primitive
function isPrimitive(obj) {
return (obj !== Object(obj));
}
function isFirstload() {
try {
fs.readFileSync(lockPath);
return false
} catch (err) {
return true
}
}
function lockFirstload() {
fs.writeFileSync(lockPath, '', () => { });
}
function activate(context) {
console.log('vscode-vibrancy is active!');
var isWin = /^win/.test(process.platform);
var appDir = path.dirname(require.main.filename);
var HTMLFile = appDir + '/vs/code/electron-browser/workbench/workbench.html';
var JSFile = appDir + '/main.js';
var runtimeVersion = 'v1';
var runtimeDir = appDir + '/vscode-vibrancy-runtime-' + runtimeVersion;
async function installRuntime() {
if (!isWin) return;
if (fs.existsSync(runtimeDir)) return;
await fs.mkdir(runtimeDir);
await fsExtra.copy(path.resolve(__dirname, '../runtime'), path.resolve(runtimeDir));
}
async function installJS() {
const config = vscode.workspace.getConfiguration("vscode_vibrancy");
const currentTheme = getCurrentTheme(config);
const themeConfig = require(path.resolve(__dirname, themeConfigPaths[currentTheme]));
const themeCSS = await fs.readFile(path.join(__dirname, themeStylePaths[currentTheme]), 'utf-8');
const JS = await fs.readFile(JSFile, 'utf-8');
const injectData = {
os: os,
config: config,
theme: themeConfig,
themeCSS: themeCSS
}
const base = __filename;
const newJS = JS.replace(/\/\* !! VSCODE-VIBRANCY-START !! \*\/[\s\S]*?\/\* !! VSCODE-VIBRANCY-END !! \*\//, '')
+ '\n/* !! VSCODE-VIBRANCY-START !! */\n;(function(){\n'
+ `if (!require(\'fs\').existsSync(${JSON.stringify(base)})) return;\n`
+ `global.vscode_vibrancy_plugin = ${JSON.stringify(injectData)}; try{ require(${JSON.stringify(runtimeDir)}); } catch (err) {console.error(err)}\n`
+ '})()\n/* !! VSCODE-VIBRANCY-END !! */';
await fs.writeFile(JSFile, newJS, 'utf-8');
}
async function uninstallJS() {
const JS = await fs.readFile(JSFile, 'utf-8');
const needClean = /\/\* !! VSCODE-VIBRANCY-START !! \*\/[\s\S]*?\/\* !! VSCODE-VIBRANCY-END !! \*\//.test(JS);
if (needClean) {
const newJS = JS
.replace(/\/\* !! VSCODE-VIBRANCY-START !! \*\/[\s\S]*?\/\* !! VSCODE-VIBRANCY-END !! \*\//, '')
await fs.writeFile(JSFile, newJS, 'utf-8');
}
}
async function uninstallHTML() {
const HTML = await fs.readFile(HTMLFile, 'utf-8');
const needClean = /<!-- !! VSCODE-VIBRANCY-START !! -->[\s\S]*?<!-- !! VSCODE-VIBRANCY-END !! -->/.test(HTML);
if (needClean) {
const newHTML = HTML
.replace(/<!-- !! VSCODE-VIBRANCY-START !! -->[\s\S]*?<!-- !! VSCODE-VIBRANCY-END !! -->/, '')
.replace(/<meta.*http-equiv="Content-Security-Policy".*>/, '');
await fs.writeFile(HTMLFile, newHTML, 'utf-8');
}
}
function enabledRestart() {
vscode.window.showInformationMessage(localize('messages.enabled'), { title: localize('messages.restartIde') });
}
function disabledRestart() {
vscode.window.showInformationMessage(localize('messages.disabled'), { title: localize('messages.restartIde') });
}
// #### main commands ######################################################
async function Install() {
if (os === 'unknown') {
vscode.window.showInformationMessage(localize('messages.unsupported'));
throw new Error('unsupported');
}
try {
await fs.stat(JSFile);
await changeTerminalRendererType()
} catch (error) {
vscode.window.showInformationMessage(localize('messages.smthingwrong') + error);
throw error;
}
try {
await installRuntime();
await installJS();
} catch (error) {
vscode.window.showInformationMessage(localize('messages.smthingwrong') + error);
throw error;
}
}
async function Uninstall() {
try {
await fs.stat(JSFile);
await fs.stat(HTMLFile);
} catch (error) {
vscode.window.showInformationMessage(localize('messages.smthingwrong') + error);
throw error;
}
try {
// uninstall old version
await uninstallHTML();
await uninstallJS();
} catch (error) {
vscode.window.showInformationMessage(localize('messages.smthingwrong') + error);
throw error;
}
}
async function Update() {
await Uninstall();
await Install();
}
var installVibrancy = vscode.commands.registerCommand('extension.installVibrancy', async () => {
await Install();
enabledRestart();
});
var uninstallVibrancy = vscode.commands.registerCommand('extension.uninstallVibrancy', async () => {
await Uninstall()
disabledRestart();
});
var updateVibrancy = vscode.commands.registerCommand('extension.updateVibrancy', async () => {
await Update();
enabledRestart();
});
context.subscriptions.push(installVibrancy);
context.subscriptions.push(uninstallVibrancy);
context.subscriptions.push(updateVibrancy);
if (isFirstload()) {
vscode.window.showInformationMessage(localize('messages.firstload'), { title: localize('messages.installIde') })
.then(async (msg) => {
if (msg) {
await Update();
await checkColorTheme();
enabledRestart();
}
});
lockFirstload();
}
var lastConfig = vscode.workspace.getConfiguration("vscode_vibrancy");
vscode.workspace.onDidChangeConfiguration(() => {
newConfig = vscode.workspace.getConfiguration("vscode_vibrancy");
if (!deepEqual(lastConfig, newConfig)) {
lastConfig = newConfig;
vscode.window.showInformationMessage(localize('messages.configupdate'), { title: localize('messages.reloadIde') })
.then(async (msg) => {
if (msg) {
await Update();
if (newConfig.theme !== vscode.workspace.getConfiguration("vscode_vibrancy")) {
await checkColorTheme();
}
enabledRestart();
}
});
lockFirstload();
}
});
}
exports.activate = activate;
// this method is called when your extension is deactivated
function deactivate() { }
exports.deactivate = deactivate;

11
extension/platform.js Normal file
View File

@ -0,0 +1,11 @@
let os = 'unknown';
if (/^win/.test(process.platform)) {
if (require('os').release().split(".").map(Number)[0] === 10) {
os = 'win10';
}
}
if (process.platform === 'darwin') {
os = 'macos';
}
module.exports = os;

1050
native/displayconfig.cc Normal file

File diff suppressed because it is too large Load Diff

124
native/vibrancy.cc Normal file
View File

@ -0,0 +1,124 @@
#include <napi.h>
#include <dwmapi.h>
enum AccentState {
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
ACCENT_ENABLE_HOSTBACKDROP = 5, // RS5 1809
ACCENT_INVALID_STATE = 6
};
enum WindowCompositionAttribute {
WCA_ACCENT_POLICY = 19
};
struct AccentPolicy {
AccentState accentState;
int accentFlags;
int gradientColor;
int animationId;
};
struct WindowCompositionAttributeData {
WindowCompositionAttribute attribute;
PVOID pData;
ULONG dataSize;
};
typedef BOOL(WINAPI
*pSetWindowCompositionAttribute)(HWND, WindowCompositionAttributeData*);
const HINSTANCE hModule = LoadLibrary(TEXT("user32.dll"));
void setVibrancy(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
try {
if (info.Length() == 0) {
Napi::TypeError::New(env, "WINDOW_NOT_GIVEN").ThrowAsJavaScriptException();
return;
}
if (info.Length() != 6) {
Napi::TypeError::New(env, "PARAMETER_ERROR").ThrowAsJavaScriptException();
return;
}
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "UNKNOWN").ThrowAsJavaScriptException();
return;
}
HWND hWnd = (HWND) info[0].As<Napi::Number>().Int64Value();
int isRS4OrGreater = info[1].As<Napi::Number>().Int32Value();
int redValue = info[2].As<Napi::Number>().Int32Value();
int greenValue = info[3].As<Napi::Number>().Int32Value();
int blueValue = info[4].As<Napi::Number>().Int32Value();
int alphaValue = info[5].As<Napi::Number>().Int32Value();
if (hModule) {
const pSetWindowCompositionAttribute SetWindowCompositionAttribute = (pSetWindowCompositionAttribute) GetProcAddress(
hModule, "SetWindowCompositionAttribute");
if (SetWindowCompositionAttribute) {
int gradientColor = (alphaValue<<24) + (blueValue<<16) + (greenValue<<8) + (redValue);
AccentState blurType = isRS4OrGreater == 1 ? ACCENT_ENABLE_ACRYLICBLURBEHIND : ACCENT_ENABLE_BLURBEHIND;
AccentPolicy policy = {blurType, 2, gradientColor, 0};
WindowCompositionAttributeData data = {WCA_ACCENT_POLICY, &policy, sizeof(AccentPolicy)};
SetWindowCompositionAttribute(hWnd, &data);
} else {
Napi::Error::New(env, "FAIL_LOAD_DLL").ThrowAsJavaScriptException();
return;
}
FreeLibrary(hModule);
} else {
Napi::Error::New(env, "FAIL_LOAD_DLL").ThrowAsJavaScriptException();
return;
}
} catch (const char *ex) {
Napi::Error::New(env, "UNKNOWN").ThrowAsJavaScriptException();
}
}
void disableVibrancy(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
try {
if (info.Length() != 1) {
Napi::TypeError::New(env, "WINDOW_NOT_GIVEN").ThrowAsJavaScriptException();
return;
}
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "UNKNOWN").ThrowAsJavaScriptException();
return;
}
HWND hWnd = (HWND) info[0].As<Napi::Number>().Int64Value();
if (hModule) {
const pSetWindowCompositionAttribute SetWindowCompositionAttribute = (pSetWindowCompositionAttribute) GetProcAddress(
hModule, "SetWindowCompositionAttribute");
if (SetWindowCompositionAttribute) {
AccentPolicy policy = {ACCENT_DISABLED, 0, 0, 0};
WindowCompositionAttributeData data = {WCA_ACCENT_POLICY, &policy, sizeof(AccentPolicy)};
SetWindowCompositionAttribute(hWnd, &data);
} else {
Napi::Error::New(env, "FAIL_LOAD_DLL").ThrowAsJavaScriptException();
return;
}
FreeLibrary(hModule);
} else {
Napi::Error::New(env, "FAIL_LOAD_DLL").ThrowAsJavaScriptException();
return;
}
} catch (const char *ex) {
Napi::Error::New(env, "UNKNOWN").ThrowAsJavaScriptException();
}
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "setVibrancy"),
Napi::Function::New(env, setVibrancy));
exports.Set(Napi::String::New(env, "disableVibrancy"),
Napi::Function::New(env, disableVibrancy));
return exports;
}
NODE_API_MODULE(vibrancy, Init
)

829
package-lock.json generated
View File

@ -1,14 +1,502 @@
{
"name": "vscode-vibrancy",
"version": "1.0.9",
"version": "1.0.10-alpha",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"dev": true
},
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
},
"any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
},
"aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"dev": true
},
"are-we-there-yet": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
"dev": true,
"requires": {
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
}
},
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
"dev": true,
"requires": {
"safer-buffer": "~2.1.0"
}
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"dev": true
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
"dev": true
},
"at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
"dev": true
},
"aws4": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
"dev": true
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"dev": true,
"requires": {
"tweetnacl": "^0.14.3"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
"dev": true
},
"chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
"dev": true
},
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dev": true,
"requires": {
"delayed-stream": "~1.0.0"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
"dev": true
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"dev": true,
"requires": {
"assert-plus": "^1.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"dev": true
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
"dev": true
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
"dev": true,
"requires": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"env-paths": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz",
"integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==",
"dev": true
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"dev": true
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
"dev": true
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
"dev": true
},
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"dev": true,
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"fs-extra": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^1.0.0"
}
},
"fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
"dev": true,
"requires": {
"minipass": "^3.0.0"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"dev": true,
"requires": {
"aproba": "^1.0.3",
"console-control-strings": "^1.0.0",
"has-unicode": "^2.0.0",
"object-assign": "^4.1.0",
"signal-exit": "^3.0.0",
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wide-align": "^1.1.0"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"dev": true,
"requires": {
"assert-plus": "^1.0.0"
}
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"graceful-fs": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
"dev": true
},
"har-validator": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
"dev": true,
"requires": {
"ajv": "^6.12.3",
"har-schema": "^2.0.0"
}
},
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
"dev": true
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"dev": true,
"requires": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
"dev": true
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"dev": true
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
"dev": true
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
"dev": true
},
"jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
},
"dependencies": {
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
}
}
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"dev": true,
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
}
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"requires": {
"yallist": "^4.0.0"
}
},
"mime-db": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
"dev": true
},
"mime-types": {
"version": "2.1.27",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
"dev": true,
"requires": {
"mime-db": "1.44.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minipass": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
"integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
"dev": true,
"requires": {
"yallist": "^4.0.0"
}
},
"minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
"dev": true,
"requires": {
"minipass": "^3.0.0",
"yallist": "^4.0.0"
}
},
"mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"dev": true
},
"mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
@ -19,11 +507,258 @@
"thenify-all": "^1.0.0"
}
},
"node-addon-api": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz",
"integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==",
"dev": true
},
"node-gyp": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz",
"integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==",
"dev": true,
"requires": {
"env-paths": "^2.2.0",
"glob": "^7.1.4",
"graceful-fs": "^4.2.3",
"nopt": "^5.0.0",
"npmlog": "^4.1.2",
"request": "^2.88.2",
"rimraf": "^3.0.2",
"semver": "^7.3.2",
"tar": "^6.0.2",
"which": "^2.0.2"
}
},
"nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
"dev": true,
"requires": {
"abbrev": "1"
}
},
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"dev": true,
"requires": {
"are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0",
"gauge": "~2.7.3",
"set-blocking": "~2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
"dev": true
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
"dev": true
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
"dev": true
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true
},
"psl": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
"dev": true
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"dev": true
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
"dev": true
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dev": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
"dev": true,
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.3",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
}
},
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
"semver": {
"version": "7.3.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
"integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"dev": true
},
"signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
"sshpk": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
"dev": true,
"requires": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
}
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"requires": {
"safe-buffer": "~5.1.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
},
"tar": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz",
"integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==",
"dev": true,
"requires": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
"minipass": "^3.0.0",
"minizlib": "^2.1.1",
"mkdirp": "^1.0.3",
"yallist": "^4.0.0"
}
},
"thenify": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz",
@ -39,6 +774,98 @@
"requires": {
"thenify": ">= 3.1.0 < 4"
}
},
"tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"dev": true,
"requires": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"dev": true,
"requires": {
"safe-buffer": "^5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"dev": true
},
"universalify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
},
"uri-js": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
"integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
"dev": true,
"requires": {
"punycode": "^2.1.0"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"dev": true
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"dev": true,
"requires": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
},
"wide-align": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"dev": true,
"requires": {
"string-width": "^1.0.2 || 2"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
}

View File

@ -2,7 +2,7 @@
"name": "vscode-vibrancy",
"displayName": "Vibrancy",
"description": "Vibrancy Effect for Visual Studio Code",
"version": "1.0.9",
"version": "1.0.10-alpha",
"publisher": "eyhn",
"author": {
"email": "cneyhn@gmail.com",
@ -10,7 +10,7 @@
"url": "https://eyhn.in"
},
"engines": {
"vscode": "^1.41.0"
"vscode": "^1.52.1"
},
"categories": [
"Other",
@ -31,7 +31,7 @@
"activationEvents": [
"*"
],
"main": "./src/extension",
"main": "./extension/index.js",
"contributes": {
"commands": [
{
@ -56,7 +56,6 @@
"default": "auto",
"enum": [
"auto",
"dwm",
"acrylic",
"appearance-based",
"light",
@ -71,7 +70,6 @@
],
"enumDescriptions": [
"%configuration.type.auto.description%",
"%configuration.type.dwm.description%",
"%configuration.type.acrylic.description%",
"%configuration.type.appearance-based.description%",
"%configuration.type.light.description%",
@ -110,8 +108,15 @@
}
}
},
"devDependencies": {},
"scripts": {
"build-win10": "node-gyp rebuild"
},
"dependencies": {
"fs-extra": "^9.0.1",
"mz": "^2.7.0"
},
"devDependencies": {
"node-gyp": "^7.1.2",
"node-addon-api": "^3.1.0"
}
}

View File

@ -1,7 +1,6 @@
{
"configuration.type.description": "すりガラス効果の適用方法を制御します。",
"configuration.type.auto.description": "自動",
"configuration.type.dwm.description": "(Windows 7 のみ) Windows のデフォルトのブラー効果を使用します",
"configuration.type.acrylic.description": "(Windows 10 のみ) Fluent Design のブラー効果を使用します",
"configuration.type.appearance-based.description": "(MacOS のみ)",
"configuration.type.light.description": "(MacOS のみ)",
@ -18,5 +17,19 @@
"configuration.imports.description": "インポートする CSS/JS ファイルのパスを指定します。",
"extension.installVibrancy.title": "Vibrancy を有効化",
"extension.uninstallVibrancy.title": "Vibrancy を無効化",
"extension.updateVibrancy.title": "Vibrancy を再読み込み"
"extension.updateVibrancy.title": "Vibrancy を再読み込み",
"messages.admin": "変更を適用するには、Visual Studio Code を管理者として実行してください。",
"messages.firstload": "Vibrancy へようこそ。はじめに README をご覧ください。ボタンをクリックして、インストールを開始します。",
"messages.configupdate": "設定が変更されました。反映させるには、再読み込みします。",
"messages.enabled": "Vibrancy が有効化されました。設定は再起動の後に反映されます。もし Visual Studio Code が破損を検出した場合、\"今後表示しない\" をクリックします。詳細については README をご確認ください。",
"messages.disabled": "Vibrancy が無効化されました。再起動することで、元の状態に戻ります。",
"messages.already_disabled": "Vibrancy は既に無効です。",
"messages.smthingwrong": "問題が発生しました: ",
"messages.recommendedColorTheme": "現在の配色テーマは \"%1\" ですが、選択された Vibrancy テーマには \"%2\" を推奨します。",
"messages.restartIde": "Visual Studio Code を再起動",
"messages.installIde": "Vibrancy をインストール",
"messages.reloadIde": "再読み込み",
"messages.changeColorThemeIde": "配色テーマを変更する",
"messages.noIde": "いいえ"
}

View File

@ -1,7 +1,6 @@
{
"configuration.type.description": "Native method of Vibrancy Effect",
"configuration.type.auto.description": "Automatically switch with system version",
"configuration.type.dwm.description": "(Windows 7 only) Windows default window blur",
"configuration.type.acrylic.description": "(Windows 10 only) Fluent design blur",
"configuration.type.appearance-based.description": "(MacOS only)",
"configuration.type.light.description": "(MacOS only)",
@ -18,5 +17,19 @@
"configuration.imports.description": "Import CSS/JS files, as file paths.",
"extension.installVibrancy.title": "Enable Vibrancy",
"extension.uninstallVibrancy.title": "Disable Vibrancy",
"extension.updateVibrancy.title": "Reload Vibrancy"
"extension.updateVibrancy.title": "Reload Vibrancy",
"messages.firstload": "Welcome to use Vibrancy. Please read the README first. Click the button below to install.",
"messages.configupdate": "Config is changed, do you want to reload.",
"messages.enabled": "Vibrancy enabled. Restart to take effect. If Code complains about it is corrupted, CLICK DON\"T SHOW AGAIN. See README for more detail.",
"messages.disabled": "Vibrancy disabled and reverted to default. Restart to take effect.",
"messages.already_disabled": "Vibrancy already disabled.",
"messages.smthingwrong": "Something went wrong: ",
"messages.unsupported": "Unsupported operating system, only macos and win10 are supported",
"messages.recommendedColorTheme": "Your current color theme is \"%1\" and the Vibrancy theme is designed for \"%2\"!",
"messages.restartIde": "Restart Visual Studio Code",
"messages.installIde": "Install Vibrancy",
"messages.reloadIde": "Reload",
"messages.changeColorThemeIde": "Change The Color Theme",
"messages.noIde": "No"
}

View File

@ -1,7 +1,6 @@
{
"configuration.type.description":"设置毛玻璃效果的类型。",
"configuration.type.auto.description": "自动",
"configuration.type.dwm.description": "(仅限 Windows 7) Windows default window blur",
"configuration.type.acrylic.description": "(仅限 Windows 10) Fluent design blur",
"configuration.type.appearance-based.description": "(仅限 MacOS)",
"configuration.type.light.description": "(仅限 MacOS)",
@ -18,5 +17,19 @@
"configuration.imports.description": "自定义 CSS 或 JS 文件的路径。",
"extension.installVibrancy.title": "安装毛玻璃效果",
"extension.uninstallVibrancy.title": "卸载毛玻璃效果",
"extension.updateVibrancy.title": "重新安装毛玻璃效果"
"extension.updateVibrancy.title": "重新安装毛玻璃效果",
"messages.firstload": "欢迎使用 Vibrancy请先阅读 README单击下面的按钮进行安装。",
"messages.configupdate": "配置已更改,是否要重新加载。",
"messages.enabled": "已安装毛玻璃效果,重启后才能生效。如果 VSCode 提示”安装似乎损坏“,请点击“不再提示”。有关详细信息,请参阅自述文件。",
"messages.disabled": "毛玻璃已卸载并恢复为默认值。重启才能生效。",
"messages.already_disabled": "毛玻璃已经禁用。",
"messages.smthingwrong": "发生了预料之外的错误: ",
"messages.unsupported": "操作系统不支持,仅支持 macos 和 win10。",
"messages.recommendedColorTheme": "你当前的颜色主题是 \"%1\" ,而你的毛玻璃主题是为 \"%2\" 设计的!",
"messages.restartIde": "重启 Visual Studio Code",
"messages.installIde": "安装毛玻璃效果",
"messages.reloadIde": "重新加载",
"messages.changeColorThemeIde": "改变颜色主题",
"messages.noIde": "不要"
}

725
runtime/displayconfig.js Normal file
View File

@ -0,0 +1,725 @@
"use strict";
const addon = require('./displayconfig.node');
/**
* Represents a numeric error code returned from the Win32 API.
*
* @member {number} code is the exact numeric code returned by the Win32 API.
*/
class Win32Error extends Error {
constructor(code) {
super(`Win32 error code ${code}`);
this.code = code;
}
}
module.exports.Win32Error = Win32Error;
/**
* @typedef AdapterId
* @type {object}
* @property {number} LowPart
* @property {number} HighPart
*/
/**
* @typedef DisplayConfigFractional
* @type {object}
* @property {number} Numerator
* @property {number} Denominator
*/
/**
* @typedef SourcePathInfo
* @type {object}
* @property {AdapterId} adapterId
* @property {number} id
* @property {number} statusFlags
* @property {number} modeInfoIdx
*/
/**
* @typedef TargetPathInfo
* @type {object}
* @property {AdapterId} adapterId
* @property {number} id
* @property {number} statusFlags
* @property {string} outputTechnology
* @property {number} rotation
* @property {string} scaling
* @property {DisplayConfigFractional} refreshRate
* @property {string} scanlineOrdering
* @property {number} targetAvailable
* @property {number} modeInfoIdx
*/
/**
* @typedef PathInfoValue
* @type {object}
* @property {number} flags
* @property {SourcePathInfo} sourceInfo
* @property {TargetPathInfo} targetInfo
*/
/**
* @typedef PathInfo
* @type {object}
* @property {PathInfoValue} value
* @property {Buffer} buffer
*/
/**
* @typedef DisplayConfigPosition
* @type {object}
* @property {number} x
* @property {number} y
*/
/**
* @typedef SourceMode
* @type {object}
* @property {number} width
* @property {number} height
* @property {number} pixelFormat
* @property {DisplayConfigPosition} position
*/
/**
* @typedef SourceModeInfo
* @type {object}
* @property {AdapterId} adapterId
* @property {number} id
* @property {"source"} infoType
* @property {SourceMode} sourceMode
*/
/**
* @typedef PixelRate
* @type {object}
* @property {number} lowPart
* @property {number} highPart
*/
/**
* @typedef DisplayConfigSize
* @type {object}
* @property {number} cx
* @property {number} cy
*/
/**
* @typedef TargetVideoSignalInfo
* @type {object}
* @property {PixelRate} pixelRate
* @property {DisplayConfigFractional} hSyncFreq
* @property {DisplayConfigFractional} vSyncFreq
* @property {DisplayConfigSize} activeSize
* @property {DisplayConfigSize} totalSize
* @property {number} videoStandard
* @property {string} scanlineOrdering
*/
/**
* @typedef TargetMode
* @type {object}
* @property {TargetVideoSignalInfo} targetVideoSignalInfo
*/
/**
* @typedef TargetModeInfo
* @type {object}
* @property {AdapterId} adapterId
* @property {number} id
* @property {"target"} infoType
* @property {TargetMode} targetMode
*/
/**
* @typedef ModeInfoValue
* @type {SourceModeInfo | TargetModeInfo}
*/
/**
* @typedef ModeInfo
* @type {object}
* @property {ModeInfoValue} value
* @property {Buffer} buffer
*/
/**
* @typedef NameInfo
* @type {object}
* @property {AdapterId} adapterId
* @property {number} id
* @property {string} outputTechnology
* @property {number} edidManufactureId
* @property {number} edidProductCodeId
* @property {number} connectorInstance
* @property {string} monitorFriendlyDeviceName
* @property {string} monitorDevicePath
*/
/**
* @typedef QueryDisplayConfigResults
* @type {object}
* @property {PathInfo[]} pathArray
* @property {ModeInfo[]} modeInfoArray
* @property {NameInfo[]} nameArray
*/
/**
* Retrieves low-level information from the Win32 API QueryDisplayConfig.
*
* The output of this function somewhat matches the "output" values of
* QueryDisplayConfig, as documented at
* https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-querydisplayconfig,
* in the pathArray and modeInfoArray results.
*
* Additionally, this function uses the DisplayConfigGetDeviceInfo function over
* all resolved displays to return the names, output technology, and manufacturer IDs
* in the nameArray results.
*
* @returns {Promise<QueryDisplayConfigResults>}
* A Promise, resolving to { pathArray: [...], modeInfoArray: [...], nameArray: [...] },
* or rejecting with a {@link Win32Error} if something goes wrong.
*/
module.exports.queryDisplayConfig = () => {
return new Promise((resolve, reject) => {
const ran = addon.win32_queryDisplayConfig((err, result) => {
if (err !== null) {
reject(new Win32Error(err));
} else {
resolve(result);
}
});
if (!ran) {
resolve(undefined);
}
});
};
/**
* @typedef ConfigId
* @type {object}
* @property {AdapterId} adapterId
* @property {number} id
*/
/**
* @typedef ExtractedDisplayConfig
* @type {object}
* @property {string} displayName The "friendly name" of the relevant display
* @property {string} devicePath The Windows NT device path of the relevant display
* @property {ConfigId} sourceConfigId
* @property {ConfigId} targetConfigId
* @property {boolean} inUse Whether this configuration is currently being used
* @property {string} outputTechnology
* @property {number} rotation
* @property {string} scaling
* @property {SourceMode} sourceMode
* @property {TargetVideoSignalInfo | undefined} targetVideoSignalInfo
* @property {Buffer} pathBuffer A Buffer containing the exact DISPLAYCONFIG_PATH_INFO struct
* returned by QueryDisplayConfig for this configuration
* @property {Buffer} sourceModeBuffer A Buffer containing the exact DISPLAYCONFIG_MODE_INFO
* source struct returned by QueryDisplayConfig for this configuration
* @property {Buffer | undefined} targetModeBuffer A Buffer containing the exact DISPLAYCONFIG_MODE_INFO
* target struct returned by QueryDisplayConfig for this configuration
*/
/**
* Retrieves higher-level information from the Win32 API QueryDisplayConfig.
*
* Unlike {@link queryDisplayConfig}, this function pulls all relevant information
* about a device/mode pairing into a single object.
*
* @returns {Promise<ExtractedDisplayConfig>} A Promise, resolving to display configuration information
* or rejecting with a {@link Win32Error} if something goes wrong.
*/
module.exports.extractDisplayConfig = async () => {
const config = await module.exports.queryDisplayConfig();
const ret = [];
for (const { value, buffer: pathBuffer } of config.pathArray) {
let inUse = value.flags & (1 === 1) ? true : false;
const { sourceInfo, targetInfo } = value;
const {
modeInfoIdx: sourceModeIdx,
adapterId: sourceAdapterId,
id: sourceId,
} = sourceInfo;
const {
adapterId,
id,
outputTechnology,
rotation,
scaling,
modeInfoIdx: targetModeIdx,
} = targetInfo;
const sourceConfigId = {
adapterId: sourceAdapterId,
id: sourceId,
};
const targetConfigId = {
adapterId,
id,
};
const displayNameEntry = config.nameArray.find(
(n) =>
n.adapterId.LowPart === adapterId.LowPart &&
n.adapterId.HighPart === adapterId.HighPart &&
n.id === id &&
n.outputTechnology &&
outputTechnology &&
n.monitorDevicePath.length > 0
);
if (displayNameEntry === undefined) {
continue;
}
const sourceMode = config.modeArray[sourceModeIdx];
const targetMode = config.modeArray[targetModeIdx];
if (sourceMode === undefined) {
continue;
}
if (targetMode === undefined) {
// When we can't find the target mode, but _can_
// find the source mode, that just means the monitor is off.
inUse = false;
}
const sourceModeValue = sourceMode.value;
if (sourceModeValue.infoType !== "source") {
continue;
}
const { monitorFriendlyDeviceName, monitorDevicePath } = displayNameEntry;
const output = {
displayName: monitorFriendlyDeviceName,
devicePath: monitorDevicePath,
sourceConfigId,
targetConfigId,
inUse,
outputTechnology,
rotation,
scaling,
sourceMode: sourceModeValue.sourceMode,
pathBuffer,
sourceModeBuffer: sourceMode.buffer,
};
if (targetMode !== undefined) {
const targetModeValue = targetMode.value;
if (targetModeValue.infoType === "target") {
output.targetVideoSignalInfo =
targetModeValue.targetMode.targetVideoSignalInfo;
output.targetModeBuffer = targetMode.buffer;
}
}
ret.push(output);
}
return ret;
};
async function win32_toggleEnabledDisplays(args) {
return new Promise((resolve, reject) => {
const ran = addon.win32_toggleEnabledDisplays(args, (_, errorCode) => {
if (errorCode === 0) {
resolve();
} else {
reject(new Win32Error(errorCode));
}
});
if (!ran) {
resolve();
}
});
}
/**
* @typedef ToggleEnabledDisplaysArgs
* @type {object}
* @property {string[]} enablePaths Exact Windows NT device paths of the displays to enable
* @property {string[]} disablePaths Exact Windows NT device paths of the displays to disable
* @property {boolean} persistent Whether to save this configuration as the default configuration
*/
/**
* Toggles enabled/disabled state of the given displays.
*
* If "persistent", then this is saved between restarts.
*
* @param {ToggleEnabledDisplaysArgs} args
*/
module.exports.toggleEnabledDisplays = async (args) => {
const { persistent, enable: enablePaths, disable: disablePaths } = args;
const enable = [];
const disable = [];
const displayConfig = await module.exports.extractDisplayConfig();
for (const { devicePath, targetConfigId } of displayConfig) {
if (Array.isArray(enablePaths) && enablePaths.indexOf(devicePath) >= 0) {
enable.push(targetConfigId);
}
if (Array.isArray(disablePaths) && disablePaths.indexOf(devicePath) >= 0) {
disable.push(targetConfigId);
}
}
await win32_toggleEnabledDisplays({ enable, disable, persistent });
};
function setSubtract(left, right) {
const ret = new Set();
for (const entry of left) {
if (!right.has(entry)) {
ret.add(entry);
}
}
return Array.from(ret);
}
function devicePathLookupForEnabledDisplayConfig(conf) {
const ret = {};
for (const entry of conf) {
if (entry.inUse && entry.targetModeBuffer === undefined) {
continue;
}
if (ret[entry.devicePath] !== undefined) {
continue;
}
ret[entry.devicePath] = entry;
}
return ret;
}
/**
* @typedef DisplayRestorationConfigurationEntry
* @type {object}
* @property {string} devicePath
* @property {string} pathBuffer A Base-64 encoded binary blob representing
* a DISPLAYCONFIG_PATH_INFO instance for the given devicePath
* @property {string} sourceModeBuffer A Base-64 encoded binary blob representing
* a DISPLAYCONFIG_MODE_INFO source instance for the given devicePath
* @property {string} targetModeBuffer A Base-64 encoded binary blob representing
* a DISPLAYCONFIG_MODE_INFO target instance for the given devicePath
*/
/**
* Returns a display configuration suitable for restoration with {@link restoreDisplayConfig}.
*
* @returns {DisplayRestorationConfigurationEntry[]}
*/
module.exports.displayConfigForRestoration = async () => {
const currentConfig = await module.exports.extractDisplayConfig();
const ret = [];
for (const entry of currentConfig) {
if (!entry.inUse || entry.targetModeBuffer === undefined) {
continue;
}
const {
devicePath,
pathBuffer,
sourceModeBuffer,
targetModeBuffer,
} = entry;
ret.push({
devicePath,
pathBuffer: pathBuffer.toString("base64"),
sourceModeBuffer: sourceModeBuffer.toString("base64"),
targetModeBuffer: targetModeBuffer.toString("base64"),
});
}
return ret;
};
async function win32_restoreDisplayConfig(configs, persistent) {
return new Promise((resolve, reject) => {
const ran = addon.win32_restoreDisplayConfig(
configs,
(_, errorCode) => {
if (errorCode === 0) {
resolve();
} else {
reject(new Win32Error(errorCode));
}
},
persistent
);
if (!ran) {
resolve();
}
});
}
/**
* @typedef RestoreDisplayConfigArgs
* @type {object}
* @property {DisplayRestorationConfigurationEntry[]} config
* @property {boolean} persistent Whether to save this configuration as the default configuration
*/
/**
* Restores a display configuration derived from {@link displayConfigForRestoration}.
*
* If the given configuration refers to enabled displays that are not currently attached,
* this function simply enables the displays known to the given configuration and
* disables all attached displays not known to the given configuration. Otherwise,
* the given configuration is applied to the display set.
*
* @param {RestoreDisplayConfigArgs} args
*/
module.exports.restoreDisplayConfig = async (args) => {
const devicePathNames = args.config
.filter(({ targetModeBuffer }) => targetModeBuffer !== undefined)
.map(({ devicePath }) => devicePath);
const currentConfig = await module.exports.extractDisplayConfig();
const givenAsSet = new Set(currentConfig.map(({ devicePath }) => devicePath));
const expectedEnabledAsSet = new Set(devicePathNames);
const missingEnabled = setSubtract(expectedEnabledAsSet, givenAsSet);
// Here's the idea behind this:
// We have a set of monitors we want enabled, and a set of monitors that are enabled.
// Ideally, these should be identical sets. But it's also possible that
//
// 1. The current state has strictly more enabled monitors than the expected state
// 2. The current state has strictly fewer enabled monitors than the expected state
// 3. The current state has some monitors that are missing, and some that are unexpected.
//
// What we're about to do here is coerce the monitor state to the expected state; if more
// monitors are enabled or disabled in the given state then that's fine, we're correcting
// that away. The trick here is that the monitors in the expected state we _do_ want to
// enable have to exist in the first place (we don't care about the ones we want to disable,
// missing is also disabled if you squint hard enough).
if (missingEnabled.length === 0) {
const pathLookup = devicePathLookupForEnabledDisplayConfig(currentConfig);
const coercedState = [];
for (const entry of args.config) {
if (entry.targetModeBuffer === undefined) {
continue;
}
const currentConfigEntry = pathLookup[entry.devicePath];
if (currentConfigEntry === undefined) {
continue;
}
const { sourceConfigId, targetConfigId } = currentConfigEntry;
const { pathBuffer, sourceModeBuffer, targetModeBuffer } = entry;
coercedState.push({
sourceConfigId,
targetConfigId,
pathBuffer: Buffer.from(pathBuffer, "base64"),
sourceModeBuffer: Buffer.from(sourceModeBuffer, "base64"),
targetModeBuffer: Buffer.from(targetModeBuffer, "base64"),
});
}
await win32_restoreDisplayConfig(coercedState, args.persistent);
} else {
const seen = new Set();
const enable = [];
const disable = [];
const notInUse = args.config
.filter(({ targetModeBuffer }) => targetModeBuffer === undefined)
.map(({ devicePath }) => devicePath);
for (const devicePathName of devicePathNames) {
if (!seen.has(devicePathName) && givenAsSet.has(devicePathName)) {
enable.push(devicePathName);
seen.add(devicePathName);
}
}
for (const devicePathName of notInUse) {
if (!seen.has(devicePathName) && givenAsSet.has(devicePathName)) {
disable.push(devicePathName);
seen.add(devicePathName);
}
}
await module.exports.toggleEnabledDisplays({
enable,
disable,
persistent: args.persistent,
});
}
};
let currentDisplayConfig;
const displayChangeCallbacks = new Set();
async function updateDisplayStateAndNotifyCallbacks() {
try {
currentDisplayConfig = await module.exports.extractDisplayConfig();
for (const callback of Array.from(displayChangeCallbacks)) {
callback(null, currentDisplayConfig);
}
} catch (e) {
for (const callback of Array.from(displayChangeCallbacks)) {
callback(e);
}
}
}
let currentDisplayConfigPromise = updateDisplayStateAndNotifyCallbacks();
function setupListenForDisplayChanges() {
addon.win32_listenForDisplayChanges((err) => {
if (err === null) {
currentDisplayConfigPromise = currentDisplayConfigPromise.then(() =>
updateDisplayStateAndNotifyCallbacks()
);
}
});
}
/**
* Registers a display change listener.
*
* This function will be called immediately upon registration, receiving the
* current display configuration. It will also be called every time the display
* configuration changes in Windows, e.g. when users attach or rearrange new
* displays, or alter the output resolution of already-attached displays.
*
* Note that the Node event loop will continue executing if any outstanding change
* listeners are registered, precluding graceful shutdown. Use {@link removeDisplayChangeListener}
* to remove outstanding display change listeners and clear the event loop.
*
* @param {function(Error | null, ExtractedDisplayConfig | undefined): void} listener
* @returns {function(Error | null, ExtractedDisplayConfig | undefined): void} the listener argument as passed
*/
module.exports.addDisplayChangeListener = (listener) => {
if (displayChangeCallbacks.size === 0) {
setupListenForDisplayChanges();
}
displayChangeCallbacks.add(listener);
if (currentDisplayConfig !== undefined) {
listener(null, currentDisplayConfig);
}
return listener;
};
/**
* De-registers a display change listener.
*
* De-registering all display change listeners clears the event loop of pending
* work started by {@link addDisplayChangeListener} to allow for a graceful shutdown.
*
* @param {function(Error | null, ExtractedDisplayConfig | undefined): void} listener previously passed to {@link addDisplayChangeListener}
*/
module.exports.removeDisplayChangeListener = (listener) => {
displayChangeCallbacks.delete(listener);
if (displayChangeCallbacks.size === 0) {
addon.win32_stopListeningForDisplayChanges();
}
};
/**
* Establishes a context for determining the vertical refresh rate.
*
* Active instances of this class will establish perpetual work on the event loop,
* as the internals use {@link addDisplayChangeListener} to react to display changes.
*
* In order to clear the relevant work on the Node event loop, you must call
* {@link VerticalRefreshRateContext.close} when you are finished using this context.
*/
class VerticalRefreshRateContext {
constructor() {
let readyPromiseResolver;
let readyPromiseResolved = false;
this.readyPromise = new Promise((resolve) => {
readyPromiseResolver = () => {
if (readyPromiseResolved) return;
readyPromiseResolved = true;
resolve();
};
});
this.geometry = [];
const computeDisplayGeometryFromConfig = (err, conf) => {
if (err !== null) {
return;
}
const geom = [];
for (const { sourceMode, targetVideoSignalInfo, inUse } of conf) {
if (!inUse) {
continue;
}
const { width, height, position } = sourceMode;
const { vSyncFreq } = targetVideoSignalInfo;
// 30Hz is a safe guess for broken vSyncFreq outputs, I think...
const vRefreshRate =
vSyncFreq.Numerator === 0 || vSyncFreq.Denominator === 0
? 30
: vSyncFreq.Numerator / vSyncFreq.Denominator;
const top = position.y;
const bottom = position.y + height;
const left = position.x;
const right = position.x + width;
geom.push({ top, bottom, left, right, vRefreshRate });
}
this.geometry = geom;
readyPromiseResolver();
};
this.changeListener = module.exports.addDisplayChangeListener(
computeDisplayGeometryFromConfig
);
}
/**
* Computes the vertical refresh rate of the displays at a given display point.
*
* If any displays overlap at the given display point, the return result will
* be the minimum of the vertical refresh rates of each physical device displaying
* at that effective point.
*
* This method is asynchronous due to the implementation of addDisplayChangeListener;
* it waits for a valid display configuration to be captured before returning the
* best possible refresh rate.
*
* @param {number} x The vertical offset of the display point
* @param {number} y The horizontal offset of the display point
*
* @returns {number | undefined} The vertical refresh rate at the given display point,
* or undefined if the given display point is out of bounds of the available display space.
*/
async findVerticalRefreshRateForDisplayPoint(x, y) {
await this.readyPromise;
let ret;
for (const { top, bottom, left, right, vRefreshRate } of this.geometry) {
if (left <= x && x < right && top <= y && y < bottom) {
ret = ret === undefined ? vRefreshRate : Math.min(ret, vRefreshRate);
}
}
return ret;
}
/**
* Disconnects this instance from display change events.
*
* Disconnecting the instance from display change events will clear relevant
* work items off of the event loop as per {@link removeDisplayChangeListener}.
*/
close() {
module.exports.removeDisplayChangeListener(this.changeListener);
}
}
module.exports.VerticalRefreshRateContext = VerticalRefreshRateContext;

BIN
runtime/displayconfig.node Normal file

Binary file not shown.

136
runtime/index.js Normal file
View File

@ -0,0 +1,136 @@
const electron = require('electron');
/**
* @type {{ os: string, config: any, themeCSS: string, theme: any }}
*/
const app = global.vscode_vibrancy_plugin;
const macosType = [
"appearance-based",
"light",
"dark",
"titlebar",
"selection",
"menu",
"popover",
"sidebar",
"medium-light",
"ultra-dark"
];
const windowsType = [
"acrylic"
];
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
electron.app.on('browser-window-created', (_, window) => {
var type = app.config.type;
if (type !== 'auto') {
if (app.os === 'win10' && !windowsType.includes(type)) type = 'auto';
if (app.os === 'macos' && !macosType.includes(type)) type = 'auto';
}
if (type === 'auto') {
type = app.theme.type[app.os];
}
let opacity = app.config.opacity;
// if opacity < 0, use the theme default opacity
if (opacity < 0) {
opacity = app.theme.opacity[app.os]
}
const backgroundRGB = hexToRgb(app.theme.background);
if (app.os === 'win10') {
const bindings = require('./vibrancy.js');
bindings.setVibrancy(window.getNativeWindowHandle().readInt32LE(0), 1, backgroundRGB.r, backgroundRGB.g, backgroundRGB.b, 0);
const win10refresh = require('./win10refresh.js');
win10refresh(window, 60);
window.webContents.once('dom-ready', () => {
const currentURL = window.webContents.getURL();
if (!currentURL.includes('workbench.html')) {
return;
}
if (window.isMaximized()) {
window.unmaximize();
window.maximize();
}
});
}
if (app.os === 'macos') {
window.setVibrancy(type);
}
window.webContents.on('dom-ready', () => {
const currentURL = window.webContents.getURL();
if (!currentURL.includes('workbench.html')) {
return;
}
window.setBackgroundColor('#00000000');
window.webContents.executeJavaScript("document.body.innerHTML += " + JSON.stringify(HTML()))
});
});
function HTML() {
if (app.os === 'unknown') return '';
var type = app.config.type;
if (type === 'auto') {
type = app.theme.type[app.os];
}
let opacity = app.config.opacity;
if (opacity < 0) {
opacity = app.theme.opacity[app.os]
}
const backgroundRGB = hexToRgb(app.theme.background);
const HTML = [
`
<style>
html {
background: rgba(${backgroundRGB.r},${backgroundRGB.g},${backgroundRGB.b},${opacity}) !important;
}
</style>
`,
`
<style>
${app.themeCSS}
</style>
`,
...app.config.imports.map(function (x) {
if (!x) return '';
if (typeof x === 'string') {
x = new URL(x, 'file://').href;
if (!x.startsWith('file://')) {
x = 'file://' + x;
}
if (/^.*\.js$/.test(x)) return '<script src="' + x + '"></script>';
if (/^.*\.css$/.test(x)) return '<link rel="stylesheet" href="' + x + '"/>';
}
return '';
})
]
return HTML.join('')
}

3
runtime/vibrancy.js Normal file
View File

@ -0,0 +1,3 @@
const addon = require('./vibrancy.node');
module.exports = addon;

BIN
runtime/vibrancy.node Normal file

Binary file not shown.

260
runtime/win10refresh.js Normal file
View File

@ -0,0 +1,260 @@
const {VerticalRefreshRateContext} = require('./displayconfig')
const electron = require('electron')
const process = require('process')
function sleep(duration) {
return new Promise(resolve => setTimeout(resolve, duration));
}
function areBoundsEqual(left, right) {
return left.height === right.height
&& left.width === right.width
&& left.x === right.x
&& left.y === right.y;
}
const billion = 1000 * 1000 * 1000;
function hrtimeDeltaForFrequency(freq) {
return BigInt(Math.ceil(billion / freq));
}
let disableJitterFix = false
// Detect if cursor is near the screen edge. Used to disable the jitter fix in 'move' event.
function isInSnapZone() {
const point = electron.screen.getCursorScreenPoint()
const display = electron.screen.getDisplayNearestPoint(point)
// Check if cursor is near the left/right edge of the active display
return (point.x > display.bounds.x - 20 && point.x < display.bounds.x + 20) || (point.x > display.bounds.x + display.bounds.width - 20 && point.x < display.bounds.x + display.bounds.width + 20);
}
/**
* Unfortunately, we have to re-implement moving and resizing.
* Enabling vibrancy slows down the window's event handling loop to the
* point building a mouse event backlog. If you just handle these events
* in the backlog without taking the time difference into consideration,
* you end up with visible movement lag.
* We tried pairing 'will-move' with 'move', but Electron actually sends the
* 'move' events _before_ Windows actually commits to the operation. There's
* likely some queuing going on that's getting backed up. This is not the case
* with 'will-resize' and 'resize', which need to use the default behavior
* for compatibility with soft DPI scaling.
* The ideal rate of moving and resizing is based on the vertical sync
* rate: if your display is only fully updating at 120 Hz, we shouldn't
* be attempting to reset positions or sizes any faster than 120 Hz.
* If we were doing this in a browser context, we would just use
* requestAnimationFrame and call it a day. But we're not inside of a
* browser context here, so we have to resort to clever hacks.
* This VerticalRefreshRateContext maps a point in screen space to the
* vertical sync rate of the display(s) actually handing that point.
* It handles multiple displays with varying vertical sync rates,
* and changes to the display configuration while this process is running.
*/
module.exports = function win10refresh(win, maximumRefreshRate) {
if (!('__electron_acrylic_window__' in win)) {
win.__electron_acrylic_window__ = {};
}
const refreshCtx = new VerticalRefreshRateContext()
function getRefreshRateAtCursor(cursor) {
cursor = cursor || electron.screen.getCursorScreenPoint()
return refreshCtx.findVerticalRefreshRateForDisplayPoint(cursor.x, cursor.y)
}
// Ensure all movement operation is serialized, by setting up a continuous promise chain
// All movement operation will take the form of
//
// boundsPromise = boundsPromise.then(() => { /* work */ })
//
// So that there are no asynchronous race conditions.
let pollingRate
let doFollowUpQuery = false, isMoving = false, shouldMove = false
let moveLastUpdate = BigInt(0), resizeLastUpdate = BigInt(0)
let lastWillMoveBounds, lastWillResizeBounds,
desiredMoveBounds
let boundsPromise = Promise.race([
getRefreshRateAtCursor(electron.screen.getCursorScreenPoint()).then(rate => {
pollingRate = rate || 30
doFollowUpQuery = true
}),
// Establishing the display configuration can fail; we can't
// just block forever if that happens. Instead, establish
// a fallback polling rate and hope for the best.
sleep(2000).then(() => {
pollingRate = pollingRate || 30
})
])
async function doFollowUpQueryIfNecessary(cursor) {
if (doFollowUpQuery) {
const rate = await getRefreshRateAtCursor(cursor)
if (rate != pollingRate) console.log(`New polling rate: ${rate}`)
pollingRate = rate || 30
}
}
function setWindowBounds(bounds) {
if (win.isDestroyed()) return
win.setBounds(bounds)
desiredMoveBounds = win.getBounds()
}
function currentTimeBeforeNextActivityWindow(lastTime, forceFreq) {
return process.hrtime.bigint() <
lastTime + hrtimeDeltaForFrequency(forceFreq || pollingRate || 30)
}
function guardingAgainstMoveUpdate(fn) {
if (pollingRate === undefined || !currentTimeBeforeNextActivityWindow(moveLastUpdate)) {
moveLastUpdate = process.hrtime.bigint()
fn()
return true
} else {
return false
}
}
win.on('will-move', (e, newBounds) => {
if (win.__electron_acrylic_window__.opacityInterval) return
// We get a _lot_ of duplicate bounds sent to us in this event.
// This messes up our timing quite a bit.
if (lastWillMoveBounds !== undefined && areBoundsEqual(lastWillMoveBounds, newBounds)) {
e.preventDefault()
return
}
if (lastWillMoveBounds) {
newBounds.width = lastWillMoveBounds.width
newBounds.height = lastWillMoveBounds.height
}
lastWillMoveBounds = newBounds
// If we're asked to perform some move update and it's under
// the refresh speed limit, we can just do it immediately.
// This also catches moving windows with the keyboard.
const didOptimisticMove = !isMoving && guardingAgainstMoveUpdate(() => {
// Do nothing, the default behavior of the event is exactly what we want.
desiredMoveBounds = undefined
})
if (didOptimisticMove) {
boundsPromise = boundsPromise.then(doFollowUpQueryIfNecessary)
return
}
e.preventDefault()
// Track if the user is moving the window
if (win.__electron_acrylic_window__.moveTimeout) clearTimeout(win.__electron_acrylic_window__.moveTimeout)
win.__electron_acrylic_window__.moveTimeout = setTimeout(() => {
shouldMove = false
}, 1000 / Math.min(pollingRate, maximumRefreshRate))
// Disable next event ('move') if cursor is near the screen edge
disableJitterFix = isInSnapZone()
// Start new behavior if not already
if (!shouldMove) {
shouldMove = true
if (isMoving) return false
isMoving = true
// Get start positions
const basisBounds = win.getBounds()
const basisCursor = electron.screen.getCursorScreenPoint()
// Handle polling at a slower interval than the setInterval handler
function handleIntervalTick(moveInterval) {
boundsPromise = boundsPromise.then(() => {
if (!shouldMove) {
isMoving = false
clearInterval(moveInterval)
return
}
const cursor = electron.screen.getCursorScreenPoint()
const didIt = guardingAgainstMoveUpdate(() => {
// Set new position
if (lastWillResizeBounds && lastWillResizeBounds.width) setWindowBounds({
x: Math.floor(basisBounds.x + (cursor.x - basisCursor.x)),
y: Math.floor(basisBounds.y + (cursor.y - basisCursor.y)),
width: Math.floor(lastWillResizeBounds.width / electron.screen.getDisplayMatching(basisBounds).scaleFactor),
height: Math.floor(lastWillResizeBounds.height / electron.screen.getDisplayMatching(basisBounds).scaleFactor)
})
else setWindowBounds({
x: Math.floor(basisBounds.x + (cursor.x - basisCursor.x)),
y: Math.floor(basisBounds.y + (cursor.y - basisCursor.y)),
width: Math.floor(lastWillMoveBounds.width / electron.screen.getDisplayMatching(basisBounds).scaleFactor),
height: Math.floor(lastWillMoveBounds.height / electron.screen.getDisplayMatching(basisBounds).scaleFactor)
})
})
if (didIt) {
return doFollowUpQueryIfNecessary(cursor)
}
})
}
// Poll at 600hz while moving window
const moveInterval = setInterval(() => handleIntervalTick(moveInterval), 1000 / 600)
}
})
win.on('move', (e) => {
if (disableJitterFix) {
return false
}
if (isMoving || win.isDestroyed()) {
e.preventDefault()
return false
}
// As insane as this sounds, Electron sometimes reacts to prior
// move events out of order. Specifically, if you have win.setBounds()
// twice, then for some reason, when you exit the move state, the second
// call to win.setBounds() gets reverted to the first call to win.setBounds().
//
// Again, it's nuts. But what we can do in this circumstance is thwack the
// window back into place just to spite Electron. Yes, there's a shiver.
// No, there's not much we can do about it until Electron gets their act together.
if (desiredMoveBounds !== undefined) {
const forceBounds = desiredMoveBounds
desiredMoveBounds = undefined
win.setBounds({
x: Math.floor(forceBounds.x),
y: Math.floor(forceBounds.y),
width: Math.floor(forceBounds.width),
height: Math.floor(forceBounds.height)
})
}
})
win.on('will-resize', (e, newBounds) => {
if (lastWillResizeBounds !== undefined && areBoundsEqual(lastWillResizeBounds, newBounds)) {
e.preventDefault()
return
}
lastWillResizeBounds = newBounds
// 60 Hz ought to be enough... for resizes.
// Some systems have trouble going 120 Hz, so we'll just take the lower
// of the current pollingRate and 60 Hz.
if (pollingRate !== undefined &&
currentTimeBeforeNextActivityWindow(resizeLastUpdate, Math.min(pollingRate, maximumRefreshRate))) {
e.preventDefault()
return false
}
// We have to count this twice: once before the resize,
// and once after the resize. We actually don't have any
// timing control around _when_ the resize happened, so
// we have to be pessimistic.
resizeLastUpdate = process.hrtime.bigint()
})
win.on('resize', () => {
resizeLastUpdate = process.hrtime.bigint()
boundsPromise = boundsPromise.then(doFollowUpQueryIfNecessary)
})
// Close the VerticalRefreshRateContext so Node can exit cleanly
win.on('closed', refreshCtx.close)
}

Binary file not shown.

View File

@ -1,31 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29201.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blur-cli", "blur-cli\blur-cli.vcxproj", "{B7685D5D-1C32-4988-A15A-44EEACC7F20E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B7685D5D-1C32-4988-A15A-44EEACC7F20E}.Debug|x64.ActiveCfg = Debug|x64
{B7685D5D-1C32-4988-A15A-44EEACC7F20E}.Debug|x64.Build.0 = Debug|x64
{B7685D5D-1C32-4988-A15A-44EEACC7F20E}.Debug|x86.ActiveCfg = Debug|Win32
{B7685D5D-1C32-4988-A15A-44EEACC7F20E}.Debug|x86.Build.0 = Debug|Win32
{B7685D5D-1C32-4988-A15A-44EEACC7F20E}.Release|x64.ActiveCfg = Release|x64
{B7685D5D-1C32-4988-A15A-44EEACC7F20E}.Release|x64.Build.0 = Release|x64
{B7685D5D-1C32-4988-A15A-44EEACC7F20E}.Release|x86.ActiveCfg = Release|Win32
{B7685D5D-1C32-4988-A15A-44EEACC7F20E}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E9D6A7A8-34A9-49E0-AA23-2F49D5D65842}
EndGlobalSection
EndGlobal

View File

@ -1,127 +0,0 @@
#include "pch.h"
#include <dwmapi.h>
#include <iostream>
#include <algorithm>
struct ACCENTPOLICY {
int nAccentState;
int nFlags;
int nColor;
int nAnimationId;
};
struct WINCOMPATTRDATA {
int nAttribute;
PVOID pData;
ULONG ulDataSize;
};
enum AccentTypes {
ACCENT_DISABLE = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_ENABLE_ACRYLIC = 4
};
enum BlurTypes {
DWM_BLUR = 0,
ACRYLIC_BLUR = 1
};
char* getCmdOption(char ** begin, char ** end, const std::string & option)
{
char ** itr = std::find(begin, end, option);
if (itr != end && ++itr != end)
{
return *itr;
}
return 0;
}
bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
return std::find(begin, end, option) != end;
}
int main(int argc, char *argv[], char *envp[])
{
HWND handle = NULL;
int blurtype = DWM_BLUR;
double opacity = 0.86;
bool enable = true;
int color = 0x1e1e1e;
handle = (HWND)atoi(argv[1]);
if (cmdOptionExists(argv, argv + argc, "--type")) {
char* value_str = getCmdOption(argv, argv + argc, "--type");
if (strcmp(value_str, "acrylic") == 0) {
blurtype = ACRYLIC_BLUR;
}
else if (strcmp(value_str, "dwm") == 0) {
blurtype = DWM_BLUR;
}
}
if (cmdOptionExists(argv, argv + argc, "--enable")) {
char* value_str = getCmdOption(argv, argv + argc, "--enable");
if (strcmp(value_str, "false") == 0) {
enable = false;
}
else if (strcmp(value_str, "true") == 0) {
enable = true;
}
}
if (cmdOptionExists(argv, argv + argc, "--opacity")) {
char* value_str = getCmdOption(argv, argv + argc, "--opacity");
opacity = atof(value_str);
}
if (cmdOptionExists(argv, argv + argc, "--color")) {
char* value_str = getCmdOption(argv, argv + argc, "--color");
char* ptr;
color = strtol(value_str, &ptr, 16);
}
if (blurtype == DWM_BLUR) {
// Create and populate the Blur Behind structure
DWM_BLURBEHIND bb = { 0 };
// Enable Blur Behind and apply to the entire client area
bb.dwFlags = DWM_BB_ENABLE;
bb.fEnable = enable;
bb.hRgnBlur = NULL;
const HRESULT returnValue = DwmEnableBlurBehindWindow(handle, &bb);
return SUCCEEDED(returnValue) ? 0 : 1;
}
else if (blurtype == ACRYLIC_BLUR) {
const HINSTANCE hModule = LoadLibrary(TEXT("user32.dll"));
int result = 1;
if (hModule) {
typedef BOOL(WINAPI*pSetWindowCompositionAttribute)(HWND,
WINCOMPATTRDATA*);
const pSetWindowCompositionAttribute
SetWindowCompositionAttribute =
(pSetWindowCompositionAttribute)GetProcAddress(
hModule,
"SetWindowCompositionAttribute");
// Only works on Win10
if (SetWindowCompositionAttribute) {
ACCENTPOLICY policy =
{ enable ? ACCENT_ENABLE_ACRYLIC
: ACCENT_DISABLE , 2, ((UINT)(opacity * 255.0) << 24) | color, 0 };
WINCOMPATTRDATA data = { 19, &policy, sizeof(ACCENTPOLICY) };
if (SetWindowCompositionAttribute(handle, &data))
result = 0;
else
result = 1;
}
FreeLibrary(hModule);
return result;
}
}
}

View File

@ -1,172 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{B7685D5D-1C32-4988-A15A-44EEACC7F20E}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>blurcli</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="blur-cli.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="blur-cli.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -1,5 +0,0 @@
// pch.cpp: 与预编译标头对应的源文件;编译成功所必需的
#include "pch.h"
// 一般情况下,忽略此文件,但如果你使用的是预编译标头,请保留它。

View File

@ -1,14 +0,0 @@
// 入门提示:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
#ifndef PCH_H
#define PCH_H
// TODO: 添加要在此处预编译的标头
#endif //PCH_H

View File

@ -1,15 +0,0 @@
{
"messages.admin": "変更を適用するには、Visual Studio Code を管理者として実行してください。",
"messages.firstload": "Vibrancy へようこそ。はじめに README をご覧ください。ボタンをクリックして、インストールを開始します。",
"messages.configupdate": "設定が変更されました。反映させるには、再読み込みします。",
"messages.enabled": "Vibrancy が有効化されました。設定は再起動の後に反映されます。もし Visual Studio Code が破損を検出した場合、\"今後表示しない\" をクリックします。詳細については README をご確認ください。",
"messages.disabled": "Vibrancy が無効化されました。再起動することで、元の状態に戻ります。",
"messages.already_disabled": "Vibrancy は既に無効です。",
"messages.smthingwrong": "問題が発生しました: ",
"messages.recommendedColorTheme": "現在の配色テーマは \"%1\" ですが、選択された Vibrancy テーマには \"%2\" を推奨します。",
"messages.restartIde": "Visual Studio Code を再起動",
"messages.installIde": "Vibrancy をインストール",
"messages.reloadIde": "再読み込み",
"messages.changeColorThemeIde": "配色テーマを変更する",
"messages.noIde": "いいえ"
}

View File

@ -1,15 +0,0 @@
{
"messages.admin": "Run VS Code with admin privileges so the changes can be applied.",
"messages.firstload": "Welcome to use Vibrancy. Please read the README first. Click the button below to install.",
"messages.configupdate": "Config is changed, do you want to reload.",
"messages.enabled": "Vibrancy enabled. Restart to take effect. If Code complains about it is corrupted, CLICK DON\"T SHOW AGAIN. See README for more detail.",
"messages.disabled": "Vibrancy disabled and reverted to default. Restart to take effect.",
"messages.already_disabled": "Vibrancy already disabled.",
"messages.smthingwrong": "Something went wrong: ",
"messages.recommendedColorTheme": "Your current color theme is \"%1\" and the Vibrancy theme is designed for \"%2\"!",
"messages.restartIde": "Restart Visual Studio Code",
"messages.installIde": "Install Vibrancy",
"messages.reloadIde": "Reload",
"messages.changeColorThemeIde": "Change The Color Theme",
"messages.noIde": "No"
}

View File

@ -1,15 +0,0 @@
{
"messages.admin": "无法写入文件,请使用管理员权限运行 VSCode。",
"messages.firstload": "欢迎使用 Vibrancy请先阅读 README单击下面的按钮进行安装。",
"messages.configupdate": "配置已更改,是否要重新加载。",
"messages.enabled": "已安装毛玻璃效果,重启后才能生效。如果 VSCode 提示”安装似乎损坏“,请点击“不再提示”。有关详细信息,请参阅自述文件。",
"messages.disabled": "毛玻璃已卸载并恢复为默认值。重启才能生效。",
"messages.already_disabled": "毛玻璃已经禁用。",
"messages.smthingwrong": "发生了预料之外的错误: ",
"messages.recommendedColorTheme": "你当前的颜色主题是 \"%1\" ,而你的毛玻璃主题是为 \"%2\" 设计的!",
"messages.restartIde": "重启 Visual Studio Code",
"messages.installIde": "安装毛玻璃效果",
"messages.reloadIde": "重新加载",
"messages.changeColorThemeIde": "改变颜色主题",
"messages.noIde": "不要"
}

View File

@ -1,12 +1,10 @@
{
"type": {
"win7": "dwm",
"win10": "acrylic",
"macos": "ultra-dark"
},
"background": "1e1e1e",
"opacity": {
"win7": 0.3,
"win10": 0.8,
"macos": 0.3
},

View File

@ -1,12 +1,10 @@
{
"type": {
"win7": "dwm",
"win10": "acrylic",
"macos": "ultra-dark"
},
"background": "1e1e1e",
"opacity": {
"win7": 0.3,
"win10": 0.8,
"macos": 0.3
},

View File

@ -85,19 +85,22 @@ body {
background: transparent !important;
}
.monaco-workbench .activitybar>.content :not(.monaco-menu)>.monaco-action-bar .action-label.codicon {
color: #616161 !important;
}
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:hover .action-label.codicon {
color: #000 !important;
}
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator:before {
border-left-color: #616161 !important;
}
.monaco-workbench .part.sidebar {
background-color: rgba(228, 230, 241, 0.3) !important;
}
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item .action-label {
background-color: #616161 !important;
}
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:hover .action-label {
background-color:#000 !important;
}
.monaco-workbench .part.statusbar {
color: #616161 !important;
}

View File

@ -1,12 +1,10 @@
{
"type": {
"win7": "dwm",
"win10": "acrylic",
"macos": "medium-light"
},
"background": "ffffff",
"opacity": {
"win7": 0.3,
"win10": 0.8,
"macos": 0.3
},