// SPDX-License-Identifier: MIT #include "shortcuts.hpp" #include namespace udpscope { namespace { /// Bare letters are toggles, Ctrl is for files and windows. Nothing here shadows a key the /// plot's own controller handles ('+', '-', 'f', the arrows, Escape). constexpr Accel kAccels[] = { {GDK_KEY_space, 0, AppAction::PauseToggle, "space", "Pause or resume the display", "Acquisition"}, {GDK_KEY_a, 0, AppAction::TriggerArm, "a", "Arm or disarm the trigger", "Acquisition"}, {GDK_KEY_t, 0, AppAction::TriggerPanel, "t", "Enable or disable trigger mode", "Acquisition"}, {GDK_KEY_c, 0, AppAction::CursorsPane, "c", "Enable or disable the cursors", "Panes and editors"}, {GDK_KEY_m, 0, AppAction::ShowMeasure, "m", "Go to Measure", "Panes and editors"}, {GDK_KEY_g, 0, AppAction::ShowSignals, "g", "Go to Signals", "Panes and editors"}, {GDK_KEY_l, 0, AppAction::LayoutEditor, "l", "Show or hide the layout editor", "Panes and editors"}, {GDK_KEY_s, 0, AppAction::SidePanel, "s", "Show or hide the dock", "Panes and editors"}, {GDK_KEY_e, GDK_CONTROL_MASK, AppAction::Export, "e", "Export the visible range", "Files and windows"}, {GDK_KEY_F1, 0, AppAction::Help, "F1", "Open the documentation", "Files and windows"}, {GDK_KEY_slash, GDK_CONTROL_MASK, AppAction::Shortcuts, "slash", "Open this shortcut overview", "Files and windows"}, {GDK_KEY_t, GDK_CONTROL_MASK, AppAction::GuidedTour, "t", "Start the guided tour", "Files and windows"}, {GDK_KEY_h, GDK_CONTROL_MASK, AppAction::ContextualHelp, "h", "Turn the contextual help on or off", "Files and windows"}, {GDK_KEY_q, GDK_CONTROL_MASK, AppAction::Quit, "q", "Quit udpscope", "Files and windows"}, }; constexpr int kAccelCount = static_cast(sizeof(kAccels) / sizeof(kAccels[0])); /// The plot's own interactions, documentation only. The keyboard's modifiers are not the /// wheel's: '+' is shift+'=' on common layouts, so Shift could not mean anything there. /// /// A space-separated accelerator is the two-key alternative form the shortcut label draws /// as `+ / -`. The mouse rows carry no accelerator at all: neither GTK's accelerator syntax nor /// libadwaita's knows a wheel or a drag, and asking either to parse "Wheel" is a parse warning and an /// empty cell. The overview draws them from `src/ui/shortcuts.ui`, which gives each one GTK's generic /// gesture type and an icon where the keycaps would be. That file is the *presentation*; this table is /// what the application handles, which is why `[help]`'s `ui=` is checked against `tables=`. constexpr Gesture kGestures[] = { {"plus minus", "", "Zoom in or out, both axes", "Plot keyboard"}, {"plus minus", "", "Zoom the time axis only", "Plot keyboard"}, {"plus minus", "", "Zoom the value axis only", "Plot keyboard"}, {"Left Right", "", "Pan along time", "Plot keyboard"}, {"Up Down", "", "Pan along values", "Plot keyboard"}, {"f", "", "Fit the view to the data", "Plot keyboard"}, {"Escape", "", "Cancel the gesture in progress", "Plot keyboard"}, {"", "Wheel", "Zoom about the pointer, both axes", "Plot mouse"}, {"", "Shift and wheel", "Zoom the time axis only", "Plot mouse"}, {"", "Ctrl and wheel", "Zoom the value axis only", "Plot mouse"}, {"", "Drag", "Pan", "Plot mouse"}, {"", "Ctrl and drag", "Box zoom on time", "Plot mouse"}, {"", "Alt and drag", "Box zoom on values", "Plot mouse"}, {"", "Shift and drag", "Box zoom on time and values", "Plot mouse"}, }; constexpr int kGestureCount = static_cast(sizeof(kGestures) / sizeof(kGestures[0])); /// The only modifiers a table row may require. Lock, Num-Lock and the pointer buttons all /// arrive in the same mask and must be masked out or no row ever matches. constexpr unsigned kModMask = GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_ALT_MASK; } // namespace const Accel* app_accels(int* count) { if (count != nullptr) *count = kAccelCount; return kAccels; } const Gesture* plot_gestures(int* count) { if (count != nullptr) *count = kGestureCount; return kGestures; } const Accel* find_accel(unsigned keyval, unsigned mods) { const unsigned wanted = mods & kModMask; for (const Accel& accel : kAccels) { if (accel.keyval == keyval && accel.mods == wanted) return &accel; } return nullptr; } } // namespace udpscope