Release v4.5: import shortcuts on pre-4.4 upgrade + clearer shortcuts dialog

- Pre-v4.4 upgraders are offered a one-time dialog to copy their keyboard shortcuts
  from one of their profiles (still readable in the profile files) instead of being
  reset. Users who already went through v4.4's reset are deliberately NOT re-offered
  (gated on KeyboardShortcutsGlobalNoticeShown). New KeyboardShortcutImportDialog +
  AppConfig.KeyboardShortcutsImportOffered + MainFormHotkeyController.ReloadAndReRegisterAll.
- Keyboard shortcuts dialog: new "Clear this shortcut" button; Delete inside the
  capture box leaves a shortcut unassigned.
- Relabelled the three RemSound-app remote rows to "Send remote RemSound volume/..."
  to distinguish them from the Windows-global ones.
- Manual (readme.html + MANUAL.md), About changelog, RELEASE_NOTES updated; version 4.5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-06-22 06:36:00 +01:00
co-authored by Claude Opus 4.8
parent 8a1bc0c813
commit 962f35ab80
10 changed files with 362 additions and 72 deletions
+10 -10
View File
@@ -69,7 +69,7 @@ Let's assume you and a friend both have RemSound running, and that your two comp
## 3. Profiles ## 3. Profiles
RemSound saves your whole setup — which devices are ticked, whether you're sending or receiving, your sound quality settings, delay targets, hotkeys, your ASIO driver choice, remembered peers, currently connected peers — into a single settings file. Each saved setup is called a _profile_. You choose which profile to load every time you start the program. You might keep one profile for “morning podcast” and another for “evening jam session”, each with a different mix of devices ticked, and switch between them in a couple of clicks. RemSound saves your whole setup — which devices are ticked, whether you're sending or receiving, your sound quality settings, delay targets, your ASIO driver choice, remembered peers, currently connected peers — into a single settings file. Each saved setup is called a _profile_. You choose which profile to load every time you start the program. You might keep one profile for “morning podcast” and another for “evening jam session”, each with a different mix of devices ticked, and switch between them in a couple of clicks. (Your keyboard shortcuts are the one thing that _isn't_ saved per profile — from version 4.4 they're shared across all your profiles; see Global hotkeys.)
### The startup picker ### The startup picker
@@ -89,7 +89,7 @@ The first profile in the list is highlighted to begin with, so on a fresh instal
### What “New profile” means ### What “New profile” means
A new profile is a one-off session with all the defaults: nothing ticked in any device list, neither Receive nor Send turned on, the standard sound settings, no ASIO driver chosen, no remembered peers, and the standard hotkeys. You'd pick it for a quick session you don't plan to save, or as a clean starting point for a new profile. The Save button is hidden while you're on a new profile — there's no existing setup to update, only a new one to save. A new profile is a one-off session with all the defaults: nothing ticked in any device list, neither Receive nor Send turned on, the standard sound settings, no ASIO driver chosen, and no remembered peers. (Your keyboard shortcuts aren't part of a profile, so starting a new profile doesn't change them.) You'd pick it for a quick session you don't plan to save, or as a clean starting point for a new profile. The Save button is hidden while you're on a new profile — there's no existing setup to update, only a new one to save.
**Starting a new profile later:** the picker only appears at startup, and if you've set RemSound to _start in a specific profile_ you skip straight past it. So to start a brand-new profile at any time, use **File → New profile** (Ctrl+N, or Alt+F, W) — it opens a fresh, default session, ready for you to set up and then Save as. If your current profile has unsaved changes, it offers to save them first. **Starting a new profile later:** the picker only appears at startup, and if you've set RemSound to _start in a specific profile_ you skip straight past it. So to start a brand-new profile at any time, use **File → New profile** (Ctrl+N, or Alt+F, W) — it opens a fresh, default session, ready for you to set up and then Save as. If your current profile has unsaved changes, it offers to save them first.
@@ -127,7 +127,7 @@ The folder named after your computer keeps each machine's profiles separate. If
You can also **copy a profile file from one computer to another** : drop it into the other computer's profile folder and it will appear in that computer's startup dialog. If the other computer doesn't have the same equipment (different sound cards, different ASIO drivers), those device choices are simply skipped when the profile loads — RemSound won't show an error or a warning, the relevant lists just won't have those items ticked. You can also **copy a profile file from one computer to another** : drop it into the other computer's profile folder and it will appear in that computer's startup dialog. If the other computer doesn't have the same equipment (different sound cards, different ASIO drivers), those device choices are simply skipped when the profile loads — RemSound won't show an error or a warning, the relevant lists just won't have those items ticked.
> **Tip:** profile files are plain text and readable by people. If you ever want to change something by hand (for example, a hotkey) without opening the app, you can open the file in any text editor. > **Tip:** profile files are plain text and readable by people. If you ever want to change something by hand (for example, a remembered peer) without opening the app, you can open the file in any text editor.
### What is NOT saved in a profile ### What is NOT saved in a profile
@@ -768,9 +768,9 @@ Alt+F4| Close (the standard Windows shortcut)
## 15. Global hotkeys (work even when minimised) ## 15. Global hotkeys (work even when minimised)
Your keyboard shortcuts are **shared across all your profiles** — set one once and it works on every profile, and stays put when you switch between them. (Before version 4.4 they were saved separately inside each profile, so a shortcut set on one profile wouldn't work on another. If you're upgrading, your shortcuts will have gone back to their defaults the first time you run the new version — just set the ones you use again, once.) Your keyboard shortcuts are **shared across all your profiles** — set one once and it works on every profile, and stays put when you switch between them. (Before version 4.4 they were saved separately inside each profile, so a shortcut set on one profile wouldn't work on another. If you're upgrading from before version 4.4, the first time you run the new version RemSound offers to **bring your shortcuts across** : it shows a list of your profiles, and you pick the one you set your shortcuts up in — or choose to start fresh with the defaults.)
You set these up in the Keyboard shortcuts dialog (Ctrl+K, or Options → Keyboard shortcuts). The dialog is a single list of every hotkey you can set: **Enter** sets the highlighted row, **Del** clears it (back to _not set_), and **Escape** or the Close button closes the dialog. The defaults: You set these up in the Keyboard shortcuts dialog (Ctrl+K, or Options → Keyboard shortcuts). The dialog is a single list of every hotkey you can set: **Enter** sets the highlighted row, and **Del** — or the **Clear this shortcut** button — clears it (back to _not set_). When you're setting a shortcut, you can press **Delete** inside that box to leave it unassigned. **Escape** or the Close button closes the dialog. The defaults:
Hotkey| Action| Default Hotkey| Action| Default
---|---|--- ---|---|---
@@ -780,9 +780,9 @@ Tray toggle| Show / hide the main window| Ctrl+Shift+F10
Quick profile switch| Pop up a list of all your profiles and switch to one — works from anywhere, even with RemSound in the tray (where it stays after the switch). See _Quick profile switch_ below.| Unset Quick profile switch| Pop up a list of all your profiles and switch to one — works from anywhere, even with RemSound in the tray (where it stays after the switch). See _Quick profile switch_ below.| Unset
Volume up / down| Adjust this computer's received-sound volume| Unset Volume up / down| Adjust this computer's received-sound volume| Unset
Start / Stop recording| Start or stop a recording on this computer. The same toggle as the Record menu's start/stop item and the in-app Ctrl+R, but it works system-wide (RemSound doesn't need to be the active window). See Recording to a file for what gets captured.| Unset Start / Stop recording| Start or stop a recording on this computer. The same toggle as the Record menu's start/stop item and the in-app Ctrl+R, but it works system-wide (RemSound doesn't need to be the active window). See Recording to a file for what gets captured.| Unset
Send remote volume up to peers| Tell every connected peer to raise their RemSound volume slider by 5 points (only obeyed by peers that have ticked “Accept remote volume commands”). It doesn't change your own volume. See Remote control.| Unset Send remote RemSound volume up to peers| Tell every connected peer to raise their RemSound volume slider by 5 points (only obeyed by peers that have ticked “Accept remote volume commands”). It doesn't change your own volume. See Remote control.| Unset
Send remote volume down to peers| The same, but lowering.| Unset Send remote RemSound volume down to peers| The same, but lowering.| Unset
Send remote receive mute toggle to peers| Tell every connected peer to toggle their RemSound receive mute.| Unset Send remote RemSound receive mute toggle to peers| Tell every connected peer to toggle their RemSound receive mute.| Unset
Send Windows global volume up to peers| Tell every connected peer to nudge their _Windows_ volume up by one step (about 2%, the same as their keyboard volume key). This affects every app on the receiving computer, not just RemSound. Hold the hotkey down for bigger jumps. See Remote control.| Unset Send Windows global volume up to peers| Tell every connected peer to nudge their _Windows_ volume up by one step (about 2%, the same as their keyboard volume key). This affects every app on the receiving computer, not just RemSound. Hold the hotkey down for bigger jumps. See Remote control.| Unset
Send Windows global volume down to peers| The same, but lowering.| Unset Send Windows global volume down to peers| The same, but lowering.| Unset
Send Windows global mute toggle to peers| Tell every connected peer to toggle their Windows mute.| Unset Send Windows global mute toggle to peers| Tell every connected peer to toggle their Windows mute.| Unset
@@ -829,8 +829,8 @@ Both sets target the receiving computer. Neither one changes anything on the sen
1. On the computer that should _respond_ to remote commands (the one you're listening on — the laptop in the example): open **Preferences** (Ctrl+P) and tick **Accept remote volume commands from peers**. Save the profile (Ctrl+S) so the choice sticks. (One toggle covers both kinds of remote command.) 1. On the computer that should _respond_ to remote commands (the one you're listening on — the laptop in the example): open **Preferences** (Ctrl+P) and tick **Accept remote volume commands from peers**. Save the profile (Ctrl+S) so the choice sticks. (One toggle covers both kinds of remote command.)
2. On the computer that should _send_ remote commands (the one your keyboard is driving — the desktop in the example): open the **Keyboard shortcuts** dialog (Ctrl+K). Set whichever of the six remote-control rows you want: 2. On the computer that should _send_ remote commands (the one your keyboard is driving — the desktop in the example): open the **Keyboard shortcuts** dialog (Ctrl+K). Set whichever of the six remote-control rows you want:
* **Send remote volume up / down to peers** — nudges the receiver's RemSound slider. * **Send remote RemSound volume up / down to peers** — nudges the receiver's RemSound slider.
* **Send remote receive mute toggle to peers** — toggles the receiver's RemSound mute. * **Send remote RemSound receive mute toggle to peers** — toggles the receiver's RemSound mute.
* **Send Windows global volume up / down to peers** — nudges the receiver's Windows volume. * **Send Windows global volume up / down to peers** — nudges the receiver's Windows volume.
* **Send Windows global mute toggle to peers** — toggles the receiver's Windows mute. * **Send Windows global mute toggle to peers** — toggles the receiver's Windows mute.
Use whatever key combinations you prefer (for example Ctrl+Shift+Up / Ctrl+Shift+Down for one set, and Ctrl+Alt+Up / Ctrl+Alt+Down for the other). These are global hotkeys: they work as long as RemSound is running, no matter which app is in front. Use whatever key combinations you prefer (for example Ctrl+Shift+Up / Ctrl+Shift+Down for one set, and Ctrl+Alt+Up / Ctrl+Alt+Down for the other). These are global hotkeys: they work as long as RemSound is running, no matter which app is in front.
+16 -7
View File
@@ -1,25 +1,34 @@
# RemSound v4.4 # RemSound v4.5
Keyboard shortcuts are now shared across all your profiles. Keyboard shortcuts get easier to manage — and people upgrading from before 4.4 no longer lose theirs.
Until now, shortcuts were saved separately inside each profile — so a shortcut you set on one profile wouldn't work on another, and switching profiles could make a shortcut seem to disappear. From this version they're one set shared by the whole app: set a shortcut once and it works on every profile, and stays put when you switch. This is what people asked for. ## Bring your shortcuts across when you upgrade
**Because of this change, shortcuts have gone back to their defaults.** If you'd set up any of your own, please set them again in Options → Keyboard shortcuts (Ctrl+K) — you only need to do it once, and a reminder shows the first time you run this version. (Brand-new installs aren't affected.) In version 4.4, keyboard shortcuts moved from being saved per-profile to one shared set for the whole app. If you're updating **from before 4.4**, RemSound now offers — the first time you run it — to **bring your shortcuts across** from one of your existing profiles: it lists your profiles, you pick the one you set your shortcuts up in, or choose to start fresh. (If you already updated to 4.4, nothing changes for you here.)
## A clearer Keyboard shortcuts dialog
- A new **Clear this shortcut** button next to Close, so clearing a shortcut is discoverable — you no longer have to know the Del key.
- When you're setting a shortcut, pressing **Delete** in that box now leaves it unassigned.
## Clearer remote-control labels
The three remote-control rows that adjust a peer's **RemSound** volume now say so — "Send remote RemSound volume up / down to peers" and "Send remote RemSound receive mute toggle to peers" — so they're easy to tell apart from the "Windows global volume" rows.
## Compatibility ## Compatibility
**v4.4 talks to v3.3 through v4.3 with no trouble** — the over-the-network format is unchanged, so you don't have to update both ends at once. (Everyone still needs **v3.3 or newer**, where end-to-end encryption came in.) **v4.5 talks to v3.3 through v4.4 with no trouble** — the over-the-network format is unchanged, so you don't have to update both ends at once. (Everyone still needs **v3.3 or newer**, where end-to-end encryption came in.)
## Install ## Install
1. Download `RemSound-v4.4.zip` from this release. 1. Download `RemSound-v4.5.zip` from this release.
2. Close RemSound. 2. Close RemSound.
3. Extract the zip **over your existing RemSound folder**, overwriting program files when prompted. The zip is program files only — it won't touch your settings, profiles, logs or recordings. 3. Extract the zip **over your existing RemSound folder**, overwriting program files when prompted. The zip is program files only — it won't touch your settings, profiles, logs or recordings.
4. Run `RemSound.exe`. 4. Run `RemSound.exe`.
## Upgrading ## Upgrading
**From v3.6 or newer:** Help → Check for updates installs v4.4 with the in-app updater — and if it can't finish, it puts your old version back exactly as it was. **From v3.6 or newer:** Help → Check for updates installs v4.5 with the in-app updater — and if it can't finish, it puts your old version back exactly as it was.
**From v1.9v3.5:** Check for updates works, but uses your current version's older updater for this one hop. If auto-update has been failing on your machine, install by hand using the steps above. **From v1.9v3.5:** Check for updates works, but uses your current version's older updater for this one hop. If auto-update has been failing on your machine, install by hand using the steps above.
+10 -10
View File
@@ -92,7 +92,7 @@ ul, ol { padding-left: 1.4em; }
<h2 id="profiles">3. Profiles</h2> <h2 id="profiles">3. Profiles</h2>
<p>RemSound saves your whole setup &mdash; which devices are ticked, whether you're sending or receiving, your sound quality settings, delay targets, hotkeys, your ASIO driver choice, remembered peers, currently connected peers &mdash; into a single settings file. Each saved setup is called a <em>profile</em>. You choose which profile to load every time you start the program. You might keep one profile for &ldquo;morning podcast&rdquo; and another for &ldquo;evening jam session&rdquo;, each with a different mix of devices ticked, and switch between them in a couple of clicks.</p> <p>RemSound saves your whole setup &mdash; which devices are ticked, whether you're sending or receiving, your sound quality settings, delay targets, your ASIO driver choice, remembered peers, currently connected peers &mdash; into a single settings file. Each saved setup is called a <em>profile</em>. You choose which profile to load every time you start the program. You might keep one profile for &ldquo;morning podcast&rdquo; and another for &ldquo;evening jam session&rdquo;, each with a different mix of devices ticked, and switch between them in a couple of clicks. (Your keyboard shortcuts are the one thing that <em>isn't</em> saved per profile &mdash; from version 4.4 they're shared across all your profiles; see <a href="#hotkeys">Global hotkeys</a>.)</p>
<h3>The startup picker</h3> <h3>The startup picker</h3>
@@ -113,7 +113,7 @@ ul, ol { padding-left: 1.4em; }
<h3>What &ldquo;New profile&rdquo; means</h3> <h3>What &ldquo;New profile&rdquo; means</h3>
<p>A new profile is a one-off session with all the defaults: nothing ticked in any device list, neither Receive nor Send turned on, the standard sound settings, no ASIO driver chosen, no remembered peers, and the standard hotkeys. You'd pick it for a quick session you don't plan to save, or as a clean starting point for a new profile. The Save button is hidden while you're on a new profile &mdash; there's no existing setup to update, only a new one to save.</p> <p>A new profile is a one-off session with all the defaults: nothing ticked in any device list, neither Receive nor Send turned on, the standard sound settings, no ASIO driver chosen, and no remembered peers. (Your keyboard shortcuts aren't part of a profile, so starting a new profile doesn't change them.) You'd pick it for a quick session you don't plan to save, or as a clean starting point for a new profile. The Save button is hidden while you're on a new profile &mdash; there's no existing setup to update, only a new one to save.</p>
<p><strong>Starting a new profile later:</strong> the picker only appears at startup, and if you've set RemSound to <em>start in a specific profile</em> you skip straight past it. So to start a brand-new profile at any time, use <strong>File &rarr; New profile</strong> (Ctrl+N, or Alt+F, W) &mdash; it opens a fresh, default session, ready for you to set up and then Save as. If your current profile has unsaved changes, it offers to save them first.</p> <p><strong>Starting a new profile later:</strong> the picker only appears at startup, and if you've set RemSound to <em>start in a specific profile</em> you skip straight past it. So to start a brand-new profile at any time, use <strong>File &rarr; New profile</strong> (Ctrl+N, or Alt+F, W) &mdash; it opens a fresh, default session, ready for you to set up and then Save as. If your current profile has unsaved changes, it offers to save them first.</p>
@@ -153,7 +153,7 @@ ul, ol { padding-left: 1.4em; }
<p>You can also <strong>copy a profile file from one computer to another</strong>: drop it into the other computer's profile folder and it will appear in that computer's startup dialog. If the other computer doesn't have the same equipment (different sound cards, different ASIO drivers), those device choices are simply skipped when the profile loads &mdash; RemSound won't show an error or a warning, the relevant lists just won't have those items ticked.</p> <p>You can also <strong>copy a profile file from one computer to another</strong>: drop it into the other computer's profile folder and it will appear in that computer's startup dialog. If the other computer doesn't have the same equipment (different sound cards, different ASIO drivers), those device choices are simply skipped when the profile loads &mdash; RemSound won't show an error or a warning, the relevant lists just won't have those items ticked.</p>
<div class="note"> <div class="note">
<strong>Tip:</strong> profile files are plain text and readable by people. If you ever want to change something by hand (for example, a hotkey) without opening the app, you can open the file in any text editor. <strong>Tip:</strong> profile files are plain text and readable by people. If you ever want to change something by hand (for example, a remembered peer) without opening the app, you can open the file in any text editor.
</div> </div>
<h3>What is NOT saved in a profile</h3> <h3>What is NOT saved in a profile</h3>
@@ -810,9 +810,9 @@ Audient USB Audio ASIO Driver &mdash; Pair 3 (channels 5/6): Loop-back 1 (L) / L
<h2 id="hotkeys">15. Global hotkeys (work even when minimised)</h2> <h2 id="hotkeys">15. Global hotkeys (work even when minimised)</h2>
<p>Your keyboard shortcuts are <strong>shared across all your profiles</strong> — set one once and it works on every profile, and stays put when you switch between them. (Before version 4.4 they were saved separately inside each profile, so a shortcut set on one profile wouldn't work on another. If you're upgrading, your shortcuts will have gone back to their defaults the first time you run the new version — just set the ones you use again, once.)</p> <p>Your keyboard shortcuts are <strong>shared across all your profiles</strong> — set one once and it works on every profile, and stays put when you switch between them. (Before version 4.4 they were saved separately inside each profile, so a shortcut set on one profile wouldn't work on another. If you're upgrading from before version 4.4, the first time you run the new version RemSound offers to <strong>bring your shortcuts across</strong>: it shows a list of your profiles, and you pick the one you set your shortcuts up in &mdash; or choose to start fresh with the defaults.)</p>
<p>You set these up in the Keyboard shortcuts dialog (Ctrl+K, or Options &rarr; Keyboard shortcuts). The dialog is a single list of every hotkey you can set: <strong>Enter</strong> sets the highlighted row, <strong>Del</strong> clears it (back to <em>not set</em>), and <strong>Escape</strong> or the Close button closes the dialog. The defaults:</p> <p>You set these up in the Keyboard shortcuts dialog (Ctrl+K, or Options &rarr; Keyboard shortcuts). The dialog is a single list of every hotkey you can set: <strong>Enter</strong> sets the highlighted row, and <strong>Del</strong> &mdash; or the <strong>Clear this shortcut</strong> button &mdash; clears it (back to <em>not set</em>). When you're setting a shortcut, you can press <strong>Delete</strong> inside that box to leave it unassigned. <strong>Escape</strong> or the Close button closes the dialog. The defaults:</p>
<table> <table>
<tr><th>Hotkey</th><th>Action</th><th>Default</th></tr> <tr><th>Hotkey</th><th>Action</th><th>Default</th></tr>
@@ -822,9 +822,9 @@ Audient USB Audio ASIO Driver &mdash; Pair 3 (channels 5/6): Loop-back 1 (L) / L
<tr><td>Quick profile switch</td><td>Pop up a list of all your profiles and switch to one &mdash; works from anywhere, even with RemSound in the tray (where it stays after the switch). See <em>Quick profile switch</em> below.</td><td>Unset</td></tr> <tr><td>Quick profile switch</td><td>Pop up a list of all your profiles and switch to one &mdash; works from anywhere, even with RemSound in the tray (where it stays after the switch). See <em>Quick profile switch</em> below.</td><td>Unset</td></tr>
<tr><td>Volume up / down</td><td>Adjust this computer's received-sound volume</td><td>Unset</td></tr> <tr><td>Volume up / down</td><td>Adjust this computer's received-sound volume</td><td>Unset</td></tr>
<tr><td>Start / Stop recording</td><td>Start or stop a recording on this computer. The same toggle as the Record menu's start/stop item and the in-app Ctrl+R, but it works system-wide (RemSound doesn't need to be the active window). See <a href="#recording">Recording to a file</a> for what gets captured.</td><td>Unset</td></tr> <tr><td>Start / Stop recording</td><td>Start or stop a recording on this computer. The same toggle as the Record menu's start/stop item and the in-app Ctrl+R, but it works system-wide (RemSound doesn't need to be the active window). See <a href="#recording">Recording to a file</a> for what gets captured.</td><td>Unset</td></tr>
<tr><td>Send remote volume up to peers</td><td>Tell every connected peer to raise their RemSound volume slider by 5 points (only obeyed by peers that have ticked &ldquo;Accept remote volume commands&rdquo;). It doesn't change your own volume. See <a href="#remote-control">Remote control</a>.</td><td>Unset</td></tr> <tr><td>Send remote RemSound volume up to peers</td><td>Tell every connected peer to raise their RemSound volume slider by 5 points (only obeyed by peers that have ticked &ldquo;Accept remote volume commands&rdquo;). It doesn't change your own volume. See <a href="#remote-control">Remote control</a>.</td><td>Unset</td></tr>
<tr><td>Send remote volume down to peers</td><td>The same, but lowering.</td><td>Unset</td></tr> <tr><td>Send remote RemSound volume down to peers</td><td>The same, but lowering.</td><td>Unset</td></tr>
<tr><td>Send remote receive mute toggle to peers</td><td>Tell every connected peer to toggle their RemSound receive mute.</td><td>Unset</td></tr> <tr><td>Send remote RemSound receive mute toggle to peers</td><td>Tell every connected peer to toggle their RemSound receive mute.</td><td>Unset</td></tr>
<tr><td>Send Windows global volume up to peers</td><td>Tell every connected peer to nudge their <em>Windows</em> volume up by one step (about 2%, the same as their keyboard volume key). This affects every app on the receiving computer, not just RemSound. Hold the hotkey down for bigger jumps. See <a href="#remote-control">Remote control</a>.</td><td>Unset</td></tr> <tr><td>Send Windows global volume up to peers</td><td>Tell every connected peer to nudge their <em>Windows</em> volume up by one step (about 2%, the same as their keyboard volume key). This affects every app on the receiving computer, not just RemSound. Hold the hotkey down for bigger jumps. See <a href="#remote-control">Remote control</a>.</td><td>Unset</td></tr>
<tr><td>Send Windows global volume down to peers</td><td>The same, but lowering.</td><td>Unset</td></tr> <tr><td>Send Windows global volume down to peers</td><td>The same, but lowering.</td><td>Unset</td></tr>
<tr><td>Send Windows global mute toggle to peers</td><td>Tell every connected peer to toggle their Windows mute.</td><td>Unset</td></tr> <tr><td>Send Windows global mute toggle to peers</td><td>Tell every connected peer to toggle their Windows mute.</td><td>Unset</td></tr>
@@ -875,8 +875,8 @@ Audient USB Audio ASIO Driver &mdash; Pair 3 (channels 5/6): Loop-back 1 (L) / L
<li>On the computer that should <em>respond</em> to remote commands (the one you're listening on &mdash; the laptop in the example): open <strong>Preferences</strong> (Ctrl+P) and tick <strong>Accept remote volume commands from peers</strong>. Save the profile (Ctrl+S) so the choice sticks. (One toggle covers both kinds of remote command.)</li> <li>On the computer that should <em>respond</em> to remote commands (the one you're listening on &mdash; the laptop in the example): open <strong>Preferences</strong> (Ctrl+P) and tick <strong>Accept remote volume commands from peers</strong>. Save the profile (Ctrl+S) so the choice sticks. (One toggle covers both kinds of remote command.)</li>
<li>On the computer that should <em>send</em> remote commands (the one your keyboard is driving &mdash; the desktop in the example): open the <strong>Keyboard shortcuts</strong> dialog (Ctrl+K). Set whichever of the six remote-control rows you want: <li>On the computer that should <em>send</em> remote commands (the one your keyboard is driving &mdash; the desktop in the example): open the <strong>Keyboard shortcuts</strong> dialog (Ctrl+K). Set whichever of the six remote-control rows you want:
<ul> <ul>
<li><strong>Send remote volume up / down to peers</strong> &mdash; nudges the receiver's RemSound slider.</li> <li><strong>Send remote RemSound volume up / down to peers</strong> &mdash; nudges the receiver's RemSound slider.</li>
<li><strong>Send remote receive mute toggle to peers</strong> &mdash; toggles the receiver's RemSound mute.</li> <li><strong>Send remote RemSound receive mute toggle to peers</strong> &mdash; toggles the receiver's RemSound mute.</li>
<li><strong>Send Windows global volume up / down to peers</strong> &mdash; nudges the receiver's Windows volume.</li> <li><strong>Send Windows global volume up / down to peers</strong> &mdash; nudges the receiver's Windows volume.</li>
<li><strong>Send Windows global mute toggle to peers</strong> &mdash; toggles the receiver's Windows mute.</li> <li><strong>Send Windows global mute toggle to peers</strong> &mdash; toggles the receiver's Windows mute.</li>
</ul> </ul>
+20
View File
@@ -20,6 +20,26 @@ internal sealed class AboutDialog : Form
/// updates" path.</summary> /// updates" path.</summary>
private const string ReleaseNotes = private const string ReleaseNotes =
""" """
RemSound v4.5
Keyboard shortcuts get easier to manage.
If you're updating from before version 4.4,
RemSound now offers to bring your shortcuts
across from one of your profiles instead of
resetting them pick the profile you set them
up in, or start fresh.
The Keyboard shortcuts dialog has a new "Clear
this shortcut" button, and when you're setting a
shortcut you can press Delete to leave it
unassigned.
And the three remote-control rows now name
RemSound "Send remote RemSound volume", and so
on so they're easy to tell apart from the
Windows-volume ones.
RemSound v4.4 RemSound v4.4
Keyboard shortcuts are now shared across all Keyboard shortcuts are now shared across all
@@ -0,0 +1,137 @@
using RemSound.Core;
namespace RemSound.App;
/// <summary>
/// One-time upgrade dialog: keyboard shortcuts moved from per-profile to machine-wide storage, so the
/// user is offered the choice of copying their shortcut set from one of their existing profiles (whose
/// old per-profile shortcuts are still readable in the profile files) — or starting fresh at the
/// defaults. Accessible: a profile list plus two clearly-labelled buttons, focus landing on the list.
/// </summary>
internal sealed class KeyboardShortcutImportDialog : Form
{
private readonly ListBox profileList = new()
{
IntegralHeight = false,
Width = 400,
Height = 150,
AccessibleName = "Profile to copy keyboard shortcuts from",
TabIndex = 0,
};
/// <summary>The profile the user chose to copy shortcuts from, or null if they chose to start fresh.
/// Only meaningful when <see cref="Form.ShowDialog()"/> returned <see cref="DialogResult.OK"/>.</summary>
public string? ChosenProfileTitle { get; private set; }
public KeyboardShortcutImportDialog(IReadOnlyList<string> profileTitles)
{
Text = "Keyboard shortcuts";
AccessibleName = "Bring your keyboard shortcuts across";
AccessibleRole = AccessibleRole.Dialog;
FormBorderStyle = FormBorderStyle.FixedDialog;
MinimizeBox = false;
MaximizeBox = false;
ShowInTaskbar = false;
StartPosition = FormStartPosition.CenterScreen;
KeyPreview = true;
ClientSize = new Size(470, 330);
var info = new Label
{
AutoSize = true,
MaximumSize = new Size(440, 0),
Text = "Keyboard shortcuts are now shared across all your profiles, instead of being saved "
+ "separately in each one.\n\n"
+ "You can copy your shortcuts from one of your existing profiles, or start fresh with "
+ "the defaults. Pick a profile below, then choose what to do.",
};
var listLabel = new MnemonicLabel
{
Text = "Copy shortcuts from this &profile:",
AutoSize = true,
Anchor = AnchorStyles.Left,
MnemonicTarget = profileList,
};
foreach (var t in profileTitles) profileList.Items.Add(t);
if (profileList.Items.Count > 0) profileList.SelectedIndex = 0;
var useButton = new Button
{
Text = "&Use the shortcuts from this profile",
AccessibleName = "Use the shortcuts from this profile",
AutoSize = true,
TabIndex = 1,
};
useButton.Click += (_, _) =>
{
if (profileList.SelectedItem is string title)
{
ChosenProfileTitle = title;
DialogResult = DialogResult.OK;
Close();
}
};
var freshButton = new Button
{
Text = "Start &fresh with the defaults",
AccessibleName = "Start fresh with the defaults",
AutoSize = true,
TabIndex = 2,
};
freshButton.Click += (_, _) =>
{
ChosenProfileTitle = null;
DialogResult = DialogResult.OK;
Close();
};
var buttons = new FlowLayoutPanel
{
Dock = DockStyle.Fill,
FlowDirection = FlowDirection.LeftToRight,
AutoSize = true,
Padding = new Padding(0, 8, 0, 0),
};
buttons.Controls.Add(useButton);
buttons.Controls.Add(freshButton);
var layout = new TableLayoutPanel
{
Dock = DockStyle.Fill,
Padding = new Padding(12),
ColumnCount = 1,
RowCount = 4,
};
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
layout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
layout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
layout.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
layout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
layout.Controls.Add(info, 0, 0);
layout.Controls.Add(listLabel, 0, 1);
layout.Controls.Add(profileList, 0, 2);
layout.Controls.Add(buttons, 0, 3);
Controls.Add(layout);
AcceptButton = useButton;
// Escape leaves the choice unmade — the caller treats a non-OK result as "ask again next launch",
// so the user is never forced into a decision they didn't mean to make.
KeyDown += (_, e) =>
{
if (e.KeyCode == Keys.Escape) { DialogResult = DialogResult.Cancel; Close(); e.Handled = true; e.SuppressKeyPress = true; }
};
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
// Land focus on the profile list so NVDA announces the dialog and the first profile.
ActiveControl = null;
profileList.Focus();
WinEventNotifier.NotifyFocus(profileList);
}
}
+102 -37
View File
@@ -1381,7 +1381,7 @@ public sealed class MainForm : Form
private void RunStartupNotices() private void RunStartupNotices()
{ {
if (IsDisposed) return; if (IsDisposed) return;
MaybeShowKeyboardShortcutsGlobalNotice(); MaybeOfferKeyboardShortcutImport();
if (IsDisposed) return; if (IsDisposed) return;
MaybeShowWhatsNewAfterUpdate(); MaybeShowWhatsNewAfterUpdate();
if (IsDisposed) return; if (IsDisposed) return;
@@ -1433,53 +1433,118 @@ public sealed class MainForm : Form
} }
} }
/// <summary>One-time notice (v4.4) telling upgraders that keyboard shortcuts have moved from /// <summary>One-time upgrade flow (replaces the v4.4 reset notice): keyboard shortcuts moved from
/// per-profile to machine-wide storage (issue #14), so their shortcuts have reset to defaults and /// per-profile to machine-wide storage (issue #14). Offers upgraders the choice of copying their
/// need re-setting. Shown once to anyone who ran an earlier version; on a brand-new install (which /// shortcuts from one of their existing profiles (still readable in the profile files) or starting
/// has nothing to reset) it's silently marked done and never shown. Must run BEFORE /// fresh. Only offered to people coming straight from a PRE-v4.4 version (where shortcuts were still
/// <see cref="MaybeShowWhatsNewAfterUpdate"/>, which overwrites the LastWhatsNewVersion we read to /// per-profile), to spare them the reset — anyone who already went through v4.4's reset is left
/// tell upgraders apart from fresh installs.</summary> /// alone (re-offering would only annoy them), as is a fresh install or a user with no saved shortcuts
private void MaybeShowKeyboardShortcutsGlobalNotice() /// to import. Runs BEFORE <see cref="MaybeShowWhatsNewAfterUpdate"/>, which overwrites the
/// LastWhatsNewVersion we read to tell upgraders apart from fresh installs.</summary>
private void MaybeOfferKeyboardShortcutImport()
{ {
if (IsDisposed) return; if (IsDisposed) return;
AppConfig cfg; AppConfig cfg;
try { cfg = AppConfig.Load(); } try { cfg = AppConfig.Load(); }
catch { return; } catch { return; }
if (cfg.KeyboardShortcutsGlobalNoticeShown) return; if (cfg.KeyboardShortcutsImportOffered) return;
// A non-empty LastWhatsNewVersion means a previous version has run on this machine — i.e. this // Leave the v4.4 crowd alone. v4.4's reset set KeyboardShortcutsGlobalNoticeShown for everyone
// is an upgrade, so there were per-profile shortcuts that have now reset. A fresh install has it // who ran it; those people have already re-done their shortcuts, so re-offering an import would
// empty (it's set later, by MaybeShowWhatsNewAfterUpdate) and has nothing to reset. // only annoy them. We only want to catch people coming straight from a PRE-v4.4 version (where
// shortcuts were still per-profile), before they lose anything.
if (cfg.KeyboardShortcutsGlobalNoticeShown) { MarkShortcutImportOffered(); return; }
// Only relevant to upgraders (a previous version ran here, so LastWhatsNewVersion is set) who
// actually have old per-profile shortcuts to bring across.
var isUpgrade = !string.IsNullOrEmpty(cfg.LastWhatsNewVersion); var isUpgrade = !string.IsNullOrEmpty(cfg.LastWhatsNewVersion);
if (isUpgrade) if (!isUpgrade) { MarkShortcutImportOffered(); return; }
{
logFile.Event("keyboard shortcuts: showing one-time 'now shared across profiles' notice");
var page = new TaskDialogPage
{
Caption = "RemSound",
Heading = "Your keyboard shortcuts are now shared across profiles",
Text = "Keyboard shortcuts used to be saved separately for each profile, so a shortcut you set on one "
+ "profile wouldn't work on another. From this version they're shared across all your profiles "
+ "instead — one set for the whole app, which our users have requested.\n\n"
+ "Because of this change, your shortcuts have started fresh at their defaults. If you'd set up any "
+ "shortcuts of your own, please set them again in Options → Keyboard shortcuts (Ctrl+K). You only "
+ "need to do this once — from now on they'll stay put whatever profile you're on.",
Icon = TaskDialogIcon.Information,
Buttons = { TaskDialogButton.OK },
AllowCancel = true,
};
try { ForegroundDialog.Show(owner => TaskDialog.ShowDialog(owner, page)); }
catch (Exception ex) { logFile.Event($"keyboard shortcuts notice failed: {ex.GetType().Name}: {ex.Message}"); }
}
// Mark done either way (shown to upgraders, silently to fresh installs) so it's strictly one-time. var titles = ProfilesWithSavedShortcuts();
if (titles.Count == 0) { MarkShortcutImportOffered(); return; }
logFile.Event($"keyboard shortcuts: offering import from {titles.Count} profile(s) with saved shortcuts");
try try
{ {
var fresh = AppConfig.Load(); using var dlg = new KeyboardShortcutImportDialog(titles);
fresh.KeyboardShortcutsGlobalNoticeShown = true; var result = ForegroundDialog.Show(owner => dlg.ShowDialog(owner));
fresh.Save(); if (result != DialogResult.OK) return; // dismissed (Escape) — offer again next launch
if (dlg.ChosenProfileTitle is { } title)
{
var imported = ImportShortcutsFromProfile(title);
logFile.Event($"keyboard shortcuts: imported {imported} shortcut(s) from profile \"{title}\"");
hotkeyController.ReloadAndReRegisterAll();
} }
catch { /* harmless — at worst the notice shows again next launch */ } else
{
logFile.Event("keyboard shortcuts: user chose to start fresh with the defaults");
}
MarkShortcutImportOffered();
}
catch (Exception ex)
{
logFile.Event($"keyboard shortcuts import failed: {ex.GetType().Name}: {ex.Message}");
}
}
private static void MarkShortcutImportOffered()
{
try { var c = AppConfig.Load(); c.KeyboardShortcutsImportOffered = true; c.Save(); }
catch { /* harmless — at worst the offer shows again next launch */ }
}
/// <summary>Titles of profiles that have at least one customised keyboard shortcut saved in their
/// file (the only ones worth importing — unchanged shortcuts were stored as null).</summary>
private List<string> ProfilesWithSavedShortcuts()
{
var result = new List<string>();
if (profileStore is null) return result;
try
{
foreach (var title in profileStore.ListProfileTitles())
{
try
{
if (profileStore.Load(title) is { } p && ProfileHasAnyShortcut(p)) result.Add(title);
}
catch { /* skip an unreadable profile */ }
}
}
catch { /* enumeration failed — offer nothing */ }
return result;
}
private static bool ProfileHasAnyShortcut(Profile p) =>
p.ReceiveMuteHotkey is not null || p.SendMuteHotkey is not null || p.TrayHotkey is not null
|| p.VolumeUpHotkey is not null || p.VolumeDownHotkey is not null || p.ToggleRecordingHotkey is not null
|| p.RemoteVolumeUpHotkey is not null || p.RemoteVolumeDownHotkey is not null || p.RemoteMuteToggleHotkey is not null
|| p.SystemVolumeUpHotkey is not null || p.SystemVolumeDownHotkey is not null || p.SystemMuteToggleHotkey is not null
|| p.QuickProfileSwitchHotkey is not null || p.SpeakStatusLineHotkey is not null;
/// <summary>Copy a profile's saved (non-null) keyboard shortcuts into the machine-wide store, via the
/// settings store's now-global Save* methods. Returns how many were copied; shortcuts the profile
/// never customised (null) are left at the global default.</summary>
private int ImportShortcutsFromProfile(string title)
{
if (profileStore is null || profileStore.Load(title) is not { } p) return 0;
var n = 0;
void Copy(HotkeyRecord? rec, Action<HotkeyInfo> save) { if (rec is not null) { save(rec.ToHotkeyInfo()); n++; } }
Copy(p.ReceiveMuteHotkey, settings.SaveReceiveMuteHotkey);
Copy(p.SendMuteHotkey, settings.SaveSendMuteHotkey);
Copy(p.TrayHotkey, settings.SaveTrayHotkey);
Copy(p.VolumeUpHotkey, settings.SaveVolumeUpHotkey);
Copy(p.VolumeDownHotkey, settings.SaveVolumeDownHotkey);
Copy(p.ToggleRecordingHotkey, settings.SaveToggleRecordingHotkey);
Copy(p.RemoteVolumeUpHotkey, settings.SaveRemoteVolumeUpHotkey);
Copy(p.RemoteVolumeDownHotkey, settings.SaveRemoteVolumeDownHotkey);
Copy(p.RemoteMuteToggleHotkey, settings.SaveRemoteMuteToggleHotkey);
Copy(p.SystemVolumeUpHotkey, settings.SaveSystemVolumeUpHotkey);
Copy(p.SystemVolumeDownHotkey, settings.SaveSystemVolumeDownHotkey);
Copy(p.SystemMuteToggleHotkey, settings.SaveSystemMuteToggleHotkey);
Copy(p.QuickProfileSwitchHotkey, settings.SaveQuickProfileSwitchHotkey);
Copy(p.SpeakStatusLineHotkey, settings.SaveSpeakStatusLineHotkey);
return n;
} }
/// <summary>If the user opted in (<see cref="AppConfig.ShowWhatsNewAfterUpdate"/>) and the /// <summary>If the user opted in (<see cref="AppConfig.ShowWhatsNewAfterUpdate"/>) and the
+46 -5
View File
@@ -174,6 +174,41 @@ internal sealed class MainFormHotkeyController : IDisposable
RegisterSpeakStatusLineHotkey(); RegisterSpeakStatusLineHotkey();
} }
/// <summary>Re-read every hotkey from the (now machine-wide) settings store and re-register it.
/// Used after the one-time upgrade import writes a fresh set of shortcuts into the global config,
/// so the just-imported bindings take effect immediately without relaunching.</summary>
public void ReloadAndReRegisterAll()
{
sendMuteHotkey = settingsStore.LoadSendMuteHotkey();
receiveMuteHotkey = settingsStore.LoadReceiveMuteHotkey();
trayHotkey = settingsStore.LoadTrayHotkey();
volumeUpHotkey = settingsStore.LoadVolumeUpHotkey();
volumeDownHotkey = settingsStore.LoadVolumeDownHotkey();
toggleRecordingHotkey = settingsStore.LoadToggleRecordingHotkey();
remoteVolumeUpHotkey = settingsStore.LoadRemoteVolumeUpHotkey();
remoteVolumeDownHotkey = settingsStore.LoadRemoteVolumeDownHotkey();
remoteMuteToggleHotkey = settingsStore.LoadRemoteMuteToggleHotkey();
systemVolumeUpHotkey = settingsStore.LoadSystemVolumeUpHotkey();
systemVolumeDownHotkey = settingsStore.LoadSystemVolumeDownHotkey();
systemMuteToggleHotkey = settingsStore.LoadSystemMuteToggleHotkey();
quickProfileSwitchHotkey = settingsStore.LoadQuickProfileSwitchHotkey();
speakStatusLineHotkey = settingsStore.LoadSpeakStatusLineHotkey();
RegisterSendMuteHotkey();
RegisterReceiveMuteHotkey();
RegisterTrayHotkey();
RegisterVolumeUpHotkey();
RegisterVolumeDownHotkey();
RegisterToggleRecordingHotkey();
RegisterRemoteVolumeUpHotkey();
RegisterRemoteVolumeDownHotkey();
RegisterRemoteMuteToggleHotkey();
RegisterSystemVolumeUpHotkey();
RegisterSystemVolumeDownHotkey();
RegisterSystemMuteToggleHotkey();
RegisterQuickProfileSwitchHotkey();
RegisterSpeakStatusLineHotkey();
}
public void ShowKeyboardShortcutsDialog(IWin32Window dialogOwner) public void ShowKeyboardShortcutsDialog(IWin32Window dialogOwner)
{ {
// Modeled on the SpaceBlaster menu dialogs: // Modeled on the SpaceBlaster menu dialogs:
@@ -224,7 +259,7 @@ internal sealed class MainFormHotkeyController : IDisposable
var introLabel = new Label var introLabel = new Label
{ {
Text = "Arrow up and down to pick a shortcut. Press Enter to rebind it, Del to clear it. Escape closes the dialog.\n\n" Text = "Arrow up and down to pick a shortcut. Press Enter to rebind it, or Del (or the Clear this shortcut button) to clear it. Escape closes the dialog.\n\n"
+ "The remote-control rows send commands to connected peers; they only have an effect on peers that have 'Accept remote volume commands from peers' enabled.", + "The remote-control rows send commands to connected peers; they only have an effect on peers that have 'Accept remote volume commands from peers' enabled.",
AutoSize = true, AutoSize = true,
MaximumSize = new Size(600, 0), MaximumSize = new Size(600, 0),
@@ -249,8 +284,14 @@ internal sealed class MainFormHotkeyController : IDisposable
AutoSize = true, AutoSize = true,
Padding = new Padding(0, 8, 0, 0), Padding = new Padding(0, 8, 0, 0),
}; };
var closeButton = new Button { Text = "Close", AutoSize = true, DialogResult = DialogResult.OK, TabIndex = 1 }; var closeButton = new Button { Text = "Close", AutoSize = true, DialogResult = DialogResult.OK, TabIndex = 2 };
// Discoverable "clear" alongside the Del key — the Del shortcut isn't obvious to a screen-reader
// user. Clears whichever shortcut is selected in the list (UnsetSelected reads list.SelectedIndex,
// which the ListBox keeps even when focus is on this button).
var clearButton = new Button { Text = "&Clear this shortcut", AccessibleName = "Clear this shortcut", AutoSize = true, TabIndex = 1 };
clearButton.Click += (_, _) => UnsetSelected();
buttonsPanel.Controls.Add(closeButton); buttonsPanel.Controls.Add(closeButton);
buttonsPanel.Controls.Add(clearButton);
root.Controls.Add(buttonsPanel, 0, 2); root.Controls.Add(buttonsPanel, 0, 2);
dialog.Controls.Add(root); dialog.Controls.Add(root);
@@ -274,9 +315,9 @@ internal sealed class MainFormHotkeyController : IDisposable
list.Items.Add($"Volume up for received sound on this machine: {volumeUpHotkey}"); list.Items.Add($"Volume up for received sound on this machine: {volumeUpHotkey}");
list.Items.Add($"Volume down for received sound on this machine: {volumeDownHotkey}"); list.Items.Add($"Volume down for received sound on this machine: {volumeDownHotkey}");
list.Items.Add($"Start / Stop recording: {toggleRecordingHotkey}"); list.Items.Add($"Start / Stop recording: {toggleRecordingHotkey}");
list.Items.Add($"Send remote volume up to peers: {remoteVolumeUpHotkey}"); list.Items.Add($"Send remote RemSound volume up to peers: {remoteVolumeUpHotkey}");
list.Items.Add($"Send remote volume down to peers: {remoteVolumeDownHotkey}"); list.Items.Add($"Send remote RemSound volume down to peers: {remoteVolumeDownHotkey}");
list.Items.Add($"Send remote receive mute toggle to peers: {remoteMuteToggleHotkey}"); list.Items.Add($"Send remote RemSound receive mute toggle to peers: {remoteMuteToggleHotkey}");
list.Items.Add($"Send Windows global volume up to peers: {systemVolumeUpHotkey}"); list.Items.Add($"Send Windows global volume up to peers: {systemVolumeUpHotkey}");
list.Items.Add($"Send Windows global volume down to peers: {systemVolumeDownHotkey}"); list.Items.Add($"Send Windows global volume down to peers: {systemVolumeDownHotkey}");
list.Items.Add($"Send Windows global mute toggle to peers: {systemMuteToggleHotkey}"); list.Items.Add($"Send Windows global mute toggle to peers: {systemMuteToggleHotkey}");
+1 -1
View File
@@ -14,7 +14,7 @@
tag_name on the latest GitHub release; bump it on every public release. The tag_name on the latest GitHub release; bump it on every public release. The
AssemblyVersion / FileVersion default to this value, and Assembly.GetName().Version AssemblyVersion / FileVersion default to this value, and Assembly.GetName().Version
is what the About dialog and the updater both read. --> is what the About dialog and the updater both read. -->
<Version>4.4</Version> <Version>4.5</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+9 -1
View File
@@ -170,9 +170,17 @@ public sealed class AppConfig
/// <summary>True once the one-time "your keyboard shortcuts are now shared across profiles" notice /// <summary>True once the one-time "your keyboard shortcuts are now shared across profiles" notice
/// has been shown (to an upgrader), or silently marked done on a fresh install that had nothing to /// has been shown (to an upgrader), or silently marked done on a fresh install that had nothing to
/// reset. Stops the notice re-appearing. v4.4.</summary> /// reset. Stops the notice re-appearing. v4.4. (Superseded by the import offer below; kept so the
/// flag on an existing v4.4 config still deserialises.)</summary>
public bool KeyboardShortcutsGlobalNoticeShown { get; set; } public bool KeyboardShortcutsGlobalNoticeShown { get; set; }
/// <summary>True once the one-time "bring your keyboard shortcuts across?" import offer has been
/// resolved (the user chose to import from a profile, or to start fresh). Deliberately SEPARATE from
/// <see cref="KeyboardShortcutsGlobalNoticeShown"/> so that users who already updated to v4.4 (and
/// were reset) are STILL offered the chance to import their old per-profile shortcuts — which remain
/// readable in their profile files.</summary>
public bool KeyboardShortcutsImportOffered { get; set; }
/// <summary>If non-null and a profile with this title exists, RemSound skips the /// <summary>If non-null and a profile with this title exists, RemSound skips the
/// startup profile picker and loads this profile directly. Combine with /// startup profile picker and loads this profile directly. Combine with
/// <see cref="StartMinimised"/> + the Windows auto-start registry entry /// <see cref="StartMinimised"/> + the Windows auto-start registry entry
+11 -1
View File
@@ -18,7 +18,7 @@ public sealed class HotkeyCaptureForm : Form
KeyPreview = true; KeyPreview = true;
AccessibleName = "Change hotkey"; AccessibleName = "Change hotkey";
instructionLabel.Text = "Hold the full key combination, then release it to save it automatically."; instructionLabel.Text = "Hold the full key combination, then release it to save it automatically. Press Delete to leave this shortcut unassigned.";
instructionLabel.MaximumSize = new Size(360, 0); instructionLabel.MaximumSize = new Size(360, 0);
hotkeyTextBox.AccessibleName = "Current hotkey"; hotkeyTextBox.AccessibleName = "Current hotkey";
hotkeyTextBox.Text = "Press a hotkey combination."; hotkeyTextBox.Text = "Press a hotkey combination.";
@@ -89,6 +89,16 @@ public sealed class HotkeyCaptureForm : Form
if (key == Keys.Escape) { DialogResult = DialogResult.Cancel; Close(); return; } if (key == Keys.Escape) { DialogResult = DialogResult.Cancel; Close(); return; }
// Plain Delete (no modifiers) clears the binding — the action becomes unassigned, mirroring Del
// on the shortcuts list. Delete WITH modifiers is left to bind as a normal combination.
if (key == Keys.Delete && !control && !shift && !alt)
{
CapturedHotkey = HotkeyInfo.Unset;
DialogResult = DialogResult.OK;
Close();
return;
}
if (IsModifier(key)) if (IsModifier(key))
{ {
SawAnyModifier = true; SawAnyModifier = true;