diff --git a/inc/cvc/ariadne/widget.h b/inc/cvc/ariadne/widget.h index 789a90dac..79a9f951d 100644 --- a/inc/cvc/ariadne/widget.h +++ b/inc/cvc/ariadne/widget.h @@ -80,7 +80,9 @@ struct Track { }; enum class LayoutKind { Vertical, Horizontal, Grid }; -enum class BorderShow { None, Inner, Outer, All }; +// `Off`, not `None`: X11 defines `None` as a macro, which would break this +// declaration in any translation unit that includes an X11 header first. +enum class BorderShow { Off, Inner, Outer, All }; // A container's layout (§3.0.2 / §3.0.3b). `col_widths` sizes the tracks of a // Grid/Horizontal layout; `resizable` lets the user drag the column seams (native @@ -90,12 +92,12 @@ struct Layout { std::vector col_widths; // Grid/Horizontal column tracks std::vector row_heights; // Grid row tracks (§3.0.3b increment 2) bool resizable = false; - BorderShow borders = BorderShow::None; + BorderShow borders = BorderShow::Off; bool has_border_color = false; float border_color[4] = {0.3f, 0.3f, 0.35f, 1.0f}; bool is_set() const { return kind != LayoutKind::Vertical || !col_widths.empty() || !row_heights.empty() || - resizable || borders != BorderShow::None; + resizable || borders != BorderShow::Off; } // A resizable grid with sized rows is realized as a vertical split-pane stack // with draggable seams (§3.0.3b: "rows are a manual splitter"); anything else diff --git a/inc/cvc/gl/nodes.h b/inc/cvc/gl/nodes.h index 362fa0d1a..e7478b415 100644 --- a/inc/cvc/gl/nodes.h +++ b/inc/cvc/gl/nodes.h @@ -167,10 +167,11 @@ class VisibilityMask : public Node { std::uint32_t m_mask = 0xFFFFFFFFu; }; -// Inventor's SoSwitch: traverse one child, or none (-1), or all (-3). +// Inventor's SoSwitch: traverse one child, or none (Off, -1), or all (All, -3). `Off`, not +// `None`: X11 defines `None` as a macro. class Switch : public Group { public: - static constexpr int None = -1; + static constexpr int Off = -1; static constexpr int All = -3; using Group::Group; diff --git a/src/cvc/ariadne/ftxui_backend.cpp b/src/cvc/ariadne/ftxui_backend.cpp index e17bc11b6..dadda4272 100644 --- a/src/cvc/ariadne/ftxui_backend.cpp +++ b/src/cvc/ariadne/ftxui_backend.cpp @@ -156,7 +156,7 @@ void FtxuiBackend::end_grid() { fx::Element box = cells.empty() ? fx::text("") : (vertical ? fx::vbox(std::move(cells)) : fx::hbox(std::move(cells))); - if (layout.borders != BorderShow::None) + if (layout.borders != BorderShow::Off) box = fx::border(box); m_->add(box); } diff --git a/src/cvc/tests/CMakeLists.txt b/src/cvc/tests/CMakeLists.txt index ac169fefe..f23c5d3d1 100644 --- a/src/cvc/tests/CMakeLists.txt +++ b/src/cvc/tests/CMakeLists.txt @@ -8,6 +8,7 @@ add_executable(text_test text_test.cpp) add_executable(ariadne_loader_test ariadne_loader_test.cpp) add_executable(ariadne_runtime_test ariadne_runtime_test.cpp) add_executable(ariadne_bind_test ariadne_bind_test.cpp) +add_executable(x11_macro_headers_test x11_macro_headers_test.cpp) add_executable(net_http_client_test net_http_client_test.cpp) add_executable(uri_http_cache_test uri_http_cache_test.cpp) add_executable(state_test state_test.cpp) @@ -176,6 +177,7 @@ set(TEST_TARGETS ariadne_loader_test ariadne_runtime_test ariadne_bind_test + x11_macro_headers_test net_http_client_test uri_http_cache_test state_test @@ -442,6 +444,13 @@ target_link_libraries(ariadne_bind_test GTest::gtest_main ) +target_link_libraries(x11_macro_headers_test + PRIVATE + cvc + GTest::gtest + GTest::gtest_main +) + target_link_libraries(state_test PRIVATE cvc @@ -1647,6 +1656,7 @@ cvc_discover_tests(text_test) cvc_discover_tests(ariadne_loader_test) cvc_discover_tests(ariadne_runtime_test) cvc_discover_tests(ariadne_bind_test) +cvc_discover_tests(x11_macro_headers_test) cvc_discover_tests(net_http_client_test) cvc_discover_tests(uri_http_cache_test) cvc_discover_tests(state_test) diff --git a/src/cvc/tests/x11_macro_headers_test.cpp b/src/cvc/tests/x11_macro_headers_test.cpp new file mode 100644 index 000000000..539593e90 --- /dev/null +++ b/src/cvc/tests/x11_macro_headers_test.cpp @@ -0,0 +1,23 @@ +// X11's defines object-like macros named like ordinary identifiers -- notably +// `None` (0L) -- so a public header that declares anything called `None` stops compiling +// in a translation unit that includes an X11 header first. This TU includes +// FIRST (where X11 is available) and then the ariadne widget header, whose BorderShow enum +// used to have a `None` enumerator. Platforms without X11 build it without the macro. +// +// gtest comes BEFORE X11: googletest itself declares `struct None` (gtest-type-util.h), so +// the macro would break gtest, not just libcvc. This test is about libcvc's headers. +#include + +#if __has_include() +#include +#endif + +#include + +TEST(X11MacroHeaders, BorderShowDefaultsToOff) { +#ifdef None + static_assert(None == 0L, "X11's None macro is in effect for this translation unit"); +#endif + cvc::ariadne::Layout layout; + EXPECT_EQ(layout.borders, cvc::ariadne::BorderShow::Off); +} diff --git a/src/cvcGL/CMakeLists.txt b/src/cvcGL/CMakeLists.txt index af1add2be..0a87d58b4 100644 --- a/src/cvcGL/CMakeLists.txt +++ b/src/cvcGL/CMakeLists.txt @@ -409,6 +409,12 @@ add_executable(cvcgl_traversal test/cvcgl_traversal.cpp) target_link_libraries(cvcgl_traversal PRIVATE cvcGL) add_test(NAME cvcgl_traversal COMMAND cvcgl_traversal) +# X11 macros (None, Success, ...) vs the cvc/gl headers, in the order VTK's X11 +# render window produces (VTK first, then X11, then cvc/gl). Compile-time check; headless. +add_executable(cvcgl_x11_macros test/cvcgl_x11_macros.cpp) +target_link_libraries(cvcgl_x11_macros PRIVATE cvcGL) +add_test(NAME cvcgl_x11_macros COMMAND cvcgl_x11_macros) + # The world grid must enclose the geometry actually in the scene. It was sized # only from GraphicsNode::transformChanged, so it tracked geometry that MOVED # and ignored geometry that was merely ADDED — every static scene drew a @@ -899,7 +905,7 @@ endif() # locked unless it is listed here as headless. get_property(_cvcgl_gl_tests DIRECTORY PROPERTY TESTS) list(REMOVE_ITEM _cvcgl_gl_tests - cvcgl_smoke cvcgl_metadata_mirror cvcgl_volume_range cvcgl_traversal + cvcgl_smoke cvcgl_metadata_mirror cvcgl_volume_range cvcgl_traversal cvcgl_x11_macros cvcgl_grid_bounds cvcgl_bounds_walk cvcgl_scene_chrome cvcgl_remove cvcgl_teardown cvcgl_light_state_thread cvcgl_pose_echo cvcgl_node_outlives_scene cvcgl_texture cvcgl_texture_zerocopy diff --git a/src/cvcGL/nodes.cpp b/src/cvcGL/nodes.cpp index ff25ec9b0..c14df5b93 100644 --- a/src/cvcGL/nodes.cpp +++ b/src/cvcGL/nodes.cpp @@ -86,7 +86,7 @@ void Separator::traverse(Action &action) { // ── Switch ───────────────────────────────────────────────────────────────── void Switch::traverse(Action &action) { - if (m_which == None) + if (m_which == Off) return; if (m_which == All) { traverseChildren(action); diff --git a/src/cvcGL/test/cvcgl_traversal.cpp b/src/cvcGL/test/cvcgl_traversal.cpp index 5c915cae7..8afc29fa5 100644 --- a/src/cvcGL/test/cvcgl_traversal.cpp +++ b/src/cvcGL/test/cvcgl_traversal.cpp @@ -197,7 +197,7 @@ static void test_switch() { return a.visitedShapes(); }; CHECK(count(Switch::All) == 2); - CHECK(count(Switch::None) == 0); + CHECK(count(Switch::Off) == 0); CHECK(count(0) == 1); CHECK(count(1) == 1); CHECK(count(99) == 0); // out of range is not a crash diff --git a/src/cvcGL/test/cvcgl_x11_macros.cpp b/src/cvcGL/test/cvcgl_x11_macros.cpp new file mode 100644 index 000000000..86a441e23 --- /dev/null +++ b/src/cvcGL/test/cvcgl_x11_macros.cpp @@ -0,0 +1,24 @@ +// cvcGL apps on Linux pull X11 in through VTK's X11 render window, which includes +// after VTK's own headers -- so cvc/gl headers can be parsed with X11's +// object-like macros (None, Success, ...) already defined. Mirror that order: VTK headers +// first (X11 before them breaks VTK's own vtksys/Status.hxx on `Success`), then X11, then +// the cvc/gl header. Switch's "no child" constant used to be named `None`. +#include +#include + +#if __has_include() +#include +#endif + +#include +#include + +int main() { +#ifdef None + static_assert(None == 0L, "X11's None macro is in effect for this translation unit"); +#endif + static_assert(cvc::gl::Switch::Off == -1, "Switch::Off traverses no child"); + static_assert(cvc::gl::Switch::All == -3, "Switch::All traverses every child"); + std::puts("cvcgl_x11_macros: ok"); + return 0; +}