Skip to content

Shortcuts

NuclearMeltdown edited this page Oct 2, 2026 · 13 revisions

Shortcuts

src/hotkeys.cpp, src/hotkeys.h

Defaults

These can be reassigned under Settings → Keys:

Key Action
Enter Fullscreen
Ctrl+Enter Borderless
F1 Statistics
F2 Settings
F3 Toolbar
F5 Restart capture
Shift+F5 Reinitialise card
F6 Measure colour range again
F7 Detect video standard
F8 Detect border
F9 Start / stop recording
F10 Screenshot
Ctrl+F10 Screenshot to the clipboard
F11 Freeze
F12 Compare filters
Shift+F12 All filters off
M Mute
+ / - Volume

These cannot:

Key Action
Esc Leave fullscreen, close the settings
Ctrl+1 … Ctrl+9 Switch profile
Ctrl+F Search, while the settings are open
Double click on the picture Fullscreen
Mouse wheel Volume
Right click Menu
Shift while resizing Keep the picture's shape
Dragging the picture Move the window, when borderless

F11, F12 and Shift+F12 are described on Freeze and compare, Ctrl+F on The settings window, the last two on The main window.

What is deliberately not rebindable

// Escape always leaves fullscreen and closes the dialog, and Ctrl+1..9 always
// picks a profile: both are conventions people expect to hold, and a binding
// editor that lets you break your way out of fullscreen is a trap rather than
// a feature.

That is the whole reasoning. A UI that lets you rebind Escape produces a program you can get stuck inside.

How bindings work

enum class HotkeyAction {
  Fullscreen, Settings, Stats, RestartCapture, ReinitCard, Record,
  Screenshot, ScreenshotClipboard, Freeze, Compare, BypassFilters,
  DetectCrop, DetectStandard, RemeasureRange, Mute, VolumeUp, VolumeDown, Count
};

struct HotkeyBinding {
  Key key = Key::None;  // None = unbound
  bool ctrl, shift, alt;
};

Seventeen actions, each with one binding, held in a Hotkeys struct indexed by the enum. HotkeyAction::Count doubles as "no action bound to this combination", which is what Hotkeys::Find() returns on a miss.

Key is qBlank's own list of keys (src/keys.h), not a Windows virtual-key code; src/keys_win32.cpp translates between the two. Up to 4.4 the binding held the virtual-key number itself.

Four of them earn their place by being needed exactly when a dialog is the last thing you want to open. Shift+F5 rebuilds the card's device list from scratch, for when a card was plugged in or re-enumerated after qBlank started. F8 measures the black border around the picture and crops to it — useful whenever a source changes size, because a crop is a count of source pixels and is dropped when that count stops meaning anything (see Cropping and geometry).

F7 runs the video standard search again from the start, both stages, even when the current standard holds and shows plenty of colour — the one case the automatic search cannot see, because colour that is wrong is still colour (see Automatic video standard).

F6 throws away the full-or-limited verdict and measures it again, for the case no automatic can see: an option in the card's own driver moves every black level in the picture and leaves the media type alone, so the frozen verdict goes on describing rules that stopped applying (see Colour range and matrix).

The three sit next to each other because they are the same kind of command: a measurement on the picture in front of you, triggered because you can see something the automation does not measure. F7 and F8 both need a real picture and neither decides anything on black. F6 is the exception, and for a reason worth knowing: the black end is precisely what it measures, so a black picture is not a poor one to measure on — it is the clearest there is.

A search started this way also says what it found — the standard and the reason, over the picture for five seconds, whichever of its exits it took. The automatic search reports with a toast and only when something changed; a key that was pressed on purpose gets an answer either way.

On a source that is already locked it takes under two seconds end to end, measured on a GameCube through a PEXHDCAP60L, and the standards visibly step past one another while it runs. It cost 6.0 s until 31.08., of which 2.7 s were spent before the first switch even happened — see Automatic video standard for what each half of that was and what replaced it.

Modifiers must match exactly — HotkeyBinding::Matches() compares all three, so F9 and Shift+F9 are different bindings rather than one swallowing the other.

Three kinds of name

Each action has three strings, and they are deliberately separate:

HotkeyActionName() the label in the settings and the context menu, in the current language
HotkeyActionKey() what is written to qBlank.json — language-independent and stable
HotkeyText() "Strg+Umschalt+F9", or empty when unbound

The middle one matters: a config file written in German and read in English has to name the same action. The first and third are display only.

The key itself is stored the same way, by name ("key": "F12"), since 5.0. Next to it the file still carries the old number ("vk"), for a qBlank older than 5.0 reading the same file after a downgrade. A file that has only the number, from before 5.0, is read as before, so an update keeps every binding.

The combination text comes from the keyboard layout through GetKeyNameTextW (KeyLabel() in src/keys_win32.cpp), so a French keyboard reads its own labels rather than a translation of the American ones. Keys the layout names badly or not at all — Enter, Space, the arrows, + and - — are named by SpecialKeyName() instead.

Keys that cannot be bound

IsReservedKey() returns true for keys that must not be swallowed as a shortcut:

  • Escape — fixed, for the reason above
  • The modifiers themselves — Ctrl, Shift, Alt and both Windows keys, left and right variants included. A modifier alone is not a shortcut
  • F4 — it would collide with Alt+F4

The binding editor refuses these rather than accepting them and behaving oddly later.

Discoverability

The context menu (right click) shows the same actions with their current combinations, so a rebound key is discoverable without opening the settings.

Compare filters is a submenu there, with the two directions inside. Its key stands on the submenu rather than on either direction, because F12 switches compare on in whichever direction was chosen last.

A double click on the picture toggles fullscreen, as in any video player. Both clicks have to land on the bare picture (App::DoubleClickFullscreen()): a first click that closed a menu or grabbed the compare divider would otherwise turn the second into a switch nobody asked for. A third click counts as a new first one. While the crop picker is open, clicks belong to it.

The toolbar

The button strip along the top is on by default, and everything it offers is also on a key — but a key you have to know about first. showToolbar in AppSettings turns it off for anyone who does.

The picture is fitted below the toolbar rather than drawn underneath it (VideoRenderer::SetTopInset()), so the bar never covers what you are playing.

The statistics overlay

F1 cycles StatsDetail, which has three levels:

StatsDetail Shows
Compact Frame rates and pipeline delay
Normal Those, plus capture format, colour handling and audio buffer
Full Everything, including device names and dropped frame counts

Normal is where a wrong colour range verdict becomes visible. The virtual camera reports itself elsewhere: Settings > Recording lists every program reading it, with the format each one negotiated.

Clone this wiki locally