Skip to content

Fix: Ensure QueryTextBox receives focus after Win+R & new FocusQueryTextBox api function #3568

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 22, 2025
Merged
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
5 changes: 5 additions & 0 deletions Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@
/// Show the MainWindow when hiding
/// </summary>
void ShowMainWindow();

/// <summary>
/// Focus the query text box in the main window
/// </summary>
void FocusQueryTextBox();

/// <summary>
/// Hide MainWindow
Expand Down Expand Up @@ -202,7 +207,7 @@
Task<string> HttpGetStringAsync(string url, CancellationToken token = default);

/// <summary>
/// Http download the spefic url and return as stream

Check warning on line 210 in Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`spefic` is not a recognized word. (unrecognized-spelling)
/// </summary>
/// <param name="url">URL to call Http Get</param>
/// <param name="token">Cancellation Token</param>
Expand Down Expand Up @@ -343,7 +348,7 @@

/// <summary>
/// Reloads the query.
/// When current results are from context menu or history, it will go back to query results before requerying.

Check warning on line 351 in Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`requerying` is not a recognized word. (unrecognized-spelling)
/// </summary>
/// <param name="reselect">Choose the first result after reload if true; keep the last selected result if false. Default is true.</param>
public void ReQuery(bool reselect = true);
Expand Down
5 changes: 4 additions & 1 deletion Flow.Launcher/PublicAPIInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
Expand All @@ -10,6 +11,7 @@
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Core;
Expand All @@ -32,7 +34,6 @@
using JetBrains.Annotations;
using Squirrel;
using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
using System.ComponentModel;

namespace Flow.Launcher
{
Expand All @@ -49,7 +50,7 @@

// Must use getter to avoid circular dependency
private Updater _updater;
private Updater Updater => _updater ??= Ioc.Default.GetRequiredService<Updater>();

Check warning on line 53 in Flow.Launcher/PublicAPIInstance.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

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

private readonly object _saveSettingsLock = new();

Expand Down Expand Up @@ -93,6 +94,8 @@

public void ShowMainWindow() => _mainVM.Show();

public void FocusQueryTextBox() => _mainVM.FocusQueryTextBox();

public void HideMainWindow() => _mainVM.Hide();

public bool IsMainWindowVisible() => _mainVM.MainWindowVisibilityStatus;
Expand Down Expand Up @@ -145,7 +148,7 @@
ShellCommand.Execute(startInfo);
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")]

Check warning on line 151 in Flow.Launcher/PublicAPIInstance.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`VSTHRD` is not a recognized word. (unrecognized-spelling)
public async void CopyToClipboard(string stringToCopy, bool directCopy = false, bool showDefaultNotification = true)
{
if (string.IsNullOrEmpty(stringToCopy))
Expand Down
15 changes: 15 additions & 0 deletions Flow.Launcher/ViewModel/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
_lastQuery = new Query();
_ignoredQueryText = null; // null as invalid value

Settings = Ioc.Default.GetRequiredService<Settings>();

Check warning on line 72 in Flow.Launcher/ViewModel/MainViewModel.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`Ioc` is not a recognized word. (unrecognized-spelling)
Settings.PropertyChanged += (_, args) =>
{
switch (args.PropertyName)
Expand Down Expand Up @@ -1724,7 +1724,7 @@

#region Public Methods

#pragma warning disable VSTHRD100 // Avoid async void methods

Check warning on line 1727 in Flow.Launcher/ViewModel/MainViewModel.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

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

public void Show()
{
Expand Down Expand Up @@ -1842,7 +1842,7 @@
VisibilityChanged?.Invoke(this, new VisibilityChangedEventArgs { IsVisible = false });
}

#pragma warning restore VSTHRD100 // Avoid async void methods

Check warning on line 1845 in Flow.Launcher/ViewModel/MainViewModel.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

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

/// <summary>
/// Save history, user selected records and top most records
Expand Down Expand Up @@ -1926,6 +1926,21 @@
Results.AddResults(resultsForUpdates, token, reSelect);
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "<Pending>")]
public void FocusQueryTextBox()
{
// When application is exiting, the Application.Current will be null
Application.Current?.Dispatcher.Invoke(() =>
{
// When application is exiting, the Application.Current will be null
if (Application.Current?.MainWindow is MainWindow window)
{
window.QueryTextBox.Focus();
Keyboard.Focus(window.QueryTextBox);
}
});
}

#endregion

#region IDisposable
Expand Down
10 changes: 8 additions & 2 deletions Plugins/Flow.Launcher.Plugin.Shell/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@
string basedir = null;
string dir = null;
string excmd = Environment.ExpandEnvironmentVariables(cmd);
if (Directory.Exists(excmd) && (cmd.EndsWith("/") || cmd.EndsWith(@"\")))

Check warning on line 48 in Plugins/Flow.Launcher.Plugin.Shell/Main.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`excmd` is not a recognized word. (unrecognized-spelling)
{
basedir = excmd;

Check warning on line 50 in Plugins/Flow.Launcher.Plugin.Shell/Main.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`excmd` is not a recognized word. (unrecognized-spelling)
dir = cmd;
}
else if (Directory.Exists(Path.GetDirectoryName(excmd) ?? string.Empty))

Check warning on line 53 in Plugins/Flow.Launcher.Plugin.Shell/Main.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`excmd` is not a recognized word. (unrecognized-spelling)
{
basedir = Path.GetDirectoryName(excmd);
var dirName = Path.GetDirectoryName(cmd);
Expand Down Expand Up @@ -378,11 +378,17 @@

private void OnWinRPressed()
{
Context.API.ShowMainWindow();
// show the main window and set focus to the query box
_ = Task.Run(() =>
_ = Task.Run(async () =>
{
Context.API.ShowMainWindow();
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);
Context.API.FocusQueryTextBox();
});
}

Expand Down
Loading