Patching a Debian package locally: Nextcloud, DWM and the focus lost

If you use a Window Manager that switches focus automatically (like dwm) and the Nextcloud client, surely you are annoyed by the Nextcloud window disappearing on focus lost “feature” (and no knob to switch it off). Apparently, the developers decided that This Is The Right Way®.

With the power of The Source Code, we can change that!

I am using Debian

This short blog post is about patching a Debian package from the official repository (in this case, nextcloud-desktop). However, the patch is distro-independent, so you can do the same procedure using your favorite distro’s tools (or directly in the source code of Nextcloud Desktop software).

Requirements

We need the Debian tools for building and patching a package:

$ sudo apt-get install devscripts dpkg-dev quilt

and we need to install the development dependencies for building nextcloud-desktop:

$ sudo apt-get install appstream cmake doxygen extra-cmake-modules libcloudproviders-dev libcmocka-dev libdbus-1-dev libkf5coreaddons-dev libkf5kio-dev libqt5svg5-dev libqt5webkit5-dev libsqlite3-dev  libssl-dev pkg-config python3-sphinx qt5keychain-dev qtbase5-dev qtquickcontrols2-5-dev qttools5-dev qttools5-dev-tools qtwebengine5-dev texlive-latex-base zlib1g-dev xvfb jdupes dh-sequence-sphinxdoc

(that’s a lot of dependencies – you may use docker or podman, or an old-fashioned chroot to avoid polluting your installation).

Getting the Debian package

We will use the official Debian source package for nextcloud-desktop. To retrieve the correct URL, you can search for the package at packages.debian.org. E.g., for the Nextcloud desktop in Bullseye, packages.debian.org/bullseye/nextcloud-desktop.

The page has a section on the left named “Download Source Package”. We can use the file ending with .dsc with the dget tool. dget will download the package source code (tar.gz) and all Debian patches and extract everything ready for re-building the package:

$ mkdir my_custom_nextcloud
$ cd my_custom_nextcloud
$ dget -x -u http://deb.debian.org/debian/pool/main/n/nextcloud-desktop/nextcloud-desktop_3.1.1-2+deb11u1.dsc

(here I am using the Debian Bullseye version)

We should have some files and a directory here, e.g.:

$ ls -1
nextcloud-desktop-3.1.1
nextcloud-desktop_3.1.1-2+deb11u1.debian.tar.xz
nextcloud-desktop_3.1.1-2+deb11u1.dsc
nextcloud-desktop_3.1.1.orig.tar.gz

The source code is inside the nextcloud-desktop-3.1.1 directory; let’s switch to it:

$ cd nextcloud-desktop-3.1.1

Patching Nextcloud

While the source code is there, you can mess with it: the command that builds the package will restore the original source code before building it. The Debian way is to create a patch inside debian/patches. We do this using quilt.

First, to use quilt, we must decide a new name for the patch. If you look inside the debian/patches directory, you’ll see that patches are numbered. We can use the next available number:

$ quilt new 0009-disable-close-on-lost-focus.patch

Then, we must tell quilt which file we will modify. The code we want to edit is inside src/gui/tray/Window.qml, so we add it to quilt before editing it:

$ quilt add src/gui/tray/Window.qml

Now, we can open the file using the editor we like (e.g., vim). Around line 30 there is the onActiveChanged handler:

// Close tray window when focus is lost (e.g. click somewhere else on the screen)
onActiveChanged: {
    if(!active) {
        trayWindow.hide();
        Systray.setClosed();
    }
}

As the comment states, this function is called whenever the focus changes, and if it’s lost, it hides the main window. We can remove the if and close the file!

Finally, we can save the patch by calling quilt again:

$ quilt refresh

Building the new package(s)

Now we are ready to build the patched package! But first, we need to increment its version number with dch:

$ EMAIL=[email protected] dch -l customsuffix "Disable close on lost focus"

dch will change the debian/changelog file, adding our message (and our e-mail address) on top of the change log, and it increments the package version by adding a custom suffix customsuffix to the package version (-l indicates a “local” version, something that is not from the official repositories).

Finally, we can build the package:

$ dpkg-buildpackage -uc -us -b

-uc and -us skip signing (as we don’t have the setup to sign), and -b indicates to build only the binary package (otherwise, the tool prepares a new set of .tar.gz with the patched source code).

You will find all packages built from your patched source code in the parent directory at the end of the compilation process. Note that you don’t need to install all of them! Just replace those that you are using.

Final remarks

This guide is not for creating packages to be redistributed in official or public mirrors. In that case, I strongly suggest you to look at the Debian Maintainer Guide.