From 1b59ed99d92a90d06e889843d2cfc34a4eeec897 Mon Sep 17 00:00:00 2001 From: Andreas Just Date: Tue, 28 Jul 2026 09:02:34 +0200 Subject: [PATCH] Fix BMenuField AllDetached callback dispatch Dispatch BMenuField::AllDetached to the matching Python override instead of AllAttached. Add a focused regression test that enters the C++ trampoline paths and verifies both detach callbacks. --- bindings/interface/MenuField.cpp | 2 +- tests/menuFieldDetachCallbacks.py | 63 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/menuFieldDetachCallbacks.py diff --git a/bindings/interface/MenuField.cpp b/bindings/interface/MenuField.cpp index b96f0d8..a6da51d 100644 --- a/bindings/interface/MenuField.cpp +++ b/bindings/interface/MenuField.cpp @@ -51,7 +51,7 @@ class PyBMenuField : public BMenuField{ PYBIND11_OVERLOAD(void, BMenuField, DetachedFromWindow); } void AllDetached() override { - PYBIND11_OVERLOAD(void, BMenuField, AllAttached); + PYBIND11_OVERLOAD(void, BMenuField, AllDetached); } void FrameMoved(BPoint where) override { PYBIND11_OVERLOAD(void, BMenuField, FrameMoved, where); diff --git a/tests/menuFieldDetachCallbacks.py b/tests/menuFieldDetachCallbacks.py new file mode 100644 index 0000000..2cd1d02 --- /dev/null +++ b/tests/menuFieldDetachCallbacks.py @@ -0,0 +1,63 @@ +from Be import BApplication, BMenu, BMenuField + + +EXPECTED_CALLBACKS = [ + "DetachedFromWindow", + "AllDetached", +] + + +class CallbackProbe(BMenuField): + def __init__(self): + self.menu = BMenu("callback-probe-menu") + + BMenuField.__init__( + self, + "callback-probe", + "Callback probe", + self.menu, + ) + + self.calls = [] + + def AllAttached(self): + self.calls.append("AllAttached") + + def DetachedFromWindow(self): + self.calls.append("DetachedFromWindow") + + def AllDetached(self): + self.calls.append("AllDetached") + + +def main(): + application = BApplication( + "application/x-vnd.haiku-pyapi-" + "menufield-detach-callback-test" + ) + + field = CallbackProbe() + + # Enter the C++ virtual trampolines through the bound + # base methods instead of calling Python overrides directly. + BMenuField.DetachedFromWindow(field) + BMenuField.AllDetached(field) + + if field.calls != EXPECTED_CALLBACKS: + raise SystemExit( + "FAIL: incorrect BMenuField detach callback " + f"dispatch: {field.calls!r}" + ) + + print("callbacks =", field.calls) + print( + "BMENUFIELD DETACH CALLBACK " + "REGRESSION TEST: PASS" + ) + + del field + del application + + +if __name__ == "__main__": + main()