# GTK-NoCSD

GTK-NoCSD is an LD_PRELOAD library to disable CSD in GTK3/4, LibHandy, and LibAdwaita apps.

CSD is client side decoration, there is also server side decoration, SSD, both serving as the titlebar of windows.  
GTK3 adopted CSD, where this thick headerbar is used with application controls embedded.  
This continued into the platform library, LibHandy, then into GTK4 and the platform library of that, LibAdwaita.  
This looks good on Gnome and makes these applications alike, but looks off everywhere else and can potentially break window managers and remove window manager provided functionality.  
This library restores the server side decoration, getting back the window manager titlebar, and moves the controls from the CSD to under it, into the window content.  

## Build dependencies

- GCC
- LibAdwaita

## Building

### Make

The library uses the make build system.  
Look at ARGUMENTS block to see what can be changed.  
The makefile has the following commands:  

- build: Builds the library
- clean: Removes locally built library
- install: Builds and installs library
- uninstall: Removes installed library
- format: Formats source code with uncrustify

### Manually

Get the source files and enter the directory.  

```
git clone https://codeberg.org/MorsMortium/GTK-NoCSD.git
cd GTK-NoCSD
```

Build the library.  
Both 32 and 64 bit builds will produce a libgtk-nocsd.so.0 file, in the root of the repository.  

#### 64 bit

This command builds the library.  
```
gcc -fPIC -shared ./Source/GTK-NoCSD.c -o libgtk-nocsd.so.0 \
	-Wl,-soname,libgtk-nocsd.so.0 \
	$(pkg-config --cflags libadwaita-1 gobject-2.0 gio-2.0)
```

#### 32 bit

Building for 32 bit applications can be done like so.  
```
gcc -fPIC -shared ./Source/GTK-NoCSD.c -o libgtk-nocsd.so.0 \
	-Wl,-soname,libgtk-nocsd.so.0 \
	$(pkg-config --cflags libadwaita-1 gobject-2.0 gio-2.0 | sed 's/$/ -m32/')
```

## Packaging

You are free to package it yourself or ask distribution packagers to do it.  
Warning: Debian and distributions based on it do not have the /opt link, for flatpak you have to copy it or make a hard link to it.  

### AUR

https://aur.archlinux.org/packages/gtk-nocsd-git  

### Gentoo

### WARNING: If you previously installed the library from overlay-from-plan9, the packager went rogue and could have infected it. Remove it as soon as possible.

```
eselect repository enable gentoo-unity7
emaint sync -r gentoo-unity7
emerge -av x11-misc/gtk-nocsd
```

### Fedora

```
sudo dnf copr enable hazel-bunny/ricing
sudo dnf upgrade
sudo dnf install gtk-nocsd
```

### Debian

https://packages.debian.org/search?keywords=libgtk-nocsd0  

### Ubuntu

https://packages.ubuntu.com/search?keywords=libgtk-nocsd0  

### Kali Linux

https://pkg.kali.org/pkg/gtk-nocsd  

### ALT Linux

https://packages.altlinux.org/en/p11/srpms/libgtk-nocsd/  

## Usage

Here the naming was written for a file named libgtk-nocsd.so, available in the packages.  
If manual build was used and the file is named libgtk-nocsd.so.0, it can either be renamed to libgtk-nocsd.so or the instructions can be changed to the new name.  

`LD_PRELOAD=./libgtk-nocsd.so application`
The path can be an absolute path. If only `LD_PRELOAD=libgtk-nocsd.so` is used, it is possible that the binary changes current directory and preloading fails.

For help on setting up individual applications, I recommend my similar setup: https://codeberg.org/MorsMortium/Setup/src/commit/ef00c78e848d88ac0f6d8b426034c672863feacc/UserSetup.sh#L48  
Bear in mind the segment after, where .desktop files get their `DBusActivatable=true` part removed, which fixes them not picking up the library.  
There is also a manual guide: [SingleAppUsage.md](./SingleAppUsage.md)  

The library works globally too, usage combined with gtk3-nocsd is not supported (but also not needed).  
To use it globally, add `export LD_PRELOAD=/path/to/libgtk-nocsd.so` to `~/.bash_profile`, or in case of other system shell, the profile of that.  
When loaded globally, the `DBusActivatable=true` removal is not needed.  

Certain launchers or .desktop files start the application with `gapplication launch` which might not carry the LD_PRELOAD variable.  
this can be solved by creating a ` ~/.config/environment.d` folder, in that a .conf file, the name should not matter, for example `LD_PRELOAD.conf` and in that as content `LD_PRELOAD=/path/to/libgtk-nocsd.so`.  
After a restart these applications or applications started from these launchers will pick up the variable.  

### Options

The library supports some environment variables to influence its behavior:  

