Skip to content

Instantly share code, notes, and snippets.

@tdcosta100
Last active November 9, 2024 21:09
Show Gist options
  • Save tdcosta100/e28636c216515ca88d1f2e7a2e188912 to your computer and use it in GitHub Desktop.
Save tdcosta100/e28636c216515ca88d1f2e7a2e188912 to your computer and use it in GitHub Desktop.
A tutorial to use GUI in WSL2/WSLg replacing original Xorg by Xwayland, allowing WSL to work like native Linux, including login screen

Full desktop shell in WSL2 using WSLg (XWayland)

Note

If you want to use Wayland in WSLg in a simpler setup, you can try the WSLg (Wayland) tutorial.

In this tutorial, we will setup GUI in WSL2. No additional software outside WSL (like VcXsrv or GWSL) is required. You will find this tutorial very similar to the one that replaces Xorg with Xvnc. Indeed, it's pretty much the same tutorial, with some few changes.

The key component we need to install is the desktop metapackage you want (GNOME, KDE, Xfce, Budgie, etc), and after that, replace the default Xorg by a script that calls Xwayland instead.

For this setup, I will use Ubuntu 24.04, and install GNOME Desktop. Unfortunately older versions of Ubuntu lack some fundamental things, so we cannot reproduce it in older versions (at least not fully). Since the key components aren't bound to Ubuntu or GNOME, you can use your favorite distro and GUI. Check the Sample screenshots section for examples.

So let's go. First, we need a working WSL2 installation.

Warning

WSLg may not work as expected, since Wayland sockets are disabled for everyone, and not every app can handle this. But if you want to use Wayland apps natively, you can use the command export XDG_RUNTIME_DIR=$HOME/runtime-dir and then start your WSLg app.

Before going to real business, let's make sure we are updated.

sudo apt update
sudo apt upgrade

You also need to make sure /etc/wsl.conf have the following lines:

[boot]
systemd=true

If not, create/edit this file, add these lines and restart WSL (for example, using wsl.exe --shutdown, then reopening the distro terminal).

Now we are ready to go.

Installing components

