Declarative MATE configuration using NixOS

MATE 1.28.2, last update on 16/06/2024.

Warning: this post is a stub and contains loads of gramatical errors. I'm sorry about that.


This post is inspired by Declarative GNOME configuration with NixOS.

To follow this simple tutorial, you need to have home-manager installed. With home-manager you can set dconf values with dconf.settings, we can use this option to setup almost everything on MATE.

Themes and icons

You can check the names by applying them using MATE's appearance settings.

"org/mate/desktop/interface" = {
	gtk-theme = "menta";
	icon-theme = "mate";
	font-name = "Sans 10"; 
	document-font-name = "Sans 10"; 
	monospace-font-name = "Monospace 10"; 
};

You can also set the background from here:

"org/mate/desktop/background" = {
	picture-filename = "/path/to/image.png"; 
};

The window manager configuration, called "Marco", is separated from this.

"org/mate/marco/general" = {
	theme = "menta";
	titlebar-uses-system-font = false; 
};

Mate's terminal

Colors need to be in hex format with #. For example: #00FF00 (#RRGGBB; in this case, it's lime green).

Opacity should be set with background-darkness.

The palette is configured in a different way: it's separated with colons, and uses the following order: white:red:green:yellow:blue:magenta:cyan:black:white2:bright-red:bright-green:bright-yellow:bright-blue:bright-cyan:black2

If you use stylix you can copy the order from the console's home-manager file: "${base00}:${red}:${green}:${yellow}:${blue}:${magenta}:${cyan}:${base05}:${base03}:${bright-red}:${bright-green}:${yellow}:${bright-blue}:${bright-cyan}:${base06}".

"org/mate/terminal/profiles/default" = {
	background-color = "#000000";
	background-darkness = 0.9;
	background-type = "transparent";
	foreground-color = "#FFFFFF";
	palette = "${white}:${red}:..."; #continue 
	use-theme-colors = false;
	use-system-font = true;
};

Shortcuts

To edit this easily, download dconf-editor from nixpkgs, edit the shortcuts using mate-keybinding-properties and check the new entries in dconf.

<Mod4> is the Super key; everything else has common names.

"org/mate/marco/global-keybindings" = {
	panel-run-dialog = "<Mod4>d";
	switch-to-workspace-1 = "<Mod4>1";
	switch-to-workspace-2 = "<Mod4>2";
	switch-to-workspace-3 = "<Mod4>3"; 
	switch-to-workspace-4 = "<Mod4>4";
};

The shortcuts from the Marco (the window manager) are separated as well.

"org/mate/marco/window-keybindings" = {
	close = "<Shift><Mod4>q";
	maximize = "<Mod4>Up";
	unmaximize = "<Mod4>Down";
	tile-to-side-e = "<Mod4>Right";
	tile-to-side-w = "<Mod4>Left";

	move-to-workspace-1 = "<Mod4><Shift>1";
	move-to-workspace-2 = "<Mod4><Shift>2";
	move-to-workspace-3 = "<Mod4><Shift>3"; 
	move-to-workspace-4 = "<Mod4><Shift>4";
};

Panel

We can edit some basic panel settings. Check dconf-editor for more options:

"org/mate/panel/toplevels/top/background" = {
	auto-hide = false;
	enable-buttons = false;
	image = "/full/path/to/image.png";
	type = "image";
};
"org/mate/panel/toplevels/bottom/background" = { 
	image = "/full/path/to/image.png";
	type = "image";
};

Well, let's go to the annoying part: editing the panel's objects.

First, we need to setup the applet and launcher IDs. The following is just an example; I recommend you give a name to every single applet and launcher.

"org/mate/panel/general" = {
    "object-id-list" =  [
        #top
        "menu-bar" 
        "mate-screenshot" 
        "sensors-applet" 
        "ayatana-indicator-full" 
        #bottom
        "window-list" 
    ];
};

The first applet is the menu-bar. It is not considered an applet, so the object-type is set to menu-bar.

"org/mate/panel/objects/menu-bar" = { 
    locked = true;
    object-type = "menu-bar";
    panel-right-stick = false;
    position = 0;
    toplevel-id = "top";
};

We also can also change the icon-name. Just make sure to set it to the nice nix snowflake :). Note that this path will not change if the object name of menu-bar is altered.

"org/mate/panel/menubar" = {
    show-icon = true;
    icon-name = "nix-snowflake"; 
};

The second applet is a launcher. It's also not considered an applet. Note that we have incremented the position from 1; we can keep increasing this number to get each object's location. launcher-location can just be the application desktop file name; you don't need to send its entire path.

"org/mate/panel/objects/mate-screenshot" = {
    launcher-location = "mate-screenshot.desktop"; 
    object-type = "launcher";
    panel-right-stick = false;
    position = 1;
    toplevel-id = "top";
};

Now we can check the first real applet. This time we need to set applet-iid; again, the easiest way is to add the applet into the panel and check how we should set its values. Note that since we have changed panel-right-stick to true, this will change the location of the object: it's now on the right, and the rightmost object is 0.

"org/mate/panel/objects/sensors-applet" = {
    locked = true;
    object-type = "applet";
    applet-iid = "SensorsAppletFactory::SensorsApplet"; 
    panel-right-stick = true;
    position = 1;
    toplevel-id = "top";
};

Inside the prefs folder, we can find the configuration values for most applets.

"org/mate/panel/objects/sensors-applet/prefs".timeout-delay = 5000;

To edit objects from the bottom panel, you just need to change toplevel-id to "bottom".

Ayatana indicators

The indicators used on Ubuntu Mate can also be setup on NixOS; the pros being that events from Evolution and Thunderbird will show on the time applet.

First, we need to enable this service on nixos (not home-manager), so make sure to add every indicator you want into the packages option.

services.ayatana-indicators = {
    enable = true;
    packages = with pkgs; [
        ayatana-indicator-datetime 
        ayatana-indicator-display
        ayatana-indicator-messages
        ayatana-indicator-power
        ayatana-indicator-session
        ayatana-indicator-sound
        #ayatana-webmail
    ];
};

Going back to home-manager we can now configure the indicator applet.

"org/mate/panel/objects/ayatana-indicator-full" = {
    locked = true;
    object-type = "applet";
    applet-iid = "IndicatorAppletCompleteFactory::IndicatorAppletComplete"; 
    panel-right-stick = true;
    position = 0;
    toplevel-id = "top";
};

Sadly nix currently doesn't package ayatana-settings, so we need to check each gsettings from its GitHub repository. However, they can be configured from dconf:

"org/ayatana/indicator/datetime" = { 
    show-seconds = true;
    show-date = true;
    show-day = true;
};

Autostart

Mate uses XDG's autostart specification; you can just copy application desktop files inside ~/.config/autostart or create a simple function to do that:

let autostartString = (val: '' 
    [Desktop Entry]
    Type=Application
    Exec=${val}
    Hidden=false
    Name=${val}
    X-MATE-Autostart-Delay=2
    '');
xdg.configFile."autostart/thunderbird.desktop".text = autostartString "thunderbird";

Thank you, Tiagoquix, for proofreading my text.