Merge branch 'main' into dsc_configure_module

This commit is contained in:
Andrey Nekrasov 2024-04-01 02:16:55 +02:00
commit da2ef06364
44 changed files with 314 additions and 93 deletions

View File

@ -1,19 +1,19 @@
$ProgressPreference = 'SilentlyContinue'
$WixDownloadUrl = "https://github.com/wixtoolset/wix3/releases/download/wix314rtm/wix314.exe"
$WixBinariesDownloadUrl = "https://github.com/wixtoolset/wix3/releases/download/wix314rtm/wix314-binaries.zip"
$WixDownloadUrl = "https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314.exe"
$WixBinariesDownloadUrl = "https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314-binaries.zip"
# Download WiX binaries and verify their hash sums
Invoke-WebRequest -Uri $WixDownloadUrl -OutFile "$($ENV:Temp)\wix314.exe"
$Hash = (Get-FileHash -Algorithm SHA256 "$($ENV:Temp)\wix314.exe").Hash
if ($Hash -ne '704439EA88FC9E5A3647EEDEEB45943F9A392E3D209F58512280130096847937')
if ($Hash -ne '6BF6D03D6923D9EF827AE1D943B90B42B8EBB1B0F68EF6D55F868FA34C738A29')
{
Write-Error "$WixHash"
throw "wix314.exe has unexpected SHA256 hash: $Hash"
}
Invoke-WebRequest -Uri $WixBinariesDownloadUrl -OutFile "$($ENV:Temp)\wix314-binaries.zip"
$Hash = (Get-FileHash -Algorithm SHA256 "$($ENV:Temp)\wix314-binaries.zip").Hash
if($Hash -ne '13F067F38969FAF163D93A804B48EA0576790A202C8F10291F2000F0E356E934')
if($Hash -ne '6AC824E1642D6F7277D0ED7EA09411A508F6116BA6FAE0AA5F2C7DAA2FF43D31')
{
throw "wix314-binaries.zip has unexpected SHA256 hash: $Hash"
}

View File

