Subject: [bug#57288] [PATCH v2] gnu: Add turbovnc.

From: Maxim Cournoyer <[email-masked]>
Date: Fri, 19 Aug 2022 02:54:06 -0400

* gnu/packages/vnc.scm (turbovnc): New variable.
---
 gnu/packages/vnc.scm | 241 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 241 insertions(+)

diff --git a/gnu/packages/vnc.scm b/gnu/packages/vnc.scm
index c0fabe848b..668bdb2134 100644
--- a/gnu/packages/vnc.scm
+++ b/gnu/packages/vnc.scm
@@ -5,6 +5,7 @@
 ;;; Copyright © 2020 Marius Bakke <[email-masked]>
 ;;; Copyright © 2020 Vincent Legoll <[email-masked]>
 ;;; Copyright © 2021, 2022 Tobias Geerinckx-Rice <[email-masked]>
+;;; Copyright © 2022 Maxim Cournoyer <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -26,6 +27,7 @@ (define-module (gnu packages vnc)
   #: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 @@ (define-module (gnu packages vnc)
   #: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,240 @@ (define-public tigervnc-server
 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.
+            (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 preserved, since they
+            ;; are not packaged and fairly small.
+            (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"))))
+    (build-system cmake-build-system)
+    (arguments
+     (list
+      #:tests? #f                       ;no test suite
+      #:configure-flags
+      ;; Use system libraries.
+      #~(list "-DTVNC_SYSTEMLIBS=1"
+              "-DTVNC_SYSTEMX11=1"
+              "-DTVNC_DLOPENSSL=0"
+              (string-append "-DDRI_DRIVER_PATH="
+                             (search-input-directory %build-inputs "lib/dri"))
+              (string-append "-DXKB_BASE_DIRECTORY="
+                             (search-input-directory %build-inputs
+                                                     "share/X11/xkb"))
+              ;; 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"
+              (string-append "-DXKB_BIN_DIRECTORY="
+                             (dirname (search-input-file %build-inputs
+                                                         "bin/xkbcomp")))
+              ;; Help the build system to find the system pixman headers.
+              (string-append "-DCMAKE_C_FLAGS=-I"
+                             (search-input-directory %build-inputs
+                                                     "include/pixman-1"))
+              (string-append "-DSERVER_MISC_CONFIG_PATH="
+                             (dirname (search-input-file
+                                       %build-inputs "lib/xorg/protocol.txt"))))
+      #:phases
+      #~(modify-phases %standard-phases
+          (add-after 'unpack 'patch-build-system
+            (lambda* (#:key inputs #:allow-other-keys)
+              ;; The build system wrongly assumes that the Xfont2, fontenc and
+              ;; pixman-1 libraries are installed in the same prefix as
+              ;; libx11.
+              (substitute* "unix/Xvnc/CMakeLists.txt"
+                (("string\\(REGEX REPLACE.*X11_Xfont2_LIB.*")
+                 (format #f "set(X11_Xfont2_LIB ~a)~%"
+                         (search-input-file inputs "lib/libXfont2.so")))
+                (("string\\(REGEX REPLACE.*X11_Fontenc_LIB.*")
+                 (format #f "set(X11_Fontenc_LIB ~a)~%"
+                         (search-input-file inputs "lib/libfontenc.so")))
+                (("string\\(REGEX REPLACE.*X11_Pixman_LIB.*")
+                 (format #f "set(X11_Pixman_LIB ~a)~%"
+                         (search-input-file inputs "lib/libpixman-1.so"))))
+              (substitute* "unix/Xvnc/programs/Xserver/dix/CMakeLists.txt"
+                ;; This is needed, otherwise the same error as above would
+                ;; occur.  Mimic xorg-server's "--with-xkb-output=/tmp"
+                ;; configuration.
+                (("-DCOMPILEDDEFAULTFONTPATH=\".*\"")
+                 "-DCOMPILEDDEFAULTFONTPATH=/tmp"))))
+          (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-vncserver
+            (lambda* (#:key inputs #:allow-other-keys)
+              (substitute* "unix/vncserver.in"
+                ;; Add sane Guix System default locations for X11 fonts.
+                (("'/usr/share/X11/fonts'" all)
+                 (format #f "'~a', '~a', ~a"
+                         "/run/current-system/profile/share/fonts/X11"
+                         (string-append #$(this-package-input "font-alias")
+                                        "share/fonts/X11")
+                         all))
+                ;; Likewise for XKB layouts.
+                ;; Note: the directory must be appended to the list, as the
+                ;; last one to be searched wins.
+                (("'/opt/X11/share/X11/xkb'" all)
+                 (format #f "~a, '~a/share/X11/xkb', '~a'"
+                         all #$(this-package-input "xkeyboard-config")
+                         "/run/current-system/profile/share/X11/xkb"))
+                ;; Likewise for the xkbcompdirs.
+                (("'/opt/X11/bin'" all)
+                 (format #f "~a, '~a'" all
+                         (dirname (search-input-file inputs "bin/xkbcomp"))))
+                ;; Likewise for dridirs.
+                (("push\\(@dridirs, '/usr/local/lib/dri').*" all)
+                 (format #f "~apush(@dridirs, '~a');~%" all
+                         (dirname (search-input-file
+                                   inputs "lib/dri/swrast_dri.so"))))
+                ;; Likewise for registrydirs.
+                (("push\\(@registrydirs, '/opt/X11/lib/xorg').*" all)
+                 (format #f "~apush(@registrydirs, '~a');~%" all
+                         (dirname (search-input-file
+                                   inputs "lib/xorg/protocol.txt")))))))
+          (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")))
+                ;; There's no /etc/X11/xinit/Xsession file on Guix System, so
+                ;; attempt a better guess.
+                (("XSESSION=[[:graph:]]+")
+                 "XSESSION=$HOME/.xsession")
+                (("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") 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")
-- 
2.36.1