Example/Tutorial: Pure Wayland Desktop

[Mod: Discussion/suggestions/requests are moved here: Thread example-tutorial-pure-wayland-desktop-discussion.85994]

Hello,

I was fiddling around quite a bit, to get a completely native Wayland desktop on FreeBSD (without using xwayland, only using programs that are capable to run natively under Wayland).
Since there are some caveats and not too much documentation, I thought I am going to share my setup, maybe it helps others to setup a pure Wayland desktop on FreeBSD if they like to.

Note: The are some absolute path names starting with my home (/home/elgrande) in some files. You will need to change those paths. Unfortunately some parts here do not accept generic paths starting with '~'. I will point out where those cases occur.

Screenshots:

20220802_21h21m41s_grim.png


20220802_21h23m38s_grim.png



DISCLAIMER: Do not bother to try this, when using a Nvidia Graphics card, due to missing drm module, Wayland will not work there yet. Intel GPU works fine for me, AMD should work, too, from what I have read.


Compositor used:
x11-wm/wayfire


Apps I currently use:

Installed packages:
x11/alacritty
www/chromium
sysutils/debootstrap
graphics/drm-kmod
devel/git
x11/grim
graphics/imv
x11/kanshi
x11/mako
audio/pavucontrol
ports-mgmt/pkg
graphics/qt5-wayland
misc/qt5ct
sysutils/seatd
x11/slurp
irc/srain
security/sudo
x11/swayidle
x11/swaylock-effects
editors/vim
multimedia/vlc
editors/vscode
x11-wm/wayfire
x11-wm/wayfire-plugins-extra
graphics/wayland-protocols
x11/wcm
multimedia/webcamd
x11/wf-shell
x11/wlogout
accessibility/wlsunset
pcmanfm-gtk3 (package without own port)


Wayfire config:
~/.config/wf-shell.ini
Code:
[background]
cycle_timeout = 150
image = /home/elgrande/Pictures/freebsd_wp1.jpg
preserve_aspect = false
randomize = false

[dock]
autohide_duration = 300
css_path =
position = bottom

[panel]
autohide = false
autohide_duration = 300
background_color = gtk_headerbar
battery_font = default
battery_icon_invert = true
battery_icon_size = 24
battery_status = 1
clock_font = default
clock_format = %e %A %H:%M
css_path =
launcher_pavucontrol = pavucontrol.desktop
launchers_size = 42
launchers_spacing = 4
layer = top
menu_fuzzy_search = true
menu_icon = /home/elgrande/Pictures/freebsd_logo_icon_border_red.svg
menu_logout_command =
minimal_height = 24
network_icon_invert_color = false
network_icon_size = 32
network_status = 0
network_status_font = default
network_status_use_color = false
position = top
volume_display_timeout = 2.500000
widgets_center = window-list
widgets_left = spacing4 menu spacing18
widgets_right =  launchers clock

Note: 2 absolute paths name (starting with '/home/elgrande') are in the previous file. Please correct that to your home (and path where the pictures are saved). Unfortunately '~' seems to be not supported here.

The wallpaper file can be downloaded from
https://wallpaperset.com/w/full/e/8/3/392566.jpg
and the menu icon can be downloaded from
https://iconscout.com/icons/freebsd
(I am not sure about the exact icon anymore, but choose whatever you like)

~/.config/wayfire/wayfire.ini
Code:
[alpha]
min_value = 0.100000
modifier = <alt> <super>

[animate]
close_animation = zoom
duration = 400
enabled_for = (type equals "toplevel" | (type equals "x-or" & focusable equals true))
fade_duration = 400
fade_enabled_for = type equals "overlay"
fire_duration = 300
fire_enabled_for = none
fire_particle_size = 16.000000
fire_particles = 2000
open_animation = zoom
startup_duration = 600
zoom_duration = 500
zoom_enabled_for = none

[annotate]
clear_workspace = <alt> <super> KEY_C
draw = <alt> <super> BTN_LEFT
from_center = true
line_width = 3.000000
method = draw
stroke_color = \#FF0000FF

