mmh0000/easystroke

Easystroke - slightly modified to build on modern Linux

1

stars

991

commits

C++

primary language

Sep 4, 2026

updated

README

easystroke (maintenance fork)

Mouse-gesture recognition for X11. Hold a mouse button (or pen/finger), draw a stroke, and easystroke fires an action — key presses, shell commands, held modifiers, emulated scroll. Configured from a GTK3 tray application.

Upstream (thjaeger/easystroke) stopped in 2013. This fork keeps it building and running on current Linux. The code fixes are distro-agnostic; the packaging happens to be RPM because Fedora is what I run. Patches for other distros are welcome.

Changes in this fork

Fixes

  • Startup deadlock against glycin. signal(SIGCHLD, SIG_IGN) — harmless since 2009 — makes waitpid() return ECHILD. glycin, the sandboxed gdk-pixbuf image loader, waits on a bwrap sandbox probe that consequently never reaps, parking the main thread inside Gtk::Builder construction. The GLib main loop never ran, so no gesture was ever seen. Removed; zombies are avoided by double-fork instead. Hits any distro shipping glycin (I found it on Fedora 43), and only under GTK themes whose CSS references url() images — which is why stock Adwaita hid it.
  • Modern toolchain (GCC 15). sigc::group → lambda; dropped a custom abs() that now collides with std::abs; const GdkRectangle * to match the current GTK3 start_editing signature; explicit Boost.Serialization template instantiations.
  • Multi-monitor. Gesture trails were invisible on secondary monitors. The GdkMonitor API replaces deprecated gdk_screen_width/height; trace windows now span the full desktop, including negative coordinates and non-adjacent layouts. Absolute (tablet) devices scale to the whole desktop.
  • Crash guards. NULL GdkMonitor during monitor hotplug, zero-sized trace window geometry, and a current_dev NULL deref on XI_RawMotion after device removal.

Housekeeping

  • Fedora's long-carried downstream patch stack (Patch0–Patch16) is integrated into the source tree as individual commits, so it now benefits every distro instead of one. Two patches were dropped — one conflicted with the multi-monitor fix, one was unfinished upstream work.
  • easystroke.spec builds 0.6.0-45.fc43. It's the only packaging in the tree; contributions for other formats welcome.
  • Containerfile + build-scripts/ give reproducible containerized builds, so the host needs no build dependencies at all.
  • xi2-grab-test.c — standalone XI2 probe replicating easystroke's exact grab sequence, to separate "the X server is broken" from "easystroke is broken".

Build

Build in a container: podman or docker (needs support added in the build script), whichever you have. Please don't build natively: the Containerfile is the one place dependencies are declared, which is what keeps builds identical across machines and distros. Adding a dependency means adding it there, in the same commit.

For a full binary + RPM build:

build-scripts/podman-build-all.sh

The tree carries no git tags, so git describe comes up empty and the build bakes in a blank version. Harmless — it only shows in the About dialog — but echo 0.6.0 > version sets one.

Notes

X11 only. XInput2 passive grabs are load-bearing, so Wayland is out of scope.

License: ISC, unchanged from upstream. See LICENSE.

Contributors

thjaeger

946 commits

jwakely

10 commits

spotrh

9 commits

ausil

8 commits

mmh0000/easystroke

Easystroke - slightly modified to build on modern Linux

1

stars

991

commits

C++

primary language

Sep 4, 2026

updated

README

easystroke (maintenance fork)

Mouse-gesture recognition for X11. Hold a mouse button (or pen/finger), draw a stroke, and easystroke fires an action — key presses, shell commands, held modifiers, emulated scroll. Configured from a GTK3 tray application.

Upstream (thjaeger/easystroke) stopped in 2013. This fork keeps it building and running on current Linux. The code fixes are distro-agnostic; the packaging happens to be RPM because Fedora is what I run. Patches for other distros are welcome.

Changes in this fork

Fixes

  • Startup deadlock against glycin. signal(SIGCHLD, SIG_IGN) — harmless since 2009 — makes waitpid() return ECHILD. glycin, the sandboxed gdk-pixbuf image loader, waits on a bwrap sandbox probe that consequently never reaps, parking the main thread inside Gtk::Builder construction. The GLib main loop never ran, so no gesture was ever seen. Removed; zombies are avoided by double-fork instead. Hits any distro shipping glycin (I found it on Fedora 43), and only under GTK themes whose CSS references url() images — which is why stock Adwaita hid it.
  • Modern toolchain (GCC 15). sigc::group → lambda; dropped a custom abs() that now collides with std::abs; const GdkRectangle * to match the current GTK3 start_editing signature; explicit Boost.Serialization template instantiations.
  • Multi-monitor. Gesture trails were invisible on secondary monitors. The GdkMonitor API replaces deprecated gdk_screen_width/height; trace windows now span the full desktop, including negative coordinates and non-adjacent layouts. Absolute (tablet) devices scale to the whole desktop.
  • Crash guards. NULL GdkMonitor during monitor hotplug, zero-sized trace window geometry, and a current_dev NULL deref on XI_RawMotion after device removal.

Housekeeping

  • Fedora's long-carried downstream patch stack (Patch0–Patch16) is integrated into the source tree as individual commits, so it now benefits every distro instead of one. Two patches were dropped — one conflicted with the multi-monitor fix, one was unfinished upstream work.
  • easystroke.spec builds 0.6.0-45.fc43. It's the only packaging in the tree; contributions for other formats welcome.
  • Containerfile + build-scripts/ give reproducible containerized builds, so the host needs no build dependencies at all.
  • xi2-grab-test.c — standalone XI2 probe replicating easystroke's exact grab sequence, to separate "the X server is broken" from "easystroke is broken".

Build

Build in a container: podman or docker (needs support added in the build script), whichever you have. Please don't build natively: the Containerfile is the one place dependencies are declared, which is what keeps builds identical across machines and distros. Adding a dependency means adding it there, in the same commit.

For a full binary + RPM build:

build-scripts/podman-build-all.sh

The tree carries no git tags, so git describe comes up empty and the build bakes in a blank version. Harmless — it only shows in the About dialog — but echo 0.6.0 > version sets one.

Notes

X11 only. XInput2 passive grabs are load-bearing, so Wayland is out of scope.

License: ISC, unchanged from upstream. See LICENSE.

See what people are saying

Contributors

thjaeger

946 commits

jwakely

10 commits

spotrh

9 commits

ausil

8 commits

Languages

C++

76.9%

C

18.9%

Makefile

1.6%

Shell

1.3%

Vala

1.2%