checkpoint: fixing ux with window frame bar

This commit is contained in:
2026-03-13 13:13:35 -04:00
parent c76aba64e4
commit ca01397885
9 changed files with 226 additions and 89 deletions

9
check_hello_imgui.py Normal file
View File

@@ -0,0 +1,9 @@
import sys
import os
try:
from imgui_bundle import hello_imgui
rp = hello_imgui.RunnerParams()
print(f"Default borderless: {rp.app_window_params.borderless}")
except Exception as e:
print(f"Error: {e}")

View File

@@ -23,7 +23,7 @@ active = "C:/projects/gencpp/gencpp_sloppy.toml"
separate_message_panel = false separate_message_panel = false
separate_response_panel = false separate_response_panel = false
separate_tool_calls_panel = false separate_tool_calls_panel = false
bg_shader_enabled = false bg_shader_enabled = true
crt_filter_enabled = false crt_filter_enabled = false
separate_task_dag = false separate_task_dag = false
separate_usage_analytics = false separate_usage_analytics = false
@@ -51,20 +51,21 @@ separate_external_tools = false
"Discussion Hub" = true "Discussion Hub" = true
"Operations Hub" = true "Operations Hub" = true
Message = false Message = false
Response = false Response = true
"Tool Calls" = false "Tool Calls" = true
Theme = true Theme = true
"Log Management" = true "Log Management" = true
Diagnostics = false Diagnostics = false
"External Tools" = false "External Tools" = false
"Shader Editor" = false
[theme] [theme]
palette = "Nord Dark" palette = "Nord Dark"
font_path = "fonts/Inter-Regular.ttf" font_path = "fonts/Inter-Regular.ttf"
font_size = 16.0 font_size = 16.0
scale = 1.0 scale = 1.0
transparency = 1.0 transparency = 0.5400000214576721
child_transparency = 1.0 child_transparency = 0.5899999737739563
[mma] [mma]
max_workers = 4 max_workers = 4

25
imgui.ini Normal file
View File

@@ -0,0 +1,25 @@
;;; !!! This configuration is handled by HelloImGui and stores several Ini Files, separated by markers like this:
;;;<<<INI_NAME>>>;;;
;;;<<<ImGui_655921752_Default>>>;;;
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Docking][Data]
;;;<<<Layout_655921752_Default>>>;;;
;;;<<<HelloImGui_Misc>>>;;;
[Layout]
Name=Default
[StatusBar]
Show=false
ShowFps=true
[Theme]
Name=DarculaDarker
;;;<<<SplitIds>>>;;;
{"gImGuiSplitIDs":{}}

22
manual_slop_test.ini Normal file
View File

@@ -0,0 +1,22 @@
;;; !!! This configuration is handled by HelloImGui and stores several Ini Files, separated by markers like this:
;;;<<<INI_NAME>>>;;;
;;;<<<ImGui_655921752_Default>>>;;;
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Docking][Data]
;;;<<<Layout_655921752_Default>>>;;;
;;;<<<HelloImGui_Misc>>>;;;
[Layout]
Name=Default
[StatusBar]
Show=false
ShowFps=true
[Theme]
Name=DarculaDarker
;;;<<<SplitIds>>>;;;
{"gImGuiSplitIDs":{}}

View File