[autorotate-iio]
lock_rotation = false
rotate_down = <ctrl> <super> KEY_DOWN
rotate_left = <ctrl> <super> KEY_LEFT
rotate_right = <ctrl> <super> KEY_RIGHT
rotate_up = <ctrl> <super> KEY_UP

[autostart]
autostart_wf_shell = true
gamma = wlsunset
idle = swayidle before-sleep swaylock
notifications = mako
outputs = kanshi
#portal = /usr/libexec/xdg-desktop-portal

#[background-view]
#command = mpv --loop=inf
#file =

[bench]
average_frames = 1
frames_per_update = 3
position = top_center

[blur]
blur_by_default = type is "toplevel"
bokeh_degrade = 1
bokeh_iterations = 15
bokeh_offset = 5.000000
box_degrade = 1
box_iterations = 2
box_offset = 1.000000
gaussian_degrade = 1
gaussian_iterations = 2
gaussian_offset = 1.000000
kawase_degrade = 8
kawase_iterations = 2
kawase_offset = 2.000000
method = kawase
saturation = 1.000000
toggle = none

[command]
#binding_launcher = <super> <shift> KEY_ENTER
binding_lock = <super> <shift> KEY_ESC
binding_logout = <super> KEY_ESC
binding_mute = KEY_MUTE
binding_screenshot = <ctrl> <alt> <shift> KEY_S
binding_screenshot_interactive = <ctrl> <alt> KEY_S
#binding_screenshot = KEY_PRINT
#binding_screenshot_interactive = <shift> KEY_PRINT
binding_terminal = <super> KEY_ENTER
#command_launcher = wofi
command_light_down = decrease_brightness.sh
command_light_up = increase_brightness.sh
command_lock = swaylock
command_logout = wlogout
command_mute = amixer set Master toggle
#command_screenshot = grim $(date '+%F_%T').webp
command_screenshot = cd ~/Screenshots; grim
#command_screenshot_interactive = slurp | grim -g - $(date '+%F_%T').webp
command_screenshot_interactive = cd ~/Screenshots; slurp | grim -g -
command_terminal = alacritty
command_volume_down = mixer vol -5
command_volume_up = mixer vol +5
repeatable_binding_light_down = KEY_BRIGHTNESSDOWN
repeatable_binding_light_up = KEY_BRIGHTNESSUP
repeatable_binding_volume_down = KEY_VOLUMEDOWN
repeatable_binding_volume_up = KEY_VOLUMEUP

[core]
background_color = \#1A1A1AFF
close_top_view = <super> KEY_Q | <alt> KEY_F4
focus_button_with_modifiers = false
focus_buttons = BTN_LEFT | BTN_MIDDLE | BTN_RIGHT
focus_buttons_passthrough = true
max_render_time = -1
plugins = alpha animate autostart command cube expo fast-switcher fisheye grid idle invert move oswitch place resize switcher vswitch window-rules wm-actions wobbly wrot zoom decoration
preferred_decoration_mode = server
vheight = 3
vwidth = 3
xwayland = false
xwayland_scale = 1

[crosshair]
line_color = \#FF0000FF
line_width = 2

[cube]
activate = <alt> <ctrl> BTN_LEFT
background = \#1A1A1AFF
background_mode = simple
cubemap_image =
deform = 0
initial_animation = 350
light = true
rotate_left = none
rotate_right = none
skydome_mirror = true
skydome_texture =
speed_spin_horiz = 0.020000
speed_spin_vert = 0.020000
speed_zoom = 0.070000
zoom = 0.100000

[dbus_interface]

[decoration]
active_color = \#2E3440FF
border_size = 4
button_order = minimize maximize close
font = sans-serif
ignore_views = none
inactive_color = \#353B49FF
title_height = 30