Installing GUI

  1. First you select your favorite desktop environment metapackage. Here is a list of the most common metapackages:

    DistroDesktop EnvironmentMetapackage
    UbuntuBudgieubuntu-budgie-desktop (currently very buggy, I don't recommend using it)
    GNOMEubuntu-desktop
    KDEkubuntu-desktop
    Kylinubuntukylin-desktop
    LXDElubuntu-desktop
    MATEubuntu-mate-desktop
    Studioubuntustudio-desktop
    Unityubuntu-unity-desktop
    Xfcexubuntu-desktop
    Ubuntu/DebianCinnamontask-cinnamon-desktop
    GNOMEtask-gnome-desktop
    GNOME Flashbacktask-gnome-flashback-desktop
    KDE Plasmatask-kde-desktop
    LXDEtask-lxde-desktop
    LXQttask-lxqt-desktop
    MATEtask-mate-desktop
    Xfcetask-xfce-desktop
  2. Once you have chosen the metapackage, let's install it. For example, if you choose ubuntu-desktop, the command will be:

    sudo apt install ubuntu-desktop xwayland
    

    This will install the ubuntu-desktop and xwayland (if not already included as dependency for your metapackage). The installation will take a while, so be patient.

  3. If in Ubuntu, you may want to install snap-store. If you don't need it, you can skip this step:

    sudo snap install snap-store
    

Configuring the environment

If you are using Debian, you need to configure the locale (this is not needed in Ubuntu):

echo "LANG=en_US.UTF-8" | sudo tee -a /etc/default/locale

Create and modify services

  1. Now we have everything installed, we need to fix the directory /tmp/.X11-unix/, because it's mounted as read-only by default. We will create a new systemd unit:

    sudo systemctl edit --full --force wslg-fix.service
    
  2. Paste the code below in the editor:

    [Service]
    Type=oneshot
    ExecStart=-/usr/bin/umount /tmp/.X11-unix
    ExecStart=/usr/bin/rm -rf /tmp/.X11-unix
    ExecStart=/usr/bin/mkdir /tmp/.X11-unix
    ExecStart=/usr/bin/chmod 1777 /tmp/.X11-unix
    ExecStart=/usr/bin/ln -s /mnt/wslg/.X11-unix/X0 /tmp/.X11-unix/X0
    ExecStart=/usr/bin/chmod 0777 /mnt/wslg/runtime-dir
    ExecStart=/usr/bin/chmod 0666 /mnt/wslg/runtime-dir/wayland-0.lock
    
    [Install]
    WantedBy=multi-user.target
    
  3. Exit the editor saving the changes to the file.

  4. Let's enable wslg-fix.service:

    sudo systemctl enable wslg-fix.service
    
  5. We also need to remove all references to Wayland, because if not, some apps (gnome-terminal, for example) will open outside the desktop shell. We will edit the user-runtime-dir@.service service:

    sudo systemctl edit user-runtime-dir@.service
    
  6. Paste the code below in the editor:

    [Service]
    ExecStartPost=-/usr/bin/rm -f /run/user/%i/wayland-0 /run/user/%i/wayland-0.lock
    

Warning

Please read the editor instructions about the correct place to position the text cursor before pasting. If you paste the code in the wrong place, it will be discarded.

  1. Exit the editor saving the changes to the file.

  2. Now we will change the default startup target, because if not, a shell window will appear everytime you start your distro (for example, opening a Terminal of your distro in Windows).

    sudo systemctl set-default multi-user.target
    

Replacing default Xorg by XWayland

By default, the display manager call multiple Xorg instances, one for each user session, including the login screen, provided by GDM (if you are using the GDM as your display manager, of course). So we will replace Xorg script by a new version which calls Xwayland instead the classic Xorg. This is the real magic we are trying to do.

  1. First, let's backup the original Xorg script.

    sudo mv /usr/bin/Xorg /usr/bin/Xorg.original
    
  2. Then, we create a new Xorg script.

    sudo nano /usr/bin/Xorg.Xwayland
    
  3. Paste the code below in the editor:

    #!/bin/bash
    for arg do
      shift
      case $arg in
        # Xwayland doesn't support vtxx argument. So we convert to ttyxx instead
        vt*)
          set -- "$@" "${arg//vt/tty}"
          ;;
        # -keeptty is not supported at all by Xwayland
        -keeptty)
          ;;
        # -novtswitch is not supported at all by Xwayland
        -novtswitch)
          ;;
        # other arguments are kept intact
        *)
          set -- "$@" "$arg"
          ;;
      esac
    done
    
    # Check if the runtime dir is present, and create it if not
    if [ ! -d $HOME/runtime-dir ]
    then
     mkdir $HOME/runtime-dir
     ln -s /mnt/wslg/runtime-dir/wayland-0 /mnt/wslg/runtime-dir/wayland-0.lock $HOME/runtime-dir/
    fi
    
    # Point the XDG_RUNTIME_DIR variable to $HOME/runtime-dir
    export XDG_RUNTIME_DIR=$HOME/runtime-dir
    
    # Find an available display number
    for displayNumber in $(seq 1 100)
    do
      [ ! -e /tmp/.X11-unix/X$displayNumber ] && break
    done
    
    # Here you can change or add options to fit your needs
    command=("/usr/bin/Xwayland" ":${displayNumber}" "-geometry" "1920x1080" "-fullscreen" "$@")
    
    systemd-cat -t /usr/bin/Xorg echo "Starting Xwayland:" "${command[@]}"
    
    exec "${command[@]}"
    

    Please note the resolution of the virtual screen. You can change that to fit your needs (1366x768, 3840x2160, etc).

  4. Exit the editor saving the changes.

  5. Finally, we set the correct permissions for the file and create a link to it:

    sudo chmod 0755 /usr/bin/Xorg.Xwayland
    sudo ln -sf Xorg.Xwayland /usr/bin/Xorg
    

Warning

Sometimes, system updates replace Xorg link with the original version. Just repeat this step if this happens, and Xwayland will work again as Xorg replacement.

Configuring the monitor resolution under GDM and GNOME

