Skip to content

Commit b72077b

Browse files
committed
Support quick switch window position
1 parent b1b8707 commit b72077b

File tree

3 files changed

+83
-50
lines changed

3 files changed

+83
-50
lines changed

Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public static class QuickSwitch
2828

2929
public static Action HideQuickSwitchWindow { get; set; } = null;
3030

31+
public static QuickSwitchWindowPositions QuickSwitchWindowPosition { get; private set; }
32+
3133
#endregion
3234

3335
#region Private Fields
@@ -62,10 +64,10 @@ public static class QuickSwitch
6264
// Note: Here we do not start & stop the timer beacause when there are many dialog windows
6365
// Unhooking and hooking will take too much time which can make window position weird
6466
// So we start & stop the timer when we find a file dialog window
65-
/*private static HWINEVENTHOOK _moveSizeHook = HWINEVENTHOOK.Null;
67+
/*private static HWINEVENTHOOK _moveSizeHook = HWINEVENTHOOK.Null;*/
6668

67-
private static HWND _hookedDialogWindowHandle = HWND.Null;
68-
private static readonly object _hookedDialogWindowHandleLock = new();*/
69+
private static HWND _currentDialogWindowHandle = HWND.Null;
70+
private static readonly object _currentDialogWindowHandleLock = new();
6971

7072
private static bool _initialized = false;
7173
private static bool _enabled = false;
@@ -85,6 +87,9 @@ public static void InitializeQuickSwitch()
8587
_dragMoveTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(10) };
8688
_dragMoveTimer.Tick += (s, e) => InvokeUpdateQuickSwitchWindow();
8789

90+
// Initialize quick switch window position
91+
QuickSwitchWindowPosition = _settings.QuickSwitchWindowPosition;
92+
8893
_initialized = true;
8994
}
9095

@@ -240,18 +245,35 @@ private static unsafe void InvokeShowQuickSwitchWindow()
240245
// Show quick switch window
241246
if (_settings.ShowQuickSwitchWindow)
242247
{
248+
lock (_currentDialogWindowHandleLock)
249+
{
250+
var currentDialogWindowChanged = _currentDialogWindowHandle == HWND.Null ||
251+
_currentDialogWindowHandle != _dialogWindowHandle;
252+
253+
if (currentDialogWindowChanged)
254+
{
255+
// Save quick switch window position for one file dialog
256+
QuickSwitchWindowPosition = _settings.QuickSwitchWindowPosition;
257+
}
258+
259+
_currentDialogWindowHandle = _dialogWindowHandle;
260+
}
261+
243262
ShowQuickSwitchWindow?.Invoke(_dialogWindowHandle.Value);
244-
_dragMoveTimer?.Start();
263+
if (QuickSwitchWindowPosition == QuickSwitchWindowPositions.UnderDialog)
264+
{
265+
_dragMoveTimer?.Start();
266+
}
245267

246268
// Note: Here we do not start & stop the timer beacause when there are many dialog windows
247269
// Unhooking and hooking will take too much time which can make window position weird
248270
// So we start & stop the timer when we find a file dialog window
249-
/*lock (_hookedDialogWindowHandleLock)
271+
/*lock (_currentDialogWindowHandleLock)
250272
{
251-
var needHook = _hookedDialogWindowHandle == HWND.Null ||
252-
_hookedDialogWindowHandle != _dialogWindowHandle;
273+
var currentDialogWindowChanged = _currentDialogWindowHandle == HWND.Null ||
274+
_currentDialogWindowHandle != _dialogWindowHandle;
253275
254-
if (needHook)
276+
if (currentDialogWindowChanged)
255277
{
256278
if (!_moveSizeHook.IsNull)
257279
{
@@ -271,8 +293,6 @@ private static unsafe void InvokeShowQuickSwitchWindow()
271293
threadId,
272294
PInvoke.WINEVENT_OUTOFCONTEXT);
273295
}
274-
275-
_hookedDialogWindowHandle = _dialogWindowHandle;
276296
}*/
277297
}
278298
}
@@ -289,19 +309,19 @@ private static void InvokeResetQuickSwitchWindow()
289309
ResetQuickSwitchWindow?.Invoke();
290310
_dragMoveTimer?.Stop();
291311

