diff --git a/CHANGELOG.md b/CHANGELOG.md index b4b2388..835e067 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,18 @@ broke. The heading is parsed by `scripts/release-notes.ps1`, so keep its shape; under it is ordinary Markdown, and the renderer handles paragraphs, lists, links, `code` and **bold**. +## 1.7.8 - 31 October 2026 + +### Go to a LiveView's source window +A LiveView of a window has a **Go to source window** button that brings that window forward, +on whichever virtual desktop it is. Ctrl+Alt+Shift+W does the same from Whiteboard, and from +any other application returns to Whiteboard and resumes the LiveView. +**Preferences → Live View → Source window shortcut** offers Ctrl+Alt+. or Ctrl+Alt+J instead. + +### Ink across overlapping containers +A stroke that touches more than one container now moves with the frontmost one. It used to +stay on the canvas, linked to none of them. + ## 1.7.7 - 29 October 2026 ### Clear strokes diff --git a/Directory.Build.props b/Directory.Build.props index 1f0747a..86777fc 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,7 +5,7 @@ scripts/build-installer.ps1 both read it from here, so releasing is a reviewed change to this line rather than an edit in a pipeline variable group. --> - 1.7.7 + 1.7.8 latest enable enable diff --git a/README.md b/README.md index 2355bcb..7f135f4 100644 --- a/README.md +++ b/README.md @@ -234,10 +234,10 @@ Use **Copy settings** after finding a useful combination so the exact values can | Ctrl + tap or drag | Add what is tapped, or what the area takes, to the selection instead of replacing it | | Shift + drag a shape | Constrain the new shape to a square | | Ctrl at release (connector) | Bind the endpoint to the nearest point anywhere on the object's border, rather than to one of its eight binding points. **Anchors → Auto** on the property bar moves a bound end to the side facing the other end instead | -| Help > Preferences | Searchable settings: mode, startup monitor, full screen at startup or when idle, no-pen warning, finger drawing, mouse drawing, pen button, snippet format order, area selection, background grid, laser trail, toolbar position and layout, Insert and Lasso on the toolbar, the Insert palette, after inserting an object, always show the Eraser, update checks. Each setting is one line; its chevron opens the reasoning behind it. Search marks what it matched, and marks the chevron when the match is in the text behind it | +| Help > Preferences | Searchable settings: mode, startup monitor, full screen at startup or when idle, no-pen warning, finger drawing, mouse drawing, pen button, snippet format order, area selection, background grid, laser trail, toolbar position and layout, Insert and Lasso on the toolbar, the Insert palette, after inserting an object, always show the Eraser, the LiveView source window shortcut, update checks. Each setting is one line; its chevron opens the reasoning behind it. Search marks what it matched, and marks the chevron when the match is in the text behind it | | View > Bring to front / Bring forward / Send backward / Send to back | Reorder the selection (and its linked strokes) as one block. Letters B, W, K, and S while the View strip is open, and the same four behind the property bar's … | | Help > About | Version, channel, license, the product site, and a download link when a newer release is known | -| View > LiveView | Capture, freeze, disconnect, or reconnect a window or display | +| View > LiveView | Capture, freeze, disconnect, or reconnect a window or display. **Go to source window** is available when the captured window can be identified uniquely; **Ctrl+Alt+Shift+W**, or the keys chosen in Preferences, switches between that window and Whiteboard across virtual desktops and resumes the feed on return | | F11 | Fill the current monitor and hide title and tabs. Escape leaves it when a text container is not being edited. **Preferences → Startup → Go full screen when idle** does the same after 20 seconds without input in Whiteboard, even while another app has focus | | Ctrl+F11 | Hide title and tabs but keep this window’s size and place | @@ -245,7 +245,7 @@ With the mouse, selection is automatic: click a container to move it, or drag th **Help → Preferences → Mouse drawing** changes what the left button means, and it defaults to on when Windows reports neither a pen tablet nor a touchscreen. With it on the left button uses the selected tool, the tool stays selected rather than being handed back, and Eraser and Pan join the toolbar as they do for finger drawing. Everything above then moves to Ctrl: Ctrl and the left button select, move, and resize a container and return to the previous drawing tool, and Ctrl with a double-click centers and fits one. Two plain clicks with an ink tool are two strokes, which is why framing moves out of the way. Shift still constrains a stroke to horizontal or vertical, and Alt+L is still the laser. A mouse reports no pressure, so ink is drawn at an even width; Calligraphy still varies, because its width comes from speed. The pen path is untouched, so Mouse drawing can be left on beside a pen. -Imported images, LiveViews, text objects, shapes, and text labels act as containers. A completed stroke is linked when it touches exactly one container, including crossing its edge; a stroke touching multiple containers remains independent. A shape is picked up by its outline rather than by its interior, so ink drawn inside one stays reachable, and a label is picked up anywhere on its rotated rectangle. Moving, resizing, or turning a container transforms its linked strokes with it. **View → Bring to front**, **Bring forward**, **Send backward**, and **Send to back** reorder the selection and those linked strokes as one block. Deleting a container also deletes all of its linked strokes. Undo/redo treats each complete container operation as one action. +Imported images, LiveViews, text objects, shapes, and text labels act as containers. A completed stroke links to the frontmost container it touches, including crossing its edge; a stroke touching no container remains independent. A shape is picked up by its outline rather than by its interior, so ink drawn inside one stays reachable, and a label is picked up anywhere on its rotated rectangle. Moving, resizing, or turning a container transforms its linked strokes with it. **View → Bring to front**, **Bring forward**, **Send backward**, and **Send to back** reorder the selection and those linked strokes as one block. Deleting a container also deletes all of its linked strokes. Undo/redo treats each complete container operation as one action. Paste plain text to create a selected text container in display mode. **Help → Preferences** has Snippet format order: paste tries those languages from top to bottom and uses the first that accepts the text. Plain text always accepts and comes last by default, so DAX, SQL, KQL, and Markdown are recognized on paste; a language claims a snippet only when it carries an operator, function, or keyword, so a bare word stays a note. Put Plain text first to keep every paste plain. A language added by an update joins in front of Plain text unless Plain text is first. Recognized extensions (`.dax`, `.sql`, `.kql`, `.txt`) keep their language; other dropped text files use the same order. Choose **Plain text**, **Markdown**, **DAX**, **SQL Server**, or **KQL** from the title-bar chip afterward, or one of **Python**, **C**, **C++**, **Java**, **C#**, **JavaScript**, **TypeScript**, **Visual Basic .NET**, **R**, **Rust**, and **PHP**, which are highlighted but not formatted and are never chosen by paste; **F6** on one of them opens that language's issue on GitHub. Press **F6** to format DAX, SQL, or KQL on the selected container without entering edit. Press **F2** to edit the body; the same list is in the title bar while editing. In F2, **F6** formats in place; **Ctrl+Enter** commits that edit (including the format) and returns to display. **Escape** restores the previous text, language, and dimensions. Text reflows while its edit-mode resize grip changes the width, and the height grows automatically when necessary. Double-click still centers and fits the container. Syntax highlighting applies in both edit and display modes. A language-aware title identifies a defined DAX, SQL, or KQL object when possible. SQL Server mode targets SQL Server 2025 T-SQL, preserves `GO` batch separators, and leaves invalid scripts unchanged. KQL mode reads Kusto through Microsoft's own parser and likewise leaves an invalid query unchanged. In display mode, resizing preserves the aspect ratio and scales the complete text visual without reflowing it. diff --git a/docs/export.md b/docs/export.md index fa75269..63ce8e5 100644 --- a/docs/export.md +++ b/docs/export.md @@ -19,7 +19,7 @@ the machine). The board is one unbounded plane. A `.wboard` is a flat list of objects in world coordinates — ink strokes, images, text containers, and LiveViews — each with a bounding rectangle and a z-index that is also its creation order, plus the assets the images refer -to. A stroke that touches exactly one container is linked to it and moves with it. Nothing +to. A newly drawn stroke links to the frontmost container it touches and moves with it. Nothing in the file says where a page begins or ends. The first two exports have to decide it, and the third does not need it. diff --git a/docs/liveview-navigation.md b/docs/liveview-navigation.md new file mode 100644 index 0000000..5f53e5d --- /dev/null +++ b/docs/liveview-navigation.md @@ -0,0 +1,98 @@ +# LiveView window navigation + +Implemented locally: the third on-container button activates the source window. +One system-wide shortcut, Ctrl+Alt+Shift+W by default, does the same from Whiteboard +and returns to the existing Whiteboard window from anywhere else, resuming the feed. + +## Window identity and desktops + +The original Windows capture picker is used for both windows and displays. After +selection, Whiteboard compares the capture title and pixel dimensions with open +windows. Candidate dimensions come from temporary capture items, so window borders +and DPI do not require approximate size comparisons. No additional capture session +is started. Windows on other virtual desktops are included in enumeration. + +A single matching candidate enables navigation. Duplicate matches, changed titles, +resizing, or errors leave navigation disabled without interrupting capture. Display +capture descriptions are checked first to avoid linking a display to a window with +an identical title and size. This is a heuristic: a unique description is not proof +of identity, and a window changing while matching can make the result inconclusive. + +Once matched, the HWND and process ID are retained for the capture session; later +title changes do not trigger another search. The association is cleared on disconnect +or target closure. Reopening a board still requires Reconnect, which runs the same +picker and matching process again. + +Navigation restores a minimized window and calls `SetForegroundWindow`. Windows +selects the virtual desktop containing that existing window. Neither source nor +Whiteboard is moved to another desktop. This follows the window's current desktop; +if the user moves it during the visit, the return follows its new location. + +## Shortcut + +`RegisterHotKey` delivers the shortcut to Whiteboard whichever window is in front, +so one key serves both directions. When Whiteboard's main window is active, it goes +to the selected LiveView's source, then the last one visited, then the only LiveView +with a source window. When another application is active, it returns to Whiteboard +and resumes the LiveView last visited. It does nothing while a Whiteboard dialog or +a label or shape text edit is active. + +A registered hotkey takes the keys from every other application, including shortcuts +an application handles in its own window, which `RegisterHotKey` cannot detect. The +shortcut is therefore registered only while at least one LiveView has an available +source window, or a visit is under way, and released otherwise. A visit keeps it +registered when the source closes, so the return still works. A registration conflict +is silent when a LiveView connects, reported by **Go to source window** before leaving +the board, and reported when the shortcut is changed in Preferences. + +**Preferences → Live View → Source window shortcut** offers a fixed list: +Ctrl+Alt+Shift+W, Ctrl+Alt+., and Ctrl+Alt+J. A list, rather than recording any +combination, avoids having to reject Whiteboard's own shortcuts, Windows-key +combinations reserved by the operating system, and Ctrl+Alt combinations that type a +character with AltGr on the current keyboard layout. Ctrl+Alt+Shift+W is the default +because three modifiers keep it out of AltGr typing and out of most applications' +shortcut tables. Ctrl+Alt+J, for example, is used by Visual Studio. + +Jumping resumes a frozen source. During the visit, that feed is exempt from +**Pause when Whiteboard loses focus**, so edits can be captured before returning +to another desktop. Other feeds retain the preference. Activating Whiteboard ends +the exemption. Frame delivery still depends on the source application and Windows +Graphics Capture; activation does not guarantee that a new frame has already arrived. + +## Validation + +The default smoke suite checks matching with supplied capture descriptions, including +unique matches, duplicates, size mismatches, title changes, and inaccessible candidates. +It also checks native window identity, closed-window rejection, and hotkey registration +conflicts and cleanup. These checks do not require Windows Graphics Capture. + +Real capture tests require an interactive Windows desktop and are explicitly enabled: + +```powershell +dotnet run --project tests/SQLBI.Whiteboard.SmokeTests/SQLBI.Whiteboard.SmokeTests.csproj -c Release -- --liveview-navigation-capture +``` + +They create offscreen windows without activating them, verify capture and matching, +and check that failure leaves the selected capture item usable. GitHub's hosted runner +rejected capture-item creation with E_INVALIDARG, so this integration check is not part +of the default CI suite. Neither suite changes virtual desktops. + +Interactive checks still required on Windows 11: + +1. Capture a window with the Windows picker, jump with the shortcut, edit its contents, + and return with the same shortcut. Repeat with the button for the first jump. +2. Repeat with the source and Whiteboard on different virtual desktops. Confirm both + jumps follow the appropriate desktop and the edit appears in the feed. +3. Repeat with a minimized source, a frozen LiveView, and background capture pausing on. +4. Close the source during the visit. The shortcut must still return to Whiteboard. +5. Choose a display through the system picker. Freeze and Resume must still work; + the jump button must stay disabled. Repeat with two windows whose titles and dimensions match. +6. Change the shortcut in Preferences with a LiveView connected. The new keys must work + at once, the old ones must reach other applications again, and the button tooltip + must name the new keys. +7. Disconnect every LiveView, then close Whiteboard, and confirm another instance or + application can register the shortcut each time. + +References: [foreground activation and virtual desktops](https://devblogs.microsoft.com/oldnewthing/20171002-00/?p=97116), +[capture by HWND](https://learn.microsoft.com/en-us/windows/win32/api/windows.graphics.capture.interop/nf-windows-graphics-capture-interop-igraphicscaptureiteminterop-createforwindow), +[global hotkey registration](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey). diff --git a/docs/microsoft-whiteboard-import.md b/docs/microsoft-whiteboard-import.md index 3b30953..e3399ec 100644 --- a/docs/microsoft-whiteboard-import.md +++ b/docs/microsoft-whiteboard-import.md @@ -152,8 +152,8 @@ Windows client offers, from `paleYellowGradient` (#FEE15A) to `grayGradient` (#C Coordinates stay in canvas pixels, one to one with board units, so a 4-pixel Microsoft pen is as wide as the 4-unit pen here. A new board puts the export's top-left corner at the -origin. A stroke that touches exactly one imported container travels with it, which is the -rule for a stroke drawn by hand. +origin. A stroke that touches exactly one imported container travels with it. This import rule differs from the +rule for newly drawn strokes, which link to the frontmost container they touch. **Shape kinds** are read from the outline, because the shape's name on the page is written in the language of whoever made the board. Curves with straight sides are a tube diff --git a/site/guide.html b/site/guide.html index 4b08f76..3741319 100644 --- a/site/guide.html +++ b/site/guide.html @@ -195,11 +195,11 @@

