mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
[FancyZones]Use RawInput to detect Shift key, fix locking out Shift key (#32116)
* init RawInputDevice * static * handle input * replace keyboard hooks (ctrl, shift) * keep ctrl hook * spellcheck
This commit is contained in:
@@ -8,8 +8,6 @@ DraggingState::DraggingState(const std::function<void()>& keyUpdateCallback) :
|
|||||||
m_secondaryMouseState(false),
|
m_secondaryMouseState(false),
|
||||||
m_middleMouseState(false),
|
m_middleMouseState(false),
|
||||||
m_mouseHook(std::bind(&DraggingState::OnSecondaryMouseDown, this), std::bind(&DraggingState::OnMiddleMouseDown, this)),
|
m_mouseHook(std::bind(&DraggingState::OnSecondaryMouseDown, this), std::bind(&DraggingState::OnMiddleMouseDown, this)),
|
||||||
m_leftShiftKeyState(keyUpdateCallback),
|
|
||||||
m_rightShiftKeyState(keyUpdateCallback),
|
|
||||||
m_ctrlKeyState(keyUpdateCallback),
|
m_ctrlKeyState(keyUpdateCallback),
|
||||||
m_keyUpdateCallback(keyUpdateCallback)
|
m_keyUpdateCallback(keyUpdateCallback)
|
||||||
{
|
{
|
||||||
@@ -22,49 +20,30 @@ void DraggingState::Enable()
|
|||||||
m_mouseHook.enable();
|
m_mouseHook.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_leftShiftKeyState.enable();
|
|
||||||
m_rightShiftKeyState.enable();
|
|
||||||
m_ctrlKeyState.enable();
|
m_ctrlKeyState.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DraggingState::Disable()
|
void DraggingState::Disable()
|
||||||
{
|
{
|
||||||
const bool leftShiftPressed = m_leftShiftKeyState.state();
|
|
||||||
const bool rightShiftPressed = m_rightShiftKeyState.state();
|
|
||||||
|
|
||||||
if (FancyZonesSettings::settings().shiftDrag)
|
|
||||||
{
|
|
||||||
if (leftShiftPressed)
|
|
||||||
{
|
|
||||||
FancyZonesUtils::SwallowKey(VK_LSHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rightShiftPressed)
|
|
||||||
{
|
|
||||||
FancyZonesUtils::SwallowKey(VK_RSHIFT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dragging = false;
|
m_dragging = false;
|
||||||
m_secondaryMouseState = false;
|
m_secondaryMouseState = false;
|
||||||
m_middleMouseState = false;
|
m_middleMouseState = false;
|
||||||
|
m_shift = false;
|
||||||
|
|
||||||
m_mouseHook.disable();
|
m_mouseHook.disable();
|
||||||
m_leftShiftKeyState.disable();
|
|
||||||
m_rightShiftKeyState.disable();
|
|
||||||
m_ctrlKeyState.disable();
|
m_ctrlKeyState.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DraggingState::UpdateDraggingState() noexcept
|
void DraggingState::UpdateDraggingState() noexcept
|
||||||
{
|
{
|
||||||
// This updates m_dragEnabled depending on if the shift key is being held down
|
// This updates m_dragging depending on if the shift key is being held down
|
||||||
if (FancyZonesSettings::settings().shiftDrag)
|
if (FancyZonesSettings::settings().shiftDrag)
|
||||||
{
|
{
|
||||||
m_dragging = ((m_leftShiftKeyState.state() || m_rightShiftKeyState.state()) ^ m_secondaryMouseState);
|
m_dragging = (m_shift ^ m_secondaryMouseState);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_dragging = !((m_leftShiftKeyState.state() || m_rightShiftKeyState.state()) ^ m_secondaryMouseState);
|
m_dragging = !(m_shift ^ m_secondaryMouseState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,3 +76,9 @@ bool DraggingState::IsSelectManyZonesState() const noexcept
|
|||||||
{
|
{
|
||||||
return m_ctrlKeyState.state() || m_middleMouseState;
|
return m_ctrlKeyState.state() || m_middleMouseState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DraggingState::SetShiftState(bool value) noexcept
|
||||||
|
{
|
||||||
|
m_shift = value;
|
||||||
|
m_keyUpdateCallback();
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ public:
|
|||||||
bool IsDragging() const noexcept;
|
bool IsDragging() const noexcept;
|
||||||
bool IsSelectManyZonesState() const noexcept;
|
bool IsSelectManyZonesState() const noexcept;
|
||||||
|
|
||||||
|
void SetShiftState(bool value) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnSecondaryMouseDown();
|
void OnSecondaryMouseDown();
|
||||||
void OnMiddleMouseDown();
|
void OnMiddleMouseDown();
|
||||||
@@ -23,9 +25,10 @@ private:
|
|||||||
std::atomic<bool> m_secondaryMouseState;
|
std::atomic<bool> m_secondaryMouseState;
|
||||||
std::atomic<bool> m_middleMouseState;
|
std::atomic<bool> m_middleMouseState;
|
||||||
MouseButtonsHook m_mouseHook;
|
MouseButtonsHook m_mouseHook;
|
||||||
KeyState<VK_LSHIFT> m_leftShiftKeyState;
|
|
||||||
KeyState<VK_RSHIFT> m_rightShiftKeyState;
|
|
||||||
KeyState<VK_LCONTROL, VK_RCONTROL> m_ctrlKeyState;
|
KeyState<VK_LCONTROL, VK_RCONTROL> m_ctrlKeyState;
|
||||||
|
|
||||||
|
bool m_shift{};
|
||||||
|
|
||||||
std::function<void()> m_keyUpdateCallback;
|
std::function<void()> m_keyUpdateCallback;
|
||||||
|
|
||||||
bool m_dragging{}; // True if we should be showing zone hints while dragging
|
bool m_dragging{}; // True if we should be showing zone hints while dragging
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <FancyZonesLib/FancyZonesWindowProcessing.h>
|
#include <FancyZonesLib/FancyZonesWindowProcessing.h>
|
||||||
#include <FancyZonesLib/FancyZonesWindowProperties.h>
|
#include <FancyZonesLib/FancyZonesWindowProperties.h>
|
||||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||||
|
#include <FancyZonesLib/KeyboardInput.h>
|
||||||
#include <FancyZonesLib/MonitorUtils.h>
|
#include <FancyZonesLib/MonitorUtils.h>
|
||||||
#include <FancyZonesLib/on_thread_executor.h>
|
#include <FancyZonesLib/on_thread_executor.h>
|
||||||
#include <FancyZonesLib/Settings.h>
|
#include <FancyZonesLib/Settings.h>
|
||||||
@@ -143,6 +144,7 @@ public:
|
|||||||
void ToggleEditor() noexcept;
|
void ToggleEditor() noexcept;
|
||||||
|
|
||||||
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
||||||
|
void OnKeyboardInput(WPARAM flags, HRAWINPUT hInput) noexcept;
|
||||||
void OnDisplayChange(DisplayChangeType changeType) noexcept;
|
void OnDisplayChange(DisplayChangeType changeType) noexcept;
|
||||||
bool AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id, const FancyZonesUtils::Rect& rect) noexcept;
|
bool AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id, const FancyZonesUtils::Rect& rect) noexcept;
|
||||||
|
|
||||||
@@ -220,7 +222,13 @@ FancyZones::Run() noexcept
|
|||||||
m_window = CreateWindowExW(WS_EX_TOOLWINDOW, NonLocalizable::ToolWindowClassName, L"", WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, m_hinstance, this);
|
m_window = CreateWindowExW(WS_EX_TOOLWINDOW, NonLocalizable::ToolWindowClassName, L"", WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, m_hinstance, this);
|
||||||
if (!m_window)
|
if (!m_window)
|
||||||
{
|
{
|
||||||
Logger::error(L"Failed to create FancyZones window");
|
Logger::critical(L"Failed to create FancyZones window");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!KeyboardInput::Initialize(m_window))
|
||||||
|
{
|
||||||
|
Logger::critical(L"Failed to register raw input device");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,6 +588,12 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WM_INPUT:
|
||||||
|
{
|
||||||
|
OnKeyboardInput(wparam, reinterpret_cast<HRAWINPUT>(lparam));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case WM_SETTINGCHANGE:
|
case WM_SETTINGCHANGE:
|
||||||
{
|
{
|
||||||
if (wparam == SPI_SETWORKAREA)
|
if (wparam == SPI_SETWORKAREA)
|
||||||
@@ -717,6 +731,26 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FancyZones::OnKeyboardInput(WPARAM /*flags*/, HRAWINPUT hInput) noexcept
|
||||||
|
{
|
||||||
|
auto input = KeyboardInput::OnKeyboardInput(hInput);
|
||||||
|
if (!input.has_value())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (input.value().vkKey)
|
||||||
|
{
|
||||||
|
case VK_SHIFT:
|
||||||
|
{
|
||||||
|
m_draggingState.SetShiftState(input.value().pressed);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
||||||
{
|
{
|
||||||
Logger::info(L"Display changed, type: {}", DisplayChangeTypeName(changeType));
|
Logger::info(L"Display changed, type: {}", DisplayChangeTypeName(changeType));
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
<ClInclude Include="FancyZonesData.h" />
|
<ClInclude Include="FancyZonesData.h" />
|
||||||
<ClInclude Include="GuidUtils.h" />
|
<ClInclude Include="GuidUtils.h" />
|
||||||
<ClInclude Include="JsonHelpers.h" />
|
<ClInclude Include="JsonHelpers.h" />
|
||||||
|
<ClInclude Include="KeyboardInput.h" />
|
||||||
<ClInclude Include="KeyState.h" />
|
<ClInclude Include="KeyState.h" />
|
||||||
<ClInclude Include="FancyZonesData\LayoutHotkeys.h" />
|
<ClInclude Include="FancyZonesData\LayoutHotkeys.h" />
|
||||||
<ClInclude Include="Layout.h" />
|
<ClInclude Include="Layout.h" />
|
||||||
@@ -114,6 +115,7 @@
|
|||||||
<ClCompile Include="FancyZonesData\LayoutHotkeys.cpp">
|
<ClCompile Include="FancyZonesData\LayoutHotkeys.cpp">
|
||||||
<PrecompiledHeaderFile>../pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>../pch.h</PrecompiledHeaderFile>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="KeyboardInput.cpp" />
|
||||||
<ClCompile Include="Layout.cpp" />
|
<ClCompile Include="Layout.cpp" />
|
||||||
<ClCompile Include="LayoutConfigurator.cpp" />
|
<ClCompile Include="LayoutConfigurator.cpp" />
|
||||||
<ClCompile Include="LayoutAssignedWindows.cpp" />
|
<ClCompile Include="LayoutAssignedWindows.cpp" />
|
||||||
|
|||||||
@@ -168,6 +168,9 @@
|
|||||||
<ClInclude Include="FancyZonesData\LastUsedVirtualDesktop.h">
|
<ClInclude Include="FancyZonesData\LastUsedVirtualDesktop.h">
|
||||||
<Filter>Header Files\FancyZonesData</Filter>
|
<Filter>Header Files\FancyZonesData</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="KeyboardInput.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
@@ -278,6 +281,9 @@
|
|||||||
<ClCompile Include="FancyZonesWindowProcessing.cpp">
|
<ClCompile Include="FancyZonesWindowProcessing.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="KeyboardInput.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
|||||||
43
src/modules/fancyzones/FancyZonesLib/KeyboardInput.cpp
Normal file
43
src/modules/fancyzones/FancyZonesLib/KeyboardInput.cpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "KeyboardInput.h"
|
||||||
|
|
||||||
|
#include <hidUsage.h>
|
||||||
|
|
||||||
|
#include <common/logger/logger.h>
|
||||||
|
#include <common/utils/winapi_error.h>
|
||||||
|
|
||||||
|
bool KeyboardInput::Initialize(HWND window)
|
||||||
|
{
|
||||||
|
RAWINPUTDEVICE inputDevice{};
|
||||||
|
inputDevice.usUsagePage = HID_USAGE_PAGE_GENERIC;
|
||||||
|
inputDevice.usUsage = HID_USAGE_GENERIC_KEYBOARD;
|
||||||
|
inputDevice.dwFlags = RIDEV_INPUTSINK;
|
||||||
|
inputDevice.hwndTarget = window;
|
||||||
|
|
||||||
|
bool res = RegisterRawInputDevices(&inputDevice, 1, sizeof(inputDevice));
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
Logger::error(L"RegisterRawInputDevices error: {}", get_last_error_or_default(GetLastError()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<KeyboardInput::Key> KeyboardInput::OnKeyboardInput(HRAWINPUT hInput)
|
||||||
|
{
|
||||||
|
RAWINPUT input;
|
||||||
|
UINT size = sizeof(input);
|
||||||
|
auto result = GetRawInputData(hInput, RID_INPUT, &input, &size, sizeof(RAWINPUTHEADER));
|
||||||
|
if (result < sizeof(RAWINPUTHEADER))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.header.dwType == RIM_TYPEKEYBOARD)
|
||||||
|
{
|
||||||
|
bool pressed = (input.data.keyboard.Flags & RI_KEY_BREAK) == 0;
|
||||||
|
return KeyboardInput::Key{ input.data.keyboard.VKey, pressed };
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
17
src/modules/fancyzones/FancyZonesLib/KeyboardInput.h
Normal file
17
src/modules/fancyzones/FancyZonesLib/KeyboardInput.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class KeyboardInput
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Key
|
||||||
|
{
|
||||||
|
USHORT vkKey{};
|
||||||
|
bool pressed{};
|
||||||
|
};
|
||||||
|
|
||||||
|
KeyboardInput() = default;
|
||||||
|
~KeyboardInput() = default;
|
||||||
|
|
||||||
|
static bool Initialize(HWND window);
|
||||||
|
static std::optional<Key> OnKeyboardInput(HRAWINPUT hInput);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user