Guard the FX-drain busy indicator against silent enum drift and cursor edge cases
Promote drainStateNow's switch to error-on-missing-case locally; set DWLP_MSGRESULT on WM_SETCURSOR; add an HTCLIENT guard; skip refreshBusyCursor during a live drag; mark the docked-dialog WM_SETCURSOR routing premise [verify - DAW].
This commit is contained in:
@@ -73,7 +73,8 @@ live in `shell/bank_ops`, a sibling directory, not here.
|
||||
REAPER's, and the SDK exposes nothing host-wide. A global `SetSystemCursor` or a message
|
||||
hook would reach further and is rejected — do not reintroduce either. `IDC_APPSTARTING`
|
||||
is Windows-only (SWELL ships no equivalent), so on mac/Linux the readout is the whole
|
||||
indicator.
|
||||
indicator. `[verify — DAW]` whether REAPER's docker even routes `WM_SETCURSOR` to the
|
||||
docked child dialog at all — the whole Windows half of this rests on that.
|
||||
- **No hit-test geometry in untestable shell code.** Even when reusing a WDL piece
|
||||
(e.g. a `vwnd` control for a long scroll list), layout/hit-test math stays in pure
|
||||
CTest-covered modules — do not import a WDL control's retained-mode object model
|
||||
|
||||
@@ -479,6 +479,19 @@ bool g_accelRegistered = false;
|
||||
|
||||
// The ONE map from the reclaimer's answer to the pure readout's vocabulary. Name-for-name
|
||||
// so a divergence reads as one; the decision itself is entirely fxReclaimActivity's.
|
||||
// This TU compiles straight into the reaper_reasampler MODULE, which carries none of
|
||||
// reasampler_pure_library's -Werror=switch/we4062 promotion (footer_bar's mirror switch
|
||||
// over FxDrainState has that; this one didn't) — a fourth FxReclaimActivity enumerator
|
||||
// would fall through to Idle here with no diagnostic at all. Promoted locally instead of
|
||||
// widening the target-wide flag, which would need auditing every switch already compiled
|
||||
// into this MODULE for an intentionally-partial case list.
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(error : 4062)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic error "-Wswitch"
|
||||
#endif
|
||||
FxDrainState drainStateNow() {
|
||||
switch (fxReclaimActivity()) {
|
||||
case FxReclaimActivity::Online: return FxDrainState::Online;
|
||||
@@ -487,6 +500,11 @@ FxDrainState drainStateNow() {
|
||||
}
|
||||
return FxDrainState::Idle;
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -100,7 +100,9 @@ void handleDropFiles(HDROP hDrop) {
|
||||
// cursor at all and the footer readout carries the state alone. The cursor reaches OUR
|
||||
// windows only; REAPER's arrange and mixer answer their own WM_SETCURSOR and the SDK
|
||||
// exposes nothing host-wide to ask for. A global SetSystemCursor or a message hook would
|
||||
// reach further and is deliberately not done.
|
||||
// reach further and is deliberately not done. [verify — DAW] whether REAPER's docker even
|
||||
// routes WM_SETCURSOR to the docked child dialog at all — the premise the whole Windows
|
||||
// half of this feature rests on.
|
||||
#ifdef _WIN32
|
||||
HCURSOR busyCursor() { return LoadCursor(nullptr, IDC_APPSTARTING); }
|
||||
#else
|
||||
@@ -118,12 +120,24 @@ bool busyCursorApplies() {
|
||||
WDL_DLGRET dlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
switch (msg) {
|
||||
case WM_SETCURSOR:
|
||||
// Non-client hits (resize border, etc.) are not ours to answer for; let the
|
||||
// default handling run. Harmless today (IDD_BANK_PANEL is a bare WS_CHILD
|
||||
// with no controls or border) but the guard is the conventional one.
|
||||
if (LOWORD(lParam) != HTCLIENT) return 0;
|
||||
// Claiming the message (non-zero) is what stops the default arrow from being
|
||||
// reapplied underneath us — on Win32 via DefDlgProc, on SWELL via the same
|
||||
// return test in swell-wnd-generic.cpp. Falling through leaves every other
|
||||
// cursor decision exactly where it was (panel_drag's per-move SetCursor).
|
||||
if (busyCursorApplies()) {
|
||||
SetCursor(busyCursor());
|
||||
// A DLGPROC conveys its result through DWLP_MSGRESULT, not the raw
|
||||
// return value; WM_SETCURSOR is not on the exception-message list that
|
||||
// skips this. Without it the bare `return 1` still suppresses
|
||||
// DefDlgProc's own cursor (SWELL checks the raw return too), but a
|
||||
// parent or sender reading the result would see "unhandled".
|
||||
#ifdef _WIN32
|
||||
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -240,7 +254,10 @@ void closePanel() {
|
||||
} // namespace
|
||||
|
||||
void refreshBusyCursor() {
|
||||
if (!g_panel.hwnd) return;
|
||||
// Nothing to refresh on mac/Linux (busyCursor() is always null there), and a live
|
||||
// drag owns the cursor already (panel_drag::applyDragCursor) — forcing IDC_ARROW
|
||||
// here on a drain edge mid-drag would stomp that cue until the next mouse move.
|
||||
if (!g_panel.hwnd || !busyCursor() || g_panel.dragArmed || g_panel.dragging) return;
|
||||
POINT pt{};
|
||||
GetCursorPos(&pt); // SWELL's returns void, so its result is deliberately not tested
|
||||
// Only when our own window is the one under the pointer: a menu or another window
|
||||
|
||||
Reference in New Issue
Block a user