- `GTK_CSD`: Setting to 1 disables the library. Setting to 0 is not needed, the library itself does that. Disabling this way might not be as smooth as setting `LD_PRELOAD=""`, since this reloads without library, while `LD_PRELOAD=""` never loads it.
- `GTK_NOCSD_GNOME`: The library is disabled on GNOME by default. Setting to 1 enables it for GNOME.
- `GTK_NOCSD_CSD`: Setting to 1 retains the internal unified CSD of GTK. This can be used on GNOME and certain WMs that do not implement SSD but would want a CSD without application controls.
- `GTK_NOCSD_CSD_PADDING`: Setting to 1 removes padding from internal GTK CSD. This might be needed for some themes.

Make sure to set gtk-decoration-layout to be able to use the internal CSD.  
On GNOME with `gsettings set org.gnome.desktop.wm.preferences button-layout 'icon:minimize,maximize,close'`.  
Generally with editing your `~/.config/gtk-4.0/settings.ini` and/or `~/.config/gtk-3.0/settings.ini` and adding `gtk-decoration-layout=icon:minimize,maximize,close` in the `[Settings]` block.  
The layout was only an example, it is up to preference, documentation is here: https://docs.gtk.org/gtk4/property.Settings.gtk-decoration-layout.html  
Live reloading is not supported.  

### Flatpak

The library can be used as is.

To do so, the easiest is using Flatseal:  
In the All Applications/Filesystem the folder in which the library is has to be added.  
Remember that /usr cannot be shared, if it is there, it has to be moved or copied somewhere else.  
For the packages using the make method (all listed), /opt/gtk-nocsd/libgtk-nocsd.so is available for flatpak.  
Then, in All Applications/Environment the LD_PRELOAD variable has to be added:  
`LD_PRELOAD=/path/to/libgtk-nocsd.so` This is the same path as what was shared.  
These can be done for a single application as well, if that is needed.  

Testing a single application can be done like so:  
`flatpak run --filesystem=/path/to/ --env=LD_PRELOAD=/path/to/libgtk-nocsd.so org.developer.application`

Setting up all applications:  
`flatpak override --user --filesystem=/path/to/ --env=LD_PRELOAD=/path/to/libgtk-nocsd.so`

Setting up a single application:  
`flatpak override --user --filesystem=/path/to/ --env=LD_PRELOAD=/path/to/libgtk-nocsd.so org.developer.application`

Resetting modifications (either done by Flatseal or these commands):  
All applications: `flatpak override --user --reset`  
A single application: `flatpak override --user --reset org.developer.application`  

### Snap

The library is usable with per application setup of Snap applications.  
For instructions follow [SingleSnapUsage.md](./SingleSnapUsage.md)  
However, it is possible, that the way it is preloaded on Ubuntu/Debian, by the system package, it already gets loaded into snaps.  
This on the other hand can cause this issue.  
```
/snap/code/240/usr/share/code/bin/../code: /snap/core20/current/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by /usr/lib/x86_64-linux-gnu/libgtk-nocsd.so.0)
```
This is unlikely to be solvable in a reasonable way on the library side, it is caused by snaps being built against old library versions.  
If this is encountered with an application that does not need the library (like Visual Studio Code in the example), then unsetting it in the .desktop file is a solution.  
This can be done in KDE Menu Editor, by adding `LD_PRELOAD=` to Environment variables field of the application, or by copying the .desktop file from `/var/lib/snapd/desktop/applications` to `~/.local/share/applications`, opening the copied version with a text editor and in the `Exec=` line adding `env LD_PRELOAD= ` (with the extra space) between `Exec=` and the rest of the line.  
For an application that would need the library but encounters this issue, the real solution would be building inside snap, which I have mentioned in this issue already: https://github.com/ubuntu/gnome-sdk/issues/6  

### AppArmor

It is possible that on certain systems where AppArmor is set up to restrict applications from reaching files they should not have access to, the library might not be reachable either.  
One such distribution is Ubuntu.  
In such cases, the AppArmor profile can be edited.  
For example Evince has the profile `/etc/apparmor.d/usr.bin.evince`.  
In this file the block that is the starting binary, `/usr/bin/evince` in this case, has to be edited, the following lines have to be added:  
```
  /opt/gtk-nocsd/libgtk-nocsd.so* mr,
  /usr/local/lib64/libgtk-nocsd.so* mr,
```
This will give it access to the library.  
If the library is located elsewhere, that path has to be set up.  
After this, the profile has to be reloaded with `sudo apparmor_parser -r /etc/apparmor.d/profile.file`.  
It is possible that this needs to be repated after updates, since this file is contained by the package.  
If this happens, you can report it to your distribution.  

## Testing

The library was tested and working with the following applications

### GTK4 and LibAdwaita

- Gnome games
	- Mahjongg
	- Sudoku
	- Mines
	- Nibbles
	- Chess
	- Swell Foop
	- Robots
	- Lights Off
	- Quadrapassel
- Development tools
	- Demo
	- Node Editor
	- Widget Factory
	- Cambalache
	- Adwaita Demo
- Android Translation Layer
- Font Manager
- Dino
- Easy Effects
- vipsdisp
- Gajim
- Mission Center
- Gnome Calls
- Pidgin 3
- Lenspect
- Aether (with using `gjs -m /usr/share/aether/src/main.js` directly (or possibly in `/etc/ld.so.preload`))
- Meld (GTK4 port)
- Pamac

