Inspect X Input and Window Events Safely with xev

xev opens a small window, watches it, and prints exactly what the X server sends when you move, click or type near it. It is the fastest way to answer "is this key or click even reaching X" without guessing.

Allow about ten minutes for a first check. You need an X11 display the current user can access and the x11-utils package. This guide describes the installed xev 1.2.5, from x11-utils 7.7+6build2 on this machine. It is an event debugging tool, not something you would run day to day.

1. Check the display and version

Run the version check as your ordinary user; it does not touch the X server:

$ command -v xev
/usr/bin/xev
$ xev -version
xev 1.2.5

Before opening the event window, confirm the shell actually has a display name:

$ printf 'DISPLAY=%s\n' "${DISPLAY-}"
DISPLAY=:0

Your value may differ. An empty result usually means this shell is not inside an X11 session at all.

Warning: do not add sudo to compensate. Elevated privileges do not grant access to another user's display, and can make authentication harder, not easier.

Checkpoint: you have a working xev binary and a non-empty display value. If xev -version works but the display is empty, move to a terminal launched from the graphical session, or set up the correct X11 environment through your normal remote-desktop route.

2. Watch events from a new window

Start xev with no options:

$ xev

It creates a window and starts printing event records to the terminal. Move it, resize it, click inside it and type a few keys. Expect records such as Expose, ConfigureNotify, MotionNotify, ButtonPress and KeyPress; the exact fields, coordinates and key details depend on your window manager, keyboard layout and whatever you actually did.

Keep the terminal visible while testing if you can, the output gets noisy fast once the pointer starts moving. Stop the foreground process with Ctrl-C:

^C
$ printf 'xev stopped with status %s\n' "$?"
xev stopped with status 130

The exact status after Ctrl-C is shell-dependent, but a non-zero interrupt status is normal. Starting and stopping this test changes no persistent X configuration.

3. Filter the output when all events are too distracting

By default, xev selects every event type its command-line masks support. Narrow that with -event, which can be repeated:

$ xev -event keyboard -event mouse

Click, move the pointer and press keys inside the new window: you should see keyboard and mouse records while unrelated window-management noise drops out. The installed manpage lists these masks: keyboard, mouse, expose, visibility, structure, substructure, focus, property, colormap, owner_grab_button, randr and button.

Start with one mask when you're chasing a specific symptom, for example focus changes:

$ xev -event focus

Empty output is not necessarily a failure. Focus events need focus to actually move, so perform the action that should trigger one before assuming something is broken.

4. Save a short capture for comparison

Redirect standard output when you need to compare two runs or search for a specific record. The file grows fast, so stop the command deliberately:

$ xev -event keyboard > /tmp/xev-keyboard.txt

Type a keystroke or two in the xev window, press Ctrl-C in the terminal, then check the capture:

$ sed -n '1,24p' /tmp/xev-keyboard.txt
Outer window is 0x...
FocusIn event, serial ..., synthetic NO, window 0x...
    mode NotifyNormal, detail NotifyNonlinear
KeyPress event, serial ..., synthetic NO, window 0x...
    ...
$ test -s /tmp/xev-keyboard.txt && echo 'capture is non-empty'
capture is non-empty

Serial numbers, window IDs and line counts vary. Treat the capture as sensitive: it can contain the keys you typed. Remove it once you're done inspecting it, with rm -- /tmp/xev-keyboard.txt if it contains anything private.

Warning: that deletion is irreversible, so check the path before running it.

5. Monitor an existing window

To watch a window created by another X11 program, pass its hexadecimal window ID with -id:

$ xev -id 0xWINDOW_ID -event keyboard -event focus

Replace 0xWINDOW_ID with a real ID belonging to a window on the display named by DISPLAY. This mode does not create a test window; it asks the X server to watch the existing one you selected instead.

Get an ID with an installed X11 inspection tool such as xwininfo, if it's available:

$ xwininfo

Follow its prompt, click the target window, then copy the reported ID into the xev -id command and stop xwininfo. If the target closes, gets replaced, or does not allow the requested event selection, expect an error or nothing useful. That is a property of the target and its permissions, not a reason to run the command as root.

6. Use root monitoring only as a deliberate diagnostic

xev -root watches the display's root window instead of creating a new one:

$ xev -root -event property

This is a broad observation point: desktop components can fire property changes constantly, so start narrow and stop once you have the event you need. It is not a way to capture every event from every client either; X11 event selection rules and ownership still apply.

Security boundary: do not use -root or -id to monitor someone else's session. X event data can include keyboard details and window metadata. Only inspect a display and windows you are actually authorised to see.

7. Diagnose the common failures

Cannot open display: check DISPLAY, the session you're logged into and the X11 authorisation context. Do not guess a display number or copy another user's cookie. A Wayland-only session may still run X11 apps through a compatibility server, but that depends on your local desktop and environment.

Terminal filling with records: stop with Ctrl-C and add one or two -event filters. Empty capture: confirm you actually generated the selected event inside the xev window, and that the process is still running. A successful launch only proves the command connected and selected events; it does not prove the application you actually care about emitted the event you expected.

Done means