From f8d963161c89167e8e281c63dfb5a880bbfb455a Mon Sep 17 00:00:00 2001 From: Lamparter <71598437+Lamparter@users.noreply.github.com> Date: Sun, 19 Jul 2026 21:33:12 +0100 Subject: [PATCH 1/2] Fix --- src/Files.App/MainWindow.xaml.cs | 68 ++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/src/Files.App/MainWindow.xaml.cs b/src/Files.App/MainWindow.xaml.cs index b5bf7fd00115..6a71699a951a 100644 --- a/src/Files.App/MainWindow.xaml.cs +++ b/src/Files.App/MainWindow.xaml.cs @@ -1,6 +1,7 @@ // Copyright (c) Files Community // Licensed under the MIT License. +using Files.Shared.Helpers; using Microsoft.Extensions.Logging; using Microsoft.UI; using Microsoft.UI.Windowing; @@ -107,13 +108,24 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) } else { - var parsedArgs = eventArgs.Uri.Query.TrimStart('?').Split('='); - var unescapedValue = Uri.UnescapeDataString(parsedArgs[1].Split('&')[0]); - if (parsedArgs[0] == "tab" && parsedArgs.Length > 3 && - int.TryParse(parsedArgs[2].Split('&')[0], out var dx) && - int.TryParse(parsedArgs[3], out var dy)) - AppWindow?.Move(new(dx - 100, dy - 16)); - var folder = (StorageFolder)await FilesystemTasks.Wrap(() => StorageFolder.GetFolderFromPathAsync(unescapedValue).AsTask()); + string[] parsedArgs; + string? unescapedValue; + StorageFolder? folder; + try + { + parsedArgs = eventArgs.Uri.Query.TrimStart('?').Split('='); + unescapedValue = Uri.UnescapeDataString(parsedArgs[1].Split('&')[0]); + if (parsedArgs[0] == "tab" && parsedArgs.Length > 3 && + int.TryParse(parsedArgs[2].Split('&')[0], out var dx) && + int.TryParse(parsedArgs[3], out var dy)) + AppWindow?.Move(new(dx - 100, dy - 16)); + folder = (StorageFolder)await FilesystemTasks.Wrap(() => StorageFolder.GetFolderFromPathAsync(unescapedValue).AsTask()); + } + catch + { + rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); + break; + } if (folder is not null && !string.IsNullOrEmpty(folder.Path)) { // Convert short name to long name (#6190) @@ -262,6 +274,7 @@ private async Task EnsureContentHasKeyboardFocusAsync() private async Task InitializeFromCmdLineArgsAsync(Frame rootFrame, ParsedCommands parsedCommands, string activationPath = "") { + // Navigate to a folder in the UI async Task PerformNavigationAsync(string payload, string selectItem = null) { if (!string.IsNullOrEmpty(payload)) @@ -315,12 +328,42 @@ x.tabItem.NavigationParameter.NavigationParameter is PaneNavigationArguments pan else rootFrame.Navigate(typeof(MainPage), paneNavigationArgs, new SuppressNavigationTransitionInfo()); } + + // Open a path (navigate to a folder in the UI / open a file depending on what the path attributes are) + async Task OpenPathAsync(string payload) + { + if (!string.IsNullOrEmpty(payload)) + { + try + { + var target = Path.IsPathFullyQualified(payload) ? IO.Path.GetFullPath(payload) : IO.Path.GetFullPath(IO.Path.Combine(activationPath, payload)); + var attributes = IO.File.GetAttributes(target); + if (attributes.HasFlag(IO.FileAttributes.Directory) || FileExtensionHelpers.IsBrowsableZipFile(target, out _)) + await PerformNavigationAsync(target); + else + await LaunchHelper.LaunchAppAsync("explorer", payload, activationPath); + } + catch + { + await LaunchHelper.LaunchAppAsync("explorer", payload, activationPath); + } + } + else + { + await PerformNavigationAsync(null!); + } + } + foreach (var command in parsedCommands) { switch (command.Type) { case ParsedCommandType.OpenDirectory: + await OpenPathAsync(command.Payload); + break; case ParsedCommandType.OpenPath: + await OpenPathAsync(command.Payload); + break; case ParsedCommandType.ExplorerShellCommand: var selectItemCommand = parsedCommands.FirstOrDefault(x => x.Type == ParsedCommandType.SelectItem); await PerformNavigationAsync(command.Payload, selectItemCommand?.Payload); @@ -355,15 +398,8 @@ x.tabItem.NavigationParameter.NavigationParameter is PaneNavigationArguments pan } else { - if (!string.IsNullOrEmpty(command.Payload)) - { - var target = IO.Path.GetFullPath(IO.Path.Combine(activationPath, command.Payload)); - await PerformNavigationAsync(target); - } - else - { - await PerformNavigationAsync(null); - } + await OpenPathAsync(command.Payload); + break; } break; From 2e57bb0827fbcce0cf03eb4aff2a6ea76aeeba22 Mon Sep 17 00:00:00 2001 From: Lamparter <71598437+Lamparter@users.noreply.github.com> Date: Sun, 19 Jul 2026 21:53:45 +0100 Subject: [PATCH 2/2] Bring app to foreground on URI activation and fix nullable annotations --- src/Files.App/MainWindow.xaml.cs | 45 ++++++++++++++++---------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/Files.App/MainWindow.xaml.cs b/src/Files.App/MainWindow.xaml.cs index 6a71699a951a..e36fdcb666e6 100644 --- a/src/Files.App/MainWindow.xaml.cs +++ b/src/Files.App/MainWindow.xaml.cs @@ -72,7 +72,7 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) // WINUI3: When launching from commandline the argument is not ICommandLineActivatedEventArgs (#10370) var ppm = CommandLineParser.ParseUntrustedCommands(launchArgs.Arguments); if (ppm.IsEmpty()) - rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); + LaunchMainPage(rootFrame); else await InitializeFromCmdLineArgsAsync(rootFrame, ppm, Program.ConsumeLaunchCwd()); } @@ -91,20 +91,14 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) } else { - rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); + LaunchMainPage(rootFrame); } break; case IProtocolActivatedEventArgs eventArgs: if (eventArgs.Uri.AbsoluteUri == "files-dev:") { - rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); - - // Bring to foreground (#14730) - Win32Helper.BringToForegroundEx(new(WindowHandle)); - - // Ensure app-level keyboard shortcuts work immediately after Win+E activation. - _ = EnsureContentHasKeyboardFocusAsync(); + LaunchMainPage(rootFrame); } else { @@ -123,7 +117,7 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) } catch { - rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); + LaunchMainPage(rootFrame); break; } if (folder is not null && !string.IsNullOrEmpty(folder.Path)) @@ -148,12 +142,12 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) case "cmd": var ppm = CommandLineParser.ParseUntrustedCommands(unescapedValue); if (ppm.IsEmpty()) - rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); + LaunchMainPage(rootFrame); else await InitializeFromCmdLineArgsAsync(rootFrame, ppm, Environment.CurrentDirectory); break; default: - rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); + LaunchMainPage(rootFrame); break; } } @@ -171,7 +165,7 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) } else { - rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); + LaunchMainPage(rootFrame); } break; @@ -212,14 +206,8 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) } break; - case IStartupTaskActivatedEventArgs startupArgs: - // Just launch the app with no arguments - rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); - break; - default: - // Just launch the app with no arguments - rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); + LaunchMainPage(rootFrame); break; } @@ -275,11 +263,11 @@ private async Task EnsureContentHasKeyboardFocusAsync() private async Task InitializeFromCmdLineArgsAsync(Frame rootFrame, ParsedCommands parsedCommands, string activationPath = "") { // Navigate to a folder in the UI - async Task PerformNavigationAsync(string payload, string selectItem = null) + async Task PerformNavigationAsync(string? payload, string? selectItem = null) { if (!string.IsNullOrEmpty(payload)) { - payload = Constants.UserEnvironmentPaths.ShellPlaces.Get(payload.ToUpperInvariant(), payload); + payload = Constants.UserEnvironmentPaths.ShellPlaces.Get(payload.ToUpperInvariant(), payload)!; var folder = (StorageFolder)await FilesystemTasks.Wrap(() => StorageFolder.GetFolderFromPathAsync(payload).AsTask()); if (folder is not null && !string.IsNullOrEmpty(folder.Path)) payload = folder.Path; // Convert short name to long name (#6190) @@ -376,7 +364,7 @@ async Task OpenPathAsync(string payload) case ParsedCommandType.TagFiles: var tagService = Ioc.Default.GetService(); - var tag = tagService.GetTagsByName(command.Payload).FirstOrDefault(); + var tag = tagService!.GetTagsByName(command.Payload).FirstOrDefault(); foreach (var file in command.Args.Skip(1)) { var fileFRN = await FilesystemTasks.Wrap(() => StorageHelpers.ToStorageItem(file)) @@ -431,5 +419,16 @@ private void WindowManager_WindowMessageReceived(object? sender, WinUIEx.Messagi e.Handled = true; } } + + private void LaunchMainPage(Frame rootFrame) + { + rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); + + // Bring to foreground (#14730) + Win32Helper.BringToForegroundEx(new(WindowHandle)); + + // Ensure app-level keyboard shortcuts work immediately after Win+E activation. + _ = EnsureContentHasKeyboardFocusAsync(); + } } }