Wuss octopus - #8
Merged
Merged
Conversation
…tent Enlarging a window's viewport (or growing it past the document extent) could scroll content that no longer exists into view. wuss_window_resize now re-clamps window->scroll via wuss__scroll_clamp after recomputing the visible box; if the offset moved, the whole content box (and the scrollbar well) is invalidated, since the grown/shrunk-sliver logic assumes an unchanged interior. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…fill
Introduces wuss_backdrop_t ({ colour, pattern, pattern_bg }), replacing the
bare wuss_colour_t for wuss_config_t::backdrop and for the bg parameter of
wuss_window_create(), wuss_window_create_placed() and
wuss_window_set_background(). A non-SOLID pattern is tiled with
screen_fill_pattern(): the desktop phased to the screen origin, a window's
content phased to its scroll origin so the fill stays locked to the content.
wuss__validate_backdrop() and wuss__fill_backdrop() are shared out to a new
backdrop.c. wuss_BACKDROP_COLOUR() / wuss_BACKDROP_PATTERN() build the struct
as a compound literal; the flat-colour case is wuss_BACKDROP_COLOUR(old_value).
The icons test task now uses a CROSSHATCH pattern backdrop instead of drawing
its own grid. A transparent LABEL icon over a patterned window backdrop blends
its glyphs against the pattern's background colour, not the foreground.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The sausage could butt right up against the arrow buttons at the scroll extremes. Scale and position it over the well minus a cosmetic end gap at each end, dropped when the well is too short to spare it. drag_sausage maps pointer movement over the same track so dragging stays 1:1. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…path wuss_create no longer includes framebuf/palettes.h or assumes a palette length. A NULL palette now falls back to a built-in two-entry black/white palette instead of define_pico8_palette, and the furniture default colours use the generic bg=0, fg=(npalette>1)?1:0 scheme unconditionally. The two alloc/copy branches are merged. wuss-test: set_background test indexed palette_PICO8_ORANGE against the default palette; use index 1, which is valid for the two-entry fallback. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds the RISC OS desktop (Wimp) 16-colour palette in native Wimp index order, with palette_WIMP16_* names and a palette_WIMP16__LENGTH. The interactive wuss test picks it up via WUSS_PALETTE=wimp16; the default stays PICO-8. Its desktop backdrop now uses a DOTS pattern over light grey instead of a flat fill. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The title/close and resize/scrollbar-well drag-start branches were gated only on MOUSE_DOWN, so a middle-button (MENU) press on furniture would start a window move or resize drag. Gate them on SELECT|ADJUST as the other furniture branches already are. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add a subsection under Scrolling with an ASCII nested-box diagram of screen origin / visible / content box / clip piece / scroll / doc extent, the fields each maps to, and the screen<->document conversion formulae. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
text_redraw did line-breaking and drawing in one loop mixed with screen and scroll state. Pull the wrapping into a pure text_layout() that returns an array of spans, and the drawing into text_render(); text_redraw is now just glue. No behaviour change. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New text/bmtext module: bmtext_layout() breaks a string into lines that fit a pixel width in a bmfont (via bmfont_measure, so proportional fonts wrap correctly), bmtext_draw() draws pre-laid-out lines stacked. The wuss text-task test now calls these instead of carrying its own copy. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The SDL interactive driver (spawn_* callbacks, launcher table and the main loop) lived inside libraries/wuss/test/wuss-test.c, reachable only as a tail call from the wuss unit test when built with USE_SDL. That dragged SDL3 linkage, a USE_SDL compile-def and all the tasks/*.c modules onto DPTLibTest. Move it to apps/wuss/main.c as its own `wuss` executable, gated by a new BUILD_APPS option (which requires WUSS_FURNITURE and WUSS_ICONS and pulls SDL3). wuss-test.c is now SDL-free and holds only the unit test, which DPTLibTest still runs. The old wuss_interactive_test is renamed run_wuss. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
curve: left-shifting negative point deltas by FIX16_SHIFT is undefined; multiply by FIX16_ONE instead (same codegen). bmfont: extract_advance_widths shifted currbits by bitsperchar without the width==32 guard that the glyph decoder already has, giving a shift-by-32 when charwidth is 16. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The no-SDL path looped 1000 frames of full curve calculation and software line rasterisation on an 800x600 buffer; under ASan/UBSan that ran ~5.5s. 100 frames covers every draw path and finishes in ~0.5s. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
packer_release only absorbed a freed slot when it sat wholly inside one existing free area. A window footprint straddles several free fragments, so it was appended as an overlapping box and remove_area never coalesced. Over repeated open/close cycles the free list decayed into slivers and large placements stopped fitting despite the pixels being free. Track every box carved out by packer_place_at / packer_place_by in a placed[] list. packer_release now drops the matching placed box and rebuilds the free list from the margins minus the still-live boxes -- exact reclaim, no coalescing heuristics. packer_clear resets the placed list since its swathe has no matching release. O(nplaced^2) per release; nplaced is a handful in practice. Adds packer test4: four rounds of placing six mixed-size boxes and releasing all of them, asserting the free list collapses back to the whole page each round and a full-page box then fits.
New wuss_ICON_TYPE_FRAME draws a one-pixel grouping box with the top edge broken around an optional caption, RISC OS group-box style. Not interactive: clicks fall through as wuss_EVENT_MOUSE (hit-test already matches BUTTON only, so no change there). wuss_ICON_TYPE_LABEL gains wuss_ICON_FLAGS_JUSTIFY_RIGHT / _CENTRE; the label draw path now measures the text and positions it left (default), right or centred within the bbox. Frame caption geometry is WUSS_FRAME_CAPTION_INSET / _PAD in impl.h. The icons test task shows a frame with a right- and a centre-justified label. First stage of the staged wuss UI toolkit plan. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A wuss_ICON_TYPE_BUTTON created with the new wuss_ICON_FLAGS_DEFAULT flag
draws as a flat accent-filled rectangle inside a one-pixel accent-text
border, standing out from the bevelled ordinary buttons around it (RISC
OS's default action button).
The accent colours come from the new wuss_config_t::accent {bg, fg} pair,
cached on struct wuss beside the bevel shades and validated the same way;
both default to the titlebar colours when config is NULL.
apps/wuss/main.c sets config.accent (its config is assigned field by
field, so an unset sub-struct would be indeterminate). The icons test
task marks its 'Press me' button as the default.
Second stage of the staged wuss UI toolkit plan.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New icon types wuss_ICON_TYPE_RADIO and wuss_ICON_TYPE_OPTION with latched selected state on the icon (not the task). Radios take an int group; selecting one clears every other selected radio on the same window sharing that non-zero group. Options toggle independently. New public API wuss_icon_get_selected / wuss_icon_set_selected; the latter respects group exclusivity but delivers no task event. A user click latches the new state on MOUSE_UP before wuss_EVENT_ICON fires, so the handler sees it; ADJUST-click toggles a radio. Glyphs are primitive-drawn (square ring + centre fill for radio, box + tick for option), font-height, at the left of the bbox with the label to the right. hit-test.c makes both types interactive. The icons test task grows a three-radio group, a standalone option and a label echoing the last change. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New icon type wuss_ICON_TYPE_BITMAP draws a caller-owned const bitmap_t * at the top-left of the bbox, alpha-blended and clipped to the box, no scaling. The bitmap is borrowed, not copied, and must outlive the icon (unlike text). New flag wuss_ICON_FLAGS_INTERACTIVE makes a bitmap icon hit-testable and raise wuss_EVENT_ICON like a button; without it the icon is pure decoration and clicks fall through as wuss_EVENT_MOUSE. Other icon types ignore the flag. draw.c narrows a stack copy of the screen's clip to the icon box before the blit. create.c rejects a bitmap spec with no bitmap. hit-test.c treats an interactive bitmap like the other clickable types. The icons test task loads resources/wuss/9tile.png and shows one decorative and one interactive bitmap icon; icons_create gains a resources argument. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New icon type wuss_ICON_TYPE_MENU_ENTRY: a full-width row drawn in fg over the window background, inverting to the accent colours while the pointer is over it. Reuses the selected flag for a left-edge tick; wuss_ICON_FLAGS_SUBMENU adds a right-edge arrow; wuss_ICON_FLAGS_SEPARATOR draws a horizontal rule instead of text and makes the row inert. Disabled entries never highlight. Hover tracking: struct wuss gains hover_icon, struct wuss_icon gains hovered. wuss__icon_set_hover swaps the flag between the old and new hovered icon and invalidates whichever changed. mouse-move.c calls it with the icon under the pointer, or NULL at every early-out (no window, over furniture, no task). Cleared on window close and icon delete. This is the hook the menu helper (WUSS_MENUS) will use for submenu-on-hover. The icons test task grows a four-row menu strip: plain, ticked, submenu, separator. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New compile-time option WUSS_MENUS (implies WUSS_ICONS) guarding a thin helper for RISC OS-style pop-up menus: a menu is a borderless window of wuss_ICON_TYPE_MENU_ENTRY icons, but wuss owns layout, on-screen placement, submenu chaining on hover and whole-chain dismissal. - include/wuss/menu.h: caller-owned immutable wuss_menu_t / wuss_menu_item_t data model; wuss_menu_open / wuss_menu_close / wuss_menu_is_open; wuss_menu_select_fn_t leaf-selection callback (SELECT closes the chain, ADJUST keeps it open). - libraries/wuss/menu/menu.c + libraries/wuss/menu.h: struct wuss__menu chain nodes (window + per-item icon handles + parent/child links). Measures the widest label, sizes and places a borderless window, maps item flags (DASHED/DISABLED/submenu/TICKED) onto icon flags, and runs the chain from an internal window delegate. - struct wuss gains menu_chain; mouse-click.c dismisses the chain on a MOUSE_DOWN outside every menu window; create.c inits it, destroy.c tears down any still-open chain. - CMakeLists.txt: WUSS_MENUS option, WUSS_MENU_SOURCES, PUBLIC_HEADERS. - apps/wuss/main.c: a "Menu" launcher entry opening a static demo tree. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Port PrivateEye's menu_create_from_desc token machine to build a heap
wuss_menu_t tree from a compact string:
- ',' separates items, '|' marks a dashed separator above
- '{ ... }' after an item is its submenu (first token is a title, discarded
for source compatibility with the Wimp descriptors)
- per-token '!' ticks, '~' shades, '>' pulls a const wuss_menu_t * submenu
from the varargs
- '%s' substitutes the next const char * vararg
'>' submenus are deep-copied so the whole result tree is owned uniformly and
freed by one wuss_menu_destroy. getname() trims trailing whitespace so
"Foo { " yields "Foo".
Also fix a Stage 6a crash: wuss__menu_spawn passed an empty label to
bmfont_measure (asserts textlen > 0) for a separator row; skip empty labels
when measuring and when drawing a MENU_ENTRY.
Guarded by WUSS_MENUS. wuss-test.c gains a parser self-check.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- menus default to a white (nearest-palette) backdrop - menus keep their titlebar furniture (drop wuss_WINDOW_NO_TITLEBAR); submenu positioning switched to content bounds so rows still align under the titlebar - add screen_draw_dashed_line (Bresenham + dash-period counter) and use it for menu separator rows; covered by a new screen test - menus open under the pointer: cache wuss->pointer in both mouse entry points, expose wuss_get_pointer, shift the root menu content top-left so the pointer lands over row 0 - menu-entry highlight now swaps the row's own resolved fg/bg instead of pulling the window-manager accent pair - drop stray debug printfs left in wuss-test.c Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The menu helper created its window at a packer slot then wuss_window_move'd it
to the pointer. wuss_window_move blits the window's already-rendered pixels to
the new spot, but a just-created window has none, so the titlebar landed
unpainted (a thin sliver was all that got invalidated).
- wuss__menu_spawn now creates the window at the target point directly with
wuss_window_create; no post-move
- add wuss_menu_t.title (first field) so the titlebar has a caption;
menu.c passes it, wuss_menu_create_from_desc leaves it NULL (still discards
the descriptor's { } title token), menu_deep_copy carries it, wuss_menu_destroy
frees it
- demo menus in apps/wuss titled; test literals updated for the new field
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
wuss_MENU_ITEM_DASHED / wuss_ICON_FLAGS_SEPARATOR previously meant "this entry IS the rule, its text is ignored". Flip it: a dashed entry now draws a dashed rule along its own top edge and then renders its label as normal, remaining hit-testable. An entry that carries the flag with no text is still a bare, inert rule. - create-from-desc: '|' sets DASHED on the following item itself, no synthetic rule row - menu.c: DASHED entries are no longer skipped by the pick guard - icon/hit-test: a SEPARATOR MENU_ENTRY is inert only when its text is empty - icon/draw: SEPARATOR draws the rule in the row's ink (visible when inverted) then falls through to tick/arrow/text - apps/wuss: drop the standalone rule row, mark Quit DASHED - also lands the wuss_menu_create_from_desc SDL launcher test and the root-title-from-first-token descriptor change Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add wuss_alloc_t (malloc/realloc/free hooks) and a wuss_alloc stdlib default. wuss_create takes a const wuss_alloc_t * (NULL selects wuss_alloc); the hooks are copied into struct wuss and reached through wuss__malloc/ wuss__realloc/wuss__free helpers in impl.h. Every heap block a wuss_t owns -- the instance, its palette, windows, icons, icon-pointer arrays and menu nodes -- now allocates through them. menu/create-from-desc.c is left on stdlib: its API takes no wuss_t. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Each switch case in wuss__icon_draw now delegates to a static wuss__icon_draw_* helper taking a shared icon_draw_ctx_t. The explicit-bg / window-backdrop / fallback blend-ground ladder that was repeated across the label, frame, radio/option and menu-entry cases is factored into icon_blend_ground. Behaviour is unchanged; the pattern case still receives the content box and scroll so its tile origin does not move. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The first-line header comment of every first-party .c/.h file now
carries its path relative to libraries/, include/ or apps/ instead of a
bare basename:
/* draw.c -- wuss - draw a work-area icon */
-> /* wuss/icon/draw.c -- draw a work-area icon */
The description after '--' is preserved; a redundant "<module> - " (or
"<module> test - ") prefix is dropped, except where that prefix plus the
module's own tagline is the whole description (kept as
"wuss - minimal window manager"). Files with no header, or only a
stale/bare filename, gain a path-only header. Vendored trees
(libraries/fortify, include/fortify) are untouched.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
wuss_window_set_scroll clipped the blit source against occluding windows but not the destination. A source slice below a smaller window on top, slid by the scroll delta, could land its destination behind that window; screen_copy_rect only clips to the content box, so it painted the scrolling window's content over the occluder and marked the area 'copied', excluding it from the repaint set so nothing restored it. Clip each blit destination against the occluders too and copy only the surviving sub-pieces, each with its own matching source offset. Adds a wuss test that paints two windows in distinct colours and reads back the framebuffer behind the occluder after a scroll. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…r's source When a small window floats mid-content over a larger scrollable window with a gap all round it, wuss__clip_to_visible carves the scrolled window's blittable content into bands around the occluder. A vertical scroll shifts every band by the same delta, and one band's shifted destination can land on another band's still-unread source. Blitting the bands in clip-emit order then double-shifts the content near the occluder's bottom edge. Collect all blit sub-pieces first, order them with wuss__order_pieces (the same topological sort wuss_window_move already used, now promoted from static in move.c to a shared internal in invalidate.c), and fall back to a full content invalidate on a cycle or piece-budget overflow. Adds a regression test: paint_handle now paints one-pixel rows whose blue channel encodes document Y, so the test can read the gap column beside the occluder back and assert each row slid by exactly the scroll delta. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Move the trailing /**< member comments in wuss_icon_type, wuss_icon_flags and wuss_icon_spec to /** blocks preceding each member. Also lower the wrap tooling's default width from 80 to 77 columns (wrap_doxygen.py and wrap_protos.py, plus their tests), rewrap every public header's Doxygen blocks to the new limit, and run wrap_protos.py across the tree to rewrap prototypes that now exceed it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The interactive wuss app opened a persistent Launcher window full of button icons, one per task. Drop it and launcher.c/.h entirely; a MENU-button click on the bare backdrop now opens a "Tasks" pop-up menu at the pointer via wuss_menu_open. g_task_items and a parallel g_task_spawn table drive it: picking item i calls g_task_spawn[i]. The two menu-helper demo entries sit below a dashed rule. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t_info Drops the fw local and its NOT_USED in wuss__menu_spawn. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Also space out the menu-table declarations one blank line apart. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The MOUSE_UP handler in wuss__menu_handle called the on_select callback while the menu node was still live, then continued to touch `self`. A callback that opens a new menu (via wuss_menu_open) frees the whole chain, including the node the dispatcher was running inside, causing a heap-use-after-free on return. Capture the callback, menu and ctx up front, tear the chain down first, then invoke the callback. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The six mutable file-scope statics that carry per-run context to the argument-less spawn callbacks are now fields of one anonymous struct g rather than loose g_wuss/g_palette/... globals. The const menu tables are left as they were. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…lable wuss__scroll_step now zeroes the delta on any axis whose window carries wuss_WINDOW_NO_HSCROLL / wuss_WINDOW_NO_VSCROLL. Pop-up menus set both and have no scrollbar to clamp against; their geometry (submenu placement, hit testing) assumes scroll == 0, so a wheel turn over a menu taller than the screen was corrupting the display. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
When a menu's full height exceeds what the screen leaves for it, cap the window's content height at that maximum and clear wuss_WINDOW_NO_VSCROLL so the window gets a real vertical scrollbar. The document extent passed to wuss_window_create stays the full menu height, so the existing scroll-aware icon draw and hit test move the rows under the viewport with no further work. Submenu placement now subtracts the parent menu's scroll offset when siting a child, and the on-screen nudge accounts for the scrollbar carve on the right edge. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The icons task baked a swatch-per-fill-pattern grid into its icon-spec array alongside its labels, buttons, radios and menu entries. Move that grid into a standalone "swatches" task and drop it from icons, so each demonstrates one thing. Adds it to the interactive demo's task menu and CMake source list. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Find the system-palette entry closest to a given RGB by squared Euclidean distance, ties to the lower index. Also renames the config's furniture-colour struct wuss_palette_t -> wuss_furniture_palette_t and narrows wuss_colour_t to unsigned char. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Menu item and rule specs hardcoded fg = palette index 0, which is only black in the default palette; a custom palette with white at index 0 gave white-on-white menu text. Use a new palettecache.black (nearest to RGB 0,0,0), alongside the existing white cache now moved into the same sub-struct. The white-cache loop in create.c is replaced by wuss_nearest_colour, which also fixes its swapped R/B channel read. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Three copies of the ball -> window-local invalidation box calc collapse into ball_local_box(); the two click sites pass a degenerate box, idle passes the swept MIN/MAX range. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The SDL test tasks took palette/npalette just to index a PICO8 lookup for two or three fixed colours; use colour_rgb() literals directly and simplify each *_create signature, with apps/wuss/main.c updated to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… setup run_wuss had two near-identical wuss_config_t fill blocks (PICO-8 vs wimp16) differing only in colour constants; fold them into a 2-row index table so the field wiring exists once. Also hoist the wuss_nearest_colour calls in the icons and swatches tasks above their window-create call and drop stray trailing whitespace. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…draws A fast wheel spin delivers several wuss_scroll calls before wuss_redraw_dirty runs. wuss_window_set_scroll's incremental blit is a framebuffer memmove, so a second scroll in the same frame would slide the strip the first scroll exposed -- still marked dirty, not yet repainted -- into the window interior, smearing stale content there permanently. Before the blit, collect the pending dirty rects that overlap the content box (sampled ahead of the furniture invalidate so its unrelated rects are excluded) and subtract them from every clean blit-source piece. The stale areas are no longer blitted; they fall through to the normal content-minus-copied repaint instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
wuss_set_palette copies a new palette over the old, refreshes the cached nearest-black/white indices, broadcasts a new wuss_EVENT_PALETTE to every window's task so they can recache wuss_nearest_colour selections, then invalidates the whole screen. Length must match the palette given to wuss_create. The swatches test task rebuilds its swatch icons on wuss_EVENT_PALETTE; the interactive wuss driver cycles PICO-8 <-> Wimp16 on F4, pushing the new palette into the framebuffer bitmap and then into wuss. Also add bitmap_set_palette, which reuses an already-allocated palette buffer, and refactor bitmap_init to build its palette through it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Alphabetise the 14 spawn tasks in g_task_items and reorder g_task_spawn to match. The trailing Menu, Menu (desc) and Quit Wuss entries stay pinned below the separator. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A menu is opened from a task's MOUSE_DOWN handler. The matching MOUSE_UP was landing on the fresh menu's row 0 and immediately picking it. Add a wuss_t.menu_eat_up flag set by wuss_menu_open and consumed by the next MOUSE_UP in wuss_mouse_click; any fresh MOUSE_DOWN clears it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Menus (wuss/menu.h + descriptor parser), mid-session palette swap, wuss_nearest_colour, pluggable allocator, bmtext, the extended icon-type set, screen polyline/outline/dashed-line primitives, 8x8 Bayer dither, the Wimp16 palette, plus the draw/fill primitive renames and assorted scroll-redraw fixes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A wuss_menu_item_t may now carry a caller-owned wuss_window_t in a new `window` field (mutually exclusive with `submenu`). Hovering the row shows that window where a sub-menu would open, using the same anchor maths; moving off the row, a click outside, a leaf SELECT elsewhere, or wuss_destroy all hide it again rather than close it, so the same handle is reused next time. Backing this is a new core wuss_WINDOW_HIDDEN flag plus wuss_window_set_hidden(): a hidden window keeps its z-order slot but is not drawn, not hit-tested and occludes nothing; wuss_window_move still works on it so it can be parked and re-shown in position. Honoured in window/at.c, redraw.c, window/invalidate.c (occlusion), window/create.c (born hidden) and window/move.c (translate only, no blit). create-from-desc.c now initialises the new `window` field -- build_emit grows its array uninitialised, so a desc-built menu was dereferencing garbage on hover. apps/wuss adds a "Details" row wired to a lazily-created hidden window to exercise it interactively. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Covers db8d9af: wuss_menu_item_t::window, wuss_window_set_hidden() and the wuss_WINDOW_HIDDEN create flag.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
We have menus: