diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/MainWindow.xaml.cs b/src/modules/fancyzones/editor/FancyZonesEditor/MainWindow.xaml.cs index 687895021b..b3476ed4d9 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/MainWindow.xaml.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/MainWindow.xaml.cs @@ -5,11 +5,13 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Runtime.InteropServices; using System.Windows; using System.Windows.Automation; using System.Windows.Automation.Peers; using System.Windows.Controls; using System.Windows.Input; +using System.Windows.Interop; using Common.UI; using FancyZonesEditor.Models; using FancyZonesEditor.Utils; @@ -34,6 +36,8 @@ namespace FancyZonesEditor private ContentDialog _openedDialog; private TextBlock _createLayoutAnnounce; + private bool haveTriedToGetFocusAlready; + public int WrapPanelItemSize { get; set; } = DefaultWrapPanelItemSize; public MainWindow(bool spanZonesAcrossMonitors, Rect workArea) @@ -63,6 +67,42 @@ namespace FancyZonesEditor _settings.InitModels(); } + private void BringToFront() + { + // Get the window handle of the FancyZones Editor window + IntPtr handle = new WindowInteropHelper(this).Handle; + + // Get the handle of the window currently in the foreground + IntPtr foregroundWindowHandle = NativeMethods.GetForegroundWindow(); + + // Get the thread IDs of the current thread and the thread of the foreground window + uint currentThreadId = NativeMethods.GetCurrentThreadId(); + uint activeThreadId = NativeMethods.GetWindowThreadProcessId(foregroundWindowHandle, IntPtr.Zero); + + // Check if the active thread is different from the current thread + if (activeThreadId != currentThreadId) + { + // Attach the input processing mechanism of the current thread to the active thread + NativeMethods.AttachThreadInput(activeThreadId, currentThreadId, true); + + // Set the FancyZones Editor window as the foreground window + NativeMethods.SetForegroundWindow(handle); + + // Detach the input processing mechanism of the current thread from the active thread + NativeMethods.AttachThreadInput(activeThreadId, currentThreadId, false); + } + else + { + // Set the FancyZones Editor window as the foreground window + NativeMethods.SetForegroundWindow(handle); + } + + // Bring the FancyZones Editor window to the foreground and activate it + NativeMethods.SwitchToThisWindow(handle, true); + + haveTriedToGetFocusAlready = true; + } + public void Update() { DataContext = _settings; @@ -408,6 +448,11 @@ namespace FancyZonesEditor // This is required to fix a WPF rendering bug when using custom chrome private void OnContentRendered(object sender, EventArgs e) { + if (!haveTriedToGetFocusAlready) + { + BringToFront(); + } + InvalidateVisual(); } diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/NativeMethods.cs b/src/modules/fancyzones/editor/FancyZonesEditor/NativeMethods.cs index 944b75d539..d246bb86f3 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/NativeMethods.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/NativeMethods.cs @@ -15,5 +15,24 @@ namespace FancyZonesEditor [DllImport("kernel32", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetForegroundWindow(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); + + [DllImport("user32.dll")] + public static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll")] + public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr processId); + + [DllImport("kernel32.dll")] + public static extern uint GetCurrentThreadId(); + + [DllImport("user32.dll")] + public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); } }