char-slop/ai-dots

ai dotfiles

git clone https://git.t4t.associates/char-slop/ai-dots

Charlotte Somcomputer use for windowsdc2c12a

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