Currently, one of the annoying things is the resolution of Xwayland. Even with the -geometry switch, GDM and GNOME don't not respect it. Fortunately, this can be overriden by creating a monitors.xml file. Let's do it then.

  1. First, we create it in the current user directory:

    mkdir ~/.config
    nano ~/.config/monitors.xml
    
  2. Paste the code below in the editor (here it is configured for a 1920x1080 resolution, so change it to reflect your resolution if necessary):

    <monitors version="2">
      <configuration>
        <logicalmonitor>
          <x>0</x>
          <y>0</y>
          <scale>1</scale>
          <primary>yes</primary>
          <monitor>
            <monitorspec>
              <connector>XWAYLAND0</connector>
              <vendor>unknown</vendor>
              <product>unknown</product>
              <serial>unknown</serial>
            </monitorspec>
            <mode>
              <width>1920</width>
              <height>1080</height>
              <rate>59.963</rate>
            </mode>
          </monitor>
        </logicalmonitor>
      </configuration>
    </monitors>
  3. Exit the editor saving the changes to the file.

  4. Now let's copy this file to GDM's home directory:

    sudo mkdir /var/lib/gdm3/.config
    sudo cp ~/.config/monitors.xml /var/lib/gdm3/.config/
    
  5. Finally, we set the correct permissions to the monitors.xml of GDM user:

    sudo chown -R gdm:gdm /var/lib/gdm3/.config/
    
  6. Restart WSL using wsl.exe --shutdown, then reopen your distro terminal.

Running your distro with GUI enabled

Now you have everything ready to start. Just do the following command:

sudo systemctl start graphical.target

After a while (usually a few seconds, but it can take more if you don't have a SSD), the login screen must appear.

After logging in, the logged user's desktop must appear. When you log out, the screen will show the login interface again. This applies to GDM (which is the case if you installed Ubuntu Desktop). In GDM, you can change this behavior changing the configuration file like this:

  1. sudo nano /etc/gdm3/custom.conf

  2. Uncomment and edit the following lines:

     AutomaticLoginEnable=true
     AutomaticLogin=[your username without the brackets]
    

Shutting down

One important thing is: once you start your WSL instance, you cannot just stop it. You must perform a standard Linux shutdown. You can do one of the alternatives below:

  • Power off option on GUI menu
  • sudo poweroff

After doing that, you can safely shut down your WSL instance, either by wsl.exe --terminate or wsl.exe --shutdown. Not doing the shutdown process may cause damage to your WSL instance. So be careful.

Troubleshooting

  1. If it doesn't work at first, try to check your journalctl logs:

    journalctl -b -t /usr/lib/gdm3/gdm-x-session -t /usr/bin/Xorg --no-pager
    

    If you are using Debian, then the command is:

    journalctl -b -t /usr/libexec/gdm-x-session -t /usr/bin/Xorg --no-pager
    

    In the output, you must see what command line was generated for Xwayland, and which error messages appear. Of course, even if it works correctly, you can check the logs just to see what is happening, or for debugging.

  2. You must check if the custom Xorg script was not replaced by the default version of it. If it was the case, just repeat the steps of Replacing default Xorg by Xwayland section.

  3. Check if Xorg is your default display server, not Xephyr or Wayland. If it's not, you must change it to have Xorg as your default display server.

  4. If you are using LightDM, you also need to check logs at /var/log/lightdm (you will need to use sudo to cat files in that directory). The Xwayland output will be in the file /var/log/lightdm/x-0.log.

  5. If it still doesn't work, you can try to restart WSL with wsl.exe --shutdown (don't forget to save everything that is unsaved before, because WSL will shut down completely), then open your distro terminal again and repeat the steps of section Running your distro with GUI enabled.

Sample screenshots

GDM

GDM

LightDM (Kubuntu)

LightDM

GNOME

GNOME

KDE (Kubuntu)

KDE

LXDE (Lubuntu)

LXDE

Xfce (Xubuntu)

Xfce

Contributors

Thanks to this guys, whose feedback made this tutorial reach the current level of quality and completeness (and it will be more and more complete as more feedback is given).

@noorez
Copy link

noorez commented Sep 30, 2024

Running in debian 12 and this is what I get (-geometry is unrecognized..)

