Files
totk-pc-recomp/runtime/ui/menu_win.cpp
T
Valiantsin DzerakhandClaude Opus 5.5 8691f6d724 Remap keys, mouse buttons and controller buttons from the Controls tab
Every Switch button and the eight stick directions the keys drive get two key cells and a controller cell under the
button layout. A cell takes the next key, mouse button or controller button pressed; a key in use moves over, a
controller button swaps. The tab writes bind_ lines (new: bind_LSTICK_* / bind_RSTICK_*, key:default, pad:default) and
input_win.c builds the tables again when one changes, so remapping applies while the game runs. More keys can be
bound: Enter, Backspace, right Shift and Ctrl, Alt, the numpad, punctuation, F2-F7, F9, F12, mouse buttons 4 and 5.
Alt alone no longer enters the window menu loop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 17:53:57 +03:00

88 lines
3.4 KiB
C++

// Win32 adapter of the in-game menu: window messages to menu events (menu.h). The only Win32 code of the menu; an SDL3
// window gets its own adapter later. Window thread.
//
// F1 opens and closes the menu, Esc opens it (with the menu open, Esc goes to the menu, which closes). Esc also releases
// the cursor (input_window_msg runs first; closing the menu gives the capture back). While the menu is open, its keys,
// the mouse and focus changes go to it; the game polls the keyboard on its own (input_win.c) and gets nothing while the
// menu is open (input_menu).
#include <windows.h>
#include <windowsx.h>
#include "imgui.h"
extern "C" {
#include "input.h"
#include "ui/menu.h"
}
static ImGuiKey key_of(WPARAM vk) {
switch (vk) {
case VK_UP: return ImGuiKey_UpArrow;
case VK_DOWN: return ImGuiKey_DownArrow;
case VK_LEFT: return ImGuiKey_LeftArrow;
case VK_RIGHT: return ImGuiKey_RightArrow;
case VK_RETURN: return ImGuiKey_Enter;
case VK_SPACE: return ImGuiKey_Space;
case VK_ESCAPE: return ImGuiKey_Escape;
case VK_TAB: return ImGuiKey_Tab;
case VK_BACK: return ImGuiKey_Backspace;
case VK_DELETE: return ImGuiKey_Delete; // clears a cell of the remapping rows
case VK_HOME: return ImGuiKey_Home;
case VK_END: return ImGuiKey_End;
case VK_PRIOR: return ImGuiKey_PageUp;
case VK_NEXT: return ImGuiKey_PageDown;
case VK_SHIFT: return ImGuiKey_LeftShift;
case VK_CONTROL: return ImGuiKey_LeftCtrl;
case 'Q': return ImGuiKey_Q; // previous tab
case 'E': return ImGuiKey_E; // next tab
default: return ImGuiKey_None;
}
}
extern "C" int menu_window_msg(HWND h, UINT m, WPARAM w, LPARAM l, LRESULT *res) {
(void)h;
switch (m) {
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
// bit 30: auto-repeat
// Esc with the menu open (opened by F1 too) is not a toggle here: it goes to the menu, which closes itself
if (!(l & (1 << 30)) && (w == VK_F1 || (w == VK_ESCAPE && !menu_is_open()))) {
menu_toggle();
*res = 0;
return 1;
}
if (w == VK_F10) { // also keeps F10 from opening the window menu
if (!(l & (1 << 30))) menu_perf_cycle();
*res = 0;
return 1;
}
[[fallthrough]];
case WM_KEYUP:
case WM_SYSKEYUP:
if (!menu_is_open()) return 0;
if (ImGuiKey k = key_of(w)) menu_event_key(k, m == WM_KEYDOWN || m == WM_SYSKEYDOWN);
return 0; // F11 and the system keys keep working
case WM_MOUSEMOVE:
if (menu_is_open()) menu_event_mouse_pos((float)GET_X_LPARAM(l), (float)GET_Y_LPARAM(l));
return 0;
case WM_LBUTTONDOWN: case WM_LBUTTONUP:
case WM_RBUTTONDOWN: case WM_RBUTTONUP:
case WM_MBUTTONDOWN: case WM_MBUTTONUP: {
if (!menu_is_open()) return 0;
int b = m == WM_LBUTTONDOWN || m == WM_LBUTTONUP ? 0 : m == WM_RBUTTONDOWN || m == WM_RBUTTONUP ? 1 : 2;
int down = m == WM_LBUTTONDOWN || m == WM_RBUTTONDOWN || m == WM_MBUTTONDOWN;
menu_event_mouse_pos((float)GET_X_LPARAM(l), (float)GET_Y_LPARAM(l));
menu_event_mouse_button(b, down);
return 0;
}
case WM_MOUSEWHEEL:
if (menu_is_open()) menu_event_wheel(0, (float)GET_WHEEL_DELTA_WPARAM(w) / WHEEL_DELTA);
return 0;
case WM_SETFOCUS:
case WM_KILLFOCUS:
menu_event_focus(m == WM_SETFOCUS);
return 0;
}
return 0;
}