summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gnu/local.mk2
-rw-r--r--gnu/packages/patches/turbovnc-custom-paths.patch299
-rw-r--r--gnu/packages/patches/turbovnc-find-system-packages.patch51
-rw-r--r--gnu/packages/vnc.scm193
4 files changed, 545 insertions, 0 deletions
diff --git a/gnu/local.mk b/gnu/local.mk
index 9d08fd5b28..1b3225d075 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1885,6 +1885,8 @@ dist_patch_DATA =						\
   %D%/packages/patches/trytond-add-guix_trytond_path.patch	\
   %D%/packages/patches/ttf2eot-cstddef.patch			\
   %D%/packages/patches/tup-unbundle-dependencies.patch		\
+  %D%/packages/patches/turbovnc-custom-paths.patch		\
+  %D%/packages/patches/turbovnc-find-system-packages.patch	\
   %D%/packages/patches/tuxpaint-stamps-path.patch		\
   %D%/packages/patches/twinkle-bcg729.patch			\
   %D%/packages/patches/u-boot-allow-disabling-openssl.patch	\
diff --git a/gnu/packages/patches/turbovnc-custom-paths.patch b/gnu/packages/patches/turbovnc-custom-paths.patch
new file mode 100644
index 0000000000..563009c927
--- /dev/null
+++ b/gnu/packages/patches/turbovnc-custom-paths.patch
@@ -0,0 +1,299 @@
+From c58cdb2b7fe72685f97dee5872336f32a40fa04a Mon Sep 17 00:00:00 2001
+From: DRC <information@virtualgl.org>
+Date: Tue, 23 Aug 2022 12:02:12 -0500
+Subject: [PATCH] Improve support for distribution-specific builds
+
+- Rename the DRI_DRIVER_PATH and SERVER_MISC_CONFIG_PATH CMake variables
+  to XORG_DRI_DRIVER_PATH and XORG_REGISTRY_PATH, respectively.
+
+- Introduce a new CMake variable (XORG_FONT_PATH) that allows the X.org
+  font path to be set statically for a particular build.
+
+- Remove the unused RGB_DB macro definition.  (That macro hasn't been
+  used since TurboVNC 1.2.x.)
+
+- Introduce a new CMake variable (TVNC_STATIC_XORG_PATHS) that forces
+  Xvnc and vncserver to honor the paths set using the
+  XKB_BASE_DIRECTORY, XKB_BIN_DIRECTORY, XORG_DRI_DRIVER_PATH,
+  XORG_FONT_PATH, and XORG_REGISTRY_PATH CMake variables rather than
+  trying to determine the appropriate values of those paths at run time.
+  If enabled, this option disables the TurboVNC-specific -dridir,
+  -registrydir, and -xkbcompdir Xvnc command-line arguments.
+---
+ BUILDING.md                                   | 25 +++++++++++++++++++
+ unix/CMakeLists.txt                           |  9 +++++++
+ unix/Xvnc/programs/Xserver/dix/CMakeLists.txt | 20 +++++++++------
+ unix/Xvnc/programs/Xserver/dix/registry.c     |  2 +-
+ unix/Xvnc/programs/Xserver/glx/CMakeLists.txt | 12 ++++-----
+ unix/Xvnc/programs/Xserver/glx/glxdricommon.c |  2 +-
+ unix/Xvnc/programs/Xserver/hw/vnc/init.c      | 10 +++++++-
+ unix/Xvnc/programs/Xserver/xkb/xkbInit.c      |  2 +-
+ unix/vncserver.in                             | 13 +++++++---
+ 9 files changed, 73 insertions(+), 22 deletions(-)
+
+diff --git a/BUILDING.md b/BUILDING.md
+index 99f190b2c..b11665f95 100644
+--- a/BUILDING.md
++++ b/BUILDING.md
+@@ -181,6 +181,31 @@ directly with libssl and libcrypto by adding `-DTVNC_DLOPENSSL=0` to the CMake
+ command line.
+ 
+ 
++### Distribution-Specific Build
++
++By default, the build system builds TurboVNC binaries that can run on multiple
++O/S distributions.  This involves building some of the X.org dependencies,
++which are included in the TurboVNC source tree, and statically linking TurboVNC
++with those and other dependencies.  Distribution-specific dynamically-linked
++TurboVNC binaries can instead be built by changing the values of the following
++CMake variables:
++
++- `TJPEG_INCLUDE_DIR`
++- `TJPEG_LIBRARY`
++- `TVNC_DLOPENSSL`
++- `TVNC_STATIC_XORG_PATHS`
++- `TVNC_SYSTEMLIBS`
++- `TVNC_SYSTEMX11`
++- `XKB_BASE_DIRECTORY`
++- `XKB_BIN_DIRECTORY`
++- `XORG_DRI_DRIVER_PATH`
++- `XORG_FONT_PATH`
++- `XORG_REGISTRY_PATH`
++
++Use `ccmake` or `cmake-gui`, as described below, to view documentation for
++those variables.
++
++
+ Build Recipes
+ -------------
+ 
+diff --git a/unix/CMakeLists.txt b/unix/CMakeLists.txt
+index 1db927c94..6ef830a8b 100644
+--- a/unix/CMakeLists.txt
++++ b/unix/CMakeLists.txt
+@@ -74,6 +74,15 @@ option(TVNC_SYSTEMLIBS
+ boolean_number(TVNC_SYSTEMLIBS)
+ report_option(TVNC_SYSTEMLIBS "System zlib/bzip2/FreeType")
+ 
++option(TVNC_STATIC_XORG_PATHS
++	"Force vncserver and Xvnc to use the XKB base directory, XKB binary directory, X.org DRI driver path, X.org font path, and X.org registry path specified in the XKB_BASE_DIRECTORY, XKB_BIN_DIRECTORY, XORG_DRI_DRIVER_PATH, XORG_FONT_PATH, and XORG_REGISTRY_PATH CMake variables rather than detecting the appropriate paths at run time"
++	OFF)
++boolean_number(TVNC_STATIC_XORG_PATHS)
++report_option(TVNC_STATIC_XORG_PATHS "Static X.org paths")
++if(TVNC_STATIC_XORG_PATHS)
++	add_definitions(-DTURBOVNC_STATIC_XORG_PATHS)
++endif()
++
+ if(NOT TVNC_SYSTEMLIBS)
+ 	add_subdirectory(${CMAKE_SOURCE_DIR}/common ${CMAKE_BINARY_DIR}/common)
+ endif()
+diff --git a/unix/Xvnc/programs/Xserver/dix/CMakeLists.txt b/unix/Xvnc/programs/Xserver/dix/CMakeLists.txt
+index 784fc48d2..19a7b28c4 100644
+--- a/unix/Xvnc/programs/Xserver/dix/CMakeLists.txt
++++ b/unix/Xvnc/programs/Xserver/dix/CMakeLists.txt
+@@ -1,18 +1,22 @@
+ include_directories(../Xi ../composite ../damageext ../mi ../miext/sync
+ 	../randr ../render ../xfixes)
+ 
+-add_definitions(-DRGB_DB=\"/usr/share/X11/rgb\"
+-	-DCOMPILEDDEFAULTFONTPATH=\"/usr/share/X11/fonts/misc/,/usr/share/X11/fonts/Type1/,/usr/share/X11/fonts/75dpi/,/usr/share/X11/fonts/100dpi/\")
++set(DEFAULT_XORG_FONT_PATH
++	"/usr/share/X11/fonts/misc/,/usr/share/X11/fonts/Type1/,/usr/share/X11/fonts/75dpi/,/usr/share/X11/fonts/100dpi/")
++set(XORG_FONT_PATH ${DEFAULT_XORG_FONT_PATH} CACHE STRING
++	"X.org font path (default: ${DEFAULT_XORG_FONT_PATH})")
++message(STATUS "XORG_FONT_PATH = ${XORG_FONT_PATH}")
++add_definitions(-DCOMPILEDDEFAULTFONTPATH=\"${XORG_FONT_PATH}\")
+ 
+ if(BITS EQUAL 64)
+-	set(DEFAULT_SERVER_MISC_CONFIG_PATH "/usr/lib64/xorg")
++	set(DEFAULT_XORG_REGISTRY_PATH "/usr/lib64/xorg")
+ else()
+-	set(DEFAULT_SERVER_MISC_CONFIG_PATH "/usr/lib/xorg")
++	set(DEFAULT_XORG_REGISTRY_PATH "/usr/lib/xorg")
+ endif()
+-set(SERVER_MISC_CONFIG_PATH ${DEFAULT_SERVER_MISC_CONFIG_PATH} CACHE PATH
+-	"Path to miscellaneous server config files (default: ${DEFAULT_SERVER_MISC_CONFIG_PATH})")
+-message(STATUS "SERVER_MISC_CONFIG_PATH = ${SERVER_MISC_CONFIG_PATH}")
+-add_definitions(-DSERVER_MISC_CONFIG_PATH=\"${SERVER_MISC_CONFIG_PATH}\")
++set(XORG_REGISTRY_PATH ${DEFAULT_XORG_REGISTRY_PATH} CACHE PATH
++	"X.org registry path, which contains protocol.txt (default: ${DEFAULT_XORG_REGISTRY_PATH})")
++message(STATUS "XORG_REGISTRY_PATH = ${XORG_REGISTRY_PATH}")
++add_definitions(-DSERVER_MISC_CONFIG_PATH=\"${XORG_REGISTRY_PATH}\")
+ 
+ disable_compiler_warnings()
+ 
+diff --git a/unix/Xvnc/programs/Xserver/dix/registry.c b/unix/Xvnc/programs/Xserver/dix/registry.c
+index de4bf8eaf..3e8039250 100644
+--- a/unix/Xvnc/programs/Xserver/dix/registry.c
++++ b/unix/Xvnc/programs/Xserver/dix/registry.c
+@@ -33,7 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 
+ #ifdef X_REGISTRY_REQUEST
+ #define CORE "X11"
+-#ifdef TURBOVNC
++#if defined(TURBOVNC) && !defined(TURBOVNC_STATIC_XORG_PATHS)
+ char registry_path[PATH_MAX] = SERVER_MISC_CONFIG_PATH "/protocol.txt";
+ #define FILENAME registry_path
+ #else
+diff --git a/unix/Xvnc/programs/Xserver/glx/CMakeLists.txt b/unix/Xvnc/programs/Xserver/glx/CMakeLists.txt
+index 45f4b9635..ff8b84f6c 100644
+--- a/unix/Xvnc/programs/Xserver/glx/CMakeLists.txt
++++ b/unix/Xvnc/programs/Xserver/glx/CMakeLists.txt
+@@ -10,14 +10,14 @@ if(HAVE_BACKTRACE)
+ endif()
+ 
+ if(BITS EQUAL 64)
+-	set(DEFAULT_DRI_DRIVER_PATH "/usr/lib64/dri")
++	set(DEFAULT_XORG_DRI_DRIVER_PATH "/usr/lib64/dri")
+ else()
+-	set(DEFAULT_DRI_DRIVER_PATH "/usr/lib/dri")
++	set(DEFAULT_XORG_DRI_DRIVER_PATH "/usr/lib/dri")
+ endif()
+-set(DRI_DRIVER_PATH ${DEFAULT_DRI_DRIVER_PATH} CACHE PATH
+-	"Path to DRI drivers (default: ${DEFAULT_DRI_DRIVER_PATH})")
+-message(STATUS "DRI_DRIVER_PATH = ${DRI_DRIVER_PATH}")
+-add_definitions(-DDRI_DRIVER_PATH=\"${DRI_DRIVER_PATH}\")
++set(XORG_DRI_DRIVER_PATH ${DEFAULT_XORG_DRI_DRIVER_PATH} CACHE PATH
++	"X.org DRI driver path, which contains swrast_dri.so (default: ${DEFAULT_XORG_DRI_DRIVER_PATH})")
++message(STATUS "XORG_DRI_DRIVER_PATH = ${XORG_DRI_DRIVER_PATH}")
++add_definitions(-DDRI_DRIVER_PATH=\"${XORG_DRI_DRIVER_PATH}\")
+ 
+ disable_compiler_warnings()
+ 
+diff --git a/unix/Xvnc/programs/Xserver/glx/glxdricommon.c b/unix/Xvnc/programs/Xserver/glx/glxdricommon.c
+index be9352b5e..a16e1bcf9 100644
+--- a/unix/Xvnc/programs/Xserver/glx/glxdricommon.c
++++ b/unix/Xvnc/programs/Xserver/glx/glxdricommon.c
+@@ -258,7 +258,7 @@ glxConvertConfigs(const __DRIcoreExtension * core,
+     return head.next;
+ }
+ 
+-#ifdef TURBOVNC
++#if defined(TURBOVNC) && !defined(TURBOVNC_STATIC_XORG_PATH)
+ char *dri_driver_path = DRI_DRIVER_PATH;
+ #else
+ static const char dri_driver_path[] = DRI_DRIVER_PATH;
+diff --git a/unix/Xvnc/programs/Xserver/hw/vnc/init.c b/unix/Xvnc/programs/Xserver/hw/vnc/init.c
+index 81fbfe8b5..c8ba83772 100644
+--- a/unix/Xvnc/programs/Xserver/hw/vnc/init.c
++++ b/unix/Xvnc/programs/Xserver/hw/vnc/init.c
+@@ -103,7 +103,7 @@ from the X Consortium.
+ #ifdef GLXEXT
+ extern char *dri_driver_path;
+ #endif
+-#ifdef X_REGISTRY_REQUEST
++#if defined(X_REGISTRY_REQUEST) && !defined(TURBOVNC_STATIC_XORG_PATHS)
+ extern char registry_path[PATH_MAX];
+ #endif
+ 
+@@ -437,6 +437,7 @@ int ddxProcessArgument(int argc, char *argv[], int i)
+     return 2;
+   }
+ 
++#ifndef TURBOVNC_STATIC_XORG_PATHS
+   if (strcasecmp(argv[i], "-dridir") == 0) {
+ #ifdef GLXEXT
+     REQUIRE_ARG();
+@@ -444,6 +445,7 @@ int ddxProcessArgument(int argc, char *argv[], int i)
+ #endif
+     return 2;
+   }
++#endif
+ 
+   if (strcasecmp(argv[i], "-geometry") == 0) {
+     /* -geometry WxH or W0xH0+X0+Y0[,W1xH1+X1+Y1,...] */
+@@ -644,6 +646,7 @@ int ddxProcessArgument(int argc, char *argv[], int i)
+ 
+   /***** TurboVNC miscellaneous options *****/
+ 
++#ifndef TURBOVNC_STATIC_XORG_PATHS
+   if (strcasecmp(argv[i], "-registrydir") == 0) {
+ #ifdef X_REGISTRY_REQUEST
+     REQUIRE_ARG();
+@@ -651,6 +654,7 @@ int ddxProcessArgument(int argc, char *argv[], int i)
+ #endif
+     return 2;
+   }
++#endif
+ 
+   if (strcasecmp(argv[i], "-verbose") == 0) {
+     LogSetParameter(XLOG_VERBOSITY, X_DEBUG);
+@@ -1672,7 +1676,9 @@ void ddxUseMsg(void)
+   ErrorF("\nTurboVNC display options\n");
+   ErrorF("========================\n");
+   ErrorF("-depth D               set framebuffer depth\n");
++#ifndef TURBOVNC_STATIC_XORG_PATHS
+   ErrorF("-dridir dir            specify directory containing the swrast Mesa driver\n");
++#endif
+   ErrorF("-geometry WxH          set framebuffer width & height (single-screen)\n");
+   ErrorF("-geometry W0xH0+X0+Y0[,W1xH1+X1+Y1,...,WnxHn+Xn+Yn]\n");
+   ErrorF("                       set multi-screen geometry (see man page)\n");
+@@ -1730,7 +1736,9 @@ void ddxUseMsg(void)
+ 
+   ErrorF("\nTurboVNC miscellaneous options\n");
+   ErrorF("==============================\n");
++#ifndef TURBOVNC_STATIC_XORG_PATHS
+   ErrorF("-registrydir dir       specify directory containing protocol.txt\n");
++#endif
+   ErrorF("-verbose               print all X.org errors, warnings, and messages\n");
+   ErrorF("-version               report Xvnc version on stderr\n\n");
+ }
+diff --git a/unix/Xvnc/programs/Xserver/xkb/xkbInit.c b/unix/Xvnc/programs/Xserver/xkb/xkbInit.c
+index b63549f3d..ddd5ef7f2 100644
+--- a/unix/Xvnc/programs/Xserver/xkb/xkbInit.c
++++ b/unix/Xvnc/programs/Xserver/xkb/xkbInit.c
+@@ -767,7 +767,7 @@ XkbProcessArguments(int argc, char *argv[], int i)
+             return -1;
+         }
+     }
+-#ifdef TURBOVNC
++#if defined(TURBOVNC) && !defined(TURBOVNC_XORG_STATIC_PATHS)
+     else if (strncmp(argv[i], "-xkbcompdir", 11) == 0) {
+         if (++i < argc) {
+ #if !defined(WIN32) && !defined(__CYGWIN__)
+diff --git a/unix/vncserver.in b/unix/vncserver.in
+index 4ed8ef668..300ccbf88 100644
+--- a/unix/vncserver.in
++++ b/unix/vncserver.in
+@@ -38,6 +38,7 @@ if ($slashndx >= 0) {
+ 
+ $xauth = "xauth";
+ $buildWebServer = @TVNC_BUILDWEBSERVER@;
++$staticXorgPaths = @TVNC_STATIC_XORG_PATHS@;
+ 
+ &SanityCheck();
+ 
+@@ -98,6 +99,8 @@ unless ($xauthorityFile) {
+ chop($host = `uname -n`);
+ chop($os = `uname`);
+ 
++if (!$staticXorgPaths) {
++
+ if (-d "/etc/X11/fontpath.d") {
+   $fontPath = "catalogue:/etc/X11/fontpath.d";
+ }
+@@ -195,6 +198,8 @@ foreach $_registrydir (@registrydirs) {
+   }
+ }
+ 
++} # !$staticXorgPaths
++
+ # Check command line options
+ 
+ &ParseOptions("-geometry", 1, "-depth", 1, "-pixelformat", 1, "-name", 1,
+@@ -447,11 +452,11 @@ $cmd .= " -rfbport $vncPort";
+ $cmd .= " -fp $fontPath" if ($fontPath);
+ $cmd .= " -alr ".$autoLosslessRefresh if ($autoLosslessRefresh > 0.0);
+ $cmd .= " -deferupdate $deferUpdate";
+-$cmd .= " -xkbdir $xkbdir" if ($xkbdir);
+-$cmd .= " -xkbcompdir $xkbcompdir" if ($xkbcompdir);
++$cmd .= " -xkbdir $xkbdir" if ($xkbdir && !$staticXorgPaths);
++$cmd .= " -xkbcompdir $xkbcompdir" if ($xkbcompdir && !$staticXorgPaths);
+ $cmd .= " -pamsession" if ($pamSession);
+-$cmd .= " -dridir $dridir" if ($dridir);
+-$cmd .= " -registrydir $registrydir" if ($registrydir);
++$cmd .= " -dridir $dridir" if ($dridir && !$staticXorgPaths);
++$cmd .= " -registrydir $registrydir" if ($registrydir && !$staticXorgPaths);
+ $cmd .= " -nomt" if (!$multiThread);
+ $cmd .= " -nthreads $numThreads" if ($numThreads);
+ $cmd .= " $serverArgs" if ($serverArgs);
diff --git a/gnu/packages/patches/turbovnc-find-system-packages.patch b/gnu/packages/patches/turbovnc-find-system-packages.patch
new file mode 100644
index 0000000000..a7e7364ee7
--- /dev/null
+++ b/gnu/packages/patches/turbovnc-find-system-packages.patch
@@ -0,0 +1,51 @@
+From b4e1ffcdbfe8dc98036a16022cbcc422385c1834 Mon Sep 17 00:00:00 2001
+From: DRC <information@virtualgl.org>
+Date: Tue, 23 Aug 2022 10:07:10 -0500
+Subject: [PATCH] Build: Find Xfont2/fontenc/Pixman using pkg-config
+
+... when TVNC_SYSTEMX11=1.  Referring to #339, we can't assume that
+these libraries will share include/library paths with libX11.  This
+commit reverts e9cb8665dc3822b33dc0ffc5571fce5a759e7cb9.
+
+Rebased on 3.0.1 by Maxim Cournoyer <maxim.cournoyer@gmail.com>
+
+diff --git a/unix/Xvnc/CMakeLists.txt b/unix/Xvnc/CMakeLists.txt
+index 064feda..293f794 100644
+--- a/unix/Xvnc/CMakeLists.txt
++++ b/unix/Xvnc/CMakeLists.txt
+@@ -94,11 +94,13 @@ if(NOT TVNC_SYSTEMX11)
+ endif()
+ 
+ if(TVNC_SYSTEMX11)
++	include(FindPkgConfig)
++	pkg_check_modules(X11_Xfont2 REQUIRED xfont2)
++	pkg_check_modules(X11_Fontenc REQUIRED fontenc)
++	pkg_check_modules(X11_Pixman REQUIRED pixman-1)
+ 	include_directories(${X11_X11_INCLUDE_PATH} ${X11_Xau_INCLUDE_PATH}
+-		${X11_Xdmcp_INCLUDE_PATH} ${X11_Xkbfile_INCLUDE_PATH})
+-	string(REGEX REPLACE "X11" "Xfont2" X11_Xfont2_LIB ${X11_X11_LIB})
+-	string(REGEX REPLACE "X11" "fontenc" X11_Fontenc_LIB ${X11_X11_LIB})
+-	string(REGEX REPLACE "X11" "pixman-1" X11_Pixman_LIB ${X11_X11_LIB})
++		${X11_Xdmcp_INCLUDE_PATH} ${X11_Xkbfile_INCLUDE_PATH}
++		${X11_Xfont2_INCLUDEDIR} ${X11_Pixman_INCLUDEDIR}/pixman-1)
+ else()
+ 	include_directories(${CMAKE_CURRENT_BINARY_DIR}/X_include)
+ 	set(X11_Xau_LIB Xau)
+diff --git a/unix/Xvnc/programs/Xserver/CMakeLists.txt b/unix/Xvnc/programs/Xserver/CMakeLists.txt
+index 8c05d43..f8d8f76 100644
+--- a/unix/Xvnc/programs/Xserver/CMakeLists.txt
++++ b/unix/Xvnc/programs/Xserver/CMakeLists.txt
+@@ -182,9 +182,10 @@ if(HAVE_MONOTONIC_CLOCK)
+ endif()
+ target_link_libraries(Xvnc dix mi vnc fb Xi composite mi damage damageext randr
+ 	record render os present Xext-server sync xfixes xkb ${X11_Xau_LIB}
+-	${X11_Xdmcp_LIB} ${X11_Xfont2_LIB} ${X11_Fontenc_LIB} ${FREETYPE_LIBRARIES}
+-	${X11_Pixman_LIB} sha1 ${TJPEG_LIBRARY} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES}
+-	vncauth m pthread ${PAM_LIB} ${EXTRA_LIB})
++	${X11_Xdmcp_LIB} ${X11_Xfont2_LDFLAGS} ${X11_Fontenc_LDFLAGS}
++	${FREETYPE_LIBRARIES} ${X11_Pixman_LDFLAGS} sha1 ${TJPEG_LIBRARY}
++	${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} vncauth m pthread ${PAM_LIB}
++	${EXTRA_LIB})
+ if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "(OpenBSD|FreeBSD|NetBSD|DragonFly)")
+ 	find_library(ICONV_LIBRARIES NAMES iconv)
+ 	target_link_libraries(Xvnc ${ICONV_LIBRARIES})
diff --git a/gnu/packages/vnc.scm b/gnu/packages/vnc.scm
index c0fabe848b..84c84aec76 100644
--- a/gnu/packages/vnc.scm
+++ b/gnu/packages/vnc.scm
@@ -5,6 +5,7 @@
 ;;; Copyright © 2020 Marius Bakke <marius@gnu.org>
 ;;; Copyright © 2020 Vincent Legoll <vincent.legoll@gmail.com>
 ;;; Copyright © 2021, 2022 Tobias Geerinckx-Rice <me@tobias.gr>
+;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -26,6 +27,7 @@
   #:use-module (guix download)
   #:use-module (guix git-download)
   #:use-module ((guix licenses) #:prefix license:)
+  #:use-module (guix gexp)
   #:use-module (guix packages)
   #:use-module (guix utils)
   #:use-module (gnu packages)
@@ -37,17 +39,22 @@
   #:use-module (gnu packages crypto)
   #:use-module (gnu packages cups)
   #:use-module (gnu packages fltk)
+  #:use-module (gnu packages fontutils)
   #:use-module (gnu packages freedesktop)
   #:use-module (gnu packages gettext)
+  #:use-module (gnu packages gl)
   #:use-module (gnu packages glib)
   #:use-module (gnu packages gnome)
   #:use-module (gnu packages gnupg)
   #:use-module (gnu packages gtk)
+  #:use-module (gnu packages guile)
   #:use-module (gnu packages image)
+  #:use-module (gnu packages java)
   #:use-module (gnu packages linux)
   #:use-module (gnu packages pcre)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages pkg-config)
+  #:use-module (gnu packages python)
   #:use-module (gnu packages rdesktop)
   #:use-module (gnu packages sdl)
   #:use-module (gnu packages spice)
@@ -318,6 +325,192 @@ and TLS encryption.  This package installs the VNC server, a program that will
 enable users with VNC clients to log into a graphical session on the machine
 where the server is installed.")))
 
+(define-public turbovnc
+  (package
+    (name "turbovnc")
+    (version "3.0.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "mirror://sourceforge/turbovnc/" version
+                           "/turbovnc-" version ".tar.gz"))
+       (modules '((guix build utils)
+                  (ice-9 ftw)
+                  (srfi srfi-26)))
+       (snippet
+        #~(begin
+            ;; There are a few bundled Java libraries, such as jsch and jzlib,
+            ;; bundled under java/com/jcraft/ as well as mindrot and spf4j,
+            ;; bundled under java/org.  These are used by the 'vncviewer'
+            ;; program.  The jsch copy is modified and integrates changes from
+            ;; https://github.com/mwiede/jsch, so cannot easily be un-bundled.
+            (define (directory? x)
+              (and=> (stat x #f) (compose (cut eq? 'directory <>) stat:type)))
+
+            (define (delete-all-but directory . preserve)
+              (with-directory-excursion directory
+                (let* ((pred (negate (cut member <> (append '("." "..")
+                                                            preserve))))
+                       (items (scandir "." pred)))
+                  (for-each (lambda (item)
+                              (if (directory? item)
+                                  (delete-file-recursively item)
+                                  (delete-file item)))
+                            items))))
+
+            ;; d3des, rfb (headers) and turbojpeg-jni are small and not
+            ;; packaged in Guix, so preserve them.
+            (delete-all-but "common" "d3des" "rfb" "turbojpeg-jni")
+            ;; Delete bundled headers which aren't used.
+            (delete-all-but "unix/Xvnc/include" "tvnc_version.h.in")
+            ;; This 243 lines of code C library is used by
+            ;; unix/Xvnc/programs/Xserver/os/xsha1.c.
+            (delete-all-but "unix/Xvnc/lib" "CMakeLists.txt" "libsha1")
+            (delete-file-recursively "unix/Xvnc/extras")))
+       (sha256
+        (base32
+         "182amp471qvr2cn2rbw97zpbkh9q7mf92w1r25cg4apx5k26m7c3"))
+       (patches (search-patches "turbovnc-find-system-packages.patch"
+                                "turbovnc-custom-paths.patch"))))
+    (build-system cmake-build-system)
+    (arguments
+     (list
+      #:tests? #f                       ;no test suite
+      #:configure-flags
+      ;; Use system libraries.
+      #~(list "-DTVNC_SYSTEMLIBS=ON"
+              "-DTVNC_SYSTEMX11=ON"
+              "-DTVNC_DLOPENSSL=OFF"
+              (string-append "-DXORG_DRI_DRIVER_PATH="
+                             (search-input-directory %build-inputs "lib/dri"))
+              (string-append "-DXORG_FONT_PATH="
+                             "/run/current-system/profile/share/fonts/X11,"
+                             (string-append #$(this-package-input "font-alias")
+                                            "share/fonts/X11"))
+              (string-append "-DXORG_REGISTRY_PATH="
+                             (dirname (search-input-file
+                                       %build-inputs "lib/xorg/protocol.txt")))
+              (string-append "-DXKB_BASE_DIRECTORY="
+                             (search-input-directory %build-inputs
+                                                     "share/X11/xkb"))
+              (string-append "-DXKB_BIN_DIRECTORY="
+                             (dirname (search-input-file %build-inputs
+                                                         "bin/xkbcomp")))
+              ;; The default rule is 'xorg', which doesn't match the 'base'
+              ;; rule file installed by our version of xkeyboard-config.
+              ;; Without this change, running Xvnc would fail with the error
+              ;; "XKB: Failed to compile keymap"
+              "-DXKB_DFLT_RULES=base"
+              ;; Mimic xorg-server's "--with-xkb-output=/tmp" configuration.
+              "-DCOMPILEDDEFAULTFONTPATH=/tmp"
+              "-DTVNC_STATIC_XORG_PATHS=ON")
+      #:phases
+      #~(modify-phases %standard-phases
+          (add-after 'unpack 'patch-vncviewer
+            (lambda* (#:key inputs #:allow-other-keys)
+              (define openjdk #$(this-package-input "openjdk"))
+              (substitute* "unix/vncviewer/vncviewer.in"
+                (("\\$BINDIR/../java/jre")
+                 openjdk)
+                ;; Avoid resorting to grep and sed to locate libjawt.so.
+                (("^_TMP=.*")
+                 (string-append "_TMP=" openjdk "/lib\n")))))
+          (add-after 'unpack 'patch-xstartup.turbovnc
+            (lambda* (#:key inputs #:allow-other-keys)
+              (substitute* "unix/xstartup.turbovnc"
+                (("DBUS_LAUNCH=[[:graph:]]+")
+                 (format #f "DBUS_LAUNCH=~a"
+                         (search-input-file inputs "bin/dbus-launch")))
+                (("XSESSIONSDIR=[[:graph:]]+")
+                 (format #f "XSESSIONSDIR=~a"
+                         "/run/current-system/profile/share/xsessions"))
+                (("GREP=[[:graph:]]+")
+                 (format #f "GREP=~a"
+                         (search-input-file inputs "bin/grep")))
+                (("SED=[[:graph:]]+")
+                 (format #f "SED=~a"
+                         (search-input-file inputs "bin/sed")))
+                (("TVNC_SSHAGENT=[[:graph:]]+")
+                 (format #f "TVNC_SSHAGENT=~a"
+                         (search-input-file inputs "bin/ssh-agent")))
+                (("TVNC_VGLRUN=\"vglrun" all)
+                 (string-append "TVNC_VGLRUN="
+                                (search-input-file inputs "bin/vglrun") all)))))
+          (add-after 'install 'wrap-vncserver
+            (lambda* (#:key inputs outputs #:allow-other-keys)
+              (wrap-script (search-input-file outputs "bin/vncserver")
+                (list "PATH" 'prefix
+                      (map (lambda (p)
+                             (dirname (search-input-file inputs p)))
+                           '("bin/uname" ;coreutils
+                             "bin/xauth"
+                             "bin/xdpyinfo"))))))
+          (add-after 'install 'wrap-xstartup.turbovnc
+            (lambda* (#:key inputs outputs #:allow-other-keys)
+              (wrap-script (search-input-file outputs "bin/xstartup.turbovnc")
+                (list "PATH" 'prefix
+                      (map (lambda (p)
+                             (dirname (search-input-file inputs p)))
+                           '("bin/uname" ;coreutils
+                             ;; These are used as the fallback when no desktop
+                             ;; session was found.
+                             "bin/twm"
+                             "bin/xsetroot"
+                             "bin/xterm")))))))))
+    (native-inputs
+     (list `(,openjdk "jdk")
+           pkg-config
+           python))
+    (inputs
+     (list dbus
+           font-alias
+           freetype
+           guile-3.0
+           libfontenc
+           libjpeg-turbo
+           libx11
+           libxdamage
+           libxext
+           libxfont2
+           libxi
+           libxkbfile
+           linux-pam
+           mesa
+           openjdk
+           openssh
+           openssl
+           perl
+           pixman
+           twm
+           virtualgl
+           xauth
+           xdpyinfo
+           xkbcomp
+           xkeyboard-config
+           xorg-server
+           xorgproto
+           xsetroot
+           xterm
+           xtrans
+           zlib))
+    (home-page "https://turbovnc.org/")
+    (synopsis "Highly-optimized VNC remote desktop software")
+    (description "TurboVNC is a high-speed version of VNC derived from
+TightVNC, with which it remains compatible.  It contains a variant of Tight
+encoding that is tuned to maximize performance for image-intensive
+applications (such as VirtualGL, video applications, and image editors) while
+still providing excellent performance for other types of applications.  Some
+of its unique features are:
+@itemize
+@item a user-facing @command{vncserver} command;
+@item the ability to capture keyboard keys even when not in full screen mode;
+@item a full screen mode that is compatible with ratpoison*
+@end itemize
+*Although due to a quirk in Java, you'll want to set the
+@env{_JAVA_AWT_WM_NONREPARENTING} environment variable when using it with
+ratpoison.")
+    (license license:gpl2+)))
+
 (define-public libvnc
   (package
     (name "libvnc")