Pin a live demo without leaving the board

Keep ink on the slide you are discussing

-

A finished stroke that touches only one container (an image, a text block, or a LiveView) travels with that container when you move or resize it. A stroke that crosses two containers stays on the canvas. Delete the container and its linked ink goes with it. Undo treats the whole operation as one step.

+

A finished stroke travels with the frontmost container it touches when you move or resize that container. Containers underneath do not take the stroke. Delete the container and its linked ink goes with it. Undo treats the whole operation as one step.

- + Ink linked to a container @@ -245,7 +245,7 @@

Keep ink on the slide you are discussing

1 sits wholly inside the chart container, so it travels with it. The dashed outline is where the container was.

-

2 crosses into the notes container, so it stays on the canvas.

+

2 touches both containers and links to the notes container, which is in front.

@@ -969,7 +969,7 @@

Shapes, connectors, and text

Select comes back once one object is drawn, and Escape returns to Select at any time. Preferences → Toolbar keeps it for the next one instead, adds Insert to the floating palette, or pins the Insert row into a second palette you can drag anywhere. Shapes, connectors, and labels are saved in the board, undone with everything else, and exported to a deck or a PDF as objects you can select and change — in PowerPoint the straight arrows are still attached to their shapes.

LiveView

-

View → LiveView captures a window or a display. The container behaves like an image: move, resize, frame, delete, undo.

+

View → LiveView captures a window or a display. When the captured window can be identified uniquely, Go to source window opens it, and Ctrl+Alt+Shift+W switches between it and Whiteboard, resuming the feed each time you return. Each jump follows the window to its virtual desktop, and Preferences → Live View offers two other keys. The container behaves like an image: move, resize, frame, delete, undo.

Turn on Preferences → Live View → Pause when Whiteboard loses focus to stop capture while you use another application and keep the last frame visible. Returning to Whiteboard resumes the views that were playing, leaving manually paused views paused. Whiteboard's own dialogs do not interrupt capture.

diff --git a/site/shortcuts.html b/site/shortcuts.html index 271bad4..acdc8d2 100644 --- a/site/shortcuts.html +++ b/site/shortcuts.html @@ -86,6 +86,12 @@