mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
GetThreadDescription (win 10+ thread name) API support
This commit is contained in:
@@ -1516,6 +1516,7 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c
|
||||
out_evt->stack_base = demon_stack_base_vaddr_from_thread(event->thread);
|
||||
out_evt->tls_root = demon_tls_root_vaddr_from_thread(event->thread);
|
||||
out_evt->rip_vaddr = event->instruction_pointer;
|
||||
out_evt->string = event->string;
|
||||
}break;
|
||||
case DEMON_EventKind_LoadModule:
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global GetThreadDescriptionFunctionType *demon_w32_GetThreadDescription = 0;
|
||||
|
||||
global B32 demon_w32_resume_needed = 0;
|
||||
global DWORD demon_w32_resume_pid = 0;
|
||||
global DWORD demon_w32_resume_tid = 0;
|
||||
@@ -26,6 +28,17 @@ global String8List demon_w32_environment = {0};
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal U64
|
||||
demon_w32_hash_from_string(String8 string)
|
||||
{
|
||||
U64 result = 5381;
|
||||
for(U64 i = 0; i < string.size; i += 1)
|
||||
{
|
||||
result = ((result << 5) + result) + string.str[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal DEMON_W32_Ext*
|
||||
demon_w32_ext_alloc(void){
|
||||
DEMON_W32_Ext *result = demon_w32_proc_ext_free;
|
||||
@@ -351,6 +364,11 @@ demon_os_init(void){
|
||||
demon_w32_ext_arena = arena_alloc();
|
||||
demon_w32_detach_proc_arena = arena_alloc();
|
||||
|
||||
// rjf: load Windows 10+ GetThreadDescription API
|
||||
{
|
||||
demon_w32_GetThreadDescription = (GetThreadDescriptionFunctionType *)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "GetThreadDescription");
|
||||
}
|
||||
|
||||
// rjf: setup environment variables
|
||||
{
|
||||
CHAR *this_proc_env = GetEnvironmentStrings();
|
||||
@@ -771,6 +789,19 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
|
||||
DWORD sus_result = SuspendThread(thread_ext->thread.handle);
|
||||
(void)sus_result;
|
||||
|
||||
// rjf: unpack thread name
|
||||
String8 thread_name = {0};
|
||||
if(demon_w32_GetThreadDescription != 0)
|
||||
{
|
||||
WCHAR *thread_name_w = 0;
|
||||
HRESULT hr = demon_w32_GetThreadDescription(evt.u.CreateThread.hThread, &thread_name_w);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
thread_name = str8_from_16(arena, str16_cstring((U16 *)thread_name_w));
|
||||
LocalFree(thread_name_w);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: determine if this is the halter thread
|
||||
B32 is_halter = (evt.dwThreadId == demon_w32_halter_thread_id);
|
||||
|
||||
@@ -780,6 +811,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
|
||||
e->process = demon_ent_handle_from_ptr(process);
|
||||
e->thread = demon_ent_handle_from_ptr(thread);
|
||||
e->code = evt.dwThreadId;
|
||||
e->string = thread_name;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
@@ -1140,6 +1172,48 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: gather new thread-names
|
||||
if(demon_w32_GetThreadDescription != 0)
|
||||
{
|
||||
for(DEMON_Entity *process = demon_ent_root->first;
|
||||
process != 0;
|
||||
process = process->next)
|
||||
{
|
||||
if(process->kind != DEMON_EntityKind_Process) { continue; }
|
||||
for(DEMON_Entity *thread = process->first;
|
||||
thread != 0;
|
||||
thread = thread->next)
|
||||
{
|
||||
if(thread->kind != DEMON_EntityKind_Thread) { continue; }
|
||||
DEMON_W32_Ext *thread_ext = demon_w32_ext(thread);
|
||||
if(thread_ext->thread.last_name_hash == 0 ||
|
||||
thread_ext->thread.name_gather_time_us+1000000 <= os_now_microseconds())
|
||||
{
|
||||
String8 name = {0};
|
||||
{
|
||||
WCHAR *thread_name_w = 0;
|
||||
HRESULT hr = demon_w32_GetThreadDescription(thread_ext->thread.handle, &thread_name_w);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
name = str8_from_16(scratch.arena, str16_cstring((U16 *)thread_name_w));
|
||||
LocalFree(thread_name_w);
|
||||
}
|
||||
}
|
||||
U64 name_hash = demon_w32_hash_from_string(name);
|
||||
if(name.size != 0 && name_hash != thread_ext->thread.last_name_hash)
|
||||
{
|
||||
DEMON_Event *e = demon_push_event(arena, &result, DEMON_EventKind_SetThreadName);
|
||||
e->process = demon_ent_handle_from_ptr(process);
|
||||
e->thread = demon_ent_handle_from_ptr(thread);
|
||||
e->string = push_str8_copy(arena, name);
|
||||
}
|
||||
thread_ext->thread.name_gather_time_us = os_now_microseconds();
|
||||
thread_ext->thread.last_name_hash = name_hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(allen): handle errors? if (!got_new_event) ? if (!good_state) ?
|
||||
|
||||
// TODO(allen): per-Architecture
|
||||
|
||||
@@ -35,6 +35,8 @@ union DEMON_W32_Ext
|
||||
struct{
|
||||
HANDLE handle;
|
||||
U64 thread_local_base;
|
||||
U64 last_name_hash;
|
||||
U64 name_gather_time_us;
|
||||
} thread;
|
||||
struct{
|
||||
HANDLE handle;
|
||||
@@ -68,6 +70,7 @@ struct DEMON_W32_EntityNode
|
||||
DEMON_Entity *entity;
|
||||
};
|
||||
|
||||
typedef HRESULT GetThreadDescriptionFunctionType(HANDLE hThread, WCHAR **ppszThreadDescription);
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Win32 Demon Exceptions
|
||||
@@ -352,6 +355,7 @@ struct DEMON_PeOptionalHeader32Plus
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal U64 demon_w32_hash_from_string(String8 string);
|
||||
internal DEMON_W32_Ext* demon_w32_ext_alloc(void);
|
||||
internal DEMON_W32_Ext* demon_w32_ext(DEMON_Entity *entity);
|
||||
|
||||
|
||||
+31
-1
@@ -1852,6 +1852,7 @@ df_entity_change_parent(DF_StateDeltaHistory *hist, DF_Entity *entity, DF_Entity
|
||||
internal void
|
||||
df_entity_equip_txt_pt(DF_Entity *entity, TxtPt point)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->text_point = point;
|
||||
entity->flags |= DF_EntityFlag_HasTextPoint;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1860,6 +1861,7 @@ df_entity_equip_txt_pt(DF_Entity *entity, TxtPt point)
|
||||
internal void
|
||||
df_entity_equip_txt_pt_alt(DF_Entity *entity, TxtPt point)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->text_point_alt = point;
|
||||
entity->flags |= DF_EntityFlag_HasTextPointAlt;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1868,6 +1870,7 @@ df_entity_equip_txt_pt_alt(DF_Entity *entity, TxtPt point)
|
||||
internal void
|
||||
df_entity_equip_entity_handle(DF_Entity *entity, DF_Handle handle)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->entity_handle = handle;
|
||||
entity->flags |= DF_EntityFlag_HasEntityHandle;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1876,6 +1879,7 @@ df_entity_equip_entity_handle(DF_Entity *entity, DF_Handle handle)
|
||||
internal void
|
||||
df_entity_equip_b32(DF_Entity *entity, B32 b32)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->b32 = b32;
|
||||
entity->flags |= DF_EntityFlag_HasB32;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1884,6 +1888,7 @@ df_entity_equip_b32(DF_Entity *entity, B32 b32)
|
||||
internal void
|
||||
df_entity_equip_u64(DF_Entity *entity, U64 u64)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->u64 = u64;
|
||||
entity->flags |= DF_EntityFlag_HasU64;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1892,6 +1897,7 @@ df_entity_equip_u64(DF_Entity *entity, U64 u64)
|
||||
internal void
|
||||
df_entity_equip_rng1u64(DF_Entity *entity, Rng1U64 range)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->rng1u64 = range;
|
||||
entity->flags |= DF_EntityFlag_HasRng1U64;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1900,6 +1906,7 @@ df_entity_equip_rng1u64(DF_Entity *entity, Rng1U64 range)
|
||||
internal void
|
||||
df_entity_equip_color_rgba(DF_Entity *entity, Vec4F32 rgba)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
Vec3F32 rgb = v3f32(rgba.x, rgba.y, rgba.z);
|
||||
Vec3F32 hsv = hsv_from_rgb(rgb);
|
||||
Vec4F32 hsva = v4f32(hsv.x, hsv.y, hsv.z, rgba.w);
|
||||
@@ -1909,6 +1916,7 @@ df_entity_equip_color_rgba(DF_Entity *entity, Vec4F32 rgba)
|
||||
internal void
|
||||
df_entity_equip_color_hsva(DF_Entity *entity, Vec4F32 hsva)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->color_hsva = hsva;
|
||||
entity->flags |= DF_EntityFlag_HasColor;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1917,6 +1925,7 @@ df_entity_equip_color_hsva(DF_Entity *entity, Vec4F32 hsva)
|
||||
internal void
|
||||
df_entity_equip_death_timer(DF_Entity *entity, F32 seconds_til_death)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->flags |= DF_EntityFlag_DiesWithTime;
|
||||
entity->life_left = seconds_til_death;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1925,6 +1934,7 @@ df_entity_equip_death_timer(DF_Entity *entity, F32 seconds_til_death)
|
||||
internal void
|
||||
df_entity_equip_cfg_src(DF_Entity *entity, DF_CfgSrc cfg_src)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->cfg_src = cfg_src;
|
||||
df_entity_notify_mutation(entity);
|
||||
}
|
||||
@@ -1934,6 +1944,7 @@ df_entity_equip_cfg_src(DF_Entity *entity, DF_CfgSrc cfg_src)
|
||||
internal void
|
||||
df_entity_equip_ctrl_machine_id(DF_Entity *entity, CTRL_MachineID machine_id)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->ctrl_machine_id = machine_id;
|
||||
entity->flags |= DF_EntityFlag_HasCtrlMachineID;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1942,6 +1953,7 @@ df_entity_equip_ctrl_machine_id(DF_Entity *entity, CTRL_MachineID machine_id)
|
||||
internal void
|
||||
df_entity_equip_ctrl_handle(DF_Entity *entity, CTRL_Handle handle)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->ctrl_handle = handle;
|
||||
entity->flags |= DF_EntityFlag_HasCtrlHandle;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1950,6 +1962,7 @@ df_entity_equip_ctrl_handle(DF_Entity *entity, CTRL_Handle handle)
|
||||
internal void
|
||||
df_entity_equip_arch(DF_Entity *entity, Architecture arch)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->arch = arch;
|
||||
entity->flags |= DF_EntityFlag_HasArch;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1958,6 +1971,7 @@ df_entity_equip_arch(DF_Entity *entity, Architecture arch)
|
||||
internal void
|
||||
df_entity_equip_ctrl_id(DF_Entity *entity, U32 id)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->ctrl_id = id;
|
||||
entity->flags |= DF_EntityFlag_HasCtrlID;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1966,6 +1980,7 @@ df_entity_equip_ctrl_id(DF_Entity *entity, U32 id)
|
||||
internal void
|
||||
df_entity_equip_stack_base(DF_Entity *entity, U64 stack_base)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->stack_base = stack_base;
|
||||
entity->flags |= DF_EntityFlag_HasStackBase;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1974,6 +1989,7 @@ df_entity_equip_stack_base(DF_Entity *entity, U64 stack_base)
|
||||
internal void
|
||||
df_entity_equip_tls_root(DF_Entity *entity, U64 tls_root)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->tls_root = tls_root;
|
||||
entity->flags |= DF_EntityFlag_HasTLSRoot;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1982,6 +1998,7 @@ df_entity_equip_tls_root(DF_Entity *entity, U64 tls_root)
|
||||
internal void
|
||||
df_entity_equip_vaddr_rng(DF_Entity *entity, Rng1U64 range)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->vaddr_rng = range;
|
||||
entity->flags |= DF_EntityFlag_HasVAddrRng;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1990,6 +2007,7 @@ df_entity_equip_vaddr_rng(DF_Entity *entity, Rng1U64 range)
|
||||
internal void
|
||||
df_entity_equip_vaddr(DF_Entity *entity, U64 vaddr)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->vaddr = vaddr;
|
||||
entity->flags |= DF_EntityFlag_HasVAddr;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -2000,7 +2018,19 @@ df_entity_equip_vaddr(DF_Entity *entity, U64 vaddr)
|
||||
internal void
|
||||
df_entity_equip_name(DF_StateDeltaHistory *hist, DF_Entity *entity, String8 name)
|
||||
{
|
||||
entity->name = df_name_alloc(hist, name);
|
||||
df_require_entity_nonnil(entity, return);
|
||||
if(entity->name.size != 0)
|
||||
{
|
||||
df_name_release(hist, entity->name);
|
||||
}
|
||||
if(name.size != 0)
|
||||
{
|
||||
entity->name = df_name_alloc(hist, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
entity->name = str8_zero();
|
||||
}
|
||||
entity->name_generation += 1;
|
||||
df_entity_notify_mutation(entity);
|
||||
}
|
||||
|
||||
@@ -1355,6 +1355,7 @@ internal DF_CoreCmdKind df_core_cmd_kind_from_string(String8 string);
|
||||
|
||||
//- rjf: nil
|
||||
internal B32 df_entity_is_nil(DF_Entity *entity);
|
||||
#define df_require_entity_nonnil(entity, if_nil_stmts) do{if(df_entity_is_nil(entity)){if_nil_stmts;}}while(0)
|
||||
|
||||
//- rjf: handle <-> entity conversions
|
||||
internal U64 df_index_from_entity(DF_Entity *entity);
|
||||
|
||||
+10
-142
@@ -32,12 +32,6 @@
|
||||
// at all where the font ever was) The font path will now remain "stable"
|
||||
// in the sense that it won't rewrite it anymore. But you cannot use the
|
||||
// debugger because it's the wrong font path, so you get no text.
|
||||
// [x] When I click in the theme window on something like "Code (Meta)", it
|
||||
// opens up a tiny window, which only shows a tiny bit of what I imagine
|
||||
// is the entire color picker? It makes the picker unusable because more
|
||||
// of the UI for it is clipped and cannot be accessed.
|
||||
// [x] Clicking anywhere in the color picker that isn't a button closes the
|
||||
// color picker for some reason?
|
||||
// [ ] In a "hover watch" (where you hover over a variable and it shows a pop-
|
||||
// up watch window), if you expand an item near the bottom of the listing,
|
||||
// it will be clipped to the bottom of the listing instead of showing the
|
||||
@@ -45,8 +39,6 @@
|
||||
// actually visible)
|
||||
//
|
||||
// [ ] @bug @feature @cleanup general feedback from casey
|
||||
// [x] ** I don't like how panels get dimmer when they are not active, because
|
||||
// it makes them harder for me to read. Is there a way to turn this off?
|
||||
// [ ] ** I couldn't figure out how to really view threads in the debugger.
|
||||
// The only place I found a thread list was in "The Scheduler", but it
|
||||
// only lists threads by ID, which is hard to use. I can hover over them
|
||||
@@ -211,6 +203,8 @@
|
||||
// [ ] @feature search-in-all-files
|
||||
// [ ] @feature memory view mutation controls
|
||||
// [ ] @feature memory view user-made annotations
|
||||
//
|
||||
// [ ] @feature auto-scroll output window
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: 2024/2 tasks
|
||||
@@ -316,140 +310,14 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Completed Tasks
|
||||
//
|
||||
// [x] adding watches to source locations
|
||||
// [x] tab overflow buttons
|
||||
// [x] "working set" of targets, just used 'enabled' slot on target entities
|
||||
// [x] convert hover-eval ui to a frontend-wide global ui concept, so that we can have watch-hover trees from anywhere
|
||||
// [x] annotate code slices with relevant watches
|
||||
// [x] ability to duplicate targets easily
|
||||
// [x] ability to label targets separately from their EXE
|
||||
//
|
||||
// [x] txti layer needs lexing
|
||||
// [x] dbgi autoconversion layer needs to work reliably
|
||||
// [x] new dbgi system on frontend
|
||||
// [x] new bini system on frontend
|
||||
// [x] new dbgi system needs in-parallel typegraph builders
|
||||
// [x] eval is busted
|
||||
// [x] fail or debug non-text
|
||||
// [x] clean loading
|
||||
// [x] watch pins
|
||||
// [x] snapping should still work if a file is loading while the snap first occurs
|
||||
// [x] keyboard usage (set-next-statement, run-to-line, etc.)
|
||||
// [x] go-to-name (both file & symbol)
|
||||
//
|
||||
// [x] in-memory disassembly view
|
||||
// [x] visualize conversion tasks as they occur
|
||||
// [x] raddbg.exe self-sufficiency => built-in converter execution mode
|
||||
// [x] move path-mapping fallback from pending-entity into code view
|
||||
// [x] per-target entry point overrides
|
||||
// [x] logic on when double click on callstack entry goes to source or disassembly is very confusing,
|
||||
// because it seems it matters whether disassembly tab is in same panel as source, or is placed in
|
||||
// different panel in VS double clicking on stack stays in disassembly if disassembly tab is currently
|
||||
// active. Otherwise if source is active, it goes to source code (regardless if disasm is open/visible
|
||||
// or not)
|
||||
// [x] global variable (just regular C++ bool in the same file) does not show value when hovering over source
|
||||
// code, or when put into watch window.
|
||||
//
|
||||
// [x] debugger ui thread needs wakeup when a debug event is hit
|
||||
// [x] ctrl thread needs to re-resolve breakpoints as modules/threads come in during a run
|
||||
// [x] automatically pull in members from containing struct in member functions
|
||||
// when looking up locals
|
||||
// [x] iron out weird state machine bugs with hover-eval
|
||||
//
|
||||
// [x] thread-local eval
|
||||
// [x] tabs in source code render as squares
|
||||
//
|
||||
// [x] breakpoint stop-conditions
|
||||
// [x] first-chance exception hitting (d3d11 as an example offender)
|
||||
// [x] soft-halt refresh
|
||||
//
|
||||
// [x] conditional breakpoints cannot be submitted if they don't compile
|
||||
// need to (a) visualize and (b) equip the ctrl thread with a 'halt on
|
||||
// new debug info feature', which can be done repeatedly until something
|
||||
// compiles (?)
|
||||
//
|
||||
// [x] outputdebugstring logs
|
||||
//
|
||||
// [x] memory view
|
||||
//
|
||||
// [x] when application starts then the focus is on cmd.exe window of application not
|
||||
// debugger. This means if I press F11 to step into main(), the application cmd.exe will go fullscreen
|
||||
// hiding debugger (F11 key for ConEmu I use makes it go fullscreen)
|
||||
// [x] I'd prefer if ctrl+click on word would go to function definition, not double click
|
||||
// double clicking in source code should select word - which easy way to double click and ctrl+c to copy
|
||||
// it, pretty much standard thing in any text editorr/viewer and triple click for selecting whole line
|
||||
// [x] command line DF_CfgSrc -> explicitly visualize as temporary, provide UI
|
||||
// path to make permanent (in either user or profile?)
|
||||
//
|
||||
// [x] memory view annotations: bytes in a range of memory actually have a
|
||||
// *stack* of possible interpretations, for any particular low-level
|
||||
// representation (assuming 1 is fine for this case). a U32 member in
|
||||
// a local struct on the stack has 3 layers: U32 -> local -> stack.
|
||||
// each of these are useful information about that U32's range of bytes.
|
||||
// so, the memory view annotation system ought to be expanded to support-
|
||||
// ing stacks of annotations, and gracefully visualizing multiple nested
|
||||
// ones. after that is supported, we can use the type info to derive the
|
||||
// lowest level representation of some bytes. each stack can only have
|
||||
// one low-level type. that low-level type, then, can be used to directly
|
||||
// interpret the bytes - the others can be used to show the "conceptual
|
||||
// stack".
|
||||
//
|
||||
// [x] entity tree ui replacement (scheduler, modules, breakpoints, pins)
|
||||
// [x] theme menu
|
||||
// [x] complete transition to UI_ScrollPt coordinate space scrolling - eliminate
|
||||
// old scrolls & scroll regions
|
||||
// [x] settings menu
|
||||
// [x] exception filter settings & controls in ctrl layer
|
||||
//
|
||||
// [x] @polish @cleanup convert eval/watch to scroll list
|
||||
// [x] @feature memory view keyboard navigation
|
||||
// [x] @bug fix general ui line edit editing rules - conflicting with navigation, etc.
|
||||
// [x] @polish have expander space even if not used in watch window
|
||||
// [x] @bug references do not expand properly
|
||||
// [x] @bug panel deletion improper size bug
|
||||
// [x] @bug panel serialization/deserialization bug?
|
||||
// [x] unfinished char/string literal lexing
|
||||
//
|
||||
// [x] C++ problems in watch window: evaluating "this" shows no members. The type seems correct reference
|
||||
// to struct (which is local variable) does not show any members, like I have "tm_mem_zone_rt& z = ..."
|
||||
// in source code, and doing "z" produces no children, nor does "&z" but then at least it shows correct
|
||||
// address as value. if I ask for member of this when currently inside of member function (like "m_zone_stack")
|
||||
// it shows "unknown identifier m_zone_stack" but "this->m_zone_stack" works fine!
|
||||
// [x] if I write x'z in watch window and press enter, it only shows x and loses 'z - it does not show it, but when I edit cell then 'z comes back. It pretends I entered just x and shows x value.
|
||||
// [x] it seems the glyph advance for default font size is kind of wrong, as characters are a blitted a bit over top of each other
|
||||
//
|
||||
// [x] @bug deleting a watch tree while it is expanded causes cursor to go back to first row - cannot simply increment cursor. maybe keep in same spot, but rebuild viz blocks?
|
||||
// [x] @bug do not squish partially-cut-off view rule block uis
|
||||
// [x] @feature "solo step", or "solo mode" freeze-all-unselected-threads-on-step-commands
|
||||
// [x] @feature typing autocomplete lister
|
||||
// [x] @feature directional navigation of panel focus
|
||||
// [x] @cleanup @feature cache eviction in texture cache & hash store
|
||||
//
|
||||
//- 2023/12/7
|
||||
//
|
||||
// [x] @bug hash store cache eviction can only work if user never blindly tries to go from hash -> data, because
|
||||
// they must be able to retry... hmm...
|
||||
// [x] txt cell revamp. keyboard focus in both default & non w/ multiple options, helper lister, etc.
|
||||
// [x] `bitmap:(w:width, h:height, [fmt:fmt])` - interpret memory as raw bitmap data
|
||||
// [x] `geo:n[ topology stride]` - interpret memory as geometry
|
||||
// [x] cursor helper -> upgraded txt cell. classify inputs & show dropdowns (locals, globals, types, view rules, etc.)
|
||||
// [x] @bug page-up and page-down in src view, when near the end of file
|
||||
//
|
||||
//- 2023/12/8
|
||||
//
|
||||
// [x] @bug parse `unsigned int` correctly in eval parser
|
||||
// [x] @bug ., + operators should work on registers
|
||||
// [x] @bug straighten out register eval problems
|
||||
// [x] @cleanup finish ui_em transition
|
||||
//
|
||||
//- 2023/12/22
|
||||
//
|
||||
// [x] @bug set-bp-while-running seems to not resume after soft-halt, might be a soft-halt bug
|
||||
// [x] @bug weird view snapping in watch scrolling down
|
||||
//
|
||||
//- 2024/01/10
|
||||
//
|
||||
// [x] @feature allow `,count`, `,x`, `,b` style watch window expression extensions, which add to view rule, for VS-like behavior fastpaths
|
||||
// [x] ** I don't like how panels get dimmer when they are not active, because
|
||||
// it makes them harder for me to read. Is there a way to turn this off?
|
||||
// [x] When I click in the theme window on something like "Code (Meta)", it
|
||||
// opens up a tiny window, which only shows a tiny bit of what I imagine
|
||||
// is the entire color picker? It makes the picker unusable because more
|
||||
// of the UI for it is clipped and cannot be accessed.
|
||||
// [x] Clicking anywhere in the color picker that isn't a button closes the
|
||||
// color picker for some reason?
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes
|
||||
|
||||
Reference in New Issue
Block a user