### GTK3 and LibHandy

- Gnome games
	- 2048
	- Five or More
	- Four in a Row
	- Hitori
	- Klotski
	- Tetravex
	- Taquin
	- Atomix
	- Iagno/Reversi
- Development tools
	- Demo
	- Widget Factory
	- Icon Browser
	- Glade
- Lutris
- BleachBit
- SongRec
- Gnome-Pie
- Trackma
- Emote
- HardInfo2
- Pamac (LibHandy version)

The library is intentionally disabled for GTK Inspector windows.
There are no known applications where this does not work.

## Screenshots

### Before

![](./Images/Old1.png)
![](./Images/Old2.png)
![](./Images/Old3.png)
![](./Images/Old4.png)
![](./Images/Old5.png)

### After

![](./Images/New1.png)
![](./Images/New2.png)
![](./Images/New3.png)
![](./Images/New4.png)
![](./Images/New5.png)

### Gnome CSD removal

![](./Images/GNoCSD.png)

## Theming

### GTK3/GTK4

As usual.

### LibHandy/LibAdwaita

Set GTK_THEME variable to theme (folder in `/usr/share/themes` or `~/.themes`).

### Inside flatpak

Copy `/usr/share/themes` to `~/.themes` in case of system theme.  
Pass through `~/.themes` folder to flatpak with `--filesystem=~/.themes`.  
Set theme name with environment variable `--env=GTK_THEME=Breeze:dark`.  
`:dark` is dark preference, `:whatever else` is light preference.  
Not having either (`--env=GTK_THEME=Breeze`) is leaving it to the default.  

## Comparison with GTK3-Classic

### Positives of GTK3-Classic

- It restores more of the classic look and behavior, as listed here: https://github.com/lah7/gtk3-classic/blob/master/README.Patches.md In opposition this library only removes CSD, while keeping original features of CSD, like drag, right click for desktop menu and search buttons. Apart from this it gives a bit of help with theming (enforcing GTK_THEME and setting LibHandy/LibAdwaita dark preference)
- GTK3-Classic is more straightforward to deploy, it is just built and installed like GTK3. In opposition this library might be finicky to get into applications, with finding what places propagate the environment variable and where to put the library, to make it accessible.
- Possibly less error prone. Since the entire GTK3 library is replaced, nothing unexpected can happen. With GTK-NoCSD the internal GTK functions cannot be changed, which can cause issues.
- Does not influence other GTK versions or even not GTK applications. GTK-NoCSD has to have safeguards against breaking GTK2 and applications using GLib or programs using one even lower level function. With global loading the library is present and runs some code in all applications of even CLI commands, unlike GTK3-Classic.

### Positives of GTK-NoCSD

- Works with all GTK versions (GTK3/4/LibHandy/LibAdwaita)
- Works automatically or can be relatively easy to make it work with AppImage, Flatpak, Snap. GTK3-Classic replaces GTK3, which is much harder to do, if possible at all in these packaging methods.
- Works not only on X11 but on Wayland too. On Wayland it can be used to remove the secondary CSD of GTK, which some tiling WMs have an issue with, or to make all applications use this secondary CSD, on GNOME for example (still CSD, but no application controls in the titlebar)
- Much easier to disable fully, momentarily/per application or permanently, unsetting  LD_PRELOAD is enough, while GTK3-Classic needs the original GTK3 installed for full disable.
- Much faster to build (a single file, instead of the entire GTK3)

## Contributions

### Contributions are welcome!

Rules of contribution:

- Use the naming conventions (PascalCase everywhere, no shortening of words)
- Format the code with uncrustify, which can be done with running this command in the root directory: `uncrustify -c ./Uncrustify.cfg --replace ./Source/*.c`
- Keep 80 characters line length (handled by uncrustify in C)
- Never call GTK/GDK/GObject/GLib functions that don't start with o_, unless own function. Exceptions, with `// WARNING: Macro`
	- g_error
	- g_return_val_if_fail
	- g_signal_connect
	- g_signal_handlers_disconnect_by_func
	- g_new0
	- G_DECLARE_FINAL_TYPE
	- G_DEFINE_TYPE
	- GTK_WIDGET_CLASS
	- G_OBJECT_TYPE
	- G_CALLBACK if inside g_signal_connect
- If own replacement function is called comment `// WARNING: Own call`
- If having to cast between signed and unsigned or larger to smaller, add `// WARNING: Downcast`
- Avoid macros, if possible
- The build should not produce any warnings

## Support

### Never open issues for GTK/Gnome apps, when this library is in use.

If you have any problem with any apps, that is caused by this library, report it here.
If there is an issue with an application, that is not caused by the library, make all reports/investigations with the library disabled.
The library won't have a dedicated chat, but feel free to join our Matrix community https://matrix.to/#/%23TheWorldMachineOffTopic%3Amatrix.org?via=matrix.org&via=midov.pl&via=monero.social

## Donation

If you like my work, feel free to donate: https://morsmortium.neocities.org/donation
