Keybinds
A plugin can bind keyboard shortcuts to actions. Bindings are stored as strings
(e.g. "Ctrl+F;F2") so users can rebind them, and they show up in the shared
keybind UI. There are three pieces:
- A binding string member you load/save like any other setting.
- A keybind entry registered so the UI can display and edit it.
- The actual binding to a handler, done in
OnBindHotkeys.
Storing the binding string
Keybind strings live in the shared [keybinds] section, not your own. Use
LoadKeybinds/SaveKeybinds and namespace your keys with PrefixedKey so they
never collide with another plugin's:
class MyPlugin : public PluginBase
{
std::string toggleKey_ = "Ctrl+M";
protected:
const char* PluginName() const override { return "MyPlugin"; }
void LoadKeybinds(IPluginSettings& ks) override
{
toggleKey_ = ks.GetString(PrefixedKey("toggle").c_str(), "Ctrl+M");
}
void SaveKeybinds(IPluginSettings& ks) override
{
ks.SetString(PrefixedKey("toggle").c_str(), toggleKey_.c_str());
}
};
PrefixedKey("toggle") yields "MyPlugin.toggle".
Registering the entry for the UI
Override RegisterKeybinds and register an entry backed by your string member.
The <framelift/ContextHelpers.h> overload takes the std::string& directly and
writes the get/set glue for you:
#include <framelift/ContextHelpers.h>
void RegisterKeybinds(IPluginContext& ctx) override
{
framelift::RegisterKeybindEntry(ctx, "Toggle my panel", "MyPlugin.toggle", toggleKey_);
}
- label — human-readable text shown in the keybind list.
- actionName — a stable identifier (namespaced).
- bindStr — the member the UI reads from and writes back to.
Binding to a handler
Override OnBindHotkeys. It runs once, after all plugins are installed, so you
can safely reference services other plugins registered. Use the framelift::Bind
helpers, which accept a lambda:
#include <framelift/HotkeyHelpers.h>
void OnBindHotkeys(Hotkeys& keys) override
{
// Named, rebindable binding driven by the stored string.
framelift::Bind(keys, "MyPlugin.toggle", toggleKey_, [this] {
showPanel_ = !showPanel_;
});
}
Bind has overloads for:
- Named bindings from a bind-list string (
"Ctrl+F;F2"— first entry is the rebindable name, the rest are aliases). This is what pairs with a registered keybind entry. - Unnamed bindings to a fixed
Key(+ optionalMod) from<framelift/AppEvent.h>, e.g.framelift::Bind(keys, Keys::Space, [this] { ... }).
Each binding heap-allocates its closure and registers a cleanup callback, so the memory is released automatically when your plugin unloads.
Handling raw key events instead
For one-off keyboard handling that does not need to be user-rebindable, override
OnKeyDownEvent instead of registering a hotkey. Return true to consume the
event and stop further dispatch:
bool OnKeyDownEvent(const AppEvent& e) override
{
const auto& k = e.AsKey();
if (k.key == Keys::Escape && k.mods == Mod::None)
{
Close();
return true; // consumed
}
return false;
}
See AppEvent for the Key/Mod constants and the
payload accessors.