292-
// Note: Here we do not start & stop the timer beacause when there are many dialog windows
293-
// Unhooking and hooking will take too much time which can make window position weird
294-
// So we start & stop the timer when we find a file dialog window
295-
/*lock (_hookedDialogWindowHandleLock)
312+
lock (_currentDialogWindowHandleLock)
296313
{
297-
if (!_moveSizeHook.IsNull)
314+
// Note: Here we do not start & stop the timer beacause when there are many dialog windows
315+
// Unhooking and hooking will take too much time which can make window position weird
316+
// So we start & stop the timer when we find a file dialog window
317+
/*if (!_moveSizeHook.IsNull)
298318
{
299319
PInvoke.UnhookWinEvent(_moveSizeHook);
300320
_moveSizeHook = HWINEVENTHOOK.Null;
301-
}
321+
}*/
302322

303-
_hookedDialogWindowHandle = HWND.Null;
304-
}*/
323+
_currentDialogWindowHandle = HWND.Null;
324+
}
305325
}
306326

307327
private static void InvokeHideQuickSwitchWindow()
@@ -375,7 +395,6 @@ uint dwmsEventTime
375395
else if (hwnd == _mainWindowHandle)
376396
{
377397
// Nothing to do
378-
Log.Debug(ClassName, $"Quick Switch Window: {hwnd}");
379398
}
380399
else
381400
{
@@ -730,6 +749,9 @@ public static void Dispose()
730749
PInvoke.UnhookWinEvent(_locationChangeHook);
731750
_locationChangeHook = HWINEVENTHOOK.Null;
732751
}
752+
// Note: Here we do not start & stop the timer beacause when there are many dialog windows
753+
// Unhooking and hooking will take too much time which can make window position weird
754+
// So we start & stop the timer when we find a file dialog window
733755
/*if (!_moveSizeHook.IsNull)
734756
{
735757
PInvoke.UnhookWinEvent(_moveSizeHook);

Flow.Launcher/MainWindow.xaml.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ private async void OnLoaded(object sender, RoutedEventArgs e)
196196
if (_viewModel.MainWindowVisibilityStatus)
197197
{
198198
// Play sound effect before activing the window
199-
if (_settings.UseSound && !_viewModel.IsQuickSwitch)
199+
if (_settings.UseSound && !_viewModel.IsQuickSwitchWindowUnderDialog())
200200
{
201201
SoundPlay();
202202
}
@@ -219,7 +219,7 @@ private async void OnLoaded(object sender, RoutedEventArgs e)
219219
QueryTextBox.Focus();
220220

221221
// Play window animation
222-
if (_settings.UseAnimation && !_viewModel.IsQuickSwitch)
222+
if (_settings.UseAnimation && !_viewModel.IsQuickSwitchWindowUnderDialog())
223223
{
224224
WindowAnimation();
225225
}
@@ -326,7 +326,7 @@ private void OnClosed(object sender, EventArgs e)
326326

327327
private void OnLocationChanged(object sender, EventArgs e)
328328
{
329-
if (_viewModel.IsQuickSwitch)
329+
if (_viewModel.IsQuickSwitchWindowUnderDialog())
330330
{
331331
return;
332332
}
@@ -340,7 +340,7 @@ private void OnLocationChanged(object sender, EventArgs e)
340340

341341
private async void OnDeactivated(object sender, EventArgs e)
342342
{
343-
if (_viewModel.IsQuickSwitch)
343+
if (_viewModel.IsQuickSwitchWindowUnderDialog())
344344
{
345345
return;
346346
}
@@ -483,7 +483,7 @@ private async void OnContextMenusForSettingsClick(object sender, RoutedEventArgs
483483

484484
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
485485
{
486-
if (_viewModel.IsQuickSwitch)
486+
if (_viewModel.IsQuickSwitchWindowUnderDialog())
487487
{
488488
return IntPtr.Zero;
489489
}
@@ -669,7 +669,7 @@ private void UpdateNotifyIconText()
669669

670670
public void UpdatePosition()
671671
{
672-
if (_viewModel.IsQuickSwitch)
672+
if (_viewModel.IsQuickSwitchWindowUnderDialog())
673673
{
674674
UpdateQuickSwitchPosition();
675675
}
@@ -1170,8 +1170,8 @@ private void InitializeQuickSwitch()
11701170

11711171
private void UpdateQuickSwitchPosition()
11721172
{
1173-
if (_viewModel.DialogWindowHandle == nint.Zero ||
1174-
!_viewModel.MainWindowVisibilityStatus) return;
1173+
if (_viewModel.DialogWindowHandle == nint.Zero || !_viewModel.MainWindowVisibilityStatus) return;
1174+
if (!_viewModel.IsQuickSwitchWindowUnderDialog()) return;
11751175

11761176
// Get dialog window rect
11771177
var result = Win32Helper.GetWindowRect(_viewModel.DialogWindowHandle, out var window);

Flow.Launcher/ViewModel/MainViewModel.cs

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,32 +1593,39 @@ public bool ShouldIgnoreHotkeys()
15931593

15941594
#region Quick Switch
15951595

1596-
public bool IsQuickSwitch { get; private set; } = false;
15971596
public nint DialogWindowHandle { get; private set; } = nint.Zero;
1598-
1597+
1598+
private bool IsQuickSwitch { get; set; } = false;
1599+
1600+
private static QuickSwitchWindowPositions QuickSwitchWindowPosition => QuickSwitch.QuickSwitchWindowPosition;
1601+
15991602
private bool PreviousMainWindowVisibilityStatus { get; set; }
1600-
private bool ResetWindowOnNextShow { get; set; } = false;
16011603

16021604
public void InitializeVisibilityStatus(bool visibilityStatus)
16031605
{
16041606
PreviousMainWindowVisibilityStatus = visibilityStatus;
16051607
}
16061608

1609+
public bool IsQuickSwitchWindowUnderDialog()
1610+
{
1611+
return IsQuickSwitch && QuickSwitchWindowPosition == QuickSwitchWindowPositions.UnderDialog;
1612+
}
1613+
16071614
#pragma warning disable VSTHRD100 // Avoid async void methods
16081615

16091616
public async void SetupQuickSwitch(nint handle)
16101617
{
16111618
if (handle == nint.Zero) return;
16121619

16131620
// Only set flag & reset window once for one file dialog
1614-
var needReset = false;
1621+
var dialogWindowHandleChanged = false;
16151622
if (DialogWindowHandle != handle)
16161623
{
16171624
PreviousMainWindowVisibilityStatus = MainWindowVisibilityStatus;
16181625
DialogWindowHandle = handle;
16191626
IsQuickSwitch = true;
16201627

1621-
needReset = true;
1628+
dialogWindowHandleChanged = true;
16221629

16231630
// Wait for a while to make sure the dialog is shown
16241631
// If don't give a time, Positioning will be weird
@@ -1630,27 +1637,34 @@ public async void SetupQuickSwitch(nint handle)
16301637

16311638
if (MainWindowVisibilityStatus)
16321639
{
1633-
// Only update the position
1634-
if (PreviousMainWindowVisibilityStatus)
1640+
if (dialogWindowHandleChanged)
16351641
{
1642+
// Only update the position
16361643
Application.Current?.Dispatcher.Invoke(() =>
16371644
{
16381645
(Application.Current?.MainWindow as MainWindow).UpdatePosition();
16391646
});
16401647

1641-
if (needReset)
1642-
{
1643-
_ = ResetWindowAsync();
1644-
}
1648+
_ = ResetWindowAsync();
16451649
}
16461650
}
16471651
else
16481652
{
1649-
Show();
1653+
if (QuickSwitchWindowPosition == QuickSwitchWindowPositions.UnderDialog)
1654+
{
1655+
Show();
16501656

1651-
if (needReset)
1657+
if (dialogWindowHandleChanged)
1658+
{
1659+
_ = ResetWindowAsync();
1660+
}
1661+
}
1662+
else
16521663
{
1653-
_ = ResetWindowAsync();
1664+
if (dialogWindowHandleChanged)
1665+
{
1666+
_ = ResetWindowAsync();
1667+
}
16541668
}
16551669
}
16561670
}
@@ -1692,7 +1706,7 @@ public async void ResetQuickSwitch()
16921706
}
16931707
else
16941708
{
1695-
ResetWindowOnNextShow = true;
1709+
_ = ResetWindowAsync();
16961710
}
16971711
}
16981712
}
@@ -1703,9 +1717,12 @@ public void HideQuickSwitch()
17031717
{
17041718
if (DialogWindowHandle != nint.Zero)
17051719
{
1706-
if (MainWindowVisibilityStatus)
1720+
if (QuickSwitchWindowPosition == QuickSwitchWindowPositions.UnderDialog)
17071721
{
1708-
Hide();
1722+
if (MainWindowVisibilityStatus)
1723+
{
1724+
Hide();
1725+
}
17091726
}
17101727
}
17111728
}
@@ -1773,12 +1790,6 @@ public void Show()
17731790
{
17741791
Win32Helper.SwitchToEnglishKeyboardLayout(true);
17751792
}
1776-
1777-
if (ResetWindowOnNextShow)
1778-
{
1779-
ResetWindowOnNextShow = false;
1780-
_ = ResetWindowAsync();
1781-
}
17821793
}
17831794

17841795
public async void Hide(bool reset = true)

0 commit comments

Comments
 (0)