Add WIN_WORKSPACE(w) macro to window.h that returns frame->workspace
when the window has a frame (X11 path) or wwin->workspace when it does
not (Wayland path, set in Phase 67).
Replace all unsafe frame->workspace reads with WIN_WORKSPACE() in:
- window.c: wWindowObscuresWindow (workspace comparison + geometry),
wWindowFocusPrev/Next (same-workspace filter),
wWindowSaveState (state serialization)
- session.c: session save (workspace name lookup)
- switchmenu.c: all five switch-menu workspace comparisons/lookups
Also guard wWindowObscuresWindow's frame->core width/height reads with
a ternary that falls back to client.{width,height} for frameless windows.
This eliminates the last class of NULL frame->workspace dereferences
reachable from workspace-switch, focus-cycle, session-save, and
switch-menu code paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>