char-slop/ai-dots
ai dotfiles
git clone https://git.t4t.associates/char-slop/ai-dots
dc2c12a
main
1using System ; 2using System . Collections . Generic ; 3using System . ComponentModel ; 4using System . Diagnostics ; 5using System . Drawing ; 6using System . Drawing . Drawing2D ; 7using System . Drawing . Imaging ; 8using System . IO ; 9using System . Runtime . InteropServices ; 10 11public static class PiDesktop 12{ 13[ StructLayout ( LayoutKind . Sequential )] 14struct MouseInput 15{ 16public int dx , dy ; 17public uint mouseData , flags , time ; 18public UIntPtr extraInfo ; 19} 20 21[ StructLayout ( LayoutKind . Sequential )] 22struct KeyboardInput 23{ 24public ushort vk , scan ; 25public uint flags , time ; 26public UIntPtr extraInfo ; 27} 28 29[ StructLayout ( LayoutKind . Explicit )] 30struct InputUnion 31{ 32[ FieldOffset ( 0 )] public MouseInput mouse ; 33[ FieldOffset ( 0 )] public KeyboardInput keyboard ; 34} 35 36[ StructLayout ( LayoutKind . Sequential )] 37struct Input 38{ 39public uint type ; 40public InputUnion data ; 41} 42 43[ StructLayout ( LayoutKind . Sequential )] 44struct Point { public int x , y ; } 45 46[ StructLayout ( LayoutKind . Sequential )] 47struct CursorInfo 48{ 49public uint size , flags ; 50public IntPtr cursor ; 51public Point position ; 52} 53 54[ StructLayout ( LayoutKind . Sequential )] 55struct IconInfo 56{ 57public int isIcon ; 58public uint xHotspot , yHotspot ; 59public IntPtr mask , color ; 60} 61 62[ DllImport ( "user32.dll" , SetLastError = true )] 63static extern uint SendInput ( uint count , Input [] inputs , int size ); 64[ DllImport ( "user32.dll" )] 65static extern int GetSystemMetrics ( int index ); 66[ DllImport ( "user32.dll" )] 67static extern bool SetProcessDPIAware (); 68[ DllImport ( "user32.dll" )] 69static extern IntPtr SetThreadDpiAwarenessContext ( IntPtr context ); 70[ DllImport ( "user32.dll" , CharSet = CharSet . Unicode )] 71static extern short VkKeyScanEx ( char ch , IntPtr layout ); 72[ DllImport ( "user32.dll" )] 73static extern IntPtr GetKeyboardLayout ( uint threadId ); 74[ DllImport ( "user32.dll" )] 75static extern IntPtr GetForegroundWindow (); 76[ DllImport ( "user32.dll" )] 77static extern uint GetWindowThreadProcessId ( IntPtr window , IntPtr processId ); 78[ DllImport ( "user32.dll" )] 79static extern bool GetCursorInfo ( ref CursorInfo info ); 80[ DllImport ( "user32.dll" )] 81static extern bool GetIconInfo ( IntPtr icon , out IconInfo info ); 82[ DllImport ( "user32.dll" )] 83static extern bool DrawIconEx ( IntPtr dc , int x , int y , IntPtr icon , 84int width , int height , uint step , IntPtr brush , uint flags ); 85[ DllImport ( "gdi32.dll" )] 86static extern bool DeleteObject ( IntPtr obj ); 87 88static int heldButtons ; 89static readonly List < ushort > heldKeys = new List < ushort > (); 90static readonly Dictionary < string , ushort > modifiers = new Dictionary < string , ushort > 91{ 92{ "shift" , 0x10 }, { "ctrl" , 0x11 }, { "alt" , 0x12 }, { "logo" , 0x5b } 93}; 94static readonly Dictionary < string , ushort > namedKeys = new Dictionary < string , ushort > 95{ 96{ "Return" , 0x0d }, { "Enter" , 0x0d }, { "Escape" , 0x1b }, { "Esc" , 0x1b }, 97{ "Tab" , 0x09 }, { "BackSpace" , 0x08 }, { "Backspace" , 0x08 }, 98{ "Delete" , 0x2e }, { "Del" , 0x2e }, { "Insert" , 0x2d }, { "Ins" , 0x2d }, 99{ "space" , 0x20 }, { "Left" , 0x25 }, { "Right" , 0x27 }, { "Up" , 0x26 }, 100{ "Down" , 0x28 }, { "Page_Up" , 0x21 }, { "Page_Down" , 0x22 }, 101{ "Home" , 0x24 }, { "End" , 0x23 } 102}; 103 104public static void Initialize () 105{ 106// DPI virtualization would otherwise put capture and input in different coordinate spaces. 107SetProcessDPIAware (); 108try { SetThreadDpiAwarenessContext ( new IntPtr ( - 4 )); } 109catch ( EntryPointNotFoundException ) { } 110for ( int i = 1 ; i <= 12 ; i ++ ) namedKeys [ "F" + i ] = ( ushort )( 0x6f + i ); 111} 112 113static void Send ( params Input [] inputs ) 114{ 115if ( SendInput (( uint ) inputs . Length , inputs , Marshal . SizeOf ( typeof ( Input ))) != inputs . Length ) 116throw new Win32Exception ( Marshal . GetLastWin32Error (), 117"Windows rejected desktop input. Elevated apps require Pi to run at the same integrity level; secure desktops are not supported." ); 118} 119 120static Input Mouse ( uint flags , uint data , int x , int y ) 121{ 122return new Input { type = 0 , data = new InputUnion { 123mouse = new MouseInput { flags = flags , mouseData = data , dx = x , dy = y } 124} }; 125} 126 127static Input Key ( ushort vk , ushort scan , uint flags ) 128{ 129if (( vk >= 0x21 && vk <= 0x28 ) || vk == 0x2d || vk == 0x2e || vk == 0x5b ) 130flags |= 0x0001 ; 131return new Input { type = 1 , data = new InputUnion { 132keyboard = new KeyboardInput { vk = vk , scan = scan , flags = flags } 133} }; 134} 135 136static int ButtonMask ( string [] buttons ) 137{ 138int mask = 0 ; 139foreach ( string button in buttons ?? new string [ 0 ]) 140{ 141switch ( button ) 142{ 143case "left" : mask |= 1 ; break ; 144case "middle" : mask |= 2 ; break ; 145case "right" : mask |= 4 ; break ; 146default : throw new ArgumentException ( "Unsupported button: " + button ); 147} 148} 149return mask ; 150} 151 152public static void Pointer ( int x , int y , string [] buttons ) 153{ 154if ( x < 0 || x > 1919 || y < 0 || y > 1079 ) 155throw new ArgumentOutOfRangeException ( "Desktop coordinates" ); 156int next = ButtonMask ( buttons ); 157uint flags = 0x0001 | 0x8000 | 0x4000 ; 158int [] bits = { 1 , 2 , 4 }; 159uint [] down = { 0x0002 , 0x0020 , 0x0008 }; 160uint [] up = { 0x0004 , 0x0040 , 0x0010 }; 161for ( int i = 0 ; i < bits . Length ; i ++ ) 162if ((( next ^ heldButtons ) & bits [ i ]) != 0 ) 163flags |= ( next & bits [ i ]) != 0 ? down [ i ] : up [ i ]; 164heldButtons |= next ; 165Send ( Mouse ( flags , 0 , ( int ) Math . Round ( x * 65535.0 / 1919 ), ( int ) Math . Round ( y * 65535.0 / 1079 ))); 166heldButtons = next ; 167} 168 169public static void Scroll ( int x , int y , string direction , int ticks , string [] buttons ) 170{ 171uint flag ; 172int delta ; 173switch ( direction ) 174{ 175case "up" : flag = 0x0800 ; delta = 120 ; break ; 176case "down" : flag = 0x0800 ; delta = - 120 ; break ; 177case "left" : flag = 0x1000 ; delta = - 120 ; break ; 178case "right" : flag = 0x1000 ; delta = 120 ; break ; 179default : throw new ArgumentException ( "Unsupported direction: " + direction ); 180} 181Pointer ( x , y , buttons ); 182for ( int i = 0 ; i < ticks ; i ++ ) Send ( Mouse ( flag , unchecked (( uint ) delta ), 0 , 0 )); 183} 184 185public static void PressKey ( string name , string [] requestedModifiers ) 186{ 187var keys = new List < ushort > (); 188foreach ( string modifier in requestedModifiers ?? new string [ 0 ]) 189{ 190ushort key ; 191if ( ! modifiers . TryGetValue ( modifier , out key )) 192throw new ArgumentException ( "Unsupported modifier: " + modifier ); 193if ( ! keys . Contains ( key )) keys . Add ( key ); 194} 195ushort vk ; 196if ( ! namedKeys . TryGetValue ( name , out vk )) 197{ 198if ( name . Length != 1 ) throw new ArgumentException ( "Unsupported key name: " + name ); 199uint thread = GetWindowThreadProcessId ( GetForegroundWindow (), IntPtr . Zero ); 200short mapped = VkKeyScanEx ( name [ 0 ], GetKeyboardLayout ( thread )); 201if ( mapped == - 1 ) throw new ArgumentException ( "Key is absent from the active keyboard layout: " + name ); 202vk = ( ushort )( mapped & 0xff ); 203ushort [] implied = { 0x10 , 0x11 , 0x12 }; 204for ( int i = 0 ; i < implied . Length ; i ++ ) 205if (( mapped & ( 0x100 << i )) != 0 && ! keys . Contains ( implied [ i ])) keys . Add ( implied [ i ]); 206} 207keys . Add ( vk ); 208try 209{ 210foreach ( ushort key in keys ) 211{ 212heldKeys . Add ( key ); 213Send ( Key ( key , 0 , 0 )); 214} 215} 216finally { ReleaseKeys (); } 217} 218 219public static void TypeText ( string text ) 220{ 221foreach ( char ch in text . Replace ( "\r\n" , "\n" )) 222{ 223if ( ch == '\n' || ch == '\r' ) PressKey ( "Return" , null ); 224else if ( ch == '\t' ) PressKey ( "Tab" , null ); 225else Send ( Key ( 0 , ch , 0x0004 ), Key ( 0 , ch , 0x0004 | 0x0002 )); 226} 227} 228 229static void ReleaseKeys () 230{ 231var keys = new List < ushort > ( heldKeys ); 232keys . Reverse (); 233foreach ( ushort key in keys ) 234{ 235Send ( Key ( key , 0 , 0x0002 )); 236heldKeys . Remove ( key ); 237} 238} 239 240public static void Release () 241{ 242try { ReleaseKeys (); } 243finally 244{ 245uint flags = 0 ; 246if (( heldButtons & 1 ) != 0 ) flags |= 0x0004 ; 247if (( heldButtons & 2 ) != 0 ) flags |= 0x0040 ; 248if (( heldButtons & 4 ) != 0 ) flags |= 0x0010 ; 249if ( flags != 0 ) Send ( Mouse ( flags , 0 , 0 , 0 )); 250heldButtons = 0 ; 251} 252} 253 254public static string Screenshot () 255{ 256int left = GetSystemMetrics ( 76 ), top = GetSystemMetrics ( 77 ); 257int width = GetSystemMetrics ( 78 ), height = GetSystemMetrics ( 79 ); 258using ( var desktop = new Bitmap ( width , height , PixelFormat . Format32bppArgb )) 259using ( var graphics = Graphics . FromImage ( desktop )) 260using ( var output = new Bitmap ( 1920 , 1080 , PixelFormat . Format32bppArgb )) 261using ( var scaled = Graphics . FromImage ( output )) 262using ( var stream = new MemoryStream ()) 263{ 264graphics . CopyFromScreen ( left , top , 0 , 0 , new Size ( width , height ), CopyPixelOperation . SourceCopy ); 265var cursor = new CursorInfo { size = ( uint ) Marshal . SizeOf ( typeof ( CursorInfo )) }; 266IconInfo icon ; 267if ( GetCursorInfo ( ref cursor ) && ( cursor . flags & 1 ) != 0 && GetIconInfo ( cursor . cursor , out icon )) 268{ 269IntPtr dc = graphics . GetHdc (); 270try 271{ 272DrawIconEx ( dc , cursor . position . x - left - ( int ) icon . xHotspot , 273cursor . position . y - top - ( int ) icon . yHotspot , cursor . cursor , 0 , 0 , 0 , IntPtr . Zero , 3 ); 274} 275finally 276{ 277graphics . ReleaseHdc ( dc ); 278if ( icon . mask != IntPtr . Zero ) DeleteObject ( icon . mask ); 279if ( icon . color != IntPtr . Zero ) DeleteObject ( icon . color ); 280} 281} 282scaled . InterpolationMode = InterpolationMode . HighQualityBicubic ; 283scaled . DrawImage ( desktop , new Rectangle ( 0 , 0 , 1920 , 1080 )); 284output . Save ( stream , ImageFormat . Png ); 285return Convert . ToBase64String ( stream . ToArray ()); 286} 287} 288 289public static void OpenBrowser ( string url ) 290{ 291var uri = new Uri ( url ); 292if ( uri . Scheme != "http" && uri . Scheme != "https" ) 293throw new ArgumentException ( "Only HTTP and HTTPS URLs are supported" ); 294Process . Start ( new ProcessStartInfo ( uri . AbsoluteUri ) { UseShellExecute = true }); 295} 296}