using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; using System.Windows.Media; using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.Graphics.Dwm; using Windows.Win32.UI.WindowsAndMessaging; using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher.Infrastructure { public static class Win32Helper { #region Blur Handling public static bool IsBackdropSupported() { // Mica and Acrylic only supported Windows 11 22000+ return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version.Build >= 22000; } public static unsafe bool DWMSetCloakForWindow(Window window, bool cloak) { var cloaked = cloak ? 1 : 0; return PInvoke.DwmSetWindowAttribute( GetWindowHandle(window), DWMWINDOWATTRIBUTE.DWMWA_CLOAK, &cloaked, (uint)Marshal.SizeOf()).Succeeded; } public static unsafe bool DWMSetBackdropForWindow(Window window, BackdropTypes backdrop) { var backdropType = backdrop switch { BackdropTypes.Acrylic => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_TRANSIENTWINDOW, BackdropTypes.Mica => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_MAINWINDOW, BackdropTypes.MicaAlt => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_TABBEDWINDOW, _ => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_AUTO }; return PInvoke.DwmSetWindowAttribute( GetWindowHandle(window), DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, (uint)Marshal.SizeOf()).Succeeded; } public static unsafe bool DWMSetDarkModeForWindow(Window window, bool useDarkMode) { var darkMode = useDarkMode ? 1 : 0; return PInvoke.DwmSetWindowAttribute( GetWindowHandle(window), DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, &darkMode, (uint)Marshal.SizeOf()).Succeeded; } /// /// /// /// /// DoNotRound, Round, RoundSmall, Default /// public static unsafe bool DWMSetCornerPreferenceForWindow(Window window, string cornerType) { var preference = cornerType switch { "DoNotRound" => DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_DONOTROUND, "Round" => DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_ROUND, "RoundSmall" => DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_ROUNDSMALL, "Default" => DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_DEFAULT, _ => throw new InvalidOperationException("Invalid corner type") }; return PInvoke.DwmSetWindowAttribute( GetWindowHandle(window), DWMWINDOWATTRIBUTE.DWMWA_WINDOW_CORNER_PREFERENCE, &preference, (uint)Marshal.SizeOf()).Succeeded; } #endregion #region Wallpaper public static unsafe string GetWallpaperPath() { var wallpaperPtr = stackalloc char[(int)PInvoke.MAX_PATH]; PInvoke.SystemParametersInfo(SYSTEM_PARAMETERS_INFO_ACTION.SPI_GETDESKWALLPAPER, PInvoke.MAX_PATH, wallpaperPtr, 0); var wallpaper = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(wallpaperPtr); return wallpaper.ToString(); } #endregion #region Window Foreground public static nint GetForegroundWindow() { return PInvoke.GetForegroundWindow().Value; } public static bool SetForegroundWindow(Window window) { return PInvoke.SetForegroundWindow(GetWindowHandle(window)); } public static bool SetForegroundWindow(nint handle) { return PInvoke.SetForegroundWindow(new(handle)); } #endregion #region Task Switching /// /// Hide windows in the Alt+Tab window list /// /// To hide a window public static void HideFromAltTab(Window window) { var hwnd = GetWindowHandle(window); var exStyle = GetCurrentWindowStyle(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE); // Add TOOLWINDOW style, remove APPWINDOW style var newExStyle = ((uint)exStyle | (uint)WINDOW_EX_STYLE.WS_EX_TOOLWINDOW) & ~(uint)WINDOW_EX_STYLE.WS_EX_APPWINDOW; SetWindowLong(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)newExStyle); } /// /// Restore window display in the Alt+Tab window list. /// /// To restore the displayed window public static void ShowInAltTab(Window window) { var hwnd = GetWindowHandle(window); var exStyle = GetCurrentWindowStyle(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE); // Remove the TOOLWINDOW style and add the APPWINDOW style. var newExStyle = ((uint)exStyle & ~(uint)WINDOW_EX_STYLE.WS_EX_TOOLWINDOW) | (uint)WINDOW_EX_STYLE.WS_EX_APPWINDOW; SetWindowLong(GetWindowHandle(window), WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)newExStyle); } /// /// Disable windows toolbar's control box /// This will also disable system menu with Alt+Space hotkey /// public static void DisableControlBox(Window window) { var hwnd = GetWindowHandle(window); var style = GetCurrentWindowStyle(hwnd, WINDOW_LONG_PTR_INDEX.GWL_STYLE); style &= ~(int)WINDOW_STYLE.WS_SYSMENU; SetWindowLong(hwnd, WINDOW_LONG_PTR_INDEX.GWL_STYLE, style); } private static int GetCurrentWindowStyle(HWND hWnd, WINDOW_LONG_PTR_INDEX nIndex) { var style = PInvoke.GetWindowLong(hWnd, nIndex); if (style == 0 && Marshal.GetLastPInvokeError() != 0) { throw new Win32Exception(Marshal.GetLastPInvokeError()); } return style; } private static int SetWindowLong(HWND hWnd, WINDOW_LONG_PTR_INDEX nIndex, int dwNewLong) { PInvoke.SetLastError(WIN32_ERROR.NO_ERROR); // Clear any existing error var result = PInvoke.SetWindowLong(hWnd, nIndex, dwNewLong); if (result == 0 && Marshal.GetLastPInvokeError() != 0) { throw new Win32Exception(Marshal.GetLastPInvokeError()); } return result; } #endregion #region Window Fullscreen private const string WINDOW_CLASS_CONSOLE = "ConsoleWindowClass"; private const string WINDOW_CLASS_WINTAB = "Flip3D"; private const string WINDOW_CLASS_PROGMAN = "Progman"; private const string WINDOW_CLASS_WORKERW = "WorkerW"; private static HWND _hwnd_shell; private static HWND HWND_SHELL => _hwnd_shell != HWND.Null ? _hwnd_shell : _hwnd_shell = PInvoke.GetShellWindow(); private static HWND _hwnd_desktop; private static HWND HWND_DESKTOP => _hwnd_desktop != HWND.Null ? _hwnd_desktop : _hwnd_desktop = PInvoke.GetDesktopWindow(); public static unsafe bool IsForegroundWindowFullscreen() { // Get current active window var hWnd = PInvoke.GetForegroundWindow(); if (hWnd.Equals(HWND.Null)) { return false; } // If current active window is desktop or shell, exit early if (hWnd.Equals(HWND_DESKTOP) || hWnd.Equals(HWND_SHELL)) { return false; } string windowClass; const int capacity = 256; Span buffer = stackalloc char[capacity]; int validLength; fixed (char* pBuffer = buffer) { validLength = PInvoke.GetClassName(hWnd, pBuffer, capacity); } windowClass = buffer[..validLength].ToString(); // For Win+Tab (Flip3D) if (windowClass == WINDOW_CLASS_WINTAB) { return false; } PInvoke.GetWindowRect(hWnd, out var appBounds); // For console (ConsoleWindowClass), we have to check for negative dimensions if (windowClass == WINDOW_CLASS_CONSOLE) { return appBounds.top < 0 && appBounds.bottom < 0; } // For desktop (Progman or WorkerW, depends on the system), we have to check if (windowClass is WINDOW_CLASS_PROGMAN or WINDOW_CLASS_WORKERW) { var hWndDesktop = PInvoke.FindWindowEx(hWnd, HWND.Null, "SHELLDLL_DefView", null); hWndDesktop = PInvoke.FindWindowEx(hWndDesktop, HWND.Null, "SysListView32", "FolderView"); if (hWndDesktop.Value != IntPtr.Zero) { return false; } } var monitorInfo = MonitorInfo.GetNearestDisplayMonitor(hWnd); return (appBounds.bottom - appBounds.top) == monitorInfo.RectMonitor.Height && (appBounds.right - appBounds.left) == monitorInfo.RectMonitor.Width; } #endregion #region Pixel to DIP /// /// Transforms pixels to Device Independent Pixels used by WPF /// /// current window, required to get presentation source /// horizontal position in pixels /// vertical position in pixels /// point containing device independent pixels public static Point TransformPixelsToDIP(Visual visual, double unitX, double unitY) { Matrix matrix; var source = PresentationSource.FromVisual(visual); if (source is not null) { matrix = source.CompositionTarget.TransformFromDevice; } else { using var src = new HwndSource(new HwndSourceParameters()); matrix = src.CompositionTarget.TransformFromDevice; } return new Point((int)(matrix.M11 * unitX), (int)(matrix.M22 * unitY)); } #endregion #region WndProc public static bool WM_ENTERSIZEMOVE(int msg) { return msg == (int)PInvoke.WM_ENTERSIZEMOVE; } public static bool WM_EXITSIZEMOVE(int msg) { return msg == (int)PInvoke.WM_EXITSIZEMOVE; } #endregion #region Window Handle internal static HWND GetWindowHandle(Window window, bool ensure = false) { var windowHelper = new WindowInteropHelper(window); if (ensure) { windowHelper.EnsureHandle(); } return new(windowHelper.Handle); } #endregion } }