diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index ec3898aa7e..d362237c6f 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,4 @@ -blank_issues_enabled: false +blank_issues_enabled: true contact_links: - name: "\U0001F4F7 Video Conference Mute Issue" url: https://github.com/microsoft/PowerToys/issues/6246 diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index e31bf2dce1..0826878799 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1,11 +1,9 @@ aac -AAD abcd abcdef abcdefgh abgr ABlocked -ABOUTBOX Abug accctrl Acceleratorkeys @@ -22,12 +20,10 @@ actioned activatable ACTIVATEAPP Addavirtualdesktop -Addins addrum ADDUNDORECORD ADifferent ADMINS -adopsinsider advapi advfirewall AFeature @@ -35,27 +31,22 @@ AFX AGGREGATABLE AHybrid Aissue -akamaihd ALarger alekhyareddy -alertsolid ALIGNLEFT ALLAPPS Alloc ALLOWUNDO -ALogo ALPHATYPE Altdown altform amd Amicrosoft -AMirror AModifier AMPROPERTY AMPROPSETID anges ansicolor -antialiased ANull AOC aocfnapldcnfbofgmbbllojgocaelgdd @@ -108,7 +99,6 @@ asm asmx aspnet aspx -asyncwebview ASYNCWINDOWPLACEMENT ASYNCWINDOWPOS atl @@ -120,7 +110,6 @@ atlstr attr Attribs aumid -Aut AUTHN AUTOAPPEND autocomplete @@ -176,14 +165,12 @@ bootstrapper BOTTOMALIGN BPBF bpp -Breadcrumb bricelam BRIGHTGREEN Browsable bsd bstr bti -Btn BTNFACE Bto buf @@ -196,7 +183,6 @@ buildtransitive BValue bytearray callbackptr -capitalized CANRENAME Captureascreenshot CAPTURECHANGED @@ -223,13 +209,8 @@ chdir checkbox checkboxes CHECKCANCELED -Checkedin -checknetisolation -Chicklet CHILDACTIVATE -Childof CHILDWINDOW -choiceref chrdavis Chris's chrono @@ -250,7 +231,6 @@ CLIENTPULL clientside CLIPCHILDREN CLIPSIBLINGS -CLogo clrcall cls CLSCTX @@ -277,7 +257,6 @@ Codespaces COINIT colorconv colorpicker -colorpickerref COLORREF colorscheme COLUMNCLICK @@ -290,12 +269,10 @@ comhost cominterop commandline commctrl -Commdlg -commondataservicecds Compat COMPOSITIONFULL comsupp -concat +Concat concrt config CONFLICTINGMODIFIERKEY @@ -312,8 +289,6 @@ CONTROLL CONTROLPARENT Controlz coords -COPYDATASTRUCT -corehr cortana cotaskmem COULDNOT @@ -321,7 +296,6 @@ countof countslabelrenamingfmt countslabelselectedfmt cout -CPlus CPower cpp CPPARM @@ -339,8 +313,6 @@ cref CRename critsec crlf -CRM -crmcustomerinsightsapp CRSEL crutkas CSearch @@ -371,7 +343,6 @@ CURSORINFO cursorpos CUSTOMACTIONTEST cvd -cw cwchar cwd cx @@ -393,7 +364,6 @@ DARKPURPLE DARKRED DARKTEAL DARKYELLOW -Dataflows Datavalue DATAW davidegiacometti @@ -444,18 +414,15 @@ desktopshorcutinstalled desktopwindowxamlsource dest DEU -Devagya devblogs devdocs devenum DEVMON df DFactory -Dialpad diffing difftime dimm -dirname dirs DISABLEASACTIONKEY dispid @@ -477,15 +444,12 @@ dllexport dllhost dllimport dllmain -DLogo -DMap DNLEN doctype DONTVALIDATEPATH dotnet DOUBLEBUFFER DOverlay -downlevel DOWNLOADONLY dpi DPICHANGED @@ -493,14 +457,11 @@ DPolicy DPopup DPSAPI Draggen -Drakula DRAWFRAME drawingcolor dreamsofameaningfullife drivedetectionwarning -DRM dropdown -dropref dshow dst DSVG @@ -528,110 +489,21 @@ dword dworigin dwrite dxgi -EABF -EAC -EACB -EACC -EADA -EADB -EADF -EAE -EAEE -EAEF -EAF -EAFC -EAFD Easeof -eb -EBC -EBD -EBDA -EBE -EBEC -EBEE -EBEF -EBF -EBFC -ECAA -ECAB -ECAC -ECAF -ECCA -ECCB -ECCD -ECDC -ECDE -ECDF -ECEB -ECED -ECEE +EB ecef -ECFE -ECFF ecount EDB -EDBB -EDBC -EDBD -EDBE -EDBF -EDCA -EDCB -EDCC -EDCD -EDCE -EDCF -EDDB -EDDC -EDDD -EDDE -EDDF -EDE ededf -EDFF -edgelogo -edgeoldlogo EDITKEYBOARD editkeyboardwindow -editorbody editorconfig -editorhead -editorheadbuttons -editortitle -editorzone EDITSHORTCUTS editshortcutswindow -Edu -EEB -EEBA -EEBB -EEBC -EEBD -EEBE -EEBF -EECB -EECC -EECD -EECE -EECF -EED -EEED -EEEF -EEF efa -EFB -EFBA -EFC -EFDA -EFDE -EFE -EFEB -EFFC -EFFE efgh EFile egistry -ELogo elseif Emoji emptyrecyclebin @@ -643,7 +515,6 @@ endregion Enque ENTERSIZEMOVE Entireitemname -Entitlements entrypoint ENU enum @@ -666,7 +537,6 @@ etw EUQ ev evenodd -eventdatemissed eventlog everytime EWXFORCE @@ -706,7 +576,6 @@ FANCYZONESDRAWLAYOUTTEST FANCYZONESEDITOR Farbraum FARPROC -Favicon fd feimage ffcd @@ -747,7 +616,6 @@ FPower FRAMECHANGED FRAMEDOWNLOAD Froml -FSharp fstream ftps FTYPE @@ -780,7 +648,6 @@ GETSTATE GETTEXT GETTEXTLENGTH gh -Giftbox github githubusercontent gitignore @@ -789,7 +656,6 @@ gmx GNumber google GPTR -grayscale gui guiddef GUITHREADINFO @@ -890,6 +756,7 @@ hxx Hyperlink IAction IActivated +IAnimatable IApp IApplication IAppx @@ -911,7 +778,6 @@ IComparer ICONERROR ICONINFORMATION ICONQUESTION -Iconset IContext ICONWARNING ICore @@ -935,6 +801,7 @@ IDrop idx IDXGI IDYES +IEasing IEnum IEnumerable IEnumerator @@ -954,12 +821,10 @@ IFile ifndef IFolder ifstream -IIcon iid IImage Iindex IInitialize -IInput IInspectable IItem IJson @@ -978,8 +843,6 @@ IMoniker IMonitor IMouse impl -INav -Inbox INDEXTOSTATEIMAGEMASK indierawk Infobar @@ -1018,7 +881,6 @@ INSTALLSTATE INSTALLUILEVEL Inste Intelli -Intellisense interactable Interlop interop @@ -1109,15 +971,13 @@ jp jpe jpeg jpg -jsoref JPN json jsonval -jsx +JSX junja jxr jyuwono -Kaizala kbd KBDLLHOOKSTRUCT kbm @@ -1133,10 +993,8 @@ keydown keydropdowncontrol keyevent KEYEVENTF -keynum -keyof keyhook -keyparts +keynum keyremaps keystokes Keystool @@ -1159,6 +1017,7 @@ LBUTTON LBUTTONDBLCLK LBUTTONDOWN LBUTTONUP +LCIDTo lcl Lclean LCONTROL @@ -1190,7 +1049,6 @@ Linux listbox listview llkhf -LLogo Llvm lmcons LMEM @@ -1264,8 +1122,7 @@ LVS LVSIL LWA lwin -Lync -lzw +LZW mailto MAINICON Mainwindow @@ -1289,7 +1146,6 @@ MATCHMODE MAXIMIZEBOX MAXSHORTCUTSIZE maxversiontested -mayitbeegh MBUTTON MBUTTONDBLCLK MBUTTONDOWN @@ -1326,11 +1182,9 @@ miniz minlevel MINMAXINFO Miracast -mixin MJPG mkdir -MLogo -MMI +mmi mockapi MODECHANGE moderncop @@ -1350,7 +1204,6 @@ MOUSESWITCH MOUSEWHEEL MOVESIZEEND MOVESIZESTART -Moveto MOVEWINDOWS moz mozilla @@ -1394,7 +1247,6 @@ mutexes muxc mvvm MYICON -myuri NAMECHANGE nameof NAMEONLY @@ -1488,10 +1340,8 @@ notmatch Noto NOTRACK NOUPDATE -nowrap NOZORDER npm -npmjs npos NResize ntdll @@ -1517,7 +1367,6 @@ Oem officehubintl ofs ofstream -Oject oldcolor olditem oldnewthing @@ -1528,11 +1377,7 @@ OleAut OLECHAR OLEDB OLIVEGREEN -OLogo -Onboarding onebranch -onedrive -onedrivelogo ONITEM onstd oobe @@ -1549,7 +1394,6 @@ ostr ostream ostringstream OSVERSIONINFOEXW -osx otating OUTOFCONTEXT OUTOFMEMORY @@ -1563,7 +1407,6 @@ PAINTSTRUCT PAIT PALEBLUE PALETTEWINDOW -Pano paramref params PARENTNOTIFY @@ -1580,7 +1423,6 @@ pcb pcelt pch PCIDLIST -PCOPYDATASTRUCT PCorswitchaccounts PCWSTR pdb @@ -1600,9 +1442,6 @@ pgp pguid phbm phbmp -Phishing -php -phptest phwnd pici pid @@ -1617,7 +1456,6 @@ PKBDLLHOOKSTRUCT placeholders plib PLK -PLogo plugin pluginsmodel plvdi @@ -1628,14 +1466,12 @@ pnm pnmdr pnmlv POINTL -pointstar policheck polymorpism popd popup POPUPWINDOW posix -powerappscds powerlauncher powerpreview powerrename @@ -1674,7 +1510,6 @@ prgms pri PRINTCLIENT printf -Printfax prm PROCESSKEY PRODUCTVERSION @@ -1718,8 +1553,6 @@ pwcs PWSTR pwtd px -py -Qand QI qianlifeng qit @@ -1825,7 +1658,6 @@ roslyn royvou rpc RRF -RSHIFT rshift Rsp rst @@ -1845,7 +1677,6 @@ runsettings runtimeclass runtimeconfig runtimes -rutkas rv rvalue rvm @@ -1866,7 +1697,6 @@ SCOPEID screenshot scrollable scrollviewer -scss sddl sdk SDKDDK @@ -1902,9 +1732,7 @@ Setttings SETWORKAREA sfgao SFGAOF -Sharei SHAREIMAGELISTS -Sharepoint sharpkeys shcore shellapi @@ -1913,7 +1741,6 @@ shellex SHELLEXECUTEINFO SHELLEXECUTEINFOW shellscalingapi -Shelveset SHFILEINFO SHGFI SHIFTDRAG @@ -1924,11 +1751,11 @@ shlwapi shobjidl SHORTCUTATLEAST shortcutcontrol +Shortcutguide SHORTCUTMAXONEACTIONKEY SHORTCUTNOREPEATEDMODIFIER SHORTCUTONEACTIONKEY SHORTCUTSTARTWITHMODIFIER -Shortcutguide Shortcuttool shortdate SHORTPATH @@ -1945,13 +1772,11 @@ sidepanel siex SIGABRT sigdn -Signin signtool SINGLEKEY singlekeyremapcontrol SINGLESEL singletones -sixpointstar SIZEBOX sizeg Sizename @@ -1964,11 +1789,8 @@ sketchapp SKIPOWNPROCESS sku SKYBLUE -Skype SLGP -Slideshow sln -SLogo SMALLICON SMTO Snd @@ -1981,9 +1803,7 @@ spdo spdth spec'ing spesi -spinbuttonref splitwstring -spoprod sppd sppre spsi @@ -2007,9 +1827,7 @@ sstream STACKFRAME stackoverflow stackpanel -Staffhub standalone -Starburst STARTF startupapps STARTUPINFO @@ -2026,8 +1844,8 @@ stdcall stdcpp stdcpplatest stdexcept -stdio stdin +stdio stdlib STDMETHODCALLTYPE STDMETHODIMP @@ -2042,9 +1860,8 @@ stoul stoull strcmp strftime -Strikethrough Stringified -stringify +Stringify STRINGIZE stringstream stringtable @@ -2057,14 +1874,11 @@ Stubless STYLECHANGED STYLECHANGING stylecop -stylesheet Subdir subfolder subkey SUBLANG subquery -subsetted -subsetter substr Superbar sut @@ -2072,13 +1886,10 @@ SVE svg SVGIn svgpreviewhandler -svgr -SVGSVG Switchbetweenvirtualdesktops SWP swprintf SYMED -Symlink SYMOPT SYNCPAINT sys @@ -2097,7 +1908,6 @@ SYSTEMTIME sz tadele Tahoma -talenthrcore talynone TApp TApplication @@ -2109,7 +1919,6 @@ targetnametoken targetsize targetver taskbar -Taskboard TASKID taskkill tasklist @@ -2121,7 +1930,6 @@ tcscpy TCustom td TDevice -Telemarketer Templated templatenamespace Temporarilypeekatthedesktop @@ -2135,7 +1943,6 @@ textblock textbox TEXTINCLUDE textref -TFVC tga thead THEMECHANGED @@ -2144,7 +1951,6 @@ THISCOMPONENT thre tif TILEDWINDOW -Timeline TIMERID timeunion timeutil @@ -2155,11 +1961,6 @@ tlbimp tmp TNP todo -toggleleft -toggleoff -toggleon -toggleref -toggleright toggleswitch toolbar toolset @@ -2177,16 +1978,11 @@ traies TRAYMOUSEMESSAGE TRK trl -truetype trunc -tslint TStr tsx tt -TVM tw -twelvepointstar -txyewy TYMED typedef TYPEKEY @@ -2195,12 +1991,10 @@ typename typeof typeparam TYPESHORTCUT -typings Tz UAC UAL uap -UCHAR udit UIA Uid @@ -2223,7 +2017,6 @@ UNCPRIORITY undef UNDNAME unescape -Ungroup unicode Unindent uninit @@ -2243,13 +2036,10 @@ UNLEN unlicense Unmap UNORM -Unpublish unregister unregistering unremapped unsubscribe -Unsync -Untag Updatelayout UPDOWNKEYDROPSLIST UPGRADINGPRODUCTCODE @@ -2303,7 +2093,6 @@ viewbox viewmodel virtualization Visibletrue -Visio visualbrush visualstudio vk @@ -2311,19 +2100,16 @@ VKey vm vmax vmin -Voicemail VOS VREDRAW VSC VSCBD vscode -vsconfig VSCROLL vse vsonline vstemplate VSTHRD -VSTS VSTT VTABLE Vtbl @@ -2348,20 +2134,15 @@ wcsnicmp wdp wdupenv weakme -webapp webcam webclient -webkit -webp webpack webpage website -webview wekyb Whichdoes whitespaces WIC -Wifi wifstream wih wiki @@ -2379,7 +2160,7 @@ WINDOWNAME WINDOWPLACEMENT WINDOWPOSCHANGED WINDOWPOSCHANGING -windowsapp +Windowsapp WINDOWSBUILDNUMBER windowsdesktop windowssearch @@ -2413,7 +2194,6 @@ WKSG wmain WMKEYDOWN WMKEYUP -wmonk wmp WMSYSKEYDOWN WMSYSKEYUP @@ -2422,7 +2202,6 @@ WNDCLASS WNDCLASSEX WNDCLASSEXW WNDPROC -woff wofstream wordpad workaround @@ -2455,14 +2234,12 @@ wxs xa xamarin xaml -XAngle XAttribute xbf XBUTTON XBUTTONDBLCLK XBUTTONDOWN XBUTTONUP -XCOPY XDiff XDocument XElement @@ -2485,15 +2262,12 @@ XToolset xunit XY Yaml -YAngle YDiff YESNO YIncrement yinwang -YLogo yml YOffset -YourUserName YStr YUY YUYV diff --git a/README.md b/README.md index 72c49243a2..0819bccbda 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline - Windows 10 v1903 (build 18362) or newer. - ⚠️ PowerToys minimum version of Windows 10 is v1903 starting with the 0.37 release -- Have [.NET Core 3.1.13 Desktop Runtime](https://dotnet.microsoft.com/download/dotnet-core/thank-you/runtime-desktop-3.1.13-windows-x64-installer). The installer should handle this but we want to directly make people aware. +- Have [.NET Core 3.1.14 Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-desktop-3.1.14-windows-x64-installer). The installer should handle this but we want to directly make people aware. ### Via GitHub with EXE [Recommended] diff --git a/doc/devdocs/modules/launcher/new-plugin-checklist.md b/doc/devdocs/modules/launcher/new-plugin-checklist.md index dbf4f99755..e3d05c6713 100644 --- a/doc/devdocs/modules/launcher/new-plugin-checklist.md +++ b/doc/devdocs/modules/launcher/new-plugin-checklist.md @@ -28,3 +28,10 @@ - [ ] Test the plugin with a local build. Build the installer, install, check that the plugin works as expected - [ ] All plugin's binaries have to be included in the signed build [`pipeline.user.windows.yml`](/.pipelines/pipeline.user.windows.yml) - [ ] The plugin target framework has to be .NET Core 3.1. All dependencies have to have .NET 5 version + +Some localization steps can only be done after the first pass by the localization team to provide the localized resources. +In the PR that adds a new plugin, reference a new issue to track the work for fully enabling localization for the new plugin. + + - [ ] Add the resource folder to https://github.com/microsoft/PowerToys/blob/21247c0bb09a1bee3d14d6efa53d0c247f7236af/installer/PowerToysSetup/Product.wxs#L825 + - [ ] Add the resource files under the section https://github.com/microsoft/PowerToys/blob/21247c0bb09a1bee3d14d6efa53d0c247f7236af/installer/PowerToysSetup/Product.wxs#L882 + \ No newline at end of file diff --git a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp index 144f54abaa..f2d996c30e 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp +++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp @@ -219,16 +219,6 @@ int Bootstrapper(HINSTANCE hInstance) SetupLogger(logDir, severity); spdlog::debug("PowerToys Bootstrapper is launched\nnoFullUI: {}\nsilent: {}\nno_start_pt: {}\nskip_dotnet_install: {}\nlog_level: {}\ninstall_dir: {}\nextract_msi: {}\n", noFullUI, g_Silent, noStartPT, skipDotnetInstall, logLevel, installDirArg, extractMsiOnly); - - const VersionHelper myVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); - - // Do not support installing on Windows < 1903 - if (myVersion >= VersionHelper{0, 36, 0} && updating::is_old_windows_version()) - { - ShowMessageBoxError(IDS_OLD_WINDOWS_ERROR); - spdlog::error("PowerToys {} requires at least Windows 1903 to run.", myVersion.toString()); - return 1; - } // If a user requested an MSI -> extract it and exit if (extractMsiOnly) @@ -241,9 +231,20 @@ int Bootstrapper(HINSTANCE hInstance) { spdlog::error("MSI installer couldn't be extracted"); } + return 0; } + const VersionHelper myVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); + + // Do not support installing on Windows < 1903 + if (updating::is_1809_or_older()) + { + ShowMessageBoxError(IDS_OLD_WINDOWS_ERROR); + spdlog::error("PowerToys {} requires at least Windows 1903 to run.", myVersion.toString()); + return 1; + } + // Check if there's a newer version installed const auto installedVersion = updating::get_installed_powertoys_version(); if (installedVersion && *installedVersion >= myVersion) diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 2c5529c5cd..7787e2984d 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -822,7 +822,7 @@ - + @@ -879,7 +879,7 @@ - + @@ -910,6 +910,9 @@ + + + diff --git a/src/common/interop/keyboard_layout.cpp b/src/common/interop/keyboard_layout.cpp index 8f00009f40..a37cc787de 100644 --- a/src/common/interop/keyboard_layout.cpp +++ b/src/common/interop/keyboard_layout.cpp @@ -1,11 +1,10 @@ #include "pch.h" +#include +#include + #include "keyboard_layout_impl.h" #include "shared_constants.h" -#include - -using namespace winrt; - LayoutMap::LayoutMap() : impl(new LayoutMap::LayoutMapImpl()) { diff --git a/src/common/updating/dotnet_installation.cpp b/src/common/updating/dotnet_installation.cpp index 7cd7383d6a..b3ad70f051 100644 --- a/src/common/updating/dotnet_installation.cpp +++ b/src/common/updating/dotnet_installation.cpp @@ -10,7 +10,7 @@ namespace fs = std::filesystem; namespace updating { - constexpr size_t REQUIRED_MINIMAL_PATCH = 13; + constexpr size_t REQUIRED_MINIMAL_PATCH = 14; bool dotnet_is_installed() { @@ -46,7 +46,7 @@ namespace updating std::optional download_dotnet() { - const wchar_t DOTNET_DESKTOP_DOWNLOAD_LINK[] = L"https://download.visualstudio.microsoft.com/download/pr/aa717f57-3ae5-48fa-a3ab-0018338d0726/fb37276b1575772461701339110e7a54/windowsdesktop-runtime-3.1.13-win-x64.exe"; + const wchar_t DOTNET_DESKTOP_DOWNLOAD_LINK[] = L"https://download.visualstudio.microsoft.com/download/pr/88437980-f813-4a01-865c-f992ad4909bb/9a936984781f6ce3526ffc946267e0ea/windowsdesktop-runtime-3.1.14-win-x64.exe"; const wchar_t DOTNET_DESKTOP_FILENAME[] = L"windowsdesktop-runtime.exe"; auto dotnet_download_path = fs::temp_directory_path() / DOTNET_DESKTOP_FILENAME; diff --git a/src/common/updating/installer.cpp b/src/common/updating/installer.cpp index fd5c7574c1..f7b4a673a3 100644 --- a/src/common/updating/installer.cpp +++ b/src/common/updating/installer.cpp @@ -193,7 +193,7 @@ namespace updating co_return false; } - bool is_old_windows_version() + bool is_1809_or_older() { return !Is19H1OrHigher(); } diff --git a/src/common/updating/installer.h b/src/common/updating/installer.h index 5263fe4e3e..0da8952482 100644 --- a/src/common/updating/installer.h +++ b/src/common/updating/installer.h @@ -17,5 +17,5 @@ namespace updating std::optional get_installed_powertoys_version(); std::future uninstall_previous_msix_version_async(); - bool is_old_windows_version(); + bool is_1809_or_older(); } \ No newline at end of file diff --git a/src/modules/colorPicker/ColorPickerUI/Behaviors/MoveWindowBehavior.cs b/src/modules/colorPicker/ColorPickerUI/Behaviors/MoveWindowBehavior.cs deleted file mode 100644 index 6a3f096d0c..0000000000 --- a/src/modules/colorPicker/ColorPickerUI/Behaviors/MoveWindowBehavior.cs +++ /dev/null @@ -1,60 +0,0 @@ -// 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 System.Windows.Media.Animation; -using Microsoft.Xaml.Behaviors; - -namespace ColorPicker.Behaviors -{ - public class MoveWindowBehavior : Behavior - { - public static readonly DependencyProperty LeftProperty = DependencyProperty.Register("Left", typeof(double), typeof(MoveWindowBehavior), new PropertyMetadata(new PropertyChangedCallback(LeftPropertyChanged))); - - private static void LeftPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var sender = ((MoveWindowBehavior)d).AssociatedObject; - var move = new DoubleAnimation(sender.Left, (double)e.NewValue, new Duration(TimeSpan.FromMilliseconds(150)), FillBehavior.Stop); - move.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut }; - sender.BeginAnimation(Window.LeftProperty, move, HandoffBehavior.Compose); - } - - public static readonly DependencyProperty TopProperty = DependencyProperty.Register("Top", typeof(double), typeof(MoveWindowBehavior), new PropertyMetadata(new PropertyChangedCallback(TopPropertyChanged))); - - private static void TopPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var sender = ((MoveWindowBehavior)d).AssociatedObject; - var move = new DoubleAnimation(sender.Top, (double)e.NewValue, new Duration(TimeSpan.FromMilliseconds(150)), FillBehavior.Stop); - move.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut }; - sender.BeginAnimation(Window.TopProperty, move, HandoffBehavior.Compose); - } - - public double Left - { - get - { - return (double)GetValue(LeftProperty); - } - - set - { - SetValue(LeftProperty, value); - } - } - - public double Top - { - get - { - return (double)GetValue(TopProperty); - } - - set - { - SetValue(TopProperty, value); - } - } - } -} diff --git a/src/modules/colorPicker/ColorPickerUI/Behaviors/ResizeBehavior.cs b/src/modules/colorPicker/ColorPickerUI/Behaviors/ResizeBehavior.cs index 1f7c3b5857..5424f44acd 100644 --- a/src/modules/colorPicker/ColorPickerUI/Behaviors/ResizeBehavior.cs +++ b/src/modules/colorPicker/ColorPickerUI/Behaviors/ResizeBehavior.cs @@ -11,20 +11,55 @@ namespace ColorPicker.Behaviors { public class ResizeBehavior : Behavior { + // animation behavior variables + // used when size is getting bigger + private static readonly TimeSpan _animationTime = TimeSpan.FromMilliseconds(200); + private static readonly IEasingFunction _easeFunction = new SineEase() { EasingMode = EasingMode.EaseOut }; + + // used when size is getting smaller + private static readonly TimeSpan _animationTimeSmaller = _animationTime; + private static readonly IEasingFunction _easeFunctionSmaller = new QuadraticEase() { EasingMode = EasingMode.EaseIn }; + + private static void CustomAnimation(DependencyProperty prop, IAnimatable sender, double fromValue, double toValue) + { + // if the animation is to/from a value of 0, it will cancel the current animation + DoubleAnimation move = null; + if (toValue > 0 && fromValue > 0) + { + // if getting bigger + if (fromValue < toValue) + { + move = new DoubleAnimation(fromValue, toValue, new Duration(_animationTime), FillBehavior.Stop) + { + EasingFunction = _easeFunction, + }; + } + else + { + move = new DoubleAnimation(fromValue, toValue, new Duration(_animationTimeSmaller), FillBehavior.Stop) + { + EasingFunction = _easeFunctionSmaller, + }; + } + } + + // HandoffBehavior must be SnapshotAndReplace + // Compose does not allow cancellation + sender.BeginAnimation(prop, move, HandoffBehavior.SnapshotAndReplace); + } + public static readonly DependencyProperty WidthProperty = DependencyProperty.Register("Width", typeof(double), typeof(ResizeBehavior), new PropertyMetadata(new PropertyChangedCallback(WidthPropertyChanged))); private static void WidthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var sender = ((ResizeBehavior)d).AssociatedObject; - var move = new DoubleAnimation(sender.Width, (double)e.NewValue, new Duration(TimeSpan.FromMilliseconds(150)), FillBehavior.Stop); - move.Completed += (s, e1) => - { - sender.BeginAnimation(FrameworkElement.WidthProperty, null); - sender.Width = (double)e.NewValue; - }; - move.EasingFunction = new QuadraticEase() { EasingMode = EasingMode.EaseOut }; - sender.BeginAnimation(FrameworkElement.WidthProperty, move, HandoffBehavior.Compose); + var fromValue = sender.Width; + var toValue = (double)e.NewValue; + + // setting Width before animation prevents jumping + sender.Width = toValue; + CustomAnimation(FrameworkElement.WidthProperty, sender, fromValue, toValue); } public static readonly DependencyProperty HeightProperty = DependencyProperty.Register("Height", typeof(double), typeof(ResizeBehavior), new PropertyMetadata(new PropertyChangedCallback(HeightPropertyChanged))); @@ -32,15 +67,13 @@ namespace ColorPicker.Behaviors private static void HeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var sender = ((ResizeBehavior)d).AssociatedObject; - var move = new DoubleAnimation(sender.Height, (double)e.NewValue, new Duration(TimeSpan.FromMilliseconds(150)), FillBehavior.Stop); - move.Completed += (s, e1) => - { - sender.BeginAnimation(FrameworkElement.HeightProperty, null); - sender.Height = (double)e.NewValue; - }; - move.EasingFunction = new QuadraticEase() { EasingMode = EasingMode.EaseOut }; - sender.BeginAnimation(FrameworkElement.HeightProperty, move, HandoffBehavior.Compose); + var fromValue = sender.Height; + var toValue = (double)e.NewValue; + + // setting Height before animation prevents jumping + sender.Height = toValue; + CustomAnimation(FrameworkElement.HeightProperty, sender, fromValue, toValue); } public double Width diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/ZoomWindowHelper.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/ZoomWindowHelper.cs index ffd61da6ff..ad9564260d 100644 --- a/src/modules/colorPicker/ColorPickerUI/Helpers/ZoomWindowHelper.cs +++ b/src/modules/colorPicker/ColorPickerUI/Helpers/ZoomWindowHelper.cs @@ -18,33 +18,27 @@ namespace ColorPicker.Helpers [Export(typeof(ZoomWindowHelper))] public class ZoomWindowHelper { - private const int ZoomWindowChangeDelayInMS = 50; private const int ZoomFactor = 2; private const int BaseZoomImageSize = 50; private const int MaxZoomLevel = 4; private const int MinZoomLevel = 0; + private static readonly Bitmap _bmp = new Bitmap(BaseZoomImageSize, BaseZoomImageSize, PixelFormat.Format32bppArgb); + private static readonly Graphics _graphics = Graphics.FromImage(_bmp); + private readonly IZoomViewModel _zoomViewModel; private readonly AppStateHandler _appStateHandler; - private readonly IThrottledActionInvoker _throttledActionInvoker; private int _currentZoomLevel; private int _previousZoomLevel; private ZoomWindow _zoomWindow; - private double _lastLeft; - private double _lastTop; - - private double _previousScaledX; - private double _previousScaledY; - [ImportingConstructor] - public ZoomWindowHelper(IZoomViewModel zoomViewModel, AppStateHandler appStateHandler, IThrottledActionInvoker throttledActionInvoker) + public ZoomWindowHelper(IZoomViewModel zoomViewModel, AppStateHandler appStateHandler) { _zoomViewModel = zoomViewModel; _appStateHandler = appStateHandler; - _throttledActionInvoker = throttledActionInvoker; _appStateHandler.AppClosed += AppStateHandler_AppClosed; _appStateHandler.AppHidden += AppStateHandler_AppClosed; } @@ -73,7 +67,7 @@ namespace ColorPicker.Helpers { _currentZoomLevel = 0; _previousZoomLevel = 0; - HideZoomWindow(); + HideZoomWindow(true); } private void SetZoomImage(System.Windows.Point point) @@ -89,28 +83,17 @@ namespace ColorPicker.Helpers { var x = (int)point.X - (BaseZoomImageSize / 2); var y = (int)point.Y - (BaseZoomImageSize / 2); - var rect = new Rectangle(x, y, BaseZoomImageSize, BaseZoomImageSize); - using (var bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb)) - { - var g = Graphics.FromImage(bmp); - g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy); + _graphics.CopyFromScreen(x, y, 0, 0, _bmp.Size, CopyPixelOperation.SourceCopy); - var bitmapImage = BitmapToImageSource(bmp); - - _zoomViewModel.ZoomArea = bitmapImage; - _zoomViewModel.ZoomFactor = 1; - } + _zoomViewModel.ZoomArea = BitmapToImageSource(_bmp); } else { - var enlarge = (_currentZoomLevel - _previousZoomLevel) > 0 ? true : false; - var currentZoomFactor = enlarge ? ZoomFactor : 1.0 / ZoomFactor; - - _zoomViewModel.ZoomFactor *= currentZoomFactor; + _zoomViewModel.ZoomFactor = Math.Pow(ZoomFactor, _currentZoomLevel - 1); } - ShowZoomWindow((int)point.X, (int)point.Y); + ShowZoomWindow(point); } private static BitmapSource BitmapToImageSource(Bitmap bitmap) @@ -130,84 +113,67 @@ namespace ColorPicker.Helpers } } - private void HideZoomWindow() + private void HideZoomWindow(bool fully = false) { if (_zoomWindow != null) { - _zoomWindow.Hide(); + _zoomWindow.Opacity = 0; + _zoomViewModel.DesiredWidth = 0; + _zoomViewModel.DesiredHeight = 0; + + if (fully) + { + _zoomWindow.Hide(); + } } } - private void ShowZoomWindow(int x, int y) + private void ShowZoomWindow(System.Windows.Point point) { - if (_zoomWindow == null) + _zoomWindow ??= new ZoomWindow { - _zoomWindow = new ZoomWindow(); - _zoomWindow.Content = _zoomViewModel; - _zoomWindow.Loaded += ZoomWindow_Loaded; - _zoomWindow.IsVisibleChanged += ZoomWindow_IsVisibleChanged; - } + Content = _zoomViewModel, + Opacity = 0, + }; - // we just started zooming, remember where we opened zoom window - if (_currentZoomLevel == 1 && _previousZoomLevel == 0) - { - var dpi = MonitorResolutionHelper.GetCurrentMonitorDpi(); - _previousScaledX = x / dpi.DpiScaleX; - _previousScaledY = y / dpi.DpiScaleY; - } - - _lastLeft = Math.Floor(_previousScaledX - (BaseZoomImageSize * Math.Pow(ZoomFactor, _currentZoomLevel - 1) / 2)); - _lastTop = Math.Floor(_previousScaledY - (BaseZoomImageSize * Math.Pow(ZoomFactor, _currentZoomLevel - 1) / 2)); - - var justShown = false; if (!_zoomWindow.IsVisible) { - _zoomWindow.Left = _lastLeft; - _zoomWindow.Top = _lastTop; - _zoomViewModel.Height = BaseZoomImageSize; - _zoomViewModel.Width = BaseZoomImageSize; _zoomWindow.Show(); - justShown = true; + } + + if (_zoomWindow.Opacity < 0.5) + { + var halfWidth = _zoomWindow.Width / 2; + var halfHeight = _zoomWindow.Height / 2; + + // usually takes 1-3 iterations to converge + // 5 is just an arbitrary limit to prevent infinite loops + for (var i = 0; i < 5; i++) + { + // mouse position relative to top left of _zoomWindow + var scaledPoint = _zoomWindow.PointFromScreen(point); + + var diffX = scaledPoint.X - halfWidth; + var diffY = scaledPoint.Y - halfHeight; + + // minimum difference that is considered important + const double minDiff = 0.05; + if (Math.Abs(diffX) < minDiff && Math.Abs(diffY) < minDiff) + { + break; + } + + _zoomWindow.Left += diffX; + _zoomWindow.Top += diffY; + } // make sure color picker window is on top of just opened zoom window AppStateHandler.SetTopMost(); + _zoomWindow.Opacity = 1; } - // dirty hack - sometimes when we just show a window on a second monitor with different DPI, - // window position is not set correctly on a first time, we need to "ping" it again to make it appear on the proper location - if (justShown) - { - _zoomWindow.Left = _lastLeft + 1; - _zoomWindow.Top = _lastTop + 1; - SessionEventHelper.Event.ZoomUsed = true; - } - - _throttledActionInvoker.ScheduleAction( - () => - { - _zoomWindow.DesiredLeft = _lastLeft; - _zoomWindow.DesiredTop = _lastTop; - _zoomViewModel.DesiredHeight = BaseZoomImageSize * _zoomViewModel.ZoomFactor; - _zoomViewModel.DesiredWidth = BaseZoomImageSize * _zoomViewModel.ZoomFactor; - }, - ZoomWindowChangeDelayInMS); - } - - private void ZoomWindow_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) - { - // need to set at this point again, to avoid issues moving between screens with different scaling - if ((bool)e.NewValue) - { - _zoomWindow.Left = _lastLeft; - _zoomWindow.Top = _lastTop; - } - } - - private void ZoomWindow_Loaded(object sender, RoutedEventArgs e) - { - // need to call it again at load time, because it does was not dpi aware at the first time of Show() call - _zoomWindow.Left = _lastLeft; - _zoomWindow.Top = _lastTop; + _zoomViewModel.DesiredHeight = BaseZoomImageSize * _zoomViewModel.ZoomFactor; + _zoomViewModel.DesiredWidth = BaseZoomImageSize * _zoomViewModel.ZoomFactor; } private void AppStateHandler_AppClosed(object sender, EventArgs e) diff --git a/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs b/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs index 25ddd3aaf6..7bc46756ca 100644 --- a/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs +++ b/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs @@ -133,7 +133,17 @@ namespace ColorPicker.ViewModels { ClipboardHelper.CopyToClipboard(ColorText); - _userSettings.ColorHistory.Insert(0, GetColorString()); + var color = GetColorString(); + + var oldIndex = _userSettings.ColorHistory.IndexOf(color); + if (oldIndex != -1) + { + _userSettings.ColorHistory.Move(oldIndex, 0); + } + else + { + _userSettings.ColorHistory.Insert(0, color); + } if (_userSettings.ColorHistory.Count > _userSettings.ColorHistoryLimit.Value) { diff --git a/src/modules/colorPicker/ColorPickerUI/Views/ZoomView.xaml b/src/modules/colorPicker/ColorPickerUI/Views/ZoomView.xaml index 1c5c0214cb..5c6c617f6f 100644 --- a/src/modules/colorPicker/ColorPickerUI/Views/ZoomView.xaml +++ b/src/modules/colorPicker/ColorPickerUI/Views/ZoomView.xaml @@ -11,6 +11,8 @@ Focusable="False"> - diff --git a/src/modules/colorPicker/ColorPickerUI/ZoomWindow.xaml.cs b/src/modules/colorPicker/ColorPickerUI/ZoomWindow.xaml.cs index 2fac62c8b3..8434b8879d 100644 --- a/src/modules/colorPicker/ColorPickerUI/ZoomWindow.xaml.cs +++ b/src/modules/colorPicker/ColorPickerUI/ZoomWindow.xaml.cs @@ -10,50 +10,16 @@ namespace ColorPicker /// /// Interaction logic for ZoomWindow.xaml /// - public partial class ZoomWindow : Window, INotifyPropertyChanged + public partial class ZoomWindow : Window { - private double _left; - private double _top; - public ZoomWindow() { InitializeComponent(); DataContext = this; - } - public double DesiredLeft - { - get - { - return _left; - } - - set - { - _left = value; - NotifyPropertyChanged(nameof(DesiredLeft)); - } - } - - public double DesiredTop - { - get - { - return _top; - } - - set - { - _top = value; - NotifyPropertyChanged(nameof(DesiredTop)); - } - } - - public event PropertyChangedEventHandler PropertyChanged; - - private void NotifyPropertyChanged(string propertyName) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + // must be large enough to fit max zoom + Width = 500; + Height = 500; } } } diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml index c372a74c8b..bb3c1abe77 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml +++ b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml @@ -10,21 +10,9 @@ + - - diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/CanvasEditorWindow.xaml b/src/modules/fancyzones/editor/FancyZonesEditor/CanvasEditorWindow.xaml index 2488816fed..f483b4374f 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/CanvasEditorWindow.xaml +++ b/src/modules/fancyzones/editor/FancyZonesEditor/CanvasEditorWindow.xaml @@ -12,7 +12,7 @@ BorderThickness="0" xmlns:ui="http://schemas.modernwpf.com/2019" ui:WindowHelper.UseModernWindowStyle="True" - ui:TitleBar.IsIconVisible="True" + ui:TitleBar.IsIconVisible="False" SizeToContent="Height" Background="{DynamicResource PrimaryBackgroundBrush}" ResizeMode="NoResize" @@ -45,6 +45,7 @@ FontFamily="Segoe MDL2 Assets" Content="" FontSize="24" + TabIndex="0" ToolTip="{x:Static props:Resources.Add_zone}" DataContext="{Binding Path=Model, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" IsEnabled="{Binding IsZoneAddingAllowed}" @@ -60,9 +61,11 @@ Style="{StaticResource DefaultButtonStyle}" HorizontalAlignment="Stretch" Grid.Column="2" + TabIndex="2" Click="OnCancel" /> - - - - - + + + + + + + + + + +