| 866 | } |
| 867 | |
| 868 | SpectrumWidget::SpectrumWidget(QWidget* parent) |
| 869 | : SPECTRUM_BASE_CLASS(parent) |
| 870 | { |
| 871 | // Container declaration — every token lookup made by this widget or |
| 872 | // any of its children (without their own declaration) resolves |
| 873 | // through the "spectrum" scope chain. Token migration into this |
| 874 | // scope happens in step 4 of the refactor. |
| 875 | theme::setContainer(this, QStringLiteral("spectrum")); |
| 876 | |
| 877 | m_panStats.clock.start(); // panstats rates are meaningless without an epoch |
| 878 | |
| 879 | setMinimumHeight(100); |
| 880 | setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
| 881 | setAutoFillBackground(false); |
| 882 | setAccessibleName(tr("Panadapter spectrum display")); |
| 883 | #ifdef AETHER_GPU_SPECTRUM |
| 884 | // Explicitly request Metal on macOS. |
| 885 | # ifdef Q_OS_MAC |
| 886 | setApi(QRhiWidget::Api::Metal); |
| 887 | // WA_NativeWindow forces Qt to create a dedicated native NSView for this widget. |
| 888 | // Without it, QRhiWidget embedded in a QWidget hierarchy (especially one whose |
| 889 | // backing store was created before this widget was added) fails to obtain a QRhi |
| 890 | // context because the parent window's surface type is RasterSurface, not MetalSurface |
| 891 | // (#714, Qt 6.6 era). The native view is expensive, though: every present forces |
| 892 | // a raster flushSubWindow blend of the pan region on the GUI thread. |
| 893 | // AETHER_PAN_NO_NATIVE_WINDOW=1 skips it to validate the composited path on |
| 894 | // newer Qt, where the whole window flushes through one rhi swapchain. |
| 895 | if (nativeWindowPreferred()) { |
| 896 | setAttribute(Qt::WA_NativeWindow); |
| 897 | } |
| 898 | # else |
| 899 | // Warn if running under XWayland — GLX context switching between the main |
| 900 | // window and child dialogs (e.g. Radio Setup) can trigger BadAccess (#1233). |
| 901 | // main.cpp normally forces native Wayland, but log it if we ended up here. |
| 902 | if (QGuiApplication::platformName() == QLatin1String("xcb") |
| 903 | && qEnvironmentVariable("XDG_SESSION_TYPE") == QLatin1String("wayland")) { |
| 904 | qWarning() << "SpectrumWidget: running under XWayland with OpenGL — " |
| 905 | "GLX context issues may occur. Set QT_QPA_PLATFORM=wayland " |
| 906 | "or AETHER_NO_GPU=1 to work around (#1233)"; |
| 907 | } |
| 908 | # endif |
| 909 | #else |
| 910 | setAttribute(Qt::WA_OpaquePaintEvent); |
| 911 | #endif |
| 912 | setSpectrumCursor(Qt::CrossCursor); |
| 913 | setMouseTracking(true); |
| 914 | |
| 915 | // Floating overlay menu (child widget, stays on top) |
| 916 | m_overlayMenu = new SpectrumOverlayMenu(this); |
| 917 | m_overlayMenu->raise(); |
| 918 | |
| 919 | m_tnfHoverPopup = new QLabel(this); |
| 920 | m_tnfHoverPopup->setAttribute(Qt::WA_TransparentForMouseEvents); |
| 921 | m_tnfHoverPopup->setMargin(6); |
| 922 | m_tnfHoverPopup->hide(); |
| 923 | m_tnfHoverPopup->raise(); |
| 924 | |
| 925 | m_interlockNotificationLabel = new QLabel(this); |
nothing calls this directly
no test coverage detected