basalt-win32 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/cli/runWindows.js +35 -0
- package/cli/shared.js +75 -0
- package/native/CMakeLists.txt +429 -0
- package/native/tests/test_win32_accessibility.cpp +585 -0
- package/native/tests/test_win32_animated_image.cpp +351 -0
- package/native/tests/test_win32_clipboard.cpp +121 -0
- package/native/tests/test_win32_focus.cpp +195 -0
- package/native/tests/test_win32_hittest.cpp +750 -0
- package/native/tests/test_win32_image.cpp +370 -0
- package/native/tests/test_win32_imageloader.cpp +208 -0
- package/native/tests/test_win32_input.cpp +511 -0
- package/native/tests/test_win32_key_events.cpp +84 -0
- package/native/tests/test_win32_mounting.cpp +757 -0
- package/native/tests/test_win32_paint.cpp +1799 -0
- package/native/tests/test_win32_scrollview.cpp +647 -0
- package/native/tests/test_win32_selection.cpp +215 -0
- package/native/tests/test_win32_text.cpp +1456 -0
- package/native/tests/test_win32_textinput.cpp +1594 -0
- package/native/tests/test_win32_titlebar.cpp +111 -0
- package/native/tests/test_win32_titlebar_actions.cpp +62 -0
- package/native/tests/test_win32_view.cpp +222 -0
- package/native/win32/ColorSchemeWin32.cpp +56 -0
- package/native/win32/ComponentRegistryWin32.cpp +156 -0
- package/native/win32/DirectWriteLayout.cpp +485 -0
- package/native/win32/DirectWriteLayout.h +77 -0
- package/native/win32/DirectWriteLayoutManager.cpp +154 -0
- package/native/win32/FontRegistryDirectWrite.cpp +117 -0
- package/native/win32/PlatformServicesWin32.cpp +744 -0
- package/native/win32/RnWin32Accessible.cpp +343 -0
- package/native/win32/RnWin32Accessible.h +130 -0
- package/native/win32/RnWin32Image.cpp +588 -0
- package/native/win32/RnWin32Image.h +139 -0
- package/native/win32/RnWin32TextLayout.cpp +1379 -0
- package/native/win32/RnWin32TextLayout.h +390 -0
- package/native/win32/RnWin32View.cpp +2956 -0
- package/native/win32/RnWin32View.h +926 -0
- package/native/win32/Win32AnimationChoreographer.cpp +76 -0
- package/native/win32/Win32AnimationChoreographer.h +61 -0
- package/native/win32/Win32Clip.h +209 -0
- package/native/win32/Win32Cursors.cpp +309 -0
- package/native/win32/Win32Cursors.h +121 -0
- package/native/win32/Win32DropTarget.cpp +567 -0
- package/native/win32/Win32DropTarget.h +42 -0
- package/native/win32/Win32Focus.cpp +262 -0
- package/native/win32/Win32Focus.h +109 -0
- package/native/win32/Win32ImageLoader.cpp +199 -0
- package/native/win32/Win32ImageLoader.h +133 -0
- package/native/win32/Win32InputScopes.h +92 -0
- package/native/win32/Win32KeyEvents.cpp +126 -0
- package/native/win32/Win32KeyEvents.h +20 -0
- package/native/win32/Win32MenuBar.cpp +382 -0
- package/native/win32/Win32MenuBar.h +16 -0
- package/native/win32/Win32MountingManager.cpp +1282 -0
- package/native/win32/Win32MountingManager.h +243 -0
- package/native/win32/Win32Offscreen.h +53 -0
- package/native/win32/Win32Packaging.cpp +161 -0
- package/native/win32/Win32Packaging.h +56 -0
- package/native/win32/Win32RunLoopObserver.cpp +48 -0
- package/native/win32/Win32RunLoopObserver.h +42 -0
- package/native/win32/Win32ScrollView.cpp +718 -0
- package/native/win32/Win32ScrollView.h +256 -0
- package/native/win32/Win32SkiaContext.cpp +221 -0
- package/native/win32/Win32SkiaContext.h +53 -0
- package/native/win32/Win32SkiaModule.cpp +80 -0
- package/native/win32/Win32SkiaModule.h +50 -0
- package/native/win32/Win32SkiaPeer.cpp +358 -0
- package/native/win32/Win32SkiaPeer.h +66 -0
- package/native/win32/Win32SkiaUnicode.cpp +42 -0
- package/native/win32/Win32Snapshot.cpp +201 -0
- package/native/win32/Win32Snapshot.h +66 -0
- package/native/win32/Win32Strings.h +54 -0
- package/native/win32/Win32TextInput.cpp +1296 -0
- package/native/win32/Win32TextInput.h +341 -0
- package/native/win32/Win32TitleBar.cpp +562 -0
- package/native/win32/Win32TitleBar.h +146 -0
- package/native/win32/Win32TitleBarLayout.cpp +46 -0
- package/native/win32/Win32TitleBarLayout.h +58 -0
- package/native/win32/Win32TouchDispatcher.cpp +577 -0
- package/native/win32/Win32TouchDispatcher.h +201 -0
- package/native/win32/Win32UiThread.h +27 -0
- package/native/win32/Win32WindowControl.cpp +329 -0
- package/native/win32/Win32WindowModule.cpp +209 -0
- package/native/win32/Win32WindowModule.h +72 -0
- package/native/win32/demo_layout_win32.cpp +232 -0
- package/native/win32/main_win32.cpp +2722 -0
- package/native/win32/mount_harness_win32.cpp +316 -0
- package/package.json +25 -4
- package/react-native.config.js +22 -0
- package/README.md +0 -3
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
// The Windows half of core/MenuModel.h: a real menu bar, in the window.
|
|
2
|
+
//
|
|
3
|
+
// Windows is the middle case. A menu bar is conventional rather than required,
|
|
4
|
+
// it lives inside the window rather than in a system bar, and -- unlike macOS
|
|
5
|
+
// -- nothing about editing depends on it: an EDIT control implements Ctrl+C,
|
|
6
|
+
// Ctrl+V and Ctrl+Z itself, so the Edit menu is a convenience rather than the
|
|
7
|
+
// thing that makes copying work.
|
|
8
|
+
//
|
|
9
|
+
// Which is why the roles here are posted to the focused control rather than
|
|
10
|
+
// sent down a responder chain. Windows has no responder chain; what it has is
|
|
11
|
+
// `WM_COPY` and friends, which every standard edit control answers and which
|
|
12
|
+
// reach whichever one has focus.
|
|
13
|
+
//
|
|
14
|
+
// The host forwards `WM_COMMAND` here. A menu bar costs client area, so
|
|
15
|
+
// installing one resizes the surface -- which the host already handles, because
|
|
16
|
+
// the same thing happens when a window is resized for any other reason.
|
|
17
|
+
|
|
18
|
+
#include "Win32MenuBar.h"
|
|
19
|
+
#include "TextSelection.h"
|
|
20
|
+
|
|
21
|
+
#include "MenuModel.h"
|
|
22
|
+
#include "WindowControl.h"
|
|
23
|
+
#include "Win32Strings.h"
|
|
24
|
+
|
|
25
|
+
#include <windows.h>
|
|
26
|
+
|
|
27
|
+
#include <iterator>
|
|
28
|
+
#include <string>
|
|
29
|
+
#include <utility>
|
|
30
|
+
#include <vector>
|
|
31
|
+
|
|
32
|
+
namespace basalt {
|
|
33
|
+
|
|
34
|
+
namespace {
|
|
35
|
+
|
|
36
|
+
// Command ids. An app's own item carries its own id and a role needs one of
|
|
37
|
+
// these, so they are kept apart by range: an app's ids come from JavaScript and
|
|
38
|
+
// start at 1, and roles start high enough that the two cannot meet.
|
|
39
|
+
constexpr UINT kRoleBase = 0xE000;
|
|
40
|
+
|
|
41
|
+
struct Role {
|
|
42
|
+
const char *name;
|
|
43
|
+
UINT command;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
constexpr Role kRoles[] = {
|
|
47
|
+
{"quit", kRoleBase + 1},
|
|
48
|
+
{"undo", kRoleBase + 2},
|
|
49
|
+
{"redo", kRoleBase + 3},
|
|
50
|
+
{"cut", kRoleBase + 4},
|
|
51
|
+
{"copy", kRoleBase + 5},
|
|
52
|
+
{"paste", kRoleBase + 6},
|
|
53
|
+
{"delete", kRoleBase + 7},
|
|
54
|
+
{"selectAll", kRoleBase + 8},
|
|
55
|
+
{"minimize", kRoleBase + 9},
|
|
56
|
+
{"zoom", kRoleBase + 10},
|
|
57
|
+
{"close", kRoleBase + 11},
|
|
58
|
+
{"togglefullscreen", kRoleBase + 12},
|
|
59
|
+
// "about" has no standard Windows action. An app that wants one shows its
|
|
60
|
+
// own window, which is an app's own item rather than a role.
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
UINT commandForRole(const std::string &role) {
|
|
64
|
+
for (const Role &known : kRoles) {
|
|
65
|
+
if (role == known.name) {
|
|
66
|
+
return known.command;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// The platform's own word, plus the shortcut it answers to. Windows draws an
|
|
73
|
+
// accelerator as the text after a tab; nothing here registers one, because the
|
|
74
|
+
// EDIT control already answers these keys.
|
|
75
|
+
std::wstring labelForRole(const std::string &role, const std::string &label) {
|
|
76
|
+
if (!label.empty()) {
|
|
77
|
+
return win32::widen(label);
|
|
78
|
+
}
|
|
79
|
+
if (role == "quit") {
|
|
80
|
+
return L"Exit";
|
|
81
|
+
}
|
|
82
|
+
if (role == "undo") {
|
|
83
|
+
return L"Undo\tCtrl+Z";
|
|
84
|
+
}
|
|
85
|
+
if (role == "redo") {
|
|
86
|
+
return L"Redo\tCtrl+Y";
|
|
87
|
+
}
|
|
88
|
+
if (role == "cut") {
|
|
89
|
+
return L"Cut\tCtrl+X";
|
|
90
|
+
}
|
|
91
|
+
if (role == "copy") {
|
|
92
|
+
return L"Copy\tCtrl+C";
|
|
93
|
+
}
|
|
94
|
+
if (role == "paste") {
|
|
95
|
+
return L"Paste\tCtrl+V";
|
|
96
|
+
}
|
|
97
|
+
if (role == "delete") {
|
|
98
|
+
return L"Delete";
|
|
99
|
+
}
|
|
100
|
+
if (role == "selectAll") {
|
|
101
|
+
return L"Select All\tCtrl+A";
|
|
102
|
+
}
|
|
103
|
+
if (role == "minimize") {
|
|
104
|
+
return L"Minimize";
|
|
105
|
+
}
|
|
106
|
+
if (role == "zoom") {
|
|
107
|
+
return L"Maximize";
|
|
108
|
+
}
|
|
109
|
+
if (role == "close") {
|
|
110
|
+
return L"Close";
|
|
111
|
+
}
|
|
112
|
+
if (role == "togglefullscreen") {
|
|
113
|
+
return L"Full Screen";
|
|
114
|
+
}
|
|
115
|
+
return {};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
std::function<void(int)> &handler() {
|
|
119
|
+
static std::function<void(int)> value;
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
HMENU &installed() {
|
|
124
|
+
static HMENU menu = nullptr;
|
|
125
|
+
return menu;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
void addItems(HMENU menu, const std::vector<MenuItemModel> &items);
|
|
129
|
+
|
|
130
|
+
void addItem(HMENU menu, const MenuItemModel &item) {
|
|
131
|
+
if (item.separator) {
|
|
132
|
+
AppendMenuW(menu, MF_SEPARATOR, 0, nullptr);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const UINT flags = item.enabled ? MF_ENABLED : MF_GRAYED;
|
|
137
|
+
|
|
138
|
+
if (!item.submenu.empty()) {
|
|
139
|
+
HMENU submenu = CreatePopupMenu();
|
|
140
|
+
if (submenu == nullptr) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
addItems(submenu, item.submenu);
|
|
144
|
+
AppendMenuW(menu,
|
|
145
|
+
MF_POPUP | flags,
|
|
146
|
+
reinterpret_cast<UINT_PTR>(submenu),
|
|
147
|
+
win32::widen(item.label).c_str());
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!item.role.empty()) {
|
|
152
|
+
const UINT command = commandForRole(item.role);
|
|
153
|
+
const std::wstring label = labelForRole(item.role, item.label);
|
|
154
|
+
// An unknown role is dropped: a menu item that does nothing is worse than
|
|
155
|
+
// one that is not there.
|
|
156
|
+
if (command != 0 && !label.empty()) {
|
|
157
|
+
AppendMenuW(menu, MF_STRING | flags, command, label.c_str());
|
|
158
|
+
}
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (item.id <= 0) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
std::wstring label = win32::widen(item.label);
|
|
166
|
+
if (!item.accelerator.empty()) {
|
|
167
|
+
label += L"\t";
|
|
168
|
+
label += win32::widen(item.accelerator);
|
|
169
|
+
}
|
|
170
|
+
AppendMenuW(menu, MF_STRING | flags, static_cast<UINT_PTR>(item.id), label.c_str());
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
void addItems(HMENU menu, const std::vector<MenuItemModel> &items) {
|
|
174
|
+
for (const MenuItemModel &item : items) {
|
|
175
|
+
addItem(menu, item);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
} // namespace
|
|
180
|
+
|
|
181
|
+
bool applicationMenuSupported() {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
namespace {
|
|
186
|
+
|
|
187
|
+
void describeInto(std::string &out, HMENU menu, int depth) {
|
|
188
|
+
const int count = GetMenuItemCount(menu);
|
|
189
|
+
for (int i = 0; i < count; i++) {
|
|
190
|
+
wchar_t text[512] = {0};
|
|
191
|
+
MENUITEMINFOW info{};
|
|
192
|
+
info.cbSize = sizeof(info);
|
|
193
|
+
info.fMask = MIIM_STRING | MIIM_SUBMENU | MIIM_STATE | MIIM_FTYPE;
|
|
194
|
+
info.dwTypeData = text;
|
|
195
|
+
info.cch = static_cast<UINT>(std::size(text) - 1);
|
|
196
|
+
if (!GetMenuItemInfoW(menu, static_cast<UINT>(i), TRUE, &info)) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
out.append(static_cast<size_t>(depth) * 2, ' ');
|
|
201
|
+
if ((info.fType & MFT_SEPARATOR) != 0) {
|
|
202
|
+
out += "-\n";
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
// The accelerator is the text after a tab, which is how Windows stores one;
|
|
206
|
+
// it reads the same way the macOS dump's bracket does.
|
|
207
|
+
std::wstring label(text);
|
|
208
|
+
const size_t tab = label.find(L'\t');
|
|
209
|
+
if (tab != std::wstring::npos) {
|
|
210
|
+
out += win32::narrow(label.substr(0, tab));
|
|
211
|
+
out += " [";
|
|
212
|
+
out += win32::narrow(label.substr(tab + 1));
|
|
213
|
+
out += "]";
|
|
214
|
+
} else {
|
|
215
|
+
out += win32::narrow(label);
|
|
216
|
+
}
|
|
217
|
+
if ((info.fState & MFS_DISABLED) != 0) {
|
|
218
|
+
out += " (disabled)";
|
|
219
|
+
}
|
|
220
|
+
out += "\n";
|
|
221
|
+
if (info.hSubMenu != nullptr) {
|
|
222
|
+
describeInto(out, info.hSubMenu, depth + 1);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
} // namespace
|
|
228
|
+
|
|
229
|
+
std::string describeApplicationMenu() {
|
|
230
|
+
std::string out;
|
|
231
|
+
if (installed() != nullptr) {
|
|
232
|
+
describeInto(out, installed(), 0);
|
|
233
|
+
}
|
|
234
|
+
return out;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
void setApplicationMenu(const MenuModel &menu, std::function<void(int)> onChosen) {
|
|
238
|
+
HWND window = GetActiveWindow();
|
|
239
|
+
if (window == nullptr) {
|
|
240
|
+
window = GetForegroundWindow();
|
|
241
|
+
}
|
|
242
|
+
if (window == nullptr) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
handler() = std::move(onChosen);
|
|
247
|
+
|
|
248
|
+
// An empty menu takes the bar away, which is what Windows' own default is:
|
|
249
|
+
// unlike macOS there is nothing an application needs a menu bar to do.
|
|
250
|
+
if (menu.empty()) {
|
|
251
|
+
SetMenu(window, nullptr);
|
|
252
|
+
if (installed() != nullptr) {
|
|
253
|
+
DestroyMenu(installed());
|
|
254
|
+
installed() = nullptr;
|
|
255
|
+
}
|
|
256
|
+
DrawMenuBar(window);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
HMENU bar = CreateMenu();
|
|
261
|
+
if (bar == nullptr) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
for (const MenuItemModel &top : menu) {
|
|
265
|
+
// A bare command in a menu bar is not a thing any desktop has.
|
|
266
|
+
if (top.submenu.empty()) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
HMENU submenu = CreatePopupMenu();
|
|
270
|
+
if (submenu == nullptr) {
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
addItems(submenu, top.submenu);
|
|
274
|
+
AppendMenuW(bar,
|
|
275
|
+
MF_POPUP,
|
|
276
|
+
reinterpret_cast<UINT_PTR>(submenu),
|
|
277
|
+
win32::widen(top.label).c_str());
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
SetMenu(window, bar);
|
|
281
|
+
// Destroyed after the new one is in: a menu still attached to a window
|
|
282
|
+
// cannot be freed, and freeing the old one first would leave the window
|
|
283
|
+
// pointing at nothing for the length of a call.
|
|
284
|
+
if (installed() != nullptr) {
|
|
285
|
+
DestroyMenu(installed());
|
|
286
|
+
}
|
|
287
|
+
installed() = bar;
|
|
288
|
+
DrawMenuBar(window);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
namespace win32 {
|
|
292
|
+
|
|
293
|
+
bool handleMenuCommand(unsigned int command) {
|
|
294
|
+
if (command < kRoleBase) {
|
|
295
|
+
// An app's own item. Zero is "not from a menu", which WM_COMMAND also uses
|
|
296
|
+
// for accelerators and controls.
|
|
297
|
+
if (command == 0 || !handler()) {
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
handler()(static_cast<int>(command));
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
HWND window = GetActiveWindow();
|
|
305
|
+
HWND focused = GetFocus();
|
|
306
|
+
switch (command) {
|
|
307
|
+
case kRoleBase + 1:
|
|
308
|
+
PostMessageW(window, WM_CLOSE, 0, 0);
|
|
309
|
+
return true;
|
|
310
|
+
// Posted to whatever has focus, which for these is a real EDIT control and
|
|
311
|
+
// answers every one of them itself. Windows has no responder chain; this is
|
|
312
|
+
// the equivalent.
|
|
313
|
+
case kRoleBase + 2:
|
|
314
|
+
SendMessageW(focused, WM_UNDO, 0, 0);
|
|
315
|
+
return true;
|
|
316
|
+
case kRoleBase + 3:
|
|
317
|
+
// EDIT has no redo. Reported as handled anyway: the alternative is the
|
|
318
|
+
// key travelling on to something that will do something else with it.
|
|
319
|
+
return true;
|
|
320
|
+
case kRoleBase + 4:
|
|
321
|
+
SendMessageW(focused, WM_CUT, 0, 0);
|
|
322
|
+
return true;
|
|
323
|
+
case kRoleBase + 5:
|
|
324
|
+
SendMessageW(focused, WM_COPY, 0, 0);
|
|
325
|
+
return true;
|
|
326
|
+
case kRoleBase + 6:
|
|
327
|
+
SendMessageW(focused, WM_PASTE, 0, 0);
|
|
328
|
+
return true;
|
|
329
|
+
case kRoleBase + 7:
|
|
330
|
+
SendMessageW(focused, WM_CLEAR, 0, 0);
|
|
331
|
+
return true;
|
|
332
|
+
case kRoleBase + 8:
|
|
333
|
+
SendMessageW(focused, EM_SETSEL, 0, -1);
|
|
334
|
+
return true;
|
|
335
|
+
case kRoleBase + 9:
|
|
336
|
+
ShowWindow(window, SW_MINIMIZE);
|
|
337
|
+
return true;
|
|
338
|
+
case kRoleBase + 10:
|
|
339
|
+
ShowWindow(window, IsZoomed(window) ? SW_RESTORE : SW_MAXIMIZE);
|
|
340
|
+
return true;
|
|
341
|
+
case kRoleBase + 11:
|
|
342
|
+
PostMessageW(window, WM_CLOSE, 0, 0);
|
|
343
|
+
return true;
|
|
344
|
+
case kRoleBase + 12:
|
|
345
|
+
setWindowFullScreen(!windowBounds().fullScreen);
|
|
346
|
+
return true;
|
|
347
|
+
default:
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
} // namespace win32
|
|
353
|
+
|
|
354
|
+
// --- Roles, for a popup menu too ----------------------------------------------
|
|
355
|
+
//
|
|
356
|
+
// `showMenu` in PlatformServicesWin32.cpp performs a role itself rather than
|
|
357
|
+
// letting a WM_COMMAND carry it, because it has a promise to settle with the
|
|
358
|
+
// index chosen. The work is the same work: `handleMenuCommand` above already
|
|
359
|
+
// posts WM_COPY and friends to whatever has focus, so this is a second caller
|
|
360
|
+
// for it rather than a second implementation.
|
|
361
|
+
bool menuRoleSupported(const std::string &role) {
|
|
362
|
+
return commandForRole(role) != 0;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
void performMenuRole(const std::string &role) {
|
|
366
|
+
// A paragraph's selection first, when there is one: `Copy` over selected text
|
|
367
|
+
// means that text, and the focused control below is what the role meant when
|
|
368
|
+
// only a <TextInput> could hold a selection. At most one of the two exists --
|
|
369
|
+
// pressing in a field clears a paragraph's selection on the way past -- so
|
|
370
|
+
// the order settles a case that does not arise rather than choosing between
|
|
371
|
+
// two live selections. See core/TextSelection.h.
|
|
372
|
+
if (role == "copy" && copySelectedText()) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const UINT command = commandForRole(role);
|
|
377
|
+
if (command == 0) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
win32::handleMenuCommand(command);
|
|
381
|
+
}
|
|
382
|
+
} // namespace basalt
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// The host's half of the Windows menu bar: forwarding WM_COMMAND.
|
|
2
|
+
//
|
|
3
|
+
// A menu bar's items arrive as WM_COMMAND on the window that owns it, and the
|
|
4
|
+
// window procedure is the host's. This is the one line it has to pass on. See
|
|
5
|
+
// Win32MenuBar.cpp for what happens to it.
|
|
6
|
+
|
|
7
|
+
#pragma once
|
|
8
|
+
|
|
9
|
+
namespace basalt::win32 {
|
|
10
|
+
|
|
11
|
+
// Handles a WM_COMMAND from the application menu. Returns false when the
|
|
12
|
+
// command was not one of its own, so the host can go on treating it as whatever
|
|
13
|
+
// else a WM_COMMAND is -- a control's notification, in this host's case.
|
|
14
|
+
bool handleMenuCommand(unsigned int command);
|
|
15
|
+
|
|
16
|
+
} // namespace basalt::win32
|