diff --git a/PowerToys.sln b/PowerToys.sln index 94b05bacb7..b794636e50 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -470,8 +470,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPOWrapperProjection", "src EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Peek", "Peek", "{17B4FA70-001E-4D33-BBBB-0D142DBC2E20}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Peek.UI.WPF", "src\modules\peek\Peek.UI.WPF\Peek.UI.WPF.csproj", "{C0240BC3-95AF-4B38-811A-76E3FD56B576}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Peek", "src\modules\peek\peek\peek.vcxproj", "{A1425B53-3D61-4679-8623-E64A0D3D0A48}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Peek.UI", "src\modules\peek\Peek.UI\Peek.UI.csproj", "{9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}" @@ -1927,18 +1925,6 @@ Global {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Release|x64.Build.0 = Release|x64 {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Release|x86.ActiveCfg = Release|x64 {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Release|x86.Build.0 = Release|x64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Debug|ARM64.Build.0 = Debug|ARM64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Debug|x64.ActiveCfg = Debug|x64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Debug|x64.Build.0 = Debug|x64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Debug|x86.ActiveCfg = Debug|x64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Debug|x86.Build.0 = Debug|x64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Release|ARM64.ActiveCfg = Release|ARM64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Release|ARM64.Build.0 = Release|ARM64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Release|x64.ActiveCfg = Release|x64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Release|x64.Build.0 = Release|x64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Release|x86.ActiveCfg = Release|x64 - {C0240BC3-95AF-4B38-811A-76E3FD56B576}.Release|x86.Build.0 = Release|x64 {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Debug|ARM64.Build.0 = Debug|ARM64 {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Debug|x64.ActiveCfg = Debug|x64 @@ -2275,7 +2261,6 @@ Global {E599C30B-9DC8-4E5A-BF27-93D4CCEDE788} = {1AFB6476-670D-4E80-A464-657E01DFF482} {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97} = {1AFB6476-670D-4E80-A464-657E01DFF482} {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {C0240BC3-95AF-4B38-811A-76E3FD56B576} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} {A1425B53-3D61-4679-8623-E64A0D3D0A48} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} diff --git a/src/modules/peek/Peek.UI.WPF/App.xaml b/src/modules/peek/Peek.UI.WPF/App.xaml deleted file mode 100644 index 1fc9407448..0000000000 --- a/src/modules/peek/Peek.UI.WPF/App.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/peek/Peek.UI.WPF/App.xaml.cs b/src/modules/peek/Peek.UI.WPF/App.xaml.cs deleted file mode 100644 index 54225caef6..0000000000 --- a/src/modules/peek/Peek.UI.WPF/App.xaml.cs +++ /dev/null @@ -1,94 +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.Threading; -using System.Windows; -using Common.UI; -using ManagedCommon; - -namespace Peek.UI -{ - /// - /// Interaction logic for App.xaml - /// - public partial class App : Application, IDisposable - { - private ThemeManager? _themeManager; - - private Mutex? _instanceMutex; - private static string[] _args = Array.Empty(); - private int _powerToysRunnerPid; - private bool disposedValue; - - // TODO: Make sure no window appears or blinks at startup - protected override void OnStartup(StartupEventArgs e) - { - _args = e?.Args ?? Array.Empty(); - - // allow only one instance of peek - _instanceMutex = new Mutex(true, @"Local\PowerToys_Peek_InstanceMutex", out bool createdNew); - if (!createdNew) - { - _instanceMutex = null; - Environment.Exit(0); - return; - } - - if (_args?.Length > 0) - { - _ = int.TryParse(_args[0], out _powerToysRunnerPid); - - RunnerHelper.WaitForPowerToysRunner(_powerToysRunnerPid, () => - { - Environment.Exit(0); - }); - } - else - { - _powerToysRunnerPid = -1; - } - - _themeManager = new ThemeManager(this); - base.OnStartup(e); - } - - protected override void OnExit(ExitEventArgs e) - { - if (_instanceMutex != null) - { - _instanceMutex.ReleaseMutex(); - } - - base.OnExit(e); - } - - protected virtual void Dispose(bool disposing) - { - if (!disposedValue) - { - if (disposing) - { - _instanceMutex?.Dispose(); - } - - // TODO: free unmanaged resources (unmanaged objects) and override finalizer - // TODO: set large fields to null - disposedValue = true; - } - } - - public void Dispose() - { - // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method - Dispose(true); - GC.SuppressFinalize(this); - } - - public bool IsRunningDetachedFromPowerToys() - { - return _powerToysRunnerPid == -1; - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/AssemblyInfo.cs b/src/modules/peek/Peek.UI.WPF/AssemblyInfo.cs deleted file mode 100644 index bcac370d7d..0000000000 --- a/src/modules/peek/Peek.UI.WPF/AssemblyInfo.cs +++ /dev/null @@ -1,10 +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.Windows; - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, // where theme specific resource dictionaries are located (used if a resource is not found in the page, or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly) // where the generic resource dictionary is locate (used if a resource is not found in the page, app, or any theme specific resource dictionaries) -] diff --git a/src/modules/peek/Peek.UI.WPF/Assets/error.png b/src/modules/peek/Peek.UI.WPF/Assets/error.png deleted file mode 100644 index c2eb2fc2df..0000000000 Binary files a/src/modules/peek/Peek.UI.WPF/Assets/error.png and /dev/null differ diff --git a/src/modules/peek/Peek.UI.WPF/Extensions/LinkedListNodeExtensions.cs b/src/modules/peek/Peek.UI.WPF/Extensions/LinkedListNodeExtensions.cs deleted file mode 100644 index 5e740726e4..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Extensions/LinkedListNodeExtensions.cs +++ /dev/null @@ -1,21 +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.Collections.Generic; - -namespace Peek.UI.Extensions -{ - public static class LinkedListNodeExtensions - { - public static LinkedListNode? GetNextOrFirst(this LinkedListNode current) - { - return current.Next ?? current.List?.First; - } - - public static LinkedListNode? GetPreviousOrLast(this LinkedListNode current) - { - return current.Previous ?? current.List?.Last; - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Extensions/SizeExtensions.cs b/src/modules/peek/Peek.UI.WPF/Extensions/SizeExtensions.cs deleted file mode 100644 index 19ac26c8b9..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Extensions/SizeExtensions.cs +++ /dev/null @@ -1,61 +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.Windows; - -namespace Peek.UI.Extensions -{ - public static class SizeExtensions - { - public static Rect Fit(this Size sizeToFit, Rect bounds, Size maxSize, Size minSize, Size allowedGap, double reservedHeight) - { - double resultingWidth = sizeToFit.Width; - double resultingHeight = sizeToFit.Height; - - var ratioWidth = sizeToFit.Width / maxSize.Width; - var ratioHeight = sizeToFit.Height / maxSize.Height; - - if (ratioWidth > ratioHeight) - { - if (ratioWidth > 1) - { - resultingWidth = maxSize.Width; - resultingHeight = sizeToFit.Height / ratioWidth; - } - } - else - { - if (ratioHeight > 1) - { - resultingWidth = sizeToFit.Width / ratioHeight; - resultingHeight = maxSize.Height; - } - } - - if (resultingWidth < minSize.Width - allowedGap.Width) - { - resultingWidth = minSize.Width; - } - - if (resultingHeight < minSize.Height - allowedGap.Height) - { - resultingHeight = minSize.Height; - } - - resultingHeight += reservedHeight; - - // Calculate offsets to center content - double offsetX = (maxSize.Width - resultingWidth) / 2; - double offsetY = (maxSize.Height - resultingHeight) / 2; - - var maxWindowLeft = bounds.Left + ((bounds.Right - bounds.Left - maxSize.Width) / 2); - var maxWindowTop = bounds.Top + ((bounds.Bottom - bounds.Top - maxSize.Height) / 2); - - var resultingLeft = maxWindowLeft + offsetX; - var resultingTop = maxWindowTop + offsetY; - - return new Rect(resultingLeft, resultingTop, resultingWidth, resultingHeight); - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Extensions/WindowExtensions.cs b/src/modules/peek/Peek.UI.WPF/Extensions/WindowExtensions.cs deleted file mode 100644 index 17abcda12c..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Extensions/WindowExtensions.cs +++ /dev/null @@ -1,41 +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.Interop; -using Peek.UI.Native; -using static Peek.UI.Native.NativeModels; - -namespace Peek.UI.Extensions -{ - public static class WindowExtensions - { - public static void SetToolStyle(this Window window) - { - var handle = new WindowInteropHelper(window).Handle; - _ = NativeMethods.SetWindowLong(handle, GwlExStyle, NativeMethods.GetWindowLong(handle, GwlExStyle) | WsExToolWindow); - } - - public static void BringToForeground(this Window window) - { - // Use SendInput hack to allow Activate to work - required to resolve focus issue https://github.com/microsoft/PowerToys/issues/4270 - Input input = new Input { Type = InputType.InputMouse, Data = { } }; - Input[] inputs = new Input[] { input }; - - // Send empty mouse event. This makes this thread the last to send input, and hence allows it to pass foreground permission checks - _ = NativeMethods.SendInput(1, inputs, Input.Size); - - window.Activate(); - } - - public static void RoundCorners(this Window window) - { - IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(Window.GetWindow(window)).EnsureHandle(); - var attribute = DwmWindowAttributed.DwmaWindowCornerPreference; - var preference = DwmWindowCornerPreference.DwmCpRound; - NativeMethods.DwmSetWindowAttribute(hWnd, attribute, ref preference, sizeof(uint)); - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Helpers/FileExplorerHelper.cs b/src/modules/peek/Peek.UI.WPF/Helpers/FileExplorerHelper.cs deleted file mode 100644 index c5262a3279..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Helpers/FileExplorerHelper.cs +++ /dev/null @@ -1,34 +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.Collections.Generic; - -namespace Peek.UI.Helpers -{ - public static class FileExplorerHelper - { - public static IEnumerable GetSelectedItems(IntPtr handle) - { - var selectedItems = new List(); - var shell = new Shell32.Shell(); - foreach (SHDocVw.InternetExplorer window in shell.Windows()) - { - if (window.HWND == (int)handle) - { - Shell32.FolderItems items = ((Shell32.IShellFolderViewDual2)window.Document).SelectedItems(); - if (items != null && items.Count > 0) - { - foreach (Shell32.FolderItem item in items) - { - selectedItems.Add(item.Path); - } - } - } - } - - return selectedItems; - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Helpers/FileLoadHelper.cs b/src/modules/peek/Peek.UI.WPF/Helpers/FileLoadHelper.cs deleted file mode 100644 index e43e7d72c2..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Helpers/FileLoadHelper.cs +++ /dev/null @@ -1,122 +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.Drawing.Imaging; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Media.Imaging; -using Peek.UI.Models; - -namespace Peek.UI.Helpers -{ - public static class FileLoadHelper - { - public static Task LoadDimensionsAsync(string filename) - { - return Task.Run(() => - { - Size size = new Size(0, 0); - try - { - using (FileStream stream = File.OpenRead(filename)) - { - string extension = Path.GetExtension(stream.Name); - if (FileTypeHelper.IsSupportedImage(extension)) - { - using (System.Drawing.Image sourceImage = System.Drawing.Image.FromStream(stream, false, false)) - { - var rotation = EvaluateRotationToApply(sourceImage); - if (rotation == Rotation.Rotate90 || rotation == Rotation.Rotate270) - { - size = new Size(sourceImage.Height, sourceImage.Width); - } - else - { - size = new Size(sourceImage.Width, sourceImage.Height); - } - - return Task.FromResult(new DimensionData { Size = size, Rotation = rotation }); - } - } - else - { - return Task.FromResult(new DimensionData { Size = size, Rotation = Rotation.Rotate0 }); - } - } - } - catch (Exception) - { - return Task.FromResult(new DimensionData { Size = size, Rotation = Rotation.Rotate0 }); - } - }); - } - - public static async Task LoadThumbnailAsync(string filename, bool iconFallback) - { - var thumbnail = await Task.Run(() => - { - var bitmapSource = ThumbnailHelper.GetThumbnail(filename, iconFallback); - bitmapSource.Freeze(); - return bitmapSource; - }); - - return thumbnail; - } - - public static Task LoadIconAsync(string filename) - { - return Task.Run(() => - { - var bitmapSource = ThumbnailHelper.GetIcon(filename); - bitmapSource.Freeze(); - return bitmapSource; - }); - } - - public static Task LoadFullImageAsync(string filename, Rotation rotation) - { - return Task.Run(() => - { - var bitmap = new BitmapImage(); - bitmap.BeginInit(); - bitmap.CacheOption = BitmapCacheOption.OnLoad; - bitmap.UriSource = new Uri(filename); - bitmap.Rotation = rotation; - bitmap.EndInit(); - bitmap.Freeze(); - return bitmap; - }); - } - - private static Rotation EvaluateRotationToApply(System.Drawing.Image image) - { - PropertyItem? property = image.PropertyItems?.FirstOrDefault(p => p.Id == 274); - - if (property != null && property.Value != null && property.Value.Length > 0) - { - int orientation = property.Value[0]; - - if (orientation == 6) - { - return Rotation.Rotate90; - } - - if (orientation == 3) - { - return Rotation.Rotate180; - } - - if (orientation == 8) - { - return Rotation.Rotate270; - } - } - - return Rotation.Rotate0; - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Helpers/FileTypeHelper.cs b/src/modules/peek/Peek.UI.WPF/Helpers/FileTypeHelper.cs deleted file mode 100644 index 40b6a2ad23..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Helpers/FileTypeHelper.cs +++ /dev/null @@ -1,77 +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 Peek.UI.Native; -using static Peek.UI.Native.NativeModels; - -namespace Peek.UI.Helpers -{ - public static class FileTypeHelper - { - public static bool IsSupportedImage(string extension) => extension switch - { - ".bmp" => true, - ".gif" => true, - ".jpg" => true, - ".jfif" => true, - ".jfi" => true, - ".jif" => true, - ".jpeg" => true, - ".jpe" => true, - ".png" => true, - ".tif" => true, - ".tiff" => true, - _ => false, - }; - - public static bool IsMedia(string extension) - { - return IsImage(extension) || IsVideo(extension); - } - - public static bool IsImage(string extension) - { - return IsPerceivedType(extension, PerceivedType.Image); - } - - public static bool IsVideo(string extension) - { - return IsPerceivedType(extension, PerceivedType.Video); - } - - public static bool IsDocument(string extension) - { - return IsPerceivedType(extension, PerceivedType.Document); - } - - internal static bool IsPerceivedType(string extension, PerceivedType perceivedType) - { - if (string.IsNullOrEmpty(extension)) - { - return false; - } - - PerceivedType perceived; - Perceived flag; - bool isPerceivedType = false; - - try - { - if (NativeMethods.AssocGetPerceivedType(extension, out perceived, out flag, IntPtr.Zero) == HResult.Ok) - { - isPerceivedType = perceived == perceivedType; - } - } - catch (Exception) - { - // TODO: AssocGetPerceivedType throws on some file types (json, ps1, exe, etc.) - // Properly handle these - return false; - } - - return isPerceivedType; - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Helpers/ThumbnailHelper.cs b/src/modules/peek/Peek.UI.WPF/Helpers/ThumbnailHelper.cs deleted file mode 100644 index 77a9bcf099..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Helpers/ThumbnailHelper.cs +++ /dev/null @@ -1,128 +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.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Windows; -using System.Windows.Interop; -using System.Windows.Media.Imaging; -using Peek.UI.Models; -using Peek.UI.Native; -using static Peek.UI.Native.NativeModels; - -namespace Peek.UI.Helpers -{ - public static class ThumbnailHelper - { - private static readonly Assembly Assembly = Assembly.GetExecutingAssembly(); - public static readonly string ProgramDirectory = Directory.GetParent(Assembly.Location)!.ToString(); - public static readonly string ErrorIcon = Path.Combine(ProgramDirectory, "Assets", "error.png"); - - // Based on https://stackoverflow.com/questions/21751747/extract-thumbnail-for-any-file-in-windows - private const string IShellItem2Guid = "7E9FB0D3-919F-4307-AB2E-9B1860310C93"; - - public static BitmapSource GetIcon(string fileName) - { - IntPtr hbitmap; - HResult hr = GetIconImpl(Path.GetFullPath(fileName), out hbitmap); - - if (hr != HResult.Ok) - { - return new BitmapImage(new Uri(ErrorIcon)); - } - - try - { - return Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); - } - finally - { - // delete HBitmap to avoid memory leaks - NativeMethods.DeleteObject(hbitmap); - } - } - - public static BitmapSource GetThumbnail(string fileName, bool iconFallback) - { - IntPtr hbitmap; - HResult hr = GetThumbnailImpl(Path.GetFullPath(fileName), out hbitmap); - - if (hr != HResult.Ok && iconFallback) - { - return GetIcon(fileName); - } - - try - { - return Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); - } - finally - { - // delete HBitmap to avoid memory leaks - NativeMethods.DeleteObject(hbitmap); - } - } - - private static HResult GetIconImpl(string filename, out IntPtr hbitmap) - { - Guid shellItem2Guid = new Guid(IShellItem2Guid); - int retCode = NativeMethods.SHCreateItemFromParsingName(filename, IntPtr.Zero, ref shellItem2Guid, out IShellItem nativeShellItem); - - if (retCode != 0) - { - throw Marshal.GetExceptionForHR(retCode)!; - } - - NativeSize large = new NativeSize { Width = 256, Height = 256 }; - var options = ThumbnailOptions.BiggerSizeOk | ThumbnailOptions.IconOnly; - - HResult hr = ((IShellItemImageFactory)nativeShellItem).GetImage(large, options, out hbitmap); - - Marshal.ReleaseComObject(nativeShellItem); - - return hr; - } - - private static HResult GetThumbnailImpl(string filename, out IntPtr hbitmap) - { - Guid shellItem2Guid = new Guid(IShellItem2Guid); - int retCode = NativeMethods.SHCreateItemFromParsingName(filename, IntPtr.Zero, ref shellItem2Guid, out IShellItem nativeShellItem); - - if (retCode != 0) - { - throw Marshal.GetExceptionForHR(retCode)!; - } - - var extraLarge = new NativeSize { Width = 1024, Height = 1024, }; - var large = new NativeSize { Width = 256, Height = 256 }; - var medium = new NativeSize { Width = 96, Height = 96 }; - var small = new NativeSize { Width = 32, Height = 32 }; - - var options = ThumbnailOptions.BiggerSizeOk | ThumbnailOptions.ThumbnailOnly | ThumbnailOptions.ScaleUp; - - HResult hr = ((IShellItemImageFactory)nativeShellItem).GetImage(extraLarge, options, out hbitmap); - - if (hr != HResult.Ok) - { - hr = ((IShellItemImageFactory)nativeShellItem).GetImage(large, options, out hbitmap); - } - - if (hr != HResult.Ok) - { - hr = ((IShellItemImageFactory)nativeShellItem).GetImage(medium, options, out hbitmap); - } - - if (hr != HResult.Ok) - { - hr = ((IShellItemImageFactory)nativeShellItem).GetImage(small, options, out hbitmap); - } - - Marshal.ReleaseComObject(nativeShellItem); - - return hr; - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Models/DimensionData.cs b/src/modules/peek/Peek.UI.WPF/Models/DimensionData.cs deleted file mode 100644 index 42d0567238..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Models/DimensionData.cs +++ /dev/null @@ -1,21 +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.Drawing.Imaging; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Media.Imaging; - -namespace Peek.UI.Models -{ - public class DimensionData - { - public Size Size { get; set; } - - public Rotation Rotation { get; set; } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Models/IShellItem.cs b/src/modules/peek/Peek.UI.WPF/Models/IShellItem.cs deleted file mode 100644 index 908e79428c..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Models/IShellItem.cs +++ /dev/null @@ -1,30 +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.Runtime.InteropServices; -using static Peek.UI.Native.NativeModels; - -namespace Peek.UI.Models -{ - [ComImport] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")] - internal interface IShellItem - { - void BindToHandler( - IntPtr pbc, - [MarshalAs(UnmanagedType.LPStruct)] Guid bhid, - [MarshalAs(UnmanagedType.LPStruct)] Guid riid, - out IntPtr ppv); - - void GetParent(out IShellItem ppsi); - - void GetDisplayName(Sigdn sigdnName, out IntPtr ppszName); - - void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs); - - void Compare(IShellItem psi, uint hint, out int piOrder); - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Models/ObservableObject.cs b/src/modules/peek/Peek.UI.WPF/Models/ObservableObject.cs deleted file mode 100644 index 8925029cbd..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Models/ObservableObject.cs +++ /dev/null @@ -1,19 +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.ComponentModel; -using System.Runtime.CompilerServices; - -namespace Peek.UI.Models -{ - public abstract class ObservableObject : INotifyPropertyChanged - { - public event PropertyChangedEventHandler? PropertyChanged; - - protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Models/ObservableRectangle.cs b/src/modules/peek/Peek.UI.WPF/Models/ObservableRectangle.cs deleted file mode 100644 index 3a9c91c523..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Models/ObservableRectangle.cs +++ /dev/null @@ -1,85 +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. - -namespace Peek.UI.Models -{ - public class ObservableRectangle : ObservableObject - { - private double _left; - - public double Left - { - get - { - return _left; - } - - set - { - if (_left != value) - { - _left = value; - OnPropertyChanged(nameof(Left)); - } - } - } - - private double _top; - - public double Top - { - get - { - return _top; - } - - set - { - if (_top != value) - { - _top = value; - OnPropertyChanged(nameof(Top)); - } - } - } - - private double _height; - - public double Height - { - get - { - return _height; - } - - set - { - if (_height != value) - { - _height = value; - OnPropertyChanged(nameof(Height)); - } - } - } - - private double _width; - - public double Width - { - get - { - return _width; - } - - set - { - if (_width != value) - { - _width = value; - OnPropertyChanged(nameof(Width)); - } - } - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Models/ObservableWindowData.cs b/src/modules/peek/Peek.UI.WPF/Models/ObservableWindowData.cs deleted file mode 100644 index 0aab543369..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Models/ObservableWindowData.cs +++ /dev/null @@ -1,88 +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.Windows; - -namespace Peek.UI.Models -{ - public class ObservableWindowData : ObservableObject - { - private double _titleBarHeight; - - public double TitleBarHeight - { - get - { - return _titleBarHeight; - } - - set - { - if (_titleBarHeight != value) - { - _titleBarHeight = value; - OnPropertyChanged(nameof(TitleBarHeight)); - } - } - } - - private ObservableRectangle _rectangle = new ObservableRectangle(); - - public ObservableRectangle Rectangle - { - get - { - return _rectangle; - } - - set - { - if (_rectangle != value) - { - _rectangle = value; - OnPropertyChanged(nameof(Rectangle)); - } - } - } - - private string _title = string.Empty; - - public string Title - { - get - { - return _title; - } - - set - { - if (_title != value) - { - _title = value; - OnPropertyChanged(nameof(Title)); - } - } - } - - private Visibility _visibility; - - public Visibility Visibility - { - get - { - return _visibility; - } - - set - { - if (_visibility != value) - { - _visibility = value; - - OnPropertyChanged(nameof(Visibility)); - } - } - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Native/NativeEventWaiter.cs b/src/modules/peek/Peek.UI.WPF/Native/NativeEventWaiter.cs deleted file mode 100644 index efb07bf413..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Native/NativeEventWaiter.cs +++ /dev/null @@ -1,28 +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.Threading; -using System.Windows; - -namespace Peek.UI.Native -{ - public static class NativeEventWaiter - { - public static void WaitForEventLoop(string eventName, Action callback) - { - new Thread(() => - { - var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName); - while (true) - { - if (eventHandle.WaitOne()) - { - Application.Current.Dispatcher.Invoke(callback); - } - } - }).Start(); - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Native/NativeMethods.cs b/src/modules/peek/Peek.UI.WPF/Native/NativeMethods.cs deleted file mode 100644 index 2be17a45d1..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Native/NativeMethods.cs +++ /dev/null @@ -1,54 +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.Runtime.InteropServices; -using Peek.UI.Models; -using static Peek.UI.Native.NativeModels; - -namespace Peek.UI.Native -{ - public static class NativeMethods - { - [DllImport("dwmapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern long DwmSetWindowAttribute( - IntPtr hwnd, - DwmWindowAttributed attribute, - ref DwmWindowCornerPreference pvAttribute, - uint cbAttribute); - - [DllImport("gdi32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool DeleteObject(IntPtr hObject); - - [DllImport("Shlwapi.dll", ExactSpelling = true, PreserveSig = false)] - internal static extern HResult AssocGetPerceivedType( - [MarshalAs(UnmanagedType.LPWStr)] string extension, - out PerceivedType perceivedType, - out Perceived perceivedFlags, - IntPtr ptrType); - - [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern int SHCreateItemFromParsingName( - [MarshalAs(UnmanagedType.LPWStr)] string path, - IntPtr pbc, - ref Guid riid, - [MarshalAs(UnmanagedType.Interface)] out IShellItem shellItem); - - [DllImport("user32.dll", SetLastError = true)] - internal static extern int GetWindowLong(IntPtr hWnd, int nIndex); - - [DllImport("user32.dll")] - internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); - - [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] - internal static extern IntPtr GetForegroundWindow(); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - internal static extern int GetWindowThreadProcessId(IntPtr handle, out int processId); - - [DllImport("user32.dll")] - internal static extern uint SendInput(uint nInputs, Input[] pInputs, int cbSize); - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Native/NativeModels.cs b/src/modules/peek/Peek.UI.WPF/Native/NativeModels.cs deleted file mode 100644 index 1cb3b6421e..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Native/NativeModels.cs +++ /dev/null @@ -1,182 +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.Runtime.InteropServices; - -namespace Peek.UI.Native -{ - public class NativeModels - { - public const int GwlExStyle = -20; - public const int WsExToolWindow = 0x00000080; - - public enum PerceivedType - { - Folder = -1, - Unknown = 0, - Image = 2, - Video = 4, - Document = 6, - } - - public enum Perceived - { - Undefined = 0x0000, - Softcoded = 0x0001, - Hardcoded = 0x0002, - NativeSupport = 0x0004, - GdiPlus = 0x0010, - WMSDK = 0x0020, - ZipFolder = 0x0040, - } - - public enum HResult - { - Ok = 0x0000, - False = 0x0001, - InvalidArguments = unchecked((int)0x80070057), - OutOfMemory = unchecked((int)0x8007000E), - NoInterface = unchecked((int)0x80004002), - Fail = unchecked((int)0x80004005), - ExtractionFailed = unchecked((int)0x8004B200), - ElementNotFound = unchecked((int)0x80070490), - TypeElementNotFound = unchecked((int)0x8002802B), - NoObject = unchecked((int)0x800401E5), - Win32ErrorCanceled = 1223, - Canceled = unchecked((int)0x800704C7), - ResourceInUse = unchecked((int)0x800700AA), - AccessDenied = unchecked((int)0x80030005), - } - - [StructLayout(LayoutKind.Sequential)] - public struct Input - { - public InputType Type; - public InputUnion Data; - - public static int Size - { - get { return Marshal.SizeOf(typeof(Input)); } - } - } - - [StructLayout(LayoutKind.Explicit)] - public struct InputUnion - { - [FieldOffset(0)] - public MouseInput Mi; - - [FieldOffset(0)] - public KeybdInput Ki; - - [FieldOffset(0)] - public HardwareInput Hi; - } - - [StructLayout(LayoutKind.Sequential)] - public struct MouseInput - { - public int Dx; - public int Dy; - public int MouseData; - public uint DwFlags; - public uint Time; - public UIntPtr DwExtraInfo; - } - - [StructLayout(LayoutKind.Sequential)] - public struct KeybdInput - { - public short WVk; - public short WScan; - public uint DwFlags; - public int Time; - public UIntPtr DwExtraInfo; - } - - [StructLayout(LayoutKind.Sequential)] - public struct HardwareInput - { - public int UMsg; - public short WParamL; - public short WParamH; - } - - public enum InputType : uint - { - InputMouse = 0, - InputKeyboard = 1, - InputHardware = 2, - } - - public enum Sigdn : uint - { - NormalDisplay = 0, - ParentRelativeParsing = 0x80018001, - ParentRelativeForAddressBar = 0x8001c001, - DesktopAbsoluteParsing = 0x80028000, - ParentRelativeEditing = 0x80031001, - DesktopAbsoluteEditing = 0x8004c000, - FileSysPath = 0x80058000, - Url = 0x80068000, - } - - public enum DwmWindowAttributed - { - DwmaWindowCornerPreference = 33, - } - - // The DWM_WINDOW_CORNER_PREFERENCE enum for DwmSetWindowAttribute's third parameter, which tells the function - // what value of the enum to set. - public enum DwmWindowCornerPreference - { - DwmCpDefault = 0, - DwmCpDoNotRound = 1, - DwmCpRound = 2, - DwmCpRoundSmall = 3, - } - - [Flags] - public enum ThumbnailOptions - { - None = 0x00, - BiggerSizeOk = 0x01, - InMemoryOnly = 0x02, - IconOnly = 0x04, - ThumbnailOnly = 0x08, - InCacheOnly = 0x10, - ScaleUp = 0x100, - } - - [ComImport] - [Guid("bcc18b79-ba16-442f-80c4-8a59c30c463b")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - internal interface IShellItemImageFactory - { - [PreserveSig] - HResult GetImage( - [In, MarshalAs(UnmanagedType.Struct)] NativeSize size, - [In] ThumbnailOptions flags, - [Out] out IntPtr phbm); - } - - [StructLayout(LayoutKind.Sequential)] - internal struct NativeSize - { - private int width; - private int height; - - public int Width - { - set { width = value; } - } - - public int Height - { - set { height = value; } - } - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Peek.UI.WPF.csproj b/src/modules/peek/Peek.UI.WPF/Peek.UI.WPF.csproj deleted file mode 100644 index 8bda35d12b..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Peek.UI.WPF.csproj +++ /dev/null @@ -1,90 +0,0 @@ - - - - WinExe - net7.0-windows10.0.19041.0 - PowerToys.Peek.UI.WPF - enable - true - false - false - ..\..\..\..\$(Platform)\$(Configuration)\modules\Peek.WPF\ - True - Resources\FluentIconsPeek.ico - - - - - tlbimp - 0 - 1 - 50a7e9b0-70ef-11d1-b75a-00a0c90564fe - 0 - false - true - - - tlbimp - 1 - 1 - eab22ac0-30c1-11cf-a7eb-0000c05bae0b - 0 - false - true - - - - - Resources\Peek.ico - - - - - - - - - Always - - - Always - - - - - - - - - - - - - - - - - $(DefaultXamlRuntime) - - - $(DefaultXamlRuntime) - - - $(DefaultXamlRuntime) - - - $(DefaultXamlRuntime) - - - $(DefaultXamlRuntime) - - - $(DefaultXamlRuntime) - - - - - - - - diff --git a/src/modules/peek/Peek.UI.WPF/Resources/Peek.ico b/src/modules/peek/Peek.UI.WPF/Resources/Peek.ico deleted file mode 100644 index daf81fdeb3..0000000000 Binary files a/src/modules/peek/Peek.UI.WPF/Resources/Peek.ico and /dev/null differ diff --git a/src/modules/peek/Peek.UI.WPF/Themes/Dark.xaml b/src/modules/peek/Peek.UI.WPF/Themes/Dark.xaml deleted file mode 100644 index 14204cfe7f..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Themes/Dark.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Dark.Accent1 - PowerToysPeek - Accent1 (Dark) - Dark - Accent1 - Black - - - - - - - \ No newline at end of file diff --git a/src/modules/peek/Peek.UI.WPF/Themes/HighContrast1.xaml b/src/modules/peek/Peek.UI.WPF/Themes/HighContrast1.xaml deleted file mode 100644 index cf168baaae..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Themes/HighContrast1.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - HighContrast.Accent2 - PowerToysPeek - Accent2 (HighContrast) - HighContrast - Accent2 - White - - - - - - - \ No newline at end of file diff --git a/src/modules/peek/Peek.UI.WPF/Themes/HighContrast2.xaml b/src/modules/peek/Peek.UI.WPF/Themes/HighContrast2.xaml deleted file mode 100644 index 65d8065e29..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Themes/HighContrast2.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - HighContrast.Accent3 - PowerToysPeek - Accent3 (HighContrast) - HighContrast - Accent3 - White - - - - - - - \ No newline at end of file diff --git a/src/modules/peek/Peek.UI.WPF/Themes/HighContrastBlack.xaml b/src/modules/peek/Peek.UI.WPF/Themes/HighContrastBlack.xaml deleted file mode 100644 index 402f414db6..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Themes/HighContrastBlack.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - HighContrast.Accent4 - PowerToysPeek - Accent4 (HighContrast) - HighContrast - Accent4 - White - - - - - - - \ No newline at end of file diff --git a/src/modules/peek/Peek.UI.WPF/Themes/HighContrastWhite.xaml b/src/modules/peek/Peek.UI.WPF/Themes/HighContrastWhite.xaml deleted file mode 100644 index bfe85de54f..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Themes/HighContrastWhite.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - HighContrast.Accent5 - PowerToysPeek - Accent5 (HighContrast) - HighContrast - Accent5 - White - - - - - - - \ No newline at end of file diff --git a/src/modules/peek/Peek.UI.WPF/Themes/Light.xaml b/src/modules/peek/Peek.UI.WPF/Themes/Light.xaml deleted file mode 100644 index 4ca102d2fe..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Themes/Light.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Light.Accent1 - PowerToysPeek - Accent1 (Light) - Light - Accent1 - White - - - - - - - \ No newline at end of file diff --git a/src/modules/peek/Peek.UI.WPF/ViewModels/MainViewModel.cs b/src/modules/peek/Peek.UI.WPF/ViewModels/MainViewModel.cs deleted file mode 100644 index 406a36b4a3..0000000000 --- a/src/modules/peek/Peek.UI.WPF/ViewModels/MainViewModel.cs +++ /dev/null @@ -1,301 +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.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media.Imaging; -using Peek.UI.Extensions; -using Peek.UI.Helpers; -using Peek.UI.Models; -using Peek.UI.Native; -using WpfScreenHelper; -using Size = System.Windows.Size; - -namespace Peek.UI.ViewModels -{ - public class MainViewModel : ObservableObject, IDisposable - { - private const double ImageScale = 0.75; - private static readonly Size MinWindowSize = new Size(720, 720); - private static readonly Size AllowedContentGap = new Size(220, 220); - - private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - - private CancellationToken CancellationToken => _cancellationTokenSource.Token; - - public IntPtr ForegroundWindowHandle { get; internal set; } - - public Image ImageControl { get; set; } - - public LinkedList SelectedFilePaths { get; set; } = new LinkedList(); - - private BitmapSource? _bitmap; - - public BitmapSource? Bitmap - { - get - { - return _bitmap; - } - - set - { - if (_bitmap != value) - { - _bitmap = value; - OnPropertyChanged(nameof(Bitmap)); - } - } - } - - private LinkedListNode? _currentSelectedFilePath; - - public LinkedListNode? CurrentSelectedFilePath - { - get - { - return _currentSelectedFilePath; - } - - set - { - if (_currentSelectedFilePath != value) - { - _currentSelectedFilePath = value; - var title = Path.GetFileName(_currentSelectedFilePath?.Value ?? string.Empty); - MainWindowData.Title = title; - OnPropertyChanged(nameof(CurrentSelectedFilePath)); - } - } - } - - public Visibility IsImageReady => IsLoading ? Visibility.Collapsed : Visibility.Visible; - - private bool _isLoading = true; - - public bool IsLoading - { - get - { - return _isLoading; - } - - set - { - if (_isLoading != value) - { - _isLoading = value; - OnPropertyChanged(nameof(IsLoading)); - OnPropertyChanged(nameof(IsImageReady)); - } - } - } - - private ObservableWindowData _mainWindowData = new ObservableWindowData(); - - public ObservableWindowData MainWindowData - { - get - { - return _mainWindowData; - } - - set - { - if (_mainWindowData != value) - { - _mainWindowData = value; - OnPropertyChanged(nameof(MainWindowData)); - } - } - } - - public MainViewModel(Image imageControl) - { - ImageControl = imageControl; - } - - // TODO: Implement proper disposal pattern - public void Dispose() - { - _cancellationTokenSource.Dispose(); - GC.SuppressFinalize(this); - } - - public void ClearSelection() - { - _cancellationTokenSource.Cancel(); - _cancellationTokenSource = new CancellationTokenSource(); - - CurrentSelectedFilePath = null; - MainWindowData.Visibility = Visibility.Collapsed; - } - - public bool TryUpdateSelectedFilePaths() - { - ForegroundWindowHandle = NativeMethods.GetForegroundWindow(); - - // TODO: Get all neighborings files in correct sorted order - var selectedItems = FileExplorerHelper.GetSelectedItems(ForegroundWindowHandle); - - var isDifferentSelectedItems = !SelectedFilePaths.SequenceEqual(selectedItems); - - if (isDifferentSelectedItems) - { - SelectedFilePaths = new LinkedList(selectedItems); - } - - CurrentSelectedFilePath = SelectedFilePaths.First; - - return isDifferentSelectedItems; - } - - // TODO: Implement proper cancellation pattern to support quick navigation - public async Task RenderImageToWindowAsync(string filename) - { - IsLoading = true; - - var screen = Screen.FromHandle(ForegroundWindowHandle); - Size maxWindowSize = new Size(screen.WpfBounds.Width * ImageScale, screen.WpfBounds.Height * ImageScale); - - // TODO: Support preview or thumbnail for document files - if (FileTypeHelper.IsSupportedImage(Path.GetExtension(filename))) - { - await RenderSupportedImageToWindowAsync(filename, screen.Bounds, maxWindowSize); - } - else if (FileTypeHelper.IsMedia(Path.GetExtension(filename)) || FileTypeHelper.IsDocument(Path.GetExtension(filename))) - { - await RenderMediaOrDocumentToWindowAsync(filename, screen.Bounds, maxWindowSize); - } - else - { - await RenderUnsupportedFileToWindowAsync(filename, screen.Bounds, maxWindowSize); - } - } - - private async Task RenderSupportedImageToWindowAsync(string filename, Rect windowBounds, Size maxWindowSize) - { - DimensionData dimensionData = await FileLoadHelper.LoadDimensionsAsync(filename); - if (CancellationToken.IsCancellationRequested) - { - _cancellationTokenSource = new CancellationTokenSource(); - return; - } - - var windowRect = dimensionData.Size.Fit(windowBounds, maxWindowSize, MinWindowSize, AllowedContentGap, MainWindowData.TitleBarHeight); - - MainWindowData.Rectangle.Width = windowRect.Width; - MainWindowData.Rectangle.Height = windowRect.Height; - MainWindowData.Rectangle.Left = windowRect.Left; - MainWindowData.Rectangle.Top = windowRect.Top; - - if (dimensionData.Size.Width > MainWindowData.Rectangle.Width || dimensionData.Size.Height > MainWindowData.Rectangle.Height) - { - ImageControl.StretchDirection = StretchDirection.Both; - } - else - { - ImageControl.StretchDirection = StretchDirection.DownOnly; - } - - await LoadImageAsync(filename, ImageControl, dimensionData.Rotation, CancellationToken); - } - - private async Task RenderMediaOrDocumentToWindowAsync(string filename, Rect windowBounds, Size maxWindowSize) - { - var bitmap = await FileLoadHelper.LoadThumbnailAsync(filename, true); - if (CancellationToken.IsCancellationRequested) - { - _cancellationTokenSource = new CancellationTokenSource(); - return; - } - - Bitmap = bitmap; - - var imageSize = new Size(bitmap.PixelWidth, bitmap.PixelHeight); - var windowRect = imageSize.Fit(windowBounds, maxWindowSize, MinWindowSize, AllowedContentGap, MainWindowData.TitleBarHeight); - - MainWindowData.Rectangle.Width = windowRect.Width; - MainWindowData.Rectangle.Height = windowRect.Height; - MainWindowData.Rectangle.Left = windowRect.Left; - MainWindowData.Rectangle.Top = windowRect.Top; - - MainWindowData.Visibility = Visibility.Visible; - IsLoading = false; - } - - private async Task RenderUnsupportedFileToWindowAsync(string filename, Rect windowBounds, Size maxWindowSize) - { - var contentSize = new Size(0, 0); - var windowRect = contentSize.Fit(windowBounds, maxWindowSize, MinWindowSize, AllowedContentGap, MainWindowData.TitleBarHeight); - - MainWindowData.Rectangle.Width = windowRect.Width; - MainWindowData.Rectangle.Height = windowRect.Height; - MainWindowData.Rectangle.Left = windowRect.Left; - MainWindowData.Rectangle.Top = windowRect.Top; - - var bitmap = await FileLoadHelper.LoadIconAsync(filename); - if (CancellationToken.IsCancellationRequested) - { - _cancellationTokenSource = new CancellationTokenSource(); - return; - } - - Bitmap = bitmap; - MainWindowData.Visibility = Visibility.Visible; - IsLoading = false; - } - - private Task LoadImageAsync(string filename, System.Windows.Controls.Image imageControl, Rotation rotation, CancellationToken cancellationToken) - { - bool isFullImageLoaded = false; - bool isThumbnailLoaded = false; - var thumbnailLoadTask = imageControl.Dispatcher.Invoke(async () => - { - var bitmap = await FileLoadHelper.LoadThumbnailAsync(filename, false); - isThumbnailLoaded = true; - - if (CancellationToken.IsCancellationRequested) - { - _cancellationTokenSource = new CancellationTokenSource(); - return; - } - - if (!isFullImageLoaded) - { - Bitmap = bitmap; - MainWindowData.Visibility = Visibility.Visible; - IsLoading = false; - } - }); - - var fullImageLoadTask = imageControl.Dispatcher.Invoke(async () => - { - var bitmap = await FileLoadHelper.LoadFullImageAsync(filename, rotation); - isFullImageLoaded = true; - - if (CancellationToken.IsCancellationRequested) - { - _cancellationTokenSource = new CancellationTokenSource(); - return; - } - - Bitmap = bitmap; - if (!isThumbnailLoaded) - { - MainWindowData.Visibility = Visibility.Visible; - IsLoading = false; - } - }); - - return Task.WhenAll(thumbnailLoadTask, fullImageLoadTask); - } - } -} diff --git a/src/modules/peek/Peek.UI.WPF/Views/MainWindow.xaml b/src/modules/peek/Peek.UI.WPF/Views/MainWindow.xaml deleted file mode 100644 index 6da3d32725..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Views/MainWindow.xaml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/modules/peek/Peek.UI.WPF/Views/MainWindow.xaml.cs b/src/modules/peek/Peek.UI.WPF/Views/MainWindow.xaml.cs deleted file mode 100644 index dcfbc5cd53..0000000000 --- a/src/modules/peek/Peek.UI.WPF/Views/MainWindow.xaml.cs +++ /dev/null @@ -1,115 +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.Input; -using interop; -using ModernWpf.Controls; -using Peek.UI.Extensions; -using Peek.UI.Native; -using Peek.UI.ViewModels; - -namespace Peek.UI.Views -{ - /// - /// Interaction logic for MainWindow.xaml - /// - public partial class MainWindow : Window, IDisposable - { - private readonly MainViewModel _viewModel; - - public MainWindow() - { - InitializeComponent(); - - this.RoundCorners(); - - _viewModel = new MainViewModel(ImageControl); - _viewModel.PropertyChanged += MainViewModel_PropertyChanged; - - DataContext = _viewModel; - - NativeEventWaiter.WaitForEventLoop(Constants.ShowPeekEvent(), OnPeekHotkey); - - Loaded += MainWindow_Loaded; - Closing += MainWindow_Closing; - KeyDown += MainWindow_KeyDown; - } - - private void MainWindow_Loaded(object sender, RoutedEventArgs e) - { - _viewModel.MainWindowData.Visibility = Visibility.Collapsed; - _viewModel.MainWindowData.TitleBarHeight = TitleBar.GetHeight(this); - _viewModel.ImageControl = ImageControl; - } - - private void MainWindow_Closing(object? sender, System.ComponentModel.CancelEventArgs e) - { - _viewModel.MainWindowData.Visibility = Visibility.Collapsed; - e.Cancel = true; - } - - private void MainWindow_KeyDown(object? sender, KeyEventArgs e) - { - if (!e.IsRepeat && _viewModel.CurrentSelectedFilePath != null) - { - switch (e.Key) - { - case Key.Left: - _viewModel.CurrentSelectedFilePath = _viewModel.CurrentSelectedFilePath.GetPreviousOrLast(); - e.Handled = true; - break; - - case Key.Right: - _viewModel.CurrentSelectedFilePath = _viewModel.CurrentSelectedFilePath.GetNextOrFirst(); - e.Handled = true; - break; - - default: break; - } - } - } - - public void Dispose() - { - _viewModel.Dispose(); - GC.SuppressFinalize(this); - } - - protected override void OnSourceInitialized(EventArgs e) - { - base.OnSourceInitialized(e); - this.SetToolStyle(); - } - - private async void MainViewModel_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) - { - switch (e.PropertyName) - { - case nameof(MainViewModel.CurrentSelectedFilePath): - if (_viewModel.CurrentSelectedFilePath != null) - { - await _viewModel.RenderImageToWindowAsync(_viewModel.CurrentSelectedFilePath.Value); - } - - break; - } - } - - private void OnPeekHotkey() - { - if (IsActive && _viewModel.MainWindowData.Visibility == Visibility.Visible) - { - _viewModel.ClearSelection(); - } - else - { - _viewModel.TryUpdateSelectedFilePaths(); - } - - this.BringToForeground(); - } - } -}