@@ -44,18 +44,18 @@ Collapsed=0
DockId=0x00000001,0 DockId=0x00000001,0
[Window][Message] [Window][Message]
Pos=642,1879 Pos=661,1426
Size=1002,242 Size=716,455
Collapsed=0 Collapsed=0
[Window][Response] [Window][Response]
Pos=1700,1898 Pos=2437,925
Size=1111,224 Size=1111,773
Collapsed=0 Collapsed=0
[Window][Tool Calls] [Window][Tool Calls]
Pos=855,1482 Pos=464,1088
Size=1014,655 Size=564,220
Collapsed=0 Collapsed=0
DockId=0x00000006,0 DockId=0x00000006,0
@@ -74,8 +74,8 @@ Collapsed=0
DockId=0xAFC85805,2 DockId=0xAFC85805,2
[Window][Theme] [Window][Theme]
Pos=0,207 Pos=0,542
Size=499,1403 Size=310,658
Collapsed=0 Collapsed=0
DockId=0x00000002,2 DockId=0x00000002,2
@@ -85,14 +85,14 @@ Size=900,700
Collapsed=0 Collapsed=0
[Window][Diagnostics] [Window][Diagnostics]
Pos=2641,34 Pos=1649,24
Size=1199,2103 Size=580,1284
Collapsed=0 Collapsed=0
DockId=0x00000010,2 DockId=0x00000010,2
[Window][Context Hub] [Window][Context Hub]
Pos=0,207 Pos=0,542
Size=499,1403 Size=310,658
Collapsed=0 Collapsed=0
DockId=0x00000002,1 DockId=0x00000002,1
@@ -103,26 +103,26 @@ Collapsed=0
DockId=0x0000000D,0 DockId=0x0000000D,0
[Window][Discussion Hub] [Window][Discussion Hub]
Pos=1172,24 Pos=649,24
Size=703,1586 Size=449,1176
Collapsed=0 Collapsed=0
DockId=0x00000013,0 DockId=0x00000013,0
[Window][Operations Hub] [Window][Operations Hub]
Pos=501,24 Pos=312,24
Size=669,1586 Size=335,1176
Collapsed=0 Collapsed=0
DockId=0x00000005,0 DockId=0x00000005,0
[Window][Files & Media] [Window][Files & Media]
Pos=0,207 Pos=0,542
Size=499,1403 Size=310,658
Collapsed=0 Collapsed=0
DockId=0x00000002,0 DockId=0x00000002,0
[Window][AI Settings] [Window][AI Settings]
Pos=0,24 Pos=0,24
Size=499,181 Size=310,516
Collapsed=0 Collapsed=0
DockId=0x00000001,0 DockId=0x00000001,0
@@ -132,14 +132,14 @@ Size=416,325
Collapsed=0 Collapsed=0
[Window][MMA Dashboard] [Window][MMA Dashboard]
Pos=1877,24 Pos=1100,24
Size=1018,1586 Size=580,1176
Collapsed=0 Collapsed=0
DockId=0x00000010,0 DockId=0x00000010,0
[Window][Log Management] [Window][Log Management]
Pos=1877,24 Pos=1100,24
Size=1018,1586 Size=580,1176
Collapsed=0 Collapsed=0
DockId=0x00000010,1 DockId=0x00000010,1
@@ -175,7 +175,7 @@ Size=381,329
Collapsed=0 Collapsed=0
[Window][Last Script Output] [Window][Last Script Output]
Pos=1005,343 Pos=2810,265
Size=800,562 Size=800,562
Collapsed=0 Collapsed=0
@@ -285,8 +285,8 @@ Size=900,700
Collapsed=0 Collapsed=0
[Window][Text Viewer - Tool Call #1 Details] [Window][Text Viewer - Tool Call #1 Details]
Pos=2318,1220 Pos=165,1081
Size=900,700 Size=727,725
Collapsed=0 Collapsed=0
[Window][Text Viewer - Tool Call #10 Details] [Window][Text Viewer - Tool Call #10 Details]
@@ -330,8 +330,8 @@ Size=967,499
Collapsed=0 Collapsed=0
[Window][Usage Analytics] [Window][Usage Analytics]
Pos=2822,1717 Pos=1649,1053
Size=1018,420 Size=580,255
Collapsed=0 Collapsed=0
DockId=0x0000000F,0 DockId=0x0000000F,0
@@ -350,6 +350,41 @@ Pos=856,546
Size=1000,800 Size=1000,800
Collapsed=0 Collapsed=0
[Window][External Tools]
Pos=531,376
Size=616,409
Collapsed=0
[Window][Text Viewer - Tool Call #2 Details]
Pos=60,60
Size=900,700
Collapsed=0
[Window][Text Viewer - Tool Call #3 Details]
Pos=60,60
Size=900,700
Collapsed=0
[Window][Text Viewer - Entry #4]
Pos=1127,922
Size=900,700
Collapsed=0
[Window][Text Viewer - Entry #10]
Pos=755,715
Size=1593,1240
Collapsed=0
[Window][Text Viewer - Entry #5]
Pos=60,60
Size=900,700
Collapsed=0
[Window][Shader Editor]
Pos=457,710
Size=493,252
Collapsed=0
[Table][0xFB6E3870,4] [Table][0xFB6E3870,4]
RefScale=13 RefScale=13
Column 0 Width=80 Column 0 Width=80
@@ -381,11 +416,11 @@ Column 3 Width=20
Column 4 Weight=1.0000 Column 4 Weight=1.0000
[Table][0x2A6000B6,4] [Table][0x2A6000B6,4]
RefScale=14 RefScale=16
Column 0 Width=42 Column 0 Width=48
Column 1 Width=61 Column 1 Width=68
Column 2 Weight=1.0000 Column 2 Weight=1.0000
Column 3 Width=105 Column 3 Width=120
[Table][0x8BCC69C7,6] [Table][0x8BCC69C7,6]
RefScale=13 RefScale=13
@@ -407,7 +442,7 @@ Column 3 Width=120
RefScale=16 RefScale=16
Column 0 Width=48 Column 0 Width=48
Column 1 Weight=1.0000 Column 1 Weight=1.0000
Column 2 Width=119 Column 2 Width=118
Column 3 Width=48 Column 3 Width=48
[Table][0xD99F45C5,4] [Table][0xD99F45C5,4]
@@ -429,9 +464,9 @@ Column 1 Width=100
Column 2 Weight=1.0000 Column 2 Weight=1.0000
[Table][0xA02D8C87,3] [Table][0xA02D8C87,3]
RefScale=24 RefScale=16
Column 0 Width=270 Column 0 Width=180
Column 1 Width=180 Column 1 Width=120
Column 2 Weight=1.0000 Column 2 Weight=1.0000
[Table][0xD0277E63,2] [Table][0xD0277E63,2]
@@ -463,20 +498,20 @@ Column 1 Weight=1.0000
DockNode ID=0x00000008 Pos=3125,170 Size=593,1157 Split=Y DockNode ID=0x00000008 Pos=3125,170 Size=593,1157 Split=Y
DockNode ID=0x00000009 Parent=0x00000008 SizeRef=1029,147 Selected=0x0469CA7A DockNode ID=0x00000009 Parent=0x00000008 SizeRef=1029,147 Selected=0x0469CA7A
DockNode ID=0x0000000A Parent=0x00000008 SizeRef=1029,145 Selected=0xDF822E02 DockNode ID=0x0000000A Parent=0x00000008 SizeRef=1029,145 Selected=0xDF822E02
DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,24 Size=2895,1586 Split=X DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,24 Size=1680,1176 Split=X
DockNode ID=0x00000003 Parent=0xAFC85805 SizeRef=2820,1183 Split=X DockNode ID=0x00000003 Parent=0xAFC85805 SizeRef=1647,1183 Split=X
DockNode ID=0x0000000B Parent=0x00000003 SizeRef=404,1186 Split=X Selected=0xF4139CA2 DockNode ID=0x0000000B Parent=0x00000003 SizeRef=404,1186 Split=X Selected=0xF4139CA2
DockNode ID=0x00000007 Parent=0x0000000B SizeRef=499,858 Split=Y Selected=0x8CA2375C DockNode ID=0x00000007 Parent=0x0000000B SizeRef=310,858 Split=Y Selected=0x8CA2375C
DockNode ID=0x00000001 Parent=0x00000007 SizeRef=824,708 CentralNode=1 Selected=0x7BD57D6A DockNode ID=0x00000001 Parent=0x00000007 SizeRef=824,624 CentralNode=1 Selected=0x7BD57D6A
DockNode ID=0x00000002 Parent=0x00000007 SizeRef=824,1403 Selected=0xF4139CA2 DockNode ID=0x00000002 Parent=0x00000007 SizeRef=824,658 Selected=0xF4139CA2
DockNode ID=0x0000000E Parent=0x0000000B SizeRef=1374,858 Split=X Selected=0x418C7449 DockNode ID=0x0000000E Parent=0x0000000B SizeRef=786,858 Split=X Selected=0x418C7449
DockNode ID=0x00000012 Parent=0x0000000E SizeRef=669,402 Split=Y Selected=0x418C7449 DockNode ID=0x00000012 Parent=0x0000000E SizeRef=335,402 Split=Y Selected=0x418C7449
DockNode ID=0x00000005 Parent=0x00000012 SizeRef=876,1455 Selected=0x418C7449 DockNode ID=0x00000005 Parent=0x00000012 SizeRef=876,1749 Selected=0x418C7449
DockNode ID=0x00000006 Parent=0x00000012 SizeRef=876,654 Selected=0x1D56B311 DockNode ID=0x00000006 Parent=0x00000012 SizeRef=876,362 Selected=0x1D56B311
DockNode ID=0x00000013 Parent=0x0000000E SizeRef=703,402 Selected=0x6F2B5B04 DockNode ID=0x00000013 Parent=0x0000000E SizeRef=449,402 Selected=0x6F2B5B04
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=435,1186 Selected=0x363E93D6 DockNode ID=0x0000000D Parent=0x00000003 SizeRef=435,1186 Selected=0x363E93D6
DockNode ID=0x00000004 Parent=0xAFC85805 SizeRef=1018,1183 Split=Y Selected=0x3AEC3498 DockNode ID=0x00000004 Parent=0xAFC85805 SizeRef=580,1183 Split=Y Selected=0x3AEC3498
DockNode ID=0x00000010 Parent=0x00000004 SizeRef=1199,1689 Selected=0x3AEC3498 DockNode ID=0x00000010 Parent=0x00000004 SizeRef=1199,1689 Selected=0x2C0206CE
DockNode ID=0x00000011 Parent=0x00000004 SizeRef=1199,420 Split=X Selected=0xDEB547B6 DockNode ID=0x00000011 Parent=0x00000004 SizeRef=1199,420 Split=X Selected=0xDEB547B6
DockNode ID=0x0000000C Parent=0x00000011 SizeRef=916,380 Selected=0x655BC6E9 DockNode ID=0x0000000C Parent=0x00000011 SizeRef=916,380 Selected=0x655BC6E9
DockNode ID=0x0000000F Parent=0x00000011 SizeRef=281,380 Selected=0xDEB547B6 DockNode ID=0x0000000F Parent=0x00000011 SizeRef=281,380 Selected=0xDEB547B6

View File

@@ -17,6 +17,7 @@ dependencies = [
"tree-sitter-python>=0.25.0", "tree-sitter-python>=0.25.0",
"mcp>=1.0.0", "mcp>=1.0.0",
"pytest-timeout>=2.4.0", "pytest-timeout>=2.4.0",
"pyopengl>=3.1.10",
] ]
[dependency-groups] [dependency-groups]

View File

@@ -0,0 +1,12 @@
from imgui_bundle import hello_imgui, imgui
def on_gui():
imgui.text("Hello world")
params = hello_imgui.RunnerParams()
params.app_window_params.borderless = True
params.app_window_params.borderless_movable = True
params.app_window_params.borderless_resizable = True
params.app_window_params.borderless_closable = True
hello_imgui.run(params)

View File

@@ -368,37 +368,57 @@ class App:
self.ai_status = f"error: {e}" self.ai_status = f"error: {e}"
imgui.end_menu() imgui.end_menu()
def _render_custom_title_bar(self) -> None: # Draw right-aligned window controls directly in the menu bar
hwnd = imgui.get_main_viewport().platform_handle try:
if not hwnd: return import ctypes
bar_height = 30 ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
imgui.set_next_window_pos((0, 0)) ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]
imgui.set_next_window_size((imgui.get_io().display_size.x, bar_height)) hwnd_capsule = imgui.get_main_viewport().platform_handle_raw
flags = (imgui.WindowFlags_.no_title_bar | imgui.WindowFlags_.no_resize | hwnd = ctypes.pythonapi.PyCapsule_GetPointer(hwnd_capsule, b"nb_handle")
imgui.WindowFlags_.no_move | imgui.WindowFlags_.no_scrollbar | except Exception:
imgui.WindowFlags_.no_saved_settings | imgui.WindowFlags_.no_bring_to_front_on_focus) hwnd = 0
imgui.push_style_var(imgui.StyleVar_.window_rounding, 0)
imgui.push_style_var(imgui.StyleVar_.window_border_size, 0) if hwnd:
imgui.push_style_var(imgui.StyleVar_.window_padding, (10, 5))
if imgui.begin("##custom_title_bar", None, flags):
imgui.text("manual slop")
if imgui.is_window_hovered() and imgui.is_mouse_dragging(0):
win32gui.ReleaseCapture()
win32gui.SendMessage(hwnd, win32con.WM_NCLBUTTONDOWN, win32con.HTCAPTION, 0)
btn_w = 40 btn_w = 40
spacing = imgui.get_style().item_spacing.x display_w = imgui.get_io().display_size.x
right_x = imgui.get_window_width() - (btn_w * 3 + spacing * 2 + 10) right_x = display_w - (btn_w * 3)
imgui.same_line(right_x)
if imgui.button("_", (btn_w, 20)): # Drag area check using an explicit invisible button spanning the empty space
curr_x = imgui.get_cursor_pos_x()
drag_w = right_x - curr_x
if drag_w > 0:
imgui.invisible_button("##drag_area", (drag_w, 0))
if imgui.is_item_hovered() and imgui.is_mouse_clicked(0):
win32gui.ReleaseCapture()
win32gui.SendMessage(hwnd, win32con.WM_NCLBUTTONDOWN, win32con.HTCAPTION, 0)
imgui.push_style_color(imgui.Col_.button, vec4(0, 0, 0, 0))
try:
is_max = win32gui.GetWindowPlacement(hwnd)[1] == win32con.SW_SHOWMAXIMIZED
except Exception:
is_max = False
imgui.set_cursor_pos_x(right_x)
if imgui.button("_", (btn_w, 0)):
win32gui.ShowWindow(hwnd, win32con.SW_MINIMIZE) win32gui.ShowWindow(hwnd, win32con.SW_MINIMIZE)
imgui.same_line()
if imgui.button("[]", (btn_w, 20)): imgui.set_cursor_pos_x(right_x + btn_w)
win32gui.ShowWindow(hwnd, win32con.SW_MAXIMIZE) if imgui.button("[=]" if is_max else "[]", (btn_w, 0)):
imgui.same_line() win32gui.ShowWindow(hwnd, win32con.SW_RESTORE if is_max else win32con.SW_MAXIMIZE)
if imgui.button("X", (btn_w, 20)):
imgui.set_cursor_pos_x(right_x + btn_w * 2)
imgui.push_style_color(imgui.Col_.button_hovered, vec4(200, 50, 50, 255))
if imgui.button("X", (btn_w, 0)):
win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0) win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)
imgui.end() imgui.pop_style_color()
imgui.pop_style_var(3)
imgui.pop_style_color()
def _render_custom_title_bar(self) -> None:
# Obsolete, removed since it renders behind the full screen dock space.
# Controls are now embedded in _show_menus.
pass
def _render_shader_live_editor(self) -> None: def _render_shader_live_editor(self) -> None:
if self.show_windows.get('Shader Editor', False): if self.show_windows.get('Shader Editor', False):

View File

@@ -9,21 +9,33 @@ def test_gui_window_controls_minimize_maximize_close():
with patch("src.gui_2.win32gui") as mock_win32gui, \ with patch("src.gui_2.win32gui") as mock_win32gui, \
patch("src.gui_2.win32con") as mock_win32con, \ patch("src.gui_2.win32con") as mock_win32con, \
patch("src.gui_2.imgui") as mock_imgui: patch("src.gui_2.imgui") as mock_imgui, \
patch("ctypes.pythonapi.PyCapsule_GetPointer") as mock_get_pointer:
# Setup mock for HWND # Setup mock for HWND
mock_viewport = MagicMock() mock_viewport = MagicMock()
mock_viewport.platform_handle = 12345 mock_viewport.platform_handle_raw = "mock_capsule"
mock_imgui.get_main_viewport.return_value = mock_viewport mock_imgui.get_main_viewport.return_value = mock_viewport
mock_get_pointer.return_value = 12345
mock_imgui.get_window_width.return_value = 800.0
mock_imgui.get_cursor_pos_x.return_value = 100.0
mock_imgui.get_io().display_size.x = 800.0
mock_style = MagicMock()
mock_style.item_spacing.x = 4.0
mock_imgui.get_style.return_value = mock_style
# Setup mock for buttons to simulate clicks # Setup mock for buttons to simulate clicks
# Let's say _render_custom_title_bar uses imgui.button # Let's say _render_custom_title_bar uses imgui.button
# We will test the close button logic # We will test the close button logic
# Since it's UI code, we just simulate the conditions # Since it's UI code, we just simulate the conditions
mock_imgui.button.return_value = True # Simulate all buttons being clicked mock_imgui.button.return_value = True # Simulate all buttons being clicked
# Call the method (to be implemented) # Avoid hitting actual menu logic that requires real runner_params
app._render_custom_title_bar() mock_imgui.begin_menu.return_value = False
app.runner_params = MagicMock()
# Call the method (now in _show_menus)
app._show_menus()
# Verify that win32gui calls are made for minimize, maximize, close # Verify that win32gui calls are made for minimize, maximize, close
# Since all buttons returned True, all actions should be triggered in this dummy test # Since all buttons returned True, all actions should be triggered in this dummy test