include(GNUInstallDirs)

find_package(SQLite3 REQUIRED)
set(GLDOZE_SQLITE3_TARGET SQLite::SQLite3)

add_library(gldoze_desktop_filesystem STATIC
  src/desktop_filesystem_service.cpp
  ${GLDOZE_REPO_ROOT}/glcommanderprivileged.cpp
)
target_include_directories(gldoze_desktop_filesystem PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src ${GLDOZE_REPO_ROOT})
target_link_libraries(gldoze_desktop_filesystem PUBLIC gldoze_engine gldoze_sdk)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
  target_compile_definitions(gldoze_desktop_filesystem PRIVATE
    "GLDOZE_FILESYSTEM_HELPER_INSTALL_PATH=\"${CMAKE_INSTALL_FULL_LIBEXECDIR}/gldoze/gldoze_filesystem_helper\"")
endif()

add_library(gldoze_desktop_preferences STATIC
  src/desktop_application_preferences.cpp
)
target_include_directories(gldoze_desktop_preferences PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_preferences PUBLIC gldoze_engine)

add_library(gldoze_desktop_documents STATIC
  src/desktop_application_documents.cpp
)
target_include_directories(gldoze_desktop_documents PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_documents PUBLIC gldoze_engine)

add_library(gldoze_desktop_audio_documents STATIC
  src/desktop_audio_document_service.cpp
)
target_include_directories(gldoze_desktop_audio_documents PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_audio_documents PUBLIC
  gldoze_foundation
  PkgConfig::AVCODEC
  PkgConfig::AVFORMAT
  PkgConfig::AVUTIL
  PkgConfig::SWRESAMPLE
)

