Compare commits

...

5 Commits

Author SHA1 Message Date
Jaime Bernardo
4282730e97 [WinUI]Upgrade Windows App SDK to 1.1.1 (#18842) 2022-06-15 01:14:15 +01:00
Jaime Bernardo
74ba26ee06 [PTRun]Add logs to check Web Browser detection (#18831)
* [PTRun]Add logs to check Web Browser detection

* Use proper initial value

* Add punctuation to the end of the log message
2022-06-14 21:05:44 +01:00
Seraphima Zykova
d7c2fe38fb [FancyZones] Update windows positions after changing the layout fix (#18805)
* removed IWorkArea interface

* split work area initialization

* changed rect type in zoneset

* tests


upd work area tests
removed obsolete, update others
updated work area tests

* get current vd windows

* update windows positions

* removed unused flag

* moved update window positions to work area

* check monitor

* refactoring
2022-06-14 16:10:40 +01:00
Jaime Bernardo
38e4692d92 [PTRun]Add setting to disable input delay (#18724)
* [PTRun]Add setting to disable input delay

* Address feedback and allow configuring delay

* Address PR feedback
2022-06-14 16:10:26 +01:00
Stefan Markovic
41ae1f9fbc [OOBE]Make OOBE window resizable (#18727) 2022-06-14 16:09:41 +01:00
27 changed files with 524 additions and 528 deletions

View File

@@ -152,19 +152,18 @@ protected:
private: private:
void UpdateWorkAreas() noexcept; void UpdateWorkAreas() noexcept;
void UpdateWindowsPositions(bool suppressMove = false) noexcept;
void CycleTabs(bool reverse) noexcept; void CycleTabs(bool reverse) noexcept;
bool OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept; bool OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept;
bool OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept; bool OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept;
bool OnSnapHotkey(DWORD vkCode) noexcept; bool OnSnapHotkey(DWORD vkCode) noexcept;
bool ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept; bool ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, std::shared_ptr<WorkArea> workArea) noexcept;
void RegisterVirtualDesktopUpdates() noexcept; void RegisterVirtualDesktopUpdates() noexcept;
void UpdateHotkey(int hotkeyId, const PowerToysSettings::HotkeyObject& hotkeyObject, bool enable) noexcept; void UpdateHotkey(int hotkeyId, const PowerToysSettings::HotkeyObject& hotkeyObject, bool enable) noexcept;
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept; std::pair<std::shared_ptr<WorkArea>, ZoneIndexSet> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& workAreaMap) noexcept;
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> workArea, const ZoneIndexSet& zoneIndexSet) noexcept; void MoveWindowIntoZone(HWND window, std::shared_ptr<WorkArea> workArea, const ZoneIndexSet& zoneIndexSet) noexcept;
bool MoveToAppLastZone(HWND window, HMONITOR active, HMONITOR primary) noexcept; bool MoveToAppLastZone(HWND window, HMONITOR active, HMONITOR primary) noexcept;
void OnEditorExitEvent() noexcept; void OnEditorExitEvent() noexcept;
@@ -289,14 +288,14 @@ FancyZones::VirtualDesktopChanged() noexcept
PostMessage(m_window, WM_PRIV_VD_SWITCH, 0, 0); PostMessage(m_window, WM_PRIV_VD_SWITCH, 0, 0);
} }
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> FancyZones::GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept std::pair<std::shared_ptr<WorkArea>, ZoneIndexSet> FancyZones::GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& workAreaMap) noexcept
{ {
if (monitor) if (monitor)
{ {
if (workAreaMap.contains(monitor)) if (workAreaMap.contains(monitor))
{ {
auto workArea = workAreaMap.at(monitor); auto workArea = workAreaMap.at(monitor);
return std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet>{ workArea, workArea->GetWindowZoneIndexes(window) }; return std::pair<std::shared_ptr<WorkArea>, ZoneIndexSet>{ workArea, workArea->GetWindowZoneIndexes(window) };
} }
else else
{ {
@@ -310,15 +309,15 @@ std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> FancyZones::GetAppZoneHistory
auto zoneIndexSet = workArea->GetWindowZoneIndexes(window); auto zoneIndexSet = workArea->GetWindowZoneIndexes(window);
if (!zoneIndexSet.empty()) if (!zoneIndexSet.empty())
{ {
return std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet>{ workArea, zoneIndexSet }; return std::pair<std::shared_ptr<WorkArea>, ZoneIndexSet>{ workArea, zoneIndexSet };
} }
} }
} }
return std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet>{ nullptr, {} }; return std::pair<std::shared_ptr<WorkArea>, ZoneIndexSet>{ nullptr, {} };
} }
void FancyZones::MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> workArea, const ZoneIndexSet& zoneIndexSet) noexcept void FancyZones::MoveWindowIntoZone(HWND window, std::shared_ptr<WorkArea> workArea, const ZoneIndexSet& zoneIndexSet) noexcept
{ {
if (workArea) if (workArea)
{ {
@@ -338,7 +337,7 @@ bool FancyZones::MoveToAppLastZone(HWND window, HMONITOR active, HMONITOR primar
} }
// Search application history on currently active monitor. // Search application history on currently active monitor.
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> appZoneHistoryInfo = GetAppZoneHistoryInfo(window, active, workAreaMap); std::pair<std::shared_ptr<WorkArea>, ZoneIndexSet> appZoneHistoryInfo = GetAppZoneHistoryInfo(window, active, workAreaMap);
// No application history on currently active monitor // No application history on currently active monitor
if (appZoneHistoryInfo.second.empty()) if (appZoneHistoryInfo.second.empty())
@@ -791,7 +790,8 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
{ {
if (FancyZonesSettings::settings().displayChange_moveWindows) if (FancyZonesSettings::settings().displayChange_moveWindows)
{ {
UpdateWindowsPositions(); auto activeWorkAreas = m_workAreaHandler.GetWorkAreasByDesktopId(VirtualDesktop::instance().GetCurrentVirtualDesktopId());
m_windowMoveHandler.UpdateWindowsPositions(activeWorkAreas);
} }
} }
} }
@@ -883,19 +883,6 @@ void FancyZones::UpdateWorkAreas() noexcept
} }
} }
void FancyZones::UpdateWindowsPositions(bool suppressMove) noexcept
{
for (const auto [window, desktopId] : VirtualDesktop::instance().GetWindowsRelatedToDesktops())
{
auto zoneIndexSet = FancyZonesWindowProperties::RetrieveZoneIndexProperty(window);
auto workArea = m_workAreaHandler.GetWorkArea(window, desktopId);
if (workArea)
{
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, workArea, suppressMove);
}
}
}
void FancyZones::CycleTabs(bool reverse) noexcept void FancyZones::CycleTabs(bool reverse) noexcept
{ {
auto window = GetForegroundWindow(); auto window = GetForegroundWindow();
@@ -994,7 +981,7 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
// If that didn't work, extract zones from all other monitors and target one of them // If that didn't work, extract zones from all other monitors and target one of them
std::vector<RECT> zoneRects; std::vector<RECT> zoneRects;
std::vector<std::pair<ZoneIndex, winrt::com_ptr<IWorkArea>>> zoneRectsInfo; std::vector<std::pair<ZoneIndex, std::shared_ptr<WorkArea>>> zoneRectsInfo;
RECT currentMonitorRect{ .top = 0, .bottom = -1 }; RECT currentMonitorRect{ .top = 0, .bottom = -1 };
for (const auto& [monitor, monitorRect] : allMonitors) for (const auto& [monitor, monitorRect] : allMonitors)
@@ -1119,7 +1106,7 @@ bool FancyZones::OnSnapHotkey(DWORD vkCode) noexcept
return false; return false;
} }
bool FancyZones::ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept bool FancyZones::ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, std::shared_ptr<WorkArea> workArea) noexcept
{ {
// Check whether Alt is used in the shortcut key combination // Check whether Alt is used in the shortcut key combination
if (GetAsyncKeyState(VK_MENU) & 0x8000) if (GetAsyncKeyState(VK_MENU) & 0x8000)
@@ -1223,8 +1210,11 @@ void FancyZones::UpdateZoneSets() noexcept
workArea->UpdateActiveZoneSet(); workArea->UpdateActiveZoneSet();
} }
auto moveWindows = FancyZonesSettings::settings().zoneSetChange_moveWindows; if (FancyZonesSettings::settings().zoneSetChange_moveWindows)
UpdateWindowsPositions(!moveWindows); {
auto activeWorkAreas = m_workAreaHandler.GetWorkAreasByDesktopId(VirtualDesktop::instance().GetCurrentVirtualDesktopId());
m_windowMoveHandler.UpdateWindowsPositions(activeWorkAreas);
}
} }
bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept

View File

@@ -4,10 +4,6 @@
#include <functional> #include <functional>
interface IWorkArea;
interface IFancyZonesSettings;
interface IZoneSet;
struct WinHookEvent; struct WinHookEvent;
interface __declspec(uuid("{50D3F0F5-736E-4186-BDF4-3D6BEE150C3A}")) IFancyZones : public IUnknown interface __declspec(uuid("{50D3F0F5-736E-4186-BDF4-3D6BEE150C3A}")) IFancyZones : public IUnknown

View File

