Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion Flow.Launcher.Infrastructure/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,13 @@ EVENT_OBJECT_HIDE
EVENT_SYSTEM_DIALOGEND

WM_POWERBROADCAST
PBT_APMRESUMEAUTOMATIC
PBT_APMRESUMEAUTOMATIC

SetForegroundWindow
GetForegroundWindow
GetCurrentThreadId
GetWindowThreadProcessId
AttachThreadInput
SetWindowPos
SetFocus
SetActiveWindow
36 changes: 35 additions & 1 deletion Flow.Launcher.Infrastructure/Win32Helper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
Expand All @@ -18,7 +18,7 @@
using Microsoft.Win32.SafeHandles;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.Graphics.Dwm;

Check warning on line 21 in Flow.Launcher.Infrastructure/Win32Helper.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`Dwm` is not a recognized word. (unrecognized-spelling)
using Windows.Win32.System.Threading;
using Windows.Win32.UI.Input.KeyboardAndMouse;
using Windows.Win32.UI.Shell.Common;
Expand All @@ -43,7 +43,7 @@
{
var cloaked = cloak ? 1 : 0;

return PInvoke.DwmSetWindowAttribute(

Check warning on line 46 in Flow.Launcher.Infrastructure/Win32Helper.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`Dwm` is not a recognized word. (unrecognized-spelling)
GetWindowHandle(window),
DWMWINDOWATTRIBUTE.DWMWA_CLOAK,
&cloaked,
Expand All @@ -54,13 +54,13 @@
{
var backdropType = backdrop switch
{
BackdropTypes.Acrylic => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_TRANSIENTWINDOW,

Check warning on line 57 in Flow.Launcher.Infrastructure/Win32Helper.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`SYSTEMBACKDROP` is not a recognized word. (unrecognized-spelling)
BackdropTypes.Mica => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_MAINWINDOW,

Check warning on line 58 in Flow.Launcher.Infrastructure/Win32Helper.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`SYSTEMBACKDROP` is not a recognized word. (unrecognized-spelling)

Check warning on line 58 in Flow.Launcher.Infrastructure/Win32Helper.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`DWMSBT` is not a recognized word. (unrecognized-spelling)
BackdropTypes.MicaAlt => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_TABBEDWINDOW,

Check warning on line 59 in Flow.Launcher.Infrastructure/Win32Helper.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`SYSTEMBACKDROP` is not a recognized word. (unrecognized-spelling)

Check warning on line 59 in Flow.Launcher.Infrastructure/Win32Helper.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`DWMSBT` is not a recognized word. (unrecognized-spelling)
_ => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_AUTO

Check warning on line 60 in Flow.Launcher.Infrastructure/Win32Helper.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`SYSTEMBACKDROP` is not a recognized word. (unrecognized-spelling)

Check warning on line 60 in Flow.Launcher.Infrastructure/Win32Helper.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`DWMSBT` is not a recognized word. (unrecognized-spelling)
};

return PInvoke.DwmSetWindowAttribute(

Check warning on line 63 in Flow.Launcher.Infrastructure/Win32Helper.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`Dwm` is not a recognized word. (unrecognized-spelling)
GetWindowHandle(window),
DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE,
&backdropType,
Expand Down Expand Up @@ -151,6 +151,40 @@
return handle.Equals(PInvoke.GetForegroundWindow());
}

/// <summary>
/// Brings the window to foreground if window is visible. From https://github.com/files-community/Files.
/// </summary>
/// <remarks>
/// For more information, visit
/// <br/>
/// - <a href="https://stackoverflow.com/questions/1544179/what-are-the-differences-between-bringwindowtotop-setforegroundwindow-setwindo" />
/// <br/>
/// - <a href="https://stackoverflow.com/questions/916259/win32-bring-a-window-to-top" />
/// </remarks>
/// <param name="window">The window to bring.</param>
public static unsafe void BringToForegroundEx(Window window)
{
var hWnd = GetWindowHandle(window);
var topMost = window.Topmost;
var hCurWnd = PInvoke.GetForegroundWindow();
var dwMyID = PInvoke.GetCurrentThreadId();
var dwCurID = PInvoke.GetWindowThreadProcessId(hCurWnd);

PInvoke.AttachThreadInput(dwCurID, dwMyID, true);

// Set the window to be the topmost window
PInvoke.SetWindowPos(hWnd, (HWND)(-1), 0, 0, 0, 0, SET_WINDOW_POS_FLAGS.SWP_NOSIZE | SET_WINDOW_POS_FLAGS.SWP_NOMOVE);
if (!topMost)
{
// Restore the window to its original position
PInvoke.SetWindowPos(hWnd, (HWND)(-2), 0, 0, 0, 0, SET_WINDOW_POS_FLAGS.SWP_SHOWWINDOW | SET_WINDOW_POS_FLAGS.SWP_NOSIZE | SET_WINDOW_POS_FLAGS.SWP_NOMOVE);
}
PInvoke.SetForegroundWindow(hWnd);
PInvoke.SetFocus(hWnd);
PInvoke.SetActiveWindow(hWnd);
PInvoke.AttachThreadInput(dwCurID, dwMyID, false);
}

#endregion

#region Task Switching
Expand Down
1 change: 1 addition & 0 deletions Flow.Launcher/ViewModel/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2249,6 +2249,7 @@ public void FocusQueryTextBox()
// When application is exiting, the Application.Current will be null
if (Application.Current?.MainWindow is MainWindow window)
{
Win32Helper.BringToForegroundEx(window);
window.QueryTextBox.Focus();
Keyboard.Focus(window.QueryTextBox);
}
Expand Down
6 changes: 3 additions & 3 deletions Plugins/Flow.Launcher.Plugin.Shell/Main.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
Expand Down Expand Up @@ -412,11 +412,11 @@ private void OnWinRPressed()
_ = Task.Run(async () =>
{
Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}");

// Win+R is a system-reserved shortcut, and though the plugin intercepts the keyboard event and
// shows the main window, Windows continues to process the Win key and briefly reclaims focus.
// So we need to wait until the keyboard event processing is completed and then set focus
await Task.Delay(50);
await Task.Delay(1000);
Context.API.FocusQueryTextBox();
Comment on lines +419 to 420
Copy link
Preview

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The delay has been increased from 50ms to 1000ms, which is a 20x increase. This significantly impacts user experience by making the application feel unresponsive. Consider a more moderate increase (e.g., 100-200ms) or implement a retry mechanism with shorter delays.

Suggested change
await Task.Delay(1000);
Context.API.FocusQueryTextBox();
// Try to set focus up to 4 times with 50ms intervals (max 200ms)
for (int i = 0; i < 4; i++)
{
await Task.Delay(50);
Context.API.FocusQueryTextBox();
}

Copilot uses AI. Check for mistakes.

});
}
Expand Down
Loading