Sep 30 10:19:42 EDNOOREZK /usr/bin/Xorg[963]: Starting Xwayland: /usr/bin/Xwayland :1 -geometry 1920x1080 -fullscreen tty1 -displayfd 3 -auth /run/user/115/gdm/Xauthority -nolisten tcp -background none -noreset -verbose 3
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: Unrecognized option: -geometry
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: use: X [:<display>] [option]
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -a #                   default pointer acceleration (factor)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -ac                    disable access control restrictions
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -audit int             set audit trail level
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -auth file             select authorization file
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -br                    create root window with black background
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: +bs                    enable any backing store support
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -bs                    disable any backing store support
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -c                     turns off key-click
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: c #                    key-click volume (0-100)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -cc int                default color visual class
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -nocursor              disable the cursor
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -core                  generate core dump on fatal error
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -displayfd fd          file descriptor to write display number to when ready to connect
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -dpi int               screen resolution in dots per inch
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -dpms                  disables VESA DPMS monitor control
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -f #                   bell base (0-100)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -fakescreenfps #       fake screen default fps (1-600)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -fp string             default font path
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -help                  prints message with these options
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: +iglx                  Allow creating indirect GLX contexts
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -iglx                  Prohibit creating indirect GLX contexts (default)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -I                     ignore all remaining arguments
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -ld int                limit data space to N Kb
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -lf int                limit number of open files to N
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -ls int                limit stack space to N Kb
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -nolock                disable the locking mechanism
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -maxclients n          set maximum number of clients (power of two)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -nolisten string       don't listen on protocol
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -listen string         listen on protocol
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -noreset               don't reset after last client exists
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -background [none]     create root window with no background
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -reset                 reset after last client exists
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -p #                   screen-saver pattern duration (minutes)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -pn                    accept failure to listen on all ports
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -nopn                  reject failure to listen on all ports
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -r                     turns off auto-repeat
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: r                      turns on auto-repeat
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -render [default|mono|gray|color] set render color alloc policy
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -retro                 start with classic stipple and cursor
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -s #                   screen-saver timeout (minutes)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -seat string           seat to run on
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -t #                   default pointer threshold (pixels/t)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -terminate [delay]     terminate at server reset (optional delay in sec)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -tst                   disable testing extensions
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: ttyxx                  server started from init on /dev/ttyxx
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: v                      video blanking for screen-saver
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -v                     screen-saver without video blanking
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -wr                    create root window with white background
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -maxbigreqsize         set maximal bigrequest size
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: +xinerama              Enable XINERAMA extension
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -xinerama              Disable XINERAMA extension
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -dumbSched             Disable smart scheduling and threaded input, enable old behavior
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -schedInterval int     Set scheduler interval in msec
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -sigstop               Enable SIGSTOP based startup
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: +extension name        Enable extension
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -extension name        Disable extension
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:  Only the following extensions can be run-time enabled/disabled:
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         Generic Event Extension
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         MIT-SHM
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         XTEST
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         XINERAMA
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         XFIXES
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         RENDER
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         RANDR
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         COMPOSITE
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         DAMAGE
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         MIT-SCREEN-SAVER
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         DOUBLE-BUFFER
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         RECORD
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         DPMS
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         X-Resource
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         XVideo
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         XVideo-MotionCompensation
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:         GLX
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -query host-name       contact named host for XDMCP
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -broadcast             broadcast for XDMCP
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -multicast [addr [hops]] IPv6 multicast for XDMCP
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -indirect host-name    contact named host for indirect XDMCP
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -port port-num         UDP port number to send messages to
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -from local-address    specify the local address to connect from
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -once                  Terminate server after one session
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -class display-class   specify display class to send in manage
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -cookie xdm-auth-bits  specify the magic cookie for XDMCP
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -displayID display-id  manufacturer display ID for request
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: [+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]:                        enable/disable accessx key sequences
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -ardelay               set XKB autorepeat delay
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -arinterval            set XKB autorepeat interval
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -rootless              run rootless, requires wm support
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -wm fd                 create X client for wm on given fd
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -initfd fd             add given fd as a listen socket for initialization clients
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -listenfd fd           add given fd as a listen socket
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -listen fd             deprecated, use "-listenfd" instead
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -eglstream             use eglstream backend for nvidia GPUs
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -shm                   use shared memory for passing buffers
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -verbose [n]           verbose startup messages
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -version               show the server version and exit
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: -noTouchPointerEmulation  disable touch pointer emulation
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: (EE)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: Fatal server error:
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: (EE) Unrecognized option: -geometry
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[961]: (EE)
Sep 30 10:19:42 EDNOOREZK /usr/libexec/gdm-x-session[959]: Unable to run X server

