@@ -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 @@ (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,242 @@ (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
+ ;; TODO: Unbundle 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.
+ (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"))
+ ;; Help the build system to find the system pixman headers.
+ (string-append "-DCMAKE_C_FLAGS=-I"
+ (search-input-directory %build-inputs
+ "include/pixman-1")))
+ #: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/CMakeLists.txt"
+ ;; The default rule file name must have changed from 'xorg' to
+ ;; 'base' for xkeyboard-config. Without this change, running
+ ;; Xvnc would fail with the error "XKB: Failed to compile
+ ;; keymap"
+ (("set\\(DEFAULT_XKB_DFLT_RULES.*)")
+ "set(DEFAULT_XKB_DFLT_RULES \"base\")")
+ ;; XXX: This somehow overrides the user-specified
+ ;; XKB_BASE_DIRECTORY.
+ (("set\\(DEFAULT_XKB_BASE_DIRECTORY .*)")
+ (format #f "set(DEFAULT_XKB_BASE_DIRECTORY \"~a\")"
+ (search-input-directory inputs "share/X11/xkb")))
+ (("set\\(DEFAULT_XKB_BIN_DIRECTORY .*)")
+ (format #f "set(DEFAULT_XKB_BIN_DIRECTORY \"~a\")"
+ (dirname (search-input-file inputs
+ "bin/xkbcomp")))))
+ (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))
+ ;; Add sane Guix System default locations 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 "TightVNC-compatible remote desktop software")
+ (description "TurboVNC is a high-speed version of VNC derived from
+TightVNC. 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")