Skip to content

Commit dd65b35

Browse files
committed
chore: ci
1 parent cea1e6a commit dd65b35

File tree

8 files changed

+476
-576
lines changed

8 files changed

+476
-576
lines changed

.github/copilot-instructions.md

Lines changed: 23 additions & 228 deletions
Original file line numberDiff line numberDiff line change
@@ -2,134 +2,39 @@
22

33
## Project Overview
44

5-
GhostDraw is a Windows desktop application that allows users to draw directly on the screen using a keyboard hotkey (Ctrl+Alt+D) and mouse input. The application uses:
5+
GhostDraw is a Windows desktop application that allows users to draw directly on the screen using a keyboard hotkey to activate and mouse input. The application uses:
66

7-
- **WPF** for UI and overlay rendering
8-
- **Global Windows Hooks** for keyboard/mouse capture
9-
- **Dependency Injection** with Microsoft.Extensions.DependencyInjection
10-
- **Structured Logging** with Serilog + Microsoft.Extensions.Logging
11-
- **.NET 8** target framework
12-
13-
### Directory Structure
14-
From repo root (`C:\code\github\ghost-draw\`):
15-
- `src/` - Main application code. .sln and project files here. **This is the project root / workspace directory.**
16-
- `.github/copilot-instructions.md` - This file.
17-
- `docs/` - Additional documentation, design notes, etc. When adding docs here, update the solution file docs folder to show them in IDEs.
18-
- `tests/` - Unit and integration tests.
19-
- `README.md` - Project overview and setup instructions.
20-
21-
**Important**: When creating or editing files:
22-
- **Repo root** = `C:\code\github\ghost-draw\` (where README.md, .github/, docs/, tests/ live)
23-
- **Project root / Workspace** = `C:\code\github\ghost-draw\src\` (where .csproj and source code live)
24-
- Documentation files (`.md`) should go in the **repo root** or `docs/` directory, NOT in `src/`
25-
- Source code files (`.cs`, `.xaml`, etc.) should go in the **project root** (`src/`) or subdirectories within it
7+
- **WPF** for UI and overlay rendering
8+
- **Global Windows Hooks** for keyboard/mouse capture
9+
- **Dependency Injection** with Microsoft.Extensions.DependencyInjection
10+
- **Structured Logging** with Serilog + Microsoft.Extensions.Logging
11+
- **.NET 8** target framework
2612

2713
## Critical Safety Requirements
2814

29-
### ?? PRIORITY #1: User Safety & System Stability
15+
### PRIORITY #1: User Safety & System Stability
3016

3117
This application intercepts global keyboard and mouse input and displays a fullscreen transparent overlay. **If the application crashes or hangs, the user could be locked out of their system.** All code must prioritize robustness and graceful failure.
3218

33-
### ?? PRIORITY #2: Ensure all new code is tested via unit tests or integration tests where applicable.
34-
Ensure The GhostDraw.Tests project has adequate coverage for any new features or changes and that all tests pass.
19+
### PRIORITY #2: Ensure all new code is tested via unit tests or integration tests where applicable.
3520

21+
Ensure The GhostDraw.Tests project has adequate coverage for any new features or changes and that all tests pass.
3622

3723
#### Mandatory Safety Practices
3824

3925
1. **Always Use Try-Catch in Critical Paths**
40-
```csharp
41-
// ? GOOD - Protected hook callback
42-
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
43-
{
44-
try
45-
{
46-
// Hook logic here
47-
}
48-
catch (Exception ex)
49-
{
50-
_logger.LogError(ex, "Hook callback failed");
51-
// MUST allow hook chain to continue
52-
}
53-
return CallNextHookEx(_hookID, nCode, wParam, lParam);
54-
}
55-
```
56-
5726
2. **Hook Callbacks MUST Always Call CallNextHookEx**
58-
- Never block the hook chain
59-
- Always return from hook callbacks quickly (< 5ms)
60-
- Never throw unhandled exceptions from hooks
61-
27+
- Never block the hook chain
28+
- Always return from hook callbacks quickly (< 5ms)
29+
- Never throw unhandled exceptions from hooks
6230
3. **Overlay Window Safety**
63-
- Overlay must NEVER prevent access to underlying windows when hidden
64-
- Always hide overlay on unhandled exceptions
65-
- Provide emergency escape mechanisms (ESC key should always hide overlay)
66-
- Window must properly release input focus when hidden
67-
31+
- Overlay must NEVER prevent access to underlying windows when hidden
32+
- Always hide overlay on unhandled exceptions
33+
- Provide emergency escape mechanisms (ESC key should always hide overlay)
34+
- Window must properly release input focus when hidden
6835
4. **Cleanup on Exit**
69-
```csharp
70-
// Always unhook on dispose/exit
71-
protected override void OnExit(ExitEventArgs e)
72-
{
73-
try
74-
{
75-
_keyboardHook?.Dispose(); // Removes hooks
76-
_notifyIcon?.Dispose();
77-
ServiceConfiguration.Shutdown();
78-
}
79-
catch (Exception ex)
80-
{
81-
_logger?.LogCritical(ex, "Failed during cleanup");
82-
}
83-
base.OnExit(e);
84-
}
85-
```
86-
8736
5. **Emergency Bailout**
88-
- Consider adding ESC key as emergency override to hide overlay
89-
- Add Ctrl+Alt+Shift+X as emergency kill switch
90-
- Log all critical errors before application termination
91-
92-
### Hook-Related Guidelines
93-
94-
- **Never** perform blocking operations in hook callbacks
95-
- **Never** call MessageBox or show dialogs from hook callbacks
96-
- **Never** do heavy processing in hook callbacks (delegate to background tasks)
97-
- **Always** log hook installation success/failure
98-
- **Always** verify hook is properly uninstalled on exit
99-
100-
### Overlay Window Guidelines
101-
102-
- **Always** set `Topmost = true` but ensure it doesn't block system dialogs
103-
- **Never** set `ShowInTaskbar = true` (prevents Alt+Tab interference)
104-
- **Always** ensure overlay is truly transparent when not drawing
105-
- **Always** hide overlay on application deactivation/suspend
106-
- **Always** test that mouse/keyboard input passes through when inactive
107-
108-
## Architecture Guidelines
109-
110-
### Dependency Injection
111-
112-
All components should use constructor injection:
113-
114-
```csharp
115-
public class MyComponent
116-
{
117-
private readonly ILogger<MyComponent> _logger;
118-
private readonly SomeDependency _dependency;
119-
120-
public MyComponent(ILogger<MyComponent> logger, SomeDependency dependency)
121-
{
122-
_logger = logger;
123-
_dependency = dependency;
124-
}
125-
}
126-
```
127-
128-
Register new services in `ServiceConfiguration.ConfigureServices()`:
129-
130-
```csharp
131-
services.AddSingleton<MyComponent>();
132-
```
37+
- Log all critical errors before application termination
13338

13439
### Logging Standards
13540

@@ -154,50 +59,6 @@ _logger.LogCritical(ex, "Keyboard hook installation failed");
15459

15560
**Never log on every mouse move** - use `LogTrace` and ensure it's filtered by default.
15661

157-
### Event Handling Pattern
158-
159-
```csharp
160-
// ? GOOD - Safe event invocation
161-
try
162-
{
163-
HotkeyPressed?.Invoke(this, EventArgs.Empty);
164-
}
165-
catch (Exception ex)
166-
{
167-
_logger.LogError(ex, "Event handler failed");
168-
// Continue execution
169-
}
170-
171-
// ? BAD - Unprotected event invocation
172-
HotkeyPressed?.Invoke(this, EventArgs.Empty); // Could crash app
173-
```
174-
175-
## Code Style Guidelines
176-
177-
### Naming Conventions
178-
179-
- Private fields: `_camelCase`
180-
- Constants: `UPPER_SNAKE_CASE` or `PascalCase`
181-
- Public/Internal: `PascalCase`
182-
- Interfaces: `IPascalCase`
183-
184-
### Error Messages
185-
186-
Include context in error messages:
187-
188-
```csharp
189-
_logger.LogError(ex, "Failed to install keyboard hook. HookID={HookId}", _hookID);
190-
```
191-
192-
### Null Safety
193-
194-
Leverage C# 8+ nullable reference types:
195-
196-
```csharp
197-
private ILogger<MyClass>? _logger; // Nullable
198-
private readonly Config _config = null!; // Non-null assertion (set in constructor)
199-
```
200-
20162
## Testing Considerations
20263

20364
When adding new features:
@@ -209,44 +70,6 @@ When adding new features:
20970
5. **Test rapid hotkey toggles** - No race conditions
21071
6. **Test high DPI scaling** - Drawing should work on all DPI settings
21172

212-
## Common Pitfalls to Avoid
213-
214-
? **Don't**: Use `Application.Current.Dispatcher.Invoke` in hook callbacks
215-
? **Do**: Queue work to background thread if needed
216-
217-
? **Don't**: Store large objects in hook callback scope
218-
? **Do**: Keep hook callbacks lean and fast
219-
220-
? **Don't**: Assume hook callbacks run on UI thread
221-
? **Do**: Marshal to UI thread only when needed
222-
223-
? **Don't**: Show error messages directly to user from background code
224-
? **Do**: Log errors and handle them gracefully
225-
226-
? **Don't**: Use `Thread.Sleep` or blocking waits in hook callbacks
227-
? **Do**: Use async/await patterns when possible (not in hooks though!)
228-
229-
## Windows API (P/Invoke) Guidelines
230-
231-
Always check return values from Windows APIs:
232-
233-
```csharp
234-
_hookID = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, hMod, 0);
235-
if (_hookID == IntPtr.Zero)
236-
{
237-
int error = Marshal.GetLastWin32Error();
238-
_logger.LogError("SetWindowsHookEx failed with error code: {ErrorCode}", error);
239-
throw new Win32Exception(error);
240-
}
241-
```
242-
243-
## Performance Guidelines
244-
245-
- Hook callbacks should complete in < 5ms
246-
- Don't allocate large objects in hot paths
247-
- Consider object pooling for frequently created objects
248-
- Profile with multiple monitors (more pixels = more work)
249-
25073
## Feature Development Workflow
25174

25275
When adding new features:
@@ -258,41 +81,13 @@ When adding new features:
25881
5. **Update settings UI** - Add configuration options when appropriate
25982
6. **Document in code** - Add XML comments for public APIs
26083

261-
## Future Considerations
262-
263-
When suggesting new features, consider:
264-
265-
- **Brush customization** (color, thickness, opacity)
266-
- **Stroke persistence** (save/load drawings)
267-
- **Undo/redo functionality**
268-
- **Screenshot integration**
269-
- **Multi-user scenarios** (Terminal Server, Fast User Switching)
270-
- **Accessibility** (screen readers, high contrast mode)
271-
- **Localization** (internationalization support)
272-
273-
## Settings Architecture
274-
275-
**IMPORTANT**: Before modifying any settings-related code, read the comprehensive settings architecture documentation:
276-
277-
📄 **[Settings Architecture Guide](../docs/settings-architecture.md)**
278-
279-
This document covers:
280-
- Settings data flow and persistence
281-
- The critical **nesting level pattern** (prevents recursion bugs)
282-
- Event handling best practices
283-
- Common pitfalls and solutions
284-
- How to add new settings correctly
285-
- Testing considerations
286-
287-
**Key Rule**: When updating UI from events or calling settings service methods, ALWAYS use the nesting level pattern to prevent infinite recursion.
288-
28984
## Resources
29085

291-
- [Low-Level Keyboard Hook Documentation](https://learn.microsoft.com/en-us/windows/win32/winmsg/lowlevelkeyboardproc)
292-
- [WPF Transparent Windows Best Practices](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/windows/)
293-
- [Serilog Best Practices](https://github.com/serilog/serilog/wiki/Writing-Log-Events)
294-
- [Microsoft.Extensions.Logging Documentation](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging)
295-
- [Settings Architecture Guide](../docs/settings-architecture.md) - Internal architecture documentation
86+
- [Low-Level Keyboard Hook Documentation](https://learn.microsoft.com/en-us/windows/win32/winmsg/lowlevelkeyboardproc)
87+
- [WPF Transparent Windows Best Practices](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/windows/)
88+
- [Serilog Best Practices](https://github.com/serilog/serilog/wiki/Writing-Log-Events)
89+
- [Microsoft.Extensions.Logging Documentation](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging)
90+
- [Settings Architecture Guide](../docs/settings-architecture.md) - Internal architecture documentation
29691

29792
---
29893

@@ -306,4 +101,4 @@ This document covers:
306101
6. **Test Edge Cases** - Crashes, multi-monitor, high DPI, rapid input
307102
7. **Document Risks** - Comment any potentially dangerous code paths
308103

309-
Remember: This application has elevated privileges and intercepts user input. With great power comes great responsibility! ???
104+
Remember: This application has elevated privileges and intercepts user input. With great power comes great responsibility!

0 commit comments

Comments
 (0)