[expo]
background = \#1A1A1AFF
duration = 300
offset = 10
select_workspace_1 = KEY_1
select_workspace_2 = KEY_2
select_workspace_3 = KEY_3
select_workspace_4 = KEY_4
select_workspace_5 = KEY_5
select_workspace_6 = KEY_6
select_workspace_7 = KEY_7
select_workspace_8 = KEY_8
select_workspace_9 = KEY_9
toggle = <super>

[extra-gestures]
close_fingers = 20
move_delay = 500
move_fingers = 3

[fast-switcher]
activate = <alt> KEY_ESC
activate_backward = <alt> <shift> KEY_ESC
inactive_alpha = 0.700000

[fisheye]
radius = 450.000000
toggle = <ctrl> <super> KEY_F
zoom = 7.000000

[follow-focus]
change_output = true
change_view = true
focus_delay = 50
raise_on_top = true
threshold = 10

[force-fullscreen]
constrain_pointer = false
constraint_area = view
key_toggle_fullscreen = <alt> <super> KEY_F
preserve_aspect = true
transparent_behind_views = true
x_skew = 0.000000
y_skew = 0.000000

[grid]
duration = 300
restore = <super> KEY_DOWN | <super> KEY_KP0
slot_b = <super> KEY_KP2
slot_bl = <super> KEY_KP1
slot_br = <super> KEY_KP3
slot_c = <super> KEY_UP | <super> KEY_KP5
slot_l = <super> KEY_LEFT | <super> KEY_KP4
slot_r = <super> KEY_RIGHT | <super> KEY_KP6
slot_t = <super> KEY_KP8
slot_tl = <super> KEY_KP7
slot_tr = <super> KEY_KP9
type = crossfade

[idle]
cube_max_zoom = 1.500000
cube_rotate_speed = 1.000000
cube_zoom_speed = 1000
disable_on_fullscreen = true
dpms_timeout = -1
screensaver_timeout = 3600
toggle = none

[input]
click_method = default
cursor_size = 24
cursor_theme = default
disable_touchpad_while_mouse = false
disable_touchpad_while_typing = false
gesture_sensitivity = 1.000000
kb_capslock_default_state = false
kb_numlock_default_state = false
kb_repeat_delay = 400
kb_repeat_rate = 40
left_handed_mode = false
middle_emulation = false
modifier_binding_timeout = 400
mouse_accel_profile = default
mouse_cursor_speed = 0.500000
mouse_scroll_speed = 1.000000
natural_scroll = false
scroll_method = default
tap_to_click = true
touchpad_accel_profile = default
touchpad_cursor_speed = 0.000000
touchpad_scroll_speed = 1.000000
xkb_layout = de
xkb_model =
xkb_options =
xkb_rules = evdev
xkb_variant =

[input-device]
output =

[invert]
preserve_hue = false
toggle = <super> KEY_I

[join-views]

[keycolor]
color = \#000000FF
opacity = 0.250000
threshold = 0.500000

[mag]
default_height = 500
toggle = <alt> <super> KEY_M
zoom_level = 75

[move]
activate = <super> BTN_LEFT
enable_snap = true
enable_snap_off = true
join_views = false
quarter_snap_threshold = 50
snap_off_threshold = 10
snap_threshold = 10
workspace_switch_after = -1

[oswitch]
next_output = <super> KEY_O
next_output_with_win = <shift> <super> KEY_O

[output]
mode = auto
position = auto
scale = 1.000000
transform = normal

[place]
mode = center

[preserve-output]
last_output_focus_timeout = 10000

[resize]
activate = <super> BTN_RIGHT

[scale]
allow_zoom = false
bg_color = \#1A1A1AE6
duration = 750
inactive_alpha = 0.750000
interact = false
middle_click_close = false
spacing = 50
text_color = \#CCCCCCFF
title_font_size = 16
title_overlay = all
title_position = center
toggle = <super> KEY_P
toggle_all =

[scale-title-filter]
bg_color = \#00000080
case_sensitive = false
font_size = 30
overlay = true
share_filter = false
text_color = \#CCCCCCCC

[showrepaint]
reduce_flicker = true
toggle = <alt> <super> KEY_S

