diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index a21a031b39..e9f9ccc8cc 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -14,14 +14,12 @@ Acceleratorkeys
ACCEPTFILES
accessibile
accessibilityinsights
-acf
Acl
aclapi
AColumn
acos
acrt
Actioncenter
-Actionkeyword
activatable
ACTIVATEAPP
activationaction
@@ -144,10 +142,8 @@ bc
bcc
bck
Bcl
-bdaa
bddac
BEGINLABELEDIT
-benjamhooper
betadele
betsegaw
BGR
@@ -184,7 +180,6 @@ bricelam
BRIGHTGREEN
Browsable
bsd
-bsearch
BSODs
bstr
BText
@@ -439,7 +434,6 @@ DELA
deletethis
delims
DENORMAL
-deondre
depersist
deprioritized
deps
@@ -637,7 +631,6 @@ EFFE
efgh
EFile
egistry
-Elems
ELogo
elseif
Emoji
@@ -660,7 +653,6 @@ epicgames
ERASEBKGND
EREOF
EResize
-eriawan
errc
errorlevel
ERRORMESSAGE
@@ -717,9 +709,7 @@ Favicon
fcharset
fd
fda
-FDFC
feimage
-FFB
ffcd
ffd
FFDDDDDD
@@ -731,7 +721,6 @@ FILEFLAGS
FILEFLAGSMASK
FILEOP
FILEOS
-filesfolder
FILESUBTYPE
FILESYSPATH
filesystem
@@ -799,7 +788,6 @@ Giftbox
github
githubusercontent
gitignore
-globalplugins
globals
gmx
google
@@ -817,7 +805,6 @@ HACCEL
hangeul
hanja
hanselman
-happlebao
hardcoded
HARDWAREINPUT
hashcode
@@ -853,9 +840,8 @@ hitinfo
HIWORD
hk
HKCC
-HKCU
HKCR
-HKE
+HKCU
hkey
HKL
HKLM
@@ -929,6 +915,7 @@ IComparer
ICONERROR
ICONINFORMATION
ICONQUESTION
+Iconsempty
Iconset
IContext
ICONWARNING
@@ -1099,10 +1086,10 @@ ITemplate
ITEMSTATEICONCLICK
ITest
ith
-itsme
IThrottled
IThumbnail
ITrigger
+itsme
IUI
IUnknown
IUri
@@ -1122,7 +1109,6 @@ Jarryd
javascript
jfif
jgeosdfsdsgmkedfgdfgdfgbkmhcgcflmi
-jhutchings
jjw
jobject
jp
@@ -1133,7 +1119,6 @@ JPN
json
JSONOf
jsonval
-jsoref
jsx
junja
jxr
@@ -1366,7 +1351,6 @@ moz
mozilla
mpmc
mru
-msazure
msbuild
msc
msclr
@@ -1375,7 +1359,6 @@ mscorlib
msdata
msdn
msedge
-MSGBOX
mshtmdid
msi
MSIHANDLE
@@ -1438,7 +1421,7 @@ NESW
netcore
netcoreapp
netframework
-netfx
+NETFX
netsh
netstandard
Neue
@@ -1550,7 +1533,7 @@ onedrive
onedrivelogo
ONITEM
onstd
-OOBE
+oobe
opencode
opensource
Openthe
@@ -1745,7 +1728,7 @@ queryfocus
QUERYOPEN
QUEUESYNC
qwertyuiopasdfghjklzxcvbnm
-QWORD
+qword
qwrtyuiopsghjklzxvnm
Radiobuttons
RAII
@@ -1791,7 +1774,6 @@ REMAPUNSUCCESSFUL
Remotable
REMOTEDISPLAY
REMOTESESSION
-removefolder
Removelnk
renamable
RENAMEONCOLLISION
@@ -1858,8 +1840,7 @@ RUNLEVEL
runsettings
runtimeclass
runtimeconfig
-Runtimes
-Rutkas
+runtimes
rv
rvalue
rvm
@@ -1889,10 +1870,9 @@ SEARCHFOR
searchqueryhelper
SEARCHREPLACEGROUP
searchterm
-Searcn
Secur
securityoverview
-Segoe
+segoe
Sekan
SENDCHANGE
sendinput
@@ -1995,7 +1975,6 @@ SLogo
SMALLICON
SMTO
snd
-snickler
somil
SORTDOWN
SOURCECLIENTAREAONLY
@@ -2114,7 +2093,6 @@ syslog
SYSMENU
systemd
SYSTEMTIME
-systray
sz
tadele
Tahoma
@@ -2315,7 +2293,6 @@ VDId
vec
VERBSONLY
VERBW
-verifybothfolderfilesequal
verrsrc
VERSIONINFO
Versioning
@@ -2382,7 +2359,6 @@ webpage
website
webview
wekyb
-welcomeoverview
Whichdoes
whitespaces
WIC
@@ -2497,7 +2473,6 @@ XElement
XFile
XIncrement
XInstance
-XJson
xlink
XLoc
xml
@@ -2518,7 +2493,6 @@ YDiff
YESNO
YIncrement
yinwang
-YJson
YLogo
yml
YOffset
diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs
index 1fa0af4bd9..be32db0888 100644
--- a/installer/PowerToysSetup/Product.wxs
+++ b/installer/PowerToysSetup/Product.wxs
@@ -268,7 +268,10 @@
-
+
+
+
+
@@ -683,6 +686,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -778,6 +795,8 @@
+
+
diff --git a/src/common/SettingsAPI/settings_helpers.cpp b/src/common/SettingsAPI/settings_helpers.cpp
index 3bd8dd12fd..646cd1a76f 100644
--- a/src/common/SettingsAPI/settings_helpers.cpp
+++ b/src/common/SettingsAPI/settings_helpers.cpp
@@ -5,6 +5,7 @@ namespace PTSettingsHelper
{
constexpr inline const wchar_t* settings_filename = L"\\settings.json";
constexpr inline const wchar_t* log_settings_filename = L"log_settings.json";
+ constexpr inline const wchar_t* oobe_filename = L"oobe_settings.json";
std::wstring get_root_save_folder_location()
{
@@ -77,4 +78,34 @@ namespace PTSettingsHelper
result = result.append(log_settings_filename);
return result.wstring();
}
+
+ bool get_oobe_opened_state()
+ {
+ std::filesystem::path oobePath(PTSettingsHelper::get_root_save_folder_location());
+ oobePath = oobePath.append(oobe_filename);
+ if (std::filesystem::exists(oobePath))
+ {
+ auto saved_settings = json::from_file(oobePath.c_str());
+ if (!saved_settings.has_value())
+ {
+ return false;
+ }
+
+ bool opened = saved_settings->GetNamedBoolean(L"openedAtFirstLaunch", false);
+ return opened;
+ }
+
+ return false;
+ }
+
+ void save_oobe_opened_state()
+ {
+ std::filesystem::path oobePath(PTSettingsHelper::get_root_save_folder_location());
+ oobePath = oobePath.append(oobe_filename);
+
+ json::JsonObject obj;
+ obj.SetNamedValue(L"openedAtFirstLaunch", json::value(true));
+
+ json::to_file(oobePath.c_str(), obj);
+ }
}
diff --git a/src/common/SettingsAPI/settings_helpers.h b/src/common/SettingsAPI/settings_helpers.h
index 2437620f5d..6e220f70ea 100644
--- a/src/common/SettingsAPI/settings_helpers.h
+++ b/src/common/SettingsAPI/settings_helpers.h
@@ -14,4 +14,7 @@ namespace PTSettingsHelper
void save_general_settings(const json::JsonObject& settings);
json::JsonObject load_general_settings();
std::wstring get_log_settings_file_location();
+
+ bool get_oobe_opened_state();
+ void save_oobe_opened_state();
}
diff --git a/src/common/interop/interop.cpp b/src/common/interop/interop.cpp
index ab0eb2ebb1..8f682d17e9 100644
--- a/src/common/interop/interop.cpp
+++ b/src/common/interop/interop.cpp
@@ -138,5 +138,13 @@ public
static String ^ PowerLauncherSharedEvent() {
return gcnew String(CommonSharedConstants::POWER_LAUNCHER_SHARED_EVENT);
}
+
+ static String ^ ShowColorPickerSharedEvent() {
+ return gcnew String(CommonSharedConstants::SHOW_COLOR_PICKER_SHARED_EVENT);
+ }
+
+ static String ^ ShowShortcutGuideSharedEvent() {
+ return gcnew String(CommonSharedConstants::SHOW_SHORTCUT_GUIDE_SHARED_EVENT);
+ }
};
}
diff --git a/src/common/interop/shared_constants.h b/src/common/interop/shared_constants.h
index 5446057c92..c3e8b0fc71 100644
--- a/src/common/interop/shared_constants.h
+++ b/src/common/interop/shared_constants.h
@@ -13,6 +13,12 @@ namespace CommonSharedConstants
// Path to the event used by PowerLauncher
const wchar_t POWER_LAUNCHER_SHARED_EVENT[] = L"Local\\PowerToysRunInvokeEvent-30f26ad7-d36d-4c0e-ab02-68bb5ff3c4ab";
+ // Path to the event used to show Color Picker
+ const wchar_t SHOW_COLOR_PICKER_SHARED_EVENT[] = L"Local\\ShowColorPickerEvent-8c46be2a-3e05-4186-b56b-4ae986ef2525";
+
+ // Path to the event used to show Shortcut Guide
+ const wchar_t SHOW_SHORTCUT_GUIDE_SHARED_EVENT[] = L"Local\\ShowShortcutGuideEvent-6982d682-7462-404f-95af-86ae3f089c4f";
+
// Max DWORD for key code to disable keys.
const int VK_DISABLED = 0x100;
}
\ No newline at end of file
diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/NativeEventWaiter.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/NativeEventWaiter.cs
new file mode 100644
index 0000000000..e44d4d9867
--- /dev/null
+++ b/src/modules/colorPicker/ColorPickerUI/Helpers/NativeEventWaiter.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.ComponentModel.Composition;
+using System.Threading;
+using System.Windows;
+using interop;
+
+namespace ColorPicker.Helpers
+{
+ [Export(typeof(NativeEventWaiter))]
+ public class NativeEventWaiter
+ {
+ private AppStateHandler _appStateHandler;
+
+ [ImportingConstructor]
+ public NativeEventWaiter(AppStateHandler appStateHandler)
+ {
+ _appStateHandler = appStateHandler;
+ WaitForEventLoop(Constants.ShowColorPickerSharedEvent(), _appStateHandler.ShowColorPicker);
+ }
+
+ public static void WaitForEventLoop(string eventName, Action callback)
+ {
+ new Thread(() =>
+ {
+ var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
+ while (true)
+ {
+ if (eventHandle.WaitOne())
+ {
+ Logger.LogInfo("Successfully waited for SHOW_COLOR_PICKER_EVENT");
+ Application.Current.Dispatcher.Invoke(callback);
+ }
+ }
+ }).Start();
+ }
+ }
+}
diff --git a/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs b/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs
index 1bc807bf64..23bd9cc30f 100644
--- a/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs
+++ b/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs
@@ -26,6 +26,7 @@ namespace ColorPicker.ViewModels
private readonly ZoomWindowHelper _zoomWindowHelper;
private readonly AppStateHandler _appStateHandler;
private readonly IUserSettings _userSettings;
+ private readonly NativeEventWaiter _nativeEventWaiter;
///
/// Backing field for
@@ -48,11 +49,13 @@ namespace ColorPicker.ViewModels
ZoomWindowHelper zoomWindowHelper,
AppStateHandler appStateHandler,
KeyboardMonitor keyboardMonitor,
+ NativeEventWaiter nativeEventWaiter,
IUserSettings userSettings)
{
_zoomWindowHelper = zoomWindowHelper;
_appStateHandler = appStateHandler;
_userSettings = userSettings;
+ _nativeEventWaiter = nativeEventWaiter;
if (mouseInfoProvider != null)
{
diff --git a/src/modules/shortcut_guide/d2d_window.cpp b/src/modules/shortcut_guide/d2d_window.cpp
index 9eed55edd7..b1161e99a9 100644
--- a/src/modules/shortcut_guide/d2d_window.cpp
+++ b/src/modules/shortcut_guide/d2d_window.cpp
@@ -41,6 +41,7 @@ void D2DWindow::show(UINT x, UINT y, UINT width, UINT height)
on_show();
SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, 0);
ShowWindow(hwnd, SW_SHOWNORMAL);
+ SetForegroundWindow(hwnd);
UpdateWindow(hwnd);
}
diff --git a/src/modules/shortcut_guide/native_event_waiter.cpp b/src/modules/shortcut_guide/native_event_waiter.cpp
new file mode 100644
index 0000000000..b038ea4ffd
--- /dev/null
+++ b/src/modules/shortcut_guide/native_event_waiter.cpp
@@ -0,0 +1,29 @@
+#include "pch.h"
+#include "native_event_waiter.h"
+
+void NativeEventWaiter::run()
+{
+ while (!aborting)
+ {
+ auto result = WaitForSingleObject(event_handle, timeout);
+ if (!aborting && result == WAIT_OBJECT_0)
+ {
+ action();
+ }
+ }
+}
+
+NativeEventWaiter::NativeEventWaiter(const std::wstring& event_name, std::function action)
+{
+ event_handle = CreateEventW(NULL, FALSE, FALSE, event_name.c_str());
+ this->action = action;
+ running_thread = std::thread([&]() { run(); });
+}
+
+NativeEventWaiter::~NativeEventWaiter()
+{
+ aborting = true;
+ SetEvent(event_handle);
+ running_thread.join();
+ CloseHandle(event_handle);
+}
diff --git a/src/modules/shortcut_guide/native_event_waiter.h b/src/modules/shortcut_guide/native_event_waiter.h
new file mode 100644
index 0000000000..14bf1a2d0d
--- /dev/null
+++ b/src/modules/shortcut_guide/native_event_waiter.h
@@ -0,0 +1,20 @@
+#pragma once
+#include "pch.h"
+#include "common/interop/shared_constants.h"
+
+class NativeEventWaiter
+{
+ static const int timeout = 1000;
+
+ HANDLE event_handle;
+ std::function action;
+ std::atomic aborting;
+
+ void run();
+ std::thread running_thread;
+
+public:
+
+ NativeEventWaiter(const std::wstring& event_name, std::function action);
+ ~NativeEventWaiter();
+};
diff --git a/src/modules/shortcut_guide/shortcut_guide.cpp b/src/modules/shortcut_guide/shortcut_guide.cpp
index 22cc94398c..48bf07d49d 100644
--- a/src/modules/shortcut_guide/shortcut_guide.cpp
+++ b/src/modules/shortcut_guide/shortcut_guide.cpp
@@ -5,6 +5,7 @@
#include
#include
+#include
#include
#include
@@ -94,6 +95,8 @@ namespace
((style & WS_THICKFRAME) == WS_THICKFRAME);
return result;
}
+
+ const LPARAM eventActivateWindow = 1;
}
OverlayWindow::OverlayWindow()
@@ -212,6 +215,13 @@ void OverlayWindow::enable()
instance->target_state->toggle_force_shown();
return 0;
}
+
+ if (msg == WM_APP && lparam == eventActivateWindow)
+ {
+ instance->target_state->toggle_force_shown();
+ return 0;
+ }
+
if (msg != WM_HOTKEY)
{
return 0;
@@ -260,6 +270,12 @@ void OverlayWindow::enable()
}
}
RegisterHotKey(winkey_popup->get_window_handle(), alternative_switch_hotkey_id, alternative_switch_modifier_mask, alternative_switch_vk_code);
+
+ auto show_action = [&]() {
+ PostMessageW(winkey_popup->get_window_handle(), WM_APP, 0, eventActivateWindow);
+ };
+
+ event_waiter = std::make_unique(CommonSharedConstants::SHOW_SHORTCUT_GUIDE_SHARED_EVENT, show_action);
}
_enabled = true;
}
@@ -276,6 +292,7 @@ void OverlayWindow::disable(bool trace_event)
Trace::EnableShortcutGuide(false);
}
UnregisterHotKey(winkey_popup->get_window_handle(), alternative_switch_hotkey_id);
+ event_waiter.reset();
winkey_popup->hide();
target_state->exit();
target_state.reset();
diff --git a/src/modules/shortcut_guide/shortcut_guide.h b/src/modules/shortcut_guide/shortcut_guide.h
index 393bb4ec2e..88b7a37a6e 100644
--- a/src/modules/shortcut_guide/shortcut_guide.h
+++ b/src/modules/shortcut_guide/shortcut_guide.h
@@ -1,6 +1,7 @@
#pragma once
#include
#include "overlay_window.h"
+#include "native_event_waiter.h"
#include "Generated Files/resource.h"
@@ -44,6 +45,7 @@ private:
std::unique_ptr winkey_popup;
bool _enabled = false;
HHOOK hook_handle;
+ std::unique_ptr event_waiter;
void init_settings();
void disable(bool trace_event);
diff --git a/src/modules/shortcut_guide/shortcut_guide.vcxproj b/src/modules/shortcut_guide/shortcut_guide.vcxproj
index 7d1fdec6be..b165f02eba 100644
--- a/src/modules/shortcut_guide/shortcut_guide.vcxproj
+++ b/src/modules/shortcut_guide/shortcut_guide.vcxproj
@@ -67,6 +67,7 @@
+
@@ -83,6 +84,7 @@
+
diff --git a/src/modules/shortcut_guide/shortcut_guide.vcxproj.filters b/src/modules/shortcut_guide/shortcut_guide.vcxproj.filters
index 7ee044a73d..6f093d1b3f 100644
--- a/src/modules/shortcut_guide/shortcut_guide.vcxproj.filters
+++ b/src/modules/shortcut_guide/shortcut_guide.vcxproj.filters
@@ -36,6 +36,9 @@
Source Files
+
+ Source Files
+
@@ -73,6 +76,9 @@
Header Files
+
+ Header Files
+
diff --git a/src/runner/main.cpp b/src/runner/main.cpp
index 6f08690bb4..b57daabf84 100644
--- a/src/runner/main.cpp
+++ b/src/runner/main.cpp
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
extern updating::notifications::strings Strings;
@@ -77,12 +78,8 @@ void open_menu_from_another_instance()
PostMessageW(hwnd_main, WM_COMMAND, ID_SETTINGS_MENU_COMMAND, 0);
}
-int runner(bool isProcessElevated, bool openSettings)
+int runner(bool isProcessElevated, bool openSettings, bool openOobe)
{
- std::filesystem::path logFilePath(PTSettingsHelper::get_root_save_folder_location());
- logFilePath.append(LogSettings::runnerLogPath);
- Logger::init(LogSettings::runnerLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location());
-
Logger::info("Runner is starting. Elevated={}", isProcessElevated);
DPIAware::EnableDPIAwarenessForThisProcess();
@@ -161,6 +158,11 @@ int runner(bool isProcessElevated, bool openSettings)
open_settings_window();
}
+ if (openOobe)
+ {
+ open_oobe_window();
+ }
+
result = run_message_loop();
}
catch (std::runtime_error& err)
@@ -336,6 +338,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
break;
}
+ std::filesystem::path logFilePath(PTSettingsHelper::get_root_save_folder_location());
+ logFilePath.append(LogSettings::runnerLogPath);
+ Logger::init(LogSettings::runnerLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location());
+
wil::unique_mutex_nothrow msi_mutex;
wil::unique_mutex_nothrow msix_mutex;
@@ -401,6 +407,20 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
}
}
+ bool openOobe = false;
+ try
+ {
+ openOobe = !PTSettingsHelper::get_oobe_opened_state();
+ if (openOobe)
+ {
+ PTSettingsHelper::save_oobe_opened_state();
+ }
+ }
+ catch (const std::exception& e)
+ {
+ Logger::error("Failed to get or save OOBE state with an exception: {}", e.what());
+ }
+
int result = 0;
try
{
@@ -411,6 +431,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
auto general_settings = load_general_settings();
const bool openSettings = std::string(lpCmdLine).find("--open-settings") != std::string::npos;
+
// Apply the general settings but don't save it as the modules() variable has not been loaded yet
apply_general_settings(general_settings, false);
int rvalue = 0;
@@ -420,7 +441,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
std::string(lpCmdLine).find("--dont-elevate") != std::string::npos))
{
- result = runner(elevated, openSettings);
+ result = runner(elevated, openSettings, openOobe);
}
else
{
diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp
index 97a345a9ee..7d6d45c0f9 100644
--- a/src/runner/settings_window.cpp
+++ b/src/runner/settings_window.cpp
@@ -277,7 +277,7 @@ BOOL run_settings_non_elevated(LPCWSTR executable_path, LPWSTR executable_args,
DWORD g_settings_process_id = 0;
-void run_settings_window()
+void run_settings_window(bool showOobeWindow)
{
g_isLaunchInProgress = true;
@@ -303,7 +303,7 @@ void run_settings_window()
executable_path.append(L"\\PowerToysSettings.exe");
}
- // Arg 2: pipe server. Generate unique names for the pipes, if getting a UUID is possible.
+ // Args 2,3: pipe server. 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_");
UUID temp_uuid;
@@ -327,10 +327,10 @@ void run_settings_window()
uuid_chars = nullptr;
}
- // Arg 3: process pid.
+ // Arg 4: process pid.
DWORD powertoys_pid = GetCurrentProcessId();
- // Arg 4: settings theme.
+ // Arg 5: settings theme.
const std::wstring settings_theme_setting{ get_general_settings().theme };
std::wstring settings_theme = L"system";
if (settings_theme_setting == L"dark" || (settings_theme_setting == L"system" && WindowsColors::is_dark_mode()))
@@ -338,33 +338,18 @@ void run_settings_window()
settings_theme = L"dark";
}
- // Arg 4: settings theme.
GeneralSettings save_settings = get_general_settings();
+ // Arg 6: elevated status
bool isElevated{ get_general_settings().isElevated };
- std::wstring settings_elevatedStatus;
- settings_elevatedStatus = isElevated;
-
- if (isElevated)
- {
- settings_elevatedStatus = L"true";
- }
- else
- {
- settings_elevatedStatus = L"false";
- }
-
+ std::wstring settings_elevatedStatus = isElevated ? L"true" : L"false";
+
+ // Arg 7: is user an admin
bool isAdmin{ get_general_settings().isAdmin };
- std::wstring settings_isUserAnAdmin;
+ std::wstring settings_isUserAnAdmin = isAdmin ? L"true" : L"false";
- if (isAdmin)
- {
- settings_isUserAnAdmin = L"true";
- }
- else
- {
- settings_isUserAnAdmin = L"false";
- }
+ // Arg 8: should oobe window be shown
+ std::wstring settings_showOobe = showOobeWindow ? L"true" : L"false";
// create general settings file to initialize the settings file with installation configurations like :
// 1. Run on start up.
@@ -384,7 +369,9 @@ void run_settings_window()
executable_args.append(settings_elevatedStatus);
executable_args.append(L" ");
executable_args.append(settings_isUserAnAdmin);
-
+ executable_args.append(L" ");
+ executable_args.append(settings_showOobe);
+
BOOL process_created = false;
// Due to a bug in .NET, running the Settings process as non-elevated
@@ -510,7 +497,9 @@ void open_settings_window()
{
if (!g_isLaunchInProgress)
{
- std::thread(run_settings_window).detach();
+ std::thread([]() {
+ run_settings_window(false);
+ }).detach();
}
}
}
@@ -526,3 +515,10 @@ void close_settings_window()
}
}
}
+
+void open_oobe_window()
+{
+ std::thread([]() {
+ run_settings_window(true);
+ }).detach();
+}
diff --git a/src/runner/settings_window.h b/src/runner/settings_window.h
index 0f9048f16e..c4eb56bb7c 100644
--- a/src/runner/settings_window.h
+++ b/src/runner/settings_window.h
@@ -1,3 +1,5 @@
#pragma once
void open_settings_window();
-void close_settings_window();
\ No newline at end of file
+void close_settings_window();
+
+void open_oobe_window();
\ No newline at end of file
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeModuleRunEvent.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeModuleRunEvent.cs
new file mode 100644
index 0000000000..4b0721d410
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeModuleRunEvent.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Tracing;
+using Microsoft.PowerToys.Telemetry;
+using Microsoft.PowerToys.Telemetry.Events;
+
+namespace Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events
+{
+ [EventData]
+ public class OobeModuleRunEvent : EventBase, IEvent
+ {
+ public string ModuleName { get; set; }
+
+ public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeSectionEvent.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeSectionEvent.cs
new file mode 100644
index 0000000000..bb3265773d
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeSectionEvent.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Tracing;
+using Microsoft.PowerToys.Telemetry;
+using Microsoft.PowerToys.Telemetry.Events;
+
+namespace Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events
+{
+ [EventData]
+ public class OobeSectionEvent : EventBase, IEvent
+ {
+ public string Section { get; set; }
+
+ public double TimeOpenedMs { get; set; }
+
+ public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeSettingsEvent.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeSettingsEvent.cs
new file mode 100644
index 0000000000..f0e7293ed3
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeSettingsEvent.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Tracing;
+using Microsoft.PowerToys.Telemetry;
+using Microsoft.PowerToys.Telemetry.Events;
+
+namespace Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events
+{
+ [EventData]
+ public class OobeSettingsEvent : EventBase, IEvent
+ {
+ public string ModuleName { get; set; }
+
+ public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeStartedEvent.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeStartedEvent.cs
new file mode 100644
index 0000000000..771cdfc402
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/Telemetry/Events/OobeStartedEvent.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Tracing;
+using Microsoft.PowerToys.Telemetry;
+using Microsoft.PowerToys.Telemetry.Events;
+
+namespace Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events
+{
+ [EventData]
+ public class OobeStartedEvent : EventBase, IEvent
+ {
+ public bool OobeStarted { get; set; } = true;
+
+ public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsColorPicker.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsColorPicker.png
new file mode 100644
index 0000000000..b120ef4683
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsColorPicker.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsFancyZones.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsFancyZones.png
new file mode 100644
index 0000000000..afa3f1739b
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsFancyZones.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsFileExplorerPreview.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsFileExplorerPreview.png
new file mode 100644
index 0000000000..337457d6ed
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsFileExplorerPreview.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsImageResizer.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsImageResizer.png
new file mode 100644
index 0000000000..a4f82a5e00
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsImageResizer.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsKeyboardManager.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsKeyboardManager.png
new file mode 100644
index 0000000000..2d6db29ff1
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsKeyboardManager.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsPowerRename.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsPowerRename.png
new file mode 100644
index 0000000000..6400b89e2d
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsPowerRename.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsPowerToys.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsPowerToys.png
new file mode 100644
index 0000000000..a7b0109afd
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsPowerToys.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsPowerToysRun.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsPowerToysRun.png
new file mode 100644
index 0000000000..24bfb98494
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsPowerToysRun.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsShortcutGuide.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsShortcutGuide.png
new file mode 100644
index 0000000000..2613c44846
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsShortcutGuide.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsVideoConferenceMute.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsVideoConferenceMute.png
new file mode 100644
index 0000000000..2b9e8dfdac
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/FluentIcons/FluentIconsVideoConferenceMute.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/ColorPicker.gif b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/ColorPicker.gif
new file mode 100644
index 0000000000..a926917aaf
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/ColorPicker.gif differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/FancyZones.gif b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/FancyZones.gif
new file mode 100644
index 0000000000..6395240d4f
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/FancyZones.gif differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/FileExplorer.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/FileExplorer.png
new file mode 100644
index 0000000000..2fe02e0b8c
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/FileExplorer.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/ImageResizer.gif b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/ImageResizer.gif
new file mode 100644
index 0000000000..b82fa8f814
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/ImageResizer.gif differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/KBM.gif b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/KBM.gif
new file mode 100644
index 0000000000..a59840c960
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/KBM.gif differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/OOBEShortcutGuide.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/OOBEShortcutGuide.png
new file mode 100644
index 0000000000..377b09325f
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/OOBEShortcutGuide.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/PowerRename.gif b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/PowerRename.gif
new file mode 100644
index 0000000000..31f9e112f7
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/PowerRename.gif differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/Run.gif b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/Run.gif
new file mode 100644
index 0000000000..2eb870b1d3
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/Run.gif differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/VideoConferenceMute.png b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/VideoConferenceMute.png
new file mode 100644
index 0000000000..b7b47a01c2
Binary files /dev/null and b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Assets/Modules/OOBE/VideoConferenceMute.png differ
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Helpers/NativeMethods.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Helpers/NativeMethods.cs
index 4f91dd4b4b..176c10a735 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Helpers/NativeMethods.cs
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Helpers/NativeMethods.cs
@@ -6,7 +6,7 @@ using System.Runtime.InteropServices;
namespace Microsoft.PowerToys.Settings.UI.Helpers
{
- internal static class NativeMethods
+ public static class NativeMethods
{
[DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs, NativeKeyboardHelper.INPUT[] pInputs, int cbSize);
@@ -14,7 +14,12 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern short GetAsyncKeyState(int vKey);
+#pragma warning disable CA1401 // P/Invokes should not be visible
[DllImport("user32.dll")]
public static extern bool ShowWindow(System.IntPtr hWnd, int nCmdShow);
+
+ [DllImport("user32.dll")]
+ public static extern bool AllowSetForegroundWindow(int dwProcessId);
+#pragma warning restore CA1401 // P/Invokes should not be visible
}
}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj
index 67370b3e30..fb1af0417a 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj
@@ -111,6 +111,42 @@
+
+
+
+
+ OobeColorPicker.xaml
+
+
+ OobeFancyZones.xaml
+
+
+ OobeFileExplorer.xaml
+
+
+ OobeImageResizer.xaml
+
+
+ OobeKBM.xaml
+
+
+ OobeOverview.xaml
+
+
+ OobePowerRename.xaml
+
+
+ OobeRun.xaml
+
+
+ OobeShellPage.xaml
+
+
+ OobeShortcutGuide.xaml
+
+
+ OobeVideoConference.xaml
+
@@ -153,11 +189,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -216,6 +271,50 @@
MSBuild:Compile
Designer
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -300,6 +399,7 @@
Microsoft.PowerToys.Settings.UI.Library
+
14.0
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Enums/PowerToysModulesEnum.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Enums/PowerToysModulesEnum.cs
new file mode 100644
index 0000000000..10806e19fc
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Enums/PowerToysModulesEnum.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Enums
+{
+ public enum PowerToysModulesEnum
+ {
+ Overview = 0,
+ ColorPicker,
+ FancyZones,
+ ImageResizer,
+ KBM,
+ Run,
+ PowerRename,
+ FileExplorer,
+ ShortcutGuide,
+ VideoConference,
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/ViewModel/OobePowerToysModule.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/ViewModel/OobePowerToysModule.cs
new file mode 100644
index 0000000000..76cd71fa23
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/ViewModel/OobePowerToysModule.cs
@@ -0,0 +1,79 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
+using Microsoft.PowerToys.Telemetry;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.ViewModel
+{
+ public class OobePowerToysModule
+ {
+ private System.Diagnostics.Stopwatch timeOpened = new System.Diagnostics.Stopwatch();
+
+ public string ModuleName { get; set; }
+
+ public string Tag { get; set; }
+
+ public bool IsNew { get; set; }
+
+ public string Image { get; set; }
+
+ public string Icon { get; set; }
+
+ public string FluentIcon { get; set; }
+
+ public string PreviewImageSource { get; set; }
+
+ public string Description { get; set; }
+
+ public string Link { get; set; }
+
+ public string DescriptionLink { get; set; }
+
+ public OobePowerToysModule()
+ {
+ }
+
+ public OobePowerToysModule(OobePowerToysModule other)
+ {
+ if (other == null)
+ {
+ return;
+ }
+
+ ModuleName = other.ModuleName;
+ Tag = other.Tag;
+ IsNew = other.IsNew;
+ Image = other.Image;
+ Icon = other.Icon;
+ FluentIcon = other.FluentIcon;
+ PreviewImageSource = other.PreviewImageSource;
+ Description = other.Description;
+ Link = other.Link;
+ DescriptionLink = other.DescriptionLink;
+ timeOpened = other.timeOpened;
+ }
+
+ public void LogOpeningSettingsEvent()
+ {
+ PowerToysTelemetry.Log.WriteEvent(new OobeSettingsEvent() { ModuleName = this.ModuleName });
+ }
+
+ public void LogRunningModuleEvent()
+ {
+ PowerToysTelemetry.Log.WriteEvent(new OobeModuleRunEvent() { ModuleName = this.ModuleName });
+ }
+
+ public void LogOpeningModuleEvent()
+ {
+ timeOpened.Start();
+ }
+
+ public void LogClosingModuleEvent()
+ {
+ timeOpened.Stop();
+ PowerToysTelemetry.Log.WriteEvent(new OobeSectionEvent() { Section = this.ModuleName, TimeOpenedMs = timeOpened.ElapsedMilliseconds });
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/ViewModel/OobeShellViewModel.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/ViewModel/OobeShellViewModel.cs
new file mode 100644
index 0000000000..6159b58690
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/ViewModel/OobeShellViewModel.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.ViewModel
+{
+ public class OobeShellViewModel
+ {
+ public OobeShellViewModel()
+ {
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeColorPicker.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeColorPicker.xaml
new file mode 100644
index 0000000000..748d36dae2
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeColorPicker.xaml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeColorPicker.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeColorPicker.xaml.cs
new file mode 100644
index 0000000000..6c1707ed8d
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeColorPicker.xaml.cs
@@ -0,0 +1,61 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading;
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class OobeColorPicker : Page
+ {
+ public OobePowerToysModule ViewModel { get; set; }
+
+ public OobeColorPicker()
+ {
+ this.InitializeComponent();
+ ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.ColorPicker]);
+ DataContext = ViewModel;
+ }
+
+ private void Start_ColorPicker_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.ColorPickerSharedEventCallback != null)
+ {
+ using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, OobeShellPage.ColorPickerSharedEventCallback()))
+ {
+ eventHandle.Set();
+ }
+ }
+
+ ViewModel.LogRunningModuleEvent();
+ }
+
+ private void SettingsLaunchButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.OpenMainWindowCallback != null)
+ {
+ OobeShellPage.OpenMainWindowCallback(typeof(ColorPickerPage));
+ }
+
+ ViewModel.LogOpeningSettingsEvent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ViewModel.LogOpeningModuleEvent();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ViewModel.LogClosingModuleEvent();
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFancyZones.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFancyZones.xaml
new file mode 100644
index 0000000000..10052406be
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFancyZones.xaml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFancyZones.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFancyZones.xaml.cs
new file mode 100644
index 0000000000..69101d40a3
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFancyZones.xaml.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class OobeFancyZones : Page
+ {
+ public OobePowerToysModule ViewModel { get; set; }
+
+ public OobeFancyZones()
+ {
+ this.InitializeComponent();
+ ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.FancyZones]);
+ DataContext = ViewModel;
+ }
+
+ private void SettingsLaunchButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.OpenMainWindowCallback != null)
+ {
+ OobeShellPage.OpenMainWindowCallback(typeof(FancyZonesPage));
+ }
+
+ ViewModel.LogOpeningSettingsEvent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ViewModel.LogOpeningModuleEvent();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ViewModel.LogClosingModuleEvent();
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFileExplorer.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFileExplorer.xaml
new file mode 100644
index 0000000000..4d586eba86
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFileExplorer.xaml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFileExplorer.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFileExplorer.xaml.cs
new file mode 100644
index 0000000000..0c1111f473
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeFileExplorer.xaml.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class OobeFileExplorer : Page
+ {
+ public OobePowerToysModule ViewModel { get; set; }
+
+ public OobeFileExplorer()
+ {
+ this.InitializeComponent();
+ ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.FileExplorer]);
+ DataContext = ViewModel;
+ }
+
+ private void SettingsLaunchButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.OpenMainWindowCallback != null)
+ {
+ OobeShellPage.OpenMainWindowCallback(typeof(PowerPreviewPage));
+ }
+
+ ViewModel.LogOpeningSettingsEvent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ViewModel.LogOpeningModuleEvent();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ViewModel.LogClosingModuleEvent();
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeImageResizer.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeImageResizer.xaml
new file mode 100644
index 0000000000..942f7f8d3b
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeImageResizer.xaml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeImageResizer.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeImageResizer.xaml.cs
new file mode 100644
index 0000000000..1cf0730d58
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeImageResizer.xaml.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class OobeImageResizer : Page
+ {
+ public OobePowerToysModule ViewModel { get; set; }
+
+ public OobeImageResizer()
+ {
+ this.InitializeComponent();
+ ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.ImageResizer]);
+ DataContext = ViewModel;
+ }
+
+ private void SettingsLaunchButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.OpenMainWindowCallback != null)
+ {
+ OobeShellPage.OpenMainWindowCallback(typeof(ImageResizerPage));
+ }
+
+ ViewModel.LogOpeningSettingsEvent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ViewModel.LogOpeningModuleEvent();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ViewModel.LogClosingModuleEvent();
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeKBM.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeKBM.xaml
new file mode 100644
index 0000000000..35ba58e895
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeKBM.xaml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeKBM.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeKBM.xaml.cs
new file mode 100644
index 0000000000..f917344ccb
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeKBM.xaml.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class OobeKBM : Page
+ {
+ public OobePowerToysModule ViewModel { get; set; }
+
+ public OobeKBM()
+ {
+ this.InitializeComponent();
+ ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.KBM]);
+ DataContext = ViewModel;
+ }
+
+ private void SettingsLaunchButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.OpenMainWindowCallback != null)
+ {
+ OobeShellPage.OpenMainWindowCallback(typeof(KeyboardManagerPage));
+ }
+
+ ViewModel.LogOpeningSettingsEvent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ViewModel.LogOpeningModuleEvent();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ViewModel.LogClosingModuleEvent();
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeOverview.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeOverview.xaml
new file mode 100644
index 0000000000..d684b12aa7
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeOverview.xaml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeOverview.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeOverview.xaml.cs
new file mode 100644
index 0000000000..e2dbb85461
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeOverview.xaml.cs
@@ -0,0 +1,44 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ public sealed partial class OobeOverview : Page
+ {
+ public OobePowerToysModule ViewModel { get; set; }
+
+ public OobeOverview()
+ {
+ this.InitializeComponent();
+ ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.Overview]);
+ DataContext = ViewModel;
+ }
+
+ private void SettingsLaunchButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.OpenMainWindowCallback != null)
+ {
+ OobeShellPage.OpenMainWindowCallback(typeof(GeneralPage));
+ }
+
+ ViewModel.LogOpeningSettingsEvent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ViewModel.LogOpeningModuleEvent();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ViewModel.LogClosingModuleEvent();
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobePowerRename.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobePowerRename.xaml
new file mode 100644
index 0000000000..204422e227
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobePowerRename.xaml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobePowerRename.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobePowerRename.xaml.cs
new file mode 100644
index 0000000000..035b6aec2a
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobePowerRename.xaml.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class OobePowerRename : Page
+ {
+ public OobePowerToysModule ViewModel { get; set; }
+
+ public OobePowerRename()
+ {
+ this.InitializeComponent();
+ ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.PowerRename]);
+ DataContext = ViewModel;
+ }
+
+ private void SettingsLaunchButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.OpenMainWindowCallback != null)
+ {
+ OobeShellPage.OpenMainWindowCallback(typeof(PowerRenamePage));
+ }
+
+ ViewModel.LogOpeningSettingsEvent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ViewModel.LogOpeningModuleEvent();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ViewModel.LogClosingModuleEvent();
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeRun.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeRun.xaml
new file mode 100644
index 0000000000..3c6d9634d1
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeRun.xaml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeRun.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeRun.xaml.cs
new file mode 100644
index 0000000000..d67901fa98
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeRun.xaml.cs
@@ -0,0 +1,61 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading;
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class OobeRun : Page
+ {
+ public OobePowerToysModule ViewModel { get; set; }
+
+ public OobeRun()
+ {
+ this.InitializeComponent();
+ ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.Run]);
+ DataContext = ViewModel;
+ }
+
+ private void Start_Run_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.RunSharedEventCallback != null)
+ {
+ using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, OobeShellPage.RunSharedEventCallback()))
+ {
+ eventHandle.Set();
+ }
+ }
+
+ ViewModel.LogRunningModuleEvent();
+ }
+
+ private void SettingsLaunchButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.OpenMainWindowCallback != null)
+ {
+ OobeShellPage.OpenMainWindowCallback(typeof(PowerLauncherPage));
+ }
+
+ ViewModel.LogOpeningSettingsEvent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ViewModel.LogOpeningModuleEvent();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ViewModel.LogClosingModuleEvent();
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShellPage.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShellPage.xaml
new file mode 100644
index 0000000000..9f0ee9296a
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShellPage.xaml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShellPage.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShellPage.xaml.cs
new file mode 100644
index 0000000000..8a63b9701c
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShellPage.xaml.cs
@@ -0,0 +1,225 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.ObjectModel;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Windows.ApplicationModel.Resources;
+using Windows.UI.Xaml.Controls;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ public sealed partial class OobeShellPage : UserControl
+ {
+ public static Func RunSharedEventCallback { get; set; }
+
+ public static void SetRunSharedEventCallback(Func implementation)
+ {
+ RunSharedEventCallback = implementation;
+ }
+
+ public static Func ColorPickerSharedEventCallback { get; set; }
+
+ public static void SetColorPickerSharedEventCallback(Func implementation)
+ {
+ ColorPickerSharedEventCallback = implementation;
+ }
+
+ public static Func ShortcutGuideSharedEventCallback { get; set; }
+
+ public static void SetShortcutGuideSharedEventCallback(Func implementation)
+ {
+ ShortcutGuideSharedEventCallback = implementation;
+ }
+
+ public static Action OpenMainWindowCallback { get; set; }
+
+ public static void SetOpenMainWindowCallback(Action implementation)
+ {
+ OpenMainWindowCallback = implementation;
+ }
+
+ ///
+ /// Gets view model.
+ ///
+ public OobeShellViewModel ViewModel { get; } = new OobeShellViewModel();
+
+ ///
+ /// Gets or sets a shell handler to be used to update contents of the shell dynamically from page within the frame.
+ ///
+ public static OobeShellPage OobeShellHandler { get; set; }
+
+ public ObservableCollection Modules { get; }
+
+ public OobeShellPage()
+ {
+ InitializeComponent();
+
+ DataContext = ViewModel;
+ OobeShellHandler = this;
+
+ Modules = new ObservableCollection();
+ ResourceLoader loader = ResourceLoader.GetForViewIndependentUse();
+
+ Modules.Insert((int)PowerToysModulesEnum.Overview, new OobePowerToysModule()
+ {
+ ModuleName = loader.GetString("Oobe_Welcome"),
+ Tag = "Overview",
+ IsNew = false,
+ Icon = "\uEF3C",
+ Image = "ms-appx:///Assets/Modules/ColorPicker.png",
+ FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerToys.png",
+ PreviewImageSource = "https://github.com/microsoft/PowerToys/raw/master/doc/images/overview/PT%20hero%20image.png",
+ DescriptionLink = "https://aka.ms/PowerToysOverview",
+ Link = "https://github.com/microsoft/PowerToys/releases/",
+ });
+ Modules.Insert((int)PowerToysModulesEnum.ColorPicker, new OobePowerToysModule()
+ {
+ ModuleName = loader.GetString("Oobe_ColorPicker"),
+ Tag = "ColorPicker",
+ IsNew = false,
+ Icon = "\uEF3C",
+ Image = "ms-appx:///Assets/Modules/ColorPicker.png",
+ FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsColorPicker.png",
+ PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/ColorPicker.gif",
+ Description = loader.GetString("Oobe_ColorPicker_Description"),
+ Link = "https://aka.ms/PowerToysOverview_ColorPicker",
+ });
+ Modules.Insert((int)PowerToysModulesEnum.FancyZones, new OobePowerToysModule()
+ {
+ ModuleName = loader.GetString("Oobe_FancyZones"),
+ Tag = "FancyZones",
+ IsNew = false,
+ Icon = "\uE737",
+ Image = "ms-appx:///Assets/Modules/FancyZones.png",
+ FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsFancyZones.png",
+ PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/FancyZones.gif",
+ Description = loader.GetString("Oobe_FancyZones_Description"),
+ Link = "https://aka.ms/PowerToysOverview_FancyZones",
+ });
+ Modules.Insert((int)PowerToysModulesEnum.ImageResizer, new OobePowerToysModule()
+ {
+ ModuleName = loader.GetString("Oobe_ImageResizer"),
+ Tag = "ImageResizer",
+ IsNew = false,
+ Icon = "\uEB9F",
+ Image = "ms-appx:///Assets/Modules/ImageResizer.png",
+ FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsImageResizer.png",
+ Description = loader.GetString("Oobe_ImageResizer_Description"),
+ PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/ImageResizer.gif",
+ Link = "https://aka.ms/PowerToysOverview_ImageResizer",
+ });
+ Modules.Insert((int)PowerToysModulesEnum.KBM, new OobePowerToysModule()
+ {
+ ModuleName = loader.GetString("Oobe_KBM"),
+ Tag = "KBM",
+ IsNew = false,
+ Icon = "\uE765",
+ Image = "ms-appx:///Assets/Modules/KeyboardManager.png",
+ FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsKeyboardManager.png",
+ Description = loader.GetString("Oobe_KBM_Description"),
+ PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/KBM.gif",
+ Link = "https://aka.ms/PowerToysOverview_KeyboardManager",
+ });
+ Modules.Insert((int)PowerToysModulesEnum.Run, new OobePowerToysModule()
+ {
+ ModuleName = loader.GetString("Oobe_Run"),
+ Tag = "Run",
+ IsNew = false,
+ Icon = "\uE773",
+ Image = "ms-appx:///Assets/Modules/PowerLauncher.png",
+ FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerToysRun.png",
+ PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/Run.gif",
+ Description = loader.GetString("Oobe_PowerRun_Description"),
+ Link = "https://aka.ms/PowerToysOverview_PowerToysRun",
+ });
+ Modules.Insert((int)PowerToysModulesEnum.PowerRename, new OobePowerToysModule()
+ {
+ ModuleName = loader.GetString("Oobe_PowerRename"),
+ Tag = "PowerRename",
+ IsNew = false,
+ Icon = "\uE8AC",
+ Image = "ms-appx:///Assets/Modules/PowerRename.png",
+ FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerRename.png",
+ Description = loader.GetString("Oobe_PowerRename_Description"),
+ PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/PowerRename.gif",
+ Link = "https://aka.ms/PowerToysOverview_PowerRename",
+ });
+ Modules.Insert((int)PowerToysModulesEnum.FileExplorer, new OobePowerToysModule()
+ {
+ ModuleName = loader.GetString("Oobe_FileExplorer"),
+ Tag = "FileExplorer",
+ IsNew = false,
+ Icon = "\uEC50",
+ FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsFileExplorerPreview.png",
+ Image = "ms-appx:///Assets/Modules/PowerPreview.png",
+ Description = loader.GetString("Oobe_FileExplorer_Description"),
+ PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/FileExplorer.png",
+ Link = "https://aka.ms/PowerToysOverview_FileExplorerAddOns",
+ });
+ Modules.Insert((int)PowerToysModulesEnum.ShortcutGuide, new OobePowerToysModule()
+ {
+ ModuleName = loader.GetString("Oobe_ShortcutGuide"),
+ Tag = "ShortcutGuide",
+ IsNew = false,
+ Icon = "\uEDA7",
+ FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsShortcutGuide.png",
+ Image = "ms-appx:///Assets/Modules/ShortcutGuide.png",
+ Description = loader.GetString("Oobe_ShortcutGuide_Description"),
+ PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/OOBEShortcutGuide.png",
+ Link = "https://aka.ms/PowerToysOverview_ShortcutGuide",
+ });
+ /* Modules.Insert((int)PowerToysModulesEnum.VideoConference, new OobePowerToysModule()
+ {
+ ModuleName = loader.GetString("Oobe_VideoConference"),
+ Tag = "VideoConference",
+ IsNew = true,
+ Icon = "\uEC50",
+ FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsVideoConferenceMute.png",
+ Image = "ms-appx:///Assets/Modules/VideoConference.png",
+ Description = loader.GetString("Oobe_VideoConference_Description"),
+ PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/VideoConferenceMute.png",
+ Link = "https://aka.ms/PowerToysOverview_VideoConference",
+ }); */
+ }
+
+ public void OnClosing()
+ {
+ if (NavigationView.SelectedItem != null)
+ {
+ ((OobePowerToysModule)NavigationView.SelectedItem).LogClosingModuleEvent();
+ }
+ }
+
+ private void UserControl_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (Modules.Count > 0)
+ {
+ NavigationView.SelectedItem = Modules[(int)PowerToysModulesEnum.Overview];
+ }
+ }
+
+ [SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "Params are required for event handler signature requirements.")]
+ private void NavigationView_SelectionChanged(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewSelectionChangedEventArgs args)
+ {
+ OobePowerToysModule selectedItem = args.SelectedItem as OobePowerToysModule;
+
+ switch (selectedItem.Tag)
+ {
+ case "Overview": NavigationFrame.Navigate(typeof(OobeOverview)); break;
+ case "ColorPicker": NavigationFrame.Navigate(typeof(OobeColorPicker)); break;
+ case "FancyZones": NavigationFrame.Navigate(typeof(OobeFancyZones)); break;
+ case "Run": NavigationFrame.Navigate(typeof(OobeRun)); break;
+ case "ImageResizer": NavigationFrame.Navigate(typeof(OobeImageResizer)); break;
+ case "KBM": NavigationFrame.Navigate(typeof(OobeKBM)); break;
+ case "PowerRename": NavigationFrame.Navigate(typeof(OobePowerRename)); break;
+ case "FileExplorer": NavigationFrame.Navigate(typeof(OobeFileExplorer)); break;
+ case "ShortcutGuide": NavigationFrame.Navigate(typeof(OobeShortcutGuide)); break;
+ case "VideoConference": NavigationFrame.Navigate(typeof(OobeVideoConference)); break;
+ }
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShortcutGuide.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShortcutGuide.xaml
new file mode 100644
index 0000000000..674c0bcfad
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShortcutGuide.xaml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShortcutGuide.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShortcutGuide.xaml.cs
new file mode 100644
index 0000000000..956c33384b
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeShortcutGuide.xaml.cs
@@ -0,0 +1,61 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading;
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class OobeShortcutGuide : Page
+ {
+ public OobePowerToysModule ViewModel { get; set; }
+
+ public OobeShortcutGuide()
+ {
+ this.InitializeComponent();
+ ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.ShortcutGuide]);
+ DataContext = ViewModel;
+ }
+
+ private void Start_ShortcutGuide_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.ShortcutGuideSharedEventCallback != null)
+ {
+ using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, OobeShellPage.ShortcutGuideSharedEventCallback()))
+ {
+ eventHandle.Set();
+ }
+ }
+
+ ViewModel.LogRunningModuleEvent();
+ }
+
+ private void SettingsLaunchButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (OobeShellPage.OpenMainWindowCallback != null)
+ {
+ OobeShellPage.OpenMainWindowCallback(typeof(ShortcutGuidePage));
+ }
+
+ ViewModel.LogOpeningSettingsEvent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ViewModel.LogOpeningModuleEvent();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ViewModel.LogClosingModuleEvent();
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeVideoConference.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeVideoConference.xaml
new file mode 100644
index 0000000000..d80e1710d4
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeVideoConference.xaml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeVideoConference.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeVideoConference.xaml.cs
new file mode 100644
index 0000000000..3723113964
--- /dev/null
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/OOBE/Views/OobeVideoConference.xaml.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
+using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class OobeVideoConference : Page
+ {
+ public OobePowerToysModule ViewModel { get; set; }
+
+ public OobeVideoConference()
+ {
+ this.InitializeComponent();
+ ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.VideoConference]);
+ DataContext = ViewModel;
+ }
+
+ private void SettingsLaunchButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ ViewModel.LogOpeningSettingsEvent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ViewModel.LogOpeningModuleEvent();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ViewModel.LogClosingModuleEvent();
+ }
+ }
+}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
index ec39763343..0bc54216b0 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
@@ -977,4 +977,172 @@
You can include or remove each plugin from the global results, change the direct activation phrase and configure additional options.
+
+ Let's get started!
+
+
+ Welcome to PowerToys! These overviews will help you quickly learn the basics of all our utilities.
+
+
+ Getting started
+
+
+ Launch
+
+
+ Learn more about
+
+
+ Color Picker is a system-wide color selection tool for Windows 10 that enables you to pick colors from any currently running application and automatically copies it in a configurable format to your clipboard.
+
+
+ FancyZones is a window manager that makes it easy to create complex window layouts and quickly position windows into those layouts.
+
+
+ PowerToys introduces add-ons to the Window’s File Explorer that will currently enable Markdown files (.md) and SVG icons (.svg) to be viewed in the preview pane.
+
+
+ Image Resizer is a Windows shell extension for simple bulk image-resizing.
+
+
+ Keyboard Manager allows you to customize the keyboard to be more productive by remapping keys and creating your own keyboard shortcuts.
+
+
+ PowerRename enables you to perform simple bulk renaming, searching and replacing file names.
+
+
+ PowerToys Run is a quick launcher for power users that contains some additional features without sacrificing performance.
+
+
+ Shortcut Guide presents the user with a listing of available shortcuts for the current state of the desktop.
+
+
+ Video Conference Mute allows users to quickly mute the microphone and turn off the camera while on a conference call with a single keystroke, regardless of what application has focus on your computer.
+
+
+ For returning users, check out what is new on this latest version of
+
+
+ Microsoft PowerToys is a set of utilities for power users to tune and streamline their Windows 10 experience for greater productivity.
+Take a moment to preview the various utilities listed or view our comprehensive documentation on
+
+
+ Microsoft Docs.
+
+
+ PowerToys in our release notes.
+
+
+ Win + Shift + C to open Color Picker.
+
+
+ To select a color with more precision, scroll the mouse wheel to zoom in.
+
+
+ Shift + drag while dragging the window to snap a window to a zone, and release the window in the desired zone.
+Win + ` to open the FancyZones editor.
+
+
+ Snap a window to multiple zones by holding the Ctrl key (while also holding Shift) when dragging a window.
+
+
+ Open Windows File Explorer, select the View tab in the File Explorer ribbon, then select Preview Pane.
+From there, simply click on a Markdown file or SVG icon in the File Explorer and observe the content on the preview pane!
+
+
+ How to create mappings
+
+
+ How to enable
+
+
+ How to launch
+
+
+ How to use
+
+
+ In File Explorer, right-clicking one or more image files and clicking on Resize pictures from the context menu.
+
+
+ Want a custom size? You can add them in the PowerToys Settings!
+
+
+ Launch PowerToys settings, navigate to the Keyboard Manager menu, and select either Remap a key or Remap a shortcut.
+
+
+ Want to only have a shortcut work for a single application? Use the Target App field when creating the shortcut remapping.
+
+
+ In File Explorer, right-clicking one or more selected files and clicking on PowerRename from the context menu.
+
+
+ PowerRename supports searching for files using regular expressions to enable more advanced renaming functionalities.
+
+
+ Alt + Space to open PowerToys and just start typing.
+
+
+ PowerToys runs supports various action keys to funnel search queries for a specific subset of results. Typing < searches for running processes only, ? will search only for file, or . for installed applications! See PowerToys documentation for the complete set of 'Action Keys' available.
+
+
+ Win + ? to open Shortcut Guide, press it again to close or press Esc. You can also launch it by holding the Win key for one second!
+
+
+ Tips & tricks
+
+
+ Win + N to toggle both your microphone and video
+Win + Shift + A to toggle your microphone
+Win + Shift + O to toggle your video
+
+
+ Color Picker
+ Do not localize this string
+
+
+ FancyZones
+ Do not localize this string
+
+
+ File Explorer add-ons
+ Do not localize this string
+
+
+ ImageResizer
+ Do not localize this string
+
+
+ Keyboard Manager
+ Do not localize this string
+
+
+ Overview
+
+
+ PowerRename
+ Do not localize this string
+
+
+ PowerToys Run
+ Do not localize this string
+
+
+ Shortcut Guide
+ Do not localize this string
+
+
+ Video Conference
+ Do not localize this string
+
+
+ Welcome to PowerToys
+ Do not localize 'PowerToys'
+
+
+ Settings
+
+
+ PowerToys Tour
+
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Styles/TextBlock.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Styles/TextBlock.xaml
index f6f0f9fd7f..e8ee207831 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Styles/TextBlock.xaml
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Styles/TextBlock.xaml
@@ -5,7 +5,7 @@
+
+
\ No newline at end of file
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml
index 4c4ccae2ce..50d9348408 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml
@@ -187,6 +187,10 @@
RelativePanel.Below="AboutImage"
Orientation="Vertical" >
+
+
+
+
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs
index 63bf95342a..d956327bf4 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs
@@ -122,5 +122,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
Helpers.StartProcessHelper.Start(Helpers.StartProcessHelper.ColorsSettings);
}
+
+ private void OobeButton_Click(object sender, RoutedEventArgs e)
+ {
+ ShellPage.OpenOobeWindowCallback();
+ }
}
}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/ShellPage.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/ShellPage.xaml
index 59e274a377..96a250ed32 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/ShellPage.xaml
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/ShellPage.xaml
@@ -105,6 +105,7 @@
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/ShellPage.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/ShellPage.xaml.cs
index 9a82503ade..7ec85b843c 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/ShellPage.xaml.cs
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/ShellPage.xaml.cs
@@ -2,8 +2,10 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+using Microsoft.PowerToys.Settings.UI.Services;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Windows.Data.Json;
using Windows.UI.Xaml.Controls;
@@ -21,6 +23,11 @@ namespace Microsoft.PowerToys.Settings.UI.Views
/// message.
public delegate void IPCMessageCallback(string msg);
+ ///
+ /// Declaration for the opening oobe window callback function.
+ ///
+ public delegate void OobeOpeningCallback();
+
///
/// Gets or sets a shell handler to be used to update contents of the shell dynamically from page within the frame.
///
@@ -41,6 +48,11 @@ namespace Microsoft.PowerToys.Settings.UI.Views
///
public static IPCMessageCallback CheckForUpdatesMsgCallback { get; set; }
+ ///
+ /// Gets or sets callback function for opening oobe window
+ ///
+ public static OobeOpeningCallback OpenOobeWindowCallback { get; set; }
+
///
/// Gets view model.
///
@@ -114,6 +126,15 @@ namespace Microsoft.PowerToys.Settings.UI.Views
CheckForUpdatesMsgCallback = implementation;
}
+ ///
+ /// Set oobe opening callback function
+ ///
+ /// delegate function implementation.
+ public static void SetOpenOobeCallback(OobeOpeningCallback implementation)
+ {
+ OpenOobeWindowCallback = implementation;
+ }
+
public static void SetElevationStatus(bool isElevated)
{
IsElevated = isElevated;
@@ -124,6 +145,11 @@ namespace Microsoft.PowerToys.Settings.UI.Views
IsUserAnAdmin = isAdmin;
}
+ public static void Navigate(Type type)
+ {
+ NavigationService.Navigate(type);
+ }
+
public void Refresh()
{
shellFrame.Navigate(typeof(GeneralPage));
diff --git a/src/settings-ui/PowerToys.Settings/App.xaml b/src/settings-ui/PowerToys.Settings/App.xaml
index 7eff0b2507..deedff2ed9 100644
--- a/src/settings-ui/PowerToys.Settings/App.xaml
+++ b/src/settings-ui/PowerToys.Settings/App.xaml
@@ -1,7 +1,7 @@
+ Startup="Application_Startup">
diff --git a/src/settings-ui/PowerToys.Settings/App.xaml.cs b/src/settings-ui/PowerToys.Settings/App.xaml.cs
index 7eefca8e6c..56b244638f 100644
--- a/src/settings-ui/PowerToys.Settings/App.xaml.cs
+++ b/src/settings-ui/PowerToys.Settings/App.xaml.cs
@@ -2,7 +2,10 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using System.Windows;
+using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
+using Microsoft.PowerToys.Telemetry;
namespace PowerToys.Settings
{
@@ -11,5 +14,60 @@ namespace PowerToys.Settings
///
public partial class App : Application
{
+ private MainWindow settingsWindow;
+
+ public bool ShowOobe { get; set; }
+
+ public void OpenSettingsWindow(Type type)
+ {
+ if (settingsWindow == null)
+ {
+ settingsWindow = new MainWindow();
+ }
+
+ settingsWindow.Show();
+ settingsWindow.NavigateToSection(type);
+ }
+
+ private void InitHiddenSettingsWindow()
+ {
+ settingsWindow = new MainWindow();
+
+ // To avoid visual flickering, show the window with a size of 0,0
+ // and don't show it in the taskbar
+ var originalHight = settingsWindow.Height;
+ var originalWidth = settingsWindow.Width;
+ settingsWindow.Height = 0;
+ settingsWindow.Width = 0;
+ settingsWindow.ShowInTaskbar = false;
+
+ settingsWindow.Show();
+ settingsWindow.Hide();
+
+ settingsWindow.Height = originalHight;
+ settingsWindow.Width = originalWidth;
+ settingsWindow.ShowInTaskbar = true;
+ }
+
+ private void Application_Startup(object sender, StartupEventArgs e)
+ {
+ if (!ShowOobe)
+ {
+ settingsWindow = new MainWindow();
+ settingsWindow.Show();
+ }
+ else
+ {
+ PowerToysTelemetry.Log.WriteEvent(new OobeStartedEvent());
+
+ // Create the Settings window so that it's fully initialized and
+ // it will be ready to receive the notification if the user opens
+ // the Settings from the tray icon.
+ InitHiddenSettingsWindow();
+
+ OobeWindow oobeWindow = new OobeWindow();
+ oobeWindow.Show();
+ }
+ }
}
}
diff --git a/src/settings-ui/PowerToys.Settings/MainWindow.xaml b/src/settings-ui/PowerToys.Settings/MainWindow.xaml
index 0dffeae7be..0899c7ece7 100644
--- a/src/settings-ui/PowerToys.Settings/MainWindow.xaml
+++ b/src/settings-ui/PowerToys.Settings/MainWindow.xaml
@@ -7,7 +7,7 @@
xmlns:Controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"
xmlns:xaml="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
mc:Ignorable="d"
- Title="PowerToys Settings" MinWidth="480" Height="800" Width="1100" Closing="MainWindow_Closing">
+ Title="PowerToys Settings" MinWidth="480" Height="800" Width="1100" Closing="MainWindow_Closing" Loaded="MainWindow_Loaded" Activated="MainWindow_Activated">
diff --git a/src/settings-ui/PowerToys.Settings/MainWindow.xaml.cs b/src/settings-ui/PowerToys.Settings/MainWindow.xaml.cs
index 438c756a34..714035fb6c 100644
--- a/src/settings-ui/PowerToys.Settings/MainWindow.xaml.cs
+++ b/src/settings-ui/PowerToys.Settings/MainWindow.xaml.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation
+// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -16,6 +16,8 @@ namespace PowerToys.Settings
// Interaction logic for MainWindow.xaml.
public partial class MainWindow : Window
{
+ private static Window inst;
+
private bool isOpen = true;
public MainWindow()
@@ -29,6 +31,23 @@ namespace PowerToys.Settings
PowerToysTelemetry.Log.WriteEvent(new SettingsBootEvent() { BootTimeMs = bootTime.ElapsedMilliseconds });
}
+ public static void CloseHiddenWindow()
+ {
+ if (inst != null && inst.Visibility == Visibility.Hidden)
+ {
+ inst.Close();
+ }
+ }
+
+ public void NavigateToSection(Type type)
+ {
+ if (inst != null)
+ {
+ Activate();
+ ShellPage.Navigate(type);
+ }
+ }
+
private void WindowsXamlHost_ChildChanged(object sender, EventArgs e)
{
// If sender is null, it could lead to a NullReferenceException. This might occur on restarting as admin (check https://github.com/microsoft/PowerToys/issues/7393 for details)
@@ -63,6 +82,13 @@ namespace PowerToys.Settings
Program.GetTwoWayIPCManager().Send(msg);
});
+ // open oobe
+ ShellPage.SetOpenOobeCallback(() =>
+ {
+ var oobe = new OobeWindow();
+ oobe.Show();
+ });
+
// receive IPC Message
Program.IPCMessageReceivedCallback = (string msg) =>
{
@@ -97,7 +123,15 @@ namespace PowerToys.Settings
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
- isOpen = false;
+ if (OobeWindow.IsOpened)
+ {
+ e.Cancel = true;
+ ((Window)sender).Hide();
+ }
+ else
+ {
+ isOpen = false;
+ }
// XAML Islands: If the window is closed while minimized, exit the process. Required to avoid process not terminating issue - https://github.com/microsoft/PowerToys/issues/4430
if (WindowState == WindowState.Minimized)
@@ -106,5 +140,18 @@ namespace PowerToys.Settings
System.Threading.Tasks.Task.Run(() => { Environment.Exit(0); });
}
}
+
+ private void MainWindow_Loaded(object sender, RoutedEventArgs e)
+ {
+ inst = (Window)sender;
+ }
+
+ private void MainWindow_Activated(object sender, EventArgs e)
+ {
+ if (((Window)sender).Visibility == Visibility.Hidden)
+ {
+ ((Window)sender).Visibility = Visibility.Visible;
+ }
+ }
}
}
diff --git a/src/settings-ui/PowerToys.Settings/OobeWindow.xaml b/src/settings-ui/PowerToys.Settings/OobeWindow.xaml
new file mode 100644
index 0000000000..b4d87d43d2
--- /dev/null
+++ b/src/settings-ui/PowerToys.Settings/OobeWindow.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
diff --git a/src/settings-ui/PowerToys.Settings/OobeWindow.xaml.cs b/src/settings-ui/PowerToys.Settings/OobeWindow.xaml.cs
new file mode 100644
index 0000000000..dec8fe81f7
--- /dev/null
+++ b/src/settings-ui/PowerToys.Settings/OobeWindow.xaml.cs
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Windows;
+using interop;
+using Microsoft.PowerToys.Settings.UI.Helpers;
+using Microsoft.PowerToys.Settings.UI.OOBE.Views;
+using Microsoft.Toolkit.Wpf.UI.XamlHost;
+
+namespace PowerToys.Settings
+{
+ ///
+ /// Interaction logic for OobeWindow.xaml
+ ///
+ public partial class OobeWindow : Window
+ {
+ private static Window inst;
+ private OobeShellPage shellPage;
+
+ public static bool IsOpened
+ {
+ get
+ {
+ return inst != null;
+ }
+ }
+
+ public OobeWindow()
+ {
+ InitializeComponent();
+ }
+
+ private void Window_Closed(object sender, EventArgs e)
+ {
+ if (shellPage != null)
+ {
+ shellPage.OnClosing();
+ }
+
+ inst = null;
+ MainWindow.CloseHiddenWindow();
+ }
+
+ private void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ if (inst != null)
+ {
+ inst.Close();
+ }
+
+ inst = this;
+ }
+
+ private void WindowsXamlHost_ChildChanged(object sender, EventArgs e)
+ {
+ if (sender == null)
+ {
+ return;
+ }
+
+ WindowsXamlHost windowsXamlHost = sender as WindowsXamlHost;
+ shellPage = windowsXamlHost.GetUwpInternalObject() as OobeShellPage;
+
+ OobeShellPage.SetRunSharedEventCallback(() =>
+ {
+ return Constants.PowerLauncherSharedEvent();
+ });
+
+ OobeShellPage.SetColorPickerSharedEventCallback(() =>
+ {
+ return Constants.ShowColorPickerSharedEvent();
+ });
+
+ OobeShellPage.SetShortcutGuideSharedEventCallback(() =>
+ {
+ NativeMethods.AllowSetForegroundWindow(PowerToys.Settings.Program.PowerToysPID);
+ return Constants.ShowShortcutGuideSharedEvent();
+ });
+
+ OobeShellPage.SetOpenMainWindowCallback((Type type) =>
+ {
+ ((App)Application.Current).OpenSettingsWindow(type);
+ });
+ }
+ }
+}
diff --git a/src/settings-ui/PowerToys.Settings/Program.cs b/src/settings-ui/PowerToys.Settings/Program.cs
index ec365eca28..5c5424c9f2 100644
--- a/src/settings-ui/PowerToys.Settings/Program.cs
+++ b/src/settings-ui/PowerToys.Settings/Program.cs
@@ -19,10 +19,12 @@ namespace PowerToys.Settings
Theme, // used in the old settings
ElevatedStatus,
IsUserAdmin,
+ ShowOobeWindow,
}
// Quantity of arguments
- private const int ArgumentsQty = 6;
+ private const int RequiredArgumentsQty = 6;
+ private const int RequiredAndOptionalArgumentsQty = 7;
// Create an instance of the IPC wrapper.
private static TwoWayPipeMessageIPCManaged ipcmanager;
@@ -43,7 +45,7 @@ namespace PowerToys.Settings
App app = new App();
app.InitializeComponent();
- if (args != null && args.Length >= ArgumentsQty)
+ if (args != null && args.Length >= RequiredArgumentsQty)
{
_ = int.TryParse(args[(int)Arguments.PTPid], out int powerToysPID);
PowerToysPID = powerToysPID;
@@ -51,6 +53,12 @@ namespace PowerToys.Settings
IsElevated = args[(int)Arguments.ElevatedStatus] == "true";
IsUserAnAdmin = args[(int)Arguments.IsUserAdmin] == "true";
+ if (args.Length == RequiredAndOptionalArgumentsQty)
+ {
+ // open oobe window
+ app.ShowOobe = args[(int)Arguments.ShowOobeWindow] == "true";
+ }
+
RunnerHelper.WaitForPowerToysRunner(PowerToysPID, () =>
{
Environment.Exit(0);