mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-28 07:39:49 +08:00
Add keyboard shortcuts (without GUI) for switching windows in the same zone (tabs) (#13973)
Authored-by: float4 <float4-unspecified-mail>
This commit is contained in:
parent
cd5c22aaa1
commit
9d9df949ef
@ -147,7 +147,8 @@ protected:
|
||||
|
||||
private:
|
||||
void UpdateZoneWindows() noexcept;
|
||||
void UpdateWindowsPositions() noexcept;
|
||||
void UpdateWindowsPositions(bool suppressMove = false) noexcept;
|
||||
void CycleTabs(bool reverse) noexcept;
|
||||
bool OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept;
|
||||
bool OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept;
|
||||
bool OnSnapHotkey(DWORD vkCode) noexcept;
|
||||
@ -155,6 +156,7 @@ private:
|
||||
|
||||
void RegisterVirtualDesktopUpdates() noexcept;
|
||||
|
||||
void UpdateHotkey(int hotkeyId, const PowerToysSettings::HotkeyObject& hotkeyObject, bool enable) noexcept;
|
||||
void OnSettingsChanged() noexcept;
|
||||
|
||||
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept;
|
||||
@ -201,6 +203,14 @@ private:
|
||||
Exit,
|
||||
Terminate
|
||||
};
|
||||
|
||||
// IDs used to register hot keys (keyboard shortcuts).
|
||||
enum class HotkeyId : int
|
||||
{
|
||||
Editor = 1,
|
||||
NextTab = 2,
|
||||
PrevTab = 3,
|
||||
};
|
||||
};
|
||||
|
||||
std::function<void()> FancyZones::disableModuleCallback = {};
|
||||
@ -224,7 +234,12 @@ FancyZones::Run() noexcept
|
||||
return;
|
||||
}
|
||||
|
||||
RegisterHotKey(m_window, 1, m_settings->GetSettings()->editorHotkey.get_modifiers(), m_settings->GetSettings()->editorHotkey.get_code());
|
||||
RegisterHotKey(m_window, static_cast<int>(HotkeyId::Editor), m_settings->GetSettings()->editorHotkey.get_modifiers(), m_settings->GetSettings()->editorHotkey.get_code());
|
||||
if (m_settings->GetSettings()->windowSwitching)
|
||||
{
|
||||
RegisterHotKey(m_window, static_cast<int>(HotkeyId::NextTab), m_settings->GetSettings()->nextTabHotkey.get_modifiers(), m_settings->GetSettings()->nextTabHotkey.get_code());
|
||||
RegisterHotKey(m_window, static_cast<int>(HotkeyId::PrevTab), m_settings->GetSettings()->prevTabHotkey.get_modifiers(), m_settings->GetSettings()->prevTabHotkey.get_code());
|
||||
}
|
||||
|
||||
m_virtualDesktop.Init();
|
||||
|
||||
@ -639,10 +654,15 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
||||
{
|
||||
case WM_HOTKEY:
|
||||
{
|
||||
if (wparam == 1)
|
||||
if (wparam == static_cast<WPARAM>(HotkeyId::Editor))
|
||||
{
|
||||
ToggleEditor();
|
||||
}
|
||||
else if (wparam == static_cast<WPARAM>(HotkeyId::NextTab) || wparam == static_cast<WPARAM>(HotkeyId::PrevTab))
|
||||
{
|
||||
bool reverse = wparam == static_cast<WPARAM>(HotkeyId::PrevTab);
|
||||
CycleTabs(reverse);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -787,6 +807,7 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
||||
|
||||
UpdateZoneWindows();
|
||||
|
||||
|
||||
if ((changeType == DisplayChangeType::WorkArea) || (changeType == DisplayChangeType::DisplayChange))
|
||||
{
|
||||
if (m_settings->GetSettings()->displayChange_moveWindows)
|
||||
@ -897,7 +918,7 @@ void FancyZones::UpdateZoneWindows() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZones::UpdateWindowsPositions() noexcept
|
||||
void FancyZones::UpdateWindowsPositions(bool suppressMove) noexcept
|
||||
{
|
||||
for (const auto [window, desktopId] : m_virtualDesktop.GetWindowsRelatedToDesktops())
|
||||
{
|
||||
@ -905,11 +926,23 @@ void FancyZones::UpdateWindowsPositions() noexcept
|
||||
auto zoneWindow = m_workAreaHandler.GetWorkArea(window, desktopId);
|
||||
if (zoneWindow)
|
||||
{
|
||||
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, zoneWindow);
|
||||
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, zoneWindow, suppressMove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZones::CycleTabs(bool reverse) noexcept
|
||||
{
|
||||
auto window = GetForegroundWindow();
|
||||
HMONITOR current = WorkAreaKeyFromWindow(window);
|
||||
|
||||
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, current);
|
||||
if (workArea)
|
||||
{
|
||||
workArea->CycleTabs(window, reverse);
|
||||
}
|
||||
}
|
||||
|
||||
bool FancyZones::OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept
|
||||
{
|
||||
_TRACER_;
|
||||
@ -1135,21 +1168,36 @@ void FancyZones::RegisterVirtualDesktopUpdates() noexcept
|
||||
FancyZonesDataInstance().SyncVirtualDesktops(m_currentDesktopId);
|
||||
}
|
||||
|
||||
void FancyZones::OnSettingsChanged() noexcept
|
||||
void FancyZones::UpdateHotkey(int hotkeyId, const PowerToysSettings::HotkeyObject& hotkeyObject, bool enable) noexcept
|
||||
{
|
||||
_TRACER_;
|
||||
m_settings->ReloadSettings();
|
||||
UnregisterHotKey(m_window, hotkeyId);
|
||||
|
||||
// Update the hotkey
|
||||
UnregisterHotKey(m_window, 1);
|
||||
auto modifiers = m_settings->GetSettings()->editorHotkey.get_modifiers();
|
||||
auto code = m_settings->GetSettings()->editorHotkey.get_code();
|
||||
auto result = RegisterHotKey(m_window, 1, modifiers, code);
|
||||
if (!enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto modifiers = hotkeyObject.get_modifiers();
|
||||
auto code = hotkeyObject.get_code();
|
||||
auto result = RegisterHotKey(m_window, hotkeyId, modifiers, code);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Logger::error(L"Failed to register hotkey: {}", get_last_error_or_default(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZones::OnSettingsChanged() noexcept
|
||||
{
|
||||
_TRACER_;
|
||||
m_settings->ReloadSettings();
|
||||
|
||||
// Update the hotkeys
|
||||
UpdateHotkey(static_cast<int>(HotkeyId::Editor), m_settings->GetSettings()->editorHotkey, true);
|
||||
|
||||
auto windowSwitching = m_settings->GetSettings()->windowSwitching;
|
||||
UpdateHotkey(static_cast<int>(HotkeyId::NextTab), m_settings->GetSettings()->nextTabHotkey, windowSwitching);
|
||||
UpdateHotkey(static_cast<int>(HotkeyId::PrevTab), m_settings->GetSettings()->prevTabHotkey, windowSwitching);
|
||||
|
||||
// Needed if we toggled spanZonesAcrossMonitors
|
||||
m_workAreaHandler.Clear();
|
||||
@ -1177,10 +1225,9 @@ void FancyZones::UpdateZoneSets() noexcept
|
||||
{
|
||||
workArea->UpdateActiveZoneSet();
|
||||
}
|
||||
if (m_settings->GetSettings()->zoneSetChange_moveWindows)
|
||||
{
|
||||
UpdateWindowsPositions();
|
||||
}
|
||||
|
||||
auto moveWindows = m_settings->GetSettings()->zoneSetChange_moveWindows;
|
||||
UpdateWindowsPositions(!moveWindows);
|
||||
}
|
||||
|
||||
bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
#include <FancyZonesLib/Zone.h>
|
||||
|
||||
@ -8,6 +9,7 @@
|
||||
namespace ZonedWindowProperties
|
||||
{
|
||||
const wchar_t PropertyMultipleZoneID[] = L"FancyZones_zones";
|
||||
const wchar_t PropertySortKeyWithinZone[] = L"FancyZones_TabSortKeyWithinZone";
|
||||
const wchar_t PropertyRestoreSizeID[] = L"FancyZones_RestoreSize";
|
||||
const wchar_t PropertyRestoreOriginID[] = L"FancyZones_RestoreOrigin";
|
||||
|
||||
@ -44,3 +46,28 @@ inline void StampWindow(HWND window, Bitmask bitmask) noexcept
|
||||
memcpy(&rawData, data.data(), sizeof data);
|
||||
SetProp(window, ZonedWindowProperties::PropertyMultipleZoneID, rawData);
|
||||
}
|
||||
|
||||
inline std::optional<size_t> GetTabSortKeyWithinZone(HWND window)
|
||||
{
|
||||
auto rawTabSortKeyWithinZone = ::GetPropW(window, ZonedWindowProperties::PropertySortKeyWithinZone);
|
||||
if (rawTabSortKeyWithinZone == NULL)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto tabSortKeyWithinZone = reinterpret_cast<uint64_t>(rawTabSortKeyWithinZone) - 1;
|
||||
return tabSortKeyWithinZone;
|
||||
}
|
||||
|
||||
inline void SetTabSortKeyWithinZone(HWND window, std::optional<size_t> tabSortKeyWithinZone)
|
||||
{
|
||||
if (!tabSortKeyWithinZone.has_value())
|
||||
{
|
||||
::RemovePropW(window, ZonedWindowProperties::PropertySortKeyWithinZone);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto rawTabSortKeyWithinZone = reinterpret_cast<HANDLE>(tabSortKeyWithinZone.value() + 1);
|
||||
::SetPropW(window, ZonedWindowProperties::PropertySortKeyWithinZone, rawTabSortKeyWithinZone);
|
||||
}
|
||||
}
|
@ -196,6 +196,15 @@
|
||||
<data name="Setting_Launch_Editor_Hotkey_Label" xml:space="preserve">
|
||||
<value>Configure the zone editor hotkey</value>
|
||||
</data>
|
||||
<data name="Setting_Window_Switching_Toggle_Label" xml:space="preserve">
|
||||
<value>Toggle shortcuts for switching between windows in the current zone</value>
|
||||
</data>
|
||||
<data name="Setting_Next_Tab_Hotkey_Label" xml:space="preserve">
|
||||
<value>Shortcut for switching to the next window in the current zone</value>
|
||||
</data>
|
||||
<data name="Setting_Prev_Tab_Hotkey_Label" xml:space="preserve">
|
||||
<value>Shortcut for switching to the previous window in the current zone</value>
|
||||
</data>
|
||||
<data name="Setting_Excluded_Apps_Description" xml:space="preserve">
|
||||
<value>To exclude an application from snapping to zones add its name here (one per line). Excluded apps will react to the Windows Snap regardless of all other settings.</value>
|
||||
<comment>Windows refers to the Operating system</comment>
|
||||
|
@ -32,6 +32,9 @@ namespace NonLocalizable
|
||||
const wchar_t ZoneBorderColorID[] = L"fancyzones_zoneBorderColor";
|
||||
const wchar_t ZoneHighlightColorID[] = L"fancyzones_zoneHighlightColor";
|
||||
const wchar_t EditorHotkeyID[] = L"fancyzones_editor_hotkey";
|
||||
const wchar_t WindowSwitchingToggleID[] = L"fancyzones_windowSwitching";
|
||||
const wchar_t NextTabHotkeyID[] = L"fancyzones_nextTab_hotkey";
|
||||
const wchar_t PrevTabHotkeyID[] = L"fancyzones_prevTab_hotkey";
|
||||
const wchar_t ExcludedAppsID[] = L"fancyzones_excluded_apps";
|
||||
const wchar_t ZoneHighlightOpacityID[] = L"fancyzones_highlight_opacity";
|
||||
|
||||
@ -77,7 +80,7 @@ private:
|
||||
PCWSTR name;
|
||||
bool* value;
|
||||
int resourceId;
|
||||
} m_configBools[16] = {
|
||||
} m_configBools[17] = {
|
||||
{ NonLocalizable::ShiftDragID, &m_settings.shiftDrag, IDS_SETTING_DESCRIPTION_SHIFTDRAG },
|
||||
{ NonLocalizable::MouseSwitchID, &m_settings.mouseSwitch, IDS_SETTING_DESCRIPTION_MOUSESWITCH },
|
||||
{ NonLocalizable::OverrideSnapHotKeysID, &m_settings.overrideSnapHotkeys, IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS },
|
||||
@ -94,6 +97,7 @@ private:
|
||||
{ NonLocalizable::ShowOnAllMonitorsID, &m_settings.showZonesOnAllMonitors, IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS },
|
||||
{ NonLocalizable::SpanZonesAcrossMonitorsID, &m_settings.spanZonesAcrossMonitors, IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS },
|
||||
{ NonLocalizable::MakeDraggedWindowTransparentID, &m_settings.makeDraggedWindowTransparent, IDS_SETTING_DESCRIPTION_MAKE_DRAGGED_WINDOW_TRANSPARENT },
|
||||
{ NonLocalizable::WindowSwitchingToggleID, &m_settings.windowSwitching, IDS_SETTING_WINDOW_SWITCHING_TOGGLE_LABEL },
|
||||
};
|
||||
};
|
||||
|
||||
@ -116,6 +120,8 @@ FancyZonesSettings::GetConfig(_Out_ PWSTR buffer, _Out_ int* buffer_size) noexce
|
||||
IDS_SETTING_LAUNCH_EDITOR_BUTTON,
|
||||
IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION);
|
||||
settings.add_hotkey(NonLocalizable::EditorHotkeyID, IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, m_settings.editorHotkey);
|
||||
settings.add_hotkey(NonLocalizable::NextTabHotkeyID, IDS_SETTING_NEXT_TAB_HOTKEY_LABEL, m_settings.nextTabHotkey);
|
||||
settings.add_hotkey(NonLocalizable::PrevTabHotkeyID, IDS_SETTING_PREV_TAB_HOTKEY_LABEL, m_settings.prevTabHotkey);
|
||||
|
||||
for (auto const& setting : m_configBools)
|
||||
{
|
||||
@ -182,6 +188,16 @@ void FancyZonesSettings::LoadSettings(PCWSTR config, bool fromFile) noexcept
|
||||
m_settings.editorHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
|
||||
}
|
||||
|
||||
if (const auto val = values.get_json(NonLocalizable::NextTabHotkeyID))
|
||||
{
|
||||
m_settings.nextTabHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
|
||||
}
|
||||
|
||||
if (const auto val = values.get_json(NonLocalizable::PrevTabHotkeyID))
|
||||
{
|
||||
m_settings.prevTabHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
|
||||
}
|
||||
|
||||
if (auto val = values.get_string_value(NonLocalizable::ExcludedAppsID))
|
||||
{
|
||||
m_settings.excludedApps = std::move(*val);
|
||||
@ -246,6 +262,8 @@ void FancyZonesSettings::SaveSettings() noexcept
|
||||
values.add_property(NonLocalizable::ZoneHighlightOpacityID, m_settings.zoneHighlightOpacity);
|
||||
values.add_property(NonLocalizable::OverlappingZonesAlgorithmID, (int)m_settings.overlappingZonesAlgorithm);
|
||||
values.add_property(NonLocalizable::EditorHotkeyID, m_settings.editorHotkey.get_json());
|
||||
values.add_property(NonLocalizable::NextTabHotkeyID, m_settings.nextTabHotkey.get_json());
|
||||
values.add_property(NonLocalizable::PrevTabHotkeyID, m_settings.prevTabHotkey.get_json());
|
||||
values.add_property(NonLocalizable::ExcludedAppsID, m_settings.excludedApps);
|
||||
|
||||
values.save_to_settings_file();
|
||||
|
@ -38,6 +38,9 @@ struct Settings
|
||||
int zoneHighlightOpacity = 50;
|
||||
OverlappingZonesAlgorithm overlappingZonesAlgorithm = OverlappingZonesAlgorithm::Smallest;
|
||||
PowerToysSettings::HotkeyObject editorHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, VK_OEM_3);
|
||||
bool windowSwitching = true;
|
||||
PowerToysSettings::HotkeyObject nextTabHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, false, VK_NEXT);
|
||||
PowerToysSettings::HotkeyObject prevTabHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, false, VK_PRIOR);
|
||||
std::wstring excludedApps = L"";
|
||||
std::vector<std::wstring> excludedAppsArray;
|
||||
};
|
||||
|
@ -123,6 +123,17 @@ void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto zoneWindow = zoneWindowMap.find(monitor);
|
||||
if (zoneWindow != zoneWindowMap.end())
|
||||
{
|
||||
const auto zoneWindowPtr = zoneWindow->second;
|
||||
const auto activeZoneSet = zoneWindowPtr->ActiveZoneSet();
|
||||
if (activeZoneSet)
|
||||
{
|
||||
activeZoneSet->DismissWindow(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& zoneWindowMap) noexcept
|
||||
@ -273,11 +284,11 @@ void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const st
|
||||
}
|
||||
}
|
||||
|
||||
void WindowMoveHandler::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, winrt::com_ptr<IWorkArea> zoneWindow) noexcept
|
||||
void WindowMoveHandler::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, winrt::com_ptr<IWorkArea> zoneWindow, bool suppressMove) noexcept
|
||||
{
|
||||
if (window != m_windowMoveSize)
|
||||
{
|
||||
zoneWindow->MoveWindowIntoZoneByIndexSet(window, indexSet);
|
||||
zoneWindow->MoveWindowIntoZoneByIndexSet(window, indexSet, suppressMove);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& zoneWindowMap) noexcept;
|
||||
void MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& zoneWindowMap) noexcept;
|
||||
|
||||
void MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, winrt::com_ptr<IWorkArea> zoneWindow) noexcept;
|
||||
void MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, winrt::com_ptr<IWorkArea> zoneWindow, bool suppressMove = false) noexcept;
|
||||
bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> zoneWindow) noexcept;
|
||||
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> zoneWindow) noexcept;
|
||||
bool ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IWorkArea> zoneWindow) noexcept;
|
||||
|
@ -117,7 +117,7 @@ public:
|
||||
IFACEMETHODIMP_(void)
|
||||
MoveWindowIntoZoneByIndex(HWND window, ZoneIndex index) noexcept;
|
||||
IFACEMETHODIMP_(void)
|
||||
MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet) noexcept;
|
||||
MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, bool suppressMove = false) noexcept;
|
||||
IFACEMETHODIMP_(bool)
|
||||
MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle) noexcept;
|
||||
IFACEMETHODIMP_(bool)
|
||||
@ -139,6 +139,8 @@ public:
|
||||
IFACEMETHODIMP_(void)
|
||||
UpdateActiveZoneSet() noexcept;
|
||||
IFACEMETHODIMP_(void)
|
||||
CycleTabs(HWND window, bool reverse) noexcept;
|
||||
IFACEMETHODIMP_(void)
|
||||
ClearSelectedZones() noexcept;
|
||||
IFACEMETHODIMP_(void)
|
||||
FlashZones() noexcept;
|
||||
@ -311,11 +313,11 @@ WorkArea::MoveWindowIntoZoneByIndex(HWND window, ZoneIndex index) noexcept
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(void)
|
||||
WorkArea::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet) noexcept
|
||||
WorkArea::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, bool suppressMove) noexcept
|
||||
{
|
||||
if (m_activeZoneSet)
|
||||
{
|
||||
m_activeZoneSet->MoveWindowIntoZoneByIndexSet(window, m_window, indexSet);
|
||||
m_activeZoneSet->MoveWindowIntoZoneByIndexSet(window, m_window, indexSet, suppressMove);
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,6 +433,15 @@ WorkArea::UpdateActiveZoneSet() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(void)
|
||||
WorkArea::CycleTabs(HWND window, bool reverse) noexcept
|
||||
{
|
||||
if (m_activeZoneSet)
|
||||
{
|
||||
m_activeZoneSet->CycleTabs(window, reverse);
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(void)
|
||||
WorkArea::ClearSelectedZones() noexcept
|
||||
{
|
||||
|
@ -51,8 +51,9 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IWorkArea :
|
||||
*
|
||||
* @param window Handle of window which should be assigned to zone.
|
||||
* @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, const ZoneIndexSet& indexSet) = 0;
|
||||
IFACEMETHOD_(void, MoveWindowIntoZoneByIndexSet)(HWND window, const ZoneIndexSet& indexSet, bool suppressMove = false) = 0;
|
||||
/**
|
||||
* Assign window to the zone based on direction (using WIN + LEFT/RIGHT arrow), based on zone index numbers,
|
||||
* not their on-screen position.
|
||||
@ -113,6 +114,13 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IWorkArea :
|
||||
* 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.
|
||||
*/
|
||||
|
@ -130,7 +130,7 @@ public:
|
||||
IFACEMETHODIMP_(void)
|
||||
MoveWindowIntoZoneByIndex(HWND window, HWND workAreaWindow, ZoneIndex index) noexcept;
|
||||
IFACEMETHODIMP_(void)
|
||||
MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const ZoneIndexSet& indexSet) noexcept;
|
||||
MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const ZoneIndexSet& indexSet, bool suppressMove = false) noexcept;
|
||||
IFACEMETHODIMP_(bool)
|
||||
MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND workAreaWindow, DWORD vkCode, bool cycle) noexcept;
|
||||
IFACEMETHODIMP_(bool)
|
||||
@ -139,6 +139,10 @@ public:
|
||||
ExtendWindowByDirectionAndPosition(HWND window, HWND workAreaWindow, DWORD vkCode) noexcept;
|
||||
IFACEMETHODIMP_(void)
|
||||
MoveWindowIntoZoneByPoint(HWND window, HWND workAreaWindow, POINT ptClient) noexcept;
|
||||
IFACEMETHODIMP_(void)
|
||||
DismissWindow(HWND window) noexcept;
|
||||
IFACEMETHODIMP_(void)
|
||||
CycleTabs(HWND window, bool reverse) noexcept;
|
||||
IFACEMETHODIMP_(bool)
|
||||
CalculateZones(RECT workArea, int zoneCount, int spacing) noexcept;
|
||||
IFACEMETHODIMP_(bool) IsZoneEmpty(ZoneIndex zoneIndex) const noexcept;
|
||||
@ -151,6 +155,8 @@ private:
|
||||
bool CalculateUniquePriorityGridLayout(Rect workArea, int zoneCount, int spacing) noexcept;
|
||||
bool CalculateCustomLayout(Rect workArea, int spacing) noexcept;
|
||||
bool CalculateGridZones(Rect workArea, FancyZonesDataTypes::GridLayoutInfo gridLayoutInfo, int spacing);
|
||||
HWND GetNextTab(ZoneIndexSet indexSet, HWND current, bool reverse) noexcept;
|
||||
void InsertTabIntoZone(HWND window, std::optional<size_t> tabSortKeyWithinZone, const ZoneIndexSet& indexSet);
|
||||
ZoneIndexSet ZoneSelectSubregion(const ZoneIndexSet& capturedZones, POINT pt) const;
|
||||
ZoneIndexSet ZoneSelectClosestCenter(const ZoneIndexSet& capturedZones, POINT pt) const;
|
||||
|
||||
@ -160,6 +166,7 @@ private:
|
||||
|
||||
ZonesMap m_zones;
|
||||
std::map<HWND, ZoneIndexSet> m_windowIndexSet;
|
||||
std::map<ZoneIndexSet, std::vector<HWND>> m_windowsByIndexSets;
|
||||
|
||||
// Needed for ExtendWindowByDirectionAndPosition
|
||||
std::map<HWND, ZoneIndexSet> m_windowInitialIndexSet;
|
||||
@ -289,7 +296,7 @@ ZoneSet::MoveWindowIntoZoneByIndex(HWND window, HWND workAreaWindow, ZoneIndex i
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(void)
|
||||
ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const ZoneIndexSet& zoneIds) noexcept
|
||||
ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const ZoneIndexSet& zoneIds, bool suppressMove) noexcept
|
||||
{
|
||||
if (m_zones.empty())
|
||||
{
|
||||
@ -303,11 +310,13 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const Zo
|
||||
m_windowInitialIndexSet.erase(window);
|
||||
}
|
||||
|
||||
auto tabSortKeyWithinZone = GetTabSortKeyWithinZone(window);
|
||||
DismissWindow(window);
|
||||
|
||||
RECT size;
|
||||
bool sizeEmpty = true;
|
||||
Bitmask bitmask = 0;
|
||||
|
||||
m_windowIndexSet[window] = {};
|
||||
auto& indexSet = m_windowIndexSet[window];
|
||||
|
||||
for (ZoneIndex id : zoneIds)
|
||||
{
|
||||
@ -328,7 +337,7 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const Zo
|
||||
sizeEmpty = false;
|
||||
}
|
||||
|
||||
m_windowIndexSet[window].push_back(id);
|
||||
indexSet.push_back(id);
|
||||
}
|
||||
|
||||
if (id < std::numeric_limits<ZoneIndex>::digits)
|
||||
@ -339,9 +348,14 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const Zo
|
||||
|
||||
if (!sizeEmpty)
|
||||
{
|
||||
SaveWindowSizeAndOrigin(window);
|
||||
SizeWindowToRect(window, size);
|
||||
if (!suppressMove)
|
||||
{
|
||||
SaveWindowSizeAndOrigin(window);
|
||||
SizeWindowToRect(window, size);
|
||||
}
|
||||
|
||||
StampWindow(window, bitmask);
|
||||
InsertTabIntoZone(window, tabSortKeyWithinZone, indexSet);
|
||||
}
|
||||
}
|
||||
|
||||
@ -546,6 +560,110 @@ ZoneSet::MoveWindowIntoZoneByPoint(HWND window, HWND workAreaWindow, POINT ptCli
|
||||
MoveWindowIntoZoneByIndexSet(window, workAreaWindow, zones);
|
||||
}
|
||||
|
||||
void ZoneSet::DismissWindow(HWND window) noexcept
|
||||
{
|
||||
auto& indexSet = m_windowIndexSet[window];
|
||||
if (!indexSet.empty())
|
||||
{
|
||||
auto& windows = m_windowsByIndexSets[indexSet];
|
||||
windows.erase(find(begin(windows), end(windows), window));
|
||||
if (windows.empty())
|
||||
{
|
||||
m_windowsByIndexSets.erase(indexSet);
|
||||
}
|
||||
|
||||
indexSet.clear();
|
||||
}
|
||||
|
||||
SetTabSortKeyWithinZone(window, std::nullopt);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(void)
|
||||
ZoneSet::CycleTabs(HWND window, bool reverse) noexcept
|
||||
{
|
||||
auto indexSet = GetZoneIndexSetFromWindow(window);
|
||||
|
||||
// Do nothing in case the window is not recognized
|
||||
if (indexSet.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
auto next = GetNextTab(indexSet, window, reverse);
|
||||
if (next == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
auto success = SetForegroundWindow(next);
|
||||
if (!success && GetLastError() == ERROR_INVALID_WINDOW_HANDLE)
|
||||
{
|
||||
// Dismiss the encountered window since it was probably closed
|
||||
DismissWindow(next);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HWND ZoneSet::GetNextTab(ZoneIndexSet indexSet, HWND current, bool reverse) noexcept
|
||||
{
|
||||
const auto& tabs = m_windowsByIndexSets[indexSet];
|
||||
auto tabIt = std::find(tabs.begin(), tabs.end(), current);
|
||||
if (!reverse)
|
||||
{
|
||||
++tabIt;
|
||||
return tabIt == tabs.end() ? tabs.front() : *tabIt;
|
||||
}
|
||||
else
|
||||
{
|
||||
return tabIt == tabs.begin() ? tabs.back() : *(--tabIt);
|
||||
}
|
||||
}
|
||||
|
||||
void ZoneSet::InsertTabIntoZone(HWND window, std::optional<size_t> tabSortKeyWithinZone, const ZoneIndexSet& indexSet)
|
||||
{
|
||||
if (tabSortKeyWithinZone.has_value())
|
||||
{
|
||||
// Insert the tab using the provided sort key
|
||||
auto predicate = [tabSortKeyWithinZone](HWND tab) {
|
||||
auto currentTabSortKeyWithinZone = GetTabSortKeyWithinZone(tab);
|
||||
if (currentTabSortKeyWithinZone.has_value())
|
||||
{
|
||||
return currentTabSortKeyWithinZone.value() > tabSortKeyWithinZone;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
auto position = std::find_if(m_windowsByIndexSets[indexSet].begin(), m_windowsByIndexSets[indexSet].end(), predicate);
|
||||
m_windowsByIndexSets[indexSet].insert(position, window);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert the tab at the end
|
||||
tabSortKeyWithinZone = 0;
|
||||
if (!m_windowsByIndexSets[indexSet].empty())
|
||||
{
|
||||
auto prevTab = m_windowsByIndexSets[indexSet].back();
|
||||
auto prevTabSortKeyWithinZone = GetTabSortKeyWithinZone(prevTab);
|
||||
if (prevTabSortKeyWithinZone.has_value())
|
||||
{
|
||||
tabSortKeyWithinZone = prevTabSortKeyWithinZone.value() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
m_windowsByIndexSets[indexSet].push_back(window);
|
||||
}
|
||||
|
||||
SetTabSortKeyWithinZone(window, tabSortKeyWithinZone);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(bool)
|
||||
ZoneSet::CalculateZones(RECT workAreaRect, int zoneCount, int spacing) noexcept
|
||||
{
|
||||
|
@ -64,8 +64,9 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
|
||||
* @param workAreaWindow The m_window of a WorkArea, it's a hidden window representing the
|
||||
* current monitor desktop work area.
|
||||
* @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) = 0;
|
||||
IFACEMETHOD_(void, MoveWindowIntoZoneByIndexSet)(HWND window, HWND workAreaWindow, const ZoneIndexSet& indexSet, bool suppressMove = false) = 0;
|
||||
/**
|
||||
* Assign window to the zone based on direction (using WIN + LEFT/RIGHT arrow), based on zone index numbers,
|
||||
* not their on-screen position.
|
||||
@ -119,6 +120,21 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
|
||||
*/
|
||||
IFACEMETHOD_(void, MoveWindowIntoZoneByPoint)
|
||||
(HWND window, HWND workAreaWindow, POINT ptClient) = 0;
|
||||
/**
|
||||
* Dismiss window from zone.
|
||||
*
|
||||
* @param window Handle of window which should be dismissed from zone.
|
||||
*/
|
||||
IFACEMETHOD_(void, DismissWindow)
|
||||
(HWND window) = 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;
|
||||
/**
|
||||
* Calculate zone coordinates within zone layout based on number of zones and spacing.
|
||||
*
|
||||
|
@ -52,7 +52,10 @@
|
||||
#define ZoneBorderColorKey "ZoneBorderColor"
|
||||
#define ZoneHighlightColorKey "ZoneHighlightColor"
|
||||
#define ZoneHighlightOpacityKey "ZoneHighlightOpacity"
|
||||
#define HotkeyKey "Hotkey"
|
||||
#define EditorHotkeyKey "EditorHotkey"
|
||||
#define WindowSwitchingToggleKey "WindowSwitchingToggle"
|
||||
#define NextTabHotkey "NextTabHotkey"
|
||||
#define PrevTabHotkey "PrevTabHotkey"
|
||||
#define ExcludedAppsCountKey "ExcludedAppsCount"
|
||||
#define KeyboardValueKey "KeyboardValue"
|
||||
#define ActiveSetKey "ActiveSet"
|
||||
@ -244,15 +247,21 @@ void Trace::FancyZones::QuickLayoutSwitched(bool shortcutUsed) noexcept
|
||||
TraceLoggingBoolean(shortcutUsed, QuickLayoutSwitchedWithShortcutUsed));
|
||||
}
|
||||
|
||||
static std::wstring HotKeyToString(const PowerToysSettings::HotkeyObject& hotkey)
|
||||
{
|
||||
return L"alt:" + std::to_wstring(hotkey.alt_pressed())
|
||||
+ L", ctrl:" + std::to_wstring(hotkey.ctrl_pressed())
|
||||
+ L", shift:" + std::to_wstring(hotkey.shift_pressed())
|
||||
+ L", win:" + std::to_wstring(hotkey.win_pressed())
|
||||
+ L", code:" + std::to_wstring(hotkey.get_code())
|
||||
+ L", keyFromCode:" + hotkey.get_key();
|
||||
}
|
||||
|
||||
void Trace::SettingsTelemetry(const Settings& settings) noexcept
|
||||
{
|
||||
const auto& editorHotkey = settings.editorHotkey;
|
||||
std::wstring hotkeyStr = L"alt:" + std::to_wstring(editorHotkey.alt_pressed())
|
||||
+ L", ctrl:" + std::to_wstring(editorHotkey.ctrl_pressed())
|
||||
+ L", shift:" + std::to_wstring(editorHotkey.shift_pressed())
|
||||
+ L", win:" + std::to_wstring(editorHotkey.win_pressed())
|
||||
+ L", code:" + std::to_wstring(editorHotkey.get_code())
|
||||
+ L", keyFromCode:" + editorHotkey.get_key();
|
||||
auto editorHotkeyStr = HotKeyToString(settings.editorHotkey);
|
||||
auto nextTabHotkeyStr = HotKeyToString(settings.nextTabHotkey);
|
||||
auto prevTabHotkeyStr = HotKeyToString(settings.prevTabHotkey);
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
@ -281,7 +290,10 @@ void Trace::SettingsTelemetry(const Settings& settings) noexcept
|
||||
TraceLoggingWideString(settings.zoneHighlightColor.c_str(), ZoneHighlightColorKey),
|
||||
TraceLoggingInt32(settings.zoneHighlightOpacity, ZoneHighlightOpacityKey),
|
||||
TraceLoggingInt32((int)settings.overlappingZonesAlgorithm, OverlappingZonesAlgorithmKey),
|
||||
TraceLoggingWideString(hotkeyStr.c_str(), HotkeyKey),
|
||||
TraceLoggingWideString(editorHotkeyStr.c_str(), EditorHotkeyKey),
|
||||
TraceLoggingBoolean(settings.windowSwitching, WindowSwitchingToggleKey),
|
||||
TraceLoggingWideString(nextTabHotkeyStr.c_str(), NextTabHotkey),
|
||||
TraceLoggingWideString(prevTabHotkeyStr.c_str(), PrevTabHotkey),
|
||||
TraceLoggingInt32(static_cast<int>(settings.excludedAppsArray.size()), ExcludedAppsCountKey));
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,9 @@ namespace FancyZonesUnitTests
|
||||
PowerToysSettings::Settings ptSettings(HINSTANCE{}, L"FancyZonesUnitTests");
|
||||
|
||||
ptSettings.add_hotkey(L"fancyzones_editor_hotkey", IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, settings.editorHotkey);
|
||||
ptSettings.add_bool_toggle(L"fancyzones_windowSwitching", IDS_SETTING_WINDOW_SWITCHING_TOGGLE_LABEL, settings.windowSwitching);
|
||||
ptSettings.add_hotkey(L"fancyzones_nextTab_hotkey", IDS_SETTING_NEXT_TAB_HOTKEY_LABEL, settings.nextTabHotkey);
|
||||
ptSettings.add_hotkey(L"fancyzones_prevTab_hotkey", IDS_SETTING_PREV_TAB_HOTKEY_LABEL, settings.prevTabHotkey);
|
||||
ptSettings.add_bool_toggle(L"fancyzones_shiftDrag", IDS_SETTING_DESCRIPTION_SHIFTDRAG, settings.shiftDrag);
|
||||
ptSettings.add_bool_toggle(L"fancyzones_mouseSwitch", IDS_SETTING_DESCRIPTION_MOUSESWITCH, settings.mouseSwitch);
|
||||
ptSettings.add_bool_toggle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, settings.overrideSnapHotkeys);
|
||||
|
@ -41,6 +41,7 @@ namespace FancyZonesUnitTests
|
||||
Assert::AreEqual(expected.showZonesOnAllMonitors, actual.showZonesOnAllMonitors);
|
||||
Assert::AreEqual(expected.spanZonesAcrossMonitors, actual.spanZonesAcrossMonitors);
|
||||
Assert::AreEqual(expected.makeDraggedWindowTransparent, actual.makeDraggedWindowTransparent);
|
||||
Assert::AreEqual(expected.windowSwitching, actual.windowSwitching);
|
||||
Assert::AreEqual(expected.zoneColor.c_str(), actual.zoneColor.c_str());
|
||||
Assert::AreEqual(expected.zoneBorderColor.c_str(), actual.zoneBorderColor.c_str());
|
||||
Assert::AreEqual(expected.zoneHighlightColor.c_str(), actual.zoneHighlightColor.c_str());
|
||||
@ -53,6 +54,8 @@ namespace FancyZonesUnitTests
|
||||
}
|
||||
|
||||
compareHotkeyObjects(expected.editorHotkey, actual.editorHotkey);
|
||||
compareHotkeyObjects(expected.nextTabHotkey, actual.nextTabHotkey);
|
||||
compareHotkeyObjects(expected.prevTabHotkey, actual.prevTabHotkey);
|
||||
}
|
||||
|
||||
TEST_CLASS (FancyZonesSettingsCreationUnitTest)
|
||||
@ -62,7 +65,6 @@ namespace FancyZonesUnitTests
|
||||
PCWSTR m_moduleKey = L"FancyZonesUnitTests";
|
||||
std::wstring m_tmpName;
|
||||
|
||||
const PowerToysSettings::HotkeyObject m_defaultHotkeyObject = PowerToysSettings::HotkeyObject::from_settings(true, false, false, false, VK_OEM_3);
|
||||
const Settings m_defaultSettings;
|
||||
|
||||
TEST_METHOD_INITIALIZE(Init)
|
||||
@ -128,6 +130,9 @@ namespace FancyZonesUnitTests
|
||||
values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHighlightColor);
|
||||
values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity);
|
||||
values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json());
|
||||
values.add_property(L"fancyzones_windowSwitching", expected.windowSwitching);
|
||||
values.add_property(L"fancyzones_nextTab_hotkey", expected.nextTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_prevTab_hotkey", expected.prevTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_excluded_apps", expected.excludedApps);
|
||||
|
||||
values.save_to_settings_file();
|
||||
@ -168,6 +173,9 @@ namespace FancyZonesUnitTests
|
||||
values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHighlightColor);
|
||||
values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity);
|
||||
values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json());
|
||||
values.add_property(L"fancyzones_windowSwitching", expected.windowSwitching);
|
||||
values.add_property(L"fancyzones_nextTab_hotkey", expected.nextTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_prevTab_hotkey", expected.prevTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_excluded_apps", expected.excludedApps);
|
||||
|
||||
values.save_to_settings_file();
|
||||
@ -202,6 +210,8 @@ namespace FancyZonesUnitTests
|
||||
.zoneHighlightColor = L"#00FFD7",
|
||||
.zoneHighlightOpacity = 45,
|
||||
.editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3),
|
||||
.nextTabHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_NEXT),
|
||||
.prevTabHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_PRIOR),
|
||||
.excludedApps = L"app",
|
||||
.excludedAppsArray = { L"APP" },
|
||||
};
|
||||
@ -212,6 +222,9 @@ namespace FancyZonesUnitTests
|
||||
values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHighlightColor);
|
||||
values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity);
|
||||
values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json());
|
||||
values.add_property(L"fancyzones_windowSwitching", expected.windowSwitching);
|
||||
values.add_property(L"fancyzones_nextTab_hotkey", expected.nextTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_prevTab_hotkey", expected.prevTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_excluded_apps", expected.excludedApps);
|
||||
|
||||
values.save_to_settings_file();
|
||||
@ -246,6 +259,9 @@ namespace FancyZonesUnitTests
|
||||
values.add_property(L"fancyzones_makeDraggedWindowTransparent", expected.makeDraggedWindowTransparent);
|
||||
values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity);
|
||||
values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json());
|
||||
values.add_property(L"fancyzones_windowSwitching", expected.windowSwitching);
|
||||
values.add_property(L"fancyzones_nextTab_hotkey", expected.nextTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_prevTab_hotkey", expected.prevTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_excluded_apps", expected.excludedApps);
|
||||
|
||||
values.save_to_settings_file();
|
||||
@ -281,6 +297,9 @@ namespace FancyZonesUnitTests
|
||||
values.add_property(L"fancyzones_zoneColor", expected.zoneColor);
|
||||
values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHighlightColor);
|
||||
values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json());
|
||||
values.add_property(L"fancyzones_windowSwitching", expected.windowSwitching);
|
||||
values.add_property(L"fancyzones_nextTab_hotkey", expected.nextTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_prevTab_hotkey", expected.prevTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_excluded_apps", expected.excludedApps);
|
||||
|
||||
values.save_to_settings_file();
|
||||
@ -354,6 +373,9 @@ namespace FancyZonesUnitTests
|
||||
values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHighlightColor);
|
||||
values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity);
|
||||
values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json());
|
||||
values.add_property(L"fancyzones_windowSwitching", expected.windowSwitching);
|
||||
values.add_property(L"fancyzones_nextTab_hotkey", expected.nextTabHotkey.get_json());
|
||||
values.add_property(L"fancyzones_prevTab_hotkey", expected.prevTabHotkey.get_json());
|
||||
|
||||
values.save_to_settings_file();
|
||||
|
||||
@ -416,6 +438,9 @@ namespace FancyZonesUnitTests
|
||||
IDS_SETTING_LAUNCH_EDITOR_BUTTON,
|
||||
IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION);
|
||||
ptSettings.add_hotkey(L"fancyzones_editor_hotkey", IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, settings.editorHotkey);
|
||||
ptSettings.add_bool_toggle(L"fancyzones_windowSwitching", IDS_SETTING_WINDOW_SWITCHING_TOGGLE_LABEL, settings.windowSwitching);
|
||||
ptSettings.add_hotkey(L"fancyzones_nextTab_hotkey", IDS_SETTING_NEXT_TAB_HOTKEY_LABEL, settings.nextTabHotkey);
|
||||
ptSettings.add_hotkey(L"fancyzones_prevTab_hotkey", IDS_SETTING_PREV_TAB_HOTKEY_LABEL, settings.prevTabHotkey);
|
||||
ptSettings.add_bool_toggle(L"fancyzones_shiftDrag", IDS_SETTING_DESCRIPTION_SHIFTDRAG, settings.shiftDrag);
|
||||
ptSettings.add_bool_toggle(L"fancyzones_mouseSwitch", IDS_SETTING_DESCRIPTION_MOUSESWITCH, settings.mouseSwitch);
|
||||
ptSettings.add_bool_toggle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, settings.overrideSnapHotkeys);
|
||||
@ -517,6 +542,8 @@ namespace FancyZonesUnitTests
|
||||
.zoneHighlightColor = L"#00AABB",
|
||||
.zoneHighlightOpacity = 45,
|
||||
.editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, false, false, false, VK_OEM_3),
|
||||
.nextTabHotkey = PowerToysSettings::HotkeyObject::from_settings(false, false, false, false, VK_NEXT),
|
||||
.prevTabHotkey = PowerToysSettings::HotkeyObject::from_settings(false, false, false, false, VK_PRIOR),
|
||||
.excludedApps = L"app\r\napp2",
|
||||
.excludedAppsArray = { L"APP", L"APP2" },
|
||||
};
|
||||
|
@ -10,7 +10,13 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
public class FZConfigProperties
|
||||
{
|
||||
// in reality, this file needs to be kept in sync currently with src\modules\fancyzones\lib\Settings.h
|
||||
public static readonly HotkeySettings DefaultHotkeyValue = new HotkeySettings(true, false, false, true, 0xc0);
|
||||
public const int VkOem3 = 0xc0;
|
||||
public const int VkNext = 0x22;
|
||||
public const int VkPrior = 0x21;
|
||||
|
||||
public static readonly HotkeySettings DefaultEditorHotkeyValue = new HotkeySettings(true, false, false, true, VkOem3);
|
||||
public static readonly HotkeySettings DefaultNextTabHotkeyValue = new HotkeySettings(true, false, false, false, VkNext);
|
||||
public static readonly HotkeySettings DefaultPrevTabHotkeyValue = new HotkeySettings(true, false, false, false, VkPrior);
|
||||
|
||||
public FZConfigProperties()
|
||||
{
|
||||
@ -32,7 +38,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
FancyzonesSpanZonesAcrossMonitors = new BoolProperty();
|
||||
FancyzonesZoneHighlightColor = new StringProperty(ConfigDefaults.DefaultFancyZonesZoneHighlightColor);
|
||||
FancyzonesHighlightOpacity = new IntProperty(50);
|
||||
FancyzonesEditorHotkey = new KeyboardKeysProperty(DefaultHotkeyValue);
|
||||
FancyzonesEditorHotkey = new KeyboardKeysProperty(DefaultEditorHotkeyValue);
|
||||
FancyzonesWindowSwitching = new BoolProperty(true);
|
||||
FancyzonesNextTabHotkey = new KeyboardKeysProperty(DefaultNextTabHotkeyValue);
|
||||
FancyzonesPrevTabHotkey = new KeyboardKeysProperty(DefaultPrevTabHotkeyValue);
|
||||
FancyzonesMakeDraggedWindowTransparent = new BoolProperty();
|
||||
FancyzonesExcludedApps = new StringProperty();
|
||||
FancyzonesInActiveColor = new StringProperty(ConfigDefaults.DefaultFancyZonesInActiveColor);
|
||||
@ -99,6 +108,15 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
[JsonPropertyName("fancyzones_editor_hotkey")]
|
||||
public KeyboardKeysProperty FancyzonesEditorHotkey { get; set; }
|
||||
|
||||
[JsonPropertyName("fancyzones_windowSwitching")]
|
||||
public BoolProperty FancyzonesWindowSwitching { get; set; }
|
||||
|
||||
[JsonPropertyName("fancyzones_nextTab_hotkey")]
|
||||
public KeyboardKeysProperty FancyzonesNextTabHotkey { get; set; }
|
||||
|
||||
[JsonPropertyName("fancyzones_prevTab_hotkey")]
|
||||
public KeyboardKeysProperty FancyzonesPrevTabHotkey { get; set; }
|
||||
|
||||
[JsonPropertyName("fancyzones_excluded_apps")]
|
||||
public StringProperty FancyzonesExcludedApps { get; set; }
|
||||
|
||||
|
@ -89,6 +89,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
_highlightOpacity = Settings.Properties.FancyzonesHighlightOpacity.Value;
|
||||
_excludedApps = Settings.Properties.FancyzonesExcludedApps.Value;
|
||||
EditorHotkey = Settings.Properties.FancyzonesEditorHotkey.Value;
|
||||
_windowSwitching = Settings.Properties.FancyzonesWindowSwitching.Value;
|
||||
NextTabHotkey = Settings.Properties.FancyzonesNextTabHotkey.Value;
|
||||
PrevTabHotkey = Settings.Properties.FancyzonesPrevTabHotkey.Value;
|
||||
|
||||
// set the callback functions value to hangle outgoing IPC message.
|
||||
SendConfigMSG = ipcMSGCallBackFunc;
|
||||
@ -127,6 +130,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
private int _highlightOpacity;
|
||||
private string _excludedApps;
|
||||
private HotkeySettings _editorHotkey;
|
||||
private bool _windowSwitching;
|
||||
private HotkeySettings _nextTabHotkey;
|
||||
private HotkeySettings _prevTabHotkey;
|
||||
private string _zoneInActiveColor;
|
||||
private string _zoneBorderColor;
|
||||
private string _zoneHighlightColor;
|
||||
@ -152,6 +158,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
OnPropertyChanged(nameof(SnapHotkeysCategoryEnabled));
|
||||
OnPropertyChanged(nameof(QuickSwitchEnabled));
|
||||
OnPropertyChanged(nameof(WindowSwitchingCategoryEnabled));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -172,6 +179,14 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool WindowSwitchingCategoryEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isEnabled && _windowSwitching;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShiftDrag
|
||||
{
|
||||
get
|
||||
@ -604,7 +619,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
{
|
||||
if (value == null || value.IsEmpty())
|
||||
{
|
||||
_editorHotkey = FZConfigProperties.DefaultHotkeyValue;
|
||||
_editorHotkey = FZConfigProperties.DefaultEditorHotkeyValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -617,6 +632,78 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool WindowSwitching
|
||||
{
|
||||
get
|
||||
{
|
||||
return _windowSwitching;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value != _windowSwitching)
|
||||
{
|
||||
_windowSwitching = value;
|
||||
|
||||
Settings.Properties.FancyzonesWindowSwitching.Value = _windowSwitching;
|
||||
NotifyPropertyChanged();
|
||||
OnPropertyChanged(nameof(WindowSwitchingCategoryEnabled));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HotkeySettings NextTabHotkey
|
||||
{
|
||||
get
|
||||
{
|
||||
return _nextTabHotkey;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value != _nextTabHotkey)
|
||||
{
|
||||
if (value == null || value.IsEmpty())
|
||||
{
|
||||
_nextTabHotkey = FZConfigProperties.DefaultNextTabHotkeyValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_nextTabHotkey = value;
|
||||
}
|
||||
|
||||
Settings.Properties.FancyzonesNextTabHotkey.Value = _nextTabHotkey;
|
||||
NotifyPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HotkeySettings PrevTabHotkey
|
||||
{
|
||||
get
|
||||
{
|
||||
return _prevTabHotkey;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value != _prevTabHotkey)
|
||||
{
|
||||
if (value == null || value.IsEmpty())
|
||||
{
|
||||
_prevTabHotkey = FZConfigProperties.DefaultPrevTabHotkeyValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_prevTabHotkey = value;
|
||||
}
|
||||
|
||||
Settings.Properties.FancyzonesPrevTabHotkey.Value = _prevTabHotkey;
|
||||
NotifyPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string ExcludedApps
|
||||
{
|
||||
get
|
||||
|
@ -51,6 +51,9 @@ namespace ViewModelTests
|
||||
Assert.AreEqual(originalSettings.Properties.FancyzonesBorderColor.Value, viewModel.ZoneBorderColor);
|
||||
Assert.AreEqual(originalSettings.Properties.FancyzonesDisplayChangeMoveWindows.Value, viewModel.DisplayChangeMoveWindows);
|
||||
Assert.AreEqual(originalSettings.Properties.FancyzonesEditorHotkey.Value.ToString(), viewModel.EditorHotkey.ToString());
|
||||
Assert.AreEqual(originalSettings.Properties.FancyzonesWindowSwitching.Value, viewModel.WindowSwitching);
|
||||
Assert.AreEqual(originalSettings.Properties.FancyzonesNextTabHotkey.Value.ToString(), viewModel.NextTabHotkey.ToString());
|
||||
Assert.AreEqual(originalSettings.Properties.FancyzonesPrevTabHotkey.Value.ToString(), viewModel.PrevTabHotkey.ToString());
|
||||
Assert.AreEqual(originalSettings.Properties.FancyzonesExcludedApps.Value, viewModel.ExcludedApps);
|
||||
Assert.AreEqual(originalSettings.Properties.FancyzonesHighlightOpacity.Value, viewModel.HighlightOpacity);
|
||||
Assert.AreEqual(originalSettings.Properties.FancyzonesInActiveColor.Value, viewModel.ZoneInActiveColor);
|
||||
|
@ -449,6 +449,24 @@
|
||||
<data name="FancyZones_HotkeyEditorControl.Header" xml:space="preserve">
|
||||
<value>Open layout editor</value>
|
||||
<comment>Shortcut to launch the FancyZones layout editor application</comment>
|
||||
</data>
|
||||
<data name="FancyZones_WindowSwitching_GroupSettings.Header" xml:space="preserve">
|
||||
<value>Window switching</value>
|
||||
</data>
|
||||
<data name="FancyZones_WindowSwitching_GroupSettings.Description" xml:space="preserve">
|
||||
<value>Shortcuts for switching between windows in the current zone</value>
|
||||
</data>
|
||||
<data name="FancyZones_HotkeyNextTabControl.Header" xml:space="preserve">
|
||||
<value>Next window</value>
|
||||
</data>
|
||||
<data name="FancyZones_HotkeyNextTabControl.Description" xml:space="preserve">
|
||||
<value>Shortcut for switching to the next window in the current zone</value>
|
||||
</data>
|
||||
<data name="FancyZones_HotkeyPrevTabControl.Header" xml:space="preserve">
|
||||
<value>Previous window</value>
|
||||
</data>
|
||||
<data name="FancyZones_HotkeyPrevTabControl.Description" xml:space="preserve">
|
||||
<value>Shortcut for switching to the previous window in the current zone</value>
|
||||
</data>
|
||||
<data name="SettingsPage_SetShortcut.AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Shortcut setting</value>
|
||||
|
@ -148,6 +148,31 @@
|
||||
</controls:SettingExpander.Content>
|
||||
</controls:SettingExpander>
|
||||
|
||||
<controls:SettingExpander IsExpanded="True">
|
||||
<controls:SettingExpander.Header>
|
||||
<controls:Setting x:Uid="FancyZones_WindowSwitching_GroupSettings" Icon="⎘" Style="{StaticResource ExpanderHeaderSettingStyle}">
|
||||
<controls:Setting.ActionContent>
|
||||
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.WindowSwitching}"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
</controls:SettingExpander.Header>
|
||||
<controls:SettingExpander.Content>
|
||||
<StackPanel>
|
||||
<controls:Setting x:Uid="FancyZones_HotkeyNextTabControl" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.WindowSwitchingCategoryEnabled}" Icon="⎘" Style="{StaticResource ExpanderContentSettingStyle}">
|
||||
<controls:Setting.ActionContent>
|
||||
<controls:ShortcutControl HotkeySettings="{x:Bind Path=ViewModel.NextTabHotkey, Mode=TwoWay}" MinWidth="{StaticResource SettingActionControlMinWidth}"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
|
||||
<controls:Setting x:Uid="FancyZones_HotkeyPrevTabControl" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.WindowSwitchingCategoryEnabled}" Icon="⎗" Style="{StaticResource ExpanderContentSettingStyle}">
|
||||
<controls:Setting.ActionContent>
|
||||
<controls:ShortcutControl HotkeySettings="{x:Bind Path=ViewModel.PrevTabHotkey, Mode=TwoWay}" MinWidth="{StaticResource SettingActionControlMinWidth}"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
</StackPanel>
|
||||
</controls:SettingExpander.Content>
|
||||
</controls:SettingExpander>
|
||||
|
||||
<controls:SettingExpander IsExpanded="True">
|
||||
<controls:SettingExpander.Header>
|
||||
<controls:Setting x:Uid="FancyZones_OverrideSnapHotkeys" Icon="" Style="{StaticResource ExpanderHeaderSettingStyle}">
|
||||
|
Loading…
Reference in New Issue
Block a user