Skip to content

Commit 8f01ebd

Browse files
marcosqlbiclaude
andauthored
Say at startup when there is no pen or touchscreen (#80)
SQLBI Whiteboard is built for a pen or a finger. On a computer with neither there is nothing to draw with, which is worth saying rather than leaving someone to work out why the pen tools do nothing. `NoDigitizerWindow` appears at startup when Windows reports neither a pen tablet nor a touchscreen. It reads the same `Tablet.TabletDevices` list the Finger drawing setting already uses, so the two agree about what counts as a pen. The notice says what is missing, that a mouse pans, zooms and moves containers but cannot draw, and links to [discussion 78](#78) for anyone who wants to vote for mouse-only drawing. The application opens either way — refusing to start would be worse than saying what is absent. ## Dismissable, for two reasons That tablet list is a list of digitizers rather than an answer about what is plugged in right now, so a pen that has never been brought into range can be missing from it. A false positive is therefore possible, and on a genuinely mouse-only machine the notice would otherwise appear at every launch. So it carries its own **Do not show this again**, which writes `AppSettings.WarnWhenNoDigitizer` and saves immediately, and the same switch is a **Startup** row in Preferences so it can be turned back on. Settings version 11 → 12; covered by smoke tests for the default and for the round trip. README, the guide's list of what Preferences holds, and the site FAQ answer for "do I need a pen?" are updated to match. Version 1.1.5. Release build clean with `TreatWarningsAsErrors`, smoke tests pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent bbbb82f commit 8f01ebd

12 files changed

Lines changed: 183 additions & 6 deletions

File tree

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
scripts/build-installer.ps1 both read it from here, so releasing is a reviewed change
66
to this line rather than an edit in a pipeline variable group.
77
-->
8-
<VersionPrefix>1.1.4</VersionPrefix>
8+
<VersionPrefix>1.1.5</VersionPrefix>
99
<LangVersion>latest</LangVersion>
1010
<Nullable>enable</Nullable>
1111
<ImplicitUsings>enable</ImplicitUsings>

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ How the project is developed and shipped is documented separately:
1313
- A normal cursor for physical mouse input, and a pen-hover indicator that shows what a tap would do: the laser with its halo and speed trail, a dashed square around what the eraser would clear, and a high-contrast dot for everything else. All of them disappear on contact
1414
- Touch panning and two-finger pinch zoom
1515
- Optional finger drawing (default when no pen is detected): one finger uses the current tool, two fingers still pan and pinch-zoom, and Eraser and Pan appear on the toolbar
16+
- A notice at startup when Windows reports neither a pen tablet nor a touchscreen: the application still opens, but there is nothing to draw with, and [discussion 78](https://github.com/sql-bi/SQLBI-Whiteboard/discussions/78) collects votes for mouse-only drawing. Dismissable from the notice itself or from Preferences, since the tablet list Windows reports can miss a pen that has never been in range
1617
- Basic palm rejection: touch navigation is suspended when the pen makes contact
1718
- Mouse-wheel zoom and middle-button or temporary Space-key panning
1819
- Whole-stroke erasing
@@ -202,7 +203,7 @@ Use **Copy settings** after finding a useful combination so the exact values can
202203
| Delete | Delete the selected container and its linked strokes |
203204
| Alt+L | Laser pointer |
204205
| File / Edit / View / Help | Tab strip. Click a tab for a one-row command strip over the canvas. Click the canvas to hide it |
205-
| Help > Preferences | Searchable settings: startup monitor, full screen, finger drawing, pen button, snippet format order, laser trail, toolbar, update checks |
206+
| Help > Preferences | Searchable settings: startup monitor, full screen, no-pen warning, finger drawing, pen button, snippet format order, laser trail, toolbar, update checks |
206207
| View > Bring to front / Send to back | Reorder the selected image, text, or LiveView (and its linked strokes) |
207208
| Help > About | Version, channel, license, the product site, and a download link when a newer release is known |
208209
| View > LiveView | Capture, freeze, disconnect, or reconnect a window or display |

TODO.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ The delivery chain works end to end: a merge to `main` builds, signs, and publis
1616
pre-release to GitHub Releases, and one approval promotes that same build to a release.
1717
<https://whiteboard.sqlbi.com> reads its download links from the release manifest
1818
deployed beside it and needs no edit per release. The current product version is `VersionPrefix` in `Directory.Build.props`
19-
(1.1.4). Identity version for the Store package is `VersionPrefix.0` (`1.1.4.0`).
19+
(1.1.5). Identity version for the Store package is `VersionPrefix.0` (`1.1.5.0`).
2020

2121
Declaring that number is decision 20 in [docs/decisions.md](docs/decisions.md). What 1.0
2222
was waiting on shipped during 0.9.x: Preferences, `.wimport`, Explorer and VS Code

site/faq.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ <h2>Windows 11 or Windows 10?</h2>
5757
<p>Built for Windows 11. It runs on Windows 10 version 2004 or later, 64-bit. That is the same floor as Windows Graphics Capture, which LiveView uses.</p>
5858

5959
<h2>Is a pen required?</h2>
60-
<p>For ink, yes, unless Finger drawing is on. A mouse and touch pan, zoom, and move containers. A keyboard runs the rest. The rear eraser and palm rejection still need a pen. New installs default Finger drawing to <span class="ui">When no pen is detected</span>, which looks at the digitizer list Windows reports, not whether a pen is in the room. <span class="ui">On</span> makes one finger use the current tool; two fingers still pan and pinch-zoom, and Eraser and Pan appear on the toolbar. The <a href="shortcuts.html">shortcut list</a> is grouped by pen, mouse, touch, and keys.</p>
60+
<p>For ink, yes, unless Finger drawing is on. On a computer where Windows reports neither a pen tablet nor a touchscreen, a notice at startup says so and points to <a href="https://github.com/sql-bi/SQLBI-Whiteboard/discussions/78">discussion 78</a>, which collects votes for mouse-only drawing; the application still opens. A mouse and touch pan, zoom, and move containers. A keyboard runs the rest. The rear eraser and palm rejection still need a pen. New installs default Finger drawing to <span class="ui">When no pen is detected</span>, which looks at the digitizer list Windows reports, not whether a pen is in the room. <span class="ui">On</span> makes one finger use the current tool; two fingers still pan and pinch-zoom, and Eraser and Pan appear on the toolbar. The <a href="shortcuts.html">shortcut list</a> is grouped by pen, mouse, touch, and keys.</p>
6161

6262
<h2>Mac, iPad, or a browser?</h2>
6363
<p>No. It is a Windows application. Boards are files you can keep next to the material they document; they do not open in a browser.</p>

site/guide.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,7 @@ <h3>The command strip</h3>
902902
</figure>
903903

904904
<h3>Preferences</h3>
905-
<p><span class="ui">Help → Preferences</span> is a searchable list: which monitor to open on, start full screen, finger drawing, what the pen's barrel button does, snippet format order, laser trail timing and weight, toolbar placement and layout, and the daily new-version check. Settings about how something looks — the trail weight, the barrel button, where the toolbar sits and how it is laid out — draw their options rather than naming them, so the choice is made by looking. <span class="ui">Help → About</span> shows the version. New settings are more rows in Preferences, not a new dialog.</p>
905+
<p><span class="ui">Help → Preferences</span> is a searchable list: which monitor to open on, start full screen, whether to warn when there is nothing to draw with, finger drawing, what the pen's barrel button does, snippet format order, laser trail timing and weight, toolbar placement and layout, and the daily new-version check. Settings about how something looks — the trail weight, the barrel button, where the toolbar sits and how it is laid out — draw their options rather than naming them, so the choice is made by looking. <span class="ui">Help → About</span> shows the version. New settings are more rows in Preferences, not a new dialog.</p>
906906

907907
<figure class="fig">
908908
<div class="figbox">

src/SQLBI.Whiteboard.Core/Settings/AppSettings.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,15 @@ public sealed class AppSettings
9898

9999
public PenButtonSettings PenButtons { get; set; } = new();
100100

101+
/// <summary>
102+
/// Whether to say at startup that Windows reports nothing to draw with. The
103+
/// tablet list this reads is a list of digitizers rather than an answer
104+
/// about what is plugged in, so a pen that has never been brought into
105+
/// range can be missing from it - which is the other reason this can be
106+
/// turned off.
107+
/// </summary>
108+
public bool WarnWhenNoDigitizer { get; set; } = true;
109+
101110
public bool CheckForUpdates { get; set; } = true;
102111

103112
public DateTimeOffset? LastUpdateCheckUtc { get; set; }
@@ -111,7 +120,7 @@ public sealed class AppSettings
111120

112121
public static class AppSettingsSerializer
113122
{
114-
public const int CurrentVersion = 11;
123+
public const int CurrentVersion = 12;
115124

116125
private static readonly JsonSerializerOptions JsonOptions = new()
117126
{

src/SQLBI.Whiteboard/MainWindow.xaml.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,34 @@ private void MainWindow_SourceInitialized(object? sender, EventArgs e)
196196
private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
197197
{
198198
Loaded -= MainWindow_Loaded;
199+
WarnWhenNothingToDrawWith();
199200
_ = CheckForUpdatesAsync();
200201
if (_initialBoardPath is not null)
201202
{
202203
await OpenPathAsync(_initialBoardPath, confirmDiscard: false);
203204
}
204205
}
205206

207+
// A whiteboard with nothing to draw on it is worth saying out loud, rather
208+
// than leaving someone to work out why the pen tools do nothing.
209+
private void WarnWhenNothingToDrawWith()
210+
{
211+
if (!_settings.WarnWhenNoDigitizer || NoDigitizerWindow.HasDrawingDevice())
212+
{
213+
return;
214+
}
215+
216+
var notice = new NoDigitizerWindow { Owner = this };
217+
notice.ShowDialog();
218+
if (!notice.DoNotShowAgain)
219+
{
220+
return;
221+
}
222+
223+
_settings.WarnWhenNoDigitizer = false;
224+
AppSettingsStore.Save(_settings);
225+
}
226+
206227
private void BoardViewport_SizeChanged(object sender, SizeChangedEventArgs e)
207228
{
208229
_camera.Resize(e.NewSize.Width, e.NewSize.Height);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<Window x:Class="SQLBI.Whiteboard.NoDigitizerWindow"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
Title="No pen or touchscreen found"
5+
Width="480"
6+
SizeToContent="Height"
7+
ResizeMode="NoResize"
8+
WindowStartupLocation="CenterOwner"
9+
ShowInTaskbar="False"
10+
Background="{DynamicResource ToolbarBackgroundBrush}"
11+
PreviewKeyDown="Window_PreviewKeyDown">
12+
<StackPanel Margin="28,24">
13+
<TextBlock FontFamily="Segoe UI"
14+
FontSize="16"
15+
FontWeight="SemiBold"
16+
Foreground="#FF1F2937"
17+
TextWrapping="Wrap"
18+
Text="No pen or touchscreen found" />
19+
<TextBlock Margin="0,12,0,0"
20+
FontFamily="Segoe UI"
21+
FontSize="13"
22+
Foreground="#FF374151"
23+
TextWrapping="Wrap"
24+
Text="SQLBI Whiteboard is built for drawing with a pen or a finger. Windows reports no pen tablet and no touchscreen on this computer, so there is nothing here to draw with." />
25+
<TextBlock Margin="0,10,0,0"
26+
FontFamily="Segoe UI"
27+
FontSize="13"
28+
Foreground="#FF374151"
29+
TextWrapping="Wrap"
30+
Text="A mouse can pan, zoom, and move containers, and the keyboard runs the rest, but there is no mouse drawing yet. The application will open, and everything that does not need ink will work." />
31+
<TextBlock Margin="0,10,0,0"
32+
FontFamily="Segoe UI"
33+
FontSize="13"
34+
Foreground="#FF374151"
35+
TextWrapping="Wrap">
36+
<Run Text="If you would like a mouse-only version, say so here:" />
37+
<LineBreak />
38+
<Hyperlink NavigateUri="https://github.com/sql-bi/SQLBI-Whiteboard/discussions/78"
39+
RequestNavigate="DiscussionLink_RequestNavigate">
40+
<Run Text="Vote for mouse-only support" />
41+
</Hyperlink>
42+
</TextBlock>
43+
<CheckBox x:Name="DoNotShowAgainBox"
44+
Margin="0,20,0,0"
45+
FontFamily="Segoe UI"
46+
FontSize="13"
47+
Foreground="#FF374151"
48+
Content="Do not show this again" />
49+
<StackPanel Margin="0,16,0,0"
50+
Orientation="Horizontal"
51+
HorizontalAlignment="Right">
52+
<Button MinWidth="96"
53+
MinHeight="30"
54+
IsDefault="True"
55+
IsCancel="True"
56+
Content="Continue"
57+
Click="ContinueButton_Click" />
58+
</StackPanel>
59+
</StackPanel>
60+
</Window>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System.Diagnostics;
2+
using System.Windows;
3+
using System.Windows.Input;
4+
using System.Windows.Navigation;
5+
6+
namespace SQLBI.Whiteboard;
7+
8+
/// <summary>
9+
/// Shown once at startup when Windows reports neither a pen tablet nor a
10+
/// touchscreen. The application still opens - everything that does not need ink
11+
/// works with a mouse and the keyboard - so this says what is missing rather
12+
/// than refusing to start.
13+
/// </summary>
14+
public partial class NoDigitizerWindow : Window
15+
{
16+
public NoDigitizerWindow() => InitializeComponent();
17+
18+
/// <summary>
19+
/// Whether the notice was dismissed for good. Also the way out of a false
20+
/// positive, so it is offered on the notice itself rather than only in
21+
/// Preferences.
22+
/// </summary>
23+
public bool DoNotShowAgain => DoNotShowAgainBox.IsChecked == true;
24+
25+
/// <summary>
26+
/// Whether Windows reports anything to draw with. The same tablet list the
27+
/// Finger drawing setting reads, which is a list of digitizers rather than
28+
/// an answer about what is plugged in right now: a pen that has never been
29+
/// brought into range can be absent from it.
30+
/// </summary>
31+
public static bool HasDrawingDevice()
32+
{
33+
foreach (TabletDevice device in Tablet.TabletDevices)
34+
{
35+
if (device.Type is TabletDeviceType.Stylus or TabletDeviceType.Touch)
36+
{
37+
return true;
38+
}
39+
}
40+
41+
return false;
42+
}
43+
44+
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
45+
{
46+
if (e.Key == Key.Escape)
47+
{
48+
Close();
49+
e.Handled = true;
50+
}
51+
}
52+
53+
private void DiscussionLink_RequestNavigate(object sender, RequestNavigateEventArgs e)
54+
{
55+
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri)
56+
{
57+
UseShellExecute = true,
58+
});
59+
e.Handled = true;
60+
}
61+
62+
private void ContinueButton_Click(object sender, RoutedEventArgs e) => Close();
63+
}

src/SQLBI.Whiteboard/PreferencesWindow.xaml.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,7 @@ private ToggleButton CreateSwitch(SettingDescriptor setting)
727727
IsChecked = setting.Id switch
728728
{
729729
SettingsCatalog.Ids.StartFullScreen => _settings.StartFullScreen,
730+
SettingsCatalog.Ids.WarnWhenNoDigitizer => _settings.WarnWhenNoDigitizer,
730731
SettingsCatalog.Ids.CheckForUpdates => _settings.CheckForUpdates,
731732
_ => false,
732733
},
@@ -904,6 +905,10 @@ private void SetBoolean(SettingDescriptor setting, bool value)
904905
{
905906
_settings.StartFullScreen = value;
906907
}
908+
else if (setting.Id == SettingsCatalog.Ids.WarnWhenNoDigitizer)
909+
{
910+
_settings.WarnWhenNoDigitizer = value;
911+
}
907912
else if (setting.Id == SettingsCatalog.Ids.CheckForUpdates)
908913
{
909914
_settings.CheckForUpdates = value;

0 commit comments

Comments
 (0)