From 304441c71997ee61e618146f4d4302c6d2b952ad Mon Sep 17 00:00:00 2001 From: salmonik Date: Tue, 27 Oct 2026 18:21:13 +0100 Subject: GUI: Insert-only close, freeze mouse look at the source Feedback pass: - Insert now toggles the GUI; the old text tree moved to F1. - Remove the title-bar X. Insert is the only close path; Esc only cancels bind capture. - Discard accumulated mouse deltas in CInput::CreateMove before the game can apply them (CInput::ClearStates), so the camera no longer moves for a frame and snaps back. Also skip ExtraMouseSample and zero relative mouse state while the GUI is open. - Strip attack/use/impulse/weapon selection from the command while open; keep jump, duck and walk. Skip combat command edits (spread seed) too. - Widen System page buttons so "Reload config" and "Reset defaults" fit. - Update CONTEXT/ADR for the Insert-only close behavior. --- src/gui.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 19 deletions(-) (limited to 'src/gui.cpp') diff --git a/src/gui.cpp b/src/gui.cpp index 923cd4d..eb9062e 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -1,4 +1,4 @@ -// gui.cpp — custom immediate-mode GUI shell (temporary F2 preview) +// gui.cpp — custom immediate-mode GUI shell (temporary Insert preview) // // This is the first vertical slice: the visual shell, categories, cards, // dummy controls, cursor handling and input freeze. It does not read or write @@ -575,6 +575,7 @@ static void close_gui() { g_dragging = false; g_scroll_drag = false; g_slider_drag = -1; + input_clear_mouse_states(); if (g_sdl_ready) { if (sd_set_relative) sd_set_relative(g_prev_relative ? 1 : 0); @@ -611,6 +612,7 @@ static void open_gui() { if (sd_show_cursor) sd_show_cursor(1); } + input_clear_mouse_states(); g_open = true; g_capture_card = -1; g_wheel.exchange(0); @@ -659,7 +661,7 @@ static void handle_capture(const unsigned char *keys) { for (int k = 0; k < 512; k++) { if (!keys[k] || g_prev_keys[k]) continue; - if (k == 73 || k == 59) // Insert reserved; F2 closes the preview + if (k == 73) // Insert is reserved for opening/closing the GUI continue; g_cards[g_capture_card].bind = k; g_capture_card = -1; @@ -674,12 +676,7 @@ static void handle_mouse_click() { // title bar: drag or close Rect title{g_win_x, g_win_y, g_win_w, S(38.0f)}; - Rect close{g_win_x + g_win_w - S(38.0f), g_win_y, S(38.0f), S(38.0f)}; if (title.has(mx, my)) { - if (close.has(mx, my)) { - close_gui(); - return; - } g_dragging = true; g_drag_dx = mx - g_win_x; g_drag_dy = my - g_win_y; @@ -787,7 +784,7 @@ static void handle_mouse_click() { return; } if (ct.kind == CK_BUTTON) { - Rect b{cr.x + cr.w - S(130.0f), by + S(3.0f), S(114.0f), + Rect b{cr.x + cr.w - S(176.0f), by + S(3.0f), S(160.0f), S(26.0f)}; if (b.has(mx, my)) { logf("gui: dummy action %s", ct.label ? ct.label : "?"); @@ -858,8 +855,8 @@ void gui_handle_input() { if (nk > 512) nk = 512; update_mouse(); - bool f2 = (nk > 59) && keys[59]; - bool f2_edge = f2 && !g_prev_keys[59]; + bool toggle_key = (nk > 73) && keys[73]; + bool toggle_edge = toggle_key && !g_prev_keys[73]; bool esc = (nk > 41) && keys[41]; bool esc_edge = esc && !g_prev_keys[41]; bool left = (nk > 80) && keys[80]; @@ -867,7 +864,7 @@ void gui_handle_input() { bool left_edge = left && !g_prev_keys[80]; bool right_edge = right && !g_prev_keys[79]; - if (f2_edge) { + if (toggle_edge) { if (g_open) close_gui(); else @@ -887,6 +884,11 @@ void gui_handle_input() { sd_set_relative(0); if (sd_show_cursor) sd_show_cursor(1); + if (g_iface.engine) { + QAngle f = g_frozen; + using SetViewFn = void (*)(void *, QAngle *); + vfunc(g_iface.engine, 20)(g_iface.engine, &f); + } handle_capture(keys); @@ -1063,7 +1065,7 @@ static void draw_card(const Rect &clip, int index, int y) { text_in(clip, cr.x + S(16.0f), by + S(1.0f), ct.label, g_font_body, g_body_h, cr.w - S(24.0f), C_DIM); } else if (ct.kind == CK_BUTTON) { - Rect b{cr.x + cr.w - S(130.0f), by + S(3.0f), S(114.0f), S(26.0f)}; + Rect b{cr.x + cr.w - S(176.0f), by + S(3.0f), S(160.0f), S(26.0f)}; fill(b, Col{45, 50, 60, 255}, &clip); outline(b, C_BORDER, &clip); text_in(clip, b.x + S(10.0f), b.y + S(4.0f), ct.label, g_font_body, @@ -1126,12 +1128,6 @@ void gui_draw() { g_title_h, win.w - S(80.0f), C_TEXT); text_in(win, win.x + S(110.0f), win.y + S(10.0f), "GUI shell preview", g_font_body, g_body_h, win.w - S(180.0f), C_DIM); - Rect close{win.x + win.w - S(38.0f), win.y, S(38.0f), S(38.0f)}; - fill(close, Col{45, 48, 56, 255}); - line(close.x + S(13.0f), close.y + S(12.0f), close.x + S(25.0f), - close.y + S(25.0f), C_DIM); - line(close.x + S(25.0f), close.y + S(12.0f), close.x + S(13.0f), - close.y + S(25.0f), C_DIM); Rect side{win.x, win.y + S(38.0f), S(190.0f), win.h - S(38.0f) - S(30.0f)}; @@ -1185,7 +1181,7 @@ void gui_draw() { "config: ~/.config/hl2hake/config", g_font_body, g_body_h, foot.w - S(220.0f), C_DIM); text_in(foot, foot.x + foot.w - S(200.0f), foot.y + S(6.0f), - g_capture_card >= 0 ? "press a key / Esc" : "F2 close | Insert text", + g_capture_card >= 0 ? "press a key / Esc" : "INS close | F1 text menu", g_font_body, g_body_h, S(190.0f), C_DIM); draw_tooltip(); @@ -1281,3 +1277,40 @@ SDL_WarpMouseGlobal(int x, int y) { if (real_warp_global) real_warp_global(x, y); } + +static unsigned int (*real_get_rel_mouse)(int *, int *) = nullptr; +static int (*real_poll_event)(void *) = nullptr; + +extern "C" __attribute__((visibility("default"))) unsigned int +SDL_GetRelativeMouseState(int *x, int *y) { + if (!real_get_rel_mouse) + real_get_rel_mouse = + (unsigned int (*)(int *, int *))dlsym(RTLD_NEXT, + "SDL_GetRelativeMouseState"); + unsigned int mask = real_get_rel_mouse ? real_get_rel_mouse(x, y) : 0; + if (g_open) { + if (x) *x = 0; + if (y) *y = 0; + } + return mask; +} + +extern "C" __attribute__((visibility("default"))) int +SDL_PollEvent(void *event) { + if (!real_poll_event) + real_poll_event = (int (*)(void *))dlsym(RTLD_NEXT, "SDL_PollEvent"); + if (!real_poll_event) + return 0; + for (;;) { + int r = real_poll_event(event); + if (!r) + return 0; + if (!g_open || !event) + return r; + unsigned int type = *(unsigned int *)event; + if (type != 0x400) // SDL_MOUSEMOTION + return r; + // Drop motion while the GUI is open: the game must not accumulate look + // deltas. The GUI uses absolute SDL_GetMouseState polling. + } +} -- cgit v1.2.3