[simple-tile]
button_move = <super> BTN_LEFT
button_resize = <super> BTN_RIGHT
inner_gap_size = 5
keep_fullscreen_on_adjacent = true
key_focus_above = <super> KEY_K
key_focus_below = <super> KEY_J
key_focus_left = <super> KEY_H
key_focus_right = <super> KEY_L
key_toggle = <super> KEY_T
outer_horiz_gap_size = 0
outer_vert_gap_size = 0
tile_by_default = all

[switcher]
next_view = <alt> <shift> KEY_TAB
prev_view = <alt> KEY_TAB
speed = 500
view_thumbnail_scale = 1.000000

[vswipe]
background = \#1A1A1AFF
delta_threshold = 24.000000
duration = 180
enable_free_movement = false
enable_horizontal = true
enable_smooth_transition = false
enable_vertical = true
fingers = 4
gap = 32.000000
speed_cap = 0.050000
speed_factor = 256.000000
threshold = 0.350000

[vswitch]
background = \#1A1A1AFF
binding_down = <ctrl> <super> KEY_DOWN
binding_left = <ctrl> <super> KEY_LEFT
binding_right = <ctrl> <super> KEY_RIGHT
binding_up = <ctrl> <super> KEY_UP
binding_win_down = <ctrl> <shift> <super> KEY_DOWN
binding_win_left = <ctrl> <shift> <super> KEY_LEFT
binding_win_right = <ctrl> <shift> <super> KEY_RIGHT
binding_win_up = <ctrl> <shift> <super> KEY_UP
duration = 300
gap = 20
wraparound = false

[water]
activate = <ctrl> <super> BTN_LEFT

[windecor]
active_color = \#222222AA
border_size = 4
button_order = minimize maximize close
close_color = \#CC000077
font = sans-serif
ignore_views = none
inactive_color = \#333333DD
maximize_color = \#09FF0077
minimize_color = \#EDD40077
title_height = 24

[window-rules]

[winzoom]
dec_x_binding = <ctrl> <super> KEY_LEFT
dec_y_binding = <ctrl> <super> KEY_UP
inc_x_binding = <ctrl> <super> KEY_RIGHT
inc_y_binding = <ctrl> <super> KEY_DOWN
modifier = <ctrl> <super>
nearest_filtering = false
preserve_aspect = true
zoom_step = 0.100000

[wm-actions]
minimize = none
send_to_back = none
toggle_always_on_top = none
toggle_fullscreen = none
toggle_maximize = none
toggle_showdesktop = none
toggle_sticky = none

[wobbly]
friction = 3.000000
grid_resolution = 6
spring_k = 8.000000

[workarounds]
all_dialogs_modal = true
app_id_mode = stock
dynamic_repaint_delay = false

[workspace-names]
background_color = \#333333B3
display_duration = 500
font = sans-serif
position = center
show_option_names = false
text_color = \#FFFFFFFF

[wrot]
activate = <ctrl> <super> BTN_RIGHT
activate-3d = <shift> <super> BTN_RIGHT
invert = false
reset = <ctrl> <super> KEY_R
reset-one = <super> KEY_R
reset_radius = 25.000000
sensitivity = 24

[zoom]
modifier = <super>
smoothing_duration = 300
speed = 0.010000

Note: There are some shortcuts defined in the file above, so it is worth to have a look. E.g. '<ctrl> <alt> KEY_S' will make a interactive screenshot of an selected area and save it in ~/Screenshots. Not all shortcuts work yet, I will update this on progress.


Theme:
https://www.gnome-look.org/p/1267246/
Download 'Nordic.tarxz', extract and move 'Nordic-v40' to ~/.themes.
Make the following setting in ~/.config/gtk-3.0/settings.ini
Code:
gtk-application-prefer-dark-theme=true


