diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..2daf17078 --- /dev/null +++ b/.gitignore @@ -0,0 +1,196 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studo 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# 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 addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# 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 +# TODO: 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 + +# NuGet Packages +#*.nupkg +# The packages folder can be ignored because of Package Restore +#**/packages/* +# except build/, which is used as an MSBuild target. +#!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.[Cc]ache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +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 + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt diff --git a/Build/Redists/vcredist_x86.exe b/Build/Redists/vcredist_x86.exe new file mode 100644 index 000000000..b79557817 Binary files /dev/null and b/Build/Redists/vcredist_x86.exe differ diff --git a/EarTrumpet.Interop/AudioSessionService.cpp b/EarTrumpet.Interop/AudioSessionService.cpp new file mode 100644 index 000000000..8f638387e --- /dev/null +++ b/EarTrumpet.Interop/AudioSessionService.cpp @@ -0,0 +1,245 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include "AudioSessionService.h" +#include "ShellProperties.h" + +using namespace std; +using namespace std::tr1; +using namespace EarTrumpet::Interop; + +AudioSessionService* AudioSessionService::__instance = nullptr; + +void AudioSessionService::CleanUpAudioSessions() +{ + for (auto session = _sessions.begin(); session != _sessions.end(); session++) + { + CoTaskMemFree(session->DisplayName); + CoTaskMemFree(session->IconPath); + } + + _sessions.clear(); + _sessionMap.clear(); +} + +int AudioSessionService::GetAudioSessionCount() +{ + return _sessions.size(); +} + +HRESULT AudioSessionService::RefreshAudioSessions() +{ + CleanUpAudioSessions(); + + CComPtr deviceEnumerator; + FAST_FAIL(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&deviceEnumerator))); + + // TIP: Role parameter is not actually used https://msdn.microsoft.com/en-us/library/windows/desktop/dd371401.aspx + CComPtr device; + FAST_FAIL(deviceEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eMultimedia, &device)); + + CComPtr audioSessionManager; + FAST_FAIL(device->Activate(__uuidof(IAudioSessionManager2), CLSCTX_INPROC, nullptr, (void**)&audioSessionManager)); + + CComPtr audioSessionEnumerator; + FAST_FAIL(audioSessionManager->GetSessionEnumerator(&audioSessionEnumerator)); + + int sessionCount; + FAST_FAIL(audioSessionEnumerator->GetCount(&sessionCount)); + + for (int i = 0; i < sessionCount; i++) + { + EarTrumpetAudioSession audioSession; + if (SUCCEEDED(CreateEtAudioSessionFromAudioSession(audioSessionEnumerator, i, &audioSession))) + { + _sessions.push_back(audioSession); + } + } + + return S_OK; +} + +HRESULT AudioSessionService::CreateEtAudioSessionFromAudioSession(CComPtr audioSessionEnumerator, int sessionCount, EarTrumpetAudioSession* etAudioSession) +{ + CComPtr audioSessionControl; + FAST_FAIL(audioSessionEnumerator->GetSession(sessionCount, &audioSessionControl)); + + CComPtr audioSessionControl2; + FAST_FAIL(audioSessionControl->QueryInterface(IID_PPV_ARGS(&audioSessionControl2))); + + DWORD pid; + FAST_FAIL(audioSessionControl2->GetProcessId(&pid)); + + etAudioSession->ProcessId = pid; + + FAST_FAIL(audioSessionControl2->GetGroupingParam(&etAudioSession->GroupingId)); + + CComHeapPtr sessionIdString; + FAST_FAIL(audioSessionControl2->GetSessionIdentifier(&sessionIdString)); + + hash stringHash; + etAudioSession->SessionId = stringHash(static_cast(sessionIdString)); + + _sessionMap[etAudioSession->SessionId] = audioSessionControl2; + + CComPtr simpleAudioVolume; + FAST_FAIL(audioSessionControl->QueryInterface(IID_PPV_ARGS(&simpleAudioVolume))); + FAST_FAIL(simpleAudioVolume->GetMasterVolume(&etAudioSession->Volume)); + + if (IsImmersiveProcess(pid)) + { + PWSTR appUserModelId; + FAST_FAIL(GetAppUserModelIdFromPid(pid, &appUserModelId)); + + FAST_FAIL(GetAppProperties(appUserModelId, &etAudioSession->DisplayName, &etAudioSession->IconPath, &etAudioSession->BackgroundColor)); + + etAudioSession->IsDesktopApp = false; + } + else + { + bool isSystemSoundsSession = (S_OK == audioSessionControl2->IsSystemSoundsSession()); + + AudioSessionState state; + FAST_FAIL(audioSessionControl2->GetState(&state)); + if (!isSystemSoundsSession && (state == AudioSessionState::AudioSessionStateExpired)) + { + return E_NOT_VALID_STATE; + } + + if (isSystemSoundsSession) + { + PCWSTR pszDllPath; + BOOL isWow64Process; + if (!IsWow64Process(GetCurrentProcess(), &isWow64Process) || isWow64Process) + { + pszDllPath = L"%windir%\\sysnative\\audiosrv.dll"; + } + else + { + pszDllPath = L"%windir%\\system32\\audiosrv.dll"; + } + + wchar_t szPath[MAX_PATH] = {}; + if (0 == ExpandEnvironmentStrings(pszDllPath, szPath, ARRAYSIZE(szPath))) + { + return E_FAIL; + } + + FAST_FAIL(SHStrDup(pszDllPath, &etAudioSession->IconPath)); + FAST_FAIL(SHStrDup(L"System Sounds", &etAudioSession->DisplayName)); + } + else + { + shared_ptr processHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid), CloseHandle); + FAST_FAIL_HANDLE(processHandle.get()); + + wchar_t imagePath[MAX_PATH] = {}; + DWORD dwCch = ARRAYSIZE(imagePath); + FAST_FAIL(QueryFullProcessImageName(processHandle.get(), 0, imagePath, &dwCch) == 0 ? E_FAIL : S_OK); + + FAST_FAIL(SHStrDup(imagePath, &etAudioSession->IconPath)); + FAST_FAIL(SHStrDup(PathFindFileName(imagePath), &etAudioSession->DisplayName)); + } + + etAudioSession->IsDesktopApp = true; + etAudioSession->BackgroundColor = 0x00000000; + } + + return S_OK; +} + +HRESULT AudioSessionService::GetAudioSessions(void** audioSessions) +{ + if (_sessions.size() == 0) + { + return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); + } + + *audioSessions = &_sessions[0]; + return S_OK; +} + +BOOL AudioSessionService::IsImmersiveProcess(DWORD pid) +{ + shared_ptr processHandle(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid), CloseHandle); + FAST_FAIL_HANDLE(processHandle.get()); + + return ::IsImmersiveProcess(processHandle.get()); +} + +HRESULT AudioSessionService::GetAppUserModelIdFromPid(DWORD pid, LPWSTR* applicationUserModelIdPtr) +{ + shared_ptr processHandle(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid), CloseHandle); + FAST_FAIL_HANDLE(processHandle.get()); + + unsigned int appUserModelIdLength = 0; + long returnCode = GetApplicationUserModelId(processHandle.get(), &appUserModelIdLength, NULL); + if (returnCode != ERROR_INSUFFICIENT_BUFFER) + { + return HRESULT_FROM_WIN32(returnCode); + } + + unique_ptr appUserModelId(new wchar_t[appUserModelIdLength]); + returnCode = GetApplicationUserModelId(processHandle.get(), &appUserModelIdLength, appUserModelId.get()); + if (returnCode != ERROR_SUCCESS) + { + return HRESULT_FROM_WIN32(returnCode); + } + + FAST_FAIL(SHStrDup(appUserModelId.get(), applicationUserModelIdPtr)); + + return S_OK; +} + +HRESULT AudioSessionService::SetAudioSessionVolume(unsigned long sessionId, float volume) +{ + if (!_sessionMap[sessionId]) + { + return E_INVALIDARG; + } + + CComPtr simpleAudioVolume; + FAST_FAIL(_sessionMap[sessionId]->QueryInterface(IID_PPV_ARGS(&simpleAudioVolume))); + + FAST_FAIL(simpleAudioVolume->SetMasterVolume(volume, nullptr)); + + return S_OK; +} + +HRESULT AudioSessionService::GetAppProperties(PCWSTR pszAppId, PWSTR* ppszName, PWSTR* ppszIcon, ULONG *background) +{ + *ppszIcon = nullptr; + *ppszName = nullptr; + *background = 0; + + CComPtr item; + FAST_FAIL(SHCreateItemInKnownFolder(FOLDERID_AppsFolder, KF_FLAG_DONT_VERIFY, pszAppId, IID_PPV_ARGS(&item))); + + CComHeapPtr itemName; + FAST_FAIL(item->GetString(PKEY_ItemNameDisplay, &itemName)); + FAST_FAIL(item->GetUInt32(PKEY_AppUserModel_Background, background)); + + CComHeapPtr installPath; + FAST_FAIL(item->GetString(PKEY_AppUserModel_PackageInstallPath, &installPath)); + + CComHeapPtr iconPath; + FAST_FAIL(item->GetString(PKEY_AppUserModel_Icon, &iconPath)); + + wchar_t fullPath[MAX_PATH] = {}; + FAST_FAIL(PathCchCombine(fullPath, ARRAYSIZE(fullPath), installPath, iconPath)); + + CStringW path(fullPath); + + if (!PathFileExists(path)) + { + path.Replace(L".png", L".scale-100.png"); + } + + FAST_FAIL(SHStrDup(path, ppszIcon)); + *ppszName = itemName.Detach(); + return S_OK; +} \ No newline at end of file diff --git a/EarTrumpet.Interop/AudioSessionService.h b/EarTrumpet.Interop/AudioSessionService.h new file mode 100644 index 000000000..94ca549c9 --- /dev/null +++ b/EarTrumpet.Interop/AudioSessionService.h @@ -0,0 +1,49 @@ +#pragma once + +namespace EarTrumpet +{ + namespace Interop + { + struct EarTrumpetAudioSession + { + wchar_t* DisplayName; + wchar_t* IconPath; + GUID GroupingId; + unsigned long SessionId; + unsigned long ProcessId; + unsigned long BackgroundColor; + float Volume; + bool IsDesktopApp; + }; + + class AudioSessionService + { + private: + static AudioSessionService* __instance; + + void CleanUpAudioSessions(); + HRESULT CreateEtAudioSessionFromAudioSession(CComPtr sessionEnumerator, int sessionCount, EarTrumpetAudioSession* etAudioSession); + HRESULT GetAppProperties(PCWSTR pszAppId, PWSTR* ppszName, PWSTR* ppszIcon, ULONG *background); + HRESULT GetAppUserModelIdFromPid(DWORD pid, LPWSTR* applicationUserModelIdPtr); + BOOL IsImmersiveProcess(DWORD pid); + + std::vector _sessions; + std::map> _sessionMap; + + public: + static AudioSessionService* instance() + { + if (!__instance) + { + __instance = new AudioSessionService; + } + return __instance; + } + + int GetAudioSessionCount(); + HRESULT GetAudioSessions(void** audioSessions); + HRESULT RefreshAudioSessions(); + HRESULT SetAudioSessionVolume(unsigned long sessionId, float volume); + }; + } +} \ No newline at end of file diff --git a/EarTrumpet.Interop/EarTrumpet.Interop.vcxproj b/EarTrumpet.Interop/EarTrumpet.Interop.vcxproj new file mode 100644 index 000000000..5f3d2044b --- /dev/null +++ b/EarTrumpet.Interop/EarTrumpet.Interop.vcxproj @@ -0,0 +1,115 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {73FA0BF9-96FE-4C5B-89B2-00B861F3F778} + Win32Proj + EarTrumpetInterop + EarTrumpet.Interop + + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + true + $(SolutionDir)Build\$(Configuration)\ + $(ProjectDir)int\$(Configuration)\ + + + false + $(SolutionDir)Build\$(Configuration)\ + $(ProjectDir)int\$(Configuration)\ + false + + + + Level4 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + true + ProgramDatabase + StdCall + + + Windows + true + + + pathcch.lib;kernel32.lib;ntdll.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + + Level4 + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + false + true + StdCall + + + Windows + true + true + true + + + pathcch.lib;kernel32.lib;ntdll.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EarTrumpet.Interop/ShellProperties.h b/EarTrumpet.Interop/ShellProperties.h new file mode 100644 index 000000000..39db0f5a3 --- /dev/null +++ b/EarTrumpet.Interop/ShellProperties.h @@ -0,0 +1,10 @@ +#pragma once + +// {9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3} - PID 15 +const PROPERTYKEY PKEY_AppUserModel_PackageInstallPath = { { 0x9F4C2855, 0x9F79, 0x4B39, { 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 } }, 15 }; + +// {86D40B4D-9069-443C-819A-2A54090DCCEC} - PID 2 +const PROPERTYKEY PKEY_AppUserModel_Icon = { { 0x86D40B4D, 0x9069, 0x443C, { 0x81, 0x9A, 0x2A, 0x54, 0x09, 0x0D, 0xCC, 0xEC } }, 2 }; + +// {86D40B4D-9069-443C-819A-2A54090DCCEC} - PID 4 +const PROPERTYKEY PKEY_AppUserModel_Background = { { 0x86D40B4D, 0x9069, 0x443C, { 0x81, 0x9A, 0x2A, 0x54, 0x09, 0x0D, 0xCC, 0xEC } }, 4 }; \ No newline at end of file diff --git a/EarTrumpet.Interop/common.h b/EarTrumpet.Interop/common.h new file mode 100644 index 000000000..13f4f4515 --- /dev/null +++ b/EarTrumpet.Interop/common.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#define FAST_FAIL(x) { HRESULT __hr = x; if (FAILED(__hr)) { return __hr; } } +#define FAST_FAIL_HANDLE(x) { if(x == INVALID_HANDLE_VALUE) { return HRESULT_FROM_WIN32(GetLastError()); }} \ No newline at end of file diff --git a/EarTrumpet.Interop/exports.cpp b/EarTrumpet.Interop/exports.cpp new file mode 100644 index 000000000..fb4c42a98 --- /dev/null +++ b/EarTrumpet.Interop/exports.cpp @@ -0,0 +1,25 @@ +#include "common.h" +#include +#include "AudioSessionService.h" + +using namespace EarTrumpet::Interop; + +extern "C" __declspec(dllexport) HRESULT RefreshAudioSessions() +{ + return AudioSessionService::instance()->RefreshAudioSessions(); +} + +extern "C" __declspec(dllexport) int GetAudioSessionCount() +{ + return AudioSessionService::instance()->GetAudioSessionCount(); +} + +extern "C" __declspec(dllexport) HRESULT GetAudioSessions(void** audioSessions) +{ + return AudioSessionService::instance()->GetAudioSessions(audioSessions); +} + +extern "C" __declspec(dllexport) HRESULT SetAudioSessionVolume(unsigned long sessionId, float volume) +{ + return AudioSessionService::instance()->SetAudioSessionVolume(sessionId, volume); +} \ No newline at end of file diff --git a/EarTrumpet.sln b/EarTrumpet.sln new file mode 100644 index 000000000..0cb072013 --- /dev/null +++ b/EarTrumpet.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EarTrumpet", "EarTrumpet\EarTrumpet.csproj", "{BA3C7B42-84B0-468C-8640-217E2A24CF81}" + ProjectSection(ProjectDependencies) = postProject + {73FA0BF9-96FE-4C5B-89B2-00B861F3F778} = {73FA0BF9-96FE-4C5B-89B2-00B861F3F778} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EarTrumpet.Interop", "EarTrumpet.Interop\EarTrumpet.Interop.vcxproj", "{73FA0BF9-96FE-4C5B-89B2-00B861F3F778}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BA3C7B42-84B0-468C-8640-217E2A24CF81}.Debug|x86.ActiveCfg = Debug|x86 + {BA3C7B42-84B0-468C-8640-217E2A24CF81}.Debug|x86.Build.0 = Debug|x86 + {BA3C7B42-84B0-468C-8640-217E2A24CF81}.Release|x86.ActiveCfg = Release|x86 + {BA3C7B42-84B0-468C-8640-217E2A24CF81}.Release|x86.Build.0 = Release|x86 + {73FA0BF9-96FE-4C5B-89B2-00B861F3F778}.Debug|x86.ActiveCfg = Debug|Win32 + {73FA0BF9-96FE-4C5B-89B2-00B861F3F778}.Debug|x86.Build.0 = Debug|Win32 + {73FA0BF9-96FE-4C5B-89B2-00B861F3F778}.Release|x86.ActiveCfg = Release|Win32 + {73FA0BF9-96FE-4C5B-89B2-00B861F3F778}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/EarTrumpet/App.config b/EarTrumpet/App.config new file mode 100644 index 000000000..8e1564635 --- /dev/null +++ b/EarTrumpet/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/EarTrumpet/App.xaml b/EarTrumpet/App.xaml new file mode 100644 index 000000000..176b2f05b --- /dev/null +++ b/EarTrumpet/App.xaml @@ -0,0 +1,5 @@ + + diff --git a/EarTrumpet/App.xaml.cs b/EarTrumpet/App.xaml.cs new file mode 100644 index 000000000..87b96246f --- /dev/null +++ b/EarTrumpet/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows; + +namespace EarTrumpet +{ + public partial class App : Application + { + private void Application_Startup(object sender, StartupEventArgs e) + { + new MainWindow(); + } + } +} diff --git a/EarTrumpet/Application.ico b/EarTrumpet/Application.ico new file mode 100644 index 000000000..7a4320b8f Binary files /dev/null and b/EarTrumpet/Application.ico differ diff --git a/EarTrumpet/Color Types.txt b/EarTrumpet/Color Types.txt new file mode 100644 index 000000000..56e70342e --- /dev/null +++ b/EarTrumpet/Color Types.txt @@ -0,0 +1,1225 @@ +// +// +// This code was generated by a tool. +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +// + +FFFFFFFF ImmersiveApplicationBackground +FF000000 ImmersiveApplicationBackgroundDarkTheme +FFFFFFFF ImmersiveApplicationBackgroundLightTheme +FF000000 ImmersiveApplicationText +FFFFFFFF ImmersiveApplicationTextDarkTheme +FF000000 ImmersiveApplicationTextLightTheme +FFB26720 ImmersiveBootBackground +DED6B147 ImmersiveBootConfirmationButton +00000000 ImmersiveBootConfirmationButtonBackgroundDisabled +FFCF9454 ImmersiveBootConfirmationButtonBackgroundHover +FFFFFFFF ImmersiveBootConfirmationButtonBackgroundPressed +FFB26720 ImmersiveBootConfirmationButtonBackgroundRest +FFE0C2A6 ImmersiveBootConfirmationButtonBorderDisabled +FFFFFFFF ImmersiveBootConfirmationButtonBorderHover +FFFFFFFF ImmersiveBootConfirmationButtonBorderPressed +FFFFFFFF ImmersiveBootConfirmationButtonBorderRest +FFE0C2A6 ImmersiveBootConfirmationButtonTextDisabled +FFFFFFFF ImmersiveBootConfirmationButtonTextHover +FFB26720 ImmersiveBootConfirmationButtonTextPressed +FFFFFFFF ImmersiveBootConfirmationButtonTextRest +00000000 ImmersiveBootDefaultConfirmationButtonBackgroundDisabled +FFF3D190 ImmersiveBootDefaultConfirmationButtonBackgroundHover +FFFFFFFF ImmersiveBootDefaultConfirmationButtonBackgroundPressed +FFDDA74D ImmersiveBootDefaultConfirmationButtonBackgroundRest +FFE0C2A6 ImmersiveBootDefaultConfirmationButtonBorderDisabled +FFFFFFFF ImmersiveBootDefaultConfirmationButtonBorderHover +FFFFFFFF ImmersiveBootDefaultConfirmationButtonBorderPressed +FFFFFFFF ImmersiveBootDefaultConfirmationButtonBorderRest +FFE0C2A6 ImmersiveBootDefaultConfirmationButtonTextDisabled +FFFFFFFF ImmersiveBootDefaultConfirmationButtonTextHover +FFB26720 ImmersiveBootDefaultConfirmationButtonTextPressed +FFFFFFFF ImmersiveBootDefaultConfirmationButtonTextRest +FFF0E1D2 ImmersiveBootEditBackground +FFFFFFFF ImmersiveBootEditBackgroundActive +FFB26720 ImmersiveBootEditBackgroundDisabled +FFF5EBE2 ImmersiveBootEditBackgroundHover +FFF0E1D2 ImmersiveBootEditBackgroundRest +FFD1A479 ImmersiveBootEditBorderDisabled +FF00FFFF ImmersiveBootErrorText +FFFFFFFF ImmersiveBootMenuButtonFocusRect +FFDDA74D ImmersiveBootMenuButtonGlyphBackground +FFBC7B3D ImmersiveBootMenuButtonMouseHover +FFFFFFFF ImmersiveBootMenuButtonPressedHighlight +FFB26720 ImmersiveBootMenuButtonPressedText +FFFFFFFF ImmersiveBootPrimaryText +FFFFFFFF ImmersiveBootProgressText +FFFFFFFF ImmersiveBootSecondaryText +FFDDA74D ImmersiveBootTextLinkHover +FFF2C864 ImmersiveBootTextLinkPressed +FFFFFFFF ImmersiveBootTextLinkRest +FFFFFFFF ImmersiveBootTitleText +FFF1945A ImmersiveControlAppDefaultDarkButtonBackgroundHover +FFEC7226 ImmersiveControlAppDefaultDarkButtonBackgroundRest +FFF1945A ImmersiveControlAppDefaultDarkButtonBorderHover +FFEC7226 ImmersiveControlAppDefaultDarkButtonBorderRest +FFDAA026 ImmersiveControlAppLightToggleTrackFillEnabled +FF666666 ImmersiveControlBlackButtonDisabled +FFDEDEDE ImmersiveControlContextMenuBackgroundHover +FF000000 ImmersiveControlContextMenuBackgroundPressed +FFFFFFFF ImmersiveControlContextMenuBackgroundRest +FF7A7A7A ImmersiveControlContextMenuSeparator +FF000000 ImmersiveControlContextMenuTextHover +FFFFFFFF ImmersiveControlContextMenuTextPressed +FF000000 ImmersiveControlContextMenuTextRest +FFE5E5E5 ImmersiveControlDarkAppButtonBackgroundDisabled +3DFFFFFF ImmersiveControlDarkAppButtonBackgroundHover +FF000000 ImmersiveControlDarkAppButtonBackgroundPressed +00000000 ImmersiveControlDarkAppButtonBackgroundRest +FFE5E5E5 ImmersiveControlDarkAppButtonBorderDisabled +3D000000 ImmersiveControlDarkAppButtonBorderHover +FF000000 ImmersiveControlDarkAppButtonBorderPressed +00000000 ImmersiveControlDarkAppButtonBorderRest +FFAFAFAF ImmersiveControlDarkAppButtonTextDisabled +FFFFFFFF ImmersiveControlDarkAppButtonTextHover +FFFFFFFF ImmersiveControlDarkAppButtonTextPressed +FFFFFFFF ImmersiveControlDarkAppButtonTextRest +00000000 ImmersiveControlDarkButtonBackgroundDisabled +21FFFFFF ImmersiveControlDarkButtonBackgroundHover +FFFFFFFF ImmersiveControlDarkButtonBackgroundPressed +00000000 ImmersiveControlDarkButtonBackgroundRest +66FFFFFF ImmersiveControlDarkButtonBorderDisabled +FFFFFFFF ImmersiveControlDarkButtonBorderHover +FFFFFFFF ImmersiveControlDarkButtonBorderPressed +FFFFFFFF ImmersiveControlDarkButtonBorderRest +66FFFFFF ImmersiveControlDarkButtonTextDisabled +FFFFFFFF ImmersiveControlDarkButtonTextHover +FF000000 ImmersiveControlDarkButtonTextPressed +FFFFFFFF ImmersiveControlDarkButtonTextRest +66FFFFFF ImmersiveControlDarkCheckboxBackgroundDisabled +DEFFFFFF ImmersiveControlDarkCheckboxBackgroundHover +FFFFFFFF ImmersiveControlDarkCheckboxBackgroundPressed +CCFFFFFF ImmersiveControlDarkCheckboxBackgroundRest +66FFFFFF ImmersiveControlDarkCheckboxBorderDisabled +DEFFFFFF ImmersiveControlDarkCheckboxBorderHover +FFFFFFFF ImmersiveControlDarkCheckboxBorderPressed +CCFFFFFF ImmersiveControlDarkCheckboxBorderRest +66000000 ImmersiveControlDarkCheckboxGlyphDisabled +FF000000 ImmersiveControlDarkCheckboxGlyphHover +FF000000 ImmersiveControlDarkCheckboxGlyphPressed +FF000000 ImmersiveControlDarkCheckboxGlyphRest +66FFFFFF ImmersiveControlDarkCheckboxLabelDisabled +FFFFFFFF ImmersiveControlDarkCheckboxLabelHover +FFFFFFFF ImmersiveControlDarkCheckboxLabelPressed +FFFFFFFF ImmersiveControlDarkCheckboxLabelRest +FFFFFFFF ImmersiveControlDarkFocusRect +66FFFFFF ImmersiveControlDarkLinkDisabled +FF91E0FF ImmersiveControlDarkLinkHover +FF66D5FF ImmersiveControlDarkLinkPressed +FFD0F2FF ImmersiveControlDarkLinkRest +FF66D5FF ImmersiveControlDarkLinkVisited +BFEDEDED ImmersiveControlDarkPanningIndicator +59FFFFFF ImmersiveControlDarkProgressBackground +FF64CDF4 ImmersiveControlDarkProgressForeground +00FFFFFF ImmersiveControlDarkRichEditBackgroundDisabled +FFFFFFFF ImmersiveControlDarkRichEditBackgroundFocus +DEFFFFFF ImmersiveControlDarkRichEditBackgroundHover +FFFFFFFF ImmersiveControlDarkRichEditBackgroundPressed +CCFFFFFF ImmersiveControlDarkRichEditBackgroundRest +66FFFFFF ImmersiveControlDarkRichEditBorderDisabled +FFFFFFFF ImmersiveControlDarkRichEditBorderFocus +DEFFFFFF ImmersiveControlDarkRichEditBorderHover +FFFFFFFF ImmersiveControlDarkRichEditBorderPressed +CCFFFFFF ImmersiveControlDarkRichEditBorderRest +FFDEDEDE ImmersiveControlDarkRichEditButtonBackgroundHover +FF000000 ImmersiveControlDarkRichEditButtonBackgroundPressed +00FFFFFF ImmersiveControlDarkRichEditButtonBackgroundRest +FF000000 ImmersiveControlDarkRichEditButtonGlyphHover +FFFFFFFF ImmersiveControlDarkRichEditButtonGlyphPressed +FF000000 ImmersiveControlDarkRichEditButtonGlyphRest +FF00B9FF ImmersiveControlDarkRichEditHighlight +38FFFFFF ImmersiveControlDarkRichEditPromptTextDisabled +AB000000 ImmersiveControlDarkRichEditPromptTextFocus +AB000000 ImmersiveControlDarkRichEditPromptTextRest +2BFFFFFF ImmersiveControlDarkRichEditStartPromptBackgroundHover +1CFFFFFF ImmersiveControlDarkRichEditStartPromptBackgroundRest +55000000 ImmersiveControlDarkRichEditStartPromptButtonGlyphHover +7FFFFFFF ImmersiveControlDarkRichEditStartPromptTextRest +66FFFFFF ImmersiveControlDarkRichEditTextDisabled +FF000000 ImmersiveControlDarkRichEditTextFocus +AB000000 ImmersiveControlDarkRichEditTextHelper +FFFFFFFF ImmersiveControlDarkRichEditTextHighlighted +FF000000 ImmersiveControlDarkRichEditTextHover +FF000000 ImmersiveControlDarkRichEditTextRest +FF0097D0 ImmersiveControlDarkRoundButtonFillLayerDisabled +FF00ACEE ImmersiveControlDarkRoundButtonFillLayerHover +FFFFFFFF ImmersiveControlDarkRoundButtonFillLayerPressed +FF0097D0 ImmersiveControlDarkRoundButtonFillLayerRest +FF71A0B3 ImmersiveControlDarkRoundButtonGlyphDisabled +FFFFFFFF ImmersiveControlDarkRoundButtonGlyphLayerHover +FF0088BB ImmersiveControlDarkRoundButtonGlyphLayerPressed +FFFFFFFF ImmersiveControlDarkRoundButtonGlyphLayerRest +FF71A0B3 ImmersiveControlDarkRoundButtonOutlineDisabled +FFFFFFFF ImmersiveControlDarkRoundButtonOutlineLayerHover +FFFFFFFF ImmersiveControlDarkRoundButtonOutlineLayerPressed +FFFFFFFF ImmersiveControlDarkRoundButtonOutlineLayerRest +FFFFFFFF ImmersiveControlDarkScrollbarButtonGlyphHover +FF212121 ImmersiveControlDarkScrollbarButtonGlyphPressed +FFFFFFFF ImmersiveControlDarkScrollbarButtonGlyphRest +99FFFFFF ImmersiveControlDarkScrollbarButtonHover +FFFFFFFF ImmersiveControlDarkScrollbarButtonPressed +5EA5A5A5 ImmersiveControlDarkScrollbarButtonRest +B0FFFFFF ImmersiveControlDarkScrollbarThumbHover +FFFFFFFF ImmersiveControlDarkScrollbarThumbPressed +BFEDEDED ImmersiveControlDarkScrollbarThumbRest +5EA5A5A5 ImmersiveControlDarkScrollbarTrack +00000000 ImmersiveControlDarkSelectBackgroundDisabled +DEFFFFFF ImmersiveControlDarkSelectBackgroundHover +FFD3D3D3 ImmersiveControlDarkSelectBackgroundPressed +CCFFFFFF ImmersiveControlDarkSelectBackgroundRest +66FFFFFF ImmersiveControlDarkSelectBorderDisabled +DEFFFFFF ImmersiveControlDarkSelectBorderHover +FFFFFFFF ImmersiveControlDarkSelectBorderPressed +CCFFFFFF ImmersiveControlDarkSelectBorderRest +66FFFFFF ImmersiveControlDarkSelectGlyphDisabled +FF000000 ImmersiveControlDarkSelectGlyphRest +FF707070 ImmersiveControlDarkSelectHighlightedSecondaryTextPressed +FFFFFFFF ImmersiveControlDarkSelectHighlightedTextPressed +21000000 ImmersiveControlDarkSelectHighlightHover +FF000000 ImmersiveControlDarkSelectHighlightPressed +FF00B9FF ImmersiveControlDarkSelectHighlightSelected +FF35BEF2 ImmersiveControlDarkSelectHighlightSelectedHover +FFFFFFFF ImmersiveControlDarkSelectPopupBackgroundDisabled +21000000 ImmersiveControlDarkSelectPopupBackgroundHover +FFD3D3D3 ImmersiveControlDarkSelectPopupBackgroundPressed +FFFFFFFF ImmersiveControlDarkSelectPopupBackgroundRest +FF00B9FF ImmersiveControlDarkSelectPopupBackgroundSelected +FF000000 ImmersiveControlDarkSelectPopupBorder +66000000 ImmersiveControlDarkSelectPopupTextDisabled +FF000000 ImmersiveControlDarkSelectPopupTextHover +FF000000 ImmersiveControlDarkSelectPopupTextPressed +FF000000 ImmersiveControlDarkSelectPopupTextRest +FFFFFFFF ImmersiveControlDarkSelectPopupTextSelected +FFFFFFFF ImmersiveControlDarkSelectSecondaryTextHighlighted +FF707070 ImmersiveControlDarkSelectSecondaryTextHover +FF707070 ImmersiveControlDarkSelectSecondaryTextPressed +66FFFFFF ImmersiveControlDarkSelectTextDisabled +FFFFFFFF ImmersiveControlDarkSelectTextHighlighted +FF000000 ImmersiveControlDarkSelectTextHover +FF000000 ImmersiveControlDarkSelectTextPressed +FF000000 ImmersiveControlDarkSelectTextRest +FF0097D0 ImmersiveControlDarkSliderBorder +FFFFFFFF ImmersiveControlDarkSliderThumbBorder +FF6A6A6A ImmersiveControlDarkSliderThumbBorderDisabled +FFFFFFFF ImmersiveControlDarkSliderThumbBorderHover +FFFFFFFF ImmersiveControlDarkSliderThumbBorderPressed +FFFFFFFF ImmersiveControlDarkSliderThumbBorderRest +FF6A6A6A ImmersiveControlDarkSliderThumbDisabled +FFFFFFFF ImmersiveControlDarkSliderThumbHover +FFFFFFFF ImmersiveControlDarkSliderThumbPressed +FFFFFFFF ImmersiveControlDarkSliderThumbRest +FF000000 ImmersiveControlDarkSliderTickMark +FF363636 ImmersiveControlDarkSliderTrackBackgroundDisabled +FF717171 ImmersiveControlDarkSliderTrackBackgroundHover +FF7D7D7D ImmersiveControlDarkSliderTrackBackgroundPressed +FF6A6A6A ImmersiveControlDarkSliderTrackBackgroundRest +FF434343 ImmersiveControlDarkSliderTrackBufferingDisabled +FF8B6921 ImmersiveControlDarkSliderTrackBufferingHover +FF9C7522 ImmersiveControlDarkSliderTrackBufferingPressed +FF806120 ImmersiveControlDarkSliderTrackBufferingRest +FF515151 ImmersiveControlDarkSliderTrackFillDisabled +FF35BEF2 ImmersiveControlDarkSliderTrackFillHover +FF64CDF4 ImmersiveControlDarkSliderTrackFillPressed +FF00B9FF ImmersiveControlDarkSliderTrackFillRest +FF71A0B3 ImmersiveControlDarkToggleLabelDisabled +FFFFFFFF ImmersiveControlDarkToggleLabelEnabled +FF71A0B3 ImmersiveControlDarkToggleOnOffTextDisabled +FFFFFFFF ImmersiveControlDarkToggleOnOffTextEnabled +FF04BAFF ImmersiveControlDarkToggleThumbDisabled +FFFFFFFF ImmersiveControlDarkToggleThumbEnabled +FF478CA7 ImmersiveControlDarkToggleTrackBackgroundDisabled +FF16B5F1 ImmersiveControlDarkToggleTrackBackgroundEnabled +4AFFFFFF ImmersiveControlDarkToggleTrackBackgroundHover +59FFFFFF ImmersiveControlDarkToggleTrackBackgroundPressed +42FFFFFF ImmersiveControlDarkToggleTrackBackgroundRest +FF00ACEE ImmersiveControlDarkToggleTrackBorderDisabled +FF04BAFF ImmersiveControlDarkToggleTrackBorderEnabled +FF478CA7 ImmersiveControlDarkToggleTrackFillDisabled +FF00B9FF ImmersiveControlDarkToggleTrackFillEnabled +FF35BEF2 ImmersiveControlDarkToggleTrackFillHover +FF64CDF4 ImmersiveControlDarkToggleTrackFillPressed +FF00B9FF ImmersiveControlDarkToggleTrackFillRest +00000000 ImmersiveControlDarkToggleTrackGutterDisabled +00000000 ImmersiveControlDarkToggleTrackGutterEnabled +00000000 ImmersiveControlDefaultDarkButtonBackgroundDisabled +FF35BEF2 ImmersiveControlDefaultDarkButtonBackgroundHover +FFFFFFFF ImmersiveControlDefaultDarkButtonBackgroundPressed +FF00B9FF ImmersiveControlDefaultDarkButtonBackgroundRest +66FFFFFF ImmersiveControlDefaultDarkButtonBorderDisabled +FFFFFFFF ImmersiveControlDefaultDarkButtonBorderHover +FFFFFFFF ImmersiveControlDefaultDarkButtonBorderPressed +FFFFFFFF ImmersiveControlDefaultDarkButtonBorderRest +66FFFFFF ImmersiveControlDefaultDarkButtonTextDisabled +FFFFFFFF ImmersiveControlDefaultDarkButtonTextHover +FF000000 ImmersiveControlDefaultDarkButtonTextPressed +FFFFFFFF ImmersiveControlDefaultDarkButtonTextRest +FF000000 ImmersiveControlDefaultFocusRectDark +FFFFFFFF ImmersiveControlDefaultFocusRectLight +66CACACA ImmersiveControlDefaultLightButtonBackgroundDisabled +FF35BEF2 ImmersiveControlDefaultLightButtonBackgroundHover +FF000000 ImmersiveControlDefaultLightButtonBackgroundPressed +FF00B9FF ImmersiveControlDefaultLightButtonBackgroundRest +66CACACA ImmersiveControlDefaultLightButtonBorderDisabled +FF35BEF2 ImmersiveControlDefaultLightButtonBorderHover +FF000000 ImmersiveControlDefaultLightButtonBorderPressed +FF00B9FF ImmersiveControlDefaultLightButtonBorderRest +66000000 ImmersiveControlDefaultLightButtonTextDisabled +FFFFFFFF ImmersiveControlDefaultLightButtonTextHover +FFFFFFFF ImmersiveControlDefaultLightButtonTextPressed +FFFFFFFF ImmersiveControlDefaultLightButtonTextRest +0DFFFFFF ImmersiveControlFivePercentOpaqueWhite +00000000 ImmersiveControlHighContrastBTNFACE +00000000 ImmersiveControlHighContrastBTNTEXT +00000000 ImmersiveControlHighContrastGRAYTEXT +00000000 ImmersiveControlHighContrastHIGHLIGHT +00000000 ImmersiveControlHighContrastHIGHLIGHTTEXT +00000000 ImmersiveControlHighContrastHOTLIGHT +00000000 ImmersiveControlHighContrastWINDOW +00000000 ImmersiveControlHighContrastWINDOWTEXT +FFE5E5E5 ImmersiveControlLightAppButtonBackgroundDisabled +21000000 ImmersiveControlLightAppButtonBackgroundHover +FF000000 ImmersiveControlLightAppButtonBackgroundPressed +00000000 ImmersiveControlLightAppButtonBackgroundRest +FFE5E5E5 ImmersiveControlLightAppButtonBorderDisabled +FF000000 ImmersiveControlLightAppButtonBorderHover +FF000000 ImmersiveControlLightAppButtonBorderPressed +FF000000 ImmersiveControlLightAppButtonBorderRest +FFAFAFAF ImmersiveControlLightAppButtonTextDisabled +FF000000 ImmersiveControlLightAppButtonTextHover +FFFFFFFF ImmersiveControlLightAppButtonTextPressed +FF000000 ImmersiveControlLightAppButtonTextRest +66CACACA ImmersiveControlLightButtonBackgroundDisabled +FFD8D8D8 ImmersiveControlLightButtonBackgroundHover +FF000000 ImmersiveControlLightButtonBackgroundPressed +FFCCCCCC ImmersiveControlLightButtonBackgroundRest +66CACACA ImmersiveControlLightButtonBorderDisabled +FFD8D8D8 ImmersiveControlLightButtonBorderHover +FF000000 ImmersiveControlLightButtonBorderPressed +FFCCCCCC ImmersiveControlLightButtonBorderRest +66000000 ImmersiveControlLightButtonTextDisabled +FF000000 ImmersiveControlLightButtonTextHover +FFFFFFFF ImmersiveControlLightButtonTextPressed +FF000000 ImmersiveControlLightButtonTextRest +66CDCDCD ImmersiveControlLightCheckboxBackgroundDisabled +DFFFFFFF ImmersiveControlLightCheckboxBackgroundHover +FF000000 ImmersiveControlLightCheckboxBackgroundPressed +CCFFFFFF ImmersiveControlLightCheckboxBackgroundRest +66000000 ImmersiveControlLightCheckboxBorderDisabled +70000000 ImmersiveControlLightCheckboxBorderHover +FF000000 ImmersiveControlLightCheckboxBorderPressed +44000000 ImmersiveControlLightCheckboxBorderRest +66000000 ImmersiveControlLightCheckboxGlyphDisabled +FF000000 ImmersiveControlLightCheckboxGlyphHover +FFFFFFFF ImmersiveControlLightCheckboxGlyphPressed +FF000000 ImmersiveControlLightCheckboxGlyphRest +66000000 ImmersiveControlLightCheckboxLabelDisabled +FF000000 ImmersiveControlLightCheckboxLabelHover +FFFFFFFF ImmersiveControlLightCheckboxLabelPressed +FF000000 ImmersiveControlLightCheckboxLabelRest +FF000000 ImmersiveControlLightFocusRect +66000000 ImmersiveControlLightLinkDisabled +FF51CFFF ImmersiveControlLightLinkHover +FF8ADFFF ImmersiveControlLightLinkPressed +FF1AC0FF ImmersiveControlLightLinkRest +FF8ADFFF ImmersiveControlLightLinkVisited +EBC9C9C9 ImmersiveControlLightPanningIndicator +2B000000 ImmersiveControlLightProgressBackground +FF00B9FF ImmersiveControlLightProgressForeground +FF929292 ImmersiveControlLightRadioButtonLabelDisabled +FF212121 ImmersiveControlLightRadioButtonLabelRest +FFE6E6E6 ImmersiveControlLightRadioButtonSelectedBackgroundDisabled +FF212121 ImmersiveControlLightRadioButtonSelectedBackgroundDown +FFFFFFFF ImmersiveControlLightRadioButtonSelectedBackgroundHover +FFFFFFFF ImmersiveControlLightRadioButtonSelectedBackgroundRest +FFFFFFFF ImmersiveControlLightRadioButtonSelectedBackgroundUp +FFD9D9D9 ImmersiveControlLightRadioButtonSelectedBorderDisabled +FF212121 ImmersiveControlLightRadioButtonSelectedBorderDown +FF919191 ImmersiveControlLightRadioButtonSelectedBorderHover +FFBABABA ImmersiveControlLightRadioButtonSelectedBorderRest +FFBABABA ImmersiveControlLightRadioButtonSelectedBorderUp +FF8A8A8A ImmersiveControlLightRadioButtonSelectedGlyphDisabled +FFFFFFFF ImmersiveControlLightRadioButtonSelectedGlyphDown +FF212121 ImmersiveControlLightRadioButtonSelectedGlyphHover +FF212121 ImmersiveControlLightRadioButtonSelectedGlyphRest +FF212121 ImmersiveControlLightRadioButtonSelectedGlyphUp +FFE6E6E6 ImmersiveControlLightRadioButtonUnselectedBackgroundDisabled +FF212121 ImmersiveControlLightRadioButtonUnselectedBackgroundDown +FFFFFFFF ImmersiveControlLightRadioButtonUnselectedBackgroundHover +FFFFFFFF ImmersiveControlLightRadioButtonUnselectedBackgroundRest +FFFFFFFF ImmersiveControlLightRadioButtonUnselectedBackgroundUp +FFD9D9D9 ImmersiveControlLightRadioButtonUnselectedBorderDisabled +FF212121 ImmersiveControlLightRadioButtonUnselectedBorderDown +FF919191 ImmersiveControlLightRadioButtonUnselectedBorderHover +FFBABABA ImmersiveControlLightRadioButtonUnselectedBorderRest +FFBABABA ImmersiveControlLightRadioButtonUnselectedBorderUp +FFE6E6E6 ImmersiveControlLightRadioButtonUnselectedGlyphDisabled +FF212121 ImmersiveControlLightRadioButtonUnselectedGlyphDown +FFFFFFFF ImmersiveControlLightRadioButtonUnselectedGlyphHover +FFFFFFFF ImmersiveControlLightRadioButtonUnselectedGlyphRest +FF212121 ImmersiveControlLightRadioButtonUnselectedGlyphUp +66CACACA ImmersiveControlLightRichEditBackgroundDisabled +FFFFFFFF ImmersiveControlLightRichEditBackgroundFocus +DEFFFFFF ImmersiveControlLightRichEditBackgroundHover +FFFFFFFF ImmersiveControlLightRichEditBackgroundPressed +CCFFFFFF ImmersiveControlLightRichEditBackgroundRest +29000000 ImmersiveControlLightRichEditBorderDisabled +A3000000 ImmersiveControlLightRichEditBorderFocus +70000000 ImmersiveControlLightRichEditBorderHover +A3000000 ImmersiveControlLightRichEditBorderPressed +45000000 ImmersiveControlLightRichEditBorderRest +FFDEDEDE ImmersiveControlLightRichEditButtonBackgroundHover +FF000000 ImmersiveControlLightRichEditButtonBackgroundPressed +00FFFFFF ImmersiveControlLightRichEditButtonBackgroundRest +FF000000 ImmersiveControlLightRichEditButtonGlyphHover +FFFFFFFF ImmersiveControlLightRichEditButtonGlyphPressed +FF000000 ImmersiveControlLightRichEditButtonGlyphRest +FF00B9FF ImmersiveControlLightRichEditHighlight +38000000 ImmersiveControlLightRichEditPromptTextDisabled +AB000000 ImmersiveControlLightRichEditPromptTextFocus +AB000000 ImmersiveControlLightRichEditPromptTextRest +7D000000 ImmersiveControlLightRichEditTextDisabled +FF000000 ImmersiveControlLightRichEditTextFocus +AB000000 ImmersiveControlLightRichEditTextHelper +FFFFFFFF ImmersiveControlLightRichEditTextHighlighted +FF000000 ImmersiveControlLightRichEditTextHover +FF000000 ImmersiveControlLightRichEditTextRest +00000000 ImmersiveControlLightRoundButtonFillLayerDisabled +FFE2E2E2 ImmersiveControlLightRoundButtonFillLayerHover +FF000000 ImmersiveControlLightRoundButtonFillLayerPressed +00000000 ImmersiveControlLightRoundButtonFillLayerRest +66CACACA ImmersiveControlLightRoundButtonGlyphDisabled +FF000000 ImmersiveControlLightRoundButtonGlyphLayerHover +FFFFFFFF ImmersiveControlLightRoundButtonGlyphLayerPressed +FF000000 ImmersiveControlLightRoundButtonGlyphLayerRest +66CACACA ImmersiveControlLightRoundButtonOutlineDisabled +FF000000 ImmersiveControlLightRoundButtonOutlineLayerHover +FF000000 ImmersiveControlLightRoundButtonOutlineLayerPressed +FF000000 ImmersiveControlLightRoundButtonOutlineLayerRest +FF000000 ImmersiveControlLightScrollbarButtonGlyphHover +FFFFFFFF ImmersiveControlLightScrollbarButtonGlyphPressed +99000000 ImmersiveControlLightScrollbarButtonGlyphRest +F0D7D7D7 ImmersiveControlLightScrollbarButtonHover +BD292929 ImmersiveControlLightScrollbarButtonPressed +59D5D5D5 ImmersiveControlLightScrollbarButtonRest +EBD7D7D7 ImmersiveControlLightScrollbarThumbHover +BD292929 ImmersiveControlLightScrollbarThumbPressed +EBC9C9C9 ImmersiveControlLightScrollbarThumbRest +59D5D5D5 ImmersiveControlLightScrollbarTrack +66CACACA ImmersiveControlLightSelectBackgroundDisabled +DEFFFFFF ImmersiveControlLightSelectBackgroundHover +FFD3D3D3 ImmersiveControlLightSelectBackgroundPressed +CCFFFFFF ImmersiveControlLightSelectBackgroundRest +29000000 ImmersiveControlLightSelectBorderDisabled +70000000 ImmersiveControlLightSelectBorderHover +FF5C5C5C ImmersiveControlLightSelectBorderPressed +45000000 ImmersiveControlLightSelectBorderRest +66000000 ImmersiveControlLightSelectGlyphDisabled +FF000000 ImmersiveControlLightSelectGlyphRest +FFFFFFFF ImmersiveControlLightSelectHighlightedTextPressed +21000000 ImmersiveControlLightSelectHighlightHover +FF000000 ImmersiveControlLightSelectHighlightPressed +FF00B9FF ImmersiveControlLightSelectHighlightSelected +FF35BEF2 ImmersiveControlLightSelectHighlightSelectedHover +FFFFFFFF ImmersiveControlLightSelectPopupBackgroundDisabled +21000000 ImmersiveControlLightSelectPopupBackgroundHover +FFD3D3D3 ImmersiveControlLightSelectPopupBackgroundPressed +FFFFFFFF ImmersiveControlLightSelectPopupBackgroundRest +FF00B9FF ImmersiveControlLightSelectPopupBackgroundSelected +FF5C5C5C ImmersiveControlLightSelectPopupBorder +66000000 ImmersiveControlLightSelectPopupTextDisabled +FF000000 ImmersiveControlLightSelectPopupTextHover +FF000000 ImmersiveControlLightSelectPopupTextPressed +FF000000 ImmersiveControlLightSelectPopupTextRest +FFFFFFFF ImmersiveControlLightSelectPopupTextSelected +66000000 ImmersiveControlLightSelectTextDisabled +FFFFFFFF ImmersiveControlLightSelectTextHighlighted +FF000000 ImmersiveControlLightSelectTextHover +FF000000 ImmersiveControlLightSelectTextPressed +FF000000 ImmersiveControlLightSelectTextRest +FFFFFFFF ImmersiveControlLightSliderBorder +FF000000 ImmersiveControlLightSliderThumbBorder +FF929292 ImmersiveControlLightSliderThumbBorderDisabled +FF000000 ImmersiveControlLightSliderThumbBorderHover +FF000000 ImmersiveControlLightSliderThumbBorderPressed +FF000000 ImmersiveControlLightSliderThumbBorderRest +FF929292 ImmersiveControlLightSliderThumbDisabled +FF000000 ImmersiveControlLightSliderThumbHover +FF000000 ImmersiveControlLightSliderThumbPressed +FF000000 ImmersiveControlLightSliderThumbRest +FFFFFFFF ImmersiveControlLightSliderTickMark +FFE5E5E5 ImmersiveControlLightSliderTrackBackgroundDisabled +FFDEDEDE ImmersiveControlLightSliderTrackBackgroundHover +FFEAEAEA ImmersiveControlLightSliderTrackBackgroundPressed +FFD4D4D4 ImmersiveControlLightSliderTrackBackgroundRest +FFD4D4D4 ImmersiveControlLightSliderTrackBufferingDisabled +FFEBCD8C ImmersiveControlLightSliderTrackBufferingHover +FFEBCD8C ImmersiveControlLightSliderTrackBufferingPressed +FFEBCD8C ImmersiveControlLightSliderTrackBufferingRest +FFC4C4C4 ImmersiveControlLightSliderTrackFillDisabled +FF35BEF2 ImmersiveControlLightSliderTrackFillHover +FF64CDF4 ImmersiveControlLightSliderTrackFillPressed +FF00B9FF ImmersiveControlLightSliderTrackFillRest +FF999999 ImmersiveControlLightToggleLabelDisabled +FF000000 ImmersiveControlLightToggleLabelEnabled +FF999999 ImmersiveControlLightToggleOnOffTextDisabled +FF000000 ImmersiveControlLightToggleOnOffTextEnabled +FFA6A6A6 ImmersiveControlLightToggleThumbDisabled +FF000000 ImmersiveControlLightToggleThumbEnabled +FFE0E0E0 ImmersiveControlLightToggleTrackBackgroundDisabled +FFA6A6A6 ImmersiveControlLightToggleTrackBackgroundEnabled +4A000000 ImmersiveControlLightToggleTrackBackgroundHover +42000000 ImmersiveControlLightToggleTrackBackgroundPressed +59000000 ImmersiveControlLightToggleTrackBackgroundRest +FFCCCCCC ImmersiveControlLightToggleTrackBorderDisabled +FFA6A6A6 ImmersiveControlLightToggleTrackBorderEnabled +FFE0E0E0 ImmersiveControlLightToggleTrackFillDisabled +FF00B9FF ImmersiveControlLightToggleTrackFillEnabled +FF35BEF2 ImmersiveControlLightToggleTrackFillHover +FF64CDF4 ImmersiveControlLightToggleTrackFillPressed +FF00B9FF ImmersiveControlLightToggleTrackFillRest +00000000 ImmersiveControlLightToggleTrackGutterDisabled +00000000 ImmersiveControlLightToggleTrackGutterEnabled +00000000 ImmersiveControlProgressBorder +FFDEDEDE ImmersiveControlRadioButtonBackgroundDisabledHover +FF000000 ImmersiveControlRadioButtonBackgroundDisabledPressed +FFA6A6A6 ImmersiveControlRadioButtonBackgroundDisabledSelected +FF00B9FF ImmersiveControlRadioButtonBackgroundSelected +FF2A2A2A ImmersiveControlRadioButtonBorder +FF2A2A2A ImmersiveControlRadioButtonSeparator +FF000000 ImmersiveControlRadioButtonTextDisabledHover +FFFFFFFF ImmersiveControlRadioButtonTextDisabledPressed +FF000000 ImmersiveControlRadioButtonTextDisabledSelected +FFFFFFFF ImmersiveControlRadioButtonTextSelected +59D5D5D5 ImmersiveControlScrollbarBackground +FFDADADA ImmersiveControlScrollbarButtonBackgroundHover +99000000 ImmersiveControlScrollbarButtonBackgroundPressed +00000000 ImmersiveControlScrollbarButtonBackgroundRest +FFDADADA ImmersiveControlScrollbarButtonBorderHover +99000000 ImmersiveControlScrollbarButtonBorderPressed +00000000 ImmersiveControlScrollbarButtonBorderRest +FF000000 ImmersiveControlScrollbarButtonForegroundHover +FFFFFFFF ImmersiveControlScrollbarButtonForegroundPressed +99000000 ImmersiveControlScrollbarButtonForegroundRest +FFCDCDCD ImmersiveControlScrollbarPanningIndicatorBackground +7D9A9A9A ImmersiveControlScrollbarPanningIndicatorBorder +FFDADADA ImmersiveControlScrollbarThumbBackgroundHover +99000000 ImmersiveControlScrollbarThumbBackgroundPressed +FFCDCDCD ImmersiveControlScrollbarThumbBackgroundRest +6BB7B7B7 ImmersiveControlScrollbarThumbBorderHover +ED555555 ImmersiveControlScrollbarThumbBorderPressed +3B555555 ImmersiveControlScrollbarThumbBorderRest +59D5D5D5 ImmersiveControlScrollbarTrackBorder +FF4E1E00 ImmersiveControlSkydriveCommerceBackground +FFC66900 ImmersiveControlSkydriveCommerceDefaultButtonBackground +FF000000 ImmersiveControlSliderTooltipText +3D999999 ImmersiveControlSystemTileBorder +FFFFFFFF ImmersiveControlTooltipBackground +FF808080 ImmersiveControlTooltipBorder +FF666666 ImmersiveControlTooltipDomainText +FF666666 ImmersiveControlTooltipText +00000000 ImmersiveControlTransparent +FF000000 ImmersiveDarkAltHigh +33000000 ImmersiveDarkAltLow +99000000 ImmersiveDarkAltMedium +CC000000 ImmersiveDarkAltMediumHigh +66000000 ImmersiveDarkAltMediumLow +FFFFFFFF ImmersiveDarkBaseHigh +33FFFFFF ImmersiveDarkBaseLow +99FFFFFF ImmersiveDarkBaseMedium +CCFFFFFF ImmersiveDarkBaseMediumHigh +66FFFFFF ImmersiveDarkBaseMediumLow +FFF2F2F2 ImmersiveDarkChromeAltLow +FF000000 ImmersiveDarkChromeBlackHigh +33000000 ImmersiveDarkChromeBlackLow +CC000000 ImmersiveDarkChromeBlackMedium +66000000 ImmersiveDarkChromeBlackMediumLow +FF333333 ImmersiveDarkChromeDisabledHigh +FF858585 ImmersiveDarkChromeDisabledLow +FF767676 ImmersiveDarkChromeHigh +FF171717 ImmersiveDarkChromeLow +FF1F1F1F ImmersiveDarkChromeMedium +FF2B2B2B ImmersiveDarkChromeMediumLow +FF101010 ImmersiveDarkChromeTaskbarBase +FFFFFFFF ImmersiveDarkChromeWhite +E500B9FF ImmersiveDarkListAccentHigh +9900B9FF ImmersiveDarkListAccentLow +CC00B9FF ImmersiveDarkListAccentMedium +19FFFFFF ImmersiveDarkListLow +33FFFFFF ImmersiveDarkListMedium +FF756D6A ImmersiveFilesAppAppBarBackground +FFFFFFFF ImmersiveFilesAppAppBarForeground +00000000 ImmersiveFilesAppAppBarHighContrastBorder +FFEDEDED ImmersiveFilesAppBackground +FF777777 ImmersiveFilesAppCommandRowDisabled +FFFFFFFF ImmersiveFilesAppCommandRowHighlight +FFD2D2D2 ImmersiveFilesAppCommandRowHover +FF777777 ImmersiveFilesAppCommandRowPressed +FFA5A5A5 ImmersiveFilesAppCommandRowRest +FFFCFFB2 ImmersiveFilesAppDarkLinkText +FF777777 ImmersiveFilesAppDarkLinkTextDisabled +FFE1E2A4 ImmersiveFilesAppDarkLinkTextHover +FFC6C595 ImmersiveFilesAppDarkLinkTextPressed +FF3F3F3F ImmersiveFilesAppDefaultButtonBackgroundHover +FFFFFFFF ImmersiveFilesAppDefaultButtonBackgroundPressed +FF1D1D1D ImmersiveFilesAppDefaultButtonBackgroundRest +FF000000 ImmersiveFilesAppDefaultButtonBorderHover +FFFFFFFF ImmersiveFilesAppDefaultButtonBorderPressed +FF000000 ImmersiveFilesAppDefaultButtonBorderRest +FF000000 ImmersiveFilesAppDefaultButtonTextHover +FF000000 ImmersiveFilesAppDefaultButtonTextPressed +FF000000 ImmersiveFilesAppDefaultButtonTextRest +00000000 ImmersiveFilesAppFolderHighContrastBorder +FFFFFFFF ImmersiveFilesAppFolderHoverPrimaryText +FFFFFFFF ImmersiveFilesAppFolderPrimaryText +FFFFFFFF ImmersiveFilesAppFolderSelectionHoverPrimaryText +FFFFFFFF ImmersiveFilesAppFolderSelectionPrimaryText +FFBDBAB9 ImmersiveFilesAppHoverBackground +FFFFFFFF ImmersiveFilesAppItemBackground +FF000000 ImmersiveFilesAppItemPrimaryText +FF696969 ImmersiveFilesAppItemSecondaryText +FF0030E1 ImmersiveFilesAppLightErrorText +FF9F7000 ImmersiveFilesAppLightLinkText +FF8E8E8E ImmersiveFilesAppLightLinkTextDisabled +FFAF892F ImmersiveFilesAppLightLinkTextHover +FFBEA25F ImmersiveFilesAppLightLinkTextPressed +FF987304 ImmersiveFilesAppLocalFolderBackground +FF8C8CFF ImmersiveFilesAppLocalFolderErrorText +FFF1ECDE ImmersiveFilesAppLocalFolderHoverSecondaryText +FFF1ECDE ImmersiveFilesAppLocalFolderSecondaryText +FFFFFFFF ImmersiveFilesAppLocalFolderSelectionHoverSecondaryText +FFF1ECDE ImmersiveFilesAppLocalFolderSelectionSecondaryText +FF998200 ImmersiveFilesAppPhotosAppSelectionBackground +FF1D1D1D ImmersiveFilesAppPickerBackground +00000000 ImmersiveFilesAppPickerButtonBackgroundDisabled +FF777777 ImmersiveFilesAppPickerButtonBorderDisabled +FF777777 ImmersiveFilesAppPickerButtonTextDisabled +FF87807D ImmersiveFilesAppPickerDefaultButtonBackgroundHover +FFFFFFFF ImmersiveFilesAppPickerDefaultButtonBackgroundPressed +FF756D6A ImmersiveFilesAppPickerDefaultButtonBackgroundRest +FFFFFFFF ImmersiveFilesAppPickerDefaultButtonBorderHover +FFFFFFFF ImmersiveFilesAppPickerDefaultButtonBorderPressed +FFFFFFFF ImmersiveFilesAppPickerDefaultButtonBorderRest +FFFFFFFF ImmersiveFilesAppPickerDefaultButtonTextHover +FF000000 ImmersiveFilesAppPickerDefaultButtonTextPressed +FFFFFFFF ImmersiveFilesAppPickerDefaultButtonTextRest +FF2B2B2B ImmersiveFilesAppPickerDocumentThumbnailBackground +FF73BAFF ImmersiveFilesAppPickerErrorText +FF616161 ImmersiveFilesAppPickerHoverBackground +FFFFFFFF ImmersiveFilesAppPickerHoverPrimaryText +FFB3B3B3 ImmersiveFilesAppPickerHoverSecondaryText +FFA58524 ImmersiveFilesAppPickerLocalFolderHoverBackground +FF2B2B2B ImmersiveFilesAppPickerPaneBackground +FFCB9A05 ImmersiveFilesAppPickerPaneHighlight +FF414141 ImmersiveFilesAppPickerPaneHoverBackground +FFFFFFFF ImmersiveFilesAppPickerPaneHoverText +FFFFFFFF ImmersiveFilesAppPickerPanePrimaryText +FFB3B3B3 ImmersiveFilesAppPickerPaneSecondaryText +FFFFFFFF ImmersiveFilesAppPickerPrimaryText +FFB3B3B3 ImmersiveFilesAppPickerSecondaryText +FF9F9997 ImmersiveFilesAppPickerSelectionHoverBackground +FFFFFFFF ImmersiveFilesAppPickerSelectionHoverPrimaryText +FFFFFFFF ImmersiveFilesAppPickerSelectionHoverSecondaryText +FFFFFFFF ImmersiveFilesAppPickerSelectionPrimaryText +FFFFFFFF ImmersiveFilesAppPickerSelectionSecondaryText +FFBC6129 ImmersiveFilesAppPickerSkyDriveFolderHoverBackground +FF2B2B2B ImmersiveFilesAppPickerThumbnailPlaceholder +FFA5A5A5 ImmersiveFilesAppPickerUnavailableText +FFEDEDED ImmersiveFilesAppProgressTrackBackground +FF0CA64D ImmersiveFilesAppProgressTrackFill +FF777777 ImmersiveFilesAppSearchBorder +FF756D6A ImmersiveFilesAppSearchButtonBackground +FFFFFFFF ImmersiveFilesAppSearchButtonForeground +FF000000 ImmersiveFilesAppSearchPrimaryText +FF666666 ImmersiveFilesAppSearchSecondaryText +FF756D6A ImmersiveFilesAppSelectionBackground +FFFFFFFF ImmersiveFilesAppSelectionForeground +FFB24A09 ImmersiveFilesAppSkyDriveEmphasisText +FFB24A09 ImmersiveFilesAppSkyDriveFolderBackground +FF73BAFF ImmersiveFilesAppSkyDriveFolderErrorText +FFE8C9B6 ImmersiveFilesAppSkyDriveFolderHoverSecondaryText +FFE8C9B6 ImmersiveFilesAppSkyDriveFolderSecondaryText +FFFFFFFF ImmersiveFilesAppSkyDriveFolderSelectionHoverSecondaryText +FFE8C9B6 ImmersiveFilesAppSkyDriveFolderSelectionSecondaryText +FF6E6E6E ImmersiveFilesAppSkyDriveUnavailableText +FF8E8E8E ImmersiveFilesAppTabTextDisabled +FFB24A09 ImmersiveFilesAppTabTextHighlight +FF2F2F2F ImmersiveFilesAppTabTextHover +FF8E8E8E ImmersiveFilesAppTabTextPressed +FF5F5F5F ImmersiveFilesAppTabTextRest +00000000 ImmersiveFilesAppThumbnailHighContrastBorder +FF777777 ImmersiveFilesAppTouchSelectHighlightSelected +FF8C8C8C ImmersiveFilesAppTouchSelectHighlightSelectedHover +FFFFFFFF ImmersiveFilesAppTouchSelectHighlightSelectedHoverText +FFFFFFFF ImmersiveFilesAppTouchSelectHighlightSelectedText +7F000000 ImmersiveHardwareAppBarBackground +FF111111 ImmersiveHardwareAppSwitcherBackground +FF333333 ImmersiveHardwareAppSwitcherHotTrack +FF333333 ImmersiveHardwareAppSwitcherTextOverlayBackground +33DEDEDE ImmersiveHardwareAppSwitcherThumbnailBorder +33DEDEDE ImmersiveHardwareAppSwitcherThumbnailBorderHover +FF666666 ImmersiveHardwareButtonDisabled +FFFFFFFF ImmersiveHardwareButtonGlyphHover +FF000000 ImmersiveHardwareButtonGlyphPressed +FF3D3D3D ImmersiveHardwareButtonHover +FFFFFFFF ImmersiveHardwareButtonPressed +FFFFFFFF ImmersiveHardwareButtonRest +FF111111 ImmersiveHardwareCharmsBarBackground +FF333333 ImmersiveHardwareCharmsBarBackgroundHotTrack +FF444444 ImmersiveHardwareCharmsBarBackgroundPressed +FF111111 ImmersiveHardwareCharmsBarBackgroundRest +FF00B9FF ImmersiveHardwareCharmsBarFlag +FF71D8FF ImmersiveHardwareCharmsBarLogoWash +FFA0A0A0 ImmersiveHardwareCharmsBarSelectedText +FFA0A0A0 ImmersiveHardwareCharmsBarText +FFA0A0A0 ImmersiveHardwareCharmsBarTextDisabled +F2111111 ImmersiveHardwareClockBackground +FFFFFFFF ImmersiveHardwareClockText +FF3ACD55 ImmersiveHardwareControlLink +FF98B29B ImmersiveHardwareControlLinkDisabled +FFCCEEC9 ImmersiveHardwareControlLinkMouseHover +FF378E4D ImmersiveHardwareControlLinkPressed +FF57C764 ImmersiveHardwareControlLinkVisited +FFFFFFFF ImmersiveHardwareCountdownText +FFFFFFFF ImmersiveHardwareCropControlFill +4C000000 ImmersiveHardwareCropControlFillHover +FFFFFFFF ImmersiveHardwareCropControlFillPressed +59000000 ImmersiveHardwareCropControlOutline +59000000 ImmersiveHardwareCropControlOutlineHover +59000000 ImmersiveHardwareCropControlOutlinePressed +FF00B9FF ImmersiveHardwareDarkCandidateControlBackgroundHightlighted +FFE5E5E5 ImmersiveHardwareDarkCandidateControlBackgroundHover +FF00AAEA ImmersiveHardwareDarkCandidateControlBackgroundPressed +FF1A1A1A ImmersiveHardwareDarkCandidateControlBackgroundRest +FFFFFFFF ImmersiveHardwareDarkCandidateControlHighlightedSecondaryTextPressed +FF00B9FF ImmersiveHardwareDarkCandidateControlHighlightSelected +FFFFFFFF ImmersiveHardwareDarkCandidateControlSecondaryTextHighlighted +FF000000 ImmersiveHardwareDarkCandidateControlSecondaryTextHover +FFFFFFFF ImmersiveHardwareDarkCandidateControlSecondaryTextPressed +FF838383 ImmersiveHardwareDarkCandidateControlSecondaryTextRest +FFFFFFFF ImmersiveHardwareDarkCandidateControlSecondaryTextSelect +FF000000 ImmersiveHardwareDarkCandidateControlTextHover +FFFFFFFF ImmersiveHardwareDarkCandidateControlTextPressed +FFFFFFFF ImmersiveHardwareDarkCandidateControlTextRest +FFFFFFFF ImmersiveHardwareDarkCandidateControlTextSelect +FF1A1A1A ImmersiveHardwareDarkKeyboardBackground +FF000000 ImmersiveHardwareDarkKeyboardChildKeyKeyText +FF1A1A1A ImmersiveHardwareDarkKeyboardChildPanelBackground +FFF2F2F2 ImmersiveHardwareDarkKeyboardChildPanelKeyBackground +FF00B9FF ImmersiveHardwareDarkKeyboardEmojiCategoryTextSelected +FF4D4D4D ImmersiveHardwareDarkKeyboardFunctionKeyBackground +FFFFFFFF ImmersiveHardwareDarkKeyboardFunctionKeyText +FF838383 ImmersiveHardwareDarkKeyboardFunctionKeyTextDisabled +FFE5E5E5 ImmersiveHardwareDarkKeyboardKeyBackgroundHover +FF00B9FF ImmersiveHardwareDarkKeyboardKeyBackgroundPressed +FF333333 ImmersiveHardwareDarkKeyboardKeyBackgroundRest +FF333333 ImmersiveHardwareDarkKeyboardKeyDefaultBackgroundRest +FFFFFFFF ImmersiveHardwareDarkKeyboardKeyDefaultPrimaryTextRest +FF838383 ImmersiveHardwareDarkKeyboardKeyPrimaryTextDisabled +FF000000 ImmersiveHardwareDarkKeyboardKeyPrimaryTextHover +FFFFFFFF ImmersiveHardwareDarkKeyboardKeyPrimaryTextPressed +FFFFFFFF ImmersiveHardwareDarkKeyboardKeyPrimaryTextRest +00000000 ImmersiveHardwareDarkKeyboardKeySecondaryTextChildKeyDisabled +FFFFFFFF ImmersiveHardwareDarkKeyboardKeySecondaryTextChildKeyHover +FF00B9FF ImmersiveHardwareDarkKeyboardKeySecondaryTextChildKeyPressed +FF838383 ImmersiveHardwareDarkKeyboardKeySecondaryTextChildKeyRest +FF838383 ImmersiveHardwareDarkKeyboardKeySecondaryTextModifierKeyDisabled +FFFFFFFF ImmersiveHardwareDarkKeyboardKeySecondaryTextModifierKeyHover +FF00B9FF ImmersiveHardwareDarkKeyboardKeySecondaryTextModifierKeyPressed +FF333333 ImmersiveHardwareDarkKeyboardKeySecondaryTextModifierKeyRest +FF333333 ImmersiveHardwareDarkKeyboardNumberKeyBackground +FFFFFFFF ImmersiveHardwareDarkKeyboardNumberKeyText +FF838383 ImmersiveHardwareDarkKeyboardSpaceGripper +FF2C2627 ImmersiveHardwareDarkKeyboardThumbCentralNumberKeyBackground +FFA4A4A4 ImmersiveHardwareDarkKeyboardThumbCentralNumberKeyText +00000000 ImmersiveHardwareDarkKeyboardThumbResizeGripperBackgroundRest +FF000000 ImmersiveHardwareDarkRoundButtonFillLayerDisabled +FF3D3D3D ImmersiveHardwareDarkRoundButtonFillLayerHover +FFFFFFFF ImmersiveHardwareDarkRoundButtonFillLayerPressed +FF000000 ImmersiveHardwareDarkRoundButtonFillLayerRest +FF7D7D7D ImmersiveHardwareDarkRoundButtonGlyphDisabled +FFFFFFFF ImmersiveHardwareDarkRoundButtonGlyphLayerHover +FF000000 ImmersiveHardwareDarkRoundButtonGlyphLayerPressed +FFFFFFFF ImmersiveHardwareDarkRoundButtonGlyphLayerRest +FF7D7D7D ImmersiveHardwareDarkRoundButtonOutlineDisabled +FFFFFFFF ImmersiveHardwareDarkRoundButtonOutlineLayerHover +FFFFFFFF ImmersiveHardwareDarkRoundButtonOutlineLayerPressed +FFFFFFFF ImmersiveHardwareDarkRoundButtonOutlineLayerRest +FFE3B75A ImmersiveHardwareDefaultKeyboardKeyBackgroundHover +FF00B9FF ImmersiveHardwareDefaultKeyboardKeyBackgroundRest +FFFFFFFF ImmersiveHardwareDefaultKeyboardKeyPrimaryTextRest +FFFFFFFF ImmersiveHardwareDefaultKeyboardKeySecondaryTextRest +F0D7D7D7 ImmersiveHardwareFlipViewFillHover +BD292929 ImmersiveHardwareFlipViewFillPressed +59D5D5D5 ImmersiveHardwareFlipViewFillRest +FF000000 ImmersiveHardwareFlipViewGlyphHover +FFFFFFFF ImmersiveHardwareFlipViewGlyphPressed +FF000000 ImmersiveHardwareFlipViewGlyphRest +FFC1C19E ImmersiveHardwareFlipViewOutlineHover +BD292929 ImmersiveHardwareFlipViewOutlinePressed +59D5D5D5 ImmersiveHardwareFlipViewOutlineRest +FF1A1A1A ImmersiveHardwareGenericBackground +FF111111 ImmersiveHardwareGutterBackground +FF02ACEC ImmersiveHardwareGutterDown +FFD8D8D8 ImmersiveHardwareGutterIndicator +FF00B9FF ImmersiveHardwareGutterRest +FF9B9798 ImmersiveHardwareHandwritingPanelBorder +FFFFFFFF ImmersiveHardwareHandwritingPanelButtonBorder +FF372F30 ImmersiveHardwareHandwritingPanelButtonHover +FF676162 ImmersiveHardwareHandwritingPanelButtonPress +FF372F30 ImmersiveHardwareHandwritingPanelButtonRest +FF2A2A2A ImmersiveHardwareHandwritingPanelCharChevronPressed +FFFFFFFF ImmersiveHardwareHandwritingPanelCharChevronRest +FF2A2A2A ImmersiveHardwareHandwritingPanelConversionHoveredText +FFFFFFFF ImmersiveHardwareHandwritingPanelConversionSelectedBackground +FF2A2A2A ImmersiveHardwareHandwritingPanelConversionSelectedText +FFFFFFFF ImmersiveHardwareHandwritingPanelConversionToggledText +FF372F30 ImmersiveHardwareHandwritingPanelConversionUnselectedBackground +FFFFFFFF ImmersiveHardwareHandwritingPanelConversionUnselectedText +FF767172 ImmersiveHardwareHandwritingPanelCorrectionText +FF514A4B ImmersiveHardwareHandwritingPanelHoverWord +FFD5D5D5 ImmersiveHardwareHandwritingPanelInsertModeCharacter +FFD7D5D6 ImmersiveHardwareHandwritingPanelKanjiConversionBackground +FFE5E4E4 ImmersiveHardwareHandwritingPanelKanjiConversionBackgroundHovered +FFD7D5D6 ImmersiveHardwareHandwritingPanelKanjiConversionBorder +FF636363 ImmersiveHardwareHandwritingPanelKanjiConversionText +FF777777 ImmersiveHardwareHandwritingPanelMatchedText +FFBA8900 ImmersiveHardwareHandwritingPanelSuggestedWord +FF2D55D9 ImmersiveHardwareHelpStickerAccent +FF111111 ImmersiveHardwareHelpStickerBackground +FFFFFFFF ImmersiveHardwareHelpStickerBorder +FF000000 ImmersiveHardwareKeyboardBackground +FFFFFFFF ImmersiveHardwareKeyboardChildKeyKeyText +FF988E8F ImmersiveHardwareKeyboardChildPanelBackground +FF4C4545 ImmersiveHardwareKeyboardChildPanelKeyBackground +FF878383 ImmersiveHardwareKeyboardDarkSpaceKeyBackgroundPressed +FF82CDEA ImmersiveHardwareKeyboardEmojiCategoryTextSelected +FF211C1D ImmersiveHardwareKeyboardFunctionKeyBackground +FF565253 ImmersiveHardwareKeyboardFunctionKeyBackgroundHover +FFD5D5D5 ImmersiveHardwareKeyboardFunctionKeyText +FF575455 ImmersiveHardwareKeyboardFunctionKeyTextDisabled +FF372F30 ImmersiveHardwareKeyboardKeyBackgroundDisabled +FF676162 ImmersiveHardwareKeyboardKeyBackgroundHover +FFFFFFFF ImmersiveHardwareKeyboardKeyBackgroundPressed +FF372F30 ImmersiveHardwareKeyboardKeyBackgroundRest +00FFFFFF ImmersiveHardwareKeyboardKeyBorder +FF000000 ImmersiveHardwareKeyboardKeyDockCloseRest +FF736E6F ImmersiveHardwareKeyboardKeyPrimaryTextDisabled +FF000000 ImmersiveHardwareKeyboardKeyPrimaryTextPressed +FFFFFFFF ImmersiveHardwareKeyboardKeyPrimaryTextRest +FF736E6F ImmersiveHardwareKeyboardKeySecondaryTextDisabled +FF000000 ImmersiveHardwareKeyboardKeySecondaryTextPressed +FFD5D5D5 ImmersiveHardwareKeyboardKeySecondaryTextRest +FF4C4445 ImmersiveHardwareKeyboardNumberKeyBackground +FF777171 ImmersiveHardwareKeyboardNumberKeyBackgroundHover +FFFFFFFF ImmersiveHardwareKeyboardNumberKeyText +FF2C2627 ImmersiveHardwareKeyboardThumbCentralNumberKeyBackground +FFA4A4A4 ImmersiveHardwareKeyboardThumbCentralNumberKeyText +00000000 ImmersiveHardwareKeyboardThumbResizeGripperBackgroundRest +FFD5D5D5 ImmersiveHardwareKeyboardTitleBarText +FF686868 ImmersiveHardwareKeyboardTitleBarTextDisabled +F0D7D7D7 ImmersiveHardwarePinFlyoutFlipViewFillHover +BD292929 ImmersiveHardwarePinFlyoutFlipViewFillPressed +59D5D5D5 ImmersiveHardwarePinFlyoutFlipViewFillRest +FF000000 ImmersiveHardwarePinFlyoutFlipViewGlyphHover +FFFFFFFF ImmersiveHardwarePinFlyoutFlipViewGlyphPressed +FF000000 ImmersiveHardwarePinFlyoutFlipViewGlyphRest +F0D7D7D7 ImmersiveHardwarePinFlyoutFlipViewOutlineHover +BD292929 ImmersiveHardwarePinFlyoutFlipViewOutlinePressed +59D5D5D5 ImmersiveHardwarePinFlyoutFlipViewOutlineRest +FFFFFFFF ImmersiveHardwarePlaybackBarProgressFill +33FFFFFF ImmersiveHardwarePlaybackBarRest +59000000 ImmersiveHardwarePlaybackBarTrim +59000000 ImmersiveHardwarePlaybackButtonFill +59000000 ImmersiveHardwarePlaybackButtonFillHover +FFFFFFFF ImmersiveHardwarePlaybackButtonFillPressed +FFFFFFFF ImmersiveHardwarePlaybackButtonGlyph +FFFFFFFF ImmersiveHardwarePlaybackButtonGlyphHover +FF000000 ImmersiveHardwarePlaybackButtonGlyphPressed +FFFFFFFF ImmersiveHardwarePlaybackButtonOutline +FFFFFFFF ImmersiveHardwarePrimaryText +4C000000 ImmersiveHardwareScreenFill +4C000000 ImmersiveHardwareScrubberControlFill +59000000 ImmersiveHardwareScrubberControlFillHover +FFFFFFFF ImmersiveHardwareScrubberControlFillPressed +FFFFFFFF ImmersiveHardwareScrubberControlOutline +FFFFFFFF ImmersiveHardwareScrubberControlOutlineHover +FFFFFFFF ImmersiveHardwareScrubberControlOutlinePressed +59D5D5D5 ImmersiveHardwareSemanticZoomBackground +FFDADADA ImmersiveHardwareSemanticZoomBackgroundHover +BD292929 ImmersiveHardwareSemanticZoomBackgroundPressed +99000000 ImmersiveHardwareSemanticZoomForeground +FF000000 ImmersiveHardwareSemanticZoomForegroundHover +FFFFFFFF ImmersiveHardwareSemanticZoomForegroundPressed +00FFFFFF ImmersiveHardwareSettingCharmSystemPaneButtonDisabled +3EFFFFFF ImmersiveHardwareSettingCharmSystemPaneButtonHover +66FFFFFF ImmersiveHardwareSettingCharmSystemPaneButtonPressed +00FFFFFF ImmersiveHardwareSettingCharmSystemPaneButtonRest +66FFFFFF ImmersiveHardwareSettingCharmSystemPaneButtonSelected +CCFFFFFF ImmersiveHardwareSettingCharmSystemPaneButtonText +CCFFFFFF ImmersiveHardwareSettingCharmSystemPaneButtonTextDisabled +CCFFFFFF ImmersiveHardwareSettingCharmSystemPaneButtonTextHover +CCFFFFFF ImmersiveHardwareSettingCharmSystemPaneButtonTextPressed +CCFFFFFF ImmersiveHardwareSettingCharmSystemPaneButtonTextSelected +FF000000 ImmersiveHardwareTextPredictionBackgroundPressed +FFFFFFFF ImmersiveHardwareTextPredictionBackgroundRest +FF2A2A2A ImmersiveHardwareTextPredictionBorder +FFFFFFFF ImmersiveHardwareTextPredictionTextPressed +FF000000 ImmersiveHardwareTextPredictionTextRest +FF111111 ImmersiveHardwareTitleBarBackground +FF2311E8 ImmersiveHardwareTitleBarCloseButtonHover +FF7A70F1 ImmersiveHardwareTitleBarCloseButtonPressed +FFB36536 ImmersiveHardwareTitleBarMinimizeButtonHover +FF99603D ImmersiveHardwareTitleBarMinimizeButtonPressed +FFCA9A36 ImmersiveHardwareTrimBarProgressFill +FFFFFFFF ImmersiveHardwareTrimControlFill +4C000000 ImmersiveHardwareTrimControlFillHover +FFFFFFFF ImmersiveHardwareTrimControlFillPressed +59000000 ImmersiveHardwareTrimControlOutline +59000000 ImmersiveHardwareTrimControlOutlineHover +59000000 ImmersiveHardwareTrimControlOutlinePressed +FF222222 ImmersiveHardwareWin8Pillarbox +FF005E80 ImmersiveInputSwitchColorDarkBackground +19FFFFFF ImmersiveInputSwitchColorDarkButtonBackgroundHover +33FFFFFF ImmersiveInputSwitchColorDarkButtonBackgroundPressed +8AFFFFFF ImmersiveInputSwitchColorDarkButtonSecondaryTextHover +8AFFFFFF ImmersiveInputSwitchColorDarkButtonSecondaryTextPressed +8AFFFFFF ImmersiveInputSwitchColorDarkButtonSecondaryTextRest +FFFFFFFF ImmersiveInputSwitchColorDarkButtonTextHover +FFFFFFFF ImmersiveInputSwitchColorDarkButtonTextPressed +FFFFFFFF ImmersiveInputSwitchColorDarkButtonTextRest +FF858585 ImmersiveInputSwitchColorDarkDisabledText +FF858585 ImmersiveInputSwitchColorDarkRadioButtonBackgroundDisabledSelected +66000000 ImmersiveInputSwitchColorDarkRadioButtonBackgroundSelected +FFFFFFFF ImmersiveInputSwitchColorDarkRadioButtonBorder +FF000000 ImmersiveInputSwitchColorDarkRadioButtonTextDisabledSelected +FFFFFFFF ImmersiveInputSwitchColorDarkSelectionPrimaryText +33FFFFFF ImmersiveInputSwitchColorDarkSeparatorLine +FFCCCCCC ImmersiveInputSwitchColorDarkWindowBorder +F21E1E1E ImmersiveInputSwitchDarkBackground +19FFFFFF ImmersiveInputSwitchDarkButtonBackgroundHover +33FFFFFF ImmersiveInputSwitchDarkButtonBackgroundPressed +8AFFFFFF ImmersiveInputSwitchDarkButtonSecondaryTextHover +8AFFFFFF ImmersiveInputSwitchDarkButtonSecondaryTextPressed +8AFFFFFF ImmersiveInputSwitchDarkButtonSecondaryTextRest +FFFFFFFF ImmersiveInputSwitchDarkButtonTextHover +FFFFFFFF ImmersiveInputSwitchDarkButtonTextPressed +FFFFFFFF ImmersiveInputSwitchDarkButtonTextRest +FF858585 ImmersiveInputSwitchDarkDisabledText +FF858585 ImmersiveInputSwitchDarkRadioButtonBackgroundDisabledSelected +FF00B9FF ImmersiveInputSwitchDarkRadioButtonBackgroundSelected +FFFFFFFF ImmersiveInputSwitchDarkRadioButtonBorder +FF000000 ImmersiveInputSwitchDarkRadioButtonTextDisabledSelected +FFFFFFFF ImmersiveInputSwitchDarkSelectionPrimaryText +33FFFFFF ImmersiveInputSwitchDarkSeparatorLine +FFCCCCCC ImmersiveInputSwitchDarkWindowBorder +F2FFFFFF ImmersiveInputSwitchLightBackground +19000000 ImmersiveInputSwitchLightButtonBackgroundHover +33000000 ImmersiveInputSwitchLightButtonBackgroundPressed +8A000000 ImmersiveInputSwitchLightButtonSecondaryTextHover +8A000000 ImmersiveInputSwitchLightButtonSecondaryTextPressed +8A000000 ImmersiveInputSwitchLightButtonSecondaryTextRest +FF000000 ImmersiveInputSwitchLightButtonTextHover +FF000000 ImmersiveInputSwitchLightButtonTextPressed +FF000000 ImmersiveInputSwitchLightButtonTextRest +FFCCCCCC ImmersiveInputSwitchLightDisabledText +FFCCCCCC ImmersiveInputSwitchLightRadioButtonBackgroundDisabledSelected +FF00B9FF ImmersiveInputSwitchLightRadioButtonBackgroundSelected +FF000000 ImmersiveInputSwitchLightRadioButtonBorder +FF000000 ImmersiveInputSwitchLightRadioButtonTextDisabledSelected +FFFFFFFF ImmersiveInputSwitchLightSelectionPrimaryText +33000000 ImmersiveInputSwitchLightSeparatorLine +FF000000 ImmersiveInputSwitchLightWindowBorder +FFFFFFFF ImmersiveLightAltHigh +33FFFFFF ImmersiveLightAltLow +99FFFFFF ImmersiveLightAltMedium +CCFFFFFF ImmersiveLightAltMediumHigh +66FFFFFF ImmersiveLightAltMediumLow +FFFFFFFF ImmersiveLightBackground +FFB6B6B6 ImmersiveLightBackgroundDisabled +FF000000 ImmersiveLightBaseHigh +33000000 ImmersiveLightBaseLow +99000000 ImmersiveLightBaseMedium +CC000000 ImmersiveLightBaseMediumHigh +66000000 ImmersiveLightBaseMediumLow +FF2A2A2A ImmersiveLightBorder +FF171717 ImmersiveLightChromeAltLow +FF000000 ImmersiveLightChromeBlackHigh +33000000 ImmersiveLightChromeBlackLow +CC000000 ImmersiveLightChromeBlackMedium +66000000 ImmersiveLightChromeBlackMediumLow +FFCCCCCC ImmersiveLightChromeDisabledHigh +FF7A7A7A ImmersiveLightChromeDisabledLow +FFCCCCCC ImmersiveLightChromeHigh +FFF2F2F2 ImmersiveLightChromeLow +FFE6E6E6 ImmersiveLightChromeMedium +FFF2F2F2 ImmersiveLightChromeMediumLow +FFEFEFEF ImmersiveLightChromeTaskbarBase +FFFFFFFF ImmersiveLightChromeWhite +FFFF00FF ImmersiveLightControlLink +FFFF00FF ImmersiveLightControlLinkBackgroundPressed +FFFF00FF ImmersiveLightControlLinkDisabled +FFFF00FF ImmersiveLightControlLinkForegroundPressed +FFFF00FF ImmersiveLightControlLinkMouseHover +FFFF00FF ImmersiveLightControlLinkPressed +FFFF00FF ImmersiveLightControlLinkVisited +FFF1F1F1 ImmersiveLightDesktopToastBackground +FF999999 ImmersiveLightDisabledText +3D000000 ImmersiveLightDivider +FFF2F2F2 ImmersiveLightEntityItemBackgroundHover +FFE8E8E8 ImmersiveLightEntityItemBackgroundSelected +FFF2F2F2 ImmersiveLightEntityItemBorderHover +FFE8E8E8 ImmersiveLightEntityItemBorderSelected +FF777777 ImmersiveLightFocusRect +FF00B9FF ImmersiveLightHighlight +FFDEDEDE ImmersiveLightHoverBackground +21000000 ImmersiveLightHoverBackgroundTransparent +FF000000 ImmersiveLightHoverPrimaryText +FF000000 ImmersiveLightHoverSecondaryText +1A000000 ImmersiveLightIconBorder +FF0033E1 ImmersiveLightInlineErrorText +B200B9FF ImmersiveLightListAccentHigh +6600B9FF ImmersiveLightListAccentLow +9900B9FF ImmersiveLightListAccentMedium +19000000 ImmersiveLightListLow +33000000 ImmersiveLightListMedium +FFF4F4F4 ImmersiveLightNavBackground +21FFFFFF ImmersiveLightPCSettingsNavBarItemBackgroundHover +21FFFFFF ImmersiveLightPCSettingsNavBarItemBackgroundTouchPressed +19000000 ImmersiveLightPCSettingsSearchButtonBackgroundHover +33000000 ImmersiveLightPCSettingsSearchButtonBackgroundPressed +00000000 ImmersiveLightPCSettingsSearchButtonBackgroundRest +3B9B9B9B ImmersiveLightPlaceholderBackground +FF00B9FF ImmersiveLightPrimaryChartFill +FF000000 ImmersiveLightPrimaryText +FFF7FCF9 ImmersiveLightSearchAdBackground +FF162D89 ImmersiveLightSearchContactHeroAccentDark +FF1F6B0C ImmersiveLightSearchContactHeroAccentHitHighlight +FF2647D2 ImmersiveLightSearchContactHeroAccentLight +FF162D89 ImmersiveLightSearchContactHeroAccentLink +FF0471AB ImmersiveLightSearchFinanceGreen +FF2211CC ImmersiveLightSearchFinanceRed +FF1D1D1D ImmersiveLightSearchHeroBackground +FF494949 ImmersiveLightSearchHeroCollageAccentDark +FF696969 ImmersiveLightSearchHeroCollageAccentLight +FF8A4A4A ImmersiveLightSearchHeroMapAccentDark +FFB86767 ImmersiveLightSearchHeroMapAccentLight +FF82B300 ImmersiveLightSearchHitHighlight +FF777777 ImmersiveLightSearchNewsBackground +FFDDDDDD ImmersiveLightSearchNewsBackgroundBorder +FF0097D0 ImmersiveLightSearchSettingTilesBackground +FF999999 ImmersiveLightSearchStoreRatingEmpty +FF333333 ImmersiveLightSearchStoreRatingFull +FFFFFFFF ImmersiveLightSearchVideoTextWhite +FFED297C ImmersiveLightSearchWeatherBlue +FF6AD7FF ImmersiveLightSecondaryChartFill +FF666666 ImmersiveLightSecondaryText +B2000000 ImmersiveLightSecondaryTextTransparent +FF00B9FF ImmersiveLightSelectedTabText +FF00B9FF ImmersiveLightSelectionBackground +FF35BEF2 ImmersiveLightSelectionHoverBackground +FFFFFFFF ImmersiveLightSelectionHoverPrimaryText +FFFFFFFF ImmersiveLightSelectionHoverSecondaryText +FFFFFFFF ImmersiveLightSelectionPrimaryText +FFFFFFFF ImmersiveLightSelectionSecondaryText +FF000000 ImmersiveLightTabText +FF00B9FF ImmersiveLightTitleText +FF2226CD ImmersiveLightWUError +FF26711E ImmersiveLightWUNormal +FF0096FF ImmersiveLightWUWarning +FFA8E8FF ImmersiveMultitaskingMTVActiveVirtualDesktopHotTrackOuterBorder +FF8CE0FF ImmersiveMultitaskingMTVActiveVirtualDesktopOuterBorder +FFFFFFFF ImmersiveMultitaskingMTVCloseGlyphHotTrack +FFFFFFFF ImmersiveMultitaskingMTVCloseGlyphPressed +FFFFFFFF ImmersiveMultitaskingMTVCloseGlyphRest +00000000 ImmersiveMultitaskingMTVCloseOutlineHotTrack +00000000 ImmersiveMultitaskingMTVCloseOutlinePressed +00000000 ImmersiveMultitaskingMTVCloseOutlineRest +CC2311E8 ImmersiveMultitaskingMTVClosePlateHotTrack +FF2311E8 ImmersiveMultitaskingMTVClosePlatePressed +00000000 ImmersiveMultitaskingMTVClosePlateRest +FF000000 ImmersiveMultitaskingMTVDimmingLayer +FF000000 ImmersiveMultitaskingMTVInactiveVirtualDesktopDim +FFFFFFFF ImmersiveMultitaskingMTVNewDesktopFocusOutline +00000000 ImmersiveMultitaskingMTVNewDesktopOutlineHotTrack +00000000 ImmersiveMultitaskingMTVNewDesktopOutlinePressed +00000000 ImmersiveMultitaskingMTVNewDesktopOutlineRest +FF000000 ImmersiveMultitaskingMTVNewDesktopPlateHotTrack +FF000000 ImmersiveMultitaskingMTVNewDesktopPlatePressed +FF000000 ImmersiveMultitaskingMTVNewDesktopPlateRest +FFFFFFFF ImmersiveMultitaskingMTVNewDesktopTextHotTrack +FFFFFFFF ImmersiveMultitaskingMTVNewDesktopTextPressed +FFFFFFFF ImmersiveMultitaskingMTVNewDesktopTextRest +FFFFFFFF ImmersiveMultitaskingMTVRestVirtualDesktopInner +FFFFFFFF ImmersiveMultitaskingMTVScrollButtonGlyphDisabled +FFFFFFFF ImmersiveMultitaskingMTVScrollButtonGlyphHotTrack +FFFFFFFF ImmersiveMultitaskingMTVScrollButtonGlyphPressed +FFFFFFFF ImmersiveMultitaskingMTVScrollButtonGlyphRest +00000000 ImmersiveMultitaskingMTVScrollButtonOutlineDisabled +00000000 ImmersiveMultitaskingMTVScrollButtonOutlineHotTrack +00000000 ImmersiveMultitaskingMTVScrollButtonOutlinePressed +00000000 ImmersiveMultitaskingMTVScrollButtonOutlineRest +FF000000 ImmersiveMultitaskingMTVScrollButtonPlateDisabled +FF000000 ImmersiveMultitaskingMTVScrollButtonPlateHotTrack +FF000000 ImmersiveMultitaskingMTVScrollButtonPlatePressed +FF000000 ImmersiveMultitaskingMTVScrollButtonPlateRest +FF171717 ImmersiveMultitaskingMTVScrollViewerBackground +00000000 ImmersiveMultitaskingMTVScrollViewerOutline +FFFFFFFF ImmersiveMultitaskingMTVSwitchItemTitle +FF000000 ImmersiveMultitaskingMTVThumbnailFocusInnerBorder +FFFFFFFF ImmersiveMultitaskingMTVThumbnailFocusOuterBorder +FF000000 ImmersiveMultitaskingMTVThumbnailHotTrackInnerBorder +FFFFFFFF ImmersiveMultitaskingMTVThumbnailHotTrackOuterBorder +FF000000 ImmersiveMultitaskingMTVThumbnailInnerBorder +FF000000 ImmersiveMultitaskingMTVVirtualDesktopBarBackground +00000000 ImmersiveMultitaskingMTVVirtualDesktopBarOutline +FF00B9FF ImmersiveMultitaskingMTVVirtualDesktopDragDrop +FFFFFFFF ImmersiveMultitaskingMTVVirtualDesktopHotTrackOuterBorder +FF000000 ImmersiveMultitaskingMTVVirtualDesktopInnerBorder +FFFFFFFF ImmersiveMultitaskingMTVVirtualDesktopTitle +FF0097D0 ImmersiveSaturatedAltTabBackground +3DFFFFFF ImmersiveSaturatedAltTabHoverRect +FFFFFFFF ImmersiveSaturatedAltTabPressedRect +FF4D4244 ImmersiveSaturatedBackButtonBar +FF0097D0 ImmersiveSaturatedBackground +FFFF3CFF ImmersiveSaturatedBackgroundDisabled +FF62A4BD ImmersiveSaturatedCommandRowDisabled +FFFFFFFF ImmersiveSaturatedCommandRowHighlight +FF17BFFF ImmersiveSaturatedCommandRowHover +FF378E4D ImmersiveSaturatedCommandRowPressed +FF00B9FF ImmersiveSaturatedCommandRowRest +FFFF00FF ImmersiveSaturatedControlLink +FFFF00FF ImmersiveSaturatedControlLinkBackgroundPressed +FFFF00FF ImmersiveSaturatedControlLinkDisabled +FFFF00FF ImmersiveSaturatedControlLinkForegroundPressed +FFFF00FF ImmersiveSaturatedControlLinkMouseHover +FFFF00FF ImmersiveSaturatedControlLinkPressed +FFFF00FF ImmersiveSaturatedControlLinkVisited +FF000000 ImmersiveSaturatedDefaultDarkFocusRect +FFFFFFFF ImmersiveSaturatedDefaultLightFocusRect +FFF1F1F1 ImmersiveSaturatedDesktopToastBackground +FF80ABBB ImmersiveSaturatedDisabledText +3DFFFFFF ImmersiveSaturatedDivider +FFFFFFFF ImmersiveSaturatedFocusRect +FF000000 ImmersiveSaturatedFocusRectDark +FF007CAC ImmersiveSaturatedFolderBackground +FFB7EBFF ImmersiveSaturatedHighlight +FF11B5F2 ImmersiveSaturatedHoverBackground +FFFFFFFF ImmersiveSaturatedHoverPrimaryText +FFE6EFF2 ImmersiveSaturatedHoverSecondaryText +FF00FFFF ImmersiveSaturatedInlineErrorText +FFFFFFFF ImmersiveSaturatedPrimaryText +99FFFFFF ImmersiveSaturatedSearchHighlight +99FFFFFF ImmersiveSaturatedSearchSecondaryText +FFBFD5DD ImmersiveSaturatedSecondaryText +66FFFFFF ImmersiveSaturatedSecondaryTextDisabledTransparent +B2FFFFFF ImmersiveSaturatedSecondaryTextTransparent +FF00B9FF ImmersiveSaturatedSelectionBackground +FF35BEF2 ImmersiveSaturatedSelectionHoverBackground +FFFFFFFF ImmersiveSaturatedSelectionHoverPrimaryText +FFFFFFFF ImmersiveSaturatedSelectionHoverSecondaryText +FFFFFFFF ImmersiveSaturatedSelectionPrimaryText +FFBCE9FA ImmersiveSaturatedSelectionSecondaryText +00FFFFFF ImmersiveSaturatedSettingCharmSystemPaneButtonDisabled +21FFFFFF ImmersiveSaturatedSettingCharmSystemPaneButtonHover +3EFFFFFF ImmersiveSaturatedSettingCharmSystemPaneButtonPressed +00FFFFFF ImmersiveSaturatedSettingCharmSystemPaneButtonRest +3EFFFFFF ImmersiveSaturatedSettingCharmSystemPaneButtonSelected +CCFFFFFF ImmersiveSaturatedSettingCharmSystemPaneButtonText +CCFFFFFF ImmersiveSaturatedSettingCharmSystemPaneButtonTextDisabled +CCFFFFFF ImmersiveSaturatedSettingCharmSystemPaneButtonTextHover +CCFFFFFF ImmersiveSaturatedSettingCharmSystemPaneButtonTextPressed +CCFFFFFF ImmersiveSaturatedSettingCharmSystemPaneButtonTextSelected +FF00B9FF ImmersiveSaturatedSettingsCharmLinkHover +FF11B5F2 ImmersiveSaturatedSuggestionTilesBackground +FF0097D0 ImmersiveSaturatedSystemToastBackground +33000000 ImmersiveSaturatedThumbnailPlaceholder +FF000000 ImmersiveSaturatedWebWizardIndex +FF0097D0 ImmersiveStartAllAppsDivider +FF007CAC ImmersiveStartAPVBackground +FFD0F2FF ImmersiveStartAPVHeaderText +FFFFFF57 ImmersiveStartAPVNewAppText +FF0097D0 ImmersiveStartAPVSemanticZoomTileBackground +FF0088BB ImmersiveStartBackground +FFEE1EFF ImmersiveStartBackgroundDisabled +FF00B9FF ImmersiveStartCmdBarBackground +FF35BEF2 ImmersiveStartCmdBarButtonFillLayerHover +FFFFFFFF ImmersiveStartCmdBarButtonFillLayerPressed +FF00B9FF ImmersiveStartCmdBarButtonFillLayerRest +FFFFFFFF ImmersiveStartCmdBarButtonGlyphLayerHover +FF00B9FF ImmersiveStartCmdBarButtonGlyphLayerPressed +FFFFFFFF ImmersiveStartCmdBarButtonGlyphLayerRest +FFFFFFFF ImmersiveStartCmdBarButtonOutlineLayerHover +FFFFFFFF ImmersiveStartCmdBarButtonOutlineLayerPressed +FFFFFFFF ImmersiveStartCmdBarButtonOutlineLayerRest +FF80ABBB ImmersiveStartCommandRowDisabled +FFFFFFFF ImmersiveStartCommandRowHighlight +FFD2E2E8 ImmersiveStartCommandRowHover +FFFFFFFF ImmersiveStartCommandRowPressed +FFB1CCD6 ImmersiveStartCommandRowRest +FFFF00FF ImmersiveStartControlLink +FFFF00FF ImmersiveStartControlLinkBackgroundPressed +FFFF00FF ImmersiveStartControlLinkDisabled +FFFF00FF ImmersiveStartControlLinkForegroundPressed +FFFF00FF ImmersiveStartControlLinkMouseHover +FFFF00FF ImmersiveStartControlLinkPressed +FFFF00FF ImmersiveStartControlLinkVisited +FFFFFFFF ImmersiveStartDarkTileInstallProgressFill +66FFFFFF ImmersiveStartDarkTileInstallProgressTrack +FF000000 ImmersiveStartDefaultDarkFocusRect +FFFFFFFF ImmersiveStartDefaultLightFocusRect +FFB41746 ImmersiveStartDesktopAppBackground +CCFFFFFF ImmersiveStartDesktopBackgroundTattooAllAppsDivider +FF9B9B9B ImmersiveStartDesktopBackgroundTattooSecondaryText +FF575757 ImmersiveStartDesktopBackgroundTattooStartPromptBackgroundHover +FF474747 ImmersiveStartDesktopBackgroundTattooStartPromptBackgroundRest +FF000000 ImmersiveStartDesktopBackgroundTattooTileDim +FF555555 ImmersiveStartDesktopBackgroundTattooViewSwitchButtonHover +FF3A3A3A ImmersiveStartDesktopBackgroundTattooViewSwitchButtonRest +FF0097D0 ImmersiveStartDesktopTilesBackground +FFD5F3FF ImmersiveStartDesktopTilesText +FF80ABBB ImmersiveStartDisabledText +FFFFFFFF ImmersiveStartFocusRect +FF007CAC ImmersiveStartFolderBackground +FFCBD8DC ImmersiveStartGroupNameHeader +FFB7EBFF ImmersiveStartHighlight +FF0CA7E2 ImmersiveStartHoverBackground +FFFFFFFF ImmersiveStartHoverPrimaryText +FFE3EDF0 ImmersiveStartHoverSecondaryText +FF00FFFF ImmersiveStartInlineErrorText +FF000000 ImmersiveStartLightTileInstallProgressFill +33000000 ImmersiveStartLightTileInstallProgressTrack +FFFFFFFF ImmersiveStartPrimaryText +FFCCCCCC ImmersiveStartRoundButtonHover +FF666666 ImmersiveStartRoundButtonPressed +FFFFFFFF ImmersiveStartRoundButtonRest +FFB1CCD6 ImmersiveStartSecondaryText +FF00B9FF ImmersiveStartSelectionBackground +FF35BEF2 ImmersiveStartSelectionHoverBackground +FFFFFFFF ImmersiveStartSelectionHoverPrimaryText +FFFFFFFF ImmersiveStartSelectionHoverSecondaryText +FFFFFFFF ImmersiveStartSelectionPrimaryText +FFBCE9FA ImmersiveStartSelectionSecondaryText +FF35BEF2 ImmersiveStartSystemTilesBackground +FF80ABBB ImmersiveStartThumbnailPlaceholder +FF00B9FF ImmersiveSystemAccent +FF0089BA ImmersiveSystemAccentDark1 +FF005E80 ImmersiveSystemAccentDark2 +FF00384D ImmersiveSystemAccentDark3 +FF5CD3FF ImmersiveSystemAccentLight1 +FF8CE0FF ImmersiveSystemAccentLight2 +FFA8E8FF ImmersiveSystemAccentLight3 +FF000000 ImmersiveSystemBackground +FF000000 ImmersiveSystemBackgroundDarkTheme +FFFFFFFF ImmersiveSystemBackgroundLightTheme +FFFFFFFF ImmersiveSystemText +FFFFFFFF ImmersiveSystemTextDarkTheme +FF000000 ImmersiveSystemTextLightTheme +66626262 ImmersiveTabletModeDragJointDividerBackground +FF21170F ImmersiveTabletModePPIJointDividerBackground \ No newline at end of file diff --git a/EarTrumpet/EarTrumpet.csproj b/EarTrumpet/EarTrumpet.csproj new file mode 100644 index 000000000..d0d598a7f --- /dev/null +++ b/EarTrumpet/EarTrumpet.csproj @@ -0,0 +1,114 @@ + + + + + Debug + AnyCPU + {BA3C7B42-84B0-468C-8640-217E2A24CF81} + WinExe + Properties + EarTrumpet + EarTrumpet + v4.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + Application.ico + + + true + ..\Build\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + true + 4 + + + true + + + ..\Build\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + + + Code + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EarTrumpet/EarTrumpet.iss b/EarTrumpet/EarTrumpet.iss new file mode 100644 index 000000000..d769ac21b --- /dev/null +++ b/EarTrumpet/EarTrumpet.iss @@ -0,0 +1,37 @@ +#define AppVer GetFileVersion('..\Build\Release\EarTrumpet.exe') + +[Setup] +AppName=Ear Trumpet +AppVersion={#AppVer} +VersionInfoVersion={#AppVer} +DefaultDirName={pf}\Ear Trumpet +DefaultGroupName=Ear Trumpet +SetupIconFile=..\..\EarTrumpet\Application.ico +UninstallDisplayIcon={app}\EarTrumpet.exe +UninstallDisplayName=Ear Trumpet +Compression=lzma2 +SolidCompression=yes +OutputDir=..\Setup +OutputBaseFilename=Ear Trumpet Setup +SourceDir=..\Build\Release +DisableProgramGroupPage=yes +AllowNetworkDrive=no +AllowUNCPath=no +DisableReadyPage=yes +DisableStartupPrompt=yes +DisableWelcomePage=yes + +[Files] +Source: "EarTrumpet.exe"; DestDir: "{app}"; Flags: replacesameversion +Source: "EarTrumpet.exe.config"; DestDir: "{app}"; Flags: replacesameversion +Source: "EarTrumpet.Interop.dll"; DestDir: "{app}"; Flags: replacesameversion +Source: "..\Redists\vcredist_x86.exe"; DestDir: "{tmp}"; + +[Icons] +Name: "{commonstartmenu}\Ear Trumpet"; Filename: "{app}\EarTrumpet.exe" +Name: "{commonstartup}\Ear Trumpet"; Filename: "{app}\EarTrumpet.exe" + +[Run] +Filename: "{tmp}\vcredist_x86.exe"; Parameters: "/install /passive /norestart"; StatusMsg: Installing VC++ 2013 runtime... +Filename: "{app}\EarTrumpet.exe"; Description: "Run Ear Trumpet"; Flags: "postinstall nowait runasoriginaluser" + diff --git a/EarTrumpet/Extensions/BlurWindowExtensions.cs b/EarTrumpet/Extensions/BlurWindowExtensions.cs new file mode 100644 index 000000000..8abf8d996 --- /dev/null +++ b/EarTrumpet/Extensions/BlurWindowExtensions.cs @@ -0,0 +1,86 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Interop; + +namespace EarTrumpet.Extensions +{ + static class BlurWindowExtensions + { + static class Interop + { + [DllImport("user32.dll")] + internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttribData data); + + [StructLayout(LayoutKind.Sequential)] + internal struct WindowCompositionAttribData + { + public WindowCompositionAttribute Attribute; + public IntPtr Data; + public int SizeOfData; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct AccentPolicy + { + public AccentState AccentState; + public int AccentFlags; + public int GradientColor; + public int AnimationId; + } + + internal enum WindowCompositionAttribute + { + // ... + WCA_ACCENT_POLICY = 19 + // ... + } + + internal enum AccentState + { + ACCENT_DISABLED = 0, + ACCENT_ENABLE_GRADIENT = 1, + ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, + ACCENT_ENABLE_BLURBEHIND = 3, + ACCENT_INVALID_STATE = 4 + } + } + + public static void EnableBlur(this Window window) + { + if (SystemParameters.HighContrast) + { + return; // Blur is not useful in high contrast mode + } + + SetAccentPolicy(window, Interop.AccentState.ACCENT_ENABLE_BLURBEHIND); + } + + public static void DisableBlur(this Window window) + { + SetAccentPolicy(window, Interop.AccentState.ACCENT_DISABLED); + } + + private static void SetAccentPolicy(Window window, Interop.AccentState accentState) + { + var windowHelper = new WindowInteropHelper(window); + + var accent = new Interop.AccentPolicy(); + accent.AccentState = accentState; + + var accentStructSize = Marshal.SizeOf(accent); + + var accentPtr = Marshal.AllocHGlobal(accentStructSize); + Marshal.StructureToPtr(accent, accentPtr, false); + + var data = new Interop.WindowCompositionAttribData(); + data.Attribute = Interop.WindowCompositionAttribute.WCA_ACCENT_POLICY; + data.SizeOfData = accentStructSize; + data.Data = accentPtr; + + Interop.SetWindowCompositionAttribute(windowHelper.Handle, ref data); + + Marshal.FreeHGlobal(accentPtr); + } + } +} diff --git a/EarTrumpet/Extensions/CollectionExtensions.cs b/EarTrumpet/Extensions/CollectionExtensions.cs new file mode 100644 index 000000000..bca88b6cb --- /dev/null +++ b/EarTrumpet/Extensions/CollectionExtensions.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace EarTrumpet.Extensions +{ + public static class CollectionExtensions + { + public static void AddRange(this ICollection destination, IEnumerable source) + { + foreach (T item in source) + { + destination.Add(item); + } + } + + public static void AddSorted(this ObservableCollection collection, T item, IComparer comparer) + { + int i = 0; + while ((i < collection.Count) && (comparer.Compare(collection[i], item) < 0)) + { + i++; + } + + collection.Insert(i, item); + } + } +} diff --git a/EarTrumpet/Extensions/IconExtensions.cs b/EarTrumpet/Extensions/IconExtensions.cs new file mode 100644 index 000000000..f38520770 --- /dev/null +++ b/EarTrumpet/Extensions/IconExtensions.cs @@ -0,0 +1,46 @@ +using System; +using System.Diagnostics; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace EarTrumpet.Extensions +{ + public static class IconExtensions + { + [DllImport("gdi32.dll")] + private static extern bool DeleteObject(IntPtr hObject); + + [DllImport("shell32.dll")] + private static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex); + + [DllImport("user32.dll")] + private static extern bool DestroyIcon(IntPtr hIcon); + + public static ImageSource ToImageSource(this Icon icon) + { + Bitmap bitmap = icon.ToBitmap(); + IntPtr hBitmap = bitmap.GetHbitmap(); + + ImageSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap( + hBitmap, + IntPtr.Zero, + Int32Rect.Empty, + BitmapSizeOptions.FromEmptyOptions()); + + DeleteObject(hBitmap); + return bitmapSource; + } + + public static ImageSource ExtractIconFromDll(this string path) + { + var iconPtr = ExtractIcon(Process.GetCurrentProcess().Handle, path, 0); + var image = Imaging.CreateBitmapSourceFromHIcon(iconPtr, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); + DestroyIcon(iconPtr); + return image; + } + } +} diff --git a/EarTrumpet/Extensions/SliderExtensions.cs b/EarTrumpet/Extensions/SliderExtensions.cs new file mode 100644 index 000000000..d9bfa31db --- /dev/null +++ b/EarTrumpet/Extensions/SliderExtensions.cs @@ -0,0 +1,15 @@ +using System.Windows; +using System.Windows.Controls; + +namespace EarTrumpet.Extensions +{ + public static class SliderExtensions + { + public static void SetPositionByControlPoint(this Slider slider, Point point) + { + var percent = point.X / slider.ActualWidth; + var newValue = (slider.Maximum - slider.Minimum) * percent; + slider.Value = (newValue > slider.Maximum ? slider.Maximum : (newValue < slider.Minimum ? slider.Minimum : newValue)); + } + } +} diff --git a/EarTrumpet/Extensions/WindowExtensions.cs b/EarTrumpet/Extensions/WindowExtensions.cs new file mode 100644 index 000000000..7dfc191f0 --- /dev/null +++ b/EarTrumpet/Extensions/WindowExtensions.cs @@ -0,0 +1,54 @@ +using EarTrumpet.Services; +using System; +using System.Windows; +using System.Windows.Media.Animation; + +namespace EarTrumpet.Extensions +{ + internal static class WindowExtensions + { + public static void HideWithAnimation(this Window window) + { + TimeSpan slidetime = TimeSpan.FromSeconds(0.2); + DoubleAnimation topAnimation = new DoubleAnimation(); + topAnimation.Duration = new Duration(slidetime); + topAnimation.From = window.Top; + topAnimation.To = window.Top + 10; + topAnimation.FillBehavior = FillBehavior.Stop; + var easing = new QuinticEase(); + easing.EasingMode = EasingMode.EaseIn; + topAnimation.EasingFunction = easing; + topAnimation.Completed += (s, e) => + { + window.Visibility = Visibility.Hidden; + }; + window.BeginAnimation(Window.TopProperty, topAnimation); + } + + public static void ShowwithAnimation(this Window window) + { + window.Visibility = Visibility.Visible; + window.Topmost = false; + TimeSpan slidetime = TimeSpan.FromSeconds(0.3); + DoubleAnimation bottomAnimation = new DoubleAnimation(); + bottomAnimation.Duration = new Duration(slidetime); + double top = window.Top; + bottomAnimation.From = window.Top + 25; + bottomAnimation.To = window.Top; + bottomAnimation.FillBehavior = FillBehavior.Stop; + bottomAnimation.Completed += (s, e) => + { + window.Topmost = true; + // Set the final position again. This covers a case where frames are dropped. + // and the window ends up over the taskbar instead. + window.Top = top; + window.Activate(); + window.Focus(); + }; + var easing = new QuinticEase(); + easing.EasingMode = EasingMode.EaseOut; + bottomAnimation.EasingFunction = easing; + window.BeginAnimation(Window.TopProperty, bottomAnimation); + } + } +} diff --git a/EarTrumpet/MainWindow.xaml b/EarTrumpet/MainWindow.xaml new file mode 100644 index 000000000..3e7919fd6 --- /dev/null +++ b/EarTrumpet/MainWindow.xaml @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EarTrumpet/MainWindow.xaml.cs b/EarTrumpet/MainWindow.xaml.cs new file mode 100644 index 000000000..0be6dafe5 --- /dev/null +++ b/EarTrumpet/MainWindow.xaml.cs @@ -0,0 +1,155 @@ +using EarTrumpet.Extensions; +using EarTrumpet.Services; +using EarTrumpet.ViewModels; +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +namespace EarTrumpet +{ + public partial class MainWindow : Window + { + private readonly AudioMixerViewModel _viewModel; + + private readonly TrayIcon _trayIcon; + + public MainWindow() + { + InitializeComponent(); + + _viewModel = new AudioMixerViewModel(); + _trayIcon = new TrayIcon(); + _trayIcon.Invoked += TrayIcon_Invoked; + + DataContext = _viewModel; + + // Move keyboard focus to the first element. Disabled this since it is ugly but not sure invisible + // visuals are preferrable. + // Activated += (s,e) => MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); + + SourceInitialized += (s, e) => UpdateTheme(); + } + + void TrayIcon_Invoked() + { + if (this.Visibility == Visibility.Visible) + { + this.HideWithAnimation(); + } + else + { + _viewModel.Refresh(); + UpdateTheme(); + UpdateWindowPosition(); + this.ShowwithAnimation(); + } + } + + private void Window_Deactivated(object sender, EventArgs e) + { + this.HideWithAnimation(); + } + + private void Window_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) + { + if (e.Key == System.Windows.Input.Key.Escape) + { + this.HideWithAnimation(); + } + } + + private void Slider_TouchDown(object sender, TouchEventArgs e) + { + VisualStateManager.GoToState((FrameworkElement)sender, "Pressed", true); + + var slider = (Slider)sender; + slider.SetPositionByControlPoint(e.GetTouchPoint(slider).Position); + slider.CaptureTouch(e.TouchDevice); + e.Handled = true; + } + + private void Slider_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) + { + if (e.LeftButton == MouseButtonState.Pressed) + { + VisualStateManager.GoToState((FrameworkElement)sender, "Pressed", true); + + var slider = (Slider)sender; + slider.SetPositionByControlPoint(e.GetPosition(slider)); + slider.CaptureMouse(); + e.Handled = true; + } + } + + private void Slider_TouchUp(object sender, TouchEventArgs e) + { + VisualStateManager.GoToState((FrameworkElement)sender, "Normal", true); + + var slider = (Slider)sender; + slider.ReleaseTouchCapture(e.TouchDevice); + e.Handled = true; + } + + private void Slider_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) + { + var slider = (Slider)sender; + if (slider.IsMouseCaptured) + { + // If the point is outside of the control, clear the hover state. + Rect rcSlider = new Rect(0, 0, slider.ActualWidth, slider.ActualHeight); + if (!rcSlider.Contains(e.GetPosition(slider))) + { + VisualStateManager.GoToState((FrameworkElement)sender, "Normal", true); + } + + ((Slider)sender).ReleaseMouseCapture(); + e.Handled = true; + } + } + + private void Slider_TouchMove(object sender, TouchEventArgs e) + { + var slider = (Slider)sender; + if (slider.AreAnyTouchesCaptured) + { + slider.SetPositionByControlPoint(e.GetTouchPoint(slider).Position); + e.Handled = true; + } + } + + private void Slider_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) + { + var slider = (Slider)sender; + if (slider.IsMouseCaptured) + { + slider.SetPositionByControlPoint(e.GetPosition(slider)); + } + } + + private void UpdateTheme() + { + // Call UpdateTheme before UpdateWindowPosition in case sizes change with the theme. + ThemeService.UpdateThemeResources(Resources); + if (ThemeService.IsWindowTransparencyEnabled) + { + this.EnableBlur(); + } + else + { + this.DisableBlur(); + } + } + + private void UpdateWindowPosition() + { + this.LayoutRoot.UpdateLayout(); + this.LayoutRoot.Measure(new Size(Double.PositiveInfinity, this.MaxHeight)); + this.Height = this.LayoutRoot.DesiredSize.Height; + + var desktopWorkingArea = SystemParameters.WorkArea; + this.Left = desktopWorkingArea.Right - this.Width; + this.Top = desktopWorkingArea.Bottom - this.Height; + } + } +} diff --git a/EarTrumpet/Models/EarTrumpetAudioSessionModel.cs b/EarTrumpet/Models/EarTrumpetAudioSessionModel.cs new file mode 100644 index 000000000..756429cc6 --- /dev/null +++ b/EarTrumpet/Models/EarTrumpetAudioSessionModel.cs @@ -0,0 +1,20 @@ +using System; +using System.Runtime.InteropServices; + +namespace EarTrumpet.Models +{ + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public struct EarTrumpetAudioSessionModel + { + public string DisplayName; + public string IconPath; + public Guid GroupingId; + public uint SessionId; + public uint ProcessId; + public uint BackgroundColor; + public float Volume; + + [MarshalAs(UnmanagedType.I1)] + public bool IsDesktop; + } +} diff --git a/EarTrumpet/Models/EarTrumpetAudioSessionModelGroup.cs b/EarTrumpet/Models/EarTrumpetAudioSessionModelGroup.cs new file mode 100644 index 000000000..ec14e35a1 --- /dev/null +++ b/EarTrumpet/Models/EarTrumpetAudioSessionModelGroup.cs @@ -0,0 +1,14 @@ +using EarTrumpet.Models; +using System.Collections.Generic; + +namespace EarTrumpet.Models +{ + public class EarTrumpetAudioSessionModelGroup + { + public EarTrumpetAudioSessionModelGroup(IEnumerable sessions) + { + Sessions = sessions; + } + public IEnumerable Sessions { get; private set; } + } +} diff --git a/EarTrumpet/Properties/AssemblyInfo.cs b/EarTrumpet/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..d7bf04dc8 --- /dev/null +++ b/EarTrumpet/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows; + +[assembly: AssemblyTitle("Ear Trumpet")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Ear Trumpet")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: ComVisible(false)] +[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] \ No newline at end of file diff --git a/EarTrumpet/Services/AccentColorService.cs b/EarTrumpet/Services/AccentColorService.cs new file mode 100644 index 000000000..a6ecadf8b --- /dev/null +++ b/EarTrumpet/Services/AccentColorService.cs @@ -0,0 +1,51 @@ +using EarTrumpet.Extensions; +using System; +using System.Runtime.InteropServices; +using System.Windows.Media; + +namespace EarTrumpet.Services +{ + public static class AccentColorService + { + static class Interop + { + // Thanks, Quppa! -RR + + [DllImport("uxtheme.dll", EntryPoint = "#94", CharSet = CharSet.Unicode)] + internal static extern int GetImmersiveColorSetCount(); + + [DllImport("uxtheme.dll", EntryPoint = "#95", CharSet = CharSet.Unicode)] + internal static extern uint GetImmersiveColorFromColorSetEx(uint dwImmersiveColorSet, uint dwImmersiveColorType, bool bIgnoreHighContrast, uint dwHighContrastCacheMode); + + [DllImport("uxtheme.dll", EntryPoint = "#96", CharSet = CharSet.Unicode)] + internal static extern uint GetImmersiveColorTypeFromName(string name); + + [DllImport("uxtheme.dll", EntryPoint = "#98", CharSet = CharSet.Unicode)] + internal static extern uint GetImmersiveUserColorSetPreference(bool bForceCheckRegistry, bool bSkipCheckOnFail); + + [DllImport("uxtheme.dll", EntryPoint = "#100", CharSet = CharSet.Unicode)] + internal static extern IntPtr GetImmersiveColorNamedTypeByIndex(uint dwIndex); + } + + public static Color GetColorByTypeName(string name) + { + var colorSet = Interop.GetImmersiveUserColorSetPreference(false, false); + var colorType = Interop.GetImmersiveColorTypeFromName(name); + + uint rawColor = Interop.GetImmersiveColorFromColorSetEx(colorSet, colorType, false, 0); + + return FromABGR(rawColor); + } + + public static Color FromABGR(uint abgrValue) + { + byte[] colorBytes = new byte[4]; + colorBytes[0] = (byte)((0xFF000000 & abgrValue) >> 24); // A + colorBytes[1] = (byte)((0x00FF0000 & abgrValue) >> 16); // B + colorBytes[2] = (byte)((0x0000FF00 & abgrValue) >> 8); // G + colorBytes[3] = (byte)(0x000000FF & abgrValue); // R + + return Color.FromArgb(colorBytes[0], colorBytes[3], colorBytes[2], colorBytes[1]); + } + } +} diff --git a/EarTrumpet/Services/EarTrumpetAudioSessionService.cs b/EarTrumpet/Services/EarTrumpetAudioSessionService.cs new file mode 100644 index 000000000..a5fbb77c8 --- /dev/null +++ b/EarTrumpet/Services/EarTrumpetAudioSessionService.cs @@ -0,0 +1,59 @@ +using EarTrumpet.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace EarTrumpet.Services +{ + public class EarTrumpetAudioSessionService + { + static class Interop + { + [DllImport("EarTrumpet.Interop.dll")] + public static extern int RefreshAudioSessions(); + + [DllImport("EarTrumpet.Interop.dll")] + public static extern int GetAudioSessionCount(); + + [DllImport("EarTrumpet.Interop.dll")] + public static extern int GetAudioSessions(ref IntPtr sessions); + + [DllImport("EarTrumpet.Interop.dll")] + public static extern int SetAudioSessionVolume(uint sessionId, float volume); + } + + public IEnumerable GetAudioSessions() + { + Interop.RefreshAudioSessions(); + + var sessionCount = Interop.GetAudioSessionCount(); + var sessions = new List(); + + IntPtr rawSessionsPtr = IntPtr.Zero; + Interop.GetAudioSessions(ref rawSessionsPtr); + + var sizeOfAudioSessionStruct = Marshal.SizeOf(typeof(EarTrumpetAudioSessionModel)); + for(int i = 0; i < sessionCount; i++) + { + var window = new IntPtr(rawSessionsPtr.ToInt64() + (sizeOfAudioSessionStruct * i)); + + var session = (EarTrumpetAudioSessionModel)Marshal.PtrToStructure(window, typeof(EarTrumpetAudioSessionModel)); + sessions.Add(session); + } + return sessions; + } + + public IEnumerable GetAudioSessionGroups() + { + return GetAudioSessions().GroupBy( + x => x.GroupingId, + x => x, (key, result) => new EarTrumpetAudioSessionModelGroup(result.ToList())); + } + + public void SetAudioSessionVolume(uint sessionId, float volume) + { + Interop.SetAudioSessionVolume(sessionId, volume); + } + } +} diff --git a/EarTrumpet/Services/ThemeService.cs b/EarTrumpet/Services/ThemeService.cs new file mode 100644 index 000000000..65fad1b30 --- /dev/null +++ b/EarTrumpet/Services/ThemeService.cs @@ -0,0 +1,69 @@ +using System; +using System.Windows; +using System.Windows.Media; + +namespace EarTrumpet.Services +{ + public class ThemeService + { + public static bool IsWindowTransparencyEnabled + { + get + { + return !SystemParameters.HighContrast && UserSystemPreferencesService.IsTransparencyEnabled; + } + } + + public static void UpdateThemeResources(ResourceDictionary dictionary) + { + dictionary["WindowBackground"] = new SolidColorBrush(GetWindowBackgroundColor()); + + SetBrush(dictionary, "WindowForeground", "ImmersiveApplicationTextDarkTheme"); + ReplaceBrush(dictionary, "CottonSwabSliderThumb", "ImmersiveSystemAccent"); + ReplaceBrush(dictionary, "CottonSwabSliderTrackBackground", SystemParameters.HighContrast ? "ImmersiveSystemAccentLight1" : "ImmersiveControlDarkSliderTrackBackgroundRest"); + SetBrushWithOpacity(dictionary, "CottonSwabSliderTrackBackgroundHover", SystemParameters.HighContrast ? "ImmersiveSystemAccentLight1" : "ImmersiveDarkBaseMediumHigh", SystemParameters.HighContrast ? 1.0 : 0.25); + SetBrush(dictionary, "CottonSwabSliderTrackBackgroundPressed", "ImmersiveControlDarkSliderTrackBackgroundRest"); + ReplaceBrush(dictionary, "CottonSwabSliderTrackFill", "ImmersiveSystemAccentLight1"); + SetBrush(dictionary, "CottonSwabSliderThumbHover", "ImmersiveControlDarkSliderThumbHover"); + SetBrush(dictionary, "CottonSwabSliderThumbPressed", "ImmersiveControlDarkSliderThumbHover"); + } + + private static Color GetWindowBackgroundColor() + { + string resource; + if (SystemParameters.HighContrast) + { + resource = "ImmersiveApplicationBackground"; + } + else if (UserSystemPreferencesService.UseAccentColor) + { + resource = ThemeService.IsWindowTransparencyEnabled ? "ImmersiveSystemAccentDark2" : "ImmersiveSystemAccentDark1"; + } + else + { + resource = "ImmersiveDarkChromeMedium"; + } + + Color color = AccentColorService.GetColorByTypeName(resource); + color.A = (byte)(ThemeService.IsWindowTransparencyEnabled ? 190 : 255); + return color; + } + + private static void SetBrushWithOpacity(ResourceDictionary dictionary, string name, string immersiveAccentName, double opacity) + { + Color color = AccentColorService.GetColorByTypeName(immersiveAccentName); + color.A = (byte)(opacity * 255); + ((SolidColorBrush)dictionary[name]).Color = color; + } + + private static void SetBrush(ResourceDictionary dictionary, string name, string immersiveAccentName) + { + SetBrushWithOpacity(dictionary, name, immersiveAccentName, 1.0); + } + + private static void ReplaceBrush(ResourceDictionary dictionary, string name, string immersiveAccentName) + { + dictionary[name] = new SolidColorBrush(AccentColorService.GetColorByTypeName(immersiveAccentName)); + } + } +} diff --git a/EarTrumpet/Services/UserPreferencesService.cs b/EarTrumpet/Services/UserPreferencesService.cs new file mode 100644 index 000000000..9f6445171 --- /dev/null +++ b/EarTrumpet/Services/UserPreferencesService.cs @@ -0,0 +1,30 @@ +using Microsoft.Win32; +using System; +using System.Diagnostics; + +namespace EarTrumpet.Services +{ + public static class UserPreferencesService + { + public static bool ShowDesktopApps + { + get + { + try + { + return 1 == (int)Registry.CurrentUser.CreateSubKey(@"Software\EarTrumpet").GetValue("ShowDesktopApps"); + } + catch (Exception e) + { + Debug.WriteLine("Failed to get ShowDektopApps: " + e.Message); + return false; + } + } + + set + { + Registry.CurrentUser.CreateSubKey(@"Software\EarTrumpet").SetValue("ShowDesktopApps", value ? 1 : 0); + } + } + } +} diff --git a/EarTrumpet/Services/UserSystemPreferencesService.cs b/EarTrumpet/Services/UserSystemPreferencesService.cs new file mode 100644 index 000000000..bf969f2f4 --- /dev/null +++ b/EarTrumpet/Services/UserSystemPreferencesService.cs @@ -0,0 +1,29 @@ +using Microsoft.Win32; + +namespace EarTrumpet.Services +{ + public static class UserSystemPreferencesService + { + public static bool IsTransparencyEnabled + { + get + { + using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)) + { + return (int)baseKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize").GetValue("EnableTransparency", 0) > 0; + } + } + } + + public static bool UseAccentColor + { + get + { + using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)) + { + return (int)baseKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize").GetValue("ColorPrevalence", 0) > 0; + } + } + } + } +} diff --git a/EarTrumpet/Tray.ico b/EarTrumpet/Tray.ico new file mode 100644 index 000000000..b7f3c4f1e Binary files /dev/null and b/EarTrumpet/Tray.ico differ diff --git a/EarTrumpet/TrayIcon.cs b/EarTrumpet/TrayIcon.cs new file mode 100644 index 000000000..88f6c233d --- /dev/null +++ b/EarTrumpet/TrayIcon.cs @@ -0,0 +1,65 @@ +using EarTrumpet.Services; +using System; +using System.Reflection; +using System.Windows; + +namespace EarTrumpet +{ + class TrayIcon + { + public event Action Invoked = delegate { }; + + private readonly System.Windows.Forms.NotifyIcon _trayIcon; + + public TrayIcon() + { + _trayIcon = new System.Windows.Forms.NotifyIcon(); + _trayIcon.ContextMenu = new System.Windows.Forms.ContextMenu(); + + _trayIcon.ContextMenu.MenuItems.Add("&About Ear Trumpet..."); + _trayIcon.ContextMenu.MenuItems[0].Click += About_Click; + + _trayIcon.ContextMenu.MenuItems.Add("&Show Desktop Apps"); + _trayIcon.ContextMenu.MenuItems[1].Checked = UserPreferencesService.ShowDesktopApps; + _trayIcon.ContextMenu.MenuItems[1].Click += ShowDesktopApps_Click; + + _trayIcon.ContextMenu.MenuItems.Add("-"); + + _trayIcon.ContextMenu.MenuItems.Add("E&xit"); + _trayIcon.ContextMenu.MenuItems[3].Click += Exit_Click; + + _trayIcon.MouseClick += TrayIcon_MouseClick; + _trayIcon.Icon = new System.Drawing.Icon(Application.GetResourceStream(new Uri("pack://application:,,,/EarTrumpet;component/Tray.ico")).Stream); + _trayIcon.Text = "Ear Trumpet - Volume Control for Windows"; + _trayIcon.Visible = true; + } + + void TrayIcon_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) + { + if (e.Button == System.Windows.Forms.MouseButtons.Left) + { + Invoked.Invoke(); + } + } + + void About_Click(object sender, EventArgs e) + { + var version = Assembly.GetEntryAssembly().GetName().Version; + MessageBox.Show(String.Concat("Ear Trumpet\n", version, "\n\nUpdates and source at http://github.com/File-New-Project/EarTrumpet"), "Ear Trumpet", MessageBoxButton.OK, MessageBoxImage.Information); + } + + void ShowDesktopApps_Click(object sender, EventArgs e) + { + var menuItem = (System.Windows.Forms.MenuItem)sender; + menuItem.Checked = !menuItem.Checked; + UserPreferencesService.ShowDesktopApps = menuItem.Checked; + } + + void Exit_Click(object sender, EventArgs e) + { + _trayIcon.Visible = false; + _trayIcon.Dispose(); + Application.Current.Shutdown(); + } + } +} diff --git a/EarTrumpet/ViewModels/AppItemViewModel.cs b/EarTrumpet/ViewModels/AppItemViewModel.cs new file mode 100644 index 000000000..270332c7d --- /dev/null +++ b/EarTrumpet/ViewModels/AppItemViewModel.cs @@ -0,0 +1,119 @@ +using EarTrumpet.Extensions; +using EarTrumpet.Models; +using EarTrumpet.Services; +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace EarTrumpet.ViewModels +{ + public class AppItemViewModel : BindableBase + { + private readonly IAudioMixerViewModelCallback _callback; + private EarTrumpetAudioSessionModelGroup _sessions; + + public string DisplayName { get; set; } + public uint SessionId { get; set; } + public ImageSource Icon { get; set; } + public double IconHeight { get; set; } + public double IconWidth { get; set; } + + private int _volume = 0; + public int Volume + { + get + { + return _volume; + } + set + { + if (_volume != value) + { + _volume = value; + + foreach (var session in _sessions.Sessions) + { + _callback.SetVolume(session, (float)_volume / 100.0f); + } + RaisePropertyChanged("Volume"); + } + } + } + public Color Background { get; set; } + public bool IsDesktop { get; set; } + + public AppItemViewModel(IAudioMixerViewModelCallback callback, EarTrumpetAudioSessionModelGroup sessions) + { + _sessions = sessions; + // select a session at random as sndvol does. + var session = _sessions.Sessions.First(); + + IconHeight = IconWidth = 32; + SessionId = session.SessionId; + DisplayName = session.DisplayName; + IsDesktop = session.IsDesktop; + + _volume = Convert.ToInt32(Math.Round((session.Volume * 100), + MidpointRounding.AwayFromZero)); + _callback = callback; + + if (session.IsDesktop) + { + try + { + if (Path.GetExtension(session.IconPath) == ".dll") + { + Icon = IconExtensions.ExtractIconFromDll(session.IconPath); + } + else + { + Icon = System.Drawing.Icon.ExtractAssociatedIcon(session.IconPath).ToImageSource(); + } + } + catch { } + + Background = Colors.Transparent; + + try + { + var proc = Process.GetProcessById((int)session.ProcessId); + if (!string.IsNullOrWhiteSpace(proc.MainWindowTitle)) + { + DisplayName = proc.MainWindowTitle; + } + } + catch { } // we fallback to exe name if DisplayName is not set in the try above. + } + else + { + Icon = new BitmapImage(new Uri(session.IconPath)); + Background = AccentColorService.FromABGR(session.BackgroundColor); + } + } + + public void UpdateFromOther(AppItemViewModel other) + { + if (_volume != other.Volume) + { + _sessions = other._sessions; + _volume = other.Volume; + RaisePropertyChanged("Volume"); + } + } + + public bool IsSame(AppItemViewModel other) + { + foreach (var session in other._sessions.Sessions) + { + if (_sessions.Sessions.Where(x => x.SessionId == session.SessionId).Any()) + { + return true; + } + } + return false; + } + } +} diff --git a/EarTrumpet/ViewModels/AppItemViewModelComparer.cs b/EarTrumpet/ViewModels/AppItemViewModelComparer.cs new file mode 100644 index 000000000..2a910024a --- /dev/null +++ b/EarTrumpet/ViewModels/AppItemViewModelComparer.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace EarTrumpet.ViewModels +{ + public class AppItemViewModelComparer : IComparer + { + public static AppItemViewModelComparer Instance = new AppItemViewModelComparer(); + + public int Compare(AppItemViewModel one, AppItemViewModel two) + { + return one.DisplayName.CompareTo(two.DisplayName); + } + } +} diff --git a/EarTrumpet/ViewModels/AudioMixerViewModel.cs b/EarTrumpet/ViewModels/AudioMixerViewModel.cs new file mode 100644 index 000000000..07d1dfd71 --- /dev/null +++ b/EarTrumpet/ViewModels/AudioMixerViewModel.cs @@ -0,0 +1,91 @@ +using EarTrumpet.Extensions; +using EarTrumpet.Models; +using EarTrumpet.Services; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Windows; + +namespace EarTrumpet.ViewModels +{ + public class AudioMixerViewModel : BindableBase + { + // This encapsulates the functionality used for AppItemViewModels to call back to AudioMixerViewModel + // and thus interact with the audio session service. + public class AudioMixerViewModelCallbackProxy : IAudioMixerViewModelCallback + { + private readonly EarTrumpetAudioSessionService _service; + public AudioMixerViewModelCallbackProxy(EarTrumpetAudioSessionService service) + { + _service = service; + } + + // IAudioMixerViewModelCallback + public void SetVolume(EarTrumpetAudioSessionModel item, float volume) + { + _service.SetAudioSessionVolume(item.SessionId, volume); + } + } + + public ObservableCollection Apps { get; private set; } + + public Visibility ListVisibility { get; private set; } + public Visibility NoAppsPaneVisibility { get; private set; } + + private readonly EarTrumpetAudioSessionService _audioService; + private readonly AudioMixerViewModelCallbackProxy _proxy; + + public AudioMixerViewModel() + { + Apps = new ObservableCollection(); + _audioService = new EarTrumpetAudioSessionService(); + _proxy = new AudioMixerViewModelCallbackProxy(_audioService); + } + + public void Refresh() + { + bool hasApps = Apps.Count > 0; + + var sessions = _audioService.GetAudioSessionGroups().Select(x => new AppItemViewModel(_proxy, x)); + + List staleSessionsToRemove = new List(); + + // remove stale apps + foreach (var app in Apps) + { + if (!sessions.Where(x => (x.IsSame(app) && (!app.IsDesktop || UserPreferencesService.ShowDesktopApps))).Any()) + { + staleSessionsToRemove.Add(app); + } + } + foreach (var app in staleSessionsToRemove) { Apps.Remove(app); } + + // add new apps + foreach (var session in sessions) + { + var findApp = Apps.Where(x => x.IsSame(session)).FirstOrDefault(); + if (findApp == null) + { + if (!session.IsDesktop || UserPreferencesService.ShowDesktopApps) + { + Apps.AddSorted(session, AppItemViewModelComparer.Instance); + } + } + else + { + // update existing apps + findApp.UpdateFromOther(session); + } + } + + ListVisibility = Apps.Count > 0 ? Visibility.Visible : Visibility.Hidden; + NoAppsPaneVisibility = Apps.Count == 0 ? Visibility.Visible : Visibility.Hidden; + + if (hasApps != (Apps.Count > 0)) + { + RaisePropertyChanged("ListVisibility"); + RaisePropertyChanged("NoAppsPaneVisibility"); + } + } + } +} diff --git a/EarTrumpet/ViewModels/BindableBase.cs b/EarTrumpet/ViewModels/BindableBase.cs new file mode 100644 index 000000000..d9efd5cc1 --- /dev/null +++ b/EarTrumpet/ViewModels/BindableBase.cs @@ -0,0 +1,14 @@ +using System.ComponentModel; + +namespace EarTrumpet.ViewModels +{ + public class BindableBase : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged = delegate { }; + + protected void RaisePropertyChanged(string name) + { + PropertyChanged(this, new PropertyChangedEventArgs(name)); + } + } +} diff --git a/EarTrumpet/ViewModels/IAudioMixerViewModelCallback.cs b/EarTrumpet/ViewModels/IAudioMixerViewModelCallback.cs new file mode 100644 index 000000000..203982cc1 --- /dev/null +++ b/EarTrumpet/ViewModels/IAudioMixerViewModelCallback.cs @@ -0,0 +1,10 @@ + +using EarTrumpet.Models; + +namespace EarTrumpet.ViewModels +{ + public interface IAudioMixerViewModelCallback + { + void SetVolume(EarTrumpetAudioSessionModel session, float volume); + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..ef377a931 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 David Golden + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/README.md b/README.md new file mode 100644 index 000000000..ae5654b47 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# EarTrumpet + +Icon created by Artjom Kormanfrom the Noun Project diff --git a/Resources/EarTrumpet-768-black.png b/Resources/EarTrumpet-768-black.png new file mode 100644 index 000000000..8bee0e068 Binary files /dev/null and b/Resources/EarTrumpet-768-black.png differ diff --git a/Resources/EarTrumpet-768-white.png b/Resources/EarTrumpet-768-white.png new file mode 100644 index 000000000..49c1e9efc Binary files /dev/null and b/Resources/EarTrumpet-768-white.png differ diff --git a/Resources/noun_125731_cc.svg b/Resources/noun_125731_cc.svg new file mode 100644 index 000000000..b4490b07f --- /dev/null +++ b/Resources/noun_125731_cc.svg @@ -0,0 +1 @@ +Created by Artjom Kormanfrom the Noun Project \ No newline at end of file