@crramirez
Copy link

@noorez Debian 12 has an older version of Xwayland that doesn't work with this solution

@noorez
Copy link

noorez commented Oct 1, 2024

@noorez Debian 12 has an older version of Xwayland that doesn't work with this solution

switched over to use ubuntu24.04 on wsl. my main desktop looks just fine on my monitor resolution but the gdm login screen is unreadable (most of the fonts look blurry/smaller than they should be). I'm wondering if the scaling is wrong (or somehow the the monitors.xml file in /var/ib/gdm3/.config is not being used?..)

@tdcosta100
Copy link
Author

tdcosta100 commented Oct 1, 2024

@noorez, check if the user gdm can read the monitors.xml file doing the following commands:

sudo -u gdm -s
cat ~/.config/monitors.xml

If you cannot read the file, you need to fix its permissions.

If you can read it, check if it is correctly formed, or recreate it.

@noorez
Copy link

noorez commented Oct 2, 2024

@noorez, check if the user gdm can read the monitors.xml file doing the following commands:

sudo -u gdm -s
cat ~/.config/monitors.xml

If you cannot read the file, you need to fix its permissions.

If you can read it, check if it is correctly formed, or recreate it.

it turns out what I really needed was to tweak the gdm settings apart from monitors.xml .. I just used the gdm-settings tool to set the fonts and and such to what would be more appropriate (I suppose gdm wasn't getting initialized with more sane settings with this tutorial like I would have seen if I was running ubuntu natively and booting?... perhaps?)

another nice to have might be allowing the clipboard to work from windows to Xwayland. If I were just running dbus-launch gnome-terminal directly from a wsl terminal for example without launching the full desktop, I am able to do CTRL-SHIFT-V to paste into that gnome-terminal from something that I copied from windows.

but this is still pretty cool anyhow!

@tevaughan
Copy link

Since under the hood everything you see coming from WSLg is a RDP window

I followed your tutorial and got xfce4 working under ubuntu-24.04. This is neat!

However, your comment about RDP above makes me wonder whether it was worth all of the effort.
Might it just be better to run xrdp in ubuntu-24.04 and then launch Remote Desktop to connect to ubuntu-24.04's xrdp?

@tdcosta100
Copy link
Author

It's worth it for me hahaha. But it's case to case, if xrdp fits your needs, that's nice. But maybe it will interfere with the WSLg, so this tutorial allows you to use it as your rendering system.

@crramirez
Copy link

@tevaughan One advantage of this approach is the rendering speed, feels faster than the solution using xrdp.

@tevaughan
Copy link

tevaughan commented Oct 9, 2024

Thanks for the responses. I agree about rendering speed. It does feel faster. That makes me want to do it.

I have one problem remaining, though:
The Xwayland that gets launched in Ubuntu-24.04 is serving display :0.

This is a problem because I still have some shells in Windows Terminal, for different distributions under WSL. But each of them has DISPLAY set to :0, and so any client launched, regardless of distribution, appears in the Ubuntu-24.04-session.

I notice in the script that substitutes for Xorg, that displayNumber is being set to 1, but this seems to be overridden to :0 by whatever is calling Xorg. The ":0" is supplied as a positional parameter to Xorg, and that ":0" appears later on the command-line generated for Xwayland, but ":0" seems to take precedence over the ":1" specified earlier on Xwayland's command-line.

Is there any way for Xwayland launched in Ubuntu-24.04 to serve display :1 (rather than :0), or will that break other things?

@tevaughan
Copy link

tevaughan commented Oct 9, 2024

To make this approach perfect for folk like me, who want Ubuntu-24.04's X-session on one virtual desktop in MS Windows and want to use, on a different virtual desktop, a shell in Windows Terminal from a different linux-distribution:

  1. The Xwayland-instance would need to serve a display different from the one that is used by the MS Windows' native window-manager. So an X-window launched from a shell in Windows Terminal, regardless of distribution, would show up outside of the Xwayland in Ubuntu-24.04.

  2. The tutorial would explain how to wire up sound from inside the session in Ubuntu-24.04.

@tevaughan
Copy link

Is there any way for Xwayland launched in Ubuntu-24.04 to serve display :1 (rather than :0), or will that break other things?

What calls 'Xorg' and passes the extra parameters that end up on Xwayland's command-line? It would be neat to experiment with changing the commanded display-number, but simply ignoring the commanded display-number, which overrides displayNumber in the script, clearly does not work. (I tried it.)

@tevaughan
Copy link

tevaughan commented Oct 10, 2024

Is there any way for Xwayland launched in Ubuntu-24.04 to serve display :1 (rather than :0), or will that break other things?

I figured it out. Because I'm using lxdm (with xfce4 as the default session), I just had to edit /etc/lxdm/lxdm.conf. I was able to set the "arg" variable, which contains the invocation of /usr/bin/X with its arguments. (X is just a logical link to your Xorg script that launches Xwayland). By putting ":1" as an argument to /usr/bin/X in the "arg" variable, I got everything that I wanted.

Any X-application launched from a shell in Windows Terminal continues to be managed by the MS Windows (on :0), and I have my full-screen session with XFCE4 (on :1).

Almost perfect!

The last detail would be to get sound to work.

@loadlost
Copy link

loadlost commented Oct 12, 2024

hi. is it posible to make clipboard work? i try to change wslg.rdp but with no effect. same with multi monitors but its less troubling

@tdcosta100
Copy link
Author

The problem is not the WSLg, but the GNOME-Shell/XWayland. They are running nested, so they don't share the clipboard with the parent window (which is invisible to us). If I (or anyone else) discover how to make this happen, I will update the tutorial.

@tdcosta100
Copy link
Author

Is there any way for Xwayland launched in Ubuntu-24.04 to serve display :1 (rather than :0), or will that break other things?

I figured it out. Because I'm using lxdm (with xfce4 as the default session), I just had to edit /etc/lxdm/lxdm.conf. I was able to set the "arg" variable, which contains the invocation of /usr/bin/X with its arguments. (X is just a logical link to your Xorg script that launches Xwayland). By putting ":1" as an argument to /usr/bin/X in the "arg" variable, I got everything that I wanted.

Any X-application launched from a shell in Windows Terminal continues to be managed by the MS Windows (on :0), and I have my full-screen session with XFCE4 (on :1).

Almost perfect!

The last detail would be to get sound to work.

I don't know how it works under LXDM, but under GNOME you have to do some hacks. For example, in Ubuntu 22.04 you have to uninstall PulseAudio, so the WSLg PulseAudio takes the right place. In Ubuntu 24.04 it's a little bit different, I will dedicate some time to put my experiments into the tutorial.

@RobertBernstein
Copy link

RobertBernstein commented Nov 2, 2024

Thank you! This worked extremely well for me on Ubuntu 24.04.1 LTS. However, once I'm in the GNOME desktop, it thinks I'm offline and I don't appear to have a network connection. Some apps work just fine, e.g., Firefox and browsing the Internet. But the Software apps shows "No Connection" when I click on the Updates tab and the Settings app doesn't recognize that I'm connected to the Internet and reports "No Wi-Fi Adapter Found". Any idea how to fix this?

@tdcosta100
Copy link
Author

In previous WSL Ubuntu versions, I used to configure the network renderer in Netplan from systemd-networkd to NetworkManager, but in Ubuntu 24.04.1 "it just works". In a fresh-new install of Ubuntu 24.04.1 LTS it's like this:

image

Did you come from a previous version? If so, you should try to configure the Netplan files in /etc/netplan/ directory.

@RobertBernstein
Copy link

I did not come from a previous version. I installed Ubuntu 24.04.1 on WSL and then followed the instructions you shared. I'll take a look at the netplan. Thanks!

@tdcosta100
Copy link
Author

Nice! Please tell me if it works. My Netplan config file was something like this:

/etc/netplan/00-config.yaml

network:
  version: 2
  renderer: NetworkManager

@tdcosta100
Copy link
Author

hi. is it posible to make clipboard work? i try to change wslg.rdp but with no effect. same with multi monitors but its less troubling

Hy, @loadlost! Did you try the clipboard-sync? I tried here and it worked like a charm. Please tell me if it works for you. I'm considering putting it in the tutorial.

@w0ce83c4yvi7vcjf2qr7ia5wsp3qt9

Is there any way for Xwayland launched in Ubuntu-24.04 to serve display :1 (rather than :0), or will that break other things?

I figured it out. Because I'm using lxdm (with xfce4 as the default session), I just had to edit /etc/lxdm/lxdm.conf. I was able to set the "arg" variable, which contains the invocation of /usr/bin/X with its arguments. (X is just a logical link to your Xorg script that launches Xwayland). By putting ":1" as an argument to /usr/bin/X in the "arg" variable, I got everything that I wanted.
Any X-application launched from a shell in Windows Terminal continues to be managed by the MS Windows (on :0), and I have my full-screen session with XFCE4 (on :1).
Almost perfect!
The last detail would be to get sound to work.

I don't know how it works under LXDM, but under GNOME you have to do some hacks. For example, in Ubuntu 22.04 you have to uninstall PulseAudio, so the WSLg PulseAudio takes the right place. In Ubuntu 24.04 it's a little bit different, I will dedicate some time to put my experiments into the tutorial.

i'm using gnome on Ubuntu 24.04 as well, i'm kinda curious what trick i can do make audio work. actually, there's no a big reason for it, just wanna watch a yt video on firefox xD

btw, amazing tutorial ;)

