From 428a657547998bef25f8b475a90ad50a51442b67 Mon Sep 17 00:00:00 2001 From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com> Date: Fri, 8 Mar 2024 16:24:32 +0900 Subject: [PATCH 1/7] Easy easy --- src/Files.App/MainWindow.xaml.cs | 4 ++++ src/Files.App/NativeMethods.txt | 1 + 2 files changed, 5 insertions(+) diff --git a/src/Files.App/MainWindow.xaml.cs b/src/Files.App/MainWindow.xaml.cs index f1fbbdd78def..b715f2176bdc 100644 --- a/src/Files.App/MainWindow.xaml.cs +++ b/src/Files.App/MainWindow.xaml.cs @@ -12,6 +12,7 @@ using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; using Windows.Storage; +using Windows.Win32; using WinUIEx; using IO = System.IO; @@ -189,6 +190,9 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) break; } + // Bring to foreground (#14730) + PInvoke.SetForegroundWindow(new(WindowHandle)); + if (!AppWindow.IsVisible) { // When resuming the cached instance diff --git a/src/Files.App/NativeMethods.txt b/src/Files.App/NativeMethods.txt index 91c0b8c3b6cf..80dfd73764d7 100644 --- a/src/Files.App/NativeMethods.txt +++ b/src/Files.App/NativeMethods.txt @@ -31,3 +31,4 @@ LPARAM WM_LBUTTONUP WM_RBUTTONUP WM_DESTROY +SetForegroundWindow From b170f29cf58e83c2d71c42621a1b9ac01e468002 Mon Sep 17 00:00:00 2001 From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com> Date: Sat, 9 Mar 2024 01:45:21 +0900 Subject: [PATCH 2/7] Update --- .../Helpers/Application/AppLifecycleHelper.cs | 20 +++++++++++++++++++ src/Files.App/MainWindow.xaml.cs | 9 +-------- src/Files.App/NativeMethods.txt | 7 +++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/Files.App/Helpers/Application/AppLifecycleHelper.cs b/src/Files.App/Helpers/Application/AppLifecycleHelper.cs index b2b9188dfb3a..8c28c6ab6c4c 100644 --- a/src/Files.App/Helpers/Application/AppLifecycleHelper.cs +++ b/src/Files.App/Helpers/Application/AppLifecycleHelper.cs @@ -18,6 +18,8 @@ using Windows.Storage; using Windows.System; using Windows.UI.Notifications; +using Windows.Win32; +using Windows.Win32.UI.WindowsAndMessaging; using LogLevel = Microsoft.Extensions.Logging.LogLevel; namespace Files.App.Helpers @@ -234,6 +236,24 @@ public static void SaveSessionTabs() .ToList(); } + public static unsafe void BringToForegroundEx(Windows.Win32.Foundation.HWND hWnd) + { + // https://stackoverflow.com/questions/1544179/what-are-the-differences-between-bringwindowtotop-setforegroundwindow-setwindo + // https://stackoverflow.com/questions/916259/win32-bring-a-window-to-top + var hCurWnd = PInvoke.GetForegroundWindow(); + var dwMyID = PInvoke.GetCurrentThreadId(); + var dwCurID = PInvoke.GetWindowThreadProcessId(hCurWnd); + + PInvoke.AttachThreadInput(dwCurID, dwMyID, true); + + PInvoke.SetWindowPos(hWnd, (Windows.Win32.Foundation.HWND)(-1), 0, 0, 0, 0, SET_WINDOW_POS_FLAGS.SWP_NOSIZE | SET_WINDOW_POS_FLAGS.SWP_NOMOVE); + PInvoke.SetWindowPos(hWnd, (Windows.Win32.Foundation.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); + } + /// /// Shows exception on the Debug Output and sends Toast Notification to the Windows Notification Center. /// diff --git a/src/Files.App/MainWindow.xaml.cs b/src/Files.App/MainWindow.xaml.cs index b715f2176bdc..aabd255d11bf 100644 --- a/src/Files.App/MainWindow.xaml.cs +++ b/src/Files.App/MainWindow.xaml.cs @@ -12,7 +12,6 @@ using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; using Windows.Storage; -using Windows.Win32; using WinUIEx; using IO = System.IO; @@ -94,7 +93,6 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) } else if (!(string.IsNullOrEmpty(launchArgs.Arguments) && MainPageViewModel.AppInstances.Count > 0)) { - InteropHelpers.SwitchToThisWindow(WindowHandle, true); await NavigationHelpers.AddNewTabByPathAsync(typeof(PaneHolderPage), launchArgs.Arguments, true); } else @@ -171,8 +169,6 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) rootFrame.Navigate(typeof(MainPage), fileArgs.Files.First().Path, new SuppressNavigationTransitionInfo()); index = 1; } - else - InteropHelpers.SwitchToThisWindow(WindowHandle, true); for (; index < fileArgs.Files.Count; index++) { await NavigationHelpers.AddNewTabByPathAsync(typeof(PaneHolderPage), fileArgs.Files[index].Path, true); @@ -191,7 +187,7 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) } // Bring to foreground (#14730) - PInvoke.SetForegroundWindow(new(WindowHandle)); + AppLifecycleHelper.BringToForegroundEx(new(WindowHandle)); if (!AppWindow.IsVisible) { @@ -248,10 +244,7 @@ async Task PerformNavigationAsync(string payload, string selectItem = null) }; if (rootFrame.Content is MainPage && MainPageViewModel.AppInstances.Any()) - { - InteropHelpers.SwitchToThisWindow(WindowHandle, true); await NavigationHelpers.AddNewTabByParamAsync(typeof(PaneHolderPage), paneNavigationArgs); - } else rootFrame.Navigate(typeof(MainPage), paneNavigationArgs, new SuppressNavigationTransitionInfo()); } diff --git a/src/Files.App/NativeMethods.txt b/src/Files.App/NativeMethods.txt index 80dfd73764d7..639d7971fd9d 100644 --- a/src/Files.App/NativeMethods.txt +++ b/src/Files.App/NativeMethods.txt @@ -32,3 +32,10 @@ WM_LBUTTONUP WM_RBUTTONUP WM_DESTROY SetForegroundWindow +GetForegroundWindow +GetCurrentThreadId +GetWindowThreadProcessId +AttachThreadInput +SetWindowPos +SetFocus +SetActiveWindow From 56bfc8fcc235db21c787c8f671d29c92b1a0b8f8 Mon Sep 17 00:00:00 2001 From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com> Date: Sat, 9 Mar 2024 01:49:42 +0900 Subject: [PATCH 3/7] Added xml comment --- .../Helpers/Application/AppLifecycleHelper.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Files.App/Helpers/Application/AppLifecycleHelper.cs b/src/Files.App/Helpers/Application/AppLifecycleHelper.cs index 8c28c6ab6c4c..cb90f8cef882 100644 --- a/src/Files.App/Helpers/Application/AppLifecycleHelper.cs +++ b/src/Files.App/Helpers/Application/AppLifecycleHelper.cs @@ -236,10 +236,19 @@ public static void SaveSessionTabs() .ToList(); } + /// + /// Brings the app window to foreground. + /// + /// + /// For more information, visit + ///
+ /// - + ///
+ /// -
+ ///
+ /// The window handle to bring. public static unsafe void BringToForegroundEx(Windows.Win32.Foundation.HWND hWnd) { - // https://stackoverflow.com/questions/1544179/what-are-the-differences-between-bringwindowtotop-setforegroundwindow-setwindo - // https://stackoverflow.com/questions/916259/win32-bring-a-window-to-top var hCurWnd = PInvoke.GetForegroundWindow(); var dwMyID = PInvoke.GetCurrentThreadId(); var dwCurID = PInvoke.GetWindowThreadProcessId(hCurWnd); From 438bdf621afff57fdd843002cd08788c0a27af29 Mon Sep 17 00:00:00 2001 From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com> Date: Sun, 10 Mar 2024 23:30:57 +0900 Subject: [PATCH 4/7] Update --- src/Files.App/MainWindow.xaml.cs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Files.App/MainWindow.xaml.cs b/src/Files.App/MainWindow.xaml.cs index aabd255d11bf..a5ed763ea576 100644 --- a/src/Files.App/MainWindow.xaml.cs +++ b/src/Files.App/MainWindow.xaml.cs @@ -93,6 +93,9 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) } else if (!(string.IsNullOrEmpty(launchArgs.Arguments) && MainPageViewModel.AppInstances.Count > 0)) { + // Bring to foreground (#14730) + AppLifecycleHelper.BringToForegroundEx(new(WindowHandle)); + await NavigationHelpers.AddNewTabByPathAsync(typeof(PaneHolderPage), launchArgs.Arguments, true); } else @@ -105,6 +108,12 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) if (eventArgs.Uri.AbsoluteUri == "files-uwp:") { rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo()); + + if (MainPageViewModel.AppInstances.Count > 0) + { + // Bring to foreground (#14730) + AppLifecycleHelper.BringToForegroundEx(new(WindowHandle)); + } } else { @@ -169,6 +178,12 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) rootFrame.Navigate(typeof(MainPage), fileArgs.Files.First().Path, new SuppressNavigationTransitionInfo()); index = 1; } + else + { + // Bring to foreground (#14730) + AppLifecycleHelper.BringToForegroundEx(new(WindowHandle)); + } + for (; index < fileArgs.Files.Count; index++) { await NavigationHelpers.AddNewTabByPathAsync(typeof(PaneHolderPage), fileArgs.Files[index].Path, true); @@ -186,9 +201,6 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) break; } - // Bring to foreground (#14730) - AppLifecycleHelper.BringToForegroundEx(new(WindowHandle)); - if (!AppWindow.IsVisible) { // When resuming the cached instance @@ -244,9 +256,16 @@ async Task PerformNavigationAsync(string payload, string selectItem = null) }; if (rootFrame.Content is MainPage && MainPageViewModel.AppInstances.Any()) + { + // Bring to foreground (#14730) + AppLifecycleHelper.BringToForegroundEx(new(WindowHandle)); + await NavigationHelpers.AddNewTabByParamAsync(typeof(PaneHolderPage), paneNavigationArgs); + } else + { rootFrame.Navigate(typeof(MainPage), paneNavigationArgs, new SuppressNavigationTransitionInfo()); + } } foreach (var command in parsedCommands) { From f86eb68c3a9169f186b9fc8e32c4b85c5c4724bb Mon Sep 17 00:00:00 2001 From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com> Date: Mon, 11 Mar 2024 00:08:59 +0900 Subject: [PATCH 5/7] Req --- src/Files.App/Helpers/Interop/InteropHelpers.cs | 3 --- src/Files.App/MainWindow.xaml.cs | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/Files.App/Helpers/Interop/InteropHelpers.cs b/src/Files.App/Helpers/Interop/InteropHelpers.cs index fb85c32589f1..753c0d8450b0 100644 --- a/src/Files.App/Helpers/Interop/InteropHelpers.cs +++ b/src/Files.App/Helpers/Interop/InteropHelpers.cs @@ -29,9 +29,6 @@ public static class InteropHelpers [DllImport("kernel32.dll")] public static extern bool SetEvent(IntPtr hEvent); - [DllImport("user32.dll", SetLastError = true)] - public static extern void SwitchToThisWindow(IntPtr hWnd, bool altTab); - [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int GetDpiForWindow(IntPtr hwnd); diff --git a/src/Files.App/MainWindow.xaml.cs b/src/Files.App/MainWindow.xaml.cs index a5ed763ea576..467dbd6786e9 100644 --- a/src/Files.App/MainWindow.xaml.cs +++ b/src/Files.App/MainWindow.xaml.cs @@ -263,9 +263,7 @@ async Task PerformNavigationAsync(string payload, string selectItem = null) await NavigationHelpers.AddNewTabByParamAsync(typeof(PaneHolderPage), paneNavigationArgs); } else - { rootFrame.Navigate(typeof(MainPage), paneNavigationArgs, new SuppressNavigationTransitionInfo()); - } } foreach (var command in parsedCommands) { From 798cfa4eaec72608b055905cad06de095199a8b8 Mon Sep 17 00:00:00 2001 From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com> Date: Mon, 11 Mar 2024 00:18:12 +0900 Subject: [PATCH 6/7] Update --- .../Helpers/Application/AppLifecycleHelper.cs | 29 -------------- .../Win32/Win32Helper.WindowManagement.cs | 38 +++++++++++++++++++ src/Files.App/MainWindow.xaml.cs | 8 ++-- 3 files changed, 42 insertions(+), 33 deletions(-) create mode 100644 src/Files.App/Helpers/Win32/Win32Helper.WindowManagement.cs diff --git a/src/Files.App/Helpers/Application/AppLifecycleHelper.cs b/src/Files.App/Helpers/Application/AppLifecycleHelper.cs index cb90f8cef882..b2b9188dfb3a 100644 --- a/src/Files.App/Helpers/Application/AppLifecycleHelper.cs +++ b/src/Files.App/Helpers/Application/AppLifecycleHelper.cs @@ -18,8 +18,6 @@ using Windows.Storage; using Windows.System; using Windows.UI.Notifications; -using Windows.Win32; -using Windows.Win32.UI.WindowsAndMessaging; using LogLevel = Microsoft.Extensions.Logging.LogLevel; namespace Files.App.Helpers @@ -236,33 +234,6 @@ public static void SaveSessionTabs() .ToList(); } - /// - /// Brings the app window to foreground. - /// - /// - /// For more information, visit - ///
- /// -
- ///
- /// -
- /// - /// The window handle to bring. - public static unsafe void BringToForegroundEx(Windows.Win32.Foundation.HWND hWnd) - { - var hCurWnd = PInvoke.GetForegroundWindow(); - var dwMyID = PInvoke.GetCurrentThreadId(); - var dwCurID = PInvoke.GetWindowThreadProcessId(hCurWnd); - - PInvoke.AttachThreadInput(dwCurID, dwMyID, true); - - PInvoke.SetWindowPos(hWnd, (Windows.Win32.Foundation.HWND)(-1), 0, 0, 0, 0, SET_WINDOW_POS_FLAGS.SWP_NOSIZE | SET_WINDOW_POS_FLAGS.SWP_NOMOVE); - PInvoke.SetWindowPos(hWnd, (Windows.Win32.Foundation.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); - } - /// /// Shows exception on the Debug Output and sends Toast Notification to the Windows Notification Center. /// diff --git a/src/Files.App/Helpers/Win32/Win32Helper.WindowManagement.cs b/src/Files.App/Helpers/Win32/Win32Helper.WindowManagement.cs new file mode 100644 index 000000000000..3799ad9e1f25 --- /dev/null +++ b/src/Files.App/Helpers/Win32/Win32Helper.WindowManagement.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +using Windows.Win32; +using Windows.Win32.UI.WindowsAndMessaging; + +namespace Files.App.Helpers +{ + public static class Win32Helper + { + /// + /// Brings the app window to foreground. + /// + /// + /// For more information, visit + ///
+ /// -
+ ///
+ /// -
+ /// + /// The window handle to bring. + public static unsafe void BringToForegroundEx(Windows.Win32.Foundation.HWND hWnd) + { + var hCurWnd = PInvoke.GetForegroundWindow(); + var dwMyID = PInvoke.GetCurrentThreadId(); + var dwCurID = PInvoke.GetWindowThreadProcessId(hCurWnd); + + PInvoke.AttachThreadInput(dwCurID, dwMyID, true); + + PInvoke.SetWindowPos(hWnd, (Windows.Win32.Foundation.HWND)(-1), 0, 0, 0, 0, SET_WINDOW_POS_FLAGS.SWP_NOSIZE | SET_WINDOW_POS_FLAGS.SWP_NOMOVE); + PInvoke.SetWindowPos(hWnd, (Windows.Win32.Foundation.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); + } + } +} diff --git a/src/Files.App/MainWindow.xaml.cs b/src/Files.App/MainWindow.xaml.cs index 467dbd6786e9..418f475e35a0 100644 --- a/src/Files.App/MainWindow.xaml.cs +++ b/src/Files.App/MainWindow.xaml.cs @@ -94,7 +94,7 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) else if (!(string.IsNullOrEmpty(launchArgs.Arguments) && MainPageViewModel.AppInstances.Count > 0)) { // Bring to foreground (#14730) - AppLifecycleHelper.BringToForegroundEx(new(WindowHandle)); + Win32Helper.BringToForegroundEx(new(WindowHandle)); await NavigationHelpers.AddNewTabByPathAsync(typeof(PaneHolderPage), launchArgs.Arguments, true); } @@ -112,7 +112,7 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) if (MainPageViewModel.AppInstances.Count > 0) { // Bring to foreground (#14730) - AppLifecycleHelper.BringToForegroundEx(new(WindowHandle)); + Win32Helper.BringToForegroundEx(new(WindowHandle)); } } else @@ -181,7 +181,7 @@ public async Task InitializeApplicationAsync(object activatedEventArgs) else { // Bring to foreground (#14730) - AppLifecycleHelper.BringToForegroundEx(new(WindowHandle)); + Win32Helper.BringToForegroundEx(new(WindowHandle)); } for (; index < fileArgs.Files.Count; index++) @@ -258,7 +258,7 @@ async Task PerformNavigationAsync(string payload, string selectItem = null) if (rootFrame.Content is MainPage && MainPageViewModel.AppInstances.Any()) { // Bring to foreground (#14730) - AppLifecycleHelper.BringToForegroundEx(new(WindowHandle)); + Win32Helper.BringToForegroundEx(new(WindowHandle)); await NavigationHelpers.AddNewTabByParamAsync(typeof(PaneHolderPage), paneNavigationArgs); } From c8036440e34375eae7759cbc64057419caac6973 Mon Sep 17 00:00:00 2001 From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com> Date: Mon, 11 Mar 2024 00:20:29 +0900 Subject: [PATCH 7/7] Partial marker --- src/Files.App/Helpers/Win32/Win32Helper.WindowManagement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Files.App/Helpers/Win32/Win32Helper.WindowManagement.cs b/src/Files.App/Helpers/Win32/Win32Helper.WindowManagement.cs index 3799ad9e1f25..63c7b335554d 100644 --- a/src/Files.App/Helpers/Win32/Win32Helper.WindowManagement.cs +++ b/src/Files.App/Helpers/Win32/Win32Helper.WindowManagement.cs @@ -6,7 +6,7 @@ namespace Files.App.Helpers { - public static class Win32Helper + public static partial class Win32Helper { /// /// Brings the app window to foreground.