Search This Blog

Tuesday, December 28, 2021

Custom keyboard layout in Wayland

Unfortunately, the configuration at the and of this post does not work for Wayland Qt applications, like konsole, kate. A colleage from KDE Brazil telegram channel pointed me to a working solution.

Update 28/12/2021: the configuration below works for X11/XWayland applications only.

Going forward with migrating to Wayland. There are several smalls things to fix in my setup, one of them is adding a custom layout to workaround the fact that my child broken the Up key of my laptop's keyboard. I had mapped F9 to Up using $HOME/.Xmodmap, which does not work in Wayland. I have figure out how to that in Wayland [1] [2] and maybe this can help other people.

Create this file to configure XDG_CONFIG_HOME variable:

# /etc/profile.d/xdg.sh
export XDG_CONFIG_HOME=$HOME/.config

Create the $HOME/.config/xkb/rules/evdev.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE xkbConfigRegistry SYSTEM "xkb.dtd">

<xkbConfigRegistry version="1.1">

  <layoutList>

    <layout>

      <configItem>

        <name>lvs</name> <!-- Change to any name you want -->

        <shortDescription>Layout LVS</shortDescription> <!-- Same here -->

        <description>Layout com F8, F9 e F10 remapeadas</description> <!-- Any description you want -->

        <countryList>

          <iso3166Id>US</iso3166Id> <!-- Add your country to this list -->

          <iso3166Id>BR</iso3166Id> <!-- My country: Brazil -->

        </countryList>

        <languageList>

          <iso639Id>eng</iso639Id> <!-- Layout language -->

          <iso639Id>por</iso639Id> <!-- Brazilian Portuguese -->

        </languageList>

      </configItem>

    </layout>

  </layoutList>

</xkbConfigRegistry>


Create a file $HOME/.config/xkb/symbols/lvs (the file name have to match the layout name in evdev.xml) with the actual changes you need. I just copied the file with the symbols I wanted to change to save time:

cp /usr/share/X11/xkb/symbols/srvr_ctrl $HOME/.config/xkb/symbols/lvs

Then I removed all lines that should not be changed. The final file is the following (the actual changes are in bold):

partial function_keys

xkb_symbols "fkey2vt" {

    key <FK08> {

        type="CTRL+ALT",

        symbols[Group1]= [ Prior, F8, F8, F8, XF86_Switch_VT_8 ]

    };

    key <FK09> {

        type="CTRL+ALT",

        symbols[Group1]= [ Up, Prior, F9, F9, XF86_Switch_VT_9 ]

    };

};

Comparing all this to the .Xmodmap it seems way more complicated :-( This is my .Xmodmap:

! 74 = F8 

keycode 74 = Prior                                            

! 75 = F9                                  
keycode 75 = Up Prior

You need to restart startplasma-wayland so the changes take affect. The best part is that it also works with X11, so I removed my .Xmodmap.

PS: the Up key does not work in konsole to show the previous command when running in wayland, even with an external keyboard with a physical Up key. That works in X11.

Saturday, December 25, 2021

Nvidia optimus with wayland. Help needed.

I have given a try on wayland and it works in my notebook (Gigabyte p34v5) when using only the Intel gpu (/dev/dri/card0) and mesa. Now I have been trying to make it work with the Nvidia gpu (GeForce GTX 970M, /dev/dri/card1) using proprietary driver. The thing about that gpu is that is uses optimus and thus need the following command to work with X11:

# /usr/share/sddm/scripts/Xsetup file
xrandr --setprovideroutputsource modesetting NVIDIA-0

There is just a blank screen on sddm whithout that command (the Nvidia gpu is not physically connected to the display, it needs the Intel gpu to send image to any display, the command above connects the Nvidia gpu to the Intel one). Since xrandr does not work with wayland I am kind of stuck trying figure out the equivalent of that command for wayland. I have tried the following environment variable to no avail:

WLR_DRM_DEVICES=card1:card0

My current startwayland.sh script is:

# card0: intel
# card1: nvidia
export WLR_DRM_DEVICES=card1:card0
export KWIN_DRM_DEVICES=/dev/dri/card1:/dev/dri/card0
export XDG_RUNTIME_DIR=/tmp/1001
export XDG_SESSION_TYPE=wayland
export QT_QPA_PLATFORM=wayland
export GBM_BACKEND=nvidia-drm
export __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/10_nvidia.json:/usr/share/glvnd/egl_vendor.d/50_mesa.json
export EGL_PLATFORM=wayland
export EGL_LOG_LEVEL=debug
export QT_LOGGING_RULES="kwin*=true"
export KWIN_GL_DEBUG=1
export WAYLAND_DEBUG=1
unset DISPLAY
mkdir -m 0700 -p $XDG_RUNTIME_DIR

if [ -n "$DBUS_SESSION_BUS_ADDRESS" ]; then
    export $(dbus-launch)
    sleep 1
fi


kwin_wayland --xwayland --exit-with-session=konsole 2>&1 | tee -a kwin_wayland_log.txt

I am using kwin_wayland instead of plasma-wayland so less programs are started during my tests.

EGL is correctly initialized on both gpu by what can be seen on kwin_wayland_log.txt, though nvidia-drivers uses version 1.5 and mesa uses version 1.4.

The first relevant error is "kwin_wayland_drm: swapping buffers failed on output KWin::DrmOutput(0x559b35fd8d30, name="eDP-1", geometry=QRect(0,0 1920x1080), scale=1)". eDP-1 is my laptop's LCD and W2486 is an external monitor.

There is no screen update after I launch kwin_wayland similar to what happens with X11 without the xrandr command. I need to log through ssh to 'chvt' to a different virtual terminal or kill kwin_wayland to use laptop again. I guess I just need to instruct kwin_wayland to connect the output of nvidia gpu to intel's one to make everything work. I just do not know how to do that.

My environment:

x11-drivers/nvidia-drivers-495.46-r10:0/495 to use Nvidia's new GBM support instead of EGLStream
gui-libs/egl-wayland-1.1.9:0
gui-libs/eglexternalplatform-1.1:0
media-libs/mesa-21.3.2:0
dev-qt/qtwayland-5.15.2-r16:5/5.15.2 with patch Don't block in QWaylandDisplay::flushRequests
kde-plasma/kwin-9999:5 this is a git build of commit 445946382379b65701259bc1f75c92227348db31 from Dec 15 2021 so I can use platforms/drm: use gbm with NVidia driver 495+.

Have someone successfully run plasma-wayland with nvidia's optimus and gbm instead of EGLStream?