@tdcosta100
Copy link
Author

tdcosta100 commented Nov 5, 2024

Thank you! Well, the problem is: in the $XDG_RUNTIME_DIR/pulse directory, there are two files, native and pid. These files are the same we encounter in /mnt/wslg/runtime-dir/pulse, but because of pulseaudio/pipewire, they are overwrited, so the audio link between the distro and the WSLg is broken. We have to prevent this to hear any audio.

You can try masking the pipewire-pulse service and socket:

systemctl --user mask pipewire-pulse.service
systemctl --user mask pipewire-pulse.socket

And before starting the graphical.target:

mkdir $XDG_RUNTIME_DIR/pulse
ln -s /mnt/wslg/runtime-dir/pulse/* $XDG_RUNTIME_DIR/pulse/

@kfoxirl
Copy link

kfoxirl commented Nov 8, 2024

Great tutorial, I have been able to get the DM to work but I cant seem to get gnome to successfully launch getting the "Oh no" error. Do you have any advice on how to troubleshoot?

EDIT: I got it working through SDDM but the multiple monitors isn't working. In xrandr inside the gnome shell this is what I have for displays.

XWAYLAND0
rdp-0,3,4 - showing disconnected

I've tried updating the weston.ini, the monitors.xml and setting it with xrandr at command line but I cant seem to get it to play nice. Any ideas?

@tdcosta100
Copy link
Author

For now, you have to remove the -fullscreen option in the /usr/bin/Xorg file. Then you can set a custom resolution, but it has some drawbacks as you will find out.

@kfoxirl
Copy link

kfoxirl commented Nov 9, 2024

For now, you have to remove the -fullscreen option in the /usr/bin/Xorg file. Then you can set a custom resolution, but it has some drawbacks as you will find out.

I think Im missing something key, how does removing fullscreen permit multiple monitors?

@tdcosta100
Copy link
Author

Because fullscreen forces XWayland to use only the first monitor. When you omit this parameter, then it renders as a normal window, with the resolution you choose. It's counterintuitive, but just try and check for yourself.

@kfoxirl
Copy link

kfoxirl commented Nov 9, 2024

Thanks brother, looks like there might be a way to do both as of 01/24, ill keep you posted!

@kfoxirl
Copy link

kfoxirl commented Nov 9, 2024

-output \fIname\fP
Specifies on which output Xwayland fullscreen rootful should be placed.
The name must match the name of an existing Wayland output (output names can
be found using wayland-info). If no matching output can be found, this is

What would that syntax look like, im not finding it in man? Just --output then --output?

@tdcosta100
Copy link
Author

I really don't know, because I don't know how these details of how Weston works under WSL. Maybe you should look at the system distro, who generates the root Wayland window, with wsl --system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment