Add darkmode support for the settings window (#494)

This commit is contained in:
Bartosz Sosnowski
2019-10-16 10:21:44 +02:00
committed by GitHub
parent c8039828fa
commit 52b15f29ad
22 changed files with 343 additions and 59 deletions

View File

@@ -50,6 +50,10 @@ WindowsColors::Color WindowsColors::get_accent_color() {
WindowsColors::Color WindowsColors::get_background_color() {
winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::Background);
}
bool WindowsColors::is_dark_mode() {
return rgb_color(get_background_color()) == 0;
}
bool WindowsColors::update() {

View File

@@ -16,7 +16,7 @@ struct WindowsColors {
static Color get_accent_dark_1_color();
static Color get_accent_color();
static Color get_background_color();
static bool is_dark_mode();
// Update colors - returns true if the values where changed
bool update();

View File

@@ -3,11 +3,23 @@
#include "auto_start_helper.h"
#include <common/settings_helpers.h>
#include "powertoy_module.h"
#include <common/windows_colors.h>
using namespace web;
static std::wstring settings_theme;
web::json::value load_general_settings() {
return PTSettingsHelper::load_general_settings();
auto loaded = PTSettingsHelper::load_general_settings();
if (loaded.has_string_field(L"theme")) {
settings_theme = loaded.as_object()[L"theme"].as_string();
if (settings_theme != L"dark" && settings_theme != L"light") {
settings_theme = L"system";
}
} else {
settings_theme = L"system";
}
return loaded;
}
web::json::value get_general_settings() {
@@ -20,6 +32,9 @@ web::json::value get_general_settings() {
enabled.as_object()[name] = json::value::boolean(powertoy.is_enabled());
}
result.as_object()[L"enabled"] = enabled;
result.as_object()[L"theme"] = json::value::string(settings_theme);
result.as_object()[L"system_theme"] = json::value::string(WindowsColors::is_dark_mode() ? L"dark" : L"light");
return result;
}
@@ -52,6 +67,9 @@ void apply_general_settings(const json::value& general_configs) {
}
}
}
if (general_configs.has_string_field(L"theme")) {
settings_theme = general_configs.at(L"theme").as_string();
}
json::value save_settings = get_general_settings();
PTSettingsHelper::save_general_settings(save_settings);
}

View File

