Skip to content

Commit f25bdda

Browse files
Merge pull request #15 from RuntimeRascal/copilot/add-clear-canvas-hotkey
Add clear canvas hotkey (R key) with visual feedback
2 parents 30ccaf5 + 51b2e49 commit f25bdda

6 files changed

Lines changed: 438 additions & 3 deletions

File tree

Src/GhostDraw/App.xaml.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ protected override void OnStartup(StartupEventArgs e)
7373
_keyboardHook.HotkeyPressed += OnHotkeyPressed;
7474
_keyboardHook.HotkeyReleased += OnHotkeyReleased;
7575
_keyboardHook.EscapePressed += OnEscapePressed;
76+
_keyboardHook.ClearCanvasPressed += OnClearCanvasPressed;
7677
_keyboardHook.Start();
7778

7879
// Setup system tray icon
@@ -233,6 +234,23 @@ private void OnEscapePressed(object? sender, EventArgs e)
233234
}
234235
}
235236

237+
private void OnClearCanvasPressed(object? sender, EventArgs e)
238+
{
239+
try
240+
{
241+
// Only clear canvas if drawing mode is active
242+
if (_drawingManager?.IsDrawingMode == true)
243+
{
244+
_logger?.LogInformation("R pressed - clearing canvas");
245+
_drawingManager?.ClearCanvas();
246+
}
247+
}
248+
catch (Exception ex)
249+
{
250+
_exceptionHandler?.HandleException(ex, "Clear canvas handler");
251+
}
252+
}
253+
236254
protected override void OnExit(ExitEventArgs e)
237255
{
238256
_logger?.LogInformation("Application exiting");

Src/GhostDraw/Core/GlobalKeyboardHook.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class GlobalKeyboardHook : IDisposable
1212

1313
// Only keep VK_ESCAPE constant (emergency exit)
1414
private const int VK_ESCAPE = 0x1B; // 27
15+
private const int VK_R = 0x52; // 82 - 'R' key for clear canvas
1516

1617
private readonly ILogger<GlobalKeyboardHook> _logger;
1718
private readonly LowLevelKeyboardProc _proc;
@@ -23,6 +24,7 @@ public class GlobalKeyboardHook : IDisposable
2324
public event EventHandler? HotkeyPressed;
2425
public event EventHandler? HotkeyReleased;
2526
public event EventHandler? EscapePressed;
27+
public event EventHandler? ClearCanvasPressed;
2628

2729
// NEW: Raw key events for recorder
2830
public event EventHandler<KeyEventArgs>? KeyPressed;
@@ -181,6 +183,13 @@ private nint HookCallback(int nCode, nint wParam, nint lParam)
181183
EscapePressed?.Invoke(this, EventArgs.Empty);
182184
}
183185

186+
// Check for R key press (clear canvas)
187+
if (vkCode == VK_R && isKeyDown)
188+
{
189+
_logger.LogDebug("R key pressed - clear canvas request");
190+
ClearCanvasPressed?.Invoke(this, EventArgs.Empty);
191+
}
192+
184193
// Track hotkey state
185194
if (_hotkeyVKs.Contains(vkCode))
186195
{

Src/GhostDraw/Managers/DrawingManager.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,28 @@ public void DisableDrawingMode()
163163
// Don't throw - this is for emergency cleanup
164164
}
165165
}
166+
167+
/// <summary>
168+
/// Clears the canvas while keeping drawing mode active
169+
/// </summary>
170+
public void ClearCanvas()
171+
{
172+
try
173+
{
174+
if (_overlayWindow.IsVisible)
175+
{
176+
_logger.LogInformation("Clearing canvas (R key)");
177+
_overlayWindow.ClearCanvas();
178+
}
179+
else
180+
{
181+
_logger.LogDebug("ClearCanvas ignored - overlay not visible");
182+
}
183+
}
184+
catch (Exception ex)
185+
{
186+
_logger.LogError(ex, "Failed to clear canvas");
187+
// Don't re-throw - not critical
188+
}
189+
}
166190
}

Src/GhostDraw/Views/OverlayWindow.xaml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,54 @@
4141
Foreground="#FF0080"
4242
Text="3 px"/>
4343
</Border>
44+
45+
<!-- Canvas Cleared Toast (center of screen, cyberpunk style) -->
46+
<Border x:Name="CanvasClearedToastBorder"
47+
HorizontalAlignment="Center"
48+
VerticalAlignment="Center"
49+
Padding="24,16"
50+
Background="#1A1A2E"
51+
BorderBrush="#00FF88"
52+
BorderThickness="2"
53+
CornerRadius="4"
54+
Opacity="0"
55+
IsHitTestVisible="False">
56+
<Border.Effect>
57+
<DropShadowEffect Color="#00FF88"
58+
Opacity="0.7"
59+
BlurRadius="20"
60+
ShadowDepth="0"/>
61+
</Border.Effect>
62+
<TextBlock x:Name="CanvasClearedToastText"
63+
FontFamily="Segoe UI"
64+
FontSize="28"
65+
FontWeight="Bold"
66+
Foreground="#00FF88"
67+
Text="Canvas Cleared"/>
68+
</Border>
69+
70+
<!-- Drawing Mode Hint (center of screen, fades out on activation) -->
71+
<Border x:Name="DrawingModeHintBorder"
72+
HorizontalAlignment="Center"
73+
VerticalAlignment="Bottom"
74+
Margin="0,0,0,100"
75+
Padding="20,12"
76+
Background="#1A1A2E"
77+
BorderBrush="#808080"
78+
BorderThickness="1"
79+
CornerRadius="4"
80+
Opacity="0"
81+
IsHitTestVisible="False">
82+
<Border.Effect>
83+
<DropShadowEffect Color="#808080"
84+
Opacity="0.5"
85+
BlurRadius="10"
86+
ShadowDepth="0"/>
87+
</Border.Effect>
88+
<TextBlock FontFamily="Segoe UI"
89+
FontSize="16"
90+
Foreground="#B0B0B0"
91+
Text="Press R to clear canvas | ESC to exit"/>
92+
</Border>
4493
</Grid>
4594
</Window>

0 commit comments

Comments
 (0)