@ -80,8 +80,8 @@ The installer can only be compiled in `Release` mode; steps 1 and 2 must be perf
### Prerequisites for building the MSI installer
1. Install the [WiX Toolset Visual Studio 2022 Extension](https://marketplace.visualstudio.com/items?itemName=WixToolset.WixToolsetVisualStudio2022Extension).
1. Install the [WiX Toolset build tools](https://github.com/wixtoolset/wix3/releases/tag/wix314rtm). (installer [direct link](https://github.com/wixtoolset/wix3/releases/download/wix314rtm/wix314.exe))
1. Download [WiX binaries](https://github.com/wixtoolset/wix3/releases/download/wix314rtm/wix314-binaries.zip) and extract `wix.targets` to `C:\Program Files (x86)\WiX Toolset v3.14`.
1. Install the [WiX Toolset build tools](https://github.com/wixtoolset/wix3/releases/tag/wix3141rtm). (installer [direct link](https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314.exe))
1. Download [WiX binaries](https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314-binaries.zip) and extract `wix.targets` to `C:\Program Files (x86)\WiX Toolset v3.14`.
### Building prerequisite projects

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 178 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 179 KiB

View File

@ -8,8 +8,6 @@ DraggingState::DraggingState(const std::function<void()>& keyUpdateCallback) :
m_secondaryMouseState(false),
m_middleMouseState(false),
m_mouseHook(std::bind(&DraggingState::OnSecondaryMouseDown, this), std::bind(&DraggingState::OnMiddleMouseDown, this)),
m_leftShiftKeyState(keyUpdateCallback),
m_rightShiftKeyState(keyUpdateCallback),
m_ctrlKeyState(keyUpdateCallback),
m_keyUpdateCallback(keyUpdateCallback)
{
@ -22,49 +20,30 @@ void DraggingState::Enable()
m_mouseHook.enable();
}
m_leftShiftKeyState.enable();
m_rightShiftKeyState.enable();
m_ctrlKeyState.enable();
}
void DraggingState::Disable()
{
const bool leftShiftPressed = m_leftShiftKeyState.state();
const bool rightShiftPressed = m_rightShiftKeyState.state();
if (FancyZonesSettings::settings().shiftDrag)
{
if (leftShiftPressed)
{
FancyZonesUtils::SwallowKey(VK_LSHIFT);
}
if (rightShiftPressed)
{
FancyZonesUtils::SwallowKey(VK_RSHIFT);
}
}
m_dragging = false;
m_secondaryMouseState = false;
m_middleMouseState = false;
m_shift = false;
m_mouseHook.disable();
m_leftShiftKeyState.disable();
m_rightShiftKeyState.disable();
m_ctrlKeyState.disable();
}
void DraggingState::UpdateDraggingState() noexcept
{
// This updates m_dragEnabled depending on if the shift key is being held down
// This updates m_dragging depending on if the shift key is being held down
if (FancyZonesSettings::settings().shiftDrag)
{
m_dragging = ((m_leftShiftKeyState.state() || m_rightShiftKeyState.state()) ^ m_secondaryMouseState);
m_dragging = (m_shift ^ m_secondaryMouseState);
}
else
{
m_dragging = !((m_leftShiftKeyState.state() || m_rightShiftKeyState.state()) ^ m_secondaryMouseState);
m_dragging = !(m_shift ^ m_secondaryMouseState);
}
}
@ -97,3 +76,9 @@ bool DraggingState::IsSelectManyZonesState() const noexcept
{
return m_ctrlKeyState.state() || m_middleMouseState;
}
void DraggingState::SetShiftState(bool value) noexcept
{
m_shift = value;
m_keyUpdateCallback();
}

View File

@ -16,6 +16,8 @@ public:
bool IsDragging() const noexcept;
bool IsSelectManyZonesState() const noexcept;
void SetShiftState(bool value) noexcept;
private:
void OnSecondaryMouseDown();
void OnMiddleMouseDown();
@ -23,9 +25,10 @@ private:
std::atomic<bool> m_secondaryMouseState;
std::atomic<bool> m_middleMouseState;
MouseButtonsHook m_mouseHook;
KeyState<VK_LSHIFT> m_leftShiftKeyState;
KeyState<VK_RSHIFT> m_rightShiftKeyState;
KeyState<VK_LCONTROL, VK_RCONTROL> m_ctrlKeyState;
bool m_shift{};
std::function<void()> m_keyUpdateCallback;
bool m_dragging{}; // True if we should be showing zone hints while dragging

View File

@ -21,6 +21,7 @@
#include <FancyZonesLib/FancyZonesWindowProcessing.h>
#include <FancyZonesLib/FancyZonesWindowProperties.h>
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
#include <FancyZonesLib/KeyboardInput.h>
#include <FancyZonesLib/MonitorUtils.h>
#include <FancyZonesLib/on_thread_executor.h>
#include <FancyZonesLib/Settings.h>
@ -143,6 +144,7 @@ public:
void ToggleEditor() noexcept;
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
void OnKeyboardInput(WPARAM flags, HRAWINPUT hInput) noexcept;
void OnDisplayChange(DisplayChangeType changeType) noexcept;
bool AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id, const FancyZonesUtils::Rect& rect) noexcept;
@ -220,7 +222,13 @@ FancyZones::Run() noexcept
m_window = CreateWindowExW(WS_EX_TOOLWINDOW, NonLocalizable::ToolWindowClassName, L"", WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, m_hinstance, this);
if (!m_window)
{
Logger::error(L"Failed to create FancyZones window");
Logger::critical(L"Failed to create FancyZones window");
return;
}
if (!KeyboardInput::Initialize(m_window))
{
Logger::critical(L"Failed to register raw input device");
return;
}
@ -580,6 +588,12 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
}
break;
case WM_INPUT:
{
OnKeyboardInput(wparam, reinterpret_cast<HRAWINPUT>(lparam));
}
break;
case WM_SETTINGCHANGE:
{
if (wparam == SPI_SETWORKAREA)
@ -717,6 +731,26 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
return 0;
}
void FancyZones::OnKeyboardInput(WPARAM /*flags*/, HRAWINPUT hInput) noexcept
{
auto input = KeyboardInput::OnKeyboardInput(hInput);
if (!input.has_value())
{
return;
}
switch (input.value().vkKey)
{
case VK_SHIFT:
{
m_draggingState.SetShiftState(input.value().pressed);
}
break;
default:
break;
}
}
void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
{
Logger::info(L"Display changed, type: {}", DisplayChangeTypeName(changeType));

View File

@ -53,6 +53,7 @@
<ClInclude Include="FancyZonesData.h" />
<ClInclude Include="GuidUtils.h" />
<ClInclude Include="JsonHelpers.h" />
<ClInclude Include="KeyboardInput.h" />
<ClInclude Include="KeyState.h" />
<ClInclude Include="FancyZonesData\LayoutHotkeys.h" />
<ClInclude Include="Layout.h" />
@ -114,6 +115,7 @@
<ClCompile Include="FancyZonesData\LayoutHotkeys.cpp">
<PrecompiledHeaderFile>../pch.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="KeyboardInput.cpp" />
<ClCompile Include="Layout.cpp" />
<ClCompile Include="LayoutConfigurator.cpp" />
<ClCompile Include="LayoutAssignedWindows.cpp" />

View File

@ -168,6 +168,9 @@
<ClInclude Include="FancyZonesData\LastUsedVirtualDesktop.h">
<Filter>Header Files\FancyZonesData</Filter>
</ClInclude>
<ClInclude Include="KeyboardInput.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
@ -278,6 +281,9 @@
<ClCompile Include="FancyZonesWindowProcessing.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="KeyboardInput.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@ -0,0 +1,43 @@
#include "pch.h"
#include "KeyboardInput.h"
#include <hidUsage.h>
#include <common/logger/logger.h>
#include <common/utils/winapi_error.h>
bool KeyboardInput::Initialize(HWND window)
{
RAWINPUTDEVICE inputDevice{};
inputDevice.usUsagePage = HID_USAGE_PAGE_GENERIC;
inputDevice.usUsage = HID_USAGE_GENERIC_KEYBOARD;
inputDevice.dwFlags = RIDEV_INPUTSINK;
inputDevice.hwndTarget = window;
bool res = RegisterRawInputDevices(&inputDevice, 1, sizeof(inputDevice));
if (!res)
{
Logger::error(L"RegisterRawInputDevices error: {}", get_last_error_or_default(GetLastError()));
}
return res;
}
std::optional<KeyboardInput::Key> KeyboardInput::OnKeyboardInput(HRAWINPUT hInput)
{
RAWINPUT input;
UINT size = sizeof(input);
auto result = GetRawInputData(hInput, RID_INPUT, &input, &size, sizeof(RAWINPUTHEADER));
if (result < sizeof(RAWINPUTHEADER))
{
return std::nullopt;
}
if (input.header.dwType == RIM_TYPEKEYBOARD)
{
bool pressed = (input.data.keyboard.Flags & RI_KEY_BREAK) == 0;
return KeyboardInput::Key{ input.data.keyboard.VKey, pressed };
}
return std::nullopt;
}

View File

@ -0,0 +1,17 @@
#pragma once
class KeyboardInput
{
public:
struct Key
{
USHORT vkKey{};
bool pressed{};
};
KeyboardInput() = default;
~KeyboardInput() = default;
static bool Initialize(HWND window);
static std::optional<Key> OnKeyboardInput(HRAWINPUT hInput);
};

View File

@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Text.Json;
using System.Windows;
using FancyZonesEditor.Models;
@ -153,10 +154,13 @@ namespace FancyZonesEditor.Utils
try
{
LayoutHotkeys parser = new LayoutHotkeys();
if (!File.Exists(parser.File))
{
return new ParsingResult(true);
}
var layoutHotkeys = parser.Read(parser.File);
bool layoutHotkeysParsingResult = SetLayoutHotkeys(layoutHotkeys);
if (!layoutHotkeysParsingResult)
{
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Layout_Hotkeys_Message);
@ -178,8 +182,12 @@ namespace FancyZonesEditor.Utils
try
{
LayoutTemplates parser = new LayoutTemplates();
var templates = parser.Read(parser.File);
if (!File.Exists(parser.File))
{
return new ParsingResult(true);
}
var templates = parser.Read(parser.File);
bool parsingResult = SetTemplateLayouts(templates.LayoutTemplates);
if (parsingResult)
{
@ -202,8 +210,12 @@ namespace FancyZonesEditor.Utils
try
{
CustomLayouts parser = new CustomLayouts();
var wrapper = parser.Read(parser.File);
if (!File.Exists(parser.File))
{
return new ParsingResult(true);
}
var wrapper = parser.Read(parser.File);
bool parsingResult = SetCustomLayouts(wrapper.CustomLayouts);
if (parsingResult)
{
@ -226,8 +238,12 @@ namespace FancyZonesEditor.Utils
try
{
DefaultLayouts parser = new DefaultLayouts();
var wrapper = parser.Read(parser.File);
if (!File.Exists(parser.File))
{
return new ParsingResult(true);
}
var wrapper = parser.Read(parser.File);
bool parsingResult = SetDefaultLayouts(wrapper.DefaultLayouts);
if (parsingResult)
{

View File

@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Globalization;
using System.Threading.Tasks;
using ManagedCommon;
using Windows.Storage;
@ -25,6 +26,8 @@ namespace Peek.Common.Models
public string Path { get; init; }
public string Extension => System.IO.Path.GetExtension(Path).ToLower(CultureInfo.InvariantCulture);
public async Task<IStorageItem?> GetStorageItemAsync()
{
return await GetStorageFileAsync();

View File

@ -25,6 +25,8 @@ namespace Peek.Common.Models
public string Path { get; init; }
public string Extension => string.Empty;
public async Task<IStorageItem?> GetStorageItemAsync()
{
return await GetStorageFolderAsync();

View File

@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Globalization;
using System.Threading.Tasks;
using Peek.Common.Helpers;
using Windows.Storage;
@ -32,7 +31,7 @@ namespace Peek.Common.Models
}
}
public string Extension => System.IO.Path.GetExtension(Path).ToLower(CultureInfo.InvariantCulture);
public string Extension { get; }
public string Name { get; init; }

View File

@ -111,9 +111,9 @@ namespace Peek.FilePreviewer.Previewers.Archives
State = PreviewState.Loaded;
}
public static bool IsFileTypeSupported(string fileExt)
public static bool IsItemSupported(IFileSystemItem item)
{
return _supportedFileTypes.Contains(fileExt);
return _supportedFileTypes.Contains(item.Extension);
}
public void Dispose()

View File

@ -89,9 +89,9 @@ namespace Peek.FilePreviewer.Previewers.Drive
State = PreviewState.Loaded;
}
public static bool IsPathSupported(string path)
public static bool IsItemSupported(IFileSystemItem item)
{
return DriveInfo.GetDrives().Any(d => d.Name == path);
return DriveInfo.GetDrives().Any(d => d.Name == item.Path);
}
private string GetDriveTypeDescription(DriveType driveType) => driveType switch

View File

@ -8,7 +8,7 @@ using Peek.FilePreviewer.Previewers.Archives.Models;
namespace Peek.FilePreviewer.Previewers.Interfaces
{
public interface IArchivePreviewer : IPreviewer, IDisposable
public interface IArchivePreviewer : IPreviewer, IPreviewTarget, IDisposable
{
ObservableCollection<ArchiveItem> Tree { get; }

View File

@ -6,7 +6,7 @@ using Peek.FilePreviewer.Previewers.MediaPreviewer.Models;
namespace Peek.FilePreviewer.Previewers.Interfaces
{
public interface IAudioPreviewer : IPreviewer
public interface IAudioPreviewer : IPreviewer, IPreviewTarget
{
public AudioPreviewData? Preview { get; }
}

View File

@ -4,9 +4,9 @@
using System;
namespace Peek.FilePreviewer.Previewers
namespace Peek.FilePreviewer.Previewers.Interfaces
{
public interface IBrowserPreviewer : IPreviewer
public interface IBrowserPreviewer : IPreviewer, IPreviewTarget
{
public Uri? Preview { get; }

View File

@ -6,7 +6,7 @@ using Peek.FilePreviewer.Previewers.Drive.Models;
namespace Peek.FilePreviewer.Previewers.Interfaces
{
public interface IDrivePreviewer : IPreviewer
public interface IDrivePreviewer : IPreviewer, IPreviewTarget
{
public DrivePreviewData? Preview { get; }
}

View File

@ -7,7 +7,7 @@ using Windows.Foundation;
namespace Peek.FilePreviewer.Previewers.Interfaces
{
public interface IImagePreviewer : IPreviewer
public interface IImagePreviewer : IPreviewer, IPreviewTarget
{
public ImageSource? Preview { get; }

View File

@ -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.
using Peek.Common.Models;
namespace Peek.FilePreviewer.Previewers.Interfaces
{
public interface IPreviewTarget
{
static abstract bool IsItemSupported(IFileSystemItem item);
}
}

View File

@ -2,12 +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.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using Peek.FilePreviewer.Models;
using Windows.Foundation;
namespace Peek.FilePreviewer.Previewers
{
@ -15,8 +13,6 @@ namespace Peek.FilePreviewer.Previewers
{
PreviewState State { get; set; }
public static bool IsFileTypeSupported(string fileExt) => throw new NotImplementedException();
public Task<PreviewSize> GetPreviewSizeAsync(CancellationToken cancellationToken);
Task LoadPreviewAsync(CancellationToken cancellationToken);

View File

@ -4,9 +4,9 @@
using Windows.Win32.UI.Shell;
namespace Peek.FilePreviewer.Previewers
namespace Peek.FilePreviewer.Previewers.Interfaces
{
public interface IShellPreviewHandlerPreviewer : IPreviewer
public interface IShellPreviewHandlerPreviewer : IPreviewer, IPreviewTarget
{
public IPreviewHandler? Preview { get; }

View File

@ -6,7 +6,7 @@ using Windows.Media.Core;
namespace Peek.FilePreviewer.Previewers.Interfaces
{
public interface IVideoPreviewer : IPreviewer
public interface IVideoPreviewer : IPreviewer, IPreviewTarget
{
public MediaSource? Preview { get; }
}

View File

@ -154,9 +154,9 @@ namespace Peek.FilePreviewer.Previewers.MediaPreviewer
});
}
public static bool IsFileTypeSupported(string fileExt)
public static bool IsItemSupported(IFileSystemItem item)
{
return _supportedFileTypes.Contains(fileExt);
return _supportedFileTypes.Contains(item.Extension);
}
private static readonly HashSet<string> _supportedFileTypes = new()

View File

@ -70,9 +70,9 @@ namespace Peek.FilePreviewer.Previewers
private ImageSource? highQualityThumbnailPreview;
public static bool IsFileTypeSupported(string fileExt)
public static bool IsItemSupported(IFileSystemItem item)
{
return _supportedFileTypes.Contains(fileExt);
return _supportedFileTypes.Contains(item.Extension);
}
public void Dispose()

View File

@ -42,9 +42,9 @@ namespace Peek.FilePreviewer.Previewers
private Task<bool>? VideoTask { get; set; }
public static bool IsFileTypeSupported(string fileExt)
public static bool IsItemSupported(IFileSystemItem item)
{
return _supportedFileTypes.Contains(fileExt);
return _supportedFileTypes.Contains(item.Extension);
}
public void Dispose()

View File

@ -23,39 +23,39 @@ namespace Peek.FilePreviewer.Previewers
_previewSettings = Application.Current.GetService<IPreviewSettings>();
}
public IPreviewer Create(IFileSystemItem file)
public IPreviewer Create(IFileSystemItem item)
{
if (ImagePreviewer.IsFileTypeSupported(file.Extension))
if (ImagePreviewer.IsItemSupported(item))
{
return new ImagePreviewer(file);
return new ImagePreviewer(item);
}
else if (VideoPreviewer.IsFileTypeSupported(file.Extension))
else if (VideoPreviewer.IsItemSupported(item))
{
return new VideoPreviewer(file);
return new VideoPreviewer(item);
}
else if (AudioPreviewer.IsFileTypeSupported(file.Extension))
else if (AudioPreviewer.IsItemSupported(item))
{
return new AudioPreviewer(file);
return new AudioPreviewer(item);
}
else if (WebBrowserPreviewer.IsFileTypeSupported(file.Extension))
else if (WebBrowserPreviewer.IsItemSupported(item))
{
return new WebBrowserPreviewer(file, _previewSettings);
return new WebBrowserPreviewer(item, _previewSettings);
}
else if (ArchivePreviewer.IsFileTypeSupported(file.Extension))
else if (ArchivePreviewer.IsItemSupported(item))
{
return new ArchivePreviewer(file);
return new ArchivePreviewer(item);
}
else if (ShellPreviewHandlerPreviewer.IsFileTypeSupported(file.Extension))
else if (ShellPreviewHandlerPreviewer.IsItemSupported(item))
{
return new ShellPreviewHandlerPreviewer(file);
return new ShellPreviewHandlerPreviewer(item);
}
else if (DrivePreviewer.IsPathSupported(file.Path))
else if (DrivePreviewer.IsItemSupported(item))
{
return new DrivePreviewer(file);
return new DrivePreviewer(item);
}
// Other previewer types check their supported file types here
return CreateDefaultPreviewer(file);
return CreateDefaultPreviewer(item);
}
public IPreviewer CreateDefaultPreviewer(IFileSystemItem file)

View File

@ -16,6 +16,7 @@ using Peek.Common.Helpers;
using Peek.Common.Models;
using Peek.FilePreviewer.Models;
using Peek.FilePreviewer.Previewers.Helpers;
using Peek.FilePreviewer.Previewers.Interfaces;
using Windows.Win32;
using Windows.Win32.System.Com;
using Windows.Win32.UI.Shell;
@ -205,9 +206,9 @@ namespace Peek.FilePreviewer.Previewers
}
}
public static bool IsFileTypeSupported(string fileExt)
public static bool IsItemSupported(IFileSystemItem item)
{
return !string.IsNullOrEmpty(GetPreviewHandlerGuid(fileExt));
return !string.IsNullOrEmpty(GetPreviewHandlerGuid(item.Extension));
}
private static string? GetPreviewHandlerGuid(string fileExt)

View File

@ -13,6 +13,7 @@ using Peek.Common.Extensions;
using Peek.Common.Helpers;
using Peek.Common.Models;
using Peek.FilePreviewer.Models;
using Peek.FilePreviewer.Previewers.Interfaces;
namespace Peek.FilePreviewer.Previewers
{
@ -137,9 +138,9 @@ namespace Peek.FilePreviewer.Previewers
});
}
public static bool IsFileTypeSupported(string fileExt)
public static bool IsItemSupported(IFileSystemItem item)
{
return _supportedFileTypes.Contains(fileExt) || MonacoHelper.SupportedMonacoFileTypes.Contains(fileExt);
return _supportedFileTypes.Contains(item.Extension) || MonacoHelper.SupportedMonacoFileTypes.Contains(item.Extension);
}
private bool HasFailedLoadingPreview()

View File

@ -183,6 +183,12 @@ IFACEMETHODIMP GcodeThumbnailProvider::GetThumbnail(UINT cx, HBITMAP* phbmp, WTS
}
}
// ensure releasing the stream (not all if branches contain it)
if (m_pStream)
{
m_pStream->Release();
m_pStream = NULL;
}
return S_OK;
}

View File

@ -182,6 +182,13 @@ IFACEMETHODIMP PdfThumbnailProvider::GetThumbnail(UINT cx, HBITMAP* phbmp, WTS_A
}
}
// ensure releasing the stream (not all if branches contain it)
if (m_pStream)
{
m_pStream->Release();
m_pStream = NULL;
}
return S_OK;
}

View File

@ -183,6 +183,12 @@ IFACEMETHODIMP QoiThumbnailProvider::GetThumbnail(UINT cx, HBITMAP* phbmp, WTS_A
}
}
// ensure releasing the stream (not all if branches contain it)
if (m_pStream)
{
m_pStream->Release();
m_pStream = NULL;
}
return S_OK;
}

View File

@ -181,6 +181,13 @@ IFACEMETHODIMP StlThumbnailProvider::GetThumbnail(UINT cx, HBITMAP* phbmp, WTS_A
}
}
// ensure releasing the stream (not all if branches contain it)
if (m_pStream)
{
m_pStream->Release();
m_pStream = NULL;
}
return S_OK;
}

View File

@ -182,6 +182,13 @@ IFACEMETHODIMP SvgThumbnailProvider::GetThumbnail(UINT cx, HBITMAP* phbmp, WTS_A
}
}
// ensure releasing the stream (not all if branches contain it)
if (m_pStream)
{
m_pStream->Release();
m_pStream = NULL;
}
return S_OK;
}

View File

@ -155,7 +155,9 @@ namespace RegistryPreview
// Pull in a new REG file - we have to use the direct Win32 method because FileOpenPicker crashes when it's
// called while running as admin
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this);
string filename = OpenFilePicker.ShowDialog(
windowHandle,
resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0',
resourceLoader.GetString("OpenDialogTitle"));
@ -197,7 +199,9 @@ namespace RegistryPreview
{
// Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's
// called while running as admin
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this);
string filename = SaveFilePicker.ShowDialog(
windowHandle,
resourceLoader.GetString("SuggestFileName"),
resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0',
resourceLoader.GetString("SaveDialogTitle"));

View File

@ -2,6 +2,7 @@
// 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 RegistryPreview
@ -13,11 +14,12 @@ namespace RegistryPreview
[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool GetOpenFileName(ref FileName openFileName);
public static string ShowDialog(string filter, string dialogTitle)
public static string ShowDialog(IntPtr windowHandle, string filter, string dialogTitle)
{
FileName openFileName = default(FileName);
openFileName.StructSize = Marshal.SizeOf(openFileName);
openFileName.HwndOwner = windowHandle;
openFileName.Filter = filter;
openFileName.File = new string(new char[256]);
openFileName.MaxFile = openFileName.File.Length;

View File

@ -2,6 +2,7 @@
// 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 RegistryPreview
@ -13,11 +14,12 @@ namespace RegistryPreview
[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool GetSaveFileName(ref FileName saveFileName);
public static string ShowDialog(string suggestedFilename, string filter, string dialogTitle)
public static string ShowDialog(IntPtr windowHandle, string suggestedFilename, string filter, string dialogTitle)
{
FileName saveFileName = default(FileName);
saveFileName.StructSize = Marshal.SizeOf(saveFileName);
saveFileName.HwndOwner = windowHandle;
saveFileName.Filter = filter;
saveFileName.File = new string(new char[256]);
saveFileName.MaxFile = saveFileName.File.Length;

View File

@ -611,6 +611,7 @@ void VideoConferenceModule::enable()
#endif
hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL);
}
Trace::EnableVideoConference(true);
}
void VideoConferenceModule::unmuteAll()
@ -664,6 +665,7 @@ void VideoConferenceModule::disable()
_enabled = false;
}
Trace::EnableVideoConference(false);
}
bool VideoConferenceModule::is_enabled()

