[FancyZones] Dragging a window across monitors transparency fix (#5102)

This commit is contained in:
Seraphima Zykova
2020-07-22 19:00:03 +03:00
committed by GitHub
parent 761f0a78f4
commit 92c666692d
4 changed files with 76 additions and 72 deletions

View File

@@ -79,7 +79,11 @@ public:
bool MoveWindowIntoZoneByDirection(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow); bool MoveWindowIntoZoneByDirection(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IZoneWindow> zoneWindow);
private: private:
void UpdateDragState(HWND window) noexcept; void WarnIfElevationIsRequired(HWND window) noexcept;
void UpdateDragState() noexcept;
void SetWindowTransparency(HWND window) noexcept;
void ResetWindowTransparency() noexcept;
private: private:
winrt::com_ptr<IFancyZonesSettings> m_settings{}; winrt::com_ptr<IFancyZonesSettings> m_settings{};
@@ -94,6 +98,15 @@ private:
bool m_secondaryMouseButtonState{}; // True when secondary mouse button was clicked after window was moved bool m_secondaryMouseButtonState{}; // True when secondary mouse button was clicked after window was moved
bool m_shiftKeyState{}; // True when shift key was pressed after window was moved bool m_shiftKeyState{}; // True when shift key was pressed after window was moved
bool m_ctrlKeyState{}; // True when ctrl key was pressed after window was moved bool m_ctrlKeyState{}; // True when ctrl key was pressed after window was moved
struct WindowTransparencyProperties
{
HWND draggedWindow = nullptr;
long draggedWindowExstyle = 0;
COLORREF draggedWindowCrKey = RGB(0, 0, 0);
DWORD draggedWindowDwFlags = 0;
BYTE draggedWindowInitialAlpha = 0;
} m_windowTransparencyProperties;
}; };
WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook, CtrlKeyHook* ctrlHook) : WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>& settings, SecondaryMouseButtonsHook* mouseHook, ShiftKeyHook* shiftHook, CtrlKeyHook* ctrlHook) :
@@ -194,13 +207,17 @@ void WindowMoveHandlerPrivate::MoveSizeStart(HWND window, HMONITOR monitor, POIN
m_shiftHook->enable(); m_shiftHook->enable();
m_ctrlHook->enable(); m_ctrlHook->enable();
// This updates m_dragEnabled depending on if the shift key is being held down. // This updates m_dragEnabled depending on if the shift key is being held down
UpdateDragState(window); UpdateDragState();
// Notifies user if unable to drag elevated window
WarnIfElevationIsRequired(window);
if (m_dragEnabled) if (m_dragEnabled)
{ {
m_zoneWindowMoveSize = iter->second; m_zoneWindowMoveSize = iter->second;
m_zoneWindowMoveSize->MoveSizeEnter(window); SetWindowTransparency(m_windowMoveSize);
m_zoneWindowMoveSize->MoveSizeEnter(m_windowMoveSize);
if (m_settings->GetSettings()->showZonesOnAllMonitors) if (m_settings->GetSettings()->showZonesOnAllMonitors)
{ {
for (auto [keyMonitor, zoneWindow] : zoneWindowMap) for (auto [keyMonitor, zoneWindow] : zoneWindowMap)
@@ -217,7 +234,7 @@ void WindowMoveHandlerPrivate::MoveSizeStart(HWND window, HMONITOR monitor, POIN
} }
else if (m_zoneWindowMoveSize) else if (m_zoneWindowMoveSize)
{ {
m_zoneWindowMoveSize->RestoreOriginalTransparency(); ResetWindowTransparency();
m_zoneWindowMoveSize = nullptr; m_zoneWindowMoveSize = nullptr;
for (auto [keyMonitor, zoneWindow] : zoneWindowMap) for (auto [keyMonitor, zoneWindow] : zoneWindowMap)
{ {
@@ -237,7 +254,7 @@ void WindowMoveHandlerPrivate::MoveSizeUpdate(HMONITOR monitor, POINT const& ptS
} }
// This updates m_dragEnabled depending on if the shift key is being held down. // This updates m_dragEnabled depending on if the shift key is being held down.
UpdateDragState(m_windowMoveSize); UpdateDragState();
if (m_zoneWindowMoveSize) if (m_zoneWindowMoveSize)
{ {
@@ -246,12 +263,12 @@ void WindowMoveHandlerPrivate::MoveSizeUpdate(HMONITOR monitor, POINT const& ptS
{ {
// Drag got disabled, tell it to cancel and hide all windows // Drag got disabled, tell it to cancel and hide all windows
m_zoneWindowMoveSize = nullptr; m_zoneWindowMoveSize = nullptr;
ResetWindowTransparency();
for (auto [keyMonitor, zoneWindow] : zoneWindowMap) for (auto [keyMonitor, zoneWindow] : zoneWindowMap)
{ {
if (zoneWindow) if (zoneWindow)
{ {
zoneWindow->RestoreOriginalTransparency();
zoneWindow->HideZoneWindow(); zoneWindow->HideZoneWindow();
} }
} }
@@ -264,13 +281,12 @@ void WindowMoveHandlerPrivate::MoveSizeUpdate(HMONITOR monitor, POINT const& ptS
if (iter->second != m_zoneWindowMoveSize) if (iter->second != m_zoneWindowMoveSize)
{ {
// The drag has moved to a different monitor. // The drag has moved to a different monitor.
m_zoneWindowMoveSize->RestoreOriginalTransparency();
m_zoneWindowMoveSize->ClearSelectedZones(); m_zoneWindowMoveSize->ClearSelectedZones();
if (!m_settings->GetSettings()->showZonesOnAllMonitors) if (!m_settings->GetSettings()->showZonesOnAllMonitors)
{ {
m_zoneWindowMoveSize->HideZoneWindow(); m_zoneWindowMoveSize->HideZoneWindow();
} }
m_zoneWindowMoveSize = iter->second; m_zoneWindowMoveSize = iter->second;
m_zoneWindowMoveSize->MoveSizeEnter(m_windowMoveSize); m_zoneWindowMoveSize->MoveSizeEnter(m_windowMoveSize);
} }
@@ -302,14 +318,11 @@ void WindowMoveHandlerPrivate::MoveSizeEnd(HWND window, POINT const& ptScreen, c
m_shiftHook->disable(); m_shiftHook->disable();
m_ctrlHook->disable(); m_ctrlHook->disable();
m_inMoveSize = false;
m_dragEnabled = false;
m_secondaryMouseButtonState = false;
m_windowMoveSize = nullptr;
if (m_zoneWindowMoveSize) if (m_zoneWindowMoveSize)
{ {
auto zoneWindow = std::move(m_zoneWindowMoveSize); auto zoneWindow = std::move(m_zoneWindowMoveSize);
zoneWindow->MoveSizeEnd(window, ptScreen); ResetWindowTransparency();
zoneWindow->MoveSizeEnd(m_windowMoveSize, ptScreen);
} }
else else
{ {
@@ -345,6 +358,11 @@ void WindowMoveHandlerPrivate::MoveSizeEnd(HWND window, POINT const& ptScreen, c
} }
::RemoveProp(window, MULTI_ZONE_STAMP); ::RemoveProp(window, MULTI_ZONE_STAMP);
} }
m_inMoveSize = false;
m_dragEnabled = false;
m_secondaryMouseButtonState = false;
m_windowMoveSize = nullptr;
// Also, hide all windows (regardless of settings) // Also, hide all windows (regardless of settings)
for (auto [keyMonitor, zoneWindow] : zoneWindowMap) for (auto [keyMonitor, zoneWindow] : zoneWindowMap)
@@ -369,17 +387,8 @@ bool WindowMoveHandlerPrivate::MoveWindowIntoZoneByDirection(HWND window, DWORD
return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirection(window, vkCode, cycle); return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirection(window, vkCode, cycle);
} }
void WindowMoveHandlerPrivate::UpdateDragState(HWND window) noexcept void WindowMoveHandlerPrivate::WarnIfElevationIsRequired(HWND window) noexcept
{ {
if (m_settings->GetSettings()->shiftDrag)
{
m_dragEnabled = (m_shiftKeyState ^ m_secondaryMouseButtonState);
}
else
{
m_dragEnabled = !(m_shiftKeyState ^ m_secondaryMouseButtonState);
}
static bool warning_shown = false; static bool warning_shown = false;
if (!is_process_elevated() && IsProcessOfWindowElevated(window)) if (!is_process_elevated() && IsProcessOfWindowElevated(window))
{ {
@@ -395,3 +404,42 @@ void WindowMoveHandlerPrivate::UpdateDragState(HWND window) noexcept
} }
} }
} }
void WindowMoveHandlerPrivate::UpdateDragState() noexcept
{
if (m_settings->GetSettings()->shiftDrag)
{
m_dragEnabled = (m_shiftKeyState ^ m_secondaryMouseButtonState);
}
else
{
m_dragEnabled = !(m_shiftKeyState ^ m_secondaryMouseButtonState);
}
}
void WindowMoveHandlerPrivate::SetWindowTransparency(HWND window) noexcept
{
if (m_settings->GetSettings()->makeDraggedWindowTransparent)
{
m_windowTransparencyProperties.draggedWindowExstyle = GetWindowLong(window, GWL_EXSTYLE);
m_windowTransparencyProperties.draggedWindow = window;
SetWindowLong(window,
GWL_EXSTYLE,
m_windowTransparencyProperties.draggedWindowExstyle | WS_EX_LAYERED);
GetLayeredWindowAttributes(window, &m_windowTransparencyProperties.draggedWindowCrKey, &m_windowTransparencyProperties.draggedWindowInitialAlpha, &m_windowTransparencyProperties.draggedWindowDwFlags);
SetLayeredWindowAttributes(window, 0, (255 * 50) / 100, LWA_ALPHA);
}
}
void WindowMoveHandlerPrivate::ResetWindowTransparency() noexcept
{
if (m_settings->GetSettings()->makeDraggedWindowTransparent && m_windowTransparencyProperties.draggedWindow != nullptr)
{
SetLayeredWindowAttributes(m_windowTransparencyProperties.draggedWindow, m_windowTransparencyProperties.draggedWindowCrKey, m_windowTransparencyProperties.draggedWindowInitialAlpha, m_windowTransparencyProperties.draggedWindowDwFlags);
SetWindowLong(m_windowTransparencyProperties.draggedWindow, GWL_EXSTYLE, m_windowTransparencyProperties.draggedWindowExstyle);
m_windowTransparencyProperties.draggedWindow = nullptr;
}
}

View File

@@ -175,8 +175,6 @@ public:
IFACEMETHODIMP MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled, bool selectManyZones) noexcept; IFACEMETHODIMP MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled, bool selectManyZones) noexcept;
IFACEMETHODIMP MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept; IFACEMETHODIMP MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept;
IFACEMETHODIMP_(void) IFACEMETHODIMP_(void)
RestoreOriginalTransparency() noexcept;
IFACEMETHODIMP_(void)
MoveWindowIntoZoneByIndex(HWND window, int index) noexcept; MoveWindowIntoZoneByIndex(HWND window, int index) noexcept;
IFACEMETHODIMP_(void) IFACEMETHODIMP_(void)
MoveWindowIntoZoneByIndexSet(HWND window, const std::vector<int>& indexSet) noexcept; MoveWindowIntoZoneByIndexSet(HWND window, const std::vector<int>& indexSet) noexcept;
@@ -231,13 +229,7 @@ private:
size_t m_keyCycle{}; size_t m_keyCycle{};
static const UINT m_showAnimationDuration = 200; // ms static const UINT m_showAnimationDuration = 200; // ms
static const UINT m_flashDuration = 700; // ms static const UINT m_flashDuration = 700; // ms
HWND draggedWindow = nullptr;
long draggedWindowExstyle = 0;
COLORREF draggedWindowCrKey = RGB(0, 0, 0);
DWORD draggedWindowDwFlags = 0;
BYTE draggedWindowInitialAlpha = 0;
ULONG_PTR gdiplusToken; ULONG_PTR gdiplusToken;
}; };
@@ -309,25 +301,6 @@ bool ZoneWindow::Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monit
IFACEMETHODIMP ZoneWindow::MoveSizeEnter(HWND window) noexcept IFACEMETHODIMP ZoneWindow::MoveSizeEnter(HWND window) noexcept
{ {
if (m_windowMoveSize)
{
return E_INVALIDARG;
}
if (m_host->isMakeDraggedWindowTransparentActive())
{
draggedWindowExstyle = GetWindowLong(window, GWL_EXSTYLE);
draggedWindow = window;
SetWindowLong(window,
GWL_EXSTYLE,
draggedWindowExstyle | WS_EX_LAYERED);
GetLayeredWindowAttributes(window, &draggedWindowCrKey, &draggedWindowInitialAlpha, &draggedWindowDwFlags);
SetLayeredWindowAttributes(window, 0, (255 * 50) / 100, LWA_ALPHA);
}
m_windowMoveSize = window; m_windowMoveSize = window;
m_drawHints = true; m_drawHints = true;
m_highlightZone = {}; m_highlightZone = {};
@@ -418,8 +391,6 @@ IFACEMETHODIMP ZoneWindow::MoveSizeUpdate(POINT const& ptScreen, bool dragEnable
IFACEMETHODIMP ZoneWindow::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept IFACEMETHODIMP ZoneWindow::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept
{ {
RestoreOriginalTransparency();
if (m_windowMoveSize != window) if (m_windowMoveSize != window)
{ {
return E_INVALIDARG; return E_INVALIDARG;
@@ -440,17 +411,6 @@ IFACEMETHODIMP ZoneWindow::MoveSizeEnd(HWND window, POINT const& ptScreen) noexc
return S_OK; return S_OK;
} }
IFACEMETHODIMP_(void)
ZoneWindow::RestoreOriginalTransparency() noexcept
{
if (m_host->isMakeDraggedWindowTransparentActive() && draggedWindow != nullptr)
{
SetLayeredWindowAttributes(draggedWindow, draggedWindowCrKey, draggedWindowInitialAlpha, draggedWindowDwFlags);
SetWindowLong(draggedWindow, GWL_EXSTYLE, draggedWindowExstyle);
draggedWindow = nullptr;
}
}
IFACEMETHODIMP_(void) IFACEMETHODIMP_(void)
ZoneWindow::MoveWindowIntoZoneByIndex(HWND window, int index) noexcept ZoneWindow::MoveWindowIntoZoneByIndex(HWND window, int index) noexcept
{ {

View File

@@ -17,10 +17,9 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IZoneWindow
* hints if dragging functionality is enabled. * hints if dragging functionality is enabled.
* *
* @param window Handle of window being moved or resized. * @param window Handle of window being moved or resized.
* @param dragEnabled Boolean indicating is giving hints about active zone layout enabled.
* Hints are given while dragging window while holding SHIFT key.
*/ */
IFACEMETHOD(MoveSizeEnter)(HWND window) = 0; IFACEMETHOD(MoveSizeEnter)(HWND window) = 0;
/** /**
* A window has changed location, shape, or size. Track down window position and give zone layout * A window has changed location, shape, or size. Track down window position and give zone layout
* hints if dragging functionality is enabled. * hints if dragging functionality is enabled.
@@ -74,10 +73,7 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IZoneWindow
* @param vkCode Pressed key representing layout index. * @param vkCode Pressed key representing layout index.
*/ */
IFACEMETHOD_(void, CycleActiveZoneSet)(DWORD vkCode) = 0; IFACEMETHOD_(void, CycleActiveZoneSet)(DWORD vkCode) = 0;
/**
* Restore original transaprency of dragged window.
*/
IFACEMETHOD_(void, RestoreOriginalTransparency) () = 0;
/** /**
* Save information about zone in which window was assigned, when closing the window. * Save information about zone in which window was assigned, when closing the window.
* Used once we open same window again to assign it to its previous zone. * Used once we open same window again to assign it to its previous zone.

View File

@@ -457,7 +457,7 @@ namespace FancyZonesUnitTests
{ {
m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), {}, false); m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), {}, false);
const auto expected = E_INVALIDARG; const auto expected = S_OK;
m_zoneWindow->MoveSizeEnter(Mocks::Window()); m_zoneWindow->MoveSizeEnter(Mocks::Window());
const auto actual = m_zoneWindow->MoveSizeEnter(Mocks::Window()); const auto actual = m_zoneWindow->MoveSizeEnter(Mocks::Window());