|
24 | 24 | #include "shell/contextmenu/hooks.h" |
25 | 25 |
|
26 | 26 | #include "script.h" |
| 27 | +#include "shell/utils.h" |
27 | 28 | #include "winhttp.h" |
28 | 29 |
|
29 | 30 | #include <shellapi.h> |
@@ -1235,74 +1236,185 @@ void win32::reg_set_qword(std::string key, std::string name, int64_t value) { |
1235 | 1236 |
|
1236 | 1237 | RegCloseKey(hKey); |
1237 | 1238 | } |
| 1239 | + |
| 1240 | + |
| 1241 | +static WORD get_scancode(std::string key) { |
| 1242 | + std::transform(key.begin(), key.end(), key.begin(), ::tolower); |
| 1243 | + |
| 1244 | + static const std::unordered_map<std::string, WORD> scancodes = { |
| 1245 | + {"escape", 0x01}, {"1", 0x02}, {"2", 0x03}, {"3", 0x04}, {"4", 0x05}, |
| 1246 | + {"5", 0x06}, {"6", 0x07}, {"7", 0x08}, {"8", 0x09}, {"9", 0x0A}, |
| 1247 | + {"0", 0x0B}, {"minus", 0x0C}, {"equal", 0x0D}, {"backspace", 0x0E}, |
| 1248 | + {"tab", 0x0F}, {"q", 0x10}, {"w", 0x11}, {"e", 0x12}, {"r", 0x13}, |
| 1249 | + {"t", 0x14}, {"y", 0x15}, {"u", 0x16}, {"i", 0x17}, {"o", 0x18}, |
| 1250 | + {"p", 0x19}, {"bracket_left", 0x1A}, {"bracket_right", 0x1B}, {"enter", 0x1C}, |
| 1251 | + {"ctrl", 0x1D}, {"a", 0x1E}, {"s", 0x1F}, {"d", 0x20}, {"f", 0x21}, |
| 1252 | + {"g", 0x22}, {"h", 0x23}, {"j", 0x24}, {"k", 0x25}, {"l", 0x26}, |
| 1253 | + {"semicolon", 0x27}, {"quote", 0x28}, {"backtick", 0x29}, {"shift", 0x2A}, |
| 1254 | + {"backslash", 0x2B}, {"z", 0x2C}, {"x", 0x2D}, {"c", 0x2E}, {"v", 0x2F}, |
| 1255 | + {"b", 0x30}, {"n", 0x31}, {"m", 0x32}, {"comma", 0x33}, {"period", 0x34}, |
| 1256 | + {"slash", 0x35}, {"alt", 0x38}, {"space", 0x39}, {"capslock", 0x3A}, |
| 1257 | + {"f1", 0x3B}, {"f2", 0x3C}, {"f3", 0x3D}, {"f4", 0x3E}, {"f5", 0x3F}, |
| 1258 | + {"f6", 0x40}, {"f7", 0x41}, {"f8", 0x42}, {"f9", 0x43}, {"f10", 0x44}, |
| 1259 | + {"numlock", 0x45}, {"scrolllock", 0x46}, {"home", 0x47}, {"up", 0x48}, |
| 1260 | + {"pageup", 0x49}, {"minus_pad", 0x4A}, {"left", 0x4B}, {"center", 0x4C}, |
| 1261 | + {"right", 0x4D}, {"plus_pad", 0x4E}, {"end", 0x4F}, {"down", 0x50}, |
| 1262 | + {"pagedown", 0x51}, {"insert", 0x52}, {"delete", 0x53}, {"f11", 0x57}, |
| 1263 | + {"f12", 0x58}, {"win", 0xE05B}, {"context", 0xE05D}, {"printscreen", 0xE037}, |
| 1264 | + {"pause", 0xE11D45} |
| 1265 | + }; |
| 1266 | + |
| 1267 | + auto it = scancodes.find(key); |
| 1268 | + if (it != scancodes.end()) { |
| 1269 | + return it->second; |
| 1270 | + } |
| 1271 | + return 0; |
| 1272 | +} |
| 1273 | + |
1238 | 1274 | bool win32::is_key_down(std::string key) { |
1239 | 1275 | auto key_lower = |
1240 | 1276 | key | std::views::transform(::tolower) | std::ranges::to<std::string>(); |
1241 | 1277 |
|
1242 | | - constexpr auto key_map = |
1243 | | - std::to_array<std::pair<const char *, int>>({{"ctrl", VK_CONTROL}, |
1244 | | - {"shift", VK_SHIFT}, |
1245 | | - {"alt", VK_MENU}, |
1246 | | - {"space", VK_SPACE}, |
1247 | | - {"enter", VK_RETURN}, |
1248 | | - {"esc", VK_ESCAPE}, |
1249 | | - {"tab", VK_TAB}, |
1250 | | - {"backspace", VK_BACK}, |
1251 | | - {"delete", VK_DELETE}, |
1252 | | - {"left", VK_LEFT}, |
1253 | | - {"right", VK_RIGHT}, |
1254 | | - {"up", VK_UP}, |
1255 | | - {"down", VK_DOWN}, |
1256 | | - {"f1", VK_F1}, |
1257 | | - {"f2", VK_F2}, |
1258 | | - {"f3", VK_F3}, |
1259 | | - {"f4", VK_F4}, |
1260 | | - {"f5", VK_F5}, |
1261 | | - {"f6", VK_F6}, |
1262 | | - {"f7", VK_F7}, |
1263 | | - {"f8", VK_F8}, |
1264 | | - {"f9", VK_F9}, |
1265 | | - {"f10", VK_F10}, |
1266 | | - {"f11", VK_F11}, |
1267 | | - {"f12", VK_F12}, |
1268 | | - {"a", 'A'}, |
1269 | | - {"b", 'B'}, |
1270 | | - {"c", 'C'}, |
1271 | | - {"d", 'D'}, |
1272 | | - {"e", 'E'}, |
1273 | | - {"f", 'F'}, |
1274 | | - {"g", 'G'}, |
1275 | | - {"h", 'H'}, |
1276 | | - {"i", 'I'}, |
1277 | | - {"j", 'J'}, |
1278 | | - {"k", 'K'}, |
1279 | | - {"l", 'L'}, |
1280 | | - {"m", 'M'}, |
1281 | | - {"n", 'N'}, |
1282 | | - {"o", 'O'}, |
1283 | | - {"p", 'P'}, |
1284 | | - {"q", 'Q'}, |
1285 | | - {"r", 'R'}, |
1286 | | - {"s", 'S'}, |
1287 | | - {"t", 'T'}, |
1288 | | - {"u", 'U'}, |
1289 | | - {"v", 'V'}, |
1290 | | - {"w", 'W'}, |
1291 | | - {"x", 'X'}, |
1292 | | - {"y", 'Y'}, |
1293 | | - {"z", 'Z'}}); |
1294 | | - |
1295 | | - auto keycode = std::ranges::find_if(key_map, [key_lower](const auto &pair) { |
1296 | | - return key_lower == pair.first; |
1297 | | - }); |
1298 | | - |
1299 | | - if (keycode != key_map.end()) { |
1300 | | - return GetAsyncKeyState(keycode->second) & 0x8000; |
| 1278 | + WORD scancode = get_scancode(key_lower); |
| 1279 | + if (scancode != 0) { |
| 1280 | + SHORT state = GetAsyncKeyState(MapVirtualKeyW(scancode & 0xFF, MAPVK_VSC_TO_VK)); |
| 1281 | + return (state & 0x8000) != 0; |
1301 | 1282 | } |
1302 | 1283 |
|
1303 | 1284 | return false; |
1304 | 1285 | } |
1305 | 1286 |
|
| 1287 | + |
| 1288 | +static bool is_extended_key(WORD scancode) { |
| 1289 | + return (scancode & 0xFF00) == 0xE000 || (scancode & 0xFF0000) == 0xE10000; |
| 1290 | +} |
| 1291 | + |
| 1292 | +void win32::simulate_hotkeys(std::vector<std::string> keys) { |
| 1293 | + if (keys.empty()) return; |
| 1294 | + |
| 1295 | + for (const auto& key : keys) { |
| 1296 | + simulate_key_down(key); |
| 1297 | + } |
| 1298 | + for (auto it = keys.rbegin(); it != keys.rend(); ++it) { |
| 1299 | + simulate_key_up(*it); |
| 1300 | + } |
| 1301 | +} |
| 1302 | + |
| 1303 | +void win32::simulate_key_press(std::string key) { |
| 1304 | + simulate_key_down(key); |
| 1305 | + simulate_key_up(key); |
| 1306 | +} |
| 1307 | + |
| 1308 | +void win32::simulate_key_down(std::string key) { |
| 1309 | + WORD sc = get_scancode(key); |
| 1310 | + if (sc == 0) return; |
| 1311 | + |
| 1312 | + INPUT input = {0}; |
| 1313 | + input.type = INPUT_KEYBOARD; |
| 1314 | + input.ki.wScan = sc & 0xFF; |
| 1315 | + input.ki.dwFlags = KEYEVENTF_SCANCODE; |
| 1316 | + |
| 1317 | + if (is_extended_key(sc)) { |
| 1318 | + input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; |
| 1319 | + } |
| 1320 | + |
| 1321 | + SendInput(1, &input, sizeof(INPUT)); |
| 1322 | +} |
| 1323 | + |
| 1324 | +void win32::simulate_key_up(std::string key) { |
| 1325 | + WORD sc = get_scancode(key); |
| 1326 | + if (sc == 0) return; |
| 1327 | + |
| 1328 | + INPUT input = {0}; |
| 1329 | + input.type = INPUT_KEYBOARD; |
| 1330 | + input.ki.wScan = sc & 0xFF; |
| 1331 | + input.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; |
| 1332 | + |
| 1333 | + if (is_extended_key(sc)) { |
| 1334 | + input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; |
| 1335 | + } |
| 1336 | + |
| 1337 | + SendInput(1, &input, sizeof(INPUT)); |
| 1338 | +} |
| 1339 | + |
| 1340 | +void win32::simulate_text_input(std::string text) { |
| 1341 | + std::wstring wtext = utf8_to_wstring(text); |
| 1342 | + |
| 1343 | + for (wchar_t c : wtext) { |
| 1344 | + INPUT input[2] = {0}; |
| 1345 | + |
| 1346 | + input[0].type = INPUT_KEYBOARD; |
| 1347 | + input[0].ki.wScan = c; |
| 1348 | + input[0].ki.dwFlags = KEYEVENTF_UNICODE; |
| 1349 | + |
| 1350 | + input[1].type = INPUT_KEYBOARD; |
| 1351 | + input[1].ki.wScan = c; |
| 1352 | + input[1].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP; |
| 1353 | + |
| 1354 | + SendInput(2, input, sizeof(INPUT)); |
| 1355 | + } |
| 1356 | +} |
| 1357 | + |
| 1358 | +void win32::simulate_mouse_move(int x, int y) { |
| 1359 | + INPUT input = {0}; |
| 1360 | + input.type = INPUT_MOUSE; |
| 1361 | + input.mi.dx = (x * 65535) / (GetSystemMetrics(SM_CXSCREEN) - 1); |
| 1362 | + input.mi.dy = (y * 65535) / (GetSystemMetrics(SM_CYSCREEN) - 1); |
| 1363 | + input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; |
| 1364 | + SendInput(1, &input, sizeof(INPUT)); |
| 1365 | +} |
| 1366 | + |
| 1367 | +static void get_mouse_flags(std::string button, bool down, DWORD& flags, DWORD& data) { |
| 1368 | + std::transform(button.begin(), button.end(), button.begin(), ::tolower); |
| 1369 | + flags = 0; |
| 1370 | + data = 0; |
| 1371 | + |
| 1372 | + if (button == "left") { |
| 1373 | + flags = down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; |
| 1374 | + } else if (button == "right") { |
| 1375 | + flags = down ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; |
| 1376 | + } else if (button == "middle") { |
| 1377 | + flags = down ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP; |
| 1378 | + } else if (button == "x1") { |
| 1379 | + flags = down ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP; |
| 1380 | + data = XBUTTON1; |
| 1381 | + } else if (button == "x2") { |
| 1382 | + flags = down ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP; |
| 1383 | + data = XBUTTON2; |
| 1384 | + } |
| 1385 | +} |
| 1386 | + |
| 1387 | +void win32::simulate_mouse_click(std::string button) { |
| 1388 | + simulate_mouse_down(button); |
| 1389 | + simulate_mouse_up(button); |
| 1390 | +} |
| 1391 | + |
| 1392 | +void win32::simulate_mouse_down(std::string button) { |
| 1393 | + DWORD flags, data; |
| 1394 | + get_mouse_flags(button, true, flags, data); |
| 1395 | + |
| 1396 | + if (flags == 0) return; |
| 1397 | + |
| 1398 | + INPUT input = {0}; |
| 1399 | + input.type = INPUT_MOUSE; |
| 1400 | + input.mi.dwFlags = flags; |
| 1401 | + input.mi.mouseData = data; |
| 1402 | + SendInput(1, &input, sizeof(INPUT)); |
| 1403 | +} |
| 1404 | + |
| 1405 | +void win32::simulate_mouse_up(std::string button) { |
| 1406 | + DWORD flags, data; |
| 1407 | + get_mouse_flags(button, false, flags, data); |
| 1408 | + |
| 1409 | + if (flags == 0) return; |
| 1410 | + |
| 1411 | + INPUT input = {0}; |
| 1412 | + input.type = INPUT_MOUSE; |
| 1413 | + input.mi.dwFlags = flags; |
| 1414 | + input.mi.mouseData = data; |
| 1415 | + SendInput(1, &input, sizeof(INPUT)); |
| 1416 | +} |
| 1417 | + |
1306 | 1418 | struct WinToastEventHandler : public IWinToastHandler { |
1307 | 1419 | std::function<void(int)> on_activate = [](int) {}; |
1308 | 1420 | std::function<void(WinToastDismissalReason)> on_dismiss = |
@@ -1459,11 +1571,32 @@ void screenside_button_controller::add_button(std::string icon_svg, |
1459 | 1571 | if ($menu.expired()) |
1460 | 1572 | return; |
1461 | 1573 | auto menu = $menu.lock(); |
1462 | | - auto button = std::make_shared<screenside_button_group_widget::button_widget>(icon_svg); |
| 1574 | + auto button = |
| 1575 | + std::make_shared<screenside_button_group_widget::button_widget>( |
| 1576 | + icon_svg); |
1463 | 1577 | button->on_click = on_click; |
1464 | | - if(auto group = menu->get_child<screenside_button_group_widget>()) { |
| 1578 | + if (auto group = menu->get_child<screenside_button_group_widget>()) { |
1465 | 1579 | group->children.push_back(button); |
1466 | 1580 | group->children_dirty = true; |
1467 | 1581 | } |
1468 | 1582 | } |
| 1583 | +std::string breeze::current_process_name() { |
| 1584 | + static std::string process_name = []() { |
| 1585 | + wchar_t buffer[MAX_PATH]; |
| 1586 | + GetModuleFileNameW(NULL, buffer, MAX_PATH); |
| 1587 | + return wstring_to_utf8( |
| 1588 | + std::filesystem::path(buffer).filename().wstring()); |
| 1589 | + }(); |
| 1590 | + |
| 1591 | + return process_name; |
| 1592 | +} |
| 1593 | +std::string breeze::current_process_path() { |
| 1594 | + static std::string process_path = []() { |
| 1595 | + wchar_t buffer[MAX_PATH]; |
| 1596 | + GetModuleFileNameW(NULL, buffer, MAX_PATH); |
| 1597 | + return wstring_to_utf8(std::filesystem::path(buffer).wstring()); |
| 1598 | + }(); |
| 1599 | + |
| 1600 | + return process_path; |
| 1601 | +} |
1469 | 1602 | } // namespace mb_shell::js |
0 commit comments