Startup skript:
wayfirewayland.csh
Code:
#!/bin/csh
setenv XDG_RUNTIME_DIR /var/run/user/`id -u`
setenv GTK_THEME Nordic-v40
setenv GDK_BACKEND wayland
setenv QT_QPA_PLATFORM wayland
setenv QT_QPA_PLATFORMTHEME qt5ct
setenv LC_ALL de_DE.UTF-8
setenv LANG de_DE.UTF-8
wayfire -c ~/.config/wayfire/wayfire.ini

Note: Choose any language here, in my example this is german.

Call the script with csh wayfirewayland.csh

Note: The logoff button has been deactivated and currently has no function, since it cause strange problems requiring a reboot. In order to exit the session use '<ctrl> <alt> <backspace>'.


Fixed application launchers:
Some launchers need to be fixed (overwritten) order to support Wayland.
This can be done in wayfire by putting the changed .desktop file into ~/.local/share/applications
Here is what they contain:

~/.local/share/applications/chromium-browser.desktop
Code:
[Desktop Entry]
Type=Application
Version=1.0
Encoding=UTF-8
Name=Chromium
Comment=Google web browser based on WebKit (Wayland)
Icon=chrome
Exec=chrome --enable-features=UseOzonePlatform --ozone-platform=wayland %U
Categories=Application;Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;
StartupNotify=true

~/.local/share/applications/code-oss.desktop
Code:
[Desktop Entry]
Name=Code - OSS
Comment=Code Editing. Redefined.
GenericName=Text Editor
Exec=/usr/local/bin/code-oss --enable-features=UseOzonePlatform,WaylandWindowDecorations --ozone-platform=wayland --unity-launch %F
Icon=com.visualstudio.code.oss
Type=Application
StartupNotify=false
StartupWMClass=Code - OSS
Categories=TextEditor;Development;IDE;
MimeType=text/plain;inode/directory;application/x-code-oss-workspace;
Actions=new-empty-window;
Keywords=vscode;

[Desktop Action new-empty-window]
Name=New Empty Window
Exec=/usr/local/bin/code-oss --new-window %F
Icon=com.visualstudio.code.oss
elgrande@elawfreebsdo:~ %

~/.local/share/applications/brave-linux.desktop
Code:
[Desktop Entry]
Type=Application
Name=Brave (Linux)
Encoding=UTF-8
Comment=Brave Browser (Wayland)
Icon=/home/elgrande/Pictures/brave_browser_icon.png
Exec=/home/elgrande/bin/brave-linux.sh
Terminal=false
Categories=Application;Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;
StartupNotify=true

~/.local/share/applications/spotify.desktop
Code:
[Desktop Entry]
Type=Application
Name=Spotify
GenericName=Music Player
#Icon=spotify-client
Icon=/home/elgrande/icons/spotify-logo-256x256.ico
Exec=/home/elgrande/bin/spotify.sh
Terminal=false
MimeType=x-scheme-handler/spotify;
Categories=Audio;Music;Player;AudioVideo;
StartupWMClass=spotify

Note: 2 absolute paths name (starting with '/home/elgrande') are in the previous 2 files since '~' is not supported here. Please correct that to your home (and path where the files are).

A link to an install howto for the Linux Brave Browser and for Spotify is further down in this post.

The following 2 desktop files hide unnecessary starter entries.

~/.local/share/applications/libfm-pref-apps.desktop
Code:
[Desktop Entry]
NoDisplay=true

~/.local/share/applications/pcmanfm-desktop-pref.desktop
Code:
[Desktop Entry]
NoDisplay=true


Helper scripts:
The following files are used in ~/.config/wayfire/wayfire.ini so that the laptops brightness buttons can be used.

The following entry of 'acpi_video' is required in
/etc/rc.conf
Code:
kld_list="i915kms acpi_video"
and the following file
/usr/local/etc/sudoers.d/brightness
Code:
elgrande ALL = (root) NOPASSWD: /sbin/sysctl
has to be added.
You can of course leave all that stuff away if you do not want to use your brightness buttons, do not have them or aren't using a laptop.