@@ -9,6 +9,7 @@
#include <common/two_way_pipe_message_ipc.h>
#include "tray_icon.h"
#include "general_settings.h"
#include "common/windows_colors.h"
#define BUFSIZE 1024
@@ -116,6 +117,12 @@ void run_settings_window() {
PathRemoveFileSpec(executable_path);
wcscat_s(executable_path, L"\\PowerToysSettings.exe");
WCHAR executable_args[MAX_PATH * 3];
std::wstring settings_theme_setting = get_general_settings().at(L"theme").as_string();
std::wstring settings_theme;
if (settings_theme_setting == L"dark" || (settings_theme_setting == L"system" && WindowsColors::is_dark_mode())) {
settings_theme = L" dark"; // Include arg separating space
}
// Generate unique names for the pipes, if getting a UUID is possible
std::wstring powertoys_pipe_name(L"\\\\.\\pipe\\powertoys_runner_");
std::wstring settings_pipe_name(L"\\\\.\\pipe\\powertoys_settings_");
@@ -136,6 +143,7 @@ void run_settings_window() {
// powertoys_pipe - PowerToys pipe server.
// settings_pipe - Settings pipe server.
// powertoys_pid - PowerToys process pid.
// settings_theme - pass "dark" to start the settings window in dark mode
wcscpy_s(executable_args, L"\"");
wcscat_s(executable_args, executable_path);
wcscat_s(executable_args, L"\"");
@@ -145,6 +153,7 @@ void run_settings_window() {
wcscat_s(executable_args, settings_pipe_name.c_str());
wcscat_s(executable_args, L" ");
wcscat_s(executable_args, std::to_wstring(powertoys_pid).c_str());
wcscat_s(executable_args, settings_theme.c_str());
// Run the Settings process with non-elevated privileges

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<script>
window.output_from_webview = function(arg) {
if (typeof (window.external) !== 'undefined' && ('notify' in window.external)) {
window.external.notify(arg);
}
}
function receive_from_settings_app(arg) {
window.react_app_component.receive_config_msg(JSON.parse(arg));
return '';
}
function exit_settings_app() {
window.react_app_component.receive_exit_request();
return '';
}
window.start_with_dark_theme = true;
</script>
<title>PowerToys Settings</title>
</head>
<body>
<div id="app"></div>
<script src="dist/bundle.js" charset="UTF-8"></script>
</body>
</html>

View File

@@ -1450,6 +1450,105 @@
"integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==",
"dev": true
},
"@uifabric/azure-themes": {
"version": "7.0.8",
"resolved": "https://registry.npmjs.org/@uifabric/azure-themes/-/azure-themes-7.0.8.tgz",
"integrity": "sha512-vgZn+D/oYpwtkhqPXKCYe7tTqJukjsMhoiOXhhnpHO9ad+CS/KPsY9fL4juEJ0qELTkdTvzqQeXgF4Bl+eqPrg==",
"requires": {
"@uifabric/merge-styles": "^7.5.1",
"@uifabric/set-version": "^7.0.2",
"office-ui-fabric-react": "^7.30.0",
"tslib": "^1.7.1"
},
"dependencies": {
"@uifabric/foundation": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@uifabric/foundation/-/foundation-7.4.0.tgz",
"integrity": "sha512-3XOlCPit+8JfgRcT5xlI5REE8UXpSGKRSX1vRkKwLDQx7acp1d8eJA4S51b3Addhks9QoH/rEPYJg7ExbscI4Q==",
"requires": {
"@uifabric/set-version": "^7.0.2",
"@uifabric/styling": "^7.6.2",
"@uifabric/utilities": "^7.0.9",
"tslib": "^1.7.1"
}
},
"@uifabric/icons": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.2.0.tgz",
"integrity": "sha512-CLhAhoEevbwJVaVigBfRBU0WWOjQzICEbov/fYYMBbAbjgVOpuAbSquvJHkZtlq79O1p0iCoxMeXQVVbtcnPZw==",
"requires": {
"@uifabric/set-version": "^7.0.2",
"@uifabric/styling": "^7.6.2",
"tslib": "^1.7.1"
}
},
"@uifabric/merge-styles": {
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.5.1.tgz",
"integrity": "sha512-uhgTryb8YCbnd8Q/o6H644QMqUX/nhGAK7IGgv8G1lLwUY0zMuBBFTSXa6+oGMgsLZxNQupdhkyJ5GzgDhg5Pw==",
"requires": {
"@uifabric/set-version": "^7.0.2",
"tslib": "^1.7.1"
}
},
"@uifabric/set-version": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.2.tgz",
"integrity": "sha512-3mQp7gqPOqphwX74j+N/lJEFeivKPv8ryY9QFXUxVPnrXNwpIkDW9Wk6CPqArzgGvQngRRKYD/PcyP5iuHN52A==",
"requires": {
"tslib": "^1.7.1"
}
},
"@uifabric/styling": {
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.6.2.tgz",
"integrity": "sha512-2l4N8dpHk4kHj+EKRuLrguLJcgwrXWsn3W5cbP34C9q6xrN8ShmZE3ce8TBzT1kLPtjkrUpiJXtV5qqfc/uNXg==",
"requires": {
"@microsoft/load-themed-styles": "^1.7.13",
"@uifabric/merge-styles": "^7.5.1",
"@uifabric/set-version": "^7.0.2",
"@uifabric/utilities": "^7.0.9",
"tslib": "^1.7.1"
}
},
"@uifabric/utilities": {
"version": "7.0.9",
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.0.9.tgz",
"integrity": "sha512-Q5lzCJ/KiDchhVysbI4xXiYjRiw3EQymvCXTKnmkXUo5hWRnsVPEhlWHZAXynu4gS303ZlV73bxtcQHWl80Z5Q==",
"requires": {
"@uifabric/merge-styles": "^7.5.1",
"@uifabric/set-version": "^7.0.2",
"prop-types": "^15.5.10",
"tslib": "^1.7.1"
}
},
"office-ui-fabric-react": {
"version": "7.31.2",
"resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.31.2.tgz",
"integrity": "sha512-MLZ5fdh3k4u0WvTout6aO4SRIBLEaiTj1HrLRlqO9wxEBZJ9VVgAoHOmltCY/B+SG2E2p5lo//iMp6gEu4/tsQ==",
"requires": {
"@microsoft/load-themed-styles": "^1.7.13",
"@uifabric/example-data": "^7.0.1",
"@uifabric/foundation": "^7.4.0",
"@uifabric/icons": "^7.2.0",
"@uifabric/merge-styles": "^7.5.1",
"@uifabric/set-version": "^7.0.2",
"@uifabric/styling": "^7.6.2",
"@uifabric/utilities": "^7.0.9",
"prop-types": "^15.5.10",
"tslib": "^1.7.1"
}
}
}
},
"@uifabric/example-data": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@uifabric/example-data/-/example-data-7.0.1.tgz",
"integrity": "sha512-HWw2lAbF5Fn1NhmxxEpzgWrprEsQ7+Ut71zpAHdCJoVCVeesHl03gY/obBIz8ogrufW0RIlkrNSredy6uRzYDQ==",
"requires": {
"tslib": "^1.7.1"
}
},
"@uifabric/foundation": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@uifabric/foundation/-/foundation-7.0.2.tgz",
@@ -5524,9 +5623,9 @@
"dev": true
},
"handlebars": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
"integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.2.tgz",
"integrity": "sha512-cIv17+GhL8pHHnRJzGu2wwcthL5sb8uDKBHvZ2Dtu5s1YNt0ljbzKbamnc+gr69y7bzwQiBdr5+hOpRd5pnOdg==",
"dev": true,
"requires": {
"neo-async": "^2.6.0",

View File

@@ -14,15 +14,19 @@
"scripts": {
"just": "just-scripts",
"clean": "rimraf build lib lib-commonjs && just-scripts clean",
"build": "rimraf build && just-scripts build --min --production && cp index.html build && react-snap && cp -r build/* ../settings/settings-html",
"build": "rimraf build && just-scripts build --min --production && cp *.html build && react-snap && cp -r build/* ../settings/settings-html",
"test": "just-scripts test",
"test:update": "just-scripts jest -u",
"test:start": "just-scripts start-test",
"start": "just-scripts start",
"stack:upgrade": "just-scripts upgrade-stack"
},
"reactSnap": {
"include": ["/index.html", "/index-dark.html"]
},
"dependencies": {
"@svgr/webpack": "^4.3.2",
"@uifabric/azure-themes": "^7.0.8",
"office-ui-fabric-react": "^7.4.3",
"react": "~16.8.0",
"react-dom": "~16.8.0"

View File

@@ -1,5 +1,5 @@
import React from 'react';
import {Stack, Text, Nav, DefaultButton, PrimaryButton, ScrollablePane, INavLink, Spinner, SpinnerSize, Dialog, DialogType, DialogFooter} from 'office-ui-fabric-react';
import {Stack, Text, Nav, DefaultButton, PrimaryButton, ScrollablePane, INavLink, Spinner, SpinnerSize, Dialog, DialogType, DialogFooter, getTheme} from 'office-ui-fabric-react';
import {GeneralSettings} from './GeneralSettings';
import {ModuleSettings} from './ModuleSettings';
import '../css/layout.css';
@@ -123,10 +123,10 @@ export class App extends React.Component <any, any> {
});
}
}
const theme = getTheme()
return (
<div className='body'>
<div className='sidebar'>
<div className='body' style={{stroke: theme.palette.black}}>
<div className='sidebar' style={{backgroundColor: theme.palette.neutralLighter, color: theme.palette.black}}>
<Nav
selectedKey= {this.state.selected_menu}
onLinkClick = {
@@ -146,27 +146,27 @@ export class App extends React.Component <any, any> {
styles = {{
navItems: { margin : '0'},
compositeLink: {
backgroundColor : '#f3f2f1',
color: '#323130',
backgroundColor : theme.palette.neutralLighter,
color: theme.palette.neutralPrimary,
selectors: {
'&.is-selected button' : {
backgroundColor: '#e1dfdd',
color: '#201F1E',
backgroundColor: theme.palette.neutralLight,
color: theme.palette.neutralPrimaryAlt,
fontWeight: 'bold'
},
'&:hover button.ms-Nav-link' : {
backgroundColor: '#e1dfdd',
color: '#323130'
backgroundColor: theme.palette.neutralLight,
color: theme.palette.neutralPrimary
},
'i.ms-Button-icon' : {
color: '#201F1E',
color: theme.palette.neutralPrimary,
fontWeight: 'normal'
},
'&:hover i.ms-Button-icon' : {
color: '#201F1E',
color: theme.palette.neutralPrimary,
},
'&:active i.ms-Button-icon' : {
color: '#201F1E',
color: theme.palette.neutralPrimary,
},
},
},
@@ -181,7 +181,7 @@ export class App extends React.Component <any, any> {
]}
/>
</div>
<div className='editorzone'>
<div className='editorzone' style={{backgroundColor: theme.palette.white, color: theme.palette.black}}>
<div className='editorhead'>
<div className='editortitle'>
<Text

View File

@@ -4,6 +4,7 @@ import { ChoiceGroup } from 'office-ui-fabric-react';
export class ChoiceGroupSettingsControl extends BaseSettingsControl {
choiceref:any = null; // Keeps a reference to the corresponding item in the DOM.
selected:any;
constructor(props:any) {
super(props);
@@ -17,10 +18,11 @@ export class ChoiceGroupSettingsControl extends BaseSettingsControl {
// Fully controlled component.
// Reacting to a property change so that the control is redrawn properly.
this.setState({ property_values: props.setting })
this.selected = props.setting.value;
}
public get_value() : any {
return {'value': this.choiceref.checkedOption.key};
return {'value': this.selected};
}
public render(): JSX.Element {
@@ -31,7 +33,8 @@ export class ChoiceGroupSettingsControl extends BaseSettingsControl {
options={this.state.property_values.options}
label={this.state.property_values.display_name}
componentRef={(element) => {this.choiceref=element;}}
onChange={()=>{
onChange={(ev:any, option:any)=>{
this.selected = option.key;
this.parent_on_change();
}}
/>

View File

@@ -1,11 +1,13 @@
import React from 'react';
import { Stack, Text, DefaultButton, Label, Link} from 'office-ui-fabric-react';
import {BoolToggleSettingsControl} from './BoolToggleSettingsControl'
import { Stack, Text, PrimaryButton, Label, Link, loadTheme } from 'office-ui-fabric-react';
import { BoolToggleSettingsControl } from './BoolToggleSettingsControl'
import { ChoiceGroupSettingsControl } from './ChoiceGroupSettingsControl'
import { Separator } from 'office-ui-fabric-react/lib/Separator';
export class GeneralSettings extends React.Component <any, any> {
references: any = {};
startup_reference: any;
theme_reference: any;
parent_on_change: Function;
constructor(props: any) {
super(props);
@@ -36,6 +38,7 @@ export class GeneralSettings extends React.Component <any, any> {
let result : any = {};
result[this.state.settings_key]= {
startup: this.startup_reference.get_value().value,
theme: this.theme_reference.get_value().value,
enabled: enabled
};
return result;
@@ -116,19 +119,88 @@ export class GeneralSettings extends React.Component <any, any> {
setting={{display_name: 'Start at login', value: this.state.settings.general.startup}}
on_change={this.parent_on_change}
ref={(input) => {this.startup_reference=input;}}
/>
/>
<ChoiceGroupSettingsControl
setting={{display_name: 'Chose Settings color',
value: this.state.settings.general.theme,
options: [
{ key: 'system', text: 'System default app mode'},
{ key: 'light', text: 'Light' },
{ key: 'dark', text: 'Dark' }
]}}
on_change={() => {
const dark_mode = this.theme_reference.get_value().value === 'dark' ||
(this.theme_reference.get_value().value === 'system' && this.state.settings.general.system_theme === 'dark');
if (dark_mode) {
loadTheme({
palette: {
themePrimary: '#0088e4',
themeLighterAlt: '#000509',
themeLighter: '#001624',
themeLight: '#002944',
themeTertiary: '#005288',
themeSecondary: '#0078c8',
themeDarkAlt: '#1793e6',
themeDark: '#38a3ea',
themeDarker: '#69baef',
neutralLighterAlt: '#0b0b0b',
neutralLighter: '#151515',
neutralLight: '#252525',
neutralQuaternaryAlt: '#2f2f2f',
neutralQuaternary: '#373737',
neutralTertiaryAlt: '#595959',
neutralTertiary: '#eaeaea',
neutralSecondary: '#eeeeee',
neutralPrimaryAlt: '#f1f1f1',
neutralPrimary: '#e0e0e0',
neutralDark: '#f8f8f8',
black: '#fbfbfb',
white: '#000000',
}
});
} else {
loadTheme({
palette: {
themePrimary: '#0078d4',
themeLighterAlt: '#f3f9fd',
themeLighter: '#d0e7f8',
themeLight: '#a9d3f2',
themeTertiary: '#5ca9e5',
themeSecondary: '#1a86d9',
themeDarkAlt: '#006cbe',
themeDark: '#005ba1',
themeDarker: '#004377',
neutralLighterAlt: '#f8f8f8',
neutralLighter: '#f4f4f4',
neutralLight: '#eaeaea',
neutralQuaternaryAlt: '#dadada',
neutralQuaternary: '#d0d0d0',
neutralTertiaryAlt: '#c8c8c8',
neutralTertiary: '#bab8b7',
neutralSecondary: '#a3a2a0',
neutralPrimaryAlt: '#8d8b8a',
neutralPrimary: '#323130',
neutralDark: '#605e5d',
black: '#494847',
white: '#ffffff',
}
});
}
this.parent_on_change();
}}
ref={(input) => {this.theme_reference=input;}}
/>
<Stack>
<Label>Version 0.11.0</Label>
<DefaultButton
<PrimaryButton
styles={{
root: {
backgroundColor: "#FFFFFF",
alignSelf: "start"
}
}}
href='https://github.com/microsoft/PowerToys/releases'
target='_blank'
>Check for updates</DefaultButton>
>Check for updates</PrimaryButton>
</Stack>
{/* An empty span to always give 30px padding in Edge. */}
<span/>

View File

@@ -11,7 +11,6 @@
flex-basis: 228px;
display: flex;
flex-direction: column;
background-color: #f3f2f1;
}
.body .sidebar.collapsed {

View File

@@ -1,8 +1,36 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './components/App';
import { mergeStyles } from 'office-ui-fabric-react';
import { loadTheme, mergeStyles } from 'office-ui-fabric-react';
if ((window as any).start_with_dark_theme) {
loadTheme({
palette: {
themePrimary: '#0088e4',
themeLighterAlt: '#000509',
themeLighter: '#001624',
themeLight: '#002944',
themeTertiary: '#005288',
themeSecondary: '#0078c8',
themeDarkAlt: '#1793e6',
themeDark: '#38a3ea',
themeDarker: '#69baef',
neutralLighterAlt: '#0b0b0b',
neutralLighter: '#151515',
neutralLight: '#252525',
neutralQuaternaryAlt: '#2f2f2f',
neutralQuaternary: '#373737',
neutralTertiaryAlt: '#595959',
neutralTertiary: '#eaeaea',
neutralSecondary: '#eeeeee',
neutralPrimaryAlt: '#f1f1f1',
neutralPrimary: '#e0e0e0',
neutralDark: '#f8f8f8',
black: '#fbfbfb',
white: '#000000',
}
});
}
// Inject some global styles
mergeStyles({
selectors: {

View File

@@ -3,14 +3,14 @@
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>Group 6</title>
<desc>Created with Sketch.</desc>
<g id="Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" stroke-width="1" fill-rule="evenodd">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -237.000000)">
<g id="Group-4">
<g id="Navigation-/-Left-Nav-/-Default-/-Level-2-w-Icon-/-Rest-Copy-5" transform="translate(0.000000, 224.000000)">
<g id="Group-6" transform="translate(17.000000, 13.000000)">
<rect id="Rectangle" stroke="#000000" x="0.5" y="0.5" width="14" height="14"></rect>
<circle id="Oval" fill="#000000" cx="7.5" cy="7.5" r="2.5"></circle>
<circle id="Oval" stroke="#000000" cx="7.5" cy="7.5" r="4"></circle>
<rect id="Rectangle" fill="none" x="0.5" y="0.5" width="14" height="14"></rect>
<circle id="Oval" cx="7.5" cy="7.5" r="2.5"></circle>
<circle id="Oval" fill="none" cx="7.5" cy="7.5" r="4"></circle>
</g>
</g>
</g>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -4,7 +4,7 @@
<title>Fancy zones</title>
<desc>Created with Sketch.</desc>
<g id="Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -164.000000)" stroke="#000000">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -164.000000)">
<g id="Group-4">
<g id="Navigation-/-Left-Nav-/-Default-/-Level-2-w-Icon-/-Rest-Copy-3" transform="translate(0.000000, 152.000000)">
<g id="Fancy-zones" transform="translate(17.000000, 12.000000)">

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -4,7 +4,7 @@
<title>Fancy zones</title>
<desc>Created with Sketch.</desc>
<g id="Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -128.000000)" stroke="#000000">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -128.000000)">
<g id="Group-4">
<g id="Navigation-/-Left-Nav-/-Default-/-Level-2-w-Icon-/-Rest-Copy-2" transform="translate(0.000000, 116.000000)">
<g id="Fancy-zones" transform="translate(17.000000, 12.000000)">

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -4,7 +4,7 @@
<title>maximize</title>
<desc>Created with Sketch.</desc>
<g id="Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -56.000000)" stroke="#000000">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -56.000000)">
<g id="Group-4">
<g id="Navigation-/-Left-Nav-/-Default-/-Level-2-w-Icon-/-Rest" transform="translate(0.000000, 44.000000)">
<g id="maximize" transform="translate(17.000000, 12.000000)">

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -3,8 +3,8 @@
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>Shortcut guide</title>
<desc>Created with Sketch.</desc>
<g id="Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -92.000000)" stroke="#000000">
<g id="Icons" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -92.000000)">
<g id="Group-4">
<g id="Navigation-/-Left-Nav-/-Default-/-Level-2-w-Icon-/-Rest-Copy" transform="translate(0.000000, 80.000000)">
<g id="Shortcut-guide" transform="translate(17.000000, 12.000000)">

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -4,7 +4,7 @@
<title>Terminate tool</title>
<desc>Created with Sketch.</desc>
<g id="Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -200.000000)" stroke="#000000">
<g id="X-Large-Copy-5" transform="translate(-17.000000, -200.000000)">
<g id="Group-4">
<g id="Navigation-/-Left-Nav-/-Default-/-Level-2-w-Icon-/-Rest-Copy-4" transform="translate(0.000000, 188.000000)">
<g id="Terminate-tool" transform="translate(17.000000, 12.000000)">

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -53,6 +53,9 @@ TwoWayPipeMessageIPC* g_message_pipe = nullptr;
// Set to true if waiting for webview confirmation before closing the Window.
bool g_waiting_for_close_confirmation = false;
// Is the setting window to be started in dark mode
bool g_start_in_dark_mode = false;
#ifdef _DEBUG
void NavigateToLocalhostReactServer() {
// Useful for connecting to instance running in react development server.
@@ -203,7 +206,7 @@ void receive_message_from_webview(const std::wstring& msg) {
}
}
void initialize_webview() {
void initialize_webview(int nShowCmd) {
try {
g_webview_process = WebViewControlProcess();
auto asyncwebview = g_webview_process.CreateWebViewControlAsync((int64_t)g_main_wnd, client_rect_to_bounds_rect(g_main_wnd));
@@ -222,29 +225,29 @@ void initialize_webview() {
// Open the requested link in the default browser registered in the Shell
int res = static_cast<int>(reinterpret_cast<uintptr_t>(ShellExecute(nullptr, L"open", args.Uri().AbsoluteUri().c_str(), nullptr, nullptr, SW_SHOWNORMAL)));
WINRT_VERIFY(res > 32);
});
});
g_webview.DOMContentLoaded([=](IWebViewControl sender_loaded, WebViewControlDOMContentLoadedEventArgs const& args_loaded) {
// runs when the content has been loaded.
});
g_webview.ContentLoading([=](IWebViewControl sender, WebViewControlContentLoadingEventArgs const& args) {
ShowWindow(g_main_wnd, nShowCmd);
});
g_webview.ScriptNotify([=](IWebViewControl sender_script_notify, WebViewControlScriptNotifyEventArgs const& args_script_notify) {
// content called window.external.notify()
std::wstring message_sent = args_script_notify.Value().c_str();
receive_message_from_webview(message_sent);
});
});
g_webview.AcceleratorKeyPressed([&](IWebViewControl sender, WebViewControlAcceleratorKeyPressedEventArgs const& args) {
if (args.VirtualKey() == winrt::Windows::System::VirtualKey::F4) {
// WebView swallows key-events. Detect Alt-F4 one and close the window manually.
const auto _ = g_webview.InvokeScriptAsync(hstring(L"exit_settings_app"), {});
}
});
});
resize_web_view();
#if defined(_DEBUG) && _DEBUG_WITH_LOCALHOST
// Navigates to localhost:8080
NavigateToLocalhostReactServer();
#else
// Navigates to settings-html/index.html.
NavigateToUri(L"index.html");
// Navigates to settings-html/index.html or index-dark.html
NavigateToUri(g_start_in_dark_mode ? L"index-dark.html" : L"index.html");
#endif
} else if (status == AsyncStatus::Error) {
MessageBox(NULL, L"Failed to create the WebView control.\nPlease report the bug to https://github.com/microsoft/PowerToys/issues", L"PowerToys Settings Error", MB_OK);
@@ -254,7 +257,7 @@ void initialize_webview() {
} else if (status == AsyncStatus::Canceled) {
// Ignore.
}
});
});
} catch (hresult_error const& e) {
WCHAR message[1024] = L"";
StringCchPrintf(message, ARRAYSIZE(message), L"failed: %ls", e.message().c_str());
@@ -343,7 +346,7 @@ void register_classes(HINSTANCE hInstance) {
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(APPICON));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.hbrBackground = g_start_in_dark_mode ? CreateSolidBrush(0) : (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = nullptr;
wcex.lpszClassName = L"PTSettingsClass";
wcex.hIconSm = nullptr;
@@ -395,12 +398,15 @@ void quit_when_parent_terminates(std::wstring parent_pid) {
std::thread(wait_on_parent_process_thread, pid).detach();
}
void initialize_message_pipe() {
// Parse arguments: initialize two-way IPC message pipe and if settings window is to be started
// in dark mode.
void parse_args() {
// Expected calling arguments:
// [0] - This executable's path.
// [1] - PowerToys pipe server.
// [2] - Settings pipe server.
// [3] - PowerToys process pid.
// [4] - optional "dark" parameter if the settings window is to be started in dark mode
LPWSTR *argument_list;
int n_args;
@@ -415,6 +421,9 @@ void initialize_message_pipe() {
exit(1);
#endif
}
if (n_args > 4) {
g_start_in_dark_mode = wcscmp(argument_list[4], L"dark") == 0;
}
LocalFree(argument_list);
}
@@ -429,15 +438,14 @@ int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _
}
g_hinst = hInstance;
initialize_message_pipe();
parse_args();
register_classes(hInstance);
g_main_wnd = create_main_window(hInstance);
if (g_main_wnd == nullptr) {
MessageBox(NULL, L"Failed to create main window.\nPlease report the bug to https://github.com/microsoft/PowerToys/issues", L"PowerToys Settings Error", MB_OK);
exit(1);
}
initialize_webview();
ShowWindow(g_main_wnd, nShowCmd);
initialize_webview(nShowCmd);
// Main message loop.
MSG msg;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long