View File

@ -19,6 +19,17 @@ void Trace::UnregisterProvider() noexcept
TraceLoggingUnregister(g_hProvider);
}
// Log if the user has VCM enabled or disabled
void Trace::EnableVideoConference(const bool enabled) noexcept
{
TraceLoggingWrite(
g_hProvider,
"VideoConference_EnableVideoConference",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingBoolean(enabled, "Enabled"));
}
void Trace::SettingsChanged(const struct VideoConferenceSettings& settings) noexcept
{
bool CustomOverlayImage = (settings.imageOverlayPath.length() > 0);

View File

@ -6,6 +6,7 @@ class Trace
public:
static void RegisterProvider() noexcept;
static void UnregisterProvider() noexcept;
static void EnableVideoConference(const bool enabled) noexcept;
static void SettingsChanged(const struct VideoConferenceSettings &settings) noexcept;
static void MicrophoneMuted() noexcept;
static void CameraMuted() noexcept;

View File

@ -3,8 +3,10 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using global::PowerToys.GPOWrapper;
@ -76,6 +78,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private bool _isPowerShell7Detected;
private bool isPowerShellPreviewDetected;
private string powerShellPreviewPath;
public bool IsPowerShell7Detected
{
get => _isPowerShell7Detected;
@ -129,6 +134,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
get => RuntimeInformation.OSArchitecture == System.Runtime.InteropServices.Architecture.Arm64;
}
public string RunPowerShellOrPreviewScript(string powershellExecutable, string powershellArguments, bool hidePowerShellWindow = false)
{
if (isPowerShellPreviewDetected)
{
return RunPowerShellScript(Path.Combine(powerShellPreviewPath, "pwsh-preview.cmd"), powershellArguments, hidePowerShellWindow);
}
else
{
return RunPowerShellScript(powershellExecutable, powershellArguments, hidePowerShellWindow);
}
}
public string RunPowerShellScript(string powershellExecutable, string powershellArguments, bool hidePowerShellWindow = false)
{
string outputLog = string.Empty;
@ -160,6 +177,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
public void CheckCommandNotFoundRequirements()
{
isPowerShellPreviewDetected = false;
var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\CheckCmdNotFoundRequirements.ps1";
var arguments = $"-NoProfile -NonInteractive -ExecutionPolicy Unrestricted -File \"{ps1File}\"";
var result = RunPowerShellScript("pwsh.exe", arguments, true);
@ -179,6 +197,33 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
IsPowerShell7Detected = false;
}
if (!IsPowerShell7Detected)
{
// powerShell Preview might be installed, check it.
try
{
// we have to search for the directory where the PowerShell preview command is located. It is added to the PATH environment variable, so we have to search for it there
foreach (string pathCandidate in Environment.GetEnvironmentVariable("PATH").Split(';'))
{
if (File.Exists(Path.Combine(pathCandidate, "pwsh-preview.cmd")))
{
result = RunPowerShellScript(Path.Combine(pathCandidate, "pwsh-preview.cmd"), arguments, true);
if (result.Contains("PowerShell 7.4 or greater detected."))
{
isPowerShellPreviewDetected = true;
IsPowerShell7Detected = true;
powerShellPreviewPath = pathCandidate;
break;
}
}
}
}
catch (Exception)
{
// nothing to do. No additional PowerShell installation found
}
}
if (result.Contains("WinGet Client module detected."))
{
IsWinGetClientModuleDetected = true;
@ -204,7 +249,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\InstallPowerShell7.ps1";
var arguments = $"-NoProfile -ExecutionPolicy Unrestricted -File \"{ps1File}\"";
var result = RunPowerShellScript("powershell.exe", arguments);
var result = RunPowerShellOrPreviewScript("powershell.exe", arguments);
if (result.Contains("Powershell 7 successfully installed."))
{
IsPowerShell7Detected = true;
@ -220,7 +265,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\InstallWinGetClientModule.ps1";
var arguments = $"-NoProfile -ExecutionPolicy Unrestricted -File \"{ps1File}\"";
var result = RunPowerShellScript("pwsh.exe", arguments);
var result = RunPowerShellOrPreviewScript("pwsh.exe", arguments);
if (result.Contains("WinGet Client module detected."))
{
IsWinGetClientModuleDetected = true;
@ -237,7 +282,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\EnableModule.ps1";
var arguments = $"-NoProfile -ExecutionPolicy Unrestricted -File \"{ps1File}\" -scriptPath \"{AssemblyDirectory}\\..\"";
var result = RunPowerShellScript("pwsh.exe", arguments);
var result = RunPowerShellOrPreviewScript("pwsh.exe", arguments);
if (result.Contains("Module is already registered in the profile file.") || result.Contains("Module was successfully registered in the profile file."))
{
@ -252,7 +297,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\DisableModule.ps1";
var arguments = $"-NoProfile -ExecutionPolicy Unrestricted -File \"{ps1File}\"";
var result = RunPowerShellScript("pwsh.exe", arguments);
var result = RunPowerShellOrPreviewScript("pwsh.exe", arguments);
if (result.Contains("Removed the Command Not Found reference from the profile file.") || result.Contains("No instance of Command Not Found was found in the profile file."))
{