|
|
<!doctype html>
|
|
|
<html>
|
|
|
<head>
|
|
|
<meta charset=utf-8>
|
|
|
<meta name=generator content="Pelican 4.9.1">
|
|
|
<meta name=author content="LEdoian">
|
|
|
<meta name=description content="My personal webpage">
|
|
|
<meta name=referrer content=no-referrer>
|
|
|
|
|
|
|
|
|
<link rel=stylesheet href="../theme/css/theme.css">
|
|
|
|
|
|
<title>UCW keyboard layout on XWayland – LEdoian's Blog</title>
|
|
|
</head>
|
|
|
<body>
|
|
|
|
|
|
<header>
|
|
|
<h1>LEdoian's Blog</h1>
|
|
|
</header>
|
|
|
|
|
|
<div id=main>
|
|
|
<nav>
|
|
|
<div>
|
|
|
<!-- Main navigation -->
|
|
|
<!-- TODO! -->
|
|
|
</div>
|
|
|
<div>
|
|
|
<h2>Categories</h2>
|
|
|
<ul>
|
|
|
<li><a href="../category/networking.html">networking</a></li>
|
|
|
<li><a href="../category/talks.html">talks</a></li>
|
|
|
<li><a href="../category/technology.html">technology</a></li>
|
|
|
</ul>
|
|
|
|
|
|
<h2>Tags</h2>
|
|
|
<ul>
|
|
|
<li><a href="../tag/ipv6-only.html">ipv6-only</a></li>
|
|
|
<li><a href="../tag/dns.html">dns</a></li>
|
|
|
<li><a href="../tag/meta.html">meta</a></li>
|
|
|
<li><a href="../tag/infrastructure.html">infrastructure</a></li>
|
|
|
<li><a href="../tag/smrst.html">smršť</a></li>
|
|
|
<li><a href="../tag/trains.html">trains</a></li>
|
|
|
<li><a href="../tag/software-engineering.html">software-engineering</a></li>
|
|
|
</ul>
|
|
|
</div>
|
|
|
<div>
|
|
|
<h2>Stalk me also at</h2>
|
|
|
TODO!
|
|
|
|
|
|
<h2>I stalk</h2>
|
|
|
TODO!
|
|
|
</nav>
|
|
|
|
|
|
<main>
|
|
|
<div>
|
|
|
<h1>UCW keyboard layout on XWayland</h1>
|
|
|
<p>This is a story/writeup of how I debugged UCW layout on XWayland. You may learn
|
|
|
here how keyboard layouts work on Linux.</p>
|
|
|
<div class="section" id="background-the-ucw-layout">
|
|
|
<h2>Background: The UCW layout</h2>
|
|
|
<p>The UCW keyboard layout is one of the interesting methods of typing Czech
|
|
|
letters on a rather American keyboard. The main idea is having a classic US
|
|
|
(QWERTY) layout, but without the CapsLock, which serves as a key to add
|
|
|
diacritics, so that e.g. Caps+s creates "š". It is naturally possible to
|
|
|
combine Caps with Shift to create uppercase letters, and because not all
|
|
|
letters can have diacritics in Czech (e.g. there is no "ǩ"), it also manages to
|
|
|
cover all the German and Slovak letters. (Sometimes, there are multiple
|
|
|
diacritics for a single letter, then the additional diacritics are nearby:
|
|
|
Caps+e is "é", Caps+w is "ě".) The CapsLock can still be pressed by using
|
|
|
Alt+Caps.</p>
|
|
|
<p>The layout has some nice features like avoiding deficiencies with the Czech
|
|
|
layout (diacritics on number row are too far, both round parentheses are on the
|
|
|
same key, other parentheses only with AltGr at random places, no asterisk, for
|
|
|
some reason we have "§" though, …). Another nice feature is that it is rather
|
|
|
interoperable: I am able to type on any computer with the "most standard"
|
|
|
layout and when writing in Czech I can just not press the CapsLock key and only
|
|
|
lose my diacritics, computers can have this layout system-wide even when
|
|
|
foreign people use it,…</p>
|
|
|
<p>I would not say many people use the layout but at least several my friends do
|
|
|
and I have come across several random people on the Internet who do also. More
|
|
|
on this below :-)</p>
|
|
|
<p>The important part is how the layout is set up. Fortunately, it is contained in
|
|
|
the xkeyboard-config database, so the following command just enables it in Xorg:</p>
|
|
|
<pre class="literal-block">
|
|
|
setxkbmap us,cz -variant ,ucw -option grp:caps_switch
|
|
|
</pre>
|
|
|
<p>Technically, this sets <em>two</em> layouts (or <em>groups</em>), which are switched by
|
|
|
pressing the CapsLock key. This has some disadvantages (I have managed a few
|
|
|
times to have the order accidentally swapped and layout switchers (or their
|
|
|
users) are sometimes confused), but actual issues are rare. Under X11, that is…</p>
|
|
|
<p>Corollary 1: I want UCW to work differently.</p>
|
|
|
<div class="section" id="my-custom-keyboard-layout">
|
|
|
<h3>My custom keyboard layout?</h3>
|
|
|
<p>I didn't like fact that UCW layout is in fact just an overlay and not a
|
|
|
"proper" level 3, so I started studying how to create a custom keyboard layout.
|
|
|
Few notable resources: <a class="reference external" href="TODO">XKB page on ArchWiki</a>, manpages for
|
|
|
<a class="reference external" href="TODO">xkeyboard-config(7)</a>, <a class="reference external" href="TODO">setxkbmap(1)</a> and <a class="reference external" href="TODO">xkbcomp(1)</a> and looking into
|
|
|
<tt class="docutils literal">/usr/share/X11/xkb/symbols/cz</tt> (found by grepping <tt class="docutils literal">/usr/share/X11</tt> for
|
|
|
"ucw").</p>
|
|
|
<p>Another reason for creating my own layouts is various tweaks esp. on laptop
|
|
|
keyboards. For example, the laptop I am typing this sentence on has broken the
|
|
|
up arrow key, so I would like to map it somewhere. I use <tt class="docutils literal">xmodmap</tt> for that,
|
|
|
but if this could be contained in a single layout, it would make stuff simpler
|
|
|
for me. (And as I will later learn, <tt class="docutils literal">xmodmap</tt> <a class="reference external" href="TODO">does not work well</a> with xkb
|
|
|
layouts…)</p>
|
|
|
<p>Also, I have another tweak on my keyboards: Compose key. This really calls for
|
|
|
the custom layout! And when at it, I should create one for the ttys as well…</p>
|
|
|
<p>But this had quite a low priority (the <tt class="docutils literal">kbd.sh</tt> script in <em>all</em> my homes does
|
|
|
the job well enough), so I didn't get to it in time. Luckily, maybe – if I were
|
|
|
quicker I would not end up in this rabbit hole. At this point, I knew the basic
|
|
|
stuff and was reasonably sure that I could hack it together, at least somehow;
|
|
|
what was stopping me was lack of time and not being sure how I want to manage
|
|
|
machine-specific tweaks in two different layout syntaxes (xkb for X11 and kbd
|
|
|
for ttys).</p>
|
|
|
</div>
|
|
|
<div class="section" id="aside-a-few-notes-about-xkb-layouts-for-completeness">
|
|
|
<h3>Aside: A few notes about xkb layouts for completeness</h3>
|
|
|
<p>This all has been described elsewhere in more detail, but it is useful to
|
|
|
know when debugging layouts, so I will mention it here again.</p>
|
|
|
<p>There are two forms xkb layouts may be specified. The low-level one is called
|
|
|
KcCGST (keycodes, compat, geometry, symbols, types) and describes very much
|
|
|
everything that should happen on any keypress. These actions are described in
|
|
|
subdirectories of <tt class="docutils literal">/usr/share/X11/xkb/</tt> of the same name.</p>
|
|
|
<p>The high-level descriptions are called RMLVO (rules, model, layout, variant,
|
|
|
option) and are what you usually configure, either with <tt class="docutils literal">setxkbmap</tt> or using
|
|
|
GUI tools. Files in <tt class="docutils literal">/usr/share/X11/xkb/rules/</tt> describe the translation of
|
|
|
RMLVO to KcCGST (the XML files add human-readable names for the GUIs and the
|
|
|
like). Maybe confusingly, the RMLVO names of options and layouts are very
|
|
|
similar to the names of KcCGST compat and symbols, but are generally a
|
|
|
different thing AFAIK.</p>
|
|
|
<p>KcCGST also come in two forms: the readable one and the complete one. The
|
|
|
readable one does not determine everything in one file, instead including
|
|
|
others. The complete description is, well, complete. It is kind of similar to
|
|
|
the C preprocessing.</p>
|
|
|
<p>The readable KcCGST are what is stored in the filesystem as well as what you
|
|
|
get from <tt class="docutils literal">setxkbmap <span class="pre">-print</span></tt> and may serve as a good starting point for
|
|
|
tweaks. To get the complete ones one can use <tt class="docutils literal">xkbcomp $DISPLAY -</tt>.</p>
|
|
|
<p>The processing of these description is <a class="reference external" href="TODO">different</a> in Xorg and in Wayland. If
|
|
|
I were to bet where the bug is before digging into it, this sounds like a very
|
|
|
likely culprit.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="section" id="a-wild-friend-has-appeared">
|
|
|
<h2>A wild friend has appeared</h2>
|
|
|
<p>… and he had a problem and asked me if I would have a look into it. Apparently,
|
|
|
<a class="reference external" href="TODO">group switching didn't work in XWayland</a>. At first, I wanted to work it around
|
|
|
by finally creating the Unified UCW keymap™, but I wanted to learn more about
|
|
|
XKB (from TODO GUIDES), which took me quite long, again. (Studying, working,
|
|
|
helping with camps <em>and</em> fixing layouts takes some time…)</p>
|
|
|
<p>Also, since the issue is apparently bigger, solving all group switches would be
|
|
|
a better and more useful solution than just hacking up the Unified UCW keymap
|
|
|
(even though I want my tweaks to eventually be xkb-based anyway).</p>
|
|
|
<p>I had very little experience with Wayland until then, mostly because X11 worked
|
|
|
for me rather well. I tried running Sway few times before, but usually quickly
|
|
|
reverted to using Xorg for various reasons (Nvidia GPU in laptop, very laggy
|
|
|
mouse, maybe <em>this exact</em> issue with UCW layout) which I didn't feel like
|
|
|
solving at that moment.</p>
|
|
|
<p>I wanted to help my friend, though, so I started looking more into using Sway
|
|
|
on another laptop and reading about internals of input system on <a class="reference external" href="TODO">Peter
|
|
|
Hutterer's blog</a> TODO NAME SPELLING? Occasionally I would randomly google
|
|
|
(<a class="reference external" href="TODO">with DuckDuckGo</a> :-D) for the issue with group switching, just in case…</p>
|
|
|
</div>
|
|
|
<div class="section" id="the-nerd-snipe-issue">
|
|
|
<h2>The nerd snipe issue</h2>
|
|
|
<p><a class="reference external" href="TODO">TODO SOMEONE</a> on GitHub found out an interesting workaround: when they
|
|
|
<em>disabled</em> the group switch, the UCW layout <em>started working</em>. Complete "huh?"
|
|
|
moment, I knew I wanted to know more about why that worked. The
|
|
|
<a class="reference external" href="TODO">xkeyboard-common(7) manpage</a> says about more group switching options, so I
|
|
|
randomly tried switching by Menu key in XWayland (using <tt class="docutils literal">setxkbmap</tt> even
|
|
|
though it complained and was supposed to do nothing), and ended up with <em>both</em>
|
|
|
CapsLock and Menu adding diacritics.</p>
|
|
|
<p>After a bit of mathematic thinking (more in my <a class="reference external" href="TODO">comment of the main issue</a>) I
|
|
|
concluded that it was actually working fine, just that the <tt class="docutils literal">SetGroup</tt> action
|
|
|
was evaluated <em>twice</em>, which would overflow back to the first group when two
|
|
|
layouts are set (probably the most common case). Mathematic term for this issue
|
|
|
is "arithmetic in the Z_2 group" :-)</p>
|
|
|
<p>Corollary 2: A simple workaround is adding the UCW overlay twice, e.g.
|
|
|
<tt class="docutils literal">setxkbmap us,cz,cz <span class="pre">-variant</span> ,ucw,ucw</tt> (and thus changing the algebraic group
|
|
|
to be Z_3).</p>
|
|
|
<p>I think that another workaround would be to change the <tt class="docutils literal">compat</tt> rules for
|
|
|
XWayland, but it feels nasty to have such a quirk in xkeyboard-config database.
|
|
|
Changing them for everyone (in <tt class="docutils literal">compat/evdev</tt> directly) might break other
|
|
|
systems, so that also does not seem to be a good way.</p>
|
|
|
<p>Corollary 3: We are fixing XWayland (or the way it processes events from Wayland).</p>
|
|
|
</div>
|
|
|
<div class="section" id="learning-what-happens">
|
|
|
<h2>Learning what happens</h2>
|
|
|
<p>I continued reading, this time mostly <a class="reference external" href="TODO">who-t's post series about custom
|
|
|
layouts</a>, <a class="reference external" href="TODO">core Wayland protocol</a> as well as the source code of various
|
|
|
tools (<tt class="docutils literal">xev</tt>, <tt class="docutils literal">wev</tt>, <tt class="docutils literal">xkbcli <span class="pre">interactive-wayland</span></tt> &c.) Given that I knew
|
|
|
very little about the inner workings of the stack, I wanted to find some code
|
|
|
that would be run and "enhance" it with so many debug prints that I would
|
|
|
understand what was the state of various parts of the Xwayland's "stacked xkb".
|
|
|
I kind of knew that one part of this is <em>somewhere</em> in the XWayland server,
|
|
|
whose code felt intimidating, so I wanted to determine where to start nudging
|
|
|
it from what APIs the clients use.</p>
|
|
|
<div class="admonition tip">
|
|
|
<p class="first admonition-title">Tip</p>
|
|
|
<p>Downloading various packages in Linux is rather simple, as well as their
|
|
|
rebuilding. In Arch, I can get the package's PKGBUILD just with <tt class="docutils literal">yay <span class="pre">-G</span>
|
|
|
package</tt>, build it with <tt class="docutils literal">makepkg</tt> and install it using <tt class="docutils literal">yay <span class="pre">-U</span>
|
|
|
<span class="pre">package-….pkg.tar</span></tt>. Makepkg also has some options which allow me to tweak
|
|
|
the source code after downloading it and before building it.</p>
|
|
|
<p class="last">Other distros are probably similar, e.g. for Debian-based distros one can
|
|
|
use <tt class="docutils literal">apt source</tt>, <tt class="docutils literal">debuild</tt> and <tt class="docutils literal">apt install</tt> to do the same.</p>
|
|
|
</div>
|
|
|
<p>One interesting observation is that contrary to my expectation, XWayland does
|
|
|
not seem to use libxkbcommon (according to the <tt class="docutils literal">/proc/PID/maps</tt> file). This
|
|
|
can have several reasons, but its source code also contains a slightly tweaked
|
|
|
version of (Xorg-style) xkb, which might mean I will be dealing with <a class="reference external" href="TODO">the ugly
|
|
|
code</a> :-/ (Actually, XWayland might not process key events itself, instead
|
|
|
just passing them to clients, but this seems inconsistent with the issue – what
|
|
|
else would be introducing the second group switch?)</p>
|
|
|
<p>So now I need to understand a (hopefully small) parts of two protocols: X11 to
|
|
|
understand what the X11 clients receive from XWayland, and Wayland to
|
|
|
understand what XWayland gets from my compositor.</p>
|
|
|
<div class="section" id="understanding-x11">
|
|
|
<h3>Understanding X11</h3>
|
|
|
<p>This part is maybe the easier one, because <tt class="docutils literal">xev</tt> pretty much dumps the data.
|
|
|
I should check in the server code as well, but for the Czech chords <tt class="docutils literal">xev</tt>
|
|
|
seems to receive <tt class="docutils literal">KeyEvents</tt> with state <tt class="docutils literal">0x2000</tt> under Xorg (i3wm) and with
|
|
|
<tt class="docutils literal">0x4000</tt> under XWayland when three groups are set up (for two groups the
|
|
|
state is <tt class="docutils literal">0x0</tt>, i.e. the same as for English keypresses). State bits this
|
|
|
high encode the active group and are described in <a class="reference external" href="https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Computing_A_State_Field_from_an_XKB_State">the relevant part</a>
|
|
|
of <a class="reference external" href="https://www.x.org/releases/current/doc/kbproto/xkbproto.html">the XKB extension documentation</a>.</p>
|
|
|
<p>We can see that if we set the <tt class="docutils literal">GroupsWrap</tt> control of XKB (I don't know
|
|
|
where/how yet) to <tt class="docutils literal">ClampIntoRange</tt> it should also help work around the
|
|
|
problem. But our goal is to align behaviour of XWayland and JustWayland, i.e.
|
|
|
prevent XWayland seeing two group shifts, not to hack our way in either
|
|
|
protocol, so we do not stop here.</p>
|
|
|
<!-- Read also xkbproto: Server Internal Modifiers and Ignore Locks Behavior (might explain sth?) -->
|
|
|
<p>At this point, I had an approximate idea of how XKB is supposed to do,
|
|
|
hopefully. I have not yet read the implementation in XWayland though…</p>
|
|
|
</div>
|
|
|
<div class="section" id="understanding-wayland">
|
|
|
<h3>Understanding Wayland</h3>
|
|
|
<p>This part is supposed to also be simple: the core Wayland protocol will send us
|
|
|
<a class="reference external" href="TODO">wl_keyboard::keymap</a>, <a class="reference external" href="TODO">wl_keyboard::key</a> and
|
|
|
<a class="reference external" href="TODO">wl_keyboard::modifiers</a> events containing the required data. To prove
|
|
|
our hypotheses we can use <tt class="docutils literal">wev</tt> which does very little post-processing as
|
|
|
with <tt class="docutils literal">xev</tt>.</p>
|
|
|
<p>The client does not seem to have a say in what kind of keymap it will get, it
|
|
|
is up to the compositor. This means that even XWayland cannot say it wants raw
|
|
|
data, but <tt class="docutils literal">xkb_v1</tt>-style keycodes are probably close (they are off by 8,
|
|
|
which is kind of expected).</p>
|
|
|
<p>While exploring what happens I found out there is a bug in the stable version
|
|
|
1.0.0 of <tt class="docutils literal">wev</tt>, where it forgets to include the serial number for
|
|
|
wl_keyboard::modifiers. It has already <a class="reference external" href="https://git.sr.ht/~sircmpwn/wev/commit/83de8e931ab04ce3322a58b359d8effa7901b21c">been patched</a>
|
|
|
15 months ago, but the patch is not included in a release yet.</p>
|
|
|
<p>But I am also interested in what is exchanged between the compositor and
|
|
|
XWayland server. And there does not seem to be any kind of sniffer yet, so <a class="reference external" href="https://gitea.ledoian.cz/LEdoian/sopass/">I
|
|
|
started writing one</a>
|
|
|
<a class="footnote-reference" href="#wiresharkify" id="footnote-reference-1">[1]</a>. Only then I learned that I can set the environment variable
|
|
|
<tt class="docutils literal">WAYLAND_DEBUG=1</tt> to get dumps of all the calls that are happening. (To my
|
|
|
defense, this does not seem to be very documented. I only found a small note in
|
|
|
the <a class="reference external" href="TODO">building guide</a>. Even the <a class="reference external" href="TODO">debugging extras page</a> does
|
|
|
not mention this.)</p>
|
|
|
<!-- should fix the wl docs instead of ranting, though… -->
|
|
|
<p>By running <tt class="docutils literal">WAYLAND_DEBUG=1 Xwayland :15</tt> and <tt class="docutils literal"><span class="pre">DISPLAY=:15</span> xev</tt>, we do
|
|
|
learn what we thought was happening:</p>
|
|
|
<ul class="simple">
|
|
|
<li>XWayland gets XKB v1 keymap (I trust sway to supply the same map as to
|
|
|
<tt class="docutils literal">wev</tt> earlier.)</li>
|
|
|
<li>XWayland gets the correct (Wayland core) events from the compositor</li>
|
|
|
<li>XWayland sends a wrong (X11 with XKB) events to <tt class="docutils literal">xev</tt>.</li>
|
|
|
</ul>
|
|
|
<p>This confirms that XWayland is really the culprit here.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="section" id="digging-into-xwayland">
|
|
|
<h2>Digging into XWayland</h2>
|
|
|
<p>At this point, we have all the tools, references to documentation and knowledge
|
|
|
we could possibly have, so now we get our hands dirty. A simple <tt class="docutils literal">grep <span class="pre">-r</span>
|
|
|
wl_keyboard src/</tt> tells us that the keyboard handling occurs in the file
|
|
|
<tt class="docutils literal"><span class="pre">hw/xwayland/xwayland-input.c</span></tt> in functions <tt class="docutils literal">keyboard_handle_*</tt>, which look
|
|
|
like the libwayland-client handlers we have seen in <tt class="docutils literal">wev</tt>.</p>
|
|
|
<!-- TO-MENTION:
|
|
|
- nested compositor issues
|
|
|
- the IM resolves compose? (I could bisect it, but too lazy)
|
|
|
- copy my issue comment in case link rots.
|
|
|
- list of all the packages I had downloaded and compiled -->
|
|
|
<!-- TODO: rename XWayland to Xwayland… -->
|
|
|
<hr class="docutils" />
|
|
|
<table class="docutils footnote" frame="void" id="wiresharkify" rules="none">
|
|
|
<colgroup><col class="label" /><col /></colgroup>
|
|
|
<tbody valign="top">
|
|
|
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>It would be nice if we could analyse the traffic in a
|
|
|
general packet analysis program like Wireshark, though, so I might return to
|
|
|
sopass and write the dissectors and dumping from sopass to a pcap file in a
|
|
|
future. However, this gets put on hold now.</td></tr>
|
|
|
</tbody>
|
|
|
</table>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
</main>
|
|
|
</div> <!-- #main -->
|
|
|
|
|
|
<footer>
|
|
|
<hr>
|
|
|
Written using Pelican 4.9.1 by LEdoian.
|
|
|
</footer>
|
|
|
|
|
|
</body>
|
|
|
</html>
|