~/bin/increase_brightness.sh
Code:
#!/bin/sh
CURRENT_VAL=`sysctl hw.acpi.video.lcd0.brightness | awk '{print $2}'`
NEW_VAL=$(expr $CURRENT_VAL + 10)
if [ $NEW_VAL -le 100 ]
then
    sudo sysctl hw.acpi.video.lcd0.brightness=$NEW_VAL
else
    sudo sysctl hw.acpi.video.lcd0.brightness=100
fi
~/bin/decrease_brightness.sh
Code:
#!/bin/sh
CURRENT_VAL=`sysctl hw.acpi.video.lcd0.brightness | awk '{print $2}'`
NEW_VAL=$(expr $CURRENT_VAL - 10)
if [ $NEW_VAL -ge 0 ]
then
    sudo sysctl hw.acpi.video.lcd0.brightness=$NEW_VAL
else
    sudo sysctl hw.acpi.video.lcd0.brightness=0
fi

The following file requires Brave Browser to be installed in a Ubuntu jail under /compat/ubuntu.
~/bin/brave-linux.sh
Code:
#!/bin/sh

get_pa_sock_path()
{
    PA_SOCK_PATH=$(sockstat | awk -v me=$(whoami) -F'[ \t]+' '
        $1 == me && $2 == "pulseaudio" && $6 ~ /native/ {
            print $6;
            exit 0
        }'
    )
}

get_pa_sock_path
if [ ! -S "$PA_SOCK_PATH" ]; then
    while killall pulseaudio; do
        sleep 0.5
    done
    pulseaudio --start
    get_pa_sock_path
fi
[ -S "$PA_SOCK_PATH" ] && export PULSE_SERVER=unix:$PA_SOCK_PATH
/compat/ubuntu/opt/brave.com/brave/brave --enable-features=UseOzonePlatform --ozone-platform=wayland --no-sandbox --no-zygote --test-type --v=0

The following file requires Spotify to be installed in a Ubuntu jail under /compat/ubuntu.
~/bin/spotify.sh
Code:
#!/bin/sh

get_pa_sock_path()
{
    PA_SOCK_PATH=$(sockstat | awk -v me=$(whoami) -F'[ \t]+' '
        $1 == me && $2 == "pulseaudio" && $6 ~ /native/ {
            print $6;
            exit 0
        }'
    )
}

get_pa_sock_path
if [ ! -S "$PA_SOCK_PATH" ]; then
    while killall pulseaudio; do
        sleep 0.5
    done
    pulseaudio --start
    get_pa_sock_path
fi
[ -S "$PA_SOCK_PATH" ] && export PULSE_SERVER=unix:$PA_SOCK_PATH
LD_PRELOAD=/compat/ubuntu/root/xstub.so /compat/ubuntu/usr/bin/spotify --enable-features=UseOzonePlatform --ozone-platform=wayland


Linux Brave Browser

For the installation of the Linux Brave Browser I found a nice tutorial at https://forums.freebsd.org/threads/linuxulator-how-to-install-brave-linux-app-on-freebsd-13-0.78879/


Spotify
A good tutorial for running Linux Spotify on FreeBSD can be found here at https://www.micski.dk/2022/01/19/how-to-install-spotify-on-freebsd/


Windows Decorations

In some apps like Chromium or Brave Linux you have to switch of the client side decorations in setting and choose to use system's decorations, otherwise you will have the windows buttons twice.


Cursor Theme

If you have problems with cursors not changing, e.g. on window resize, installing a GTK cursor theme may help. See https://wiki.archlinux.org/title/Cursor_themes for details on manual installation.


Problem with /var/run/user/<UID>

If you have problems with Wayfire not starting due to some authorization problem with directory /var/run/user/<UID> remove the whole directory and recreate it empty under the ownership of the corresponding user.


last edit: 2022-08-05
Edit log:
2022-08-02: Switched to server side decorations for unified title bars. Added info for Spotify.
2022-08-03: Added section with hint for cursor problems.
2022-08-05: Added working file manager.
2023-02-03: Added a commonly know problem with the solution.
2024-01-05: Removed remark that Wayland does not run with Nvidia.
 
Last edited:
Back
Top