yaze
0.3.2
Link to the Past ROM Editor
Loading...
Searching...
No Matches
native_menu_bridge.h
Go to the documentation of this file.
1
#ifndef YAZE_APP_PLATFORM_NATIVE_MENU_BRIDGE_H_
2
#define YAZE_APP_PLATFORM_NATIVE_MENU_BRIDGE_H_
3
4
// Platform-neutral model behind the macOS native main menu.
5
//
6
// The Cocoa side (app_delegate.mm) only builds NSMenu objects and forwards
7
// clicks, key equivalents, and validation to this layer. Keeping the rules in
8
// plain C++ lets unit tests prove the chord-ownership contract without AppKit.
9
//
10
// Chord ownership contract (one owner per chord, never both):
11
// * kImGui: the item mirrors a ShortcutManager binding. The native menu
12
// shows the chord for discoverability but must NOT perform it as
13
// a key equivalent; SDL delivers the key to ImGui and
14
// ExecuteShortcuts() runs the action once. A click on the item
15
// runs the same ShortcutManager callback.
16
// * kNative: nothing in ShortcutManager binds the chord exactly. NSMenu
17
// performs it, and the SDL event filter drops the key so the
18
// chord never also reaches ImGui (ShortcutManager matches
19
// modifiers loosely, e.g. Ctrl+Cmd+F would otherwise fire Find).
20
// * kNone: the item has no usable chord (its shortcut is unbound or its
21
// key unrepresentable, or an exact ShortcutManager conflict with
22
// a different action).
23
24
#include <cstdint>
25
#include <functional>
26
#include <string>
27
#include <vector>
28
29
#ifndef IMGUI_DEFINE_MATH_OPERATORS
30
#define IMGUI_DEFINE_MATH_OPERATORS
31
#endif
32
#include "imgui/imgui.h"
33
34
namespace
yaze
{
35
namespace
editor {
36
class
ShortcutManager;
37
}
// namespace editor
38
39
namespace
platform {
40
namespace
native_menu {
41
42
enum class
MenuAction
:
int
{
43
// App menu
44
kAbout
= 0,
45
kSettings
,
46
kHide
,
47
kHideOthers
,
48
kShowAll
,
49
kQuit
,
50
// File
51
kOpenRom
,
52
kOpenProject
,
53
kSave
,
54
kSaveAs
,
55
kCloseRom
,
56
// Edit
57
kUndo
,
58
kRedo
,
59
kCut
,
60
kCopy
,
61
kPaste
,
62
kSelectAll
,
63
// View
64
kToggleSidebar
,
65
kToggleFullScreen
,
66
// Window
67
kMinimize
,
68
kZoom
,
69
kBringAllToFront
,
70
// Help
71
kKeyboardShortcuts
,
72
kCount
,
73
};
74
75
// A macOS key chord. `key` is the unshifted ASCII character ('s', ',', '/'),
76
// or 0 when there is no chord.
77
struct
KeyChord
{
78
char
key
= 0;
79
bool
command
=
false
;
80
bool
shift
=
false
;
81
bool
option
=
false
;
82
bool
control
=
false
;
83
84
bool
valid
()
const
{
return
key
!= 0; }
85
bool
operator==
(
const
KeyChord
& other)
const
{
86
return
key
== other.
key
&&
command
== other.
command
&&
87
shift
== other.
shift
&&
option
== other.
option
&&
88
control
== other.
control
;
89
}
90
bool
operator!=
(
const
KeyChord
& other)
const
{
return
!(*
this
== other); }
91
};
92
93
enum class
ChordOwner
{
kNone
,
kImGui
,
kNative
};
94
95
// How a menu action performs its work.
96
enum class
Dispatch
{
97
kShortcut
,
// ShortcutManager callback named by `shortcut_name`.
98
kHost
,
// NativeMenuHost::RunHostAction (EditorManager call).
99
kTextOrShortcut
,
// Text-field chord when ImGui wants text, else shortcut.
100
kCocoa
,
// Standard AppKit selector (hide:, performMiniaturize:).
101
};
102
103
struct
ActionSpec
{
104
MenuAction
action
;
105
const
char
*
title
;
106
// ShortcutManager entry that owns this action's chord and behavior. When the
107
// entry is missing (e.g. agent UI compiled out), the item falls back to
108
// `fallback`.
109
const
char
*
shortcut_name
;
110
KeyChord
default_chord
;
111
Dispatch
dispatch
;
112
Dispatch
fallback
;
113
// ImGui itself handles `default_chord` (text-field Cmd+X/C/V/A), so the
114
// chord stays with ImGui even without a ShortcutManager entry.
115
bool
imgui_owns_default_chord
;
116
};
117
118
const
std::vector<ActionSpec>&
ActionSpecs
();
119
const
ActionSpec
*
FindSpec
(
MenuAction
action);
120
121
// Convert a ShortcutManager key list to a macOS chord. ShortcutManager's
122
// ImGuiMod_Ctrl means Command on macOS (ImGui swaps Cmd/Ctrl). Returns an
123
// invalid chord for keys a menu key equivalent cannot express (F1, arrows).
124
KeyChord
ChordFromImGuiKeys
(
const
std::vector<ImGuiKey>& keys);
125
126
// Map the ASCII key of a chord to an ImGui key (for synthesizing text-field
127
// chords). Returns ImGuiKey_None if unsupported.
128
ImGuiKey
ImGuiKeyFromChordKey
(
char
key);
129
130
struct
ResolvedItem
{
131
KeyChord
chord
;
132
ChordOwner
owner
=
ChordOwner::kNone
;
133
// Effective dispatch after considering whether `shortcut_name` exists.
134
Dispatch
dispatch
=
Dispatch::kHost
;
135
};
136
137
// Resolve one item against the live ShortcutManager (may be null).
138
ResolvedItem
ResolveItem
(
const
editor::ShortcutManager
* shortcuts,
139
MenuAction
action);
140
141
// True when the NSMenu should perform `chord` as a key equivalent. Everything
142
// else must fall through to SDL/ImGui.
143
bool
IsNativeOwnedChord
(
const
editor::ShortcutManager
* shortcuts,
144
const
KeyChord
& chord);
145
146
// Gate for the root NSMenu's performKeyEquivalent:. False for every chord
147
// ImGui owns (a ShortcutManager binding or an ImGui-owned item); true for
148
// native-owned chords and for chords of items AppKit inserts itself
149
// (Emoji & Symbols, Dictation), which ImGui never sees as shortcuts.
150
bool
ShouldMenuPerformKeyEquivalent
(
const
editor::ShortcutManager
* shortcuts,
151
const
KeyChord
& chord);
152
153
// Editor state and side effects the menu needs. Implemented over
154
// EditorManager in app_delegate.mm and by a fake in unit tests.
155
class
NativeMenuHost
{
156
public
:
157
virtual
~NativeMenuHost
() =
default
;
158
virtual
editor::ShortcutManager
*
shortcut_manager
() = 0;
159
virtual
bool
HasLoadedRom
()
const
= 0;
160
virtual
bool
HasCurrentEditor
()
const
= 0;
161
virtual
bool
CanUndo
()
const
= 0;
162
virtual
bool
CanRedo
()
const
= 0;
163
virtual
bool
WantsTextInput
()
const
= 0;
164
// Run `action` at the start of the next ImGui frame (EditorManager's
165
// deferred-action queue), where ShortcutManager callbacks normally run.
166
virtual
void
Defer
(std::function<
void
()> action) = 0;
167
// Queue a Command+key press into ImGui's input queue (text fields).
168
virtual
void
InjectCommandChord
(ImGuiKey key) = 0;
169
virtual
void
RunHostAction
(
MenuAction
action) = 0;
170
virtual
std::vector<std::string>
RecentFiles
()
const
= 0;
171
virtual
void
OpenRecentFile
(
const
std::string& path) = 0;
172
virtual
void
ClearRecentFiles
() = 0;
173
};
174
175
bool
IsActionEnabled
(
NativeMenuHost
& host,
MenuAction
action);
176
177
// Perform a menu click. Returns false when the action is a Cocoa selector the
178
// caller must route through the responder chain itself.
179
bool
PerformAction
(
NativeMenuHost
& host,
MenuAction
action);
180
181
// Short label for a recent-file entry (file name, falls back to full path).
182
std::string
RecentFileLabel
(
const
std::string& path);
183
184
}
// namespace native_menu
185
}
// namespace platform
186
}
// namespace yaze
187
188
#endif
// YAZE_APP_PLATFORM_NATIVE_MENU_BRIDGE_H_
yaze::editor::ShortcutManager
Definition
shortcut_manager.h:52
yaze::platform::native_menu::NativeMenuHost
Definition
native_menu_bridge.h:155
yaze::platform::native_menu::NativeMenuHost::CanRedo
virtual bool CanRedo() const =0
yaze::platform::native_menu::NativeMenuHost::RecentFiles
virtual std::vector< std::string > RecentFiles() const =0
yaze::platform::native_menu::NativeMenuHost::shortcut_manager
virtual editor::ShortcutManager * shortcut_manager()=0
yaze::platform::native_menu::NativeMenuHost::InjectCommandChord
virtual void InjectCommandChord(ImGuiKey key)=0
yaze::platform::native_menu::NativeMenuHost::ClearRecentFiles
virtual void ClearRecentFiles()=0
yaze::platform::native_menu::NativeMenuHost::RunHostAction
virtual void RunHostAction(MenuAction action)=0
yaze::platform::native_menu::NativeMenuHost::HasCurrentEditor
virtual bool HasCurrentEditor() const =0
yaze::platform::native_menu::NativeMenuHost::Defer
virtual void Defer(std::function< void()> action)=0
yaze::platform::native_menu::NativeMenuHost::HasLoadedRom
virtual bool HasLoadedRom() const =0
yaze::platform::native_menu::NativeMenuHost::WantsTextInput
virtual bool WantsTextInput() const =0
yaze::platform::native_menu::NativeMenuHost::OpenRecentFile
virtual void OpenRecentFile(const std::string &path)=0
yaze::platform::native_menu::NativeMenuHost::CanUndo
virtual bool CanUndo() const =0
yaze::platform::native_menu::NativeMenuHost::~NativeMenuHost
virtual ~NativeMenuHost()=default
yaze::platform::native_menu::ChordOwner
ChordOwner
Definition
native_menu_bridge.h:93
yaze::platform::native_menu::ChordOwner::kNone
@ kNone
yaze::platform::native_menu::ChordOwner::kImGui
@ kImGui
yaze::platform::native_menu::ChordOwner::kNative
@ kNative
yaze::platform::native_menu::FindSpec
const ActionSpec * FindSpec(MenuAction action)
Definition
native_menu_bridge.cc:173
yaze::platform::native_menu::IsActionEnabled
bool IsActionEnabled(NativeMenuHost &host, MenuAction action)
Definition
native_menu_bridge.cc:298
yaze::platform::native_menu::IsNativeOwnedChord
bool IsNativeOwnedChord(const editor::ShortcutManager *shortcuts, const KeyChord &chord)
Definition
native_menu_bridge.cc:259
yaze::platform::native_menu::Dispatch
Dispatch
Definition
native_menu_bridge.h:96
yaze::platform::native_menu::Dispatch::kTextOrShortcut
@ kTextOrShortcut
yaze::platform::native_menu::Dispatch::kShortcut
@ kShortcut
yaze::platform::native_menu::Dispatch::kCocoa
@ kCocoa
yaze::platform::native_menu::Dispatch::kHost
@ kHost
yaze::platform::native_menu::ResolveItem
ResolvedItem ResolveItem(const editor::ShortcutManager *shortcuts, MenuAction action)
Definition
native_menu_bridge.cc:220
yaze::platform::native_menu::ActionSpecs
const std::vector< ActionSpec > & ActionSpecs()
Definition
native_menu_bridge.cc:102
yaze::platform::native_menu::ShouldMenuPerformKeyEquivalent
bool ShouldMenuPerformKeyEquivalent(const editor::ShortcutManager *shortcuts, const KeyChord &chord)
Definition
native_menu_bridge.cc:277
yaze::platform::native_menu::PerformAction
bool PerformAction(NativeMenuHost &host, MenuAction action)
Definition
native_menu_bridge.cc:319
yaze::platform::native_menu::ChordFromImGuiKeys
KeyChord ChordFromImGuiKeys(const std::vector< ImGuiKey > &keys)
Definition
native_menu_bridge.cc:182
yaze::platform::native_menu::RecentFileLabel
std::string RecentFileLabel(const std::string &path)
Definition
native_menu_bridge.cc:369
yaze::platform::native_menu::ImGuiKeyFromChordKey
ImGuiKey ImGuiKeyFromChordKey(char key)
Definition
native_menu_bridge.cc:213
yaze::platform::native_menu::MenuAction
MenuAction
Definition
native_menu_bridge.h:42
yaze::platform::native_menu::MenuAction::kQuit
@ kQuit
yaze::platform::native_menu::MenuAction::kCut
@ kCut
yaze::platform::native_menu::MenuAction::kShowAll
@ kShowAll
yaze::platform::native_menu::MenuAction::kSelectAll
@ kSelectAll
yaze::platform::native_menu::MenuAction::kCount
@ kCount
yaze::platform::native_menu::MenuAction::kHide
@ kHide
yaze::platform::native_menu::MenuAction::kUndo
@ kUndo
yaze::platform::native_menu::MenuAction::kCopy
@ kCopy
yaze::platform::native_menu::MenuAction::kMinimize
@ kMinimize
yaze::platform::native_menu::MenuAction::kSave
@ kSave
yaze::platform::native_menu::MenuAction::kOpenProject
@ kOpenProject
yaze::platform::native_menu::MenuAction::kAbout
@ kAbout
yaze::platform::native_menu::MenuAction::kSaveAs
@ kSaveAs
yaze::platform::native_menu::MenuAction::kBringAllToFront
@ kBringAllToFront
yaze::platform::native_menu::MenuAction::kOpenRom
@ kOpenRom
yaze::platform::native_menu::MenuAction::kPaste
@ kPaste
yaze::platform::native_menu::MenuAction::kCloseRom
@ kCloseRom
yaze::platform::native_menu::MenuAction::kSettings
@ kSettings
yaze::platform::native_menu::MenuAction::kToggleFullScreen
@ kToggleFullScreen
yaze::platform::native_menu::MenuAction::kHideOthers
@ kHideOthers
yaze::platform::native_menu::MenuAction::kZoom
@ kZoom
yaze::platform::native_menu::MenuAction::kKeyboardShortcuts
@ kKeyboardShortcuts
yaze::platform::native_menu::MenuAction::kRedo
@ kRedo
yaze::platform::native_menu::MenuAction::kToggleSidebar
@ kToggleSidebar
yaze
Definition
patch_export_usage.cc:8
yaze::platform::native_menu::ActionSpec
Definition
native_menu_bridge.h:103
yaze::platform::native_menu::ActionSpec::default_chord
KeyChord default_chord
Definition
native_menu_bridge.h:110
yaze::platform::native_menu::ActionSpec::fallback
Dispatch fallback
Definition
native_menu_bridge.h:112
yaze::platform::native_menu::ActionSpec::dispatch
Dispatch dispatch
Definition
native_menu_bridge.h:111
yaze::platform::native_menu::ActionSpec::imgui_owns_default_chord
bool imgui_owns_default_chord
Definition
native_menu_bridge.h:115
yaze::platform::native_menu::ActionSpec::shortcut_name
const char * shortcut_name
Definition
native_menu_bridge.h:109
yaze::platform::native_menu::ActionSpec::action
MenuAction action
Definition
native_menu_bridge.h:104
yaze::platform::native_menu::ActionSpec::title
const char * title
Definition
native_menu_bridge.h:105
yaze::platform::native_menu::KeyChord
Definition
native_menu_bridge.h:77
yaze::platform::native_menu::KeyChord::operator==
bool operator==(const KeyChord &other) const
Definition
native_menu_bridge.h:85
yaze::platform::native_menu::KeyChord::shift
bool shift
Definition
native_menu_bridge.h:80
yaze::platform::native_menu::KeyChord::control
bool control
Definition
native_menu_bridge.h:82
yaze::platform::native_menu::KeyChord::command
bool command
Definition
native_menu_bridge.h:79
yaze::platform::native_menu::KeyChord::key
char key
Definition
native_menu_bridge.h:78
yaze::platform::native_menu::KeyChord::valid
bool valid() const
Definition
native_menu_bridge.h:84
yaze::platform::native_menu::KeyChord::operator!=
bool operator!=(const KeyChord &other) const
Definition
native_menu_bridge.h:90
yaze::platform::native_menu::KeyChord::option
bool option
Definition
native_menu_bridge.h:81
yaze::platform::native_menu::ResolvedItem
Definition
native_menu_bridge.h:130
yaze::platform::native_menu::ResolvedItem::owner
ChordOwner owner
Definition
native_menu_bridge.h:132
yaze::platform::native_menu::ResolvedItem::chord
KeyChord chord
Definition
native_menu_bridge.h:131
yaze::platform::native_menu::ResolvedItem::dispatch
Dispatch dispatch
Definition
native_menu_bridge.h:134
src
app
platform
native_menu_bridge.h
Generated by
1.10.0