Internal
Public Access
Implements RFC 6143's Tight encoding: a compression-control byte (low 4 bits reset one of 4 persistent zlib streams; high nibble selects Fill/JPEG/Basic mode) followed by Fill's 3-byte solid color, JPEG's compact-length-prefixed baseline JPEG covering the whole rectangle (decoded via libjpeg-turbo directly, not QImage's plugin, to avoid a packaging-dependent runtime failure mode), or Basic mode's compact-length-prefixed zlib payload plus a filter (Copy, Palette, or Gradient) applied after decompression. Unlike Hextile/ZRLE, Tight has no internal tiling -- one rectangle is one filtered/compressed unit. The three filters live in vnc_pixel_codecs.h/.cpp alongside the Hextile/ZRLE decoders. Adds find_package(JPEG REQUIRED) + JPEG::JPEG as a new build dependency (confirmed available via libjpeg-turbo on this dev machine). 5 new tests cover Fill, Basic+Copy, Basic+Palette, JPEG (round-tripped through a real libjpeg-turbo-encoded fixture, compared with tolerance since JPEG is lossy), and the stream-reset flag correctly tearing down and reinitializing a targeted stream rather than erroring on stale state. Known, documented gap: this decoder always treats Basic-mode payloads as zlib-compressed; the real protocol allows very small payloads to skip compression, which couldn't be verified with confidence against the RFC text alone and is narrow enough in practice (tiny solid areas are virtually always sent as Fill instead) to leave unhandled for now -- it fails that one rectangle's decode cleanly rather than misinterpreting it silently. The Gradient filter is implemented from the spec description but is the least exercised of the three in this pass. Live-verified against the TightVNC test server that nothing regressed; that server still consistently chose Raw for actual framebuffer content regardless of announced encodings, so Tight's live decode path isn't independently confirmed against a real server here either -- the unit tests are the primary evidence. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
304 lines
11 KiB
CMake
304 lines
11 KiB
CMake
cmake_minimum_required(VERSION 3.21)
|
|
|
|
project(OrbitHub VERSION 2026.9.15 LANGUAGES CXX)
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
|
|
set(CMAKE_AUTOMOC ON)
|
|
set(CMAKE_AUTOUIC ON)
|
|
set(CMAKE_AUTORCC ON)
|
|
|
|
include(GNUInstallDirs)
|
|
|
|
find_package(Qt6 6.2 REQUIRED COMPONENTS Widgets Sql Network)
|
|
find_package(OpenSSL REQUIRED)
|
|
find_package(ZLIB REQUIRED)
|
|
find_package(JPEG REQUIRED)
|
|
|
|
qt_standard_project_setup()
|
|
|
|
option(ORBITHUB_BUILD_TESTS "Build unit tests (requires Qt6::Test)" ON)
|
|
if(ORBITHUB_BUILD_TESTS)
|
|
find_package(Qt6 6.2 QUIET COMPONENTS Test)
|
|
if(TARGET Qt6::Test)
|
|
enable_testing()
|
|
else()
|
|
message(STATUS "Qt6::Test not found -- skipping unit tests (set ORBITHUB_BUILD_TESTS=OFF to silence this)")
|
|
set(ORBITHUB_BUILD_TESTS OFF)
|
|
endif()
|
|
endif()
|
|
|
|
add_subdirectory(third_party/KodoTerm)
|
|
|
|
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/FreeRDP/CMakeLists.txt")
|
|
message(FATAL_ERROR "Vendored FreeRDP source is missing at third_party/FreeRDP")
|
|
endif()
|
|
|
|
# Pin FreeRDP build to the vendored source tree so headers/libs are always from the same revision.
|
|
set(FREERDP_UNIFIED_BUILD ON CACHE BOOL "" FORCE)
|
|
set(WITH_MANPAGES OFF CACHE BOOL "" FORCE)
|
|
set(WITH_SAMPLE OFF CACHE BOOL "" FORCE)
|
|
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
|
set(BUILD_TESTING_INTERNAL OFF CACHE BOOL "" FORCE)
|
|
set(WITH_CLIENT_COMMON ON CACHE BOOL "" FORCE)
|
|
set(WITH_CLIENT OFF CACHE BOOL "" FORCE)
|
|
set(WITH_CLIENT_SDL OFF CACHE BOOL "" FORCE)
|
|
set(WITH_CLIENT_INTERFACE OFF CACHE BOOL "" FORCE)
|
|
set(WITH_SERVER OFF CACHE BOOL "" FORCE)
|
|
set(WITH_CHANNELS ON CACHE BOOL "" FORCE)
|
|
set(WITH_CLIENT_CHANNELS ON CACHE BOOL "" FORCE)
|
|
set(WITH_FUSE OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_DRDYNVC ON CACHE BOOL "" FORCE)
|
|
set(CHANNEL_DRDYNVC_CLIENT ON CACHE BOOL "" FORCE)
|
|
set(CHANNEL_DISP ON CACHE BOOL "" FORCE)
|
|
set(CHANNEL_DISP_CLIENT ON CACHE BOOL "" FORCE)
|
|
set(CHANNEL_AINPUT OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_AUDIN OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_CLIPRDR ON CACHE BOOL "" FORCE)
|
|
set(CHANNEL_CLIPRDR_CLIENT ON CACHE BOOL "" FORCE)
|
|
set(CHANNEL_DRIVE OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_ECHO OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_ENCOMSP OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_GEOMETRY OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_LOCATION OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_PARALLEL OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_PRINTER OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_RAIL OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_RDPDR OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_RDPEAR OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_RDPECAM OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_RDPEI OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_RDPEMSC OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_RDPGFX OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_RDPSND OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_REMDESK OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_SERIAL OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_SMARTCARD OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_SSHAGENT OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_TELEMETRY OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_URBDRC OFF CACHE BOOL "" FORCE)
|
|
set(CHANNEL_VIDEO OFF CACHE BOOL "" FORCE)
|
|
set(WITH_FFMPEG OFF CACHE BOOL "" FORCE)
|
|
set(WITH_DSP_FFMPEG OFF CACHE BOOL "" FORCE)
|
|
set(WITH_VIDEO_FFMPEG OFF CACHE BOOL "" FORCE)
|
|
set(WITH_CAIRO OFF CACHE BOOL "" FORCE)
|
|
set(WITH_SWSCALE OFF CACHE BOOL "" FORCE)
|
|
set(WITH_JPEG OFF CACHE BOOL "" FORCE)
|
|
set(WITH_KRB5 OFF CACHE BOOL "" FORCE)
|
|
set(WITH_UNICODE_BUILTIN ON CACHE BOOL "" FORCE)
|
|
set(WITH_WINPR_TOOLS OFF CACHE BOOL "" FORCE)
|
|
|
|
add_subdirectory(third_party/FreeRDP EXCLUDE_FROM_ALL)
|
|
|
|
set(ORBITHUB_SOURCES
|
|
src/about_dialog.cpp
|
|
src/about_dialog.h
|
|
src/user_guide_dialog.cpp
|
|
src/user_guide_dialog.h
|
|
docs/user_guide.qrc
|
|
src/app_icon.cpp
|
|
src/app_icon.h
|
|
src/main.cpp
|
|
src/mremoteng_importer.cpp
|
|
src/mremoteng_importer.h
|
|
src/profile_dialog.cpp
|
|
src/profile_dialog.h
|
|
src/profile_repository.cpp
|
|
src/profile_repository.h
|
|
src/profiles_tree_widget.cpp
|
|
src/profiles_tree_widget.h
|
|
src/profiles_window.cpp
|
|
src/profiles_window.h
|
|
src/session_backend.h
|
|
src/session_backend_factory.cpp
|
|
src/session_backend_factory.h
|
|
src/session_tab.cpp
|
|
src/session_tab.h
|
|
src/rdp_display_widget.cpp
|
|
src/rdp_display_widget.h
|
|
src/vnc_display_widget.cpp
|
|
src/vnc_display_widget.h
|
|
src/terminal_view.cpp
|
|
src/terminal_view.h
|
|
src/session_window.cpp
|
|
src/session_window.h
|
|
src/rdp_session_backend.cpp
|
|
src/rdp_session_backend.h
|
|
src/ssh_session_backend.cpp
|
|
src/ssh_session_backend.h
|
|
src/vnc_session_backend.cpp
|
|
src/vnc_session_backend.h
|
|
src/vnc_pixel_codecs.cpp
|
|
src/vnc_pixel_codecs.h
|
|
src/unsupported_session_backend.cpp
|
|
src/unsupported_session_backend.h
|
|
)
|
|
|
|
if(WIN32)
|
|
list(APPEND ORBITHUB_SOURCES packaging/windows/orbithub.rc)
|
|
endif()
|
|
|
|
if(APPLE)
|
|
list(APPEND ORBITHUB_SOURCES packaging/macos/orbithub.icns)
|
|
set_source_files_properties(packaging/macos/orbithub.icns PROPERTIES
|
|
MACOSX_PACKAGE_LOCATION "Resources"
|
|
)
|
|
set(MACOSX_BUNDLE_ICON_FILE orbithub.icns)
|
|
set(MACOSX_BUNDLE_BUNDLE_NAME "OrbitHub")
|
|
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.darksingularity.OrbitHub")
|
|
set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}")
|
|
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}")
|
|
endif()
|
|
|
|
add_executable(orbithub WIN32 MACOSX_BUNDLE ${ORBITHUB_SOURCES})
|
|
|
|
target_link_libraries(orbithub PRIVATE Qt6::Widgets Qt6::Sql Qt6::Network)
|
|
target_link_libraries(orbithub PRIVATE KodoTerm::KodoTerm)
|
|
target_link_libraries(orbithub PRIVATE OpenSSL::Crypto)
|
|
target_link_libraries(orbithub PRIVATE ZLIB::ZLIB)
|
|
target_link_libraries(orbithub PRIVATE JPEG::JPEG)
|
|
target_compile_definitions(orbithub PRIVATE ORBITHUB_VERSION_STRING="${PROJECT_VERSION}")
|
|
if(TARGET freerdp AND TARGET winpr)
|
|
target_compile_definitions(orbithub PRIVATE ORBITHUB_HAS_FREERDP)
|
|
target_include_directories(orbithub PRIVATE
|
|
${CMAKE_CURRENT_SOURCE_DIR}/third_party/FreeRDP/include
|
|
${CMAKE_CURRENT_SOURCE_DIR}/third_party/FreeRDP/winpr/include
|
|
${CMAKE_CURRENT_BINARY_DIR}/third_party/FreeRDP/include
|
|
${CMAKE_CURRENT_BINARY_DIR}/third_party/FreeRDP/winpr/include
|
|
)
|
|
target_link_libraries(orbithub PRIVATE freerdp winpr)
|
|
if(TARGET freerdp-client)
|
|
target_link_libraries(orbithub PRIVATE freerdp-client)
|
|
endif()
|
|
else()
|
|
message(FATAL_ERROR "Vendored FreeRDP targets were not produced as expected.")
|
|
endif()
|
|
|
|
# Qt loads platform integration and SQL driver plugins dynamically at
|
|
# runtime (QFactoryLoader), so they never appear in orbithub.exe's import
|
|
# table. vcpkg's automatic DLL deployment only follows the import table, so
|
|
# these plugins have to be copied out explicitly or the app fails to start
|
|
# with "Could not find the Qt platform plugin" / "can not load requested
|
|
# driver 'QSQLITE'".
|
|
if(WIN32)
|
|
if(TARGET Qt6::QWindowsIntegrationPlugin)
|
|
add_custom_command(TARGET orbithub POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory
|
|
"$<TARGET_FILE_DIR:orbithub>/platforms"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"$<TARGET_FILE:Qt6::QWindowsIntegrationPlugin>"
|
|
"$<TARGET_FILE_DIR:orbithub>/platforms/"
|
|
COMMENT "Deploying Qt Windows platform plugin"
|
|
)
|
|
install(FILES "$<TARGET_FILE:Qt6::QWindowsIntegrationPlugin>"
|
|
DESTINATION "${CMAKE_INSTALL_BINDIR}/platforms"
|
|
)
|
|
endif()
|
|
|
|
if(TARGET Qt6::QSQLiteDriverPlugin)
|
|
add_custom_command(TARGET orbithub POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory
|
|
"$<TARGET_FILE_DIR:orbithub>/sqldrivers"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"$<TARGET_FILE:Qt6::QSQLiteDriverPlugin>"
|
|
"$<TARGET_FILE_DIR:orbithub>/sqldrivers/"
|
|
COMMENT "Deploying Qt SQLite driver plugin"
|
|
)
|
|
install(FILES "$<TARGET_FILE:Qt6::QSQLiteDriverPlugin>"
|
|
DESTINATION "${CMAKE_INSTALL_BINDIR}/sqldrivers"
|
|
)
|
|
|
|
# vcpkg's qtbase[sql-sqlite] links the plugin against vcpkg's own
|
|
# shared sqlite3 port rather than bundling SQLite into the plugin,
|
|
# so the plugin fails to load ("can not load requested driver
|
|
# 'QSQLITE'") unless sqlite3.dll also ships next to the executable.
|
|
find_file(ORBITHUB_SQLITE3_DLL
|
|
NAMES sqlite3.dll
|
|
PATHS ${CMAKE_PREFIX_PATH}
|
|
PATH_SUFFIXES bin
|
|
)
|
|
if(ORBITHUB_SQLITE3_DLL)
|
|
add_custom_command(TARGET orbithub POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"${ORBITHUB_SQLITE3_DLL}"
|
|
"$<TARGET_FILE_DIR:orbithub>/"
|
|
COMMENT "Deploying sqlite3.dll (Qt SQLite plugin dependency)"
|
|
)
|
|
install(FILES "${ORBITHUB_SQLITE3_DLL}" DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
if(APPLE)
|
|
# Mirrors macdeployqt's own layout for Qt frameworks: dylibs live in
|
|
# Contents/Frameworks inside the bundle, found via @executable_path
|
|
# (the macOS/dyld equivalent of Linux's $ORIGIN token, which dyld
|
|
# does not understand).
|
|
set_target_properties(orbithub PROPERTIES
|
|
INSTALL_RPATH "@executable_path/../Frameworks"
|
|
INSTALL_RPATH_USE_LINK_PATH ON
|
|
)
|
|
else()
|
|
set_target_properties(orbithub PROPERTIES
|
|
BUILD_RPATH_USE_ORIGIN ON
|
|
INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}/orbithub"
|
|
INSTALL_RPATH_USE_LINK_PATH ON
|
|
)
|
|
endif()
|
|
|
|
install(TARGETS orbithub
|
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
BUNDLE DESTINATION .
|
|
)
|
|
|
|
if(APPLE)
|
|
set(ORBITHUB_PRIVATE_LIB_DESTINATION "OrbitHub.app/Contents/Frameworks")
|
|
else()
|
|
set(ORBITHUB_PRIVATE_LIB_DESTINATION "${CMAKE_INSTALL_LIBDIR}/orbithub")
|
|
endif()
|
|
set(ORBITHUB_RUNTIME_TARGETS KodoTerm freerdp winpr)
|
|
if(TARGET freerdp-client)
|
|
list(APPEND ORBITHUB_RUNTIME_TARGETS freerdp-client)
|
|
endif()
|
|
foreach(runtime_target IN LISTS ORBITHUB_RUNTIME_TARGETS)
|
|
if(TARGET ${runtime_target})
|
|
install(TARGETS ${runtime_target}
|
|
RUNTIME DESTINATION ${ORBITHUB_PRIVATE_LIB_DESTINATION}
|
|
LIBRARY DESTINATION ${ORBITHUB_PRIVATE_LIB_DESTINATION}
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
)
|
|
endif()
|
|
endforeach()
|
|
|
|
install(FILES
|
|
packaging/linux/org.darksingularity.OrbitHub.desktop
|
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
|
|
)
|
|
foreach(icon_size IN ITEMS 16 24 32 48 64 128 256)
|
|
install(FILES
|
|
packaging/linux/icons/${icon_size}x${icon_size}/apps/org.darksingularity.OrbitHub.png
|
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${icon_size}x${icon_size}/apps
|
|
)
|
|
endforeach()
|
|
install(FILES
|
|
packaging/linux/org.darksingularity.OrbitHub.metainfo.xml
|
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo
|
|
)
|
|
install(FILES LICENSE
|
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/org.darksingularity.OrbitHub
|
|
)
|
|
install(FILES third_party/FreeRDP/LICENSE
|
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/org.darksingularity.OrbitHub
|
|
RENAME LICENSE-FreeRDP
|
|
)
|
|
install(FILES third_party/KodoTerm/LICENSE
|
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/org.darksingularity.OrbitHub
|
|
RENAME LICENSE-KodoTerm
|
|
)
|
|
|
|
if(ORBITHUB_BUILD_TESTS)
|
|
add_subdirectory(tests)
|
|
endif()
|