@@ -6,10 +6,10 @@
#include <common/logger/logger.h> #include <common/logger/logger.h>
winrt::com_ptr<IWorkArea> MonitorWorkAreaHandler::GetWorkArea(const GUID& desktopId, HMONITOR monitor) std::shared_ptr<WorkArea> MonitorWorkAreaHandler::GetWorkArea(const GUID& desktopId, HMONITOR monitor)
{ {
auto desktopIt = workAreaMap.find(desktopId); auto desktopIt = workAreaMap.find(desktopId);
if (desktopIt != std::end(workAreaMap)) if (desktopIt != workAreaMap.end())
{ {
auto& perDesktopData = desktopIt->second; auto& perDesktopData = desktopIt->second;
auto monitorIt = perDesktopData.find(monitor); auto monitorIt = perDesktopData.find(monitor);
@@ -21,7 +21,7 @@ winrt::com_ptr<IWorkArea> MonitorWorkAreaHandler::GetWorkArea(const GUID& deskto
return nullptr; return nullptr;
} }
winrt::com_ptr<IWorkArea> MonitorWorkAreaHandler::GetWorkAreaFromCursor(const GUID& desktopId) std::shared_ptr<WorkArea> MonitorWorkAreaHandler::GetWorkAreaFromCursor(const GUID& desktopId)
{ {
auto allMonitorsWorkArea = GetWorkArea(desktopId, NULL); auto allMonitorsWorkArea = GetWorkArea(desktopId, NULL);
if (allMonitorsWorkArea) if (allMonitorsWorkArea)
@@ -42,7 +42,7 @@ winrt::com_ptr<IWorkArea> MonitorWorkAreaHandler::GetWorkAreaFromCursor(const GU
} }
} }
winrt::com_ptr<IWorkArea> MonitorWorkAreaHandler::GetWorkArea(HWND window, const GUID& desktopId) std::shared_ptr<WorkArea> MonitorWorkAreaHandler::GetWorkArea(HWND window, const GUID& desktopId)
{ {
auto allMonitorsWorkArea = GetWorkArea(desktopId, NULL); auto allMonitorsWorkArea = GetWorkArea(desktopId, NULL);
if (allMonitorsWorkArea) if (allMonitorsWorkArea)
@@ -58,19 +58,20 @@ winrt::com_ptr<IWorkArea> MonitorWorkAreaHandler::GetWorkArea(HWND window, const
} }
} }
const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& MonitorWorkAreaHandler::GetWorkAreasByDesktopId(const GUID& desktopId) const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& MonitorWorkAreaHandler::GetWorkAreasByDesktopId(const GUID& desktopId)
{ {
if (workAreaMap.contains(desktopId)) if (workAreaMap.contains(desktopId))
{ {
return workAreaMap[desktopId]; return workAreaMap[desktopId];
} }
static const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>> empty;
static const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>> empty{};
return empty; return empty;
} }
std::vector<winrt::com_ptr<IWorkArea>> MonitorWorkAreaHandler::GetAllWorkAreas() std::vector<std::shared_ptr<WorkArea>> MonitorWorkAreaHandler::GetAllWorkAreas()
{ {
std::vector<winrt::com_ptr<IWorkArea>> workAreas{}; std::vector<std::shared_ptr<WorkArea>> workAreas{};
for (const auto& [desktopId, perDesktopData] : workAreaMap) for (const auto& [desktopId, perDesktopData] : workAreaMap)
{ {
std::transform(std::begin(perDesktopData), std::transform(std::begin(perDesktopData),
@@ -81,7 +82,7 @@ std::vector<winrt::com_ptr<IWorkArea>> MonitorWorkAreaHandler::GetAllWorkAreas()
return workAreas; return workAreas;
} }
void MonitorWorkAreaHandler::AddWorkArea(const GUID& desktopId, HMONITOR monitor, winrt::com_ptr<IWorkArea>& workArea) void MonitorWorkAreaHandler::AddWorkArea(const GUID& desktopId, HMONITOR monitor, std::shared_ptr<WorkArea>& workArea)
{ {
if (!workAreaMap.contains(desktopId)) if (!workAreaMap.contains(desktopId))
{ {

View File

@@ -2,7 +2,7 @@
#include "GuidUtils.h" #include "GuidUtils.h"
interface IWorkArea; class WorkArea;
struct ZoneColors; struct ZoneColors;
enum struct OverlappingZonesAlgorithm; enum struct OverlappingZonesAlgorithm;
@@ -18,7 +18,7 @@ public:
* @returns Object representing single work area, interface to all actions available on work area * @returns Object representing single work area, interface to all actions available on work area
* (e.g. moving windows through zone layout specified for that work area). * (e.g. moving windows through zone layout specified for that work area).
*/ */
winrt::com_ptr<IWorkArea> GetWorkArea(const GUID& desktopId, HMONITOR monitor); std::shared_ptr<WorkArea> GetWorkArea(const GUID& desktopId, HMONITOR monitor);
/** /**
* Get work area based on virtual desktop id and the current cursor position. * Get work area based on virtual desktop id and the current cursor position.
@@ -28,7 +28,7 @@ public:
* @returns Object representing single work area, interface to all actions available on work area * @returns Object representing single work area, interface to all actions available on work area
* (e.g. moving windows through zone layout specified for that work area). * (e.g. moving windows through zone layout specified for that work area).
*/ */
winrt::com_ptr<IWorkArea> GetWorkAreaFromCursor(const GUID& desktopId); std::shared_ptr<WorkArea> GetWorkAreaFromCursor(const GUID& desktopId);
/** /**
* Get work area on which specified window is located. * Get work area on which specified window is located.
@@ -39,7 +39,7 @@ public:
* @returns Object representing single work area, interface to all actions available on work area * @returns Object representing single work area, interface to all actions available on work area
* (e.g. moving windows through zone layout specified for that work area). * (e.g. moving windows through zone layout specified for that work area).
*/ */
winrt::com_ptr<IWorkArea> GetWorkArea(HWND window, const GUID& desktopId); std::shared_ptr<WorkArea> GetWorkArea(HWND window, const GUID& desktopId);
/** /**
* Get map of all work areas on single virtual desktop. Key in the map is monitor handle, while value * Get map of all work areas on single virtual desktop. Key in the map is monitor handle, while value
@@ -49,12 +49,12 @@ public:
* *
* @returns Map containing pairs of monitor and work area for that monitor (within same virtual desktop). * @returns Map containing pairs of monitor and work area for that monitor (within same virtual desktop).
*/ */
const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& GetWorkAreasByDesktopId(const GUID& desktopId); const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& GetWorkAreasByDesktopId(const GUID& desktopId);
/** /**
* @returns All registered work areas. * @returns All registered work areas.
*/ */
std::vector<winrt::com_ptr<IWorkArea>> GetAllWorkAreas(); std::vector<std::shared_ptr<WorkArea>> GetAllWorkAreas();
/** /**
* Register new work area. * Register new work area.
@@ -63,7 +63,7 @@ public:
* @param[in] monitor Monitor handle. * @param[in] monitor Monitor handle.
* @param[in] workAra Object representing single work area. * @param[in] workAra Object representing single work area.
*/ */
void AddWorkArea(const GUID& desktopId, HMONITOR monitor, winrt::com_ptr<IWorkArea>& workArea); void AddWorkArea(const GUID& desktopId, HMONITOR monitor, std::shared_ptr<WorkArea>& workArea);
/** /**
* Check if work area is already registered. * Check if work area is already registered.
@@ -89,5 +89,5 @@ public:
private: private:
// Work area is uniquely defined by monitor and virtual desktop id. // Work area is uniquely defined by monitor and virtual desktop id.
std::unordered_map<GUID, std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>> workAreaMap; std::unordered_map<GUID, std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>> workAreaMap;
}; };

View File

@@ -240,6 +240,31 @@ std::vector<std::pair<HWND, GUID>> VirtualDesktop::GetWindowsRelatedToDesktops()
return result; return result;
} }
std::vector<HWND> VirtualDesktop::GetWindowsFromCurrentDesktop() const
{
using result_t = std::vector<HWND>;
result_t windows;
auto callback = [](HWND window, LPARAM data) -> BOOL {
result_t& result = *reinterpret_cast<result_t*>(data);
result.push_back(window);
return TRUE;
};
EnumWindows(callback, reinterpret_cast<LPARAM>(&windows));
std::vector<HWND> result;
for (auto window : windows)
{
BOOL isOnCurrentVD{};
if (m_vdManager->IsWindowOnCurrentVirtualDesktop(window, &isOnCurrentVD) == S_OK && isOnCurrentVD)
{
result.push_back(window);
}
}
return result;
}
GUID VirtualDesktop::GetCurrentVirtualDesktopId() const noexcept GUID VirtualDesktop::GetCurrentVirtualDesktopId() const noexcept
{ {
return m_currentVirtualDesktopId; return m_currentVirtualDesktopId;

View File

@@ -15,6 +15,7 @@ public:
std::optional<GUID> GetDesktopId(HWND window) const; std::optional<GUID> GetDesktopId(HWND window) const;
std::optional<GUID> GetDesktopIdByTopLevelWindows() const; std::optional<GUID> GetDesktopIdByTopLevelWindows() const;
std::vector<std::pair<HWND, GUID>> GetWindowsRelatedToDesktops() const; std::vector<std::pair<HWND, GUID>> GetWindowsRelatedToDesktops() const;
std::vector<HWND> GetWindowsFromCurrentDesktop() const;
// registry // registry
std::optional<GUID> GetCurrentVirtualDesktopIdFromRegistry() const; std::optional<GUID> GetCurrentVirtualDesktopIdFromRegistry() const;

View File

@@ -59,7 +59,7 @@ WindowMoveHandler::WindowMoveHandler(const std::function<void()>& keyUpdateCallb
{ {
} }
void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& workAreaMap) noexcept
{ {
if (!FancyZonesWindowProcessing::IsProcessable(window)) if (!FancyZonesWindowProcessing::IsProcessable(window))
{ {
@@ -104,7 +104,7 @@ void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const
m_draggedWindowWorkArea->MoveSizeEnter(m_draggedWindow); m_draggedWindowWorkArea->MoveSizeEnter(m_draggedWindow);
if (FancyZonesSettings::settings().showZonesOnAllMonitors) if (FancyZonesSettings::settings().showZonesOnAllMonitors)
{ {
for (auto [keyMonitor, workArea] : workAreaMap) for (const auto& [keyMonitor, workArea] : workAreaMap)
{ {
// Skip calling ShowZonesOverlay for iter->second (m_draggedWindowWorkArea) since it // Skip calling ShowZonesOverlay for iter->second (m_draggedWindowWorkArea) since it
// was already called in MoveSizeEnter // was already called in MoveSizeEnter
@@ -120,7 +120,7 @@ void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const
{ {
ResetWindowTransparency(); ResetWindowTransparency();
m_draggedWindowWorkArea = nullptr; m_draggedWindowWorkArea = nullptr;
for (auto [keyMonitor, workArea] : workAreaMap) for (const auto& [keyMonitor, workArea] : workAreaMap)
{ {
if (workArea) if (workArea)
{ {
@@ -132,8 +132,7 @@ void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const
auto workArea = workAreaMap.find(monitor); auto workArea = workAreaMap.find(monitor);
if (workArea != workAreaMap.end()) if (workArea != workAreaMap.end())
{ {
const auto workAreaPtr = workArea->second; const auto zoneSet = workArea->second->ZoneSet();
const auto zoneSet = workAreaPtr->ZoneSet();
if (zoneSet) if (zoneSet)
{ {
zoneSet->DismissWindow(window); zoneSet->DismissWindow(window);
@@ -141,7 +140,7 @@ void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const
} }
} }
void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& workAreaMap) noexcept
{ {
if (!m_inDragging) if (!m_inDragging)
{ {
@@ -208,7 +207,7 @@ void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen,
} }
} }
void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& workAreaMap) noexcept
{ {
if (window != m_draggedWindow) if (window != m_draggedWindow)
{ {
@@ -292,29 +291,49 @@ void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const st
} }
} }
void WindowMoveHandler::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, winrt::com_ptr<IWorkArea> workArea, bool suppressMove) noexcept void WindowMoveHandler::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, std::shared_ptr<WorkArea> workArea) noexcept
{ {
if (window != m_draggedWindow) if (window != m_draggedWindow)
{ {
workArea->MoveWindowIntoZoneByIndexSet(window, indexSet, suppressMove); workArea->MoveWindowIntoZoneByIndexSet(window, indexSet);
} }
} }
bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, std::shared_ptr<WorkArea> workArea) noexcept
{ {
return workArea && workArea->MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, cycle); return workArea && workArea->MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, cycle);
} }
bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, std::shared_ptr<WorkArea> workArea) noexcept
{ {
return workArea && workArea->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle); return workArea && workArea->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle);
} }
bool WindowMoveHandler::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IWorkArea> workArea) noexcept bool WindowMoveHandler::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, std::shared_ptr<WorkArea> workArea) noexcept
{ {
return workArea && workArea->ExtendWindowByDirectionAndPosition(window, vkCode); return workArea && workArea->ExtendWindowByDirectionAndPosition(window, vkCode);
} }
void WindowMoveHandler::UpdateWindowsPositions(const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& activeWorkAreas) noexcept
{
for (const auto& window : VirtualDesktop::instance().GetWindowsFromCurrentDesktop())
{
auto zoneIndexSet = FancyZonesWindowProperties::RetrieveZoneIndexProperty(window);
if (zoneIndexSet.size() == 0)
{
continue;
}
for (const auto& [monitor, workArea] : activeWorkAreas)
{
if (MonitorFromWindow(window, MONITOR_DEFAULTTONULL) == monitor)
{
workArea->MoveWindowIntoZoneByIndexSet(window, zoneIndexSet);
}
}
}
}
void WindowMoveHandler::WarnIfElevationIsRequired(HWND window) noexcept void WindowMoveHandler::WarnIfElevationIsRequired(HWND window) noexcept
{ {
using namespace notifications; using namespace notifications;

View File

@@ -7,22 +7,24 @@
#include <functional> #include <functional>
interface IFancyZonesSettings; interface IFancyZonesSettings;
interface IWorkArea; class WorkArea;
class WindowMoveHandler class WindowMoveHandler
{ {
public: public:
WindowMoveHandler(const std::function<void()>& keyUpdateCallback); WindowMoveHandler(const std::function<void()>& keyUpdateCallback);
void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept; void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& workAreaMap) noexcept;
void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept; void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& workAreaMap) noexcept;
void MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept; void MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& workAreaMap) noexcept;
void MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, winrt::com_ptr<IWorkArea> workArea, bool suppressMove = false) noexcept; void MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, std::shared_ptr<WorkArea> workArea) noexcept;
bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept; bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, std::shared_ptr<WorkArea> workArea) noexcept;
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept; bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, std::shared_ptr<WorkArea> workArea) noexcept;
bool ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IWorkArea> workArea) noexcept; bool ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, std::shared_ptr<WorkArea> workArea) noexcept;
void UpdateWindowsPositions(const std::unordered_map<HMONITOR, std::shared_ptr<WorkArea>>& activeWorkAreas) noexcept;
inline void OnMouseDown() noexcept inline void OnMouseDown() noexcept
{ {
m_mouseState = !m_mouseState; m_mouseState = !m_mouseState;
@@ -67,7 +69,7 @@ private:
bool m_inDragging{}; // Whether or not a move/size operation is currently active bool m_inDragging{}; // Whether or not a move/size operation is currently active
HWND m_draggedWindow{}; // The window that is being moved/sized HWND m_draggedWindow{}; // The window that is being moved/sized
MoveSizeWindowInfo m_draggedWindowInfo; // MoveSizeWindowInfo of the window at the moment when dragging started MoveSizeWindowInfo m_draggedWindowInfo; // MoveSizeWindowInfo of the window at the moment when dragging started
winrt::com_ptr<IWorkArea> m_draggedWindowWorkArea; // "Active" WorkArea, where the move/size is happening. Will update as drag moves between monitors. std::shared_ptr<WorkArea> m_draggedWindowWorkArea; // "Active" WorkArea, where the move/size is happening. Will update as drag moves between monitors.
bool m_dragEnabled{}; // True if we should be showing zone hints while dragging bool m_dragEnabled{}; // True if we should be showing zone hints while dragging
WindowTransparencyProperties m_windowTransparencyProperties; WindowTransparencyProperties m_windowTransparencyProperties;

View File

@@ -3,6 +3,7 @@
#include <common/logger/call_tracer.h> #include <common/logger/call_tracer.h>
#include <common/logger/logger.h> #include <common/logger/logger.h>
#include <common/utils/winapi_error.h>
#include "FancyZonesData/AppliedLayouts.h" #include "FancyZonesData/AppliedLayouts.h"
#include "FancyZonesData/AppZoneHistory.h" #include "FancyZonesData/AppZoneHistory.h"
@@ -12,6 +13,8 @@
#include "trace.h" #include "trace.h"
#include "on_thread_executor.h" #include "on_thread_executor.h"
#include "Settings.h" #include "Settings.h"
#include <FancyZonesLib/FancyZonesWindowProperties.h>
#include <FancyZonesLib/VirtualDesktop.h>
#include <FancyZonesLib/WindowUtils.h> #include <FancyZonesLib/WindowUtils.h>
#include <ShellScalingApi.h> #include <ShellScalingApi.h>
@@ -28,8 +31,6 @@ namespace NonLocalizable
using namespace FancyZonesUtils; using namespace FancyZonesUtils;
struct WorkArea;
namespace namespace
{ {
// The reason for using this class is the need to call ShowWindow(window, SW_SHOWNORMAL); on each // The reason for using this class is the need to call ShowWindow(window, SW_SHOWNORMAL); on each
@@ -103,71 +104,6 @@ namespace
WindowPool windowPool; WindowPool windowPool;
} }
struct WorkArea : public winrt::implements<WorkArea, IWorkArea>
{
public:
WorkArea(HINSTANCE hinstance);
~WorkArea();
bool Init(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId);
IFACEMETHODIMP MoveSizeEnter(HWND window) noexcept;
IFACEMETHODIMP MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled, bool selectManyZones) noexcept;
IFACEMETHODIMP MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept;
IFACEMETHODIMP_(void)
MoveWindowIntoZoneByIndex(HWND window, ZoneIndex index) noexcept;
IFACEMETHODIMP_(void)
MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, bool suppressMove = false) noexcept;
IFACEMETHODIMP_(bool)
MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle) noexcept;
IFACEMETHODIMP_(bool)
MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept;
IFACEMETHODIMP_(bool)
ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept;
IFACEMETHODIMP_(FancyZonesDataTypes::DeviceIdData)
UniqueId() const noexcept { return { m_uniqueId }; }
IFACEMETHODIMP_(void)
SaveWindowProcessToZoneIndex(HWND window) noexcept;
IFACEMETHODIMP_(IZoneSet*)
ZoneSet() const noexcept { return m_zoneSet.get(); }
IFACEMETHODIMP_(ZoneIndexSet)
GetWindowZoneIndexes(HWND window) const noexcept;
IFACEMETHODIMP_(void)
ShowZonesOverlay() noexcept;
IFACEMETHODIMP_(void)
HideZonesOverlay() noexcept;
IFACEMETHODIMP_(void)
UpdateActiveZoneSet() noexcept;
IFACEMETHODIMP_(void)
CycleTabs(HWND window, bool reverse) noexcept;
IFACEMETHODIMP_(void)
ClearSelectedZones() noexcept;
IFACEMETHODIMP_(void)
FlashZones() noexcept;
protected:
static LRESULT CALLBACK s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept;
private:
void InitializeZoneSets(const FancyZonesDataTypes::DeviceIdData& parentUniqueId) noexcept;
void CalculateZoneSet(OverlappingZonesAlgorithm overlappingAlgorithm) noexcept;
void UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept;
LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept;
ZoneIndexSet ZonesFromPoint(POINT pt) noexcept;
void SetAsTopmostWindow() noexcept;
HMONITOR m_monitor{};
FancyZonesDataTypes::DeviceIdData m_uniqueId;
HWND m_window{}; // Hidden tool window used to represent current monitor desktop work area.
HWND m_windowMoveSize{};
winrt::com_ptr<IZoneSet> m_zoneSet;
ZoneIndexSet m_initialHighlightZone;
ZoneIndexSet m_highlightZone;
WPARAM m_keyLast{};
size_t m_keyCycle{};
std::unique_ptr<ZonesOverlay> m_zonesOverlay;
};
WorkArea::WorkArea(HINSTANCE hinstance) WorkArea::WorkArea(HINSTANCE hinstance)
{ {
WNDCLASSEXW wcex{}; WNDCLASSEXW wcex{};
@@ -184,30 +120,12 @@ WorkArea::~WorkArea()
windowPool.FreeZonesOverlayWindow(m_window); windowPool.FreeZonesOverlayWindow(m_window);
} }
bool WorkArea::Init(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId) bool WorkArea::Init(HINSTANCE hinstance, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId)
{ {
Rect workAreaRect;
m_monitor = monitor;
if (monitor)
{
MONITORINFO mi{};
mi.cbSize = sizeof(mi);
if (!GetMonitorInfoW(monitor, &mi))
{
Logger::error(L"GetMonitorInfo failed on work area initialization");
return false;
}
workAreaRect = Rect(mi.rcWork);
}
else
{
workAreaRect = GetAllMonitorsCombinedRect<&MONITORINFO::rcWork>();
}
m_uniqueId = uniqueId; m_uniqueId = uniqueId;
InitializeZoneSets(parentUniqueId); InitializeZoneSets(parentUniqueId);
m_window = windowPool.NewZonesOverlayWindow(workAreaRect, hinstance, this); m_window = windowPool.NewZonesOverlayWindow(m_workAreaRect, hinstance, this);
if (!m_window) if (!m_window)
{ {
@@ -220,7 +138,7 @@ bool WorkArea::Init(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataT
return true; return true;
} }
IFACEMETHODIMP WorkArea::MoveSizeEnter(HWND window) noexcept HRESULT WorkArea::MoveSizeEnter(HWND window) noexcept
{ {
m_windowMoveSize = window; m_windowMoveSize = window;
m_highlightZone = {}; m_highlightZone = {};
@@ -230,7 +148,7 @@ IFACEMETHODIMP WorkArea::MoveSizeEnter(HWND window) noexcept
return S_OK; return S_OK;
} }
IFACEMETHODIMP WorkArea::MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled, bool selectManyZones) noexcept HRESULT WorkArea::MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled, bool selectManyZones) noexcept
{ {
bool redraw = false; bool redraw = false;
POINT ptClient = ptScreen; POINT ptClient = ptScreen;
@@ -274,7 +192,7 @@ IFACEMETHODIMP WorkArea::MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled,
return S_OK; return S_OK;
} }
IFACEMETHODIMP WorkArea::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept HRESULT WorkArea::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept
{ {
if (m_windowMoveSize != window) if (m_windowMoveSize != window)
{ {
@@ -299,23 +217,20 @@ IFACEMETHODIMP WorkArea::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcep
return S_OK; return S_OK;
} }
IFACEMETHODIMP_(void) void WorkArea::MoveWindowIntoZoneByIndex(HWND window, ZoneIndex index) noexcept
WorkArea::MoveWindowIntoZoneByIndex(HWND window, ZoneIndex index) noexcept
{ {
MoveWindowIntoZoneByIndexSet(window, { index }); MoveWindowIntoZoneByIndexSet(window, { index });
} }
IFACEMETHODIMP_(void) void WorkArea::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet) noexcept
WorkArea::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, bool suppressMove) noexcept
{ {
if (m_zoneSet) if (m_zoneSet)
{ {
m_zoneSet->MoveWindowIntoZoneByIndexSet(window, m_window, indexSet, suppressMove); m_zoneSet->MoveWindowIntoZoneByIndexSet(window, m_window, indexSet);
} }
} }
IFACEMETHODIMP_(bool) bool WorkArea::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle) noexcept
WorkArea::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle) noexcept
{ {
if (m_zoneSet) if (m_zoneSet)
{ {
@@ -331,8 +246,7 @@ WorkArea::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool
return false; return false;
} }
IFACEMETHODIMP_(bool) bool WorkArea::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept
WorkArea::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept
{ {
if (m_zoneSet) if (m_zoneSet)
{ {
@@ -345,8 +259,7 @@ WorkArea::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bo
return false; return false;
} }
IFACEMETHODIMP_(bool) bool WorkArea::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept
WorkArea::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept
{ {
if (m_zoneSet) if (m_zoneSet)
{ {
@@ -359,8 +272,7 @@ WorkArea::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept
return false; return false;
} }
IFACEMETHODIMP_(void) void WorkArea::SaveWindowProcessToZoneIndex(HWND window) noexcept
WorkArea::SaveWindowProcessToZoneIndex(HWND window) noexcept
{ {
if (m_zoneSet) if (m_zoneSet)
{ {
@@ -378,8 +290,7 @@ WorkArea::SaveWindowProcessToZoneIndex(HWND window) noexcept
} }
} }
IFACEMETHODIMP_(ZoneIndexSet) ZoneIndexSet WorkArea::GetWindowZoneIndexes(HWND window) const noexcept
WorkArea::GetWindowZoneIndexes(HWND window) const noexcept
{ {
if (m_zoneSet) if (m_zoneSet)
{ {
@@ -401,8 +312,7 @@ WorkArea::GetWindowZoneIndexes(HWND window) const noexcept
return {}; return {};
} }
IFACEMETHODIMP_(void) void WorkArea::ShowZonesOverlay() noexcept
WorkArea::ShowZonesOverlay() noexcept
{ {
if (m_window) if (m_window)
{ {
@@ -412,8 +322,7 @@ WorkArea::ShowZonesOverlay() noexcept
} }
} }
IFACEMETHODIMP_(void) void WorkArea::HideZonesOverlay() noexcept
WorkArea::HideZonesOverlay() noexcept
{ {
if (m_window) if (m_window)
{ {
@@ -424,8 +333,7 @@ WorkArea::HideZonesOverlay() noexcept
} }
} }
IFACEMETHODIMP_(void) void WorkArea::UpdateActiveZoneSet() noexcept
WorkArea::UpdateActiveZoneSet() noexcept
{ {
bool isLayoutAlreadyApplied = AppliedLayouts::instance().IsLayoutApplied(m_uniqueId); bool isLayoutAlreadyApplied = AppliedLayouts::instance().IsLayoutApplied(m_uniqueId);
if (!isLayoutAlreadyApplied) if (!isLayoutAlreadyApplied)
@@ -441,8 +349,7 @@ WorkArea::UpdateActiveZoneSet() noexcept
} }
} }
IFACEMETHODIMP_(void) void WorkArea::CycleTabs(HWND window, bool reverse) noexcept
WorkArea::CycleTabs(HWND window, bool reverse) noexcept
{ {
if (m_zoneSet) if (m_zoneSet)
{ {
@@ -450,8 +357,7 @@ WorkArea::CycleTabs(HWND window, bool reverse) noexcept
} }
} }
IFACEMETHODIMP_(void) void WorkArea::ClearSelectedZones() noexcept
WorkArea::ClearSelectedZones() noexcept
{ {
if (m_highlightZone.size()) if (m_highlightZone.size())
{ {
@@ -460,8 +366,7 @@ WorkArea::ClearSelectedZones() noexcept
} }
} }
IFACEMETHODIMP_(void) void WorkArea::FlashZones() noexcept
WorkArea::FlashZones() noexcept
{ {
if (m_window) if (m_window)
{ {
@@ -513,31 +418,11 @@ void WorkArea::CalculateZoneSet(OverlappingZonesAlgorithm overlappingAlgorithm)
appliedLayout->sensitivityRadius, appliedLayout->sensitivityRadius,
overlappingAlgorithm)); overlappingAlgorithm));
RECT workArea;
if (m_monitor)
{
MONITORINFO monitorInfo{};
monitorInfo.cbSize = sizeof(monitorInfo);
if (GetMonitorInfoW(m_monitor, &monitorInfo))
{
workArea = monitorInfo.rcWork;
}
else
{
Logger::error(L"CalculateZoneSet: GetMonitorInfo failed");
return;
}
}
else
{
workArea = GetAllMonitorsCombinedRect<&MONITORINFO::rcWork>();
}
bool showSpacing = appliedLayout->showSpacing; bool showSpacing = appliedLayout->showSpacing;
int spacing = showSpacing ? appliedLayout->spacing : 0; int spacing = showSpacing ? appliedLayout->spacing : 0;
int zoneCount = appliedLayout->zoneCount; int zoneCount = appliedLayout->zoneCount;
zoneSet->CalculateZones(workArea, zoneCount, spacing); zoneSet->CalculateZones(m_workAreaRect, zoneCount, spacing);
UpdateActiveZoneSet(zoneSet.get()); UpdateActiveZoneSet(zoneSet.get());
} }
@@ -595,6 +480,11 @@ void WorkArea::SetAsTopmostWindow() noexcept
SetWindowPos(m_window, windowInsertAfter, 0, 0, 0, 0, flags); SetWindowPos(m_window, windowInsertAfter, 0, 0, 0, 0, flags);
} }
void WorkArea::LogInitializationError()
{
Logger::error(L"Unable to get monitor info, {}", get_last_error_or_default(GetLastError()));
}
#pragma endregion #pragma endregion
LRESULT CALLBACK WorkArea::s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept LRESULT CALLBACK WorkArea::s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept
@@ -611,13 +501,3 @@ LRESULT CALLBACK WorkArea::s_WndProc(HWND window, UINT message, WPARAM wparam, L
DefWindowProc(window, message, wparam, lparam); DefWindowProc(window, message, wparam, lparam);
} }
winrt::com_ptr<IWorkArea> MakeWorkArea(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId) noexcept
{
auto self = winrt::make_self<WorkArea>(hinstance);
if (self->Init(hinstance, monitor, uniqueId, parentUniqueId))
{
return self;
}
return nullptr;
}

View File

@@ -1,139 +1,111 @@
#pragma once #pragma once
#include "FancyZones.h"
#include "FancyZonesLib/ZoneSet.h"
#include "FancyZonesLib/FancyZonesDataTypes.h"
/** #include <FancyZonesLib/FancyZonesDataTypes.h>
* Class representing single work area, which is defined by monitor and virtual desktop. #include <FancyZonesLib/ZoneSet.h>
*/ #include <FancyZonesLib/util.h>
interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IWorkArea : public IUnknown
class ZonesOverlay;
class WorkArea
{ {
/** public:
* A window is being moved or resized. Track down window position and give zone layout WorkArea(HINSTANCE hinstance);
* hints if dragging functionality is enabled. ~WorkArea();
*
* @param window Handle of window being moved or resized.
*/
IFACEMETHOD(MoveSizeEnter)(HWND window) = 0;
/** public:
* A window has changed location, shape, or size. Track down window position and give zone layout bool Init(HINSTANCE hinstance, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId);
* hints if dragging functionality is enabled. inline bool InitWorkAreaRect(HMONITOR monitor)
* {
* @param ptScreen Cursor coordinates. m_monitor = monitor;
* @param dragEnabled Boolean indicating is giving hints about active zone layout enabled.
* Hints are given while dragging window while holding SHIFT key. #if defined(UNIT_TESTS)
* @param selectManyZones When this parameter is true, the set of highlighted zones is computed m_workAreaRect = FancyZonesUtils::Rect({ 0, 0, 1920, 1080 });
* by finding the minimum bounding rectangle of the zone(s) from which the return true;
* user started dragging and the zone(s) above which the user is hovering #endif
* at the moment this function is called. Otherwise, highlight only the zone(s)
* above which the user is currently hovering. if (monitor)
*/ {
IFACEMETHOD(MoveSizeUpdate)(POINT const& ptScreen, bool dragEnabled, bool selectManyZones) = 0; MONITORINFO mi{};
/** mi.cbSize = sizeof(mi);
* The movement or resizing of a window has finished. Assign window to the zone of it if (!GetMonitorInfoW(monitor, &mi))
* is dropped within zone borders. {
* return false;
* @param window Handle of window being moved or resized. }
* @param ptScreen Cursor coordinates where window is dropped.
*/ m_workAreaRect = FancyZonesUtils::Rect(mi.rcWork);
IFACEMETHOD(MoveSizeEnd)(HWND window, POINT const& ptScreen) = 0; }
/** else
* Assign window to the zone based on zone index inside zone layout. {
* m_workAreaRect = FancyZonesUtils::GetAllMonitorsCombinedRect<&MONITORINFO::rcWork>();
* @param window Handle of window which should be assigned to zone. }
* @param index Zone index within zone layout.
*/ return true;
IFACEMETHOD_(void, MoveWindowIntoZoneByIndex)(HWND window, ZoneIndex index) = 0; }
/**
* Assign window to the zones based on the set of zone indices inside zone layout. FancyZonesDataTypes::DeviceIdData UniqueId() const noexcept { return { m_uniqueId }; }
* IZoneSet* ZoneSet() const noexcept { return m_zoneSet.get(); }
* @param window Handle of window which should be assigned to zone.
* @param indexSet The set of zone indices within zone layout. ZoneIndexSet GetWindowZoneIndexes(HWND window) const noexcept;
* @param suppressMove Whether we should just update the records or move window to the zone.
*/ HRESULT MoveSizeEnter(HWND window) noexcept;
IFACEMETHOD_(void, MoveWindowIntoZoneByIndexSet)(HWND window, const ZoneIndexSet& indexSet, bool suppressMove = false) = 0; HRESULT MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled, bool selectManyZones) noexcept;
/** HRESULT MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept;
* Assign window to the zone based on direction (using WIN + LEFT/RIGHT arrow), based on zone index numbers, void MoveWindowIntoZoneByIndex(HWND window, ZoneIndex index) noexcept;
* not their on-screen position. void MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet) noexcept;
* bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle) noexcept;
* @param window Handle of window which should be assigned to zone. bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept;
* @param vkCode Pressed arrow key. bool ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept;
* @param cycle Whether we should move window to the first zone if we reached last zone in layout. void SaveWindowProcessToZoneIndex(HWND window) noexcept;
*
* @returns Boolean which is always true if cycle argument is set, otherwise indicating if there is more void UpdateActiveZoneSet() noexcept;
* zones left in the zone layout in which window can move.
*/ void ShowZonesOverlay() noexcept;
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirectionAndIndex)(HWND window, DWORD vkCode, bool cycle) = 0; void HideZonesOverlay() noexcept;
/** void FlashZones() noexcept;
* Assign window to the zone based on direction (using WIN + LEFT/RIGHT/UP/DOWN arrow), based on void ClearSelectedZones() noexcept;
* their on-screen position.
* void CycleTabs(HWND window, bool reverse) noexcept;
* @param window Handle of window which should be assigned to zone.
* @param vkCode Pressed arrow key. void LogInitializationError();
* @param cycle Whether we should move window to the first zone if we reached last zone in layout.
* protected:
* @returns Boolean which is always true if cycle argument is set, otherwise indicating if there is more static LRESULT CALLBACK s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept;
* zones left in the zone layout in which window can move.
*/ private:
IFACEMETHOD_(bool, MoveWindowIntoZoneByDirectionAndPosition)(HWND window, DWORD vkCode, bool cycle) = 0; void InitializeZoneSets(const FancyZonesDataTypes::DeviceIdData& parentUniqueId) noexcept;
/** void CalculateZoneSet(OverlappingZonesAlgorithm overlappingAlgorithm) noexcept;
* Extend or shrink the window to an adjacent zone based on direction (using CTRL+WIN+ALT + LEFT/RIGHT/UP/DOWN arrow), based on void UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept;
* their on-screen position. LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept;
* ZoneIndexSet ZonesFromPoint(POINT pt) noexcept;
* @param window Handle of window which should be assigned to zone. void SetAsTopmostWindow() noexcept;
* @param vkCode Pressed arrow key.
* HMONITOR m_monitor{};
* @returns Boolean indicating whether the window was rezoned. False could be returned when there are no more FancyZonesUtils::Rect m_workAreaRect{};
* zones available in the given direction.
*/ FancyZonesDataTypes::DeviceIdData m_uniqueId;
IFACEMETHOD_(bool, ExtendWindowByDirectionAndPosition)(HWND window, DWORD vkCode) = 0; HWND m_window{}; // Hidden tool window used to represent current monitor desktop work area.
/** HWND m_windowMoveSize{};
* Save information about zone in which window was assigned, when closing the window. winrt::com_ptr<IZoneSet> m_zoneSet;
* Used once we open same window again to assign it to its previous zone. ZoneIndexSet m_initialHighlightZone;
* ZoneIndexSet m_highlightZone;
* @param window Window handle. WPARAM m_keyLast{};
*/ size_t m_keyCycle{};
IFACEMETHOD_(void, SaveWindowProcessToZoneIndex)(HWND window) = 0; std::unique_ptr<ZonesOverlay> m_zonesOverlay;
/**
* @returns Unique work area identifier. Format: <device-id>_<resolution>_<virtual-desktop-id>
*/
IFACEMETHOD_(FancyZonesDataTypes::DeviceIdData, UniqueId)() const = 0;
/**
* @returns Active zone layout for this work area.
*/
IFACEMETHOD_(IZoneSet*, ZoneSet)() const = 0;
/*
* @returns Zone index of the window
*/
IFACEMETHOD_(ZoneIndexSet, GetWindowZoneIndexes)(HWND window) const = 0;
/**
* Show a drawing of the zones in the work area.
*/
IFACEMETHOD_(void, ShowZonesOverlay)() = 0;
/**
* Hide the drawing of the zones in the work area.
*/
IFACEMETHOD_(void, HideZonesOverlay)() = 0;
/**
* Update currently active zone layout for this work area.
*/
IFACEMETHOD_(void, UpdateActiveZoneSet)() = 0;
/**
* Cycle through tabs in the zone that the window is in.
*
* @param window Handle of window which is cycled from (the current tab).
* @param reverse Whether to cycle in reverse order (to the previous tab) or to move to the next tab.
*/
IFACEMETHOD_(void, CycleTabs)(HWND window, bool reverse) = 0;
/**
* Clear the selected zones when this WorkArea loses focus.
*/
IFACEMETHOD_(void, ClearSelectedZones)() = 0;
/*
* Display the layout on the screen and then hide it.
*/
IFACEMETHOD_(void, FlashZones)() = 0;
}; };
winrt::com_ptr<IWorkArea> MakeWorkArea(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId) noexcept; inline std::shared_ptr<WorkArea> MakeWorkArea(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId) noexcept
{
auto self = std::make_shared<WorkArea>(hinstance);
if (!self->InitWorkAreaRect(monitor))
{
self->LogInitializationError();
return nullptr;
}
if (!self->Init(hinstance, uniqueId, parentUniqueId))
{
return nullptr;
}
return self;
}

View File

@@ -40,7 +40,7 @@ public:
IFACEMETHODIMP_(void) IFACEMETHODIMP_(void)
MoveWindowIntoZoneByIndex(HWND window, HWND workAreaWindow, ZoneIndex index) noexcept; MoveWindowIntoZoneByIndex(HWND window, HWND workAreaWindow, ZoneIndex index) noexcept;
IFACEMETHODIMP_(void) IFACEMETHODIMP_(void)
MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const ZoneIndexSet& indexSet, bool suppressMove = false) noexcept; MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const ZoneIndexSet& indexSet) noexcept;
IFACEMETHODIMP_(bool) IFACEMETHODIMP_(bool)
MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND workAreaWindow, DWORD vkCode, bool cycle) noexcept; MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND workAreaWindow, DWORD vkCode, bool cycle) noexcept;
IFACEMETHODIMP_(bool) IFACEMETHODIMP_(bool)
@@ -54,7 +54,7 @@ public:
IFACEMETHODIMP_(void) IFACEMETHODIMP_(void)
CycleTabs(HWND window, bool reverse) noexcept; CycleTabs(HWND window, bool reverse) noexcept;
IFACEMETHODIMP_(bool) IFACEMETHODIMP_(bool)
CalculateZones(RECT workArea, int zoneCount, int spacing) noexcept; CalculateZones(FancyZonesUtils::Rect workArea, int zoneCount, int spacing) noexcept;
IFACEMETHODIMP_(bool) IsZoneEmpty(ZoneIndex zoneIndex) const noexcept; IFACEMETHODIMP_(bool) IsZoneEmpty(ZoneIndex zoneIndex) const noexcept;
IFACEMETHODIMP_(ZoneIndexSet) GetCombinedZoneRange(const ZoneIndexSet& initialZones, const ZoneIndexSet& finalZones) const noexcept; IFACEMETHODIMP_(ZoneIndexSet) GetCombinedZoneRange(const ZoneIndexSet& initialZones, const ZoneIndexSet& finalZones) const noexcept;
@@ -188,7 +188,7 @@ ZoneSet::MoveWindowIntoZoneByIndex(HWND window, HWND workAreaWindow, ZoneIndex i
} }
IFACEMETHODIMP_(void) IFACEMETHODIMP_(void)
ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const ZoneIndexSet& zoneIds, bool suppressMove) noexcept ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const ZoneIndexSet& zoneIds) noexcept
{ {
if (m_zones.empty()) if (m_zones.empty())
{ {
@@ -239,17 +239,14 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const Zo
if (!sizeEmpty) if (!sizeEmpty)
{ {
if (!suppressMove) FancyZonesWindowUtils::SaveWindowSizeAndOrigin(window);
auto rect = FancyZonesWindowUtils::AdjustRectForSizeWindowToRect(window, size, workAreaWindow);
FancyZonesWindowUtils::SizeWindowToRect(window, rect);
if (FancyZonesSettings::settings().disableRoundCorners)
{ {
FancyZonesWindowUtils::SaveWindowSizeAndOrigin(window); FancyZonesWindowUtils::DisableRoundCorners(window);
auto rect = FancyZonesWindowUtils::AdjustRectForSizeWindowToRect(window, size, workAreaWindow);
FancyZonesWindowUtils::SizeWindowToRect(window, rect);
if (FancyZonesSettings::settings().disableRoundCorners)
{
FancyZonesWindowUtils::DisableRoundCorners(window);
}
} }
FancyZonesWindowProperties::StampZoneIndexProperty(window, indexSet); FancyZonesWindowProperties::StampZoneIndexProperty(window, indexSet);
@@ -569,7 +566,7 @@ void ZoneSet::InsertTabIntoZone(HWND window, std::optional<size_t> tabSortKeyWit
} }
IFACEMETHODIMP_(bool) IFACEMETHODIMP_(bool)
ZoneSet::CalculateZones(RECT workAreaRect, int zoneCount, int spacing) noexcept ZoneSet::CalculateZones(FancyZonesUtils::Rect workAreaRect, int zoneCount, int spacing) noexcept
{ {
Rect workArea(workAreaRect); Rect workArea(workAreaRect);
//invalid work area //invalid work area

View File

@@ -2,6 +2,7 @@
#include <FancyZonesLib/LayoutConfigurator.h> #include <FancyZonesLib/LayoutConfigurator.h>
#include "Settings.h" #include "Settings.h"
#include "util.h"
namespace FancyZonesDataTypes namespace FancyZonesDataTypes
{ {
@@ -55,9 +56,8 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
* @param workAreaWindow The m_window of a WorkArea, it's a hidden window representing the * @param workAreaWindow The m_window of a WorkArea, it's a hidden window representing the
* current monitor desktop work area. * current monitor desktop work area.
* @param indexSet The set of zone indices within zone layout. * @param indexSet The set of zone indices within zone layout.
* @param suppressMove Whether we should just update the records or move window to the zone.
*/ */
IFACEMETHOD_(void, MoveWindowIntoZoneByIndexSet)(HWND window, HWND workAreaWindow, const ZoneIndexSet& indexSet, bool suppressMove = false) = 0; IFACEMETHOD_(void, MoveWindowIntoZoneByIndexSet)(HWND window, HWND workAreaWindow, const ZoneIndexSet& indexSet) = 0;
/** /**
* Assign window to the zone based on direction (using WIN + LEFT/RIGHT arrow), based on zone index numbers, * Assign window to the zone based on direction (using WIN + LEFT/RIGHT arrow), based on zone index numbers,
* not their on-screen position. * not their on-screen position.
@@ -135,7 +135,7 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
* *
* @returns Boolean indicating if calculation was successful. * @returns Boolean indicating if calculation was successful.
*/ */
IFACEMETHOD_(bool, CalculateZones)(RECT workAreaRect, int zoneCount, int spacing) = 0; IFACEMETHOD_(bool, CalculateZones)(FancyZonesUtils::Rect workAreaRect, int zoneCount, int spacing) = 0;
/** /**
* Check if the zone with the specified index is empty. Returns true if the zone with passed zoneIndex does not exist. * Check if the zone with the specified index is empty. Returns true if the zone with passed zoneIndex does not exist.
* *

View File

@@ -23,39 +23,14 @@ namespace FancyZonesUnitTests
TEST_CLASS (WorkAreaCreationUnitTests) TEST_CLASS (WorkAreaCreationUnitTests)
{ {
FancyZonesDataTypes::DeviceIdData m_parentUniqueId;
FancyZonesDataTypes::DeviceIdData m_uniqueId; FancyZonesDataTypes::DeviceIdData m_uniqueId;
FancyZonesDataTypes::DeviceIdData m_emptyUniqueId;
HINSTANCE m_hInst{};
HMONITOR m_monitor{};
MONITORINFOEX m_monitorInfo{};
GUID m_virtualDesktopGuid{};
void testWorkArea(winrt::com_ptr<IWorkArea> workArea)
{
const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom);
Assert::IsNotNull(workArea.get());
Assert::IsTrue(m_uniqueId == workArea->UniqueId());
}
TEST_METHOD_INITIALIZE(Init) TEST_METHOD_INITIALIZE(Init)
{ {
m_hInst = (HINSTANCE)GetModuleHandleW(nullptr);
m_monitor = MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
m_monitorInfo.cbSize = sizeof(m_monitorInfo);
Assert::AreNotEqual(0, GetMonitorInfoW(m_monitor, &m_monitorInfo));
m_parentUniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
CLSIDFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}", &m_parentUniqueId.virtualDesktopId);
m_uniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488"; m_uniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_uniqueId.virtualDesktopId); auto res = CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_uniqueId.virtualDesktopId);
Assert::IsTrue(SUCCEEDED(res));
auto guid = Helpers::StringToGuid(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}");
Assert::IsTrue(guid.has_value());
m_virtualDesktopGuid = *guid;
AppZoneHistory::instance().LoadData(); AppZoneHistory::instance().LoadData();
AppliedLayouts::instance().LoadData(); AppliedLayouts::instance().LoadData();
@@ -67,124 +42,76 @@ namespace FancyZonesUnitTests
std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName()); std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName());
} }
TEST_METHOD (CreateWorkArea) TEST_METHOD (CreateWorkArea)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea({}, Mocks::Monitor(), m_uniqueId, m_emptyUniqueId);
testWorkArea(workArea); Assert::IsFalse(workArea == nullptr);
Assert::IsTrue(m_uniqueId == workArea->UniqueId());
auto* zoneSet{ workArea->ZoneSet() }; auto* zoneSet{ workArea->ZoneSet() };
Assert::IsNotNull(zoneSet); Assert::IsNotNull(zoneSet);
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid)); Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3)); Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
} }
TEST_METHOD (CreateWorkAreaNoHinst) TEST_METHOD (CreateCombinedWorkArea)
{ {
auto workArea = MakeWorkArea({}, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea({}, {}, m_uniqueId, m_emptyUniqueId);
testWorkArea(workArea); Assert::IsFalse(workArea == nullptr);
Assert::IsTrue(m_uniqueId == workArea->UniqueId());
auto* zoneSet{ workArea->ZoneSet() }; auto* zoneSet{ workArea->ZoneSet() };
Assert::IsNotNull(zoneSet); Assert::IsNotNull(zoneSet);
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid)); Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3)); Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
} }
TEST_METHOD (CreateWorkAreaNoHinstFlashZones)
{
auto workArea = MakeWorkArea({}, m_monitor, m_uniqueId, {});
testWorkArea(workArea);
auto* zoneSet{ workArea->ZoneSet() };
Assert::IsNotNull(zoneSet);
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
}
TEST_METHOD (CreateWorkAreaNoMonitor)
{
auto workArea = MakeWorkArea(m_hInst, {}, m_uniqueId, {});
testWorkArea(workArea);
}
TEST_METHOD (CreateWorkAreaNoDeviceId)
{
// Generate unique id without device id
FancyZonesDataTypes::DeviceIdData uniqueIdData;
uniqueIdData.virtualDesktopId = m_virtualDesktopGuid;
auto workArea = MakeWorkArea(m_hInst, m_monitor, uniqueIdData, {});
const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom);
const FancyZonesDataTypes::DeviceIdData expectedUniqueId{ L"FallbackDevice", m_virtualDesktopGuid };
Assert::IsNotNull(workArea.get());
Assert::IsTrue(expectedUniqueId == workArea->UniqueId());
auto* zoneSet{ workArea->ZoneSet() };
Assert::IsNotNull(zoneSet);
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
}
TEST_METHOD (CreateWorkAreaNoDesktopId)
{
// Generate unique id without virtual desktop id
FancyZonesDataTypes::DeviceIdData uniqueId;
uniqueId.deviceName = FancyZonesUtils::TrimDeviceId(m_deviceId);
auto workArea = MakeWorkArea(m_hInst, m_monitor, uniqueId, {});
const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom);
Assert::IsNotNull(workArea.get());
auto* zoneSet{ workArea->ZoneSet() };
Assert::IsNotNull(zoneSet);
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
}
TEST_METHOD (CreateWorkAreaClonedFromParent) TEST_METHOD (CreateWorkAreaClonedFromParent)
{ {
using namespace FancyZonesDataTypes; using namespace FancyZonesDataTypes;
const ZoneSetLayoutType type = ZoneSetLayoutType::PriorityGrid; FancyZonesDataTypes::DeviceIdData parentUniqueId;
const int spacing = 10; parentUniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
const int zoneCount = 5; parentUniqueId.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value();
const auto customSetGuid = Helpers::CreateGuidString();
auto parentWorkArea = MakeWorkArea(m_hInst, m_monitor, m_parentUniqueId, {}); Layout layout{
.uuid = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC58}").value(),
// newWorkArea = false - workArea won't be cloned from parent .type = ZoneSetLayoutType::Rows,
auto actualWorkArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); .showSpacing = true,
.spacing = 10,
.zoneCount = 10,
.sensitivityRadius = 20,
};
auto parentWorkArea = MakeWorkArea({}, Mocks::Monitor(), parentUniqueId, m_emptyUniqueId);
AppliedLayouts::instance().ApplyLayout(parentUniqueId, layout);
auto actualWorkArea = MakeWorkArea({}, Mocks::Monitor(), m_uniqueId, parentUniqueId);
Assert::IsNotNull(actualWorkArea->ZoneSet()); Assert::IsNotNull(actualWorkArea->ZoneSet());
Assert::IsTrue(AppliedLayouts::instance().GetAppliedLayoutMap().contains(m_uniqueId)); Assert::IsTrue(AppliedLayouts::instance().GetAppliedLayoutMap().contains(m_uniqueId));
auto currentDeviceInfo = AppliedLayouts::instance().GetAppliedLayoutMap().at(m_uniqueId); auto actualLayout = AppliedLayouts::instance().GetAppliedLayoutMap().at(m_uniqueId);
// default values
Assert::AreEqual(true, currentDeviceInfo.showSpacing); Assert::AreEqual(static_cast<int>(layout.type), static_cast<int>(actualLayout.type));
Assert::AreEqual(3, currentDeviceInfo.zoneCount); Assert::AreEqual(FancyZonesUtils::GuidToString(layout.uuid).value(), FancyZonesUtils::GuidToString(actualLayout.uuid).value());
Assert::AreEqual(16, currentDeviceInfo.spacing); Assert::AreEqual(layout.sensitivityRadius, actualLayout.sensitivityRadius);
Assert::AreEqual(static_cast<int>(ZoneSetLayoutType::PriorityGrid), static_cast<int>(currentDeviceInfo.type)); Assert::AreEqual(layout.showSpacing, actualLayout.showSpacing);
Assert::AreEqual(layout.spacing, actualLayout.spacing);
Assert::AreEqual(layout.zoneCount, actualLayout.zoneCount);
} }
}; };
TEST_CLASS (WorkAreaUnitTests) TEST_CLASS (WorkAreaUnitTests)
{ {
FancyZonesDataTypes::DeviceIdData m_uniqueId; FancyZonesDataTypes::DeviceIdData m_uniqueId;
FancyZonesDataTypes::DeviceIdData m_parentUniqueId; // default empty
HINSTANCE m_hInst{}; HINSTANCE m_hInst{};
HMONITOR m_monitor{}; HMONITOR m_monitor{};
MONITORINFO m_monitorInfo{};
TEST_METHOD_INITIALIZE(Init) TEST_METHOD_INITIALIZE(Init)
{ {
m_hInst = (HINSTANCE)GetModuleHandleW(nullptr);
m_monitor = MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
m_monitorInfo.cbSize = sizeof(m_monitorInfo);
Assert::AreNotEqual(0, GetMonitorInfoW(m_monitor, &m_monitorInfo));
m_uniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488"; m_uniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_uniqueId.virtualDesktopId); CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_uniqueId.virtualDesktopId);
@@ -198,10 +125,10 @@ namespace FancyZonesUnitTests
std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName()); std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName());
} }
public: public:
TEST_METHOD (MoveSizeEnter) TEST_METHOD (MoveSizeEnter)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
const auto expected = S_OK; const auto expected = S_OK;
const auto actual = workArea->MoveSizeEnter(Mocks::Window()); const auto actual = workArea->MoveSizeEnter(Mocks::Window());
@@ -211,7 +138,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveSizeEnterTwice) TEST_METHOD (MoveSizeEnterTwice)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
const auto expected = S_OK; const auto expected = S_OK;
@@ -223,7 +150,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveSizeUpdate) TEST_METHOD (MoveSizeUpdate)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
const auto expected = S_OK; const auto expected = S_OK;
const auto actual = workArea->MoveSizeUpdate(POINT{ 0, 0 }, true, false); const auto actual = workArea->MoveSizeUpdate(POINT{ 0, 0 }, true, false);
@@ -233,7 +160,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveSizeUpdatePointNegativeCoordinates) TEST_METHOD (MoveSizeUpdatePointNegativeCoordinates)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
const auto expected = S_OK; const auto expected = S_OK;
const auto actual = workArea->MoveSizeUpdate(POINT{ -10, -10 }, true, false); const auto actual = workArea->MoveSizeUpdate(POINT{ -10, -10 }, true, false);
@@ -243,17 +170,17 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveSizeUpdatePointBigCoordinates) TEST_METHOD (MoveSizeUpdatePointBigCoordinates)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
const auto expected = S_OK; const auto expected = S_OK;
const auto actual = workArea->MoveSizeUpdate(POINT{ m_monitorInfo.rcMonitor.right + 1, m_monitorInfo.rcMonitor.bottom + 1 }, true, false); const auto actual = workArea->MoveSizeUpdate(POINT{ LONG_MAX, LONG_MAX }, true, false);
Assert::AreEqual(expected, actual); Assert::AreEqual(expected, actual);
} }
TEST_METHOD (MoveSizeEnd) TEST_METHOD (MoveSizeEnd)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
const auto window = Mocks::Window(); const auto window = Mocks::Window();
workArea->MoveSizeEnter(window); workArea->MoveSizeEnter(window);
@@ -270,7 +197,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveSizeEndWindowNotAdded) TEST_METHOD (MoveSizeEndWindowNotAdded)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
const auto window = Mocks::Window(); const auto window = Mocks::Window();
workArea->MoveSizeEnter(window); workArea->MoveSizeEnter(window);
@@ -286,7 +213,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveSizeEndDifferentWindows) TEST_METHOD (MoveSizeEndDifferentWindows)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
const auto window = Mocks::Window(); const auto window = Mocks::Window();
workArea->MoveSizeEnter(window); workArea->MoveSizeEnter(window);
@@ -299,7 +226,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveSizeEndWindowNotSet) TEST_METHOD (MoveSizeEndWindowNotSet)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
const auto expected = E_INVALIDARG; const auto expected = E_INVALIDARG;
const auto actual = workArea->MoveSizeEnd(Mocks::Window(), POINT{ 0, 0 }); const auto actual = workArea->MoveSizeEnd(Mocks::Window(), POINT{ 0, 0 });
@@ -309,7 +236,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveSizeEndInvalidPoint) TEST_METHOD (MoveSizeEndInvalidPoint)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
const auto window = Mocks::Window(); const auto window = Mocks::Window();
workArea->MoveSizeEnter(window); workArea->MoveSizeEnter(window);
@@ -326,7 +253,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByIndex) TEST_METHOD (MoveWindowIntoZoneByIndex)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
Assert::IsNotNull(workArea->ZoneSet()); Assert::IsNotNull(workArea->ZoneSet());
workArea->MoveWindowIntoZoneByIndex(Mocks::Window(), 0); workArea->MoveWindowIntoZoneByIndex(Mocks::Window(), 0);
@@ -336,7 +263,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByDirectionAndIndex) TEST_METHOD (MoveWindowIntoZoneByDirectionAndIndex)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
Assert::IsNotNull(workArea->ZoneSet()); Assert::IsNotNull(workArea->ZoneSet());
const auto window = Mocks::WindowCreate(m_hInst); const auto window = Mocks::WindowCreate(m_hInst);
@@ -351,7 +278,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByDirectionManyTimes) TEST_METHOD (MoveWindowIntoZoneByDirectionManyTimes)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
Assert::IsNotNull(workArea->ZoneSet()); Assert::IsNotNull(workArea->ZoneSet());
const auto window = Mocks::WindowCreate(m_hInst); const auto window = Mocks::WindowCreate(m_hInst);
@@ -368,7 +295,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (SaveWindowProcessToZoneIndexNullptrWindow) TEST_METHOD (SaveWindowProcessToZoneIndexNullptrWindow)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
Assert::IsNotNull(workArea->ZoneSet()); Assert::IsNotNull(workArea->ZoneSet());
workArea->SaveWindowProcessToZoneIndex(nullptr); workArea->SaveWindowProcessToZoneIndex(nullptr);
@@ -379,7 +306,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (SaveWindowProcessToZoneIndexNoWindowAdded) TEST_METHOD (SaveWindowProcessToZoneIndexNoWindowAdded)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
Assert::IsNotNull(workArea->ZoneSet()); Assert::IsNotNull(workArea->ZoneSet());
auto window = Mocks::WindowCreate(m_hInst); auto window = Mocks::WindowCreate(m_hInst);
@@ -393,7 +320,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (SaveWindowProcessToZoneIndexNoWindowAddedWithFilledAppZoneHistory) TEST_METHOD (SaveWindowProcessToZoneIndexNoWindowAddedWithFilledAppZoneHistory)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
Assert::IsNotNull(workArea->ZoneSet()); Assert::IsNotNull(workArea->ZoneSet());
const auto window = Mocks::WindowCreate(m_hInst); const auto window = Mocks::WindowCreate(m_hInst);
@@ -420,7 +347,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (SaveWindowProcessToZoneIndexWindowAdded) TEST_METHOD (SaveWindowProcessToZoneIndexWindowAdded)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
Assert::IsNotNull(workArea->ZoneSet()); Assert::IsNotNull(workArea->ZoneSet());
auto window = Mocks::WindowCreate(m_hInst); auto window = Mocks::WindowCreate(m_hInst);
@@ -449,7 +376,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (WhenWindowIsNotResizablePlacingItIntoTheZoneShouldNotResizeIt) TEST_METHOD (WhenWindowIsNotResizablePlacingItIntoTheZoneShouldNotResizeIt)
{ {
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}); auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, m_parentUniqueId);
Assert::IsNotNull(workArea->ZoneSet()); Assert::IsNotNull(workArea->ZoneSet());
auto window = Mocks::WindowCreate(m_hInst); auto window = Mocks::WindowCreate(m_hInst);

View File

@@ -36,6 +36,7 @@ namespace PowerLauncher
private Timer _firstDeleteTimer = new Timer(); private Timer _firstDeleteTimer = new Timer();
private bool _coldStateHotkeyPressed; private bool _coldStateHotkeyPressed;
private bool _disposedValue; private bool _disposedValue;
private IDisposable _reactiveSubscription;
public MainWindow(PowerToysRunSettings settings, MainViewModel mainVM) public MainWindow(PowerToysRunSettings settings, MainViewModel mainVM)
: this() : this()
@@ -161,13 +162,18 @@ namespace PowerLauncher
SearchBox.QueryTextBox.DataContext = _viewModel; SearchBox.QueryTextBox.DataContext = _viewModel;
SearchBox.QueryTextBox.PreviewKeyDown += Launcher_KeyDown; SearchBox.QueryTextBox.PreviewKeyDown += Launcher_KeyDown;
Observable.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>( SetupSearchTextBoxReactiveness(_viewModel.GetSearchQueryResultsWithDelaySetting(), _viewModel.GetSearchInputDelaySetting());
add => SearchBox.QueryTextBox.TextChanged += add, _viewModel.RegisterSettingsChangeListener(
remove => SearchBox.QueryTextBox.TextChanged -= remove) (s, prop_e) =>
.Do(@event => ClearAutoCompleteText((TextBox)@event.Sender)) {
.Throttle(TimeSpan.FromMilliseconds(150)) if (prop_e.PropertyName == nameof(PowerToysRunSettings.SearchQueryResultsWithDelay) || prop_e.PropertyName == nameof(PowerToysRunSettings.SearchInputDelay))
.Do(@event => Dispatcher.InvokeAsync(() => PerformSearchQuery((TextBox)@event.Sender))) {
.Subscribe(); Application.Current.Dispatcher.Invoke(() =>
{
SetupSearchTextBoxReactiveness(_viewModel.GetSearchQueryResultsWithDelaySetting(), _viewModel.GetSearchInputDelaySetting());
});
}
});
// Set initial language flow direction // Set initial language flow direction
SearchBox_UpdateFlowDirection(); SearchBox_UpdateFlowDirection();
@@ -188,6 +194,32 @@ namespace PowerLauncher
BringProcessToForeground(); BringProcessToForeground();
} }
private void SetupSearchTextBoxReactiveness(bool showResultsWithDelay, int searchInputDelayMs)
{
if (_reactiveSubscription != null)
{
_reactiveSubscription.Dispose();
_reactiveSubscription = null;
}
SearchBox.QueryTextBox.TextChanged -= QueryTextBox_TextChanged;
if (showResultsWithDelay)
{
_reactiveSubscription = Observable.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
add => SearchBox.QueryTextBox.TextChanged += add,
remove => SearchBox.QueryTextBox.TextChanged -= remove)
.Do(@event => ClearAutoCompleteText((TextBox)@event.Sender))
.Throttle(TimeSpan.FromMilliseconds(searchInputDelayMs))
.Do(@event => Dispatcher.InvokeAsync(() => PerformSearchQuery((TextBox)@event.Sender)))
.Subscribe();
}
else
{
SearchBox.QueryTextBox.TextChanged += QueryTextBox_TextChanged;
}
}
private void SuggestionsList_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) private void SuggestionsList_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{ {
var result = ((FrameworkElement)e.OriginalSource).DataContext; var result = ((FrameworkElement)e.OriginalSource).DataContext;
@@ -430,6 +462,13 @@ namespace PowerLauncher
} }
} }
private void QueryTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var textBox = (TextBox)sender;
ClearAutoCompleteText(textBox);
PerformSearchQuery(textBox);
}
private void ClearAutoCompleteText(TextBox textBox) private void ClearAutoCompleteText(TextBox textBox)
{ {
var text = textBox.Text; var text = textBox.Text;

View File

@@ -105,6 +105,16 @@ namespace PowerLauncher
_settings.UseCentralizedKeyboardHook = overloadSettings.Properties.UseCentralizedKeyboardHook; _settings.UseCentralizedKeyboardHook = overloadSettings.Properties.UseCentralizedKeyboardHook;
} }
if (_settings.SearchQueryResultsWithDelay != overloadSettings.Properties.SearchQueryResultsWithDelay)
{
_settings.SearchQueryResultsWithDelay = overloadSettings.Properties.SearchQueryResultsWithDelay;
}
if (_settings.SearchInputDelay != overloadSettings.Properties.SearchInputDelay)
{
_settings.SearchInputDelay = overloadSettings.Properties.SearchInputDelay;
}
if (_settings.MaxResultsToShow != overloadSettings.Properties.MaximumNumberOfResults) if (_settings.MaxResultsToShow != overloadSettings.Properties.MaximumNumberOfResults)
{ {
_settings.MaxResultsToShow = overloadSettings.Properties.MaximumNumberOfResults; _settings.MaxResultsToShow = overloadSettings.Properties.MaximumNumberOfResults;

View File

@@ -132,6 +132,11 @@ namespace PowerLauncher.ViewModel
// SetCustomPluginHotkey(); // SetCustomPluginHotkey();
} }
public void RegisterSettingsChangeListener(System.ComponentModel.PropertyChangedEventHandler handler)
{
_settings.PropertyChanged += handler;
}
private void RegisterResultsUpdatedEvent() private void RegisterResultsUpdatedEvent()
{ {
foreach (var pair in PluginManager.GetPluginsForInterface<IResultUpdated>()) foreach (var pair in PluginManager.GetPluginsForInterface<IResultUpdated>())
@@ -1104,5 +1109,15 @@ namespace PowerLauncher.ViewModel
_hotkeyTimer.Reset(); _hotkeyTimer.Reset();
return recordedTime; return recordedTime;
} }
public bool GetSearchQueryResultsWithDelaySetting()
{
return _settings.SearchQueryResultsWithDelay;
}
public int GetSearchInputDelaySetting()
{
return _settings.SearchInputDelay;
}
} }
} }

View File

@@ -152,7 +152,7 @@ namespace Wox.Infrastructure
{ {
if (string.IsNullOrEmpty(pattern)) if (string.IsNullOrEmpty(pattern))
{ {
Log.Warn("Trying to run OpenCommandInShell with an empty pattern. The default browser definition might have issues.", typeof(Helper)); Log.Warn($"Trying to run OpenCommandInShell with an empty pattern. The default browser definition might have issues. Path: '${path ?? string.Empty}' ; Arguments: '${arguments ?? string.Empty}' ; Working Directory: '${workingDir ?? string.Empty}'", typeof(Helper));
} }
else if (pattern.Contains("%1", StringComparison.Ordinal)) else if (pattern.Contains("%1", StringComparison.Ordinal))
{ {

View File

@@ -61,6 +61,44 @@ namespace Wox.Infrastructure.UserSettings
} }
} }
private bool _searchQueryResultsWithDelay = true;
public bool SearchQueryResultsWithDelay
{
get
{
return _searchQueryResultsWithDelay;
}
set
{
if (_searchQueryResultsWithDelay != value)
{
_searchQueryResultsWithDelay = value;
OnPropertyChanged(nameof(SearchQueryResultsWithDelay));
}
}
}
private int _searchInputDelay = 150;
public int SearchInputDelay
{
get
{
return _searchInputDelay;
}
set
{
if (_searchInputDelay != value)
{
_searchInputDelay = value;
OnPropertyChanged(nameof(SearchInputDelay));
}
}
}
public string Language { get; set; } = "en"; public string Language { get; set; } = "en";
public Theme Theme { get; set; } = Theme.System; public Theme Theme { get; set; } = Theme.System;

View File

@@ -15,7 +15,6 @@ namespace Wox.Plugin.Common
public static class DefaultBrowserInfo public static class DefaultBrowserInfo
{ {
private static readonly object _updateLock = new object(); private static readonly object _updateLock = new object();
private static int _lastUpdateTickCount = -1;
/// <summary>Gets the path to the MS Edge browser executable.</summary> /// <summary>Gets the path to the MS Edge browser executable.</summary>
public static string MSEdgePath => public static string MSEdgePath =>
@@ -41,7 +40,11 @@ namespace Wox.Plugin.Common
public static bool IsDefaultBrowserSet { get => !string.IsNullOrEmpty(Path); } public static bool IsDefaultBrowserSet { get => !string.IsNullOrEmpty(Path); }
public const int UpdateTimeout = 300; public const long UpdateTimeout = 300;
private static long _lastUpdateTickCount = -UpdateTimeout;
private static bool haveIRanUpdateOnce;
/// <summary> /// <summary>
/// Updates only if at least more than 300ms has passed since the last update, to avoid multiple calls to <see cref="Update"/>. /// Updates only if at least more than 300ms has passed since the last update, to avoid multiple calls to <see cref="Update"/>.
@@ -49,8 +52,8 @@ namespace Wox.Plugin.Common
/// </summary> /// </summary>
public static void UpdateIfTimePassed() public static void UpdateIfTimePassed()
{ {
int curTickCount = Environment.TickCount; long curTickCount = Environment.TickCount64;
if (curTickCount - _lastUpdateTickCount > UpdateTimeout) if (curTickCount - _lastUpdateTickCount >= UpdateTimeout)
{ {
_lastUpdateTickCount = curTickCount; _lastUpdateTickCount = curTickCount;
Update(); Update();
@@ -66,6 +69,12 @@ namespace Wox.Plugin.Common
{ {
lock (_updateLock) lock (_updateLock)
{ {
if (!haveIRanUpdateOnce)
{
Log.Warn("I've tried updating the chosen Web Browser info at least once.", typeof(DefaultBrowserInfo));
haveIRanUpdateOnce = true;
}
try try
{ {
string progId = GetRegistryValue( string progId = GetRegistryValue(

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.0\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.0\build\native\Microsoft.WindowsAppSDK.props')" /> <Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.1\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.1\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" /> <Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22000.197\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22000.197\build\Microsoft.Windows.SDK.BuildTools.props')" /> <Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22000.197\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22000.197\build\Microsoft.Windows.SDK.BuildTools.props')" />
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
@@ -175,7 +175,7 @@
<Import Project="..\..\..\..\packages\boost.1.79.0\build\boost.targets" Condition="Exists('..\..\..\..\packages\boost.1.79.0\build\boost.targets')" /> <Import Project="..\..\..\..\packages\boost.1.79.0\build\boost.targets" Condition="Exists('..\..\..\..\packages\boost.1.79.0\build\boost.targets')" />
<Import Project="..\..\..\..\packages\boost_regex-vc143.1.79.0\build\boost_regex-vc143.targets" Condition="Exists('..\..\..\..\packages\boost_regex-vc143.1.79.0\build\boost_regex-vc143.targets')" /> <Import Project="..\..\..\..\packages\boost_regex-vc143.1.79.0\build\boost_regex-vc143.targets" Condition="Exists('..\..\..\..\packages\boost_regex-vc143.1.79.0\build\boost_regex-vc143.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets')" /> <Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.0\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.0\build\native\Microsoft.WindowsAppSDK.targets')" /> <Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.1\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.1\build\native\Microsoft.WindowsAppSDK.targets')" />
</ImportGroup> </ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
@@ -188,8 +188,8 @@
<Error Condition="!Exists('..\..\..\..\packages\boost_regex-vc143.1.79.0\build\boost_regex-vc143.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost_regex-vc143.1.79.0\build\boost_regex-vc143.targets'))" /> <Error Condition="!Exists('..\..\..\..\packages\boost_regex-vc143.1.79.0\build\boost_regex-vc143.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost_regex-vc143.1.79.0\build\boost_regex-vc143.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props'))" /> <Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets'))" /> <Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.0\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.0\build\native\Microsoft.WindowsAppSDK.props'))" /> <Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.1\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.1\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.0\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.0\build\native\Microsoft.WindowsAppSDK.targets'))" /> <Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.1\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.1.1\build\native\Microsoft.WindowsAppSDK.targets'))" />
</Target> </Target>
<Target Name="AddWildCardItems" AfterTargets="BuildGenerateSources"> <Target Name="AddWildCardItems" AfterTargets="BuildGenerateSources">
<ItemGroup> <ItemGroup>

View File

@@ -5,5 +5,5 @@
<package id="Microsoft.Windows.CppWinRT" version="2.0.220418.1" targetFramework="native" /> <package id="Microsoft.Windows.CppWinRT" version="2.0.220418.1" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220201.1" targetFramework="native" /> <package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220201.1" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.22000.197" targetFramework="native" /> <package id="Microsoft.Windows.SDK.BuildTools" version="10.0.22000.197" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.1.0" targetFramework="native" /> <package id="Microsoft.WindowsAppSDK" version="1.1.1" targetFramework="native" />
</packages> </packages>

View File

@@ -51,6 +51,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("use_centralized_keyboard_hook")] [JsonPropertyName("use_centralized_keyboard_hook")]
public bool UseCentralizedKeyboardHook { get; set; } public bool UseCentralizedKeyboardHook { get; set; }
[JsonPropertyName("search_query_results_with_delay")]
public bool SearchQueryResultsWithDelay { get; set; }
[JsonPropertyName("search_input_delay")]
public int SearchInputDelay { get; set; }
public PowerLauncherProperties() public PowerLauncherProperties()
{ {
OpenPowerLauncher = new HotkeySettings(false, false, true, false, 32); OpenPowerLauncher = new HotkeySettings(false, false, true, false, 32);
@@ -65,6 +71,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library
Theme = Theme.System; Theme = Theme.System;
Position = StartupPosition.Cursor; Position = StartupPosition.Cursor;
UseCentralizedKeyboardHook = false; UseCentralizedKeyboardHook = false;
SearchQueryResultsWithDelay = true;
SearchInputDelay = 150;
} }
} }
} }

View File

@@ -296,6 +296,40 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
} }
} }
public bool SearchQueryResultsWithDelay
{
get
{
return settings.Properties.SearchQueryResultsWithDelay;
}
set
{
if (settings.Properties.SearchQueryResultsWithDelay != value)
{
settings.Properties.SearchQueryResultsWithDelay = value;
UpdateSettings();
}
}
}
public int SearchInputDelay
{
get
{
return settings.Properties.SearchInputDelay;
}
set
{
if (settings.Properties.SearchInputDelay != value)
{
settings.Properties.SearchInputDelay = value;
UpdateSettings();
}
}
}
public HotkeySettings OpenFileLocation public HotkeySettings OpenFileLocation
{ {
get get

View File

@@ -41,7 +41,6 @@ namespace Microsoft.PowerToys.Settings.UI
_appWindow.SetIcon("icon.ico"); _appWindow.SetIcon("icon.ico");
OverlappedPresenter presenter = _appWindow.Presenter as OverlappedPresenter; OverlappedPresenter presenter = _appWindow.Presenter as OverlappedPresenter;
presenter.IsResizable = false;
presenter.IsMinimizable = false; presenter.IsMinimizable = false;
presenter.IsMaximizable = false; presenter.IsMaximizable = false;

View File

@@ -57,7 +57,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="CommunityToolkit.WinUI.UI" Version="7.1.2" /> <PackageReference Include="CommunityToolkit.WinUI.UI" Version="7.1.2" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls" Version="7.1.2" /> <PackageReference Include="CommunityToolkit.WinUI.UI.Controls" Version="7.1.2" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.1.0" /> <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.1.1" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22000.194" /> <PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22000.194" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.8" /> <PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.8" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="6.0.0"> <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="6.0.0">

View File

@@ -414,6 +414,17 @@
<data name="PowerLauncher_ClearInputOnLaunch.Content" xml:space="preserve"> <data name="PowerLauncher_ClearInputOnLaunch.Content" xml:space="preserve">
<value>Clear the previous query on launch</value> <value>Clear the previous query on launch</value>
</data> </data>
<data name="PowerLauncher_SearchQueryResultsWithDelay.Header" xml:space="preserve">
<value>Delay search</value>
<comment>This is about adding a delay to wait for more input before executing a search</comment>
</data>
<data name="PowerLauncher_SearchQueryResultsWithDelay.Description" xml:space="preserve">
<value>Add a delay to wait for more input before executing a search</value>
</data>
<data name="PowerLauncher_SearchInputDelayMs.Header" xml:space="preserve">
<value>Search delay (ms)</value>
<comment>ms = milliseconds</comment>
</data>
<data name="KeyboardManager_KeysMappingLayoutRightHeader.Text" xml:space="preserve"> <data name="KeyboardManager_KeysMappingLayoutRightHeader.Text" xml:space="preserve">
<value>To:</value> <value>To:</value>
<comment>Keyboard Manager mapping keys view right header</comment> <comment>Keyboard Manager mapping keys view right header</comment>

View File

@@ -94,6 +94,29 @@
<controls:SettingsGroup x:Uid="PowerLauncher_SearchResults" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}"> <controls:SettingsGroup x:Uid="PowerLauncher_SearchResults" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="PowerLauncher_SearchQueryResultsWithDelay" Icon="&#xF182;" Style="{StaticResource ExpanderHeaderSettingStyle}" >
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.SearchQueryResultsWithDelay}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<controls:Setting x:Uid="PowerLauncher_SearchInputDelayMs" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.SearchQueryResultsWithDelay}" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<muxc:NumberBox Minimum="0"
Maximum="1000"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.SearchInputDelay}"
MinWidth="{StaticResource SettingActionControlMinWidth}"
SpinButtonPlacementMode="Compact"
HorizontalAlignment="Left"
SmallChange="10"
LargeChange="50"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Content>
</controls:SettingExpander>
<controls:SettingExpander IsExpanded="True"> <controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header> <controls:SettingExpander.Header>
<controls:Setting x:Uid="PowerLauncher_MaximumNumberOfResults" Icon="&#xE721;" Style="{StaticResource ExpanderHeaderSettingStyle}"> <controls:Setting x:Uid="PowerLauncher_MaximumNumberOfResults" Icon="&#xE721;" Style="{StaticResource ExpanderHeaderSettingStyle}">