add_library(gldoze_desktop_gallery_scenes STATIC
  src/desktop_gallery_scene_service.cpp
)
target_include_directories(gldoze_desktop_gallery_scenes PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
if(TARGET gldoze_gallery_scene_registry)
  target_link_libraries(gldoze_desktop_gallery_scenes PUBLIC gldoze_gallery_scene_registry)
else()
  # Reduced configurations (GLDOZE_BUILD_DEMO=OFF) do not create the demo
  # registry target. Provide the header path and compile the registry here so
  # the neutral gallery service keeps a defined GallerySceneRegistry symbol.
  target_include_directories(gldoze_desktop_gallery_scenes PUBLIC
    ${GLDOZE_REPO_ROOT}/apps/demo/src
    ${GLDOZE_REPO_ROOT})
  target_sources(gldoze_desktop_gallery_scenes PRIVATE
    ${GLDOZE_REPO_ROOT}/apps/demo/src/gallery_scene_registry.cpp)
endif()

add_library(gldoze_desktop_media STATIC
  src/desktop_media_service.cpp
)
target_include_directories(gldoze_desktop_media PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_media PUBLIC gldoze_engine gldoze_sdk)

add_library(gldoze_desktop_system_telemetry STATIC
  src/desktop_system_telemetry_service.cpp
)
target_include_directories(gldoze_desktop_system_telemetry PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_system_telemetry PUBLIC gldoze_engine)

add_library(gldoze_desktop_cpu_performance STATIC
  src/cpu_performance_manager.cpp
  src/cpu_performance_manager.h
)
target_include_directories(gldoze_desktop_cpu_performance PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src ${GLDOZE_REPO_ROOT})
target_link_libraries(gldoze_desktop_cpu_performance PUBLIC gldoze_foundation)

add_library(gldoze_desktop_profiler STATIC
  src/desktop_profiler_service.cpp
  ${GLDOZE_REPO_ROOT}/gpu_clock_controller.cpp
)
target_include_directories(gldoze_desktop_profiler PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_profiler PUBLIC gldoze_engine gldoze_sdk)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
  target_compile_definitions(gldoze_desktop_profiler PRIVATE
    "GLDOZE_GPU_CLOCK_HELPER_INSTALL_PATH=\"${CMAKE_INSTALL_FULL_LIBEXECDIR}/gldoze/gldoze_gpu_clock_helper\"")
endif()

add_library(gldoze_desktop_process_control STATIC
  src/desktop_process_control_service.cpp
)
target_include_directories(gldoze_desktop_process_control PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_process_control PUBLIC gldoze_engine)

add_library(gldoze_desktop_media_metadata STATIC
  src/desktop_media_metadata_service.cpp
)
target_include_directories(gldoze_desktop_media_metadata PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_media_metadata PUBLIC gldoze_engine gldoze_sdk)

find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
  pkg_check_modules(GLDOZE_DESKTOP_CURL QUIET IMPORTED_TARGET libcurl)
  pkg_check_modules(GLDOZE_DESKTOP_LIBSECRET QUIET IMPORTED_TARGET libsecret-1)
  pkg_check_modules(GLDOZE_DESKTOP_NSS QUIET IMPORTED_TARGET nss)
endif()
add_library(gldoze_desktop_media_catalog STATIC
  src/desktop_media_catalog_service.cpp
)
target_include_directories(gldoze_desktop_media_catalog PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_media_catalog PUBLIC gldoze_engine gldoze_sdk)
if(TARGET PkgConfig::GLDOZE_DESKTOP_CURL)
  target_link_libraries(gldoze_desktop_media_catalog PUBLIC PkgConfig::GLDOZE_DESKTOP_CURL)
  target_compile_definitions(gldoze_desktop_media_catalog PRIVATE GLDOZE_DESKTOP_HAS_CURL=1)
endif()

add_library(gldoze_desktop_credentials STATIC
  src/desktop_credential_service.cpp
  src/libsecret_credential_backend.cpp
  src/credential_worker.cpp
  src/secure_buffer.h
)
target_include_directories(gldoze_desktop_credentials PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_credentials PUBLIC gldoze_engine)
if(TARGET PkgConfig::GLDOZE_DESKTOP_LIBSECRET)
  target_link_libraries(gldoze_desktop_credentials PUBLIC PkgConfig::GLDOZE_DESKTOP_LIBSECRET)
  target_compile_definitions(gldoze_desktop_credentials PRIVATE GLDOZE_DESKTOP_HAS_LIBSECRET=1)
endif()

add_library(gldoze_desktop_browser_importer STATIC
  src/browser_data_importer.cpp
  src/browser_data_importer.h
  src/zen_browser_importer.cpp
  src/zen_browser_importer.h
)
target_include_directories(gldoze_desktop_browser_importer PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
target_link_libraries(gldoze_desktop_browser_importer PUBLIC gldoze_engine gldoze_desktop_credentials)
if(TARGET PkgConfig::GLDOZE_DESKTOP_NSS)
  target_link_libraries(gldoze_desktop_browser_importer PUBLIC PkgConfig::GLDOZE_DESKTOP_NSS)
  target_compile_definitions(gldoze_desktop_browser_importer PRIVATE GLDOZE_DESKTOP_HAS_NSS=1)
endif()

add_library(gldoze_desktop_scene_support STATIC
  src/desktop_scene_bridge.cpp
  ${CMAKE_CURRENT_LIST_DIR}/../demo/src/app_scenes_springmap.cpp
  ${CMAKE_CURRENT_LIST_DIR}/../demo/src/app_settings.cpp
)
target_include_directories(gldoze_desktop_scene_support
  PUBLIC
    ${CMAKE_CURRENT_LIST_DIR}/src
    ${CMAKE_CURRENT_LIST_DIR}/../demo/src
    ${CMAKE_CURRENT_LIST_DIR}/../..
)
target_link_libraries(gldoze_desktop_scene_support PUBLIC gldoze_engine)

add_library(gldoze_gltaskman STATIC
	 src/gltaskman_calendar.cpp
	 src/gltaskman_model.cpp
  src/gltaskman_repository.cpp
  src/gltaskman_service.cpp
  src/gltaskman_time_selector.cpp
  src/gltaskman_window.cpp
)
target_include_directories(gldoze_gltaskman PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src ${CMAKE_CURRENT_LIST_DIR}/../..)
target_link_libraries(gldoze_gltaskman PUBLIC gldoze_engine ${GLDOZE_SQLITE3_TARGET})

# Platform-neutral desktop vocabulary and backend selection.  This target has
# no Xlib/Wayland headers; when X11 is enabled its factory delegates to the
# separately built adapter below.
add_library(gldoze_desktop_core STATIC
  src/desktop_platform.cpp
  src/desktop_backend_registry.cpp
  src/desktop_platform_types.h
  src/desktop_platform_backend.h
  src/desktop_backend_registry.h
  src/desktop_native_surface_backend.h
  src/desktop_popup_surface.h
)
target_include_directories(gldoze_desktop_core PUBLIC
  ${CMAKE_CURRENT_LIST_DIR}/src
  ${CMAKE_CURRENT_LIST_DIR}/../..
)
if(GLDOZE_ENABLE_WAYLAND)
  target_compile_definitions(gldoze_desktop_core PRIVATE GLDOZE_ENABLE_WAYLAND=1)
endif()

if(GLDOZE_ENABLE_WAYLAND AND UNIX AND NOT APPLE)
  find_package(PkgConfig REQUIRED)
  # Arch/CachyOS currently exposes wlroots as a versioned pkg-config module.
  # Prefer the installed 0.20 ABI while retaining compatibility with the
  # older 0.19/0.18 and unversioned module names used by other distributions.
  pkg_search_module(GLDOZE_WLROOTS QUIET IMPORTED_TARGET
    wlroots-0.20 wlroots-0.19 wlroots-0.18 wlroots)
  if(NOT GLDOZE_WLROOTS_FOUND)
    message(FATAL_ERROR
      "GLDOZE_ENABLE_WAYLAND=ON requires a wlroots-0.20, wlroots-0.19, wlroots-0.18, or wlroots development module via pkg-config")
  endif()
  pkg_check_modules(GLDOZE_WAYLAND_SERVER REQUIRED IMPORTED_TARGET wayland-server)
  pkg_check_modules(GLDOZE_WAYLAND_CLIENT REQUIRED IMPORTED_TARGET wayland-client)
  pkg_check_modules(GLDOZE_WAYLAND_PROTOCOLS REQUIRED IMPORTED_TARGET wayland-protocols)
  pkg_check_modules(GLDOZE_XKBCOMMON REQUIRED IMPORTED_TARGET xkbcommon)
  pkg_check_modules(GLDOZE_PIXMAN REQUIRED IMPORTED_TARGET pixman-1)
  pkg_check_modules(GLDOZE_GBM REQUIRED IMPORTED_TARGET gbm)
  pkg_check_modules(GLDOZE_LIBSEAT REQUIRED IMPORTED_TARGET libseat)
  pkg_check_modules(GLDOZE_LIFTOFF REQUIRED IMPORTED_TARGET libliftoff)
  pkg_check_modules(GLDOZE_XCB_EWMH REQUIRED IMPORTED_TARGET xcb-ewmh)
  pkg_check_modules(GLDOZE_XCB_ERRORS REQUIRED IMPORTED_TARGET xcb-errors)
  # Server-side window decorations render the title text with cairo/pango.
  pkg_check_modules(GLDOZE_PANGO QUIET IMPORTED_TARGET pango)
  pkg_check_modules(GLDOZE_PANGOCAIRO QUIET IMPORTED_TARGET pangocairo)
  pkg_check_modules(GLDOZE_CAIRO QUIET IMPORTED_TARGET cairo)
  find_program(GLDOZE_WAYLAND_SCANNER wayland-scanner REQUIRED)
  pkg_get_variable(GLDOZE_WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
  set(GLDOZE_XDG_SHELL_XML
    "${GLDOZE_WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml")
  set(GLDOZE_XDG_DECORATION_XML
    "${GLDOZE_WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml")
  if(NOT EXISTS "${GLDOZE_XDG_SHELL_XML}")
    message(FATAL_ERROR
      "GLDOZE_ENABLE_WAYLAND=ON requires xdg-shell.xml from wayland-protocols")
  endif()
  if(NOT EXISTS "${GLDOZE_XDG_DECORATION_XML}")
    message(FATAL_ERROR
      "GLDOZE_ENABLE_WAYLAND=ON requires xdg-decoration-unstable-v1.xml from wayland-protocols")
  endif()
  set(GLDOZE_WAYLAND_GENERATED_DIR
    "${CMAKE_CURRENT_BINARY_DIR}/generated-wayland")
  set(GLDOZE_XDG_SHELL_HEADER
    "${GLDOZE_WAYLAND_GENERATED_DIR}/xdg-shell-protocol.h")
  add_custom_command(
    OUTPUT "${GLDOZE_XDG_SHELL_HEADER}"
    COMMAND ${CMAKE_COMMAND} -E make_directory "${GLDOZE_WAYLAND_GENERATED_DIR}"
    COMMAND ${GLDOZE_WAYLAND_SCANNER} server-header
      "${GLDOZE_XDG_SHELL_XML}" "${GLDOZE_XDG_SHELL_HEADER}"
    DEPENDS "${GLDOZE_XDG_SHELL_XML}"
    VERBATIM)
  set(GLDOZE_XDG_SHELL_CLIENT_HEADER
    "${GLDOZE_WAYLAND_GENERATED_DIR}/xdg-shell-client-protocol.h")
  set(GLDOZE_XDG_SHELL_CLIENT_SOURCE
    "${GLDOZE_WAYLAND_GENERATED_DIR}/xdg-shell-client-protocol.c")
  add_custom_command(
    OUTPUT "${GLDOZE_XDG_SHELL_CLIENT_HEADER}"
    COMMAND ${CMAKE_COMMAND} -E make_directory "${GLDOZE_WAYLAND_GENERATED_DIR}"
    COMMAND ${GLDOZE_WAYLAND_SCANNER} client-header
      "${GLDOZE_XDG_SHELL_XML}" "${GLDOZE_XDG_SHELL_CLIENT_HEADER}"
    DEPENDS "${GLDOZE_XDG_SHELL_XML}"
    VERBATIM)
  add_custom_command(
    OUTPUT "${GLDOZE_XDG_SHELL_CLIENT_SOURCE}"
    COMMAND ${CMAKE_COMMAND} -E make_directory "${GLDOZE_WAYLAND_GENERATED_DIR}"
    COMMAND ${GLDOZE_WAYLAND_SCANNER} private-code
      "${GLDOZE_XDG_SHELL_XML}" "${GLDOZE_XDG_SHELL_CLIENT_SOURCE}"
    DEPENDS "${GLDOZE_XDG_SHELL_XML}"
    VERBATIM)
  set(GLDOZE_XDG_DECORATION_CLIENT_HEADER
    "${GLDOZE_WAYLAND_GENERATED_DIR}/xdg-decoration-client-protocol.h")
  set(GLDOZE_XDG_DECORATION_CLIENT_SOURCE
    "${GLDOZE_WAYLAND_GENERATED_DIR}/xdg-decoration-client-protocol.c")
  add_custom_command(
    OUTPUT "${GLDOZE_XDG_DECORATION_CLIENT_HEADER}"
    COMMAND ${CMAKE_COMMAND} -E make_directory "${GLDOZE_WAYLAND_GENERATED_DIR}"
    COMMAND ${GLDOZE_WAYLAND_SCANNER} client-header
      "${GLDOZE_XDG_DECORATION_XML}" "${GLDOZE_XDG_DECORATION_CLIENT_HEADER}"
    DEPENDS "${GLDOZE_XDG_DECORATION_XML}"
    VERBATIM)
  add_custom_command(
    OUTPUT "${GLDOZE_XDG_DECORATION_CLIENT_SOURCE}"
    COMMAND ${CMAKE_COMMAND} -E make_directory "${GLDOZE_WAYLAND_GENERATED_DIR}"
    COMMAND ${GLDOZE_WAYLAND_SCANNER} private-code
      "${GLDOZE_XDG_DECORATION_XML}" "${GLDOZE_XDG_DECORATION_CLIENT_SOURCE}"
    DEPENDS "${GLDOZE_XDG_DECORATION_XML}"
    VERBATIM)
  add_library(gldoze_desktop_wayland STATIC
    src/desktop_wayland_backend.cpp
    src/desktop_wayland_backend.h
    src/desktop_wayland_keyboard.cpp
    src/desktop_wayland_keyboard.h
    src/desktop_wayland_compositor.cpp
    src/desktop_wayland_compositor.h
    src/desktop_wayland_scene_shim.c
    src/desktop_wayland_scene_shim.h
    src/desktop_wayland_datadevice_shim.c
    src/desktop_wayland_datadevice_shim.h
    src/desktop_wayland_xwayland.c
    src/desktop_wayland_xwayland.h
    "${GLDOZE_XDG_SHELL_HEADER}"
  )
  target_include_directories(gldoze_desktop_wayland PUBLIC
    ${CMAKE_CURRENT_LIST_DIR}/src
    ${CMAKE_CURRENT_LIST_DIR}/../..
  )
  target_compile_definitions(gldoze_desktop_wayland PRIVATE
    GLDOZE_ENABLE_WAYLAND=1
    WLR_USE_UNSTABLE
  )
  if(GLDOZE_WLROOTS_VERSION VERSION_GREATER_EQUAL "0.20")
    target_compile_definitions(gldoze_desktop_wayland PRIVATE
      GLDOZE_WLROOTS_API_020=1)
  endif()
  target_link_libraries(gldoze_desktop_wayland PUBLIC
    gldoze_desktop_core
    gldoze_desktop_process_control
    gldoze_external_deps
    PkgConfig::GLDOZE_WLROOTS
    PkgConfig::GLDOZE_WAYLAND_SERVER
    PkgConfig::GLDOZE_WAYLAND_PROTOCOLS
    PkgConfig::GLDOZE_XKBCOMMON
    PkgConfig::GLDOZE_PIXMAN
    PkgConfig::GLDOZE_GBM
    PkgConfig::GLDOZE_LIBSEAT
    PkgConfig::GLDOZE_LIFTOFF
    PkgConfig::GLDOZE_XCB_EWMH
    PkgConfig::GLDOZE_XCB_ERRORS
  )
  if(TARGET PkgConfig::GLDOZE_PANGO AND TARGET PkgConfig::GLDOZE_CAIRO AND TARGET PkgConfig::GLDOZE_PANGOCAIRO)
    target_link_libraries(gldoze_desktop_wayland PUBLIC
      PkgConfig::GLDOZE_PANGO
      PkgConfig::GLDOZE_PANGOCAIRO
      PkgConfig::GLDOZE_CAIRO
    )
    target_compile_definitions(gldoze_desktop_wayland PRIVATE GLDOZE_DECOR_TEXT=1)
  endif()
  if(GLDOZE_WLROOTS_LIBRARY_DIRS)
    target_link_directories(gldoze_desktop_wayland PUBLIC
      ${GLDOZE_WLROOTS_LIBRARY_DIRS})
  endif()
  if(GLDOZE_WLROOTS_LIBRARY_DIRS)
    set_target_properties(gldoze_desktop_wayland PROPERTIES
      BUILD_RPATH "${GLDOZE_WLROOTS_LIBRARY_DIRS}")
  endif()
  set_property(TARGET gldoze_desktop_wayland APPEND PROPERTY
    BUILD_RPATH "${GLDOZE_LIBSEAT_LIBRARY_DIRS};${GLDOZE_LIFTOFF_LIBRARY_DIRS};${GLDOZE_XCB_EWMH_LIBRARY_DIRS};${GLDOZE_XCB_ERRORS_LIBRARY_DIRS}")
  foreach(_gldoze_wayland_private_target IN ITEMS
      GLDOZE_LIBSEAT GLDOZE_LIFTOFF GLDOZE_XCB_EWMH GLDOZE_XCB_ERRORS)
    if(${_gldoze_wayland_private_target}_LIBRARY_DIRS)
      target_link_directories(gldoze_desktop_wayland PUBLIC
        ${${_gldoze_wayland_private_target}_LIBRARY_DIRS})
    endif()
  endforeach()
  foreach(_gldoze_wayland_private_target IN ITEMS
      GLDOZE_LIBSEAT GLDOZE_LIFTOFF GLDOZE_XCB_EWMH GLDOZE_XCB_ERRORS)
    if(${_gldoze_wayland_private_target}_LIBRARY_DIRS)
      set_property(TARGET gldoze_desktop_wayland APPEND PROPERTY
        BUILD_RPATH "${${_gldoze_wayland_private_target}_LIBRARY_DIRS}")
    endif()
  endforeach()
  target_include_directories(gldoze_desktop_wayland SYSTEM PRIVATE
    ${GLDOZE_WAYLAND_GENERATED_DIR})
endif()

if(GLDOZE_ENABLE_X11 AND UNIX AND NOT APPLE)
  add_library(gldoze_desktop_x11 STATIC
    src/desktop_x11_backend.cpp
    src/desktop_global_shortcut_manager.cpp
    src/desktop_x11_embedder.cpp
    src/desktop_x11_window_manager.cpp
    src/desktop_x11_native_surface.cpp
    src/desktop_x11_popup_surface.cpp
    ${CMAKE_CURRENT_LIST_DIR}/../../x11_surface.cpp
    ${CMAKE_CURRENT_LIST_DIR}/../../popup_surface.cpp
  )
  target_include_directories(gldoze_desktop_x11 PUBLIC
    ${CMAKE_CURRENT_LIST_DIR}/src
    ${CMAKE_CURRENT_LIST_DIR}/../..
  )
  target_compile_definitions(gldoze_desktop_x11 PUBLIC GLDOZE_RUNTIME_X11_EGL=1)
  target_link_libraries(gldoze_desktop_x11 PUBLIC gldoze_external_deps)
endif()

add_library(gldoze_desktop_support STATIC
  src/desktop_app.cpp
	src/desktop_bar_window_policy.cpp
  src/desktop_command_channel.cpp
  src/desktop_registry.cpp
  src/desktop_settings.cpp
	  src/desktop_audio_control.cpp
  src/desktop_process_launcher.cpp
	  src/desktop_monitor_layout_editor.cpp
	  src/desktop_dropdown_terminal.cpp
	  src/desktop_native_surface.cpp
	  src/desktop_developer_console.cpp
	  src/desktop_developer_console_window.cpp
	  src/developer_console_registry.cpp
	  src/developer_console_lua.cpp
	  src/desktop_dropdown_terminal_math.cpp
	  src/desktop_overview_controller.cpp
	  src/desktop_overview_math.cpp
	  src/desktop_file_list_bridge.cpp
	  src/desktop_plugin_host.cpp
	  src/desktop_polkit_agent.cpp
	  src/desktop_polkit_agent.h
  src/desktop_map_preview_widget.cpp
	  src/plugin_manager_window.cpp
	  src/desktop_service_registry.cpp
	  src/desktop_window_rules.cpp
	  src/desktop_window_rules_match.cpp
	  src/desktop_shell.cpp
)
add_library(gldoze_gldream STATIC
  src/gldream_service.cpp
  src/gldream_service.h
  src/gldream_platform.cpp
  src/gldream_platform.h
  ${GLDOZE_REPO_ROOT}/immediate_batch.cpp
)
target_include_directories(gldoze_gldream PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src ${CMAKE_CURRENT_LIST_DIR}/../..)
target_link_libraries(gldoze_gldream PUBLIC gldoze_foundation)

target_include_directories(gldoze_desktop_support PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src ${CMAKE_CURRENT_LIST_DIR}/../..)
target_link_libraries(gldoze_desktop_support PUBLIC gldoze_desktop_core gldoze_engine gldoze_gltaskman gldoze_gldream gldoze_desktop_scene_support gldoze_demo_support gldoze_plugin_runtime gldoze_desktop_filesystem gldoze_desktop_preferences gldoze_desktop_documents gldoze_desktop_audio_documents gldoze_desktop_gallery_scenes gldoze_desktop_media gldoze_desktop_system_telemetry gldoze_desktop_cpu_performance gldoze_desktop_profiler gldoze_desktop_process_control gldoze_desktop_media_metadata gldoze_desktop_media_catalog gldoze_desktop_credentials gldoze_desktop_browser_importer gldoze_remote_protocol)
if(GLDOZE_ENABLE_WAYLAND AND TARGET gldoze_desktop_wayland)
  target_link_libraries(gldoze_desktop_support PUBLIC gldoze_desktop_wayland)
  target_compile_definitions(gldoze_desktop_support PUBLIC GLDOZE_ENABLE_WAYLAND=1)
endif()

if(UNIX AND NOT APPLE)
  # Password authentication is a GLDream service capability, not an X11
  # windowing dependency. Keep it available in X11-off builds as well.
  pkg_check_modules(GLDOZE_GLDREAM_PAM REQUIRED IMPORTED_TARGET pam)
  target_link_libraries(gldoze_gldream PUBLIC PkgConfig::GLDOZE_GLDREAM_PAM)
  target_compile_definitions(gldoze_gldream PRIVATE GLDOZE_GLDREAM_PAM=1)
endif()

if(GLDOZE_ENABLE_LUAJIT)
  find_path(GLDOZE_LUAJIT_INCLUDE_DIR lua.h
    PATH_SUFFIXES luajit-2.1 luajit-2.0)
  find_library(GLDOZE_LUAJIT_LIBRARY NAMES luajit-5.1 luajit-5.2 luajit)
  if(GLDOZE_LUAJIT_INCLUDE_DIR AND GLDOZE_LUAJIT_LIBRARY)
    target_include_directories(gldoze_desktop_support PRIVATE ${GLDOZE_LUAJIT_INCLUDE_DIR})
    target_link_libraries(gldoze_desktop_support PRIVATE ${GLDOZE_LUAJIT_LIBRARY})
    target_compile_definitions(gldoze_desktop_support PRIVATE GLDOZE_ENABLE_LUAJIT=1)
    message(STATUS "Developer Console: LuaJIT enabled (${GLDOZE_LUAJIT_LIBRARY})")
  else()
    message(STATUS "Developer Console: LuaJIT not found; scripting commands will report unavailable")
  endif()
endif()
if(SQLite3_FOUND)
  target_link_libraries(gldoze_desktop_support PUBLIC ${GLDOZE_SQLITE3_TARGET})
else()
  message(FATAL_ERROR "GLTaskMan requires SQLite3 to build gldoze_desktop")
endif()
if(TARGET glmail_support)
  target_link_libraries(gldoze_desktop_support PUBLIC glmail_support)
  target_compile_definitions(gldoze_desktop_support PRIVATE GLDOZE_DESKTOP_MAIL=1)
endif()
if(GLDOZE_ENABLE_X11 AND UNIX AND NOT APPLE)
  find_package(X11 REQUIRED)
  pkg_check_modules(XFT REQUIRED IMPORTED_TARGET xft)
  target_link_libraries(gldoze_gldream PUBLIC X11::X11 X11::Xext)
  target_compile_definitions(gldoze_gldream PRIVATE GLDOZE_GLDREAM_X11=1)
  target_link_libraries(gldoze_desktop_x11 PUBLIC
    gldoze_desktop_process_control
    X11::X11 X11::Xcomposite X11::Xext PkgConfig::XFT)
  target_compile_definitions(gldoze_desktop_x11 PRIVATE
    GLDOZE_ENABLE_X11=1 GLDOZE_DESKTOP_X11_EMBED=1 GLDOZE_DESKTOP_X11_WM=1)
  target_compile_definitions(gldoze_desktop_support PUBLIC GLDOZE_DESKTOP_X11=1)
  target_sources(gldoze_gldream PRIVATE
    src/gldream_x11_platform.cpp
    src/gldream_x11_platform.h
  )
  target_link_libraries(gldoze_desktop_support PUBLIC gldoze_desktop_x11)
  if(TARGET X11::Xrandr)
    target_link_libraries(gldoze_desktop_x11 PUBLIC X11::Xrandr)
    target_compile_definitions(gldoze_desktop_x11 PRIVATE GLDOZE_DESKTOP_XRANDR=1)
  endif()
else()
  target_sources(gldoze_desktop_support PRIVATE
    src/desktop_native_surface_stub.cpp
    src/desktop_popup_surface_stub.cpp
  )
endif()

add_executable(gldoze_desktop
  src/main.cpp
  src/app_factory.cpp
  src/desktop_backend_registration.cpp
)
target_link_libraries(gldoze_desktop PRIVATE gldoze_desktop_support)
# The helper is a deliberately separate executable. In a production install
# it can be made root-owned/setuid without ever elevating the desktop shell.
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
  add_executable(gldoze_cpu_power_helper
    ${GLDOZE_REPO_ROOT}/cpu_power_helper.cpp
    ${GLDOZE_REPO_ROOT}/cpu_power_rapl.cpp
  )
  target_include_directories(gldoze_cpu_power_helper PRIVATE ${GLDOZE_REPO_ROOT})
  target_link_libraries(gldoze_cpu_power_helper PRIVATE gldoze_project_options)
  gldoze_apply_dev_warnings(gldoze_cpu_power_helper)
  set_target_properties(gldoze_cpu_power_helper PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
  add_dependencies(gldoze_desktop gldoze_cpu_power_helper)

  add_executable(gldoze_gpu_clock_helper
    ${GLDOZE_REPO_ROOT}/gpu_clock_helper.cpp
    ${GLDOZE_REPO_ROOT}/gpu_clock_controller.cpp
    ${GLDOZE_REPO_ROOT}/nvml_gpu_monitor.cpp
  )
  target_include_directories(gldoze_gpu_clock_helper PRIVATE ${GLDOZE_REPO_ROOT})
  target_compile_definitions(gldoze_gpu_clock_helper PRIVATE
    GLDOZE_NVML_CONTROL_ONLY=1)
  target_link_libraries(gldoze_gpu_clock_helper PRIVATE
    gldoze_project_options Threads::Threads ${CMAKE_DL_LIBS})
  gldoze_apply_dev_warnings(gldoze_gpu_clock_helper)
  set_target_properties(gldoze_gpu_clock_helper PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
  add_dependencies(gldoze_desktop gldoze_gpu_clock_helper)

  add_executable(gldoze_filesystem_helper
    ${GLDOZE_REPO_ROOT}/glcommander_filesystem_helper.cpp
    ${GLDOZE_REPO_ROOT}/glcommanderprivileged.cpp)
  target_include_directories(gldoze_filesystem_helper PRIVATE ${GLDOZE_REPO_ROOT})
  target_link_libraries(gldoze_filesystem_helper PRIVATE gldoze_project_options)
  gldoze_apply_dev_warnings(gldoze_filesystem_helper)
  set_target_properties(gldoze_filesystem_helper PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
  add_dependencies(gldoze_desktop gldoze_filesystem_helper)

  set(GLDOZE_FILESYSTEM_HELPER_POLICY_PATH
    "${CMAKE_INSTALL_FULL_LIBEXECDIR}/gldoze/gldoze_filesystem_helper")
  configure_file(gldoze-filesystem-helper.policy.in
    "${CMAKE_CURRENT_BINARY_DIR}/com.gldoze.filesystem.admin.policy" @ONLY)
endif()
set(GLDOZE_DESKTOP_PLUGIN_TARGETS
  gldoze_fps_meter
  gldoze_color_picker
  gldoze_glpowerforge
  gldoze_image_viewer
  gldoze_logs
  gldoze_remote_systems
  gldoze_keys
  gldoze_terminal
  gldoze_gledit
  gldoze_files
	  gldoze_audio_editor
  gldoze_render_test
  gldoze_obj_viewer
  gldoze_gallery
  gldoze_audio_cd_ripper_preview
  gldoze_map_preview_test
  gldoze_presentation_plugins
  verdant_gldoze_plugin
  gldoze_gldeck
  gldoze_profiler
)
foreach(GLDOZE_PLUGIN_TARGET IN LISTS GLDOZE_DESKTOP_PLUGIN_TARGETS)
  if(TARGET ${GLDOZE_PLUGIN_TARGET})
    add_dependencies(gldoze_desktop ${GLDOZE_PLUGIN_TARGET})
  endif()
endforeach()
if(TARGET X11::Xrandr)
  target_link_libraries(gldoze_desktop PRIVATE X11::Xrandr)
  target_compile_definitions(gldoze_desktop PRIVATE GLDOZE_DESKTOP_XRANDR=1)
  target_compile_definitions(gldoze_desktop_support PUBLIC GLDOZE_DESKTOP_XRANDR=1)
endif()
set_target_properties(gldoze_desktop PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")

if(GLDOZE_ENABLE_CEF_BROWSER)
	set(GLDOZE_CEF_ACCELERATED_OSR_AVAILABLE OFF)
	if(UNIX AND NOT APPLE AND PkgConfig_FOUND)
		# Keep this dependency narrow: the accelerated path needs EGL entry
		# points for EGL contexts and core XCB calls for X11/GLX DRI3 import.
		pkg_check_modules(GLDOZE_CEF_OSR_EGL QUIET IMPORTED_TARGET egl)
		pkg_check_modules(GLDOZE_CEF_OSR_XCB QUIET IMPORTED_TARGET xcb)
		if(TARGET PkgConfig::GLDOZE_CEF_OSR_EGL AND TARGET PkgConfig::GLDOZE_CEF_OSR_XCB)
			set(GLDOZE_CEF_ACCELERATED_OSR_AVAILABLE ON)
		endif()
	endif()
	target_sources(gldoze_desktop_support PRIVATE
	  src/cef_html_message_view.cpp
	  src/cef_html_message_view.h
	  src/browser_platform.cpp
	  src/browser_platform.h
	  src/browser_native_surface.h
		  src/browser_accelerated_osr.cpp
		  src/browser_accelerated_osr.h
		  src/browser_surface.cpp
	  src/browser_surface.h
    src/browser_window.cpp
    src/browser_window.h
    src/browser_import_window.cpp
    src/browser_import_window.h
  )
	if(GLDOZE_CEF_ACCELERATED_OSR_AVAILABLE)
		target_compile_definitions(gldoze_desktop_support PUBLIC
			GLDOZE_CEF_ACCELERATED_OSR_AVAILABLE=1)
		target_link_libraries(gldoze_desktop_support PUBLIC
			PkgConfig::GLDOZE_CEF_OSR_EGL
			PkgConfig::GLDOZE_CEF_OSR_XCB)
		message(STATUS "CEF Linux accelerated OSR: EGL and X11/GLX DRI3 DMA-BUF import enabled")
	else()
		message(STATUS "CEF Linux accelerated OSR: EGL/XCB dependencies unavailable; CPU fallback only")
	endif()
	if(TARGET gldoze_desktop_x11)
	  target_sources(gldoze_desktop_x11 PRIVATE
	    src/browser_x11_host.cpp
	    src/browser_x11_host.h
	  )
	endif()

	add_library(gldoze_cef_browser STATIC
	  src/browser_adblock.cpp
	  src/browser_adblock.h
	  src/content_filter.cpp
	  src/content_filter.h
	  src/content_filter_service.cpp
	  src/content_filter_service.h
	  src/content_filter_ipc.h
	  src/browser_clipboard_ipc.h
	  src/content_filter_scriptlet_registry.cpp
    src/content_filter_scriptlet_registry.h
	  src/youtube_content_filter_module.cpp
	  src/youtube_content_filter_module.h
	  src/mail_resource_policy.cpp
	  src/mail_resource_policy.h
	  src/browser_native_surface.h
    src/browser_application.cpp
    src/browser_application.h
	  src/browser_credential_helper.cpp
	  src/browser_credential_helper.h
	  src/browser_credential_service.cpp
	  src/browser_credential_service.h
	  src/browser_data_store.cpp
	  src/browser_data_store.h
	  src/browser_navigation.cpp
	  src/browser_navigation.h
	  src/browser_input.cpp
	  src/browser_input.h
  )
  target_include_directories(gldoze_cef_browser
    PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src
    PRIVATE ${GLDOZE_REPO_ROOT}
  )
  target_link_libraries(gldoze_cef_browser
    PRIVATE
      gldoze_engine
      # BrowserCredentialService owns a CredentialWorker. Express the direct
      # dependency here so static consumers receive the implementation after
      # the browser archive instead of relying on top-level link order.
      gldoze_desktop_credentials
      libcef_dll_wrapper
      libcef_lib
      ${CEF_STANDARD_LIBS}
  )
  if(TARGET X11::Xrandr)
    target_compile_definitions(gldoze_cef_browser PRIVATE GLDOZE_DESKTOP_XRANDR=1)
    target_link_libraries(gldoze_cef_browser PRIVATE X11::Xrandr)
  endif()
  SET_LIBRARY_TARGET_PROPERTIES(gldoze_cef_browser)
	target_link_libraries(gldoze_desktop_support PUBLIC gldoze_cef_browser)

  add_executable(gldoze_cef_subprocess
    src/cef_subprocess_main.cpp
    src/cef_credential_render_handler.cpp
    src/cef_credential_render_handler.h
    src/browser_clipboard_ipc.h
    src/browser_credential_ipc.h
    src/content_filter.cpp
    src/content_filter.h
    src/content_filter_ipc.h
    src/content_filter_scriptlet_registry.cpp
    src/content_filter_scriptlet_registry.h
    src/youtube_content_filter_module.cpp
    src/youtube_content_filter_module.h)
  target_link_libraries(gldoze_cef_subprocess
    PRIVATE
      libcef_dll_wrapper
      libcef_lib
      ${CEF_STANDARD_LIBS}
  )
  SET_EXECUTABLE_TARGET_PROPERTIES(gldoze_cef_subprocess)
  # CEF's sample defaults include an rpath for the process working directory.
  # GLDoze ships all CEF libraries beside the helper, so keep lookup scoped to
  # the executable directory and avoid loading a stray ./libcef.so.
  set(_gldoze_cef_subprocess_linker_flags ${CEF_LINKER_FLAGS})
  list(REMOVE_ITEM _gldoze_cef_subprocess_linker_flags "-Wl,-rpath,.")
  string(REPLACE ";" " " _gldoze_cef_subprocess_linker_flags
    "${_gldoze_cef_subprocess_linker_flags}")
  set_property(TARGET gldoze_cef_subprocess PROPERTY
    LINK_FLAGS "${_gldoze_cef_subprocess_linker_flags}")
  set_target_properties(gldoze_cef_subprocess PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
    BUILD_WITH_INSTALL_RPATH TRUE
    INSTALL_RPATH "$ORIGIN"
  )

  target_compile_definitions(gldoze_desktop_support PUBLIC GLDOZE_ENABLE_CEF_BROWSER=1)
  target_link_libraries(gldoze_desktop PRIVATE gldoze_cef_browser)
  add_dependencies(gldoze_desktop gldoze_cef_subprocess)
  set_target_properties(gldoze_desktop PROPERTIES
    BUILD_WITH_INSTALL_RPATH TRUE
    INSTALL_RPATH "$ORIGIN"
  )

  foreach(_cef_binary IN LISTS GLDOZE_CEF_RUNTIME_RELEASE_FILES)
    add_custom_command(TARGET gldoze_desktop POST_BUILD
      COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "${CEF_ROOT}/Release/${_cef_binary}"
        "$<TARGET_FILE_DIR:gldoze_desktop>/${_cef_binary}"
      VERBATIM
    )
  endforeach()
  foreach(_cef_resource IN LISTS GLDOZE_CEF_RUNTIME_RESOURCE_FILES)
    add_custom_command(TARGET gldoze_desktop POST_BUILD
      COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "${CEF_ROOT}/Resources/${_cef_resource}"
        "$<TARGET_FILE_DIR:gldoze_desktop>/${_cef_resource}"
      VERBATIM
    )
  endforeach()
  add_custom_command(TARGET gldoze_desktop POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
      "${CEF_ROOT}/Resources/locales"
      "$<TARGET_FILE_DIR:gldoze_desktop>/locales"
    VERBATIM
  )

  install(TARGETS gldoze_cef_subprocess
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    COMPONENT GLDozeDesktop
  )
  foreach(_cef_binary IN LISTS GLDOZE_CEF_RUNTIME_RELEASE_FILES)
    if(_cef_binary STREQUAL "chrome-sandbox")
      install(PROGRAMS "${CEF_ROOT}/Release/${_cef_binary}"
        DESTINATION ${CMAKE_INSTALL_BINDIR}
        COMPONENT GLDozeDesktop)
    else()
      install(FILES "${CEF_ROOT}/Release/${_cef_binary}"
        DESTINATION ${CMAKE_INSTALL_BINDIR}
        COMPONENT GLDozeDesktop)
    endif()
  endforeach()
  foreach(_cef_resource IN LISTS GLDOZE_CEF_RUNTIME_RESOURCE_FILES)
    install(FILES "${CEF_ROOT}/Resources/${_cef_resource}"
      DESTINATION ${CMAKE_INSTALL_BINDIR}
      COMPONENT GLDozeDesktop)
  endforeach()
  install(DIRECTORY "${CEF_ROOT}/Resources/locales/"
    DESTINATION "${CMAKE_INSTALL_BINDIR}/locales"
    COMPONENT GLDozeDesktop
  )
  install(FILES "${CEF_ROOT}/LICENSE.txt" "${CEF_ROOT}/CREDITS.html"
    DESTINATION "share/doc/gldoze-desktop/cef"
    COMPONENT GLDozeDesktop
  )
endif()

install(TARGETS gldoze_desktop RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT GLDozeDesktop)
# URL activation is an external-process boundary. Pin the desktop entry to the
# installed binary so a stale user-local gldoze_desktop earlier in PATH cannot
# start a second compositor instead of forwarding to the active instance.
configure_file("${CMAKE_CURRENT_LIST_DIR}/gldoze-browser.desktop.in"
  "${CMAKE_CURRENT_BINARY_DIR}/gldoze-browser.desktop" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/gldoze-browser.desktop"
  DESTINATION "share/applications"
  COMPONENT GLDozeDesktop
)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
  install(TARGETS gldoze_cpu_power_helper
    RUNTIME DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}/gldoze"
    PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
                GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE SETUID
    COMPONENT GLDozeDesktop)
  install(TARGETS gldoze_gpu_clock_helper
    RUNTIME DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}/gldoze"
    PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
                GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE SETUID
    COMPONENT GLDozeDesktop)
  install(TARGETS gldoze_filesystem_helper
    RUNTIME DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}/gldoze"
    PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
                GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
    COMPONENT GLDozeDesktop)
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/com.gldoze.filesystem.admin.policy"
    DESTINATION "share/polkit-1/actions"
    COMPONENT GLDozeDesktop)
endif()
install(PROGRAMS "${GLDOZE_REPO_ROOT}/scripts/gledit"
  DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT GLDozeDesktop)
install(DIRECTORY "${GLDOZE_REPO_ROOT}/assets/desktop/"
  DESTINATION "share/gldoze/assets/desktop"
  COMPONENT GLDozeDesktop
)
install(DIRECTORY "${GLDOZE_REPO_ROOT}/assets/verdant/"
  DESTINATION "share/gldoze/assets/verdant"
  COMPONENT GLDozeDesktop
)
install(DIRECTORY "${GLDOZE_REPO_ROOT}/assets/techlobby/"
  DESTINATION "share/gldoze/assets/techlobby"
  COMPONENT GLDozeDesktop
)
install(FILES
  "${GLDOZE_REPO_ROOT}/assets/JetBrainsMono-Bold.ttf"
  "${GLDOZE_REPO_ROOT}/assets/JetBrainsMono-Medium.ttf"
  "${GLDOZE_REPO_ROOT}/assets/NotoSansMono-Regular.ttf"
  "${GLDOZE_REPO_ROOT}/assets/NotoSansSymbols-Regular.ttf"
  "${GLDOZE_REPO_ROOT}/assets/Terminus-Bold.ttf"
  "${GLDOZE_REPO_ROOT}/assets/Terminus.ttf"
  "${GLDOZE_REPO_ROOT}/assets/evermono.ttf"
  DESTINATION "share/gldoze/assets"
  COMPONENT GLDozeDesktop
)
install(FILES "${CMAKE_CURRENT_LIST_DIR}/README.md"
  DESTINATION "share/doc/gldoze-desktop"
  COMPONENT GLDozeDesktop
)

if(BUILD_TESTING)
	add_executable(desktop_render_pacer_test tests/desktop_render_pacer_test.cpp)
	target_include_directories(desktop_render_pacer_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
	add_test(NAME desktop_render_pacer COMMAND desktop_render_pacer_test)

  if(GLDOZE_ENABLE_WAYLAND AND TARGET gldoze_desktop_wayland)
    add_executable(desktop_wayland_compositor_test
      tests/desktop_wayland_compositor_test.cpp
      # The Wayland archive exposes the complete backend factory. Once the
	  # renderer objects are rebuilt, the headless test therefore needs the
	  # desktop app factory and credential worker that satisfy those objects.
	  src/app_factory.cpp
	  src/credential_worker.cpp)
    target_link_libraries(desktop_wayland_compositor_test PRIVATE
      gldoze_desktop_wayland gldoze_desktop_support)
	if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
	  target_compile_options(desktop_wayland_compositor_test PRIVATE -UNDEBUG)
	endif()
    add_test(NAME desktop_wayland_compositor
      COMMAND desktop_wayland_compositor_test)

	add_executable(desktop_output_damage_test
	  tests/desktop_output_damage_test.cpp)
	target_include_directories(desktop_output_damage_test PRIVATE
	  ${CMAKE_CURRENT_LIST_DIR}/src)
	add_test(NAME desktop_output_damage COMMAND desktop_output_damage_test)

    add_executable(desktop_wayland_keyboard_test
      tests/desktop_wayland_keyboard_test.cpp)
    target_link_libraries(desktop_wayland_keyboard_test PRIVATE
      gldoze_desktop_wayland)
    add_test(NAME desktop_wayland_keyboard
      COMMAND desktop_wayland_keyboard_test)

    add_executable(screenshot_png_writer_test
      tests/screenshot_png_writer_test.cpp
      ${GLDOZE_REPO_ROOT}/screenshot_png_writer.cpp)
    target_include_directories(screenshot_png_writer_test PRIVATE
      ${GLDOZE_REPO_ROOT})
    target_link_libraries(screenshot_png_writer_test PRIVATE PNG::PNG)
    add_test(NAME screenshot_png_writer
      COMMAND screenshot_png_writer_test)

    add_executable(desktop_wayland_e2e_test
      tests/desktop_wayland_e2e_test.cpp
      # Keep the headless integration target complete when the Wayland
      # archive pulls renderer/runtime objects through the DMA-BUF backend.
      src/app_factory.cpp
      src/credential_worker.cpp
      ${GLDOZE_XDG_SHELL_CLIENT_HEADER}
      ${GLDOZE_XDG_SHELL_CLIENT_SOURCE}
      ${GLDOZE_XDG_DECORATION_CLIENT_HEADER}
      ${GLDOZE_XDG_DECORATION_CLIENT_SOURCE})
    set_source_files_properties(
      ${GLDOZE_XDG_SHELL_CLIENT_HEADER} ${GLDOZE_XDG_SHELL_CLIENT_SOURCE}
      ${GLDOZE_XDG_DECORATION_CLIENT_HEADER} ${GLDOZE_XDG_DECORATION_CLIENT_SOURCE}
      PROPERTIES GENERATED TRUE)
    target_include_directories(desktop_wayland_e2e_test PRIVATE
      ${GLDOZE_WAYLAND_GENERATED_DIR})
    target_link_libraries(desktop_wayland_e2e_test PRIVATE
      gldoze_desktop_wayland
      gldoze_desktop_support
      PkgConfig::GLDOZE_WAYLAND_CLIENT)
    # This is a behavioral integration test.  Keep its assertions live in
    # Release builds; otherwise CMake's default -DNDEBUG turns every protocol
    # check into a no-op and can falsely report success.
    target_compile_options(desktop_wayland_e2e_test PRIVATE -UNDEBUG)
    # The XWayland E2E branch creates and maps a real X11 window.  Linking
    # Xlib here keeps that regression check independent of optional desktop
    # X11 backend objects while still exercising the compositor's XWayland.
    # A Wayland-only production build does not discover X11 for the disabled
    # platform backend, so probe it independently for this test.
    find_package(X11 QUIET)
    if(TARGET X11::X11)
      target_link_libraries(desktop_wayland_e2e_test PRIVATE X11::X11)
      target_compile_definitions(desktop_wayland_e2e_test PRIVATE
        GLDOZE_E2E_HAVE_X11=1)
    endif()
    add_test(NAME desktop_wayland_e2e
      COMMAND desktop_wayland_e2e_test)
    add_test(NAME desktop_wayland_e2e_xwayland
      COMMAND desktop_wayland_e2e_test)
    set_tests_properties(desktop_wayland_e2e_xwayland PROPERTIES
      ENVIRONMENT "GLDOZE_E2E_XWAYLAND=1")
    add_test(NAME desktop_wayland_e2e_recoil
      COMMAND desktop_wayland_e2e_test)
    set_tests_properties(desktop_wayland_e2e_recoil PROPERTIES
      ENVIRONMENT "GLDOZE_E2E_RECOIL=1")
    add_test(NAME desktop_wayland_e2e_zen
      COMMAND desktop_wayland_e2e_test)
    set_tests_properties(desktop_wayland_e2e_zen PROPERTIES
      ENVIRONMENT "GLDOZE_E2E_ZEN=1")
    add_test(NAME desktop_wayland_e2e_exodus
      COMMAND desktop_wayland_e2e_test)
    set_tests_properties(desktop_wayland_e2e_exodus PROPERTIES
      ENVIRONMENT "GLDOZE_E2E_EXODUS=1")
    add_test(NAME desktop_wayland_e2e_asset_library
      COMMAND desktop_wayland_e2e_test)
    set_tests_properties(desktop_wayland_e2e_asset_library PROPERTIES
      ENVIRONMENT "GLDOZE_E2E_ASSET_LIBRARY=1")
    find_program(GLDOZE_GNOME_CALCULATOR_EXECUTABLE gnome-calculator)
    find_program(GLDOZE_DBUS_RUN_SESSION_EXECUTABLE dbus-run-session)
    if(GLDOZE_GNOME_CALCULATOR_EXECUTABLE AND
        GLDOZE_DBUS_RUN_SESSION_EXECUTABLE)
      add_test(NAME desktop_wayland_e2e_calculator
        COMMAND desktop_wayland_e2e_test)
      set_tests_properties(desktop_wayland_e2e_calculator PROPERTIES
        ENVIRONMENT "GLDOZE_E2E_CALCULATOR=1"
        TIMEOUT 20)
    endif()
  endif()

  if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    add_executable(gldoze_filesystem_helper_test
      tests/gldoze_filesystem_helper_test.cpp
      ${GLDOZE_REPO_ROOT}/glcommanderprivileged.cpp)
    target_include_directories(gldoze_filesystem_helper_test PRIVATE ${GLDOZE_REPO_ROOT})
    target_link_libraries(gldoze_filesystem_helper_test PRIVATE gldoze_project_options)
    target_compile_options(gldoze_filesystem_helper_test PRIVATE
      "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
    gldoze_apply_dev_warnings(gldoze_filesystem_helper_test)
    add_test(NAME gldoze_filesystem_helper COMMAND gldoze_filesystem_helper_test)

    add_executable(gldoze_cpu_power_helper_protocol_test
      tests/gldoze_cpu_power_helper_protocol_test.cpp)
    target_link_libraries(gldoze_cpu_power_helper_protocol_test PRIVATE gldoze_project_options)
    gldoze_apply_dev_warnings(gldoze_cpu_power_helper_protocol_test)
    add_dependencies(gldoze_cpu_power_helper_protocol_test gldoze_cpu_power_helper)
    add_test(NAME gldoze_cpu_power_helper_protocol
      COMMAND gldoze_cpu_power_helper_protocol_test
        $<TARGET_FILE:gldoze_cpu_power_helper>)
  endif()

  add_executable(gltaskman_model_test tests/gltaskman_model_test.cpp)
  target_link_libraries(gltaskman_model_test PRIVATE gldoze_gltaskman)
  add_test(NAME gltaskman_model COMMAND gltaskman_model_test)

  add_executable(gltaskman_repository_test tests/gltaskman_repository_test.cpp)
  target_link_libraries(gltaskman_repository_test PRIVATE gldoze_gltaskman)
  add_test(NAME gltaskman_repository COMMAND gltaskman_repository_test)

  add_executable(gltaskman_service_test tests/gltaskman_service_test.cpp)
  target_link_libraries(gltaskman_service_test PRIVATE gldoze_gltaskman)
  add_test(NAME gltaskman_service COMMAND gltaskman_service_test)

  add_executable(gldream_service_test tests/gldream_service_test.cpp)
  target_link_libraries(gldream_service_test PRIVATE gldoze_gldream)
  add_test(NAME gldream_service COMMAND gldream_service_test)

  add_executable(gldream_platform_test tests/gldream_platform_test.cpp)
  target_link_libraries(gldream_platform_test PRIVATE gldoze_gldream)
  if(GLDOZE_ENABLE_X11 AND UNIX AND NOT APPLE)
    target_compile_definitions(gldream_platform_test PRIVATE GLDOZE_TEST_GLDREAM_X11=1)
  endif()
  add_test(NAME gldream_platform COMMAND gldream_platform_test)

  add_executable(cpu_performance_manager_test tests/cpu_performance_manager_test.cpp)
  target_link_libraries(cpu_performance_manager_test PRIVATE gldoze_desktop_cpu_performance)
  add_test(NAME cpu_performance_manager COMMAND cpu_performance_manager_test)

  add_executable(gldoze_statusbar_test tests/gldoze_statusbar_test.cpp)
  target_link_libraries(gldoze_statusbar_test PRIVATE gldoze_engine)
  add_test(NAME gldoze_statusbar COMMAND gldoze_statusbar_test)

  add_test(NAME desktop_no_native_gldeck_ui
    COMMAND ${CMAKE_COMMAND}
      -DGLDOZE_DESKTOP_EXECUTABLE=$<TARGET_FILE:gldoze_desktop>
      -DGLDOZE_NM_EXECUTABLE=${CMAKE_NM}
      -P ${CMAKE_CURRENT_LIST_DIR}/tests/verify_no_native_gldeck_ui.cmake
  )

  add_executable(audio_cd_ripper_service_test tests/audio_cd_ripper_service_test.cpp)
  target_link_libraries(audio_cd_ripper_service_test PRIVATE gldoze_foundation)
  add_test(NAME audio_cd_ripper_service COMMAND audio_cd_ripper_service_test)

  add_executable(desktop_filesystem_service_test tests/desktop_filesystem_service_test.cpp)
  target_link_libraries(desktop_filesystem_service_test PRIVATE gldoze_desktop_filesystem)
  add_test(NAME desktop_filesystem_service COMMAND desktop_filesystem_service_test)

  add_executable(glcommander_remote_test tests/glcommander_remote_test.cpp)
  target_link_libraries(glcommander_remote_test PRIVATE gldoze_engine)
  add_test(NAME glcommander_remote COMMAND glcommander_remote_test)

  add_executable(desktop_application_preferences_test tests/desktop_application_preferences_test.cpp)
  target_link_libraries(desktop_application_preferences_test PRIVATE gldoze_desktop_preferences)
  add_test(NAME desktop_application_preferences COMMAND desktop_application_preferences_test)

  add_executable(desktop_application_documents_test tests/desktop_application_documents_test.cpp)
  target_link_libraries(desktop_application_documents_test PRIVATE gldoze_desktop_documents)
  add_test(NAME desktop_application_documents COMMAND desktop_application_documents_test)
  add_executable(desktop_audio_document_service_test tests/desktop_audio_document_service_test.cpp)
  target_link_libraries(desktop_audio_document_service_test PRIVATE gldoze_desktop_audio_documents)
  add_test(NAME desktop_audio_document_service COMMAND desktop_audio_document_service_test)

  add_executable(desktop_gallery_scene_service_test tests/desktop_gallery_scene_service_test.cpp)
  target_link_libraries(desktop_gallery_scene_service_test PRIVATE gldoze_desktop_gallery_scenes)
  add_test(NAME desktop_gallery_scene_service COMMAND desktop_gallery_scene_service_test)

  add_executable(desktop_media_service_test tests/desktop_media_service_test.cpp)
  target_link_libraries(desktop_media_service_test PRIVATE gldoze_desktop_media)
  add_test(NAME desktop_media_service COMMAND desktop_media_service_test)
  add_executable(desktop_system_telemetry_service_test tests/desktop_system_telemetry_service_test.cpp)
  target_link_libraries(desktop_system_telemetry_service_test PRIVATE gldoze_desktop_system_telemetry)
  add_test(NAME desktop_system_telemetry_service COMMAND desktop_system_telemetry_service_test)

  add_executable(desktop_profiler_service_test tests/desktop_profiler_service_test.cpp)
  target_link_libraries(desktop_profiler_service_test PRIVATE gldoze_desktop_profiler)
  add_test(NAME desktop_profiler_service COMMAND desktop_profiler_service_test)

  add_executable(gpu_profiler_query_test tests/gpu_profiler_query_test.cpp)
  target_link_libraries(gpu_profiler_query_test PRIVATE
    gldoze_engine PkgConfig::SDL3)
  find_program(GLDOZE_PROFILER_XVFB_RUN xvfb-run)
  if(GLDOZE_PROFILER_XVFB_RUN)
    add_test(NAME gpu_profiler_query
      COMMAND ${GLDOZE_PROFILER_XVFB_RUN} -a
        $<TARGET_FILE:gpu_profiler_query_test>)
  else()
    add_test(NAME gpu_profiler_query COMMAND gpu_profiler_query_test)
  endif()

  add_executable(desktop_process_control_service_test tests/desktop_process_control_service_test.cpp)
  target_link_libraries(desktop_process_control_service_test PRIVATE gldoze_desktop_process_control)
  add_test(NAME desktop_process_control_service COMMAND desktop_process_control_service_test)

  add_executable(desktop_media_metadata_service_test tests/desktop_media_metadata_service_test.cpp)
  target_link_libraries(desktop_media_metadata_service_test PRIVATE gldoze_desktop_media_metadata)
  add_test(NAME desktop_media_metadata_service COMMAND desktop_media_metadata_service_test)

  add_executable(desktop_media_catalog_service_test tests/desktop_media_catalog_service_test.cpp)
  target_link_libraries(desktop_media_catalog_service_test PRIVATE gldoze_desktop_media_catalog)
  add_test(NAME desktop_media_catalog_service COMMAND desktop_media_catalog_service_test)

  add_executable(sdk_c_abi_test tests/sdk_c_abi_test.c)
  target_link_libraries(sdk_c_abi_test PRIVATE gldoze_sdk)
  add_test(NAME sdk_c_abi COMMAND sdk_c_abi_test)

  add_executable(desktop_credential_service_test
    tests/desktop_credential_service_test.cpp
    src/browser_credential_service.cpp
  )
  target_link_libraries(desktop_credential_service_test PRIVATE gldoze_desktop_credentials)
  add_test(NAME desktop_credential_service COMMAND desktop_credential_service_test)

  add_executable(map_preview_service_contract_test tests/map_preview_service_contract_test.cpp)
  target_include_directories(map_preview_service_contract_test PRIVATE ${GLDOZE_REPO_ROOT}/sdk/include)
  target_link_libraries(map_preview_service_contract_test PRIVATE gldoze_sdk)
  add_test(NAME map_preview_service_contract COMMAND map_preview_service_contract_test)

  add_executable(service_acquisition_test
    tests/service_acquisition_test.cpp
    src/desktop_service_registry.cpp
  )
  target_include_directories(service_acquisition_test PRIVATE
    ${CMAKE_CURRENT_LIST_DIR}/src
  )
  target_link_libraries(service_acquisition_test PRIVATE gldoze_sdk gldoze_desktop_credentials)
  add_test(NAME service_acquisition COMMAND service_acquisition_test)

  add_executable(capability_test
    tests/capability_test.cpp
  )
  target_link_libraries(capability_test PRIVATE gldoze_plugin_runtime)
  add_test(NAME capability COMMAND capability_test)

  add_executable(plugin_capability_enforcement_test
    tests/plugin_capability_enforcement_test.cpp
    src/desktop_service_registry.cpp
  )
  target_include_directories(plugin_capability_enforcement_test PRIVATE
    ${CMAKE_CURRENT_LIST_DIR}/src
  )
  target_link_libraries(plugin_capability_enforcement_test PRIVATE gldoze_sdk gldoze_plugin_runtime gldoze_desktop_credentials)
  add_test(NAME plugin_capability_enforcement COMMAND plugin_capability_enforcement_test)

  add_executable(plugin_callback_boundary_test
    tests/plugin_callback_boundary_test.cpp
  )
  target_link_libraries(plugin_callback_boundary_test PRIVATE gldoze_plugin_runtime)
  add_test(NAME plugin_callback_boundary COMMAND plugin_callback_boundary_test)

  set(_gldoze_host_boundary_fixture_dir
    "${CMAKE_CURRENT_BINARY_DIR}/test-apps/org.gldoze.callback-boundary")
  add_library(gldoze_plugin_host_boundary_fixture MODULE
    tests/plugin_host_boundary_fixture.cpp)
  target_link_libraries(gldoze_plugin_host_boundary_fixture PRIVATE gldoze_sdk)
  set_target_properties(gldoze_plugin_host_boundary_fixture PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${_gldoze_host_boundary_fixture_dir}"
    PREFIX "lib"
    OUTPUT_NAME "gldoze_plugin_host_boundary_fixture")
  file(MAKE_DIRECTORY "${_gldoze_host_boundary_fixture_dir}")
  configure_file(tests/plugin_host_boundary_fixture.app.json.in
    "${_gldoze_host_boundary_fixture_dir}/app.json" @ONLY)

  add_executable(desktop_plugin_host_boundary_test
    tests/desktop_plugin_host_boundary_test.cpp
    src/app_factory.cpp
    src/credential_worker.cpp)
  target_link_libraries(desktop_plugin_host_boundary_test PRIVATE
    gldoze_desktop_support ${CMAKE_DL_LIBS})
  add_dependencies(desktop_plugin_host_boundary_test
    gldoze_plugin_host_boundary_fixture)
  add_test(NAME desktop_plugin_host_boundary
    COMMAND desktop_plugin_host_boundary_test
      "${_gldoze_host_boundary_fixture_dir}/app.json")

  add_executable(credential_log_scan_test tests/credential_log_scan_test.cpp)
  add_test(NAME credential_log_scan COMMAND credential_log_scan_test
    "${CMAKE_CURRENT_LIST_DIR}/src")

  add_executable(browser_credential_flow_test
    tests/browser_credential_flow_test.cpp
    src/browser_credential_service.cpp
    src/browser_credential_helper.cpp
    src/browser_data_store.cpp
    src/browser_navigation.cpp
  )
  target_include_directories(browser_credential_flow_test PRIVATE
    ${CMAKE_CURRENT_LIST_DIR}/src
    ${GLDOZE_REPO_ROOT}
  )
  target_link_libraries(browser_credential_flow_test PRIVATE
    gldoze_desktop_credentials gldoze_engine)
  add_test(NAME browser_credential_flow COMMAND browser_credential_flow_test)

  add_executable(browser_window_ui_contract_test
    tests/browser_window_ui_contract_test.cpp
    src/browser_credential_service.cpp
    src/browser_data_store.cpp
    src/browser_navigation.cpp
  )
  target_include_directories(browser_window_ui_contract_test PRIVATE
    ${CMAKE_CURRENT_LIST_DIR}/src
    ${GLDOZE_REPO_ROOT}
  )
  target_link_libraries(browser_window_ui_contract_test PRIVATE
    gldoze_desktop_credentials gldoze_engine)
  add_test(NAME browser_window_ui_contract COMMAND browser_window_ui_contract_test
    "${CMAKE_CURRENT_LIST_DIR}/src/browser_window.cpp"
    "${CMAKE_CURRENT_LIST_DIR}/src/browser_application.cpp"
    "${GLDOZE_REPO_ROOT}/glcontextmenu.cpp"
    "${CMAKE_CURRENT_LIST_DIR}/src/browser_accelerated_osr.cpp"
    "${CMAKE_CURRENT_LIST_DIR}/src/cef_credential_render_handler.cpp"
    "${CMAKE_CURRENT_LIST_DIR}/src/browser_surface.cpp"
    "${CMAKE_CURRENT_LIST_DIR}/src/cef_subprocess_main.cpp")

  add_executable(render_abi_test tests/render_abi_test.c)
  target_link_libraries(render_abi_test PRIVATE gldoze_sdk)
  add_test(NAME render_abi COMMAND render_abi_test)

  add_executable(gldeck_render_abi_plugin_test
    tests/gldeck_render_abi_plugin_test.cpp)
  target_link_libraries(gldeck_render_abi_plugin_test PRIVATE gldoze_sdk ${CMAKE_DL_LIBS})
  target_compile_definitions(gldeck_render_abi_plugin_test PRIVATE
    GLDECK_PLUGIN_PATH="${CMAKE_BINARY_DIR}/apps/gldeck/libgldoze_gldeck.so")
  if(TARGET gldoze_gldeck)
    add_dependencies(gldeck_render_abi_plugin_test gldoze_gldeck)
  endif()
  add_test(NAME gldeck_render_abi_plugin COMMAND gldeck_render_abi_plugin_test)

  add_executable(render_device_registry_test tests/render_device_registry_test.cpp)
  target_link_libraries(render_device_registry_test PRIVATE gldoze_engine)
  add_test(NAME render_abi_device_registry COMMAND render_device_registry_test)

  add_executable(render_abi_integration_test tests/render_abi_integration_test.cpp)
  target_link_libraries(render_abi_integration_test PRIVATE gldoze_engine PkgConfig::SDL3)
  find_program(GLDOZE_XVFB_RUN_EXECUTABLE2 xvfb-run)

  add_executable(gldeck_render_abi_visual_test
    tests/gldeck_render_abi_visual_test.cpp)
  target_link_libraries(gldeck_render_abi_visual_test PRIVATE
    gldoze_engine gldoze_sdk PkgConfig::SDL3 ${CMAKE_DL_LIBS})
  target_compile_definitions(gldeck_render_abi_visual_test PRIVATE
    GLDECK_PLUGIN_PATH="${CMAKE_BINARY_DIR}/apps/gldeck/libgldoze_gldeck.so")
  if(TARGET gldoze_gldeck)
    add_dependencies(gldeck_render_abi_visual_test gldoze_gldeck)
  endif()
  if(GLDOZE_XVFB_RUN_EXECUTABLE2)
    add_test(NAME gldeck_render_abi_visual
      COMMAND ${GLDOZE_XVFB_RUN_EXECUTABLE2} -a
        $<TARGET_FILE:gldeck_render_abi_visual_test>)
  else()
    add_test(NAME gldeck_render_abi_visual
      COMMAND gldeck_render_abi_visual_test)
  endif()
  set_tests_properties(gldeck_render_abi_visual PROPERTIES
    WORKING_DIRECTORY "${GLDOZE_REPO_ROOT}")

  if(GLDOZE_XVFB_RUN_EXECUTABLE2)
    add_test(NAME render_abi_integration
      COMMAND ${GLDOZE_XVFB_RUN_EXECUTABLE2} -a $<TARGET_FILE:render_abi_integration_test>)
  else()
    add_test(NAME render_abi_integration COMMAND render_abi_integration_test)
  endif()

  # Standalone visual diagnostic. This is intentionally not registered with
  # CTest because it writes a PNG corpus and returns 2 when image pairs differ.
  add_executable(render_abi_texture_conformance_test
    tests/render_abi_texture_conformance_test.cpp)
  target_link_libraries(render_abi_texture_conformance_test PRIVATE
    gldoze_engine PkgConfig::SDL3 PkgConfig::SDL3_IMAGE)

  # Standalone visual diagnostic comparing the historical TechLobby GL3 map
  # preview with the current GL4.6 core texture/lighting path.
  add_executable(springmap_gl_version_conformance_test
    tests/springmap_gl_version_conformance_test.cpp
    ${GLDOZE_REPO_ROOT}/immediate_batch.cpp)
  target_link_libraries(springmap_gl_version_conformance_test PRIVATE
    gldoze_engine PkgConfig::SDL3 PkgConfig::SDL3_IMAGE)

  add_executable(core_render_smoke_test tests/core_render_smoke_test.cpp)
  target_link_libraries(core_render_smoke_test PRIVATE gldoze_engine PkgConfig::SDL3)
  if(GLDOZE_XVFB_RUN_EXECUTABLE2)
    add_test(NAME core_render_smoke
      COMMAND ${GLDOZE_XVFB_RUN_EXECUTABLE2} -a $<TARGET_FILE:core_render_smoke_test>)
  else()
    add_test(NAME core_render_smoke COMMAND core_render_smoke_test)
  endif()

  add_executable(render_activity_test tests/render_activity_test.cpp)
  target_include_directories(render_activity_test PRIVATE ${CMAKE_SOURCE_DIR})
  add_test(NAME render_activity COMMAND render_activity_test)

  add_executable(frame_rate_metric_test tests/frame_rate_metric_test.cpp)
  target_link_libraries(frame_rate_metric_test PRIVATE gldoze_project_options)
  add_test(NAME frame_rate_metric COMMAND frame_rate_metric_test)

  add_executable(gltop_gpu_metrics_test tests/gltop_gpu_metrics_test.cpp)
  target_link_libraries(gltop_gpu_metrics_test PRIVATE gldoze_project_options)
  add_test(NAME gltop_gpu_metrics COMMAND gltop_gpu_metrics_test)

  add_executable(gltop_refresh_policy_test tests/gltop_refresh_policy_test.cpp)
  target_include_directories(gltop_refresh_policy_test PRIVATE ${GLDOZE_REPO_ROOT})
  target_link_libraries(gltop_refresh_policy_test PRIVATE gldoze_project_options)
  add_test(NAME gltop_refresh_policy COMMAND gltop_refresh_policy_test)

  add_executable(glb_importer_parse_test
    tests/glb_importer_parse_test.cpp
    ${GLDOZE_REPO_ROOT}/glbimporter_parse.cpp
  )
  target_link_libraries(glb_importer_parse_test PRIVATE gldoze_project_options)
  gldoze_apply_dev_warnings(glb_importer_parse_test)
  add_test(NAME glb_importer_parse COMMAND glb_importer_parse_test)

  add_executable(glb_renderer_smoke_test tests/glb_renderer_smoke_test.cpp)
  target_link_libraries(glb_renderer_smoke_test PRIVATE gldoze_engine PkgConfig::SDL3)
  if(GLDOZE_ENABLE_X11 AND UNIX AND NOT APPLE)
    target_compile_definitions(glb_renderer_smoke_test PRIVATE GLDOZE_NATIVE_EGL_SMOKE=1)
  endif()
  if(GLDOZE_XVFB_RUN_EXECUTABLE2)
    add_test(NAME glb_renderer_smoke
      COMMAND ${GLDOZE_XVFB_RUN_EXECUTABLE2} -a $<TARGET_FILE:glb_renderer_smoke_test>)
  else()
    add_test(NAME glb_renderer_smoke COMMAND glb_renderer_smoke_test)
  endif()

  if(GLDOZE_ENABLE_WAYLAND AND TARGET PkgConfig::GLDOZE_GBM)
    add_executable(desktop_dmabuf_egl_smoke_test
      tests/desktop_dmabuf_egl_smoke_test.cpp)
    target_link_libraries(desktop_dmabuf_egl_smoke_test PRIVATE
      gldoze_external_deps PkgConfig::GLDOZE_GBM)
    add_test(NAME desktop_dmabuf_egl_smoke
      COMMAND desktop_dmabuf_egl_smoke_test)

    add_executable(desktop_prime_dmabuf_bridge_smoke_test
      tests/desktop_prime_dmabuf_bridge_smoke_test.cpp)
    target_link_libraries(desktop_prime_dmabuf_bridge_smoke_test PRIVATE
      gldoze_external_deps)
    add_test(NAME desktop_prime_dmabuf_bridge_smoke
      COMMAND desktop_prime_dmabuf_bridge_smoke_test)

    add_executable(wayland_gpu_selection_contract_test
      tests/wayland_gpu_selection_contract_test.cpp)
    target_link_libraries(wayland_gpu_selection_contract_test PRIVATE
      gldoze_project_options)
    add_test(NAME wayland_gpu_selection_contract
      COMMAND wayland_gpu_selection_contract_test
        "${GLDOZE_REPO_ROOT}/coresdl.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/src/desktop_wayland_backend.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/src/desktop_wayland_scene_shim.c")
  endif()

  add_executable(desktop_file_list_bridge_test
    tests/desktop_file_list_bridge_test.cpp src/desktop_file_list_bridge.cpp)
  target_include_directories(desktop_file_list_bridge_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
  target_link_libraries(desktop_file_list_bridge_test PRIVATE gldoze_engine gldoze_sdk)
  add_test(NAME desktop_file_list_bridge COMMAND desktop_file_list_bridge_test)

  set(_gldoze_plugin_fixture_dir
    "${CMAKE_CURRENT_BINARY_DIR}/test-apps/org.gldoze.test-plugin")
  add_library(gldoze_test_plugin MODULE tests/plugin_fixture.cpp)
  target_link_libraries(gldoze_test_plugin PRIVATE gldoze_sdk)
  set_target_properties(gldoze_test_plugin PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${_gldoze_plugin_fixture_dir}"
    PREFIX "lib"
    OUTPUT_NAME "gldoze_test_plugin"
  )
  file(MAKE_DIRECTORY "${_gldoze_plugin_fixture_dir}")
  configure_file(tests/plugin_fixture.app.json.in
    "${_gldoze_plugin_fixture_dir}/app.json" @ONLY)

  # ABI 0.50 compatibility fixture
  set(_gldoze_v50_fixture_dir
    "${CMAKE_CURRENT_BINARY_DIR}/test-apps/org.gldoze.test-v50")
  add_library(gldoze_test_v50 MODULE tests/plugin_fixture_v50.cpp)
  target_link_libraries(gldoze_test_v50 PRIVATE gldoze_sdk)
  set_target_properties(gldoze_test_v50 PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${_gldoze_v50_fixture_dir}"
    PREFIX "lib"
    OUTPUT_NAME "gldoze_test_v50"
  )
  file(MAKE_DIRECTORY "${_gldoze_v50_fixture_dir}")
  configure_file(tests/plugin_fixture_v50.app.json.in
    "${_gldoze_v50_fixture_dir}/app.json" @ONLY)

  # ABI 0.52 rejection fixture
  set(_gldoze_v52_fixture_dir
    "${CMAKE_CURRENT_BINARY_DIR}/test-apps/org.gldoze.test-v52")
  add_library(gldoze_test_v52 MODULE tests/plugin_fixture_v52.cpp)
  target_link_libraries(gldoze_test_v52 PRIVATE gldoze_sdk)
  set_target_properties(gldoze_test_v52 PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${_gldoze_v52_fixture_dir}"
    PREFIX "lib"
    OUTPUT_NAME "gldoze_test_v52"
  )
  file(MAKE_DIRECTORY "${_gldoze_v52_fixture_dir}")
  configure_file(tests/plugin_fixture_v52.app.json.in
    "${_gldoze_v52_fixture_dir}/app.json" @ONLY)

  # ABI 0.54 compatibility fixture (healthy pre-0.55, no credential callbacks)
  set(_gldoze_v54_fixture_dir
    "${CMAKE_CURRENT_BINARY_DIR}/test-apps/org.gldoze.test-v54")
  add_library(gldoze_test_v54 MODULE tests/plugin_fixture_v54.cpp)
  target_link_libraries(gldoze_test_v54 PRIVATE gldoze_sdk)
  set_target_properties(gldoze_test_v54 PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${_gldoze_v54_fixture_dir}"
    PREFIX "lib"
    OUTPUT_NAME "gldoze_test_v54"
  )
  file(MAKE_DIRECTORY "${_gldoze_v54_fixture_dir}")
  configure_file(tests/plugin_fixture_v54.app.json.in
    "${_gldoze_v54_fixture_dir}/app.json" @ONLY)

  add_executable(plugin_loader_test tests/plugin_loader_test.cpp)
  target_link_libraries(plugin_loader_test PRIVATE gldoze_plugin_runtime)
  add_dependencies(plugin_loader_test gldoze_test_plugin gldoze_test_v50 gldoze_test_v52 gldoze_test_v54 gldoze_test_v56)
  add_test(NAME plugin_loader COMMAND plugin_loader_test
    "${CMAKE_CURRENT_BINARY_DIR}/test-apps")

  # ABI 0.56 compatibility fixture
  set(_gldoze_v56_fixture_dir
    "${CMAKE_CURRENT_BINARY_DIR}/test-apps/org.gldoze.test-v56")
  add_library(gldoze_test_v56 MODULE tests/plugin_fixture_v56.cpp)
  target_link_libraries(gldoze_test_v56 PRIVATE gldoze_sdk)
  set_target_properties(gldoze_test_v56 PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${_gldoze_v56_fixture_dir}"
    PREFIX "lib"
    OUTPUT_NAME "gldoze_test_v56"
  )
  file(MAKE_DIRECTORY "${_gldoze_v56_fixture_dir}")
  configure_file(tests/plugin_fixture_v56.app.json.in
    "${_gldoze_v56_fixture_dir}/app.json" @ONLY)

  if(TARGET gldoze_image_viewer)
    set(_gldoze_image_viewer_fixture_dir "${CMAKE_CURRENT_BINARY_DIR}/image-viewer-fixtures")
    file(MAKE_DIRECTORY "${_gldoze_image_viewer_fixture_dir}")
    configure_file("${GLDOZE_REPO_ROOT}/assets/window2_image_button.jpg"
      "${_gldoze_image_viewer_fixture_dir}/a.jpg" COPYONLY)
    configure_file("${GLDOZE_REPO_ROOT}/assets/window2_image_button.jpg"
      "${_gldoze_image_viewer_fixture_dir}/b.jpg" COPYONLY)
    add_executable(image_viewer_plugin_test tests/image_viewer_plugin_test.cpp)
    target_link_libraries(image_viewer_plugin_test PRIVATE gldoze_plugin_runtime)
    add_dependencies(image_viewer_plugin_test gldoze_image_viewer)
    add_test(NAME image_viewer_plugin COMMAND image_viewer_plugin_test
      "${CMAKE_BINARY_DIR}/apps" "${_gldoze_image_viewer_fixture_dir}")
  endif()

  if(TARGET gldoze_logs)
    add_executable(logs_plugin_test tests/logs_plugin_test.cpp)
    target_link_libraries(logs_plugin_test PRIVATE gldoze_plugin_runtime)
    add_dependencies(logs_plugin_test gldoze_logs)
    add_test(NAME logs_plugin COMMAND logs_plugin_test "${CMAKE_BINARY_DIR}/apps")
  endif()

  if(TARGET gldoze_keys)
    add_executable(keys_plugin_test tests/keys_plugin_test.cpp)
    target_link_libraries(keys_plugin_test PRIVATE gldoze_plugin_runtime)
    add_dependencies(keys_plugin_test gldoze_keys)
    add_test(NAME keys_plugin COMMAND keys_plugin_test "${CMAKE_BINARY_DIR}/apps")
  endif()

  if(TARGET gldoze_terminal)
    add_executable(terminal_plugin_test tests/terminal_plugin_test.cpp)
    target_link_libraries(terminal_plugin_test PRIVATE gldoze_plugin_runtime)
    add_dependencies(terminal_plugin_test gldoze_terminal)
    add_test(NAME terminal_plugin COMMAND terminal_plugin_test "${CMAKE_BINARY_DIR}/apps")
  endif()

  if(TARGET gldoze_gledit)
    add_executable(gledit_plugin_test tests/gledit_plugin_test.cpp)
    target_link_libraries(gledit_plugin_test PRIVATE gldoze_plugin_runtime)
    add_dependencies(gledit_plugin_test gldoze_gledit)
    add_test(NAME gledit_plugin COMMAND gledit_plugin_test "${CMAKE_BINARY_DIR}/apps")
  endif()

  add_executable(desktop_registry_test tests/desktop_registry_test.cpp src/desktop_registry.cpp)
  target_link_libraries(desktop_registry_test PRIVATE gldoze_plugin_runtime)
  target_compile_options(desktop_registry_test PRIVATE
    "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
  target_compile_definitions(desktop_registry_test PRIVATE
    GLDOZE_NATIVE_GLDECK_ICON="${GLDOZE_REPO_ROOT}/assets/desktop/icons/gldeck.svg")
  if(TARGET gldoze_fps_meter)
    add_dependencies(desktop_registry_test gldoze_fps_meter)
  endif()
  if(TARGET gldoze_color_picker)
    add_dependencies(desktop_registry_test gldoze_color_picker)
  endif()
  if(TARGET gldoze_glpowerforge)
	add_dependencies(desktop_registry_test gldoze_glpowerforge)
  endif()
  if(TARGET gldoze_image_viewer)
    add_dependencies(desktop_registry_test gldoze_image_viewer)
  endif()
  if(TARGET gldoze_logs)
    add_dependencies(desktop_registry_test gldoze_logs)
  endif()
  if(TARGET gldoze_keys)
    add_dependencies(desktop_registry_test gldoze_keys)
  endif()
  if(TARGET gldoze_terminal)
    add_dependencies(desktop_registry_test gldoze_terminal)
  endif()
  if(TARGET gldoze_gledit)
    add_dependencies(desktop_registry_test gldoze_gledit)
  endif()
  if(TARGET gldoze_gldeck)
    add_dependencies(desktop_registry_test gldoze_gldeck)
  endif()
  if(TARGET gldoze_files)
    add_dependencies(desktop_registry_test gldoze_files)
  endif()
  if(TARGET gldoze_audio_cd_ripper_preview)
    add_dependencies(desktop_registry_test gldoze_audio_cd_ripper_preview)
  endif()
  if(TARGET gldoze_presentation_plugins)
    add_dependencies(desktop_registry_test gldoze_presentation_plugins)
  endif()
  if(TARGET verdant_gldoze_plugin)
    add_dependencies(desktop_registry_test verdant_gldoze_plugin)
  endif()
  target_include_directories(desktop_registry_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
  if(GLDOZE_ENABLE_CEF_BROWSER)
    target_compile_definitions(desktop_registry_test PRIVATE GLDOZE_ENABLE_CEF_BROWSER=1)
  endif()
  add_test(NAME desktop_registry COMMAND desktop_registry_test "${CMAKE_BINARY_DIR}/apps")

	add_executable(desktop_process_launcher_test
		tests/desktop_process_launcher_test.cpp
		src/desktop_process_launcher.cpp)
	target_include_directories(desktop_process_launcher_test PRIVATE
		${CMAKE_CURRENT_LIST_DIR}/src)
	target_compile_options(desktop_process_launcher_test PRIVATE
		"$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
	add_test(NAME desktop_process_launcher COMMAND desktop_process_launcher_test)

	add_executable(desktop_bar_window_policy_test
		tests/desktop_bar_window_policy_test.cpp
		src/desktop_bar_window_policy.cpp)
	target_include_directories(desktop_bar_window_policy_test PRIVATE
		${CMAKE_CURRENT_LIST_DIR}/src)
	target_compile_options(desktop_bar_window_policy_test PRIVATE
		"$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
	add_test(NAME desktop_bar_window_policy COMMAND desktop_bar_window_policy_test)

	add_executable(desktop_terminal_layout_test
    tests/desktop_terminal_layout_test.cpp
    ${GLDOZE_REPO_ROOT}/terminal_layout_math.cpp
  )
  target_include_directories(desktop_terminal_layout_test PRIVATE ${GLDOZE_REPO_ROOT})
	add_test(NAME desktop_terminal_layout COMMAND desktop_terminal_layout_test)

	add_executable(terminal_osc52_test tests/terminal_osc52_test.cpp)
	target_include_directories(terminal_osc52_test PRIVATE ${GLDOZE_REPO_ROOT})
	add_test(NAME terminal_osc52 COMMAND terminal_osc52_test)

	add_executable(desktop_platform_backend_test
		tests/desktop_platform_backend_test.cpp)
	target_link_libraries(desktop_platform_backend_test PRIVATE gldoze_desktop_core)
	target_compile_options(desktop_platform_backend_test PRIVATE
	  "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
	add_test(NAME desktop_platform_backend COMMAND desktop_platform_backend_test)

  if(TARGET glmail_support)
    add_executable(glmail_window_status_test
      ${GLDOZE_REPO_ROOT}/apps/mail/tests/window_status_test.cpp
      src/app_factory.cpp)
    target_link_libraries(glmail_window_status_test PRIVATE gldoze_desktop_support)
    if(TARGET gldoze_cef_browser)
      # Match the desktop executable's static-library ordering. The browser
      # target references credential services supplied by desktop support.
      target_link_libraries(glmail_window_status_test PRIVATE gldoze_cef_browser)
    endif()
    target_compile_options(glmail_window_status_test PRIVATE
      "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
    add_test(NAME glmail_window_status COMMAND glmail_window_status_test)
  endif()

  add_executable(desktop_settings_test tests/desktop_settings_test.cpp)
  target_link_libraries(desktop_settings_test PRIVATE gldoze_desktop_support)
  add_test(NAME desktop_settings COMMAND desktop_settings_test)

  add_executable(gldropdown_geometry_test tests/gldropdown_geometry_test.cpp)
  target_include_directories(gldropdown_geometry_test PRIVATE ${GLDOZE_REPO_ROOT})
  target_link_libraries(gldropdown_geometry_test PRIVATE gldoze_project_options)
  add_test(NAME gldropdown_geometry COMMAND gldropdown_geometry_test)

  add_executable(desktop_dropdown_terminal_test tests/desktop_dropdown_terminal_test.cpp)
  target_sources(desktop_dropdown_terminal_test PRIVATE src/desktop_dropdown_terminal_math.cpp)
  target_include_directories(desktop_dropdown_terminal_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
  target_link_libraries(desktop_dropdown_terminal_test PRIVATE gldoze_engine)
  add_test(NAME desktop_dropdown_terminal COMMAND desktop_dropdown_terminal_test)

  if(UNIX AND NOT APPLE)
    add_executable(desktop_command_channel_test
      tests/desktop_command_channel_test.cpp
      src/desktop_command_channel.cpp
      ${GLDOZE_REPO_ROOT}/app_paths.cpp)
    target_include_directories(desktop_command_channel_test PRIVATE
      ${CMAKE_CURRENT_LIST_DIR}/src ${GLDOZE_REPO_ROOT})
    target_compile_options(desktop_command_channel_test PRIVATE
      "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
    add_test(NAME desktop_command_channel COMMAND desktop_command_channel_test)

    add_executable(desktop_url_handler_test
      tests/desktop_url_handler_test.cpp
      src/desktop_command_channel.cpp
      ${GLDOZE_REPO_ROOT}/app_paths.cpp)
    target_include_directories(desktop_url_handler_test PRIVATE
      ${CMAKE_CURRENT_LIST_DIR}/src ${GLDOZE_REPO_ROOT})
    target_compile_options(desktop_url_handler_test PRIVATE
      "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
    add_test(NAME desktop_url_handler COMMAND desktop_url_handler_test
      "$<TARGET_FILE:gldoze_desktop>"
      "${CMAKE_CURRENT_BINARY_DIR}/gldoze-browser.desktop"
      "${CMAKE_INSTALL_FULL_BINDIR}/gldoze_desktop")
  endif()

  add_executable(desktop_overview_test tests/desktop_overview_test.cpp src/desktop_overview_math.cpp)
  target_include_directories(desktop_overview_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src ${GLDOZE_REPO_ROOT})
  add_test(NAME desktop_overview COMMAND desktop_overview_test)

  add_executable(desktop_window_rules_test tests/desktop_window_rules_test.cpp src/desktop_window_rules_match.cpp)
  target_include_directories(desktop_window_rules_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src ${GLDOZE_REPO_ROOT})
  add_test(NAME desktop_window_rules COMMAND desktop_window_rules_test)

  add_executable(desktop_category_icons_test tests/desktop_category_icons_test.cpp)
  target_link_libraries(desktop_category_icons_test PRIVATE gldoze_engine)
  target_compile_definitions(desktop_category_icons_test PRIVATE
    GLDOZE_DESKTOP_CATEGORY_ICON_DIR="${GLDOZE_REPO_ROOT}/assets/desktop/icons/categories"
  )
  add_test(NAME desktop_category_icons COMMAND desktop_category_icons_test)

  add_executable(window_events_test tests/window_events_test.cpp ${GLDOZE_REPO_ROOT}/window_events.cpp)
  target_include_directories(window_events_test PRIVATE ${GLDOZE_REPO_ROOT})
  add_test(NAME window_events COMMAND window_events_test)

  add_executable(desktop_ui_zoom_math_test tests/desktop_ui_zoom_math_test.cpp)
  target_include_directories(desktop_ui_zoom_math_test PRIVATE ${GLDOZE_REPO_ROOT})
  add_test(NAME desktop_ui_zoom_math COMMAND desktop_ui_zoom_math_test)

  add_executable(mouse_wheel_focus_test tests/mouse_wheel_focus_test.cpp)
  add_test(NAME mouse_wheel_focus
    COMMAND mouse_wheel_focus_test
      "${GLDOZE_REPO_ROOT}/mouse.cpp"
      "${GLDOZE_REPO_ROOT}/gldoze_window_events.cpp"
      "${CMAKE_CURRENT_LIST_DIR}/src/desktop_shell.cpp"
      "${GLDOZE_REPO_ROOT}/gldoze_input.cpp")

  add_executable(techlobby_map_damage_test
    tests/techlobby_map_damage_test.cpp)
  add_test(NAME techlobby_map_damage
    COMMAND techlobby_map_damage_test
      "${GLDOZE_REPO_ROOT}/springlobbywindow.cpp")

  add_executable(techlobby_chat_damage_test
    tests/techlobby_chat_damage_test.cpp)
  add_test(NAME techlobby_chat_damage
    COMMAND techlobby_chat_damage_test
      "${GLDOZE_REPO_ROOT}/springlobbywindow.cpp")

  add_executable(techlobby_chat_scroll_test
    tests/techlobby_chat_scroll_test.cpp)
  target_include_directories(techlobby_chat_scroll_test PRIVATE
    "${GLDOZE_REPO_ROOT}")
  add_test(NAME techlobby_chat_scroll
    COMMAND techlobby_chat_scroll_test)

  add_executable(desktop_clipboard_sdl_test
    tests/desktop_clipboard_sdl_test.cpp
    ${GLDOZE_REPO_ROOT}/desktop_clipboard.cpp
  )
  target_include_directories(desktop_clipboard_sdl_test PRIVATE
    ${GLDOZE_REPO_ROOT})
  target_link_libraries(desktop_clipboard_sdl_test PRIVATE
    PkgConfig::SDL3
    Threads::Threads
  )
  target_compile_options(desktop_clipboard_sdl_test PRIVATE
    "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
  find_program(GLDOZE_XVFB_RUN_EXECUTABLE xvfb-run)
  if(GLDOZE_XVFB_RUN_EXECUTABLE)
    add_test(NAME desktop_clipboard_sdl
      COMMAND ${GLDOZE_XVFB_RUN_EXECUTABLE} -a
        $<TARGET_FILE:desktop_clipboard_sdl_test>)
  else()
    add_test(NAME desktop_clipboard_sdl
      COMMAND desktop_clipboard_sdl_test)
  endif()

	if(GLDOZE_ENABLE_X11 AND UNIX AND NOT APPLE)
	  add_executable(desktop_x11_window_manager_test tests/desktop_x11_window_manager_test.cpp)
	  target_link_libraries(desktop_x11_window_manager_test PRIVATE gldoze_desktop_support)
	  add_test(NAME desktop_x11_window_manager COMMAND desktop_x11_window_manager_test)
	  add_executable(desktop_global_shortcut_test tests/desktop_global_shortcut_test.cpp)
	  target_link_libraries(desktop_global_shortcut_test PRIVATE gldoze_desktop_support X11::Xtst)
	  add_test(NAME desktop_global_shortcut COMMAND ${GLDOZE_XVFB_RUN_EXECUTABLE} -a
	    $<TARGET_FILE:desktop_global_shortcut_test>)

    add_executable(popup_surface_test
      tests/popup_surface_test.cpp
      ${GLDOZE_REPO_ROOT}/popup_surface.cpp
    )
    target_include_directories(popup_surface_test PRIVATE ${GLDOZE_REPO_ROOT})
    target_link_libraries(popup_surface_test PRIVATE
      PkgConfig::SDL3
      X11::X11
      PkgConfig::XFT
    )
    target_compile_definitions(popup_surface_test PRIVATE GLDOZE_DESKTOP_X11_EMBED=1)
    if(TARGET X11::Xrandr)
      target_link_libraries(popup_surface_test PRIVATE X11::Xrandr)
      target_compile_definitions(popup_surface_test PRIVATE GLDOZE_DESKTOP_XRANDR=1)
    endif()
    target_compile_options(popup_surface_test PRIVATE
      "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
    find_program(GLDOZE_XVFB_RUN_EXECUTABLE xvfb-run)
    if(GLDOZE_XVFB_RUN_EXECUTABLE)
      add_test(NAME popup_surface
        COMMAND ${GLDOZE_XVFB_RUN_EXECUTABLE} -a $<TARGET_FILE:popup_surface_test>)
    endif()

    add_executable(desktop_x11_surface_input_test
      tests/desktop_x11_surface_input_test.cpp
      ${GLDOZE_REPO_ROOT}/x11_surface.cpp
    )
    target_include_directories(desktop_x11_surface_input_test PRIVATE
      ${GLDOZE_REPO_ROOT})
    target_link_libraries(desktop_x11_surface_input_test PRIVATE
      PkgConfig::SDL3
      OpenGL::GL
      X11::X11
    )
    target_compile_definitions(desktop_x11_surface_input_test PRIVATE
      GLDOZE_DESKTOP_X11_EMBED=1)
    target_compile_options(desktop_x11_surface_input_test PRIVATE
      "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
    if(GLDOZE_XVFB_RUN_EXECUTABLE)
      add_test(NAME desktop_x11_surface_input
        COMMAND ${GLDOZE_XVFB_RUN_EXECUTABLE} -a
          $<TARGET_FILE:desktop_x11_surface_input_test>)
    endif()

    add_executable(desktop_clipboard_x11_test
      tests/desktop_clipboard_x11_test.cpp
      ${GLDOZE_REPO_ROOT}/desktop_clipboard.cpp
      ${GLDOZE_REPO_ROOT}/x11_clipboard.cpp
    )
    target_include_directories(desktop_clipboard_x11_test PRIVATE
      ${GLDOZE_REPO_ROOT})
    target_link_libraries(desktop_clipboard_x11_test PRIVATE
      PkgConfig::SDL3
      X11::X11
      Threads::Threads
      OpenGL::GL
    )
    target_compile_definitions(desktop_clipboard_x11_test PRIVATE
      GLDOZE_CLIPBOARD_X11=1)
    target_compile_options(desktop_clipboard_x11_test PRIVATE
      "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
    if(GLDOZE_XVFB_RUN_EXECUTABLE)
      add_test(NAME desktop_clipboard_x11
        COMMAND ${GLDOZE_XVFB_RUN_EXECUTABLE} -a
          $<TARGET_FILE:desktop_clipboard_x11_test>)
    endif()

	add_executable(browser_native_surface_test
	  tests/browser_native_surface_test.cpp
	  src/browser_x11_host.cpp
	)
	target_include_directories(browser_native_surface_test PRIVATE
	  ${CMAKE_CURRENT_LIST_DIR}/src
	  ${GLDOZE_REPO_ROOT}
	)
	target_link_libraries(browser_native_surface_test PRIVATE
	  PkgConfig::SDL3
	  X11::X11
	  X11::Xext
	)
	target_compile_options(browser_native_surface_test PRIVATE
	  "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
	if(GLDOZE_XVFB_RUN_EXECUTABLE)
	  add_test(NAME browser_native_surface
	    COMMAND ${GLDOZE_XVFB_RUN_EXECUTABLE} -a
	      $<TARGET_FILE:browser_native_surface_test>)
	endif()
  endif()

  if(GLDOZE_ENABLE_CEF_BROWSER)
	add_executable(browser_adblock_test
	  tests/browser_adblock_test.cpp
	  src/browser_adblock.cpp
	  src/content_filter.cpp)
	target_include_directories(browser_adblock_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
	target_compile_options(browser_adblock_test PRIVATE
	  "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
	add_test(NAME browser_adblock COMMAND browser_adblock_test)

	add_executable(content_filter_test
	  tests/content_filter_test.cpp
	  src/content_filter.cpp
	  src/content_filter_service.cpp
	  src/browser_adblock.cpp
	  src/content_filter_scriptlet_registry.cpp
	  src/youtube_content_filter_module.cpp)
	target_include_directories(content_filter_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
	target_compile_definitions(content_filter_test PRIVATE
	  GLDOZE_CONTENT_FILTER_FIXTURE_DIR="${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/content_filter")
	target_compile_options(content_filter_test PRIVATE
	  "$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-UNDEBUG>")
	add_test(NAME content_filter COMMAND content_filter_test)

	add_executable(browser_input_test
	  tests/browser_input_test.cpp
	  src/browser_input.cpp
	)
	target_include_directories(browser_input_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
	target_link_libraries(browser_input_test PRIVATE PkgConfig::SDL3)
	add_test(NAME browser_input COMMAND browser_input_test)

	add_executable(browser_navigation_test
	  tests/browser_navigation_test.cpp
	  src/browser_navigation.cpp
	)
	target_include_directories(browser_navigation_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
	add_test(NAME browser_navigation COMMAND browser_navigation_test)

	add_executable(mail_resource_policy_test
	  tests/mail_resource_policy_test.cpp
	  src/mail_resource_policy.cpp
	)
	target_include_directories(mail_resource_policy_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
	add_test(NAME mail_resource_policy COMMAND mail_resource_policy_test)

	add_executable(browser_data_store_test
	  tests/browser_data_store_test.cpp
	  src/browser_data_store.cpp
	  src/browser_navigation.cpp
	)
	target_include_directories(browser_data_store_test PRIVATE
	  ${CMAKE_CURRENT_LIST_DIR}/src
	  ${GLDOZE_REPO_ROOT}
	)
	target_link_libraries(browser_data_store_test PRIVATE gldoze_engine)
	add_test(NAME browser_data_store COMMAND browser_data_store_test)

	add_executable(browser_data_importer_test
	  tests/browser_data_importer_test.cpp
	)
	target_include_directories(browser_data_importer_test PRIVATE
	  ${CMAKE_CURRENT_LIST_DIR}/src
	)
	target_link_libraries(browser_data_importer_test PRIVATE gldoze_desktop_browser_importer)
	if(TARGET PkgConfig::GLDOZE_DESKTOP_NSS)
	  target_compile_definitions(browser_data_importer_test PRIVATE GLDOZE_DESKTOP_HAS_NSS=1)
	endif()
	add_test(NAME browser_data_importer COMMAND browser_data_importer_test)

	    add_executable(browser_surface_test
	      tests/browser_surface_test.cpp
	      tests/browser_surface_test_app_factory.cpp
	      src/browser_accelerated_osr.cpp
	      src/browser_surface.cpp
    )
    target_include_directories(browser_surface_test PRIVATE
      ${CMAKE_CURRENT_LIST_DIR}/src
      ${GLDOZE_REPO_ROOT}
    )
	    # The engine's screenshot/recording hooks reference the concrete desktop
	    # app and media implementations even though this test only exercises the
	    # browser surface. Keep the test's static link closure complete.
	    target_link_libraries(browser_surface_test PRIVATE
	      gldoze_engine
	      gldoze_desktop_media
	      gldoze_desktop_support
	      PkgConfig::SDL3)
	    if(GLDOZE_CEF_ACCELERATED_OSR_AVAILABLE)
	      target_compile_definitions(browser_surface_test PRIVATE
	        GLDOZE_CEF_ACCELERATED_OSR_AVAILABLE=1)
	      target_link_libraries(browser_surface_test PRIVATE
	        PkgConfig::GLDOZE_CEF_OSR_EGL
	        PkgConfig::GLDOZE_CEF_OSR_XCB)
	    endif()
    add_test(NAME browser_surface COMMAND browser_surface_test)

	add_test(NAME cef_runtime_layout
	  COMMAND bash "${GLDOZE_REPO_ROOT}/scripts/verify_cef_runtime.sh"
	    "$<TARGET_FILE_DIR:gldoze_desktop>"
	)
  endif()
endif()
