Phase 0: browser X11-overlay inventory + mpv reference cell + tooling installs

Source-level verdict: no browser in the matrix has a code path
to hand NV12 to the X server for plane scanout. Chromium ozone-x11
wires StubOverlayManager (ozone_platform_x11.cc:262); Brave 147 +
chromium-fourier 149 inherit unchanged. Firefox WindowSurfaceX11
is RGB-only. The campaign's load-bearing hypothesis is structurally
weakened — what the X11 cells will measure for browsers is
KWin's per-frame RGB-recomposite cost, not the original
"force-GL-composite of NV12" framing. mpv --vo=xv becomes the
matrix's only direct test of the operator-supplied mechanism.

Matrix updated: 12 cells -> 16 cells (+8 mpv VO sub-points).
revert.log entries 1-5 capture all package + per-user state
mutations from this turn (measurement tools, openbox, XFCE +
xfwm4-no-comp pre-seed, firefox + AUR xtrace, XFCE rotation
+ touchscreen mapping); single SSH-driveable revert chain
returns ohm to its pre-campaign 1169-package state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 11:14:46 +00:00
parent 5d34a957ee
commit d2e11be430
30 changed files with 13176 additions and 35 deletions
+7 -3
View File
@@ -24,9 +24,13 @@ forced GL-composite. **The campaign's load-bearing hypothesis
is that this plane-allocation freedom translates into
measurable browser-video speedup.**
The matrix is 3 browsers × 2 decode paths × 2 sessions = 12
cells (some N/A where libva isn't supported). See
`phase0_findings.md` for the full table.
The matrix is (3 browsers + mpv 0.41 as a reference X11-overlay
client) × 2 decode paths × 2 sessions = 16 cells (some N/A
where libva isn't supported). The mpv cells are run twice each
— once with `--vo=xv` (legacy XVideo overlay) and once with
`--vo=gpu --gpu-context=x11` (modern DRI3 + XPresent + Mesa GL).
See `phase0_findings.md` § "Experimental matrix" for the full
table and the rationale for mpv as reference baseline.
## Campaign-contained data discipline
@@ -0,0 +1,507 @@
# Phase 0 — Browser X11-overlay-path inventory
**Date:** 2026-05-03
**Scope:** answer worklist.md item *"Browser X11-overlay-path
inventory"* — for each of Brave 147, chromium-fourier 149,
Firefox 150, and the mpv 0.41 reference client, determine
**whether a code path exists under X11 to request
hardware-overlay scanout of NV12 video buffers**, vs always
GL-compositing internally to RGB before X11 presentation.
**Method:** source-level inspection. Local Firefox 149 source
tree (acquired by the predecessor as `firefox-fourier-work/`)
read directly. Chromium 147 source acquired from the
`chromium-builder` LXD CT on boltzmann via the his subagent —
13 files, 180 KB, copied into
`phase0_evidence/chromium_ozone_x11_2026-05-03/` with full
provenance in that subtree's `README.txt`. mpv inspected via
upstream docs + its installed binary's `--vo=help`. **Runtime
engagement (does the path actually fire at playback time?) is
NOT covered here** — that's a separate, attended-launch
follow-up; design sketch at the end of this doc.
## TL;DR
| Client | X11 overlay path exists in code? | Runtime-engaged today? | Notes |
|---|---|---|---|
| Brave 147 | **No.** ozone-x11 uses `StubOverlayManager`. | N/A | upstream Chromium 147 + Brave UI patches; Ozone unchanged |
| chromium-fourier 149 | **No.** Same as upstream Chromium 149. | N/A | local patches target decode side only; Ozone unchanged |
| Firefox 150 | **No.** `WindowSurfaceX11{,Image,SHM}` are RGB-only. | N/A | gfx/webrender_bindings has DComp (Windows), no Linux equivalent |
| mpv 0.41 `--vo=xv` | **Yes (XVideo legacy path).** | unknown | only path in this matrix that *could* engage a hardware plane via X server's Xv adapter |
| mpv 0.41 `--vo=gpu --gpu-context=x11` | **No.** GL composite, identical plumbing to browsers. | N/A | DRI3 + XPresent of an RGB GL-composited framebuffer, same as Chromium/Firefox under X11 |
**Headline finding:** every Blink-based browser (Brave,
chromium-fourier) and Firefox under stock X11 ozone *cannot* hand
an NV12 dmabuf to the X server for hardware-overlay scanout;
they always GL-composite NV12 → RGB in their own GPU process and
then present an RGB framebuffer to the X server.
This **structurally weakens** the campaign's load-bearing
hypothesis (`README.md` § 1: *"the campaign's load-bearing
hypothesis is that this plane-allocation freedom translates into
measurable browser-video speedup"*). The freedom *exists* at the
DRM/Xorg layer — Plane 39 NV12 LINEAR is reachable to X11
clients in principle — but **no shipping browser ever tries to
exercise it** under X11. What the matrix's X11 cells will
actually measure for browsers is the cost of the GL composite
running in the *browser's* GPU process vs the GL composite
running in *kwin_wayland*'s process — an interesting question,
but a different one from the stated mechanism.
The mpv `--vo=xv` cell becomes the matrix's most important
single data point: it's the only client in the campaign that
can *attempt* to engage an X11 hardware-overlay plane directly.
A clean `--vo=xv` engagement establishes that the X11
hardware-overlay path *works on this hardware*; absence
establishes it doesn't even exist on rockchip-drm + Panfrost +
modesetting Xorg.
---
## Chromium ozone-x11: `StubOverlayManager` (decisive)
Source provenance:
`phase0_evidence/chromium_ozone_x11_2026-05-03/`
(Chromium 147.0.7727.116 from `chromium-builder` LXD CT on
boltzmann; tarball mtime 2026-04-25).
### The wiring
`ui/ozone/platform/x11/ozone_platform_x11.cc:262`:
```cpp
overlay_manager_ = std::make_unique<StubOverlayManager>();
```
`StubOverlayManager` (in `ui/ozone/common/stub_overlay_manager.h`)
implements the `OverlayManagerOzone` interface as a no-op —
its `CreateOverlayCandidates()` returns no candidates. Whatever
chromium's `OverlayProcessor` asks the X11 backend, the answer
is "no overlay possible here" and the regular GL-composite path
runs.
**Contrast with Wayland**
(`ui/ozone/platform/wayland/ozone_platform_wayland.cc:330`):
```cpp
std::make_unique<WaylandOverlayManager>(buffer_manager_.get());
```
A real `WaylandOverlayManager` backed by the
`WaylandBufferManagerHost`. This is the path the predecessor
campaign `kwin_overlay_subsurface` was investigating — the route
where Chromium emits `wp_subsurface` overlay candidates that
KWin Wayland may or may not promote to scanout planes (and
historically didn't, hence the predecessor's Phase 8 closure).
### What the X11 directory does NOT contain
Directory listing of `ui/ozone/platform/x11/` (from `README.txt`)
filtered for relevance:
```
$ ls ui/ozone/platform/x11/ | grep -iE 'overlay|buffer.*manager|dmabuf|present'
x11_window_manager.cc
x11_window_manager.h
```
`x11_window_manager` is the WM-events bookkeeping class
(focus/raise/restack), unrelated to overlays. **There is no
`x11_overlay_manager.cc`, no `x11_buffer_manager_host.cc`, no
`x11_dmabuf_*.cc`, and no `x11_present_*.cc`** — files that
exist on the Wayland side. The X11 backend has no machinery
to track overlay candidates, no buffer-manager IPC, no
dmabuf-feedback handling, and no Present-extension protocol
support.
### What the X11 directory DOES contain — and why it's not enough
`x11_surface_factory.cc:40-43`:
```cpp
// Native pixmaps are first imported as X11 pixmaps using DRI3
// and then into EGL.
```
DRI3 IS used by ozone-x11. But the path is:
1. GPU process gets an NV12 dmabuf from the video decoder
(VAAPI / V4L2VideoDecoder).
2. `X11SurfaceFactory::CreateNativePixmap()` wraps it as a
`gfx::NativePixmapDmaBuf`.
3. The dmabuf is imported either directly via
`EGL_EXT_image_dma_buf_import` or, as a fallback, by
creating an X11 Pixmap via DRI3 and binding that as an
EGL image.
4. **Either way, the resulting EGL image is sampled by
Chromium's GL compositor** to render the WebRender output.
5. The browser's final RGB framebuffer is presented to the X
server via `glXSwapBuffers` (or equivalent EGL swap).
This is the GL-composite path — the same path browsers use on
every X11 + GL-context combo since the late 2000s. The dmabuf
is consumed by the GPU process, not handed to the X server for
plane scanout. Plane 39 (the only NV12-LINEAR-capable plane on
rockchip-drm) is programmed by the X server at scanout time
with the **RGB** browser framebuffer, not the NV12 video buffer.
### What `chrome://gpu` would show for video acceleration
Independent of decode-side acceleration, the
*Hardware-accelerated video decode* line in `chrome://gpu` only
reports decoder status, not overlay status. `chrome://gpu`
doesn't have a "Hardware video overlay" line for Linux/X11 —
that line is Windows-only (`DCOMPSurface` on the DirectComposition
swap chain). The absence of such a line in chrome://gpu under
Linux/X11 is itself a sign: there's no overlay surface concept
in this backend.
### Brave 147 verdict
Brave is a Chromium fork. Its tree adds ~50 patches on top of
upstream Chromium covering UI/Shields/Wallet/IPFS/Tor/etc. None
of Brave's diff touches `ui/ozone/platform/x11/`, the
`OverlayProcessor`, or the GPU buffer pipeline. **Brave 147
under X11 has the identical "StubOverlayManager → GL composite"
behavior as upstream Chromium 147.**
### chromium-fourier 149 verdict
`marfrit-packages/arch/chromium-fourier/STUDY.md` documents the
patch set:
- Patch 1: bypass `media/gpu/chromeos/video_decoder_pipeline.cc`
on Linux non-ChromeOS so VaapiVideoDecoder gets used.
- Patch 2: V4L2VideoDecoder factory un-gating for non-ChromeOS.
- Patch 3 (cosmetic): default `LIBVA_DRIVER_NAME=v4l2_request`.
- `nv12-external-oes-on-modifier-external-only.patch`: EGL
import quirk for NV12 modifier-external dmabufs.
- `wayland-allow-direct-egl-gles2.patch`: Wayland-specific.
**All decode-side. Zero changes to `ui/ozone/platform/x11/`,
zero changes to the OverlayProcessor.** chromium-fourier 149's
X11 behavior is identical to upstream Chromium 149's, which is
in turn identical in Ozone shape to 147 (the
`StubOverlayManager` wiring dates to ~2019 and hasn't moved).
---
## Firefox 150 widget/gtk: RGB-only X11 surfaces (decisive)
Source: `firefox-fourier-work/firefox-149.0/`. Firefox 149 ≈ 150
on the X11-surface code path; this layer hasn't changed
materially in 5+ years.
### The X11 surface implementations
Firefox's X11 backend lives at `widget/gtk/WindowSurfaceX11*`:
- `WindowSurfaceX11.cpp` — abstract base.
- `WindowSurfaceX11Image.cpp` — XImage-based (slow legacy path).
- `WindowSurfaceX11SHM.cpp` — XShm-based (shared-memory pixmap).
`WindowSurfaceX11.cpp::GetVisualFormat()` enumerates exactly
three pixel formats:
```cpp
case 32: return gfx::SurfaceFormat::B8G8R8A8;
case 24: return gfx::SurfaceFormat::B8G8R8X8;
case 16: return gfx::SurfaceFormat::R5G6B5_UINT16;
```
All RGB. No NV12. No YUV. No dmabuf. Final pixel buffer is RGB
before reaching X.
A grep across all
`widget/gtk/WindowSurfaceX11*.{cpp,h}` files for any of
`dmabuf|DMABuf|NV12|YUV|hardware.*overlay|Plane|XPresent|DRI3`
returns **zero matches**. Firefox's X11 presentation path is
strictly software-RGB-pixmap → X.
### Why the dmabuf code in widget/gtk/ doesn't apply
Files like `DMABufSurface.cpp`, `DMABufBuffer.cpp`,
`WaylandSurface.cpp` exist and are reachable on Linux, but
their use is:
- Wayland-side: produce/consume `wl_buffer` dmabufs for the
client→compositor handoff via `zwp_linux_dmabuf_v1`.
- VAAPI-decode-side: import a hardware-decoded NV12 dmabuf as
an EGL image so Firefox's WebRender can sample it as a
texture.
In the second case (VAAPI under X11), the dmabuf is consumed by
Firefox's own GPU process for compositing. The composited
output is then handed to `WindowSurfaceX11SHM` as RGB —
identical situation to Chromium.
### Mozilla's `gfx.x11-egl.force-enabled` pref
`modules/libpref/init/StaticPrefList.yaml`:
```yaml
- name: gfx.x11-egl.force-enabled
type: bool
value: false
mirror: once
# Whether to force using EGL over GLX.
```
This forces Firefox to use **EGL over GLX** for its GL context
under X11 (better dmabuf import support since EGL has
`EGL_EXT_image_dma_buf_import`, GLX doesn't). It changes the
GPU-process composite-input plumbing, **not** the
WindowSurfaceX11 presentation plumbing. The output to X is
still RGB.
### Mozilla's hardware-overlay code is Windows-only
The only files in Firefox 149 source matching
`hardware.*overlay`:
- `gfx/webrender_bindings/DCLayerTree.cpp`
DirectComposition layer tree (Windows).
- `gfx/webrender_bindings/RenderCompositorANGLE.cpp`
ANGLE composition (Windows).
- `gfx/config/gfxFeature.h` — feature-flag enum.
- `gfx/thebes/gfxPlatform.cpp` — feature-flag plumbing.
There is no Linux/X11 hardware-overlay equivalent. Mozilla's
`MOZ_X11_EGL` env var (sometimes mentioned in forum threads as
a "force X11 hardware overlay" toggle) is just a synonym for
`gfx.x11-egl.force-enabled` — same EGL-vs-GLX scope, no
overlay-scanout effect.
### Firefox 150 verdict
**No X11 hardware-overlay path. Firefox under X11 always
GL-composites NV12 → RGB internally and presents RGB to the X
server.** Same architectural shape as Chromium ozone-x11.
---
## mpv 0.41: the only client with a path that *could* engage X11 hardware overlay
mpv installed: `mpv 1:0.41.0-3` with `libplacebo v7.360.1`
(per `02_x11_paths.txt`).
### `--vo=xv` — the legacy XVideo overlay path
XVideo (`Xv`) is an X protocol extension dating to the late
1990s, designed precisely for hardware video overlays: the
client hands the X server a YUV image; the X server programs a
hardware video plane (where available) to scanout that image,
hardware-blended with the rest of the desktop. On modesetting
Xorg driver + a DRM driver that exposes a YUV-capable plane,
the X server's XVideo adapter wires through DRI2/DRI3 to the
DRM plane allocator, and YUV image goes onto a hardware plane.
`xdpyinfo` on ohm confirms XVideo extension is initialized on
the running X server (`03_xprotocol_extensions.txt:50`,
`Xorg.0.log` line 96-97 in `01_live_session.txt`).
**Whether modesetting + rockchip-drm actually wires XVideo to
Plane 39 is the empirical question.** Possible outcomes:
- mpv `--vo=xv` programs Plane 39 NV12 → X11 hardware-overlay
path is reachable on this hardware, and the campaign has its
reference baseline.
- mpv `--vo=xv` falls back to software YUV→RGB conversion in
the X server (the modesetting "shadow Xv adapter" path) →
no hardware-overlay path on this hardware, regardless of
client.
A 5-second mpv `--vo=xv` run under a non-compositing WM, with
`drm_info` snapshots taken before / during / after, will
unambiguously answer this. *Design at the end of this doc.*
### `--vo=gpu --gpu-context=x11` — modern Mesa GL path
mpv's modern GL VO uses the same plumbing as the browsers:
DRI3 + XPresent + Mesa GL. `--hwdec=auto` or
`--hwdec=v4l2request-copy` decodes via libva → NV12 dmabuf →
imports as EGL image → mpv samples it in libplacebo's GL
compositor → glXSwapBuffers RGB to X.
This is **not** an X11 hardware-overlay path. It's the same
client-side GL composite that browsers do. Useful as a
control: if `--vo=gpu` is markedly slower than `--vo=xv` on
the same machine + same workload, the delta is the
hardware-overlay-vs-GL-composite gap — which is exactly the
quantity the campaign wants to measure.
### `--vo=drm` — bypass X entirely (NOT in scope)
mpv has a `--vo=drm` VO that talks directly to KMS, bypassing
X. The KWIN_PIVOT.md from chromium-fourier already reports
0.7 % drops with mpv `--vo=drm --hwdec=v4l2request` under no
compositor — strong evidence the underlying hardware path
(decode + DRM scanout) is healthy on this stack. But `--vo=drm`
isn't an X11 path; it doesn't tell us anything about whether
the X server can do the same plane assignment for a windowed
client. **Not added to the matrix.** Useful as a "this is the
hardware ceiling" reference outside the matrix.
---
## Implications for the matrix
### What the X11 cells of the matrix actually measure for the three browsers
Given the StubOverlayManager / WindowSurfaceX11-RGB-only
findings, the X11-cell value chain for browsers is:
1. Browser GPU process decodes video → NV12 dmabuf.
2. NV12 dmabuf imported as EGL image.
3. **Browser GPU process GL-composites NV12 → RGB** in its own
GL context (via libplacebo equivalents in Chromium's WebRender
or Firefox's WebRender).
4. RGB framebuffer presented via DRI3 + XPresent to the X
server.
5. **X server's plane allocator schedules the RGB pixmap on
Plane 39** (since on rockchip-drm Plane 39 is the only one
that can scan out the browser-window-sized buffer; Plane 45
doesn't accept RGB AFBC at the resolutions involved either,
though it does accept RGB LINEAR — to be confirmed).
Compare to Wayland-with-KWin cell:
1. Browser GPU process decodes → NV12 dmabuf.
2. NV12 dmabuf imported as EGL image (or sent via wp_subsurface
if the browser engages that route — in practice, per the
predecessor campaign, browsers don't engage wp_subsurface for
the test page).
3. **Browser GPU process GL-composites NV12 → RGB** in its own
GL context (same as X11 cell).
4. RGB framebuffer dispatched to KWin via wl_surface attach.
5. **KWin GL-composites the browser's RGB surface** with the
rest of the desktop (the wallpaper, panels, etc.).
6. KWin's merged RGB framebuffer goes to Plane 39.
The structural delta the matrix's X11 vs Wayland cells will
actually measure for browsers is therefore **the cost of step
5 in the Wayland flow** — KWin's per-frame compositing of
already-RGB browser surfaces onto its merged framebuffer. The
NV12-GL-composite (step 3) happens in *both* sessions, in the
*browser's* GPU process. The campaign's hypothesised "force-GL-
composite of every NV12 video buffer" is performed by the
browser regardless of session, not by KWin.
This **does not invalidate the campaign**. KWin's per-frame RGB
composite is still measurable and the predecessor's
`kwin_wayland %CPU at steady-state ~36 %` is suggestive that
this overhead is real. But the magnitude and the mechanism are
different from the original framing.
### Where the original "plane allocation freedom" hypothesis still applies
For the **mpv `--vo=xv`** cell — and ONLY that cell — the
client genuinely tries to hand NV12 to the X server for
scanout. Under without-KWin (X11 + non-compositing WM), the
X server is free to put that NV12 buffer on Plane 39 and
the desktop on Plane 45 — exactly the campaign's mechanism,
realised. Under Wayland-with-KWin there is no equivalent path
at all (XVideo isn't a Wayland concept; XWayland would route
through KWin and lose any scanout opportunity). So the mpv-xv
row of the matrix is the **direct test** of the
operator-supplied mechanism — and likely the only one that
can produce a positive answer.
### Recommended Phase 1 framing
The campaign's research question stays valid but its
sub-questions sharpen:
- **Q1 (mpv `--vo=xv`):** does X11+non-compositing WM on
rockchip-drm-PineTab2 actually engage hardware-overlay
scanout for an NV12 client? (matrix cells `C-X-mpv-sw` and
`C-X-mpv-hw` with `--vo=xv`)
- **Q2 (browsers):** given that browsers always GL-composite
to RGB before presentation, does removing KWin from the
display path reduce the per-frame RGB-composite cost enough
to matter for video fps / drops? (the existing browser
cells, just with their interpretation tightened)
- **Q3 (mpv `--vo=gpu`):** is the GL-composite cost in mpv's
GPU process comparable to the browsers' GL-composite cost?
(i.e., is the browsers' overhead the GL-composite itself, or
something extra browsers do around it?)
A clean Q1 positive (mpv-xv hits Plane 39) plus a marginal Q2
(browsers don't speed up much without KWin) would be the
"X11 path is fast, but browsers leave it on the table"
verdict the campaign already named as a possible outcome
shape.
A Q1 negative (mpv-xv falls back to RGB anyway) would mean
the campaign's mechanism is structurally absent on this
hardware, regardless of session. In that case the matrix
collapses to "what's the per-frame KWin overhead?" — a
scoping the predecessor `kwin_overlay_subsurface` already
asked at the protocol level and got an answer to.
---
## Open: runtime engagement check (deferred, attended-launch)
The source-level inventory above answers "does the path
*exist* in the code". To answer "is the path *engaged at
runtime* for THIS hardware × THIS Mesa × THIS X server", a
per-client probe is needed. This is the right thing to do at
**Phase 1 binding-cell-design time**, not at Phase 0
inventory time.
### Probe sketch (for later)
For each client × X11-session combination, around a
short (10-30 s) test-video playback:
1. Pre-state: `drm_info | grep -A 20 'Plane 39'` and
`drm_info | grep -A 20 'Plane 45'` — capture plane state
before launch.
2. Launch the client (operator action: open the browser to
`brave_drops_test.html` or run mpv on a known short video).
3. Capture for 10 s mid-playback:
- `x11trace -k -d :0 -o /tmp/x11trace.<client>.log` for
~3 s (the AUR `x11trace` binary at `/usr/bin/x11trace`
installed in `revert.log` entry 3) — to see what X
protocol requests the client is issuing per frame.
- `drm_info` snapshot — to see which planes are now
programmed and with what FOURCC/modifier.
- `chrome://gpu` page text via DevTools / about:support
copy — for the browser's own self-report.
4. Post-state `drm_info`.
5. Diff: a positive engagement looks like **Plane 39
programmed with `NV12` FOURCC during step 3**; a negative
engagement is **Plane 39 programmed with `XR24` / `AR24`
RGB FOURCC for the entire window**.
The probe is shaped like a Phase 1 measurement protocol but
uses a much shorter window and isn't recording per-frame
metrics — it's just "does NV12 ever reach a hardware plane?"
binary outcome per cell.
### Why deferred
Running the probe productively requires:
- A non-compositing-WM session active (entry-1 openbox or
entry-2 XFCE-no-comp) — operator session switch needed.
- An operator at the keyboard to start each client.
- A short test video file on ohm at a known path — minor
prep, not done in this campaign yet.
- The matrix cells finalised with their browser flags
(`--enable-features=...`, `MOZ_X11_EGL=1`, etc.) so the
probe gives the right answer for the conditions Phase 1
will measure.
None of those is a blocker — but folding the probe into
Phase 1's first measurement rep (where the operator is
already at the keyboard launching browsers and a test video
is being played for fps-counting purposes) is more efficient
than running it standalone in Phase 0.
---
## Worklist update
`worklist.md` item *"NEW: Browser X11-overlay-path inventory"*
should flip to `[x]` with a pointer to this file.
@@ -0,0 +1,70 @@
# Source provenance
Host: boltzmann
Container: chromium-builder (LXD)
Path inside CT: /build/chromium/src
Tarball mtime: 2026-04-25 (chromium-147.0.7727.116.tar.xz)
Fetched: 2026-05-03
Reach recipe: ssh boltzmann "sudo lxc exec chromium-builder -- cat /build/chromium/src/<path>"
## Chromium VERSION + ui/ozone/platform/x11/ listing
MAJOR=147
MINOR=0
BUILD=7727
PATCH=116
---
total 384
drwxr-xr-x 1 builder builder 2298 Apr 21 17:50 .
drwxr-xr-x 1 builder builder 78 Apr 21 17:50 ..
-rw-r--r-- 1 builder builder 5298 Apr 21 17:50 BUILD.gn
-rw-r--r-- 1 builder builder 360 Apr 21 17:50 DEPS
-rw-r--r-- 1 builder builder 89 Apr 21 17:50 OWNERS
-rw-r--r-- 1 builder builder 2841 Apr 21 17:50 atk_event_conversion.cc
-rw-r--r-- 1 builder builder 1033 Apr 21 17:50 atk_event_conversion.h
-rw-r--r-- 1 builder builder 440 Apr 21 17:50 client_native_pixmap_factory_x11.cc
-rw-r--r-- 1 builder builder 556 Apr 21 17:50 client_native_pixmap_factory_x11.h
-rw-r--r-- 1 builder builder 1255 Apr 21 17:50 gl_egl_utility_x11.cc
-rw-r--r-- 1 builder builder 1133 Apr 21 17:50 gl_egl_utility_x11.h
-rw-r--r-- 1 builder builder 2469 Apr 21 17:50 gl_surface_egl_readback_x11.cc
-rw-r--r-- 1 builder builder 1280 Apr 21 17:50 gl_surface_egl_readback_x11.h
-rw-r--r-- 1 builder builder 1218 Apr 21 17:50 hit_test_x11.cc
-rw-r--r-- 1 builder builder 508 Apr 21 17:50 hit_test_x11.h
-rw-r--r-- 1 builder builder 1198 Apr 21 17:50 linux_ui_delegate_x11.cc
-rw-r--r-- 1 builder builder 894 Apr 21 17:50 linux_ui_delegate_x11.h
-rw-r--r-- 1 builder builder 8235 Apr 21 17:50 native_pixmap_egl_x11_binding.cc
-rw-r--r-- 1 builder builder 1553 Apr 21 17:50 native_pixmap_egl_x11_binding.h
-rw-r--r-- 1 builder builder 1703 Apr 21 17:50 os_exchange_data_provider_x11.cc
-rw-r--r-- 1 builder builder 1726 Apr 21 17:50 os_exchange_data_provider_x11.h
-rw-r--r-- 1 builder builder 13470 Apr 21 17:50 ozone_platform_x11.cc
-rw-r--r-- 1 builder builder 458 Apr 21 17:50 ozone_platform_x11.h
drwxr-xr-x 1 builder builder 366 Apr 21 17:50 test
-rw-r--r-- 1 builder builder 5791 Apr 21 17:50 vulkan_implementation_x11.cc
-rw-r--r-- 1 builder builder 2126 Apr 21 17:50 vulkan_implementation_x11.h
-rw-r--r-- 1 builder builder 4729 Apr 21 17:50 vulkan_surface_x11.cc
-rw-r--r-- 1 builder builder 2797 Apr 21 17:50 vulkan_surface_x11.h
-rw-r--r-- 1 builder builder 1686 Apr 21 17:50 x11_canvas_surface.cc
-rw-r--r-- 1 builder builder 1962 Apr 21 17:50 x11_canvas_surface.h
-rw-r--r-- 1 builder builder 3845 Apr 21 17:50 x11_clipboard_ozone.cc
-rw-r--r-- 1 builder builder 2158 Apr 21 17:50 x11_clipboard_ozone.h
-rw-r--r-- 1 builder builder 1885 Apr 21 17:50 x11_global_shortcut_listener_ozone.cc
-rw-r--r-- 1 builder builder 1736 Apr 21 17:50 x11_global_shortcut_listener_ozone.h
-rw-r--r-- 1 builder builder 4440 Apr 21 17:50 x11_keyboard_hook.cc
-rw-r--r-- 1 builder builder 1600 Apr 21 17:50 x11_keyboard_hook.h
-rw-r--r-- 1 builder builder 440 Apr 21 17:50 x11_menu_utils.cc
-rw-r--r-- 1 builder builder 636 Apr 21 17:50 x11_menu_utils.h
-rw-r--r-- 1 builder builder 2846 Apr 21 17:50 x11_ozone_ui_controls_test_helper.cc
-rw-r--r-- 1 builder builder 2127 Apr 21 17:50 x11_ozone_ui_controls_test_helper.h
-rw-r--r-- 1 builder builder 9385 Apr 21 17:50 x11_screen_ozone.cc
-rw-r--r-- 1 builder builder 3750 Apr 21 17:50 x11_screen_ozone.h
-rw-r--r-- 1 builder builder 18003 Apr 21 17:50 x11_screen_ozone_unittest.cc
-rw-r--r-- 1 builder builder 8966 Apr 21 17:50 x11_surface_factory.cc
-rw-r--r-- 1 builder builder 2267 Apr 21 17:50 x11_surface_factory.h
-rw-r--r-- 1 builder builder 1191 Apr 21 17:50 x11_user_input_monitor.cc
-rw-r--r-- 1 builder builder 1279 Apr 21 17:50 x11_user_input_monitor.h
-rw-r--r-- 1 builder builder 876 Apr 21 17:50 x11_utils.cc
-rw-r--r-- 1 builder builder 754 Apr 21 17:50 x11_utils.h
-rw-r--r-- 1 builder builder 92805 Apr 21 17:50 x11_window.cc
-rw-r--r-- 1 builder builder 19102 Apr 21 17:50 x11_window.h
-rw-r--r-- 1 builder builder 3105 Apr 21 17:50 x11_window_manager.cc
-rw-r--r-- 1 builder builder 1813 Apr 21 17:50 x11_window_manager.h
-rw-r--r-- 1 builder builder 11141 Apr 21 17:50 x11_window_ozone_unittest.cc
@@ -0,0 +1,24 @@
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/common/stub_overlay_manager.h"
#include <memory>
#include "ui/ozone/public/overlay_candidates_ozone.h"
namespace ui {
StubOverlayManager::StubOverlayManager() {
}
StubOverlayManager::~StubOverlayManager() {
}
std::unique_ptr<OverlayCandidatesOzone>
StubOverlayManager::CreateOverlayCandidates(gfx::AcceleratedWidget w) {
return nullptr;
}
} // namespace ui
@@ -0,0 +1,30 @@
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_COMMON_STUB_OVERLAY_MANAGER_H_
#define UI_OZONE_COMMON_STUB_OVERLAY_MANAGER_H_
#include <memory>
#include "ui/ozone/public/overlay_manager_ozone.h"
namespace ui {
class StubOverlayManager : public OverlayManagerOzone {
public:
StubOverlayManager();
StubOverlayManager(const StubOverlayManager&) = delete;
StubOverlayManager& operator=(const StubOverlayManager&) = delete;
~StubOverlayManager() override;
// OverlayManagerOzone:
std::unique_ptr<OverlayCandidatesOzone> CreateOverlayCandidates(
gfx::AcceleratedWidget w) override;
};
} // namespace ui
#endif // UI_OZONE_COMMON_STUB_OVERLAY_MANAGER_H_
@@ -0,0 +1,204 @@
# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/chromeos/ui_mode.gni")
import("//gpu/vulkan/features.gni")
import("//ui/base/ui_features.gni")
visibility = [ "//ui/ozone/*" ]
assert(is_linux || is_chromeos)
source_set("x11") {
sources = [
"client_native_pixmap_factory_x11.cc",
"client_native_pixmap_factory_x11.h",
"gl_egl_utility_x11.cc",
"gl_egl_utility_x11.h",
"gl_surface_egl_readback_x11.cc",
"gl_surface_egl_readback_x11.h",
"hit_test_x11.cc",
"hit_test_x11.h",
"native_pixmap_egl_x11_binding.cc",
"native_pixmap_egl_x11_binding.h",
"os_exchange_data_provider_x11.cc",
"os_exchange_data_provider_x11.h",
"ozone_platform_x11.cc",
"ozone_platform_x11.h",
"x11_canvas_surface.cc",
"x11_canvas_surface.h",
"x11_clipboard_ozone.cc",
"x11_clipboard_ozone.h",
"x11_global_shortcut_listener_ozone.cc",
"x11_global_shortcut_listener_ozone.h",
"x11_keyboard_hook.cc",
"x11_keyboard_hook.h",
"x11_menu_utils.cc",
"x11_menu_utils.h",
"x11_screen_ozone.cc",
"x11_screen_ozone.h",
"x11_surface_factory.cc",
"x11_surface_factory.h",
"x11_user_input_monitor.cc",
"x11_user_input_monitor.h",
"x11_utils.cc",
"x11_utils.h",
"x11_window.cc",
"x11_window.h",
"x11_window_manager.cc",
"x11_window_manager.h",
]
deps = [
"//base",
"//build:chromecast_buildflags",
"//components/viz/common/resources:shared_image_format",
"//gpu/vulkan:buildflags",
"//net",
"//skia",
"//third_party/angle:includes",
"//ui/base",
"//ui/base:buildflags",
"//ui/base:data_exchange",
"//ui/base:hit_test",
"//ui/base:wm_role_names",
"//ui/base/clipboard:clipboard_types",
"//ui/base/cursor",
"//ui/base/data_transfer_policy",
"//ui/base/dragdrop:types",
"//ui/base/dragdrop/mojom",
"//ui/base/ime",
"//ui/base/x",
"//ui/base/x:gl",
"//ui/display/types",
"//ui/events",
"//ui/events:dom_keycode_converter",
"//ui/events/devices",
"//ui/events/devices/x11",
"//ui/events/ozone",
"//ui/events/ozone/layout",
"//ui/events/platform",
"//ui/events/platform/x11",
"//ui/events/x",
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/gfx/linux:gbm",
"//ui/gfx/linux:gbm_support_x11",
"//ui/gfx/x",
"//ui/gl",
"//ui/ozone:ozone_base",
"//ui/ozone/common",
"//ui/platform_window",
"//ui/platform_window/common",
"//ui/platform_window/wm",
]
if (is_linux) {
sources += [
"linux_ui_delegate_x11.cc",
"linux_ui_delegate_x11.h",
]
deps += [
"//components/dbus",
"//ui/base/clipboard:clipboard_util_linux",
"//ui/linux:linux_ui",
]
}
if (is_chromeos) {
deps += [ "//ui/base/ime/ash" ]
} else {
deps += [ "//ui/base/ime/linux" ]
}
if (enable_vulkan) {
sources += [
"vulkan_implementation_x11.cc",
"vulkan_implementation_x11.h",
"vulkan_surface_x11.cc",
"vulkan_surface_x11.h",
]
deps += [ "//gpu/vulkan" ]
}
if (use_xkbcommon) {
configs += [ "//ui/events/ozone/layout:xkbcommon" ]
}
if (use_atk) {
sources += [
"atk_event_conversion.cc",
"atk_event_conversion.h",
]
configs += [ "//build/config/linux/atk" ]
deps += [ "//ui/events/x" ]
}
}
source_set("x11_unittests") {
testonly = true
sources = [
"test/device_data_manager_x11_unittest.cc",
"test/events_x_unittest.cc",
"test/x11_event_translation_unittest.cc",
"test/x11_window_unittest.cc",
"x11_screen_ozone_unittest.cc",
"x11_window_ozone_unittest.cc",
]
deps = [
":x11",
"//base",
"//base/test:test_support",
"//skia",
"//testing/gmock",
"//testing/gtest",
"//ui/base",
"//ui/base:features",
"//ui/base/dragdrop:types",
"//ui/base/x",
"//ui/base/x:test_support",
"//ui/base/x:unittests",
"//ui/display:test_support",
"//ui/events:test_support",
"//ui/events/devices/x11",
"//ui/events/platform/x11",
"//ui/events/x",
"//ui/gfx:test_support",
"//ui/gfx/x",
"//ui/gfx/x:unit_test",
"//ui/ozone:platform",
"//ui/ozone:test_support",
"//ui/ozone/common",
]
if (!is_chromeos) {
sources += [ "test/os_exchange_data_provider_x11_unittest.cc" ]
deps += [ "//ui/base/clipboard:clipboard_types" ]
# ChromeOS uses a non-backed exchange data provider while the tests actually
# expect to use a normal X11 provider. Running these tests with a non-backed
# provided results in crashes when ownership selection call is made.
# Moreover, X11 on ChromeOS is used only for dev purposes and it doesn't
# support DnD between X11 windows. Instead, all the dnd operations are
# performed within a single native windows, where ash spawns number of own
# internal windows.
sources += [ "test/x11_drag_drop_client_unittest.cc" ]
}
}
source_set("test_support") {
testonly = true
sources = [
"x11_ozone_ui_controls_test_helper.cc",
"x11_ozone_ui_controls_test_helper.h",
]
deps = [
"//ui/aura",
"//ui/base/x",
"//ui/base/x:test_support",
]
}
@@ -0,0 +1,16 @@
include_rules = [
"+components/dbus",
"+components/viz/common/resources/shared_image_format.h",
"+components/viz/common/resources/shared_image_format_utils.h",
"+dbus/bus.h",
"+net/base/network_interfaces.h",
"+ui/base/x",
"+ui/base",
"+ui/linux",
]
specific_include_rules = {
"x11_ozone_ui_controls_test_helper.cc": [
"+ui/aura",
]
}
@@ -0,0 +1,375 @@
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/x11/ozone_platform_x11.h"
#include <memory>
#include <string>
#include <utility>
#include "base/command_line.h"
#include "base/message_loop/message_pump_type.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "ui/base/buildflags.h"
#include "ui/base/cursor/cursor_factory.h"
#include "ui/base/dragdrop/os_exchange_data_provider_factory_ozone.h"
#include "ui/base/x/x11_cursor_factory.h"
#include "ui/base/x/x11_util.h"
#include "ui/display/types/native_display_delegate.h"
#include "ui/events/devices/x11/touch_factory_x11.h"
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
#include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/linux/gbm_support_x11.h"
#include "ui/gfx/native_ui_types.h"
#include "ui/gfx/switches.h"
#include "ui/gfx/x/atom_cache.h"
#include "ui/gfx/x/visual_manager.h"
#include "ui/linux/linux_ui_delegate.h"
#include "ui/ozone/common/stub_overlay_manager.h"
#include "ui/ozone/platform/x11/gl_egl_utility_x11.h"
#include "ui/ozone/platform/x11/linux_ui_delegate_x11.h"
#include "ui/ozone/platform/x11/x11_clipboard_ozone.h"
#include "ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.h"
#include "ui/ozone/platform/x11/x11_keyboard_hook.h"
#include "ui/ozone/platform/x11/x11_menu_utils.h"
#include "ui/ozone/platform/x11/x11_screen_ozone.h"
#include "ui/ozone/platform/x11/x11_surface_factory.h"
#include "ui/ozone/platform/x11/x11_user_input_monitor.h"
#include "ui/ozone/platform/x11/x11_utils.h"
#include "ui/ozone/platform/x11/x11_window.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
#include "ui/ozone/public/input_controller.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/stub_input_controller.h"
#include "ui/ozone/public/system_input_injector.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_init_properties.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "ui/base/dragdrop/os_exchange_data_provider_non_backed.h"
#include "ui/base/ime/ash/input_method_ash.h"
#else
#include "ui/base/ime/linux/input_method_auralinux.h"
#include "ui/ozone/platform/x11/os_exchange_data_provider_x11.h"
#endif
namespace ui {
namespace {
// Singleton OzonePlatform implementation for X11 platform.
class OzonePlatformX11 : public OzonePlatform,
public OSExchangeDataProviderFactoryOzone {
public:
OzonePlatformX11() { SetInstance(this); }
OzonePlatformX11(const OzonePlatformX11&) = delete;
OzonePlatformX11& operator=(const OzonePlatformX11&) = delete;
~OzonePlatformX11() override = default;
// OzonePlatform:
ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override {
return surface_factory_ozone_.get();
}
ui::OverlayManagerOzone* GetOverlayManager() override {
return overlay_manager_.get();
}
CursorFactory* GetCursorFactory() override { return cursor_factory_.get(); }
std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override {
return nullptr;
}
InputController* GetInputController() override {
return input_controller_.get();
}
GpuPlatformSupportHost* GetGpuPlatformSupportHost() override {
return gpu_platform_support_host_.get();
}
std::unique_ptr<PlatformWindow> CreatePlatformWindow(
PlatformWindowDelegate* delegate,
PlatformWindowInitProperties properties) override {
auto window = std::make_unique<X11Window>(delegate);
window->Initialize(std::move(properties));
return std::move(window);
}
std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate()
override {
return nullptr;
}
std::unique_ptr<PlatformScreen> CreateScreen() override {
return std::make_unique<X11ScreenOzone>();
}
void InitScreen(PlatformScreen* screen) override {
// InitScreen is always called with the same screen that CreateScreen
// hands back, so it is safe to cast here.
static_cast<X11ScreenOzone*>(screen)->Init();
}
PlatformClipboard* GetPlatformClipboard() override {
return clipboard_.get();
}
PlatformGLEGLUtility* GetPlatformGLEGLUtility() override {
if (!gl_egl_utility_)
gl_egl_utility_ = std::make_unique<GLEGLUtilityX11>();
return gl_egl_utility_.get();
}
std::unique_ptr<InputMethod> CreateInputMethod(
ImeKeyEventDispatcher* ime_key_event_dispatcher,
gfx::AcceleratedWidget widget) override {
#if BUILDFLAG(IS_CHROMEOS)
return std::make_unique<ash::InputMethodAsh>(ime_key_event_dispatcher);
#else
return std::make_unique<InputMethodAuraLinux>(ime_key_event_dispatcher,
widget);
#endif
}
PlatformMenuUtils* GetPlatformMenuUtils() override {
return menu_utils_.get();
}
PlatformUtils* GetPlatformUtils() override { return x11_utils_.get(); }
PlatformGlobalShortcutListener* GetPlatformGlobalShortcutListener(
PlatformGlobalShortcutListenerDelegate* delegate) override {
if (!global_shortcut_listener_) {
global_shortcut_listener_ =
std::make_unique<X11GlobalShortcutListenerOzone>(delegate);
}
return global_shortcut_listener_.get();
}
std::unique_ptr<PlatformKeyboardHook> CreateKeyboardHook(
PlatformKeyboardHookTypes type,
base::RepeatingCallback<void(KeyEvent* event)> callback,
std::optional<base::flat_set<DomCode>> dom_codes,
gfx::AcceleratedWidget accelerated_widget) override {
switch (type) {
case PlatformKeyboardHookTypes::kModifier:
return std::make_unique<X11KeyboardHook>(
std::move(dom_codes), std::move(callback), accelerated_widget);
case PlatformKeyboardHookTypes::kMedia:
return nullptr;
}
}
std::unique_ptr<OSExchangeDataProvider> CreateProvider() override {
#if BUILDFLAG(IS_CHROMEOS)
return std::make_unique<OSExchangeDataProviderNonBacked>();
#else
return std::make_unique<OSExchangeDataProviderX11>();
#endif
}
const PlatformProperties& GetPlatformProperties() override {
using SupportsForTest = OzonePlatform::PlatformProperties::SupportsForTest;
const auto& override_set_parent_for_non_top_level_windows_for_test =
OzonePlatform::PlatformProperties::
override_set_parent_for_non_top_level_windows_for_test;
static base::NoDestructor<OzonePlatform::PlatformProperties> properties;
static bool initialised = false;
if (!initialised) {
properties->custom_frame_pref_default = ui::GetCustomFramePrefDefault();
// When the Ozone X11 backend is running, use a UI loop to grab Expose
// events. See GLSurfaceGLX and https://crbug.com/326995.
properties->message_pump_type_for_gpu = base::MessagePumpType::UI;
// When the Ozone X11 backend is running, use a UI loop to dispatch
// SHM completion events.
properties->message_pump_type_for_viz_compositor =
base::MessagePumpType::UI;
properties->supports_vulkan_swap_chain = true;
properties->skia_can_fall_back_to_x11 = true;
properties->platform_shows_drag_image = false;
properties->app_modal_dialogs_use_event_blocker = true;
// Defaults to false unless explicitly enabled for testing.
properties->set_parent_for_non_top_level_windows =
override_set_parent_for_non_top_level_windows_for_test ==
SupportsForTest::kYes;
initialised = true;
}
return *properties;
}
const PlatformRuntimeProperties& GetPlatformRuntimeProperties() override {
static OzonePlatform::PlatformRuntimeProperties properties;
if (has_initialized_gpu() &&
ui::GBMSupportX11::GetInstance()->has_gbm_device()) {
// This property is set when the GetPlatformRuntimeProperties is
// called on the gpu process side.
properties.supports_native_pixmaps = true;
}
properties.supports_subwindows_as_accelerated_widgets = false;
properties.supports_system_tray_windowing = true;
properties.supports_server_window_menus =
x11::Connection::Get()->WmSupportsHint(
x11::GetAtom("_GTK_SHOW_WINDOW_MENU"));
properties.supports_global_application_menus = true;
return properties;
}
bool IsNativePixmapConfigSupported(viz::SharedImageFormat format,
gfx::BufferUsage usage) const override {
return false;
}
bool IsWindowCompositingSupported() const override {
return x11::Connection::Get()
->GetOrCreateVisualManager()
.ArgbVisualAvailable();
}
bool InitializeUI(const InitParams& params) override {
if (ShouldFailInitializeUIForTest()) {
LOG(ERROR) << "Failing for test";
return false;
}
// If opening the connection failed, we can not do anything. The platform
// cannot initialise.
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kHeadless) &&
!x11::Connection::Get()->Ready()) {
LOG(ERROR) << "Missing X server or $DISPLAY";
return false;
}
InitializeCommon(params);
CreatePlatformEventSource();
overlay_manager_ = std::make_unique<StubOverlayManager>();
input_controller_ = std::make_unique<StubInputController>();
clipboard_ = std::make_unique<X11ClipboardOzone>();
cursor_factory_ = std::make_unique<X11CursorFactory>();
gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
// TODO(crbug.com/41472924): Support XKB.
keyboard_layout_engine_ = std::make_unique<StubKeyboardLayoutEngine>();
KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
keyboard_layout_engine_.get());
TouchFactory::SetTouchDeviceListFromCommandLine();
#if BUILDFLAG(USE_GTK)
linux_ui_delegate_ = std::make_unique<LinuxUiDelegateX11>();
#endif
menu_utils_ = std::make_unique<X11MenuUtils>();
x11_utils_ = std::make_unique<X11Utils>();
base::UmaHistogramEnumeration("Linux.WindowManager", GetWindowManagerUMA());
base::UmaHistogramBoolean(
"Linux.X11.XInput2",
x11::Connection::Get()->xinput_version().first == 2);
return true;
}
void InitializeGPU(const InitParams& params) override {
InitializeCommon(params);
if (params.enable_native_gpu_memory_buffers) {
base::ThreadPool::PostTask(FROM_HERE, base::BindOnce([]() {
ui::GBMSupportX11::GetInstance();
}));
}
// In single process mode either the UI thread will create an event source
// or it's a test and an event source isn't desired.
if (!params.single_process)
CreatePlatformEventSource();
// Set up the X11 connection before the sandbox gets set up. This cannot be
// done later since opening the connection requires socket() and connect().
auto connection = x11::Connection::Get()->Clone();
connection->DetachFromSequence();
surface_factory_ozone_ =
std::make_unique<X11SurfaceFactory>(std::move(connection));
}
void PostCreateMainMessageLoop(
base::OnceCallback<void()> shutdown_cb,
scoped_refptr<base::SingleThreadTaskRunner>) override {
// Installs the X11 error handlers for the UI process after the
// main message loop has started. This will allow us to exit cleanly
// if X exits before we do.
x11::Connection::Get()->SetIOErrorHandler(std::move(shutdown_cb));
}
std::unique_ptr<PlatformUserInputMonitor> GetPlatformUserInputMonitor(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
override {
return std::make_unique<X11UserInputMonitor>(std::move(io_task_runner));
}
private:
// Performs initialization steps need by both UI and GPU.
void InitializeCommon(const InitParams& params) {
if (common_initialized_)
return;
common_initialized_ = true;
}
// Creates |event_source_| if it doesn't already exist.
void CreatePlatformEventSource() {
if (event_source_)
return;
auto* connection = x11::Connection::Get();
event_source_ = std::make_unique<X11EventSource>(connection);
}
bool common_initialized_ = false;
// Objects in the UI process.
std::unique_ptr<KeyboardLayoutEngine> keyboard_layout_engine_;
std::unique_ptr<OverlayManagerOzone> overlay_manager_;
std::unique_ptr<InputController> input_controller_;
std::unique_ptr<X11ClipboardOzone> clipboard_;
std::unique_ptr<CursorFactory> cursor_factory_;
std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_;
std::unique_ptr<X11MenuUtils> menu_utils_;
std::unique_ptr<X11Utils> x11_utils_;
std::unique_ptr<PlatformGlobalShortcutListener> global_shortcut_listener_;
// Objects in the GPU process.
std::unique_ptr<X11SurfaceFactory> surface_factory_ozone_;
std::unique_ptr<GLEGLUtilityX11> gl_egl_utility_;
// Objects in both UI and GPU process.
std::unique_ptr<X11EventSource> event_source_;
#if BUILDFLAG(USE_GTK)
std::unique_ptr<LinuxUiDelegate> linux_ui_delegate_;
#endif
};
} // namespace
OzonePlatform* CreateOzonePlatformX11() {
return new OzonePlatformX11;
}
} // namespace ui
@@ -0,0 +1,17 @@
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_X11_OZONE_PLATFORM_X11_H_
#define UI_OZONE_PLATFORM_X11_OZONE_PLATFORM_X11_H_
namespace ui {
class OzonePlatform;
// Constructor hook for use in ozone_platform_list.cc
OzonePlatform* CreateOzonePlatformX11();
} // namespace ui
#endif // UI_OZONE_PLATFORM_X11_OZONE_PLATFORM_X11_H_
@@ -0,0 +1,267 @@
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/x11/x11_surface_factory.h"
#include <memory>
#include "components/viz/common/resources/shared_image_format_utils.h"
#include "gpu/vulkan/buildflags.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/linux/gbm_buffer.h"
#include "ui/gfx/linux/gbm_support_x11.h"
#include "ui/gfx/linux/native_pixmap_dmabuf.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/gl_surface_egl_x11_gles2.h"
#include "ui/ozone/common/egl_util.h"
#include "ui/ozone/common/gl_ozone_egl.h"
#include "ui/ozone/common/native_pixmap_egl_binding.h"
#include "ui/ozone/platform/x11/gl_surface_egl_readback_x11.h"
#include "ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h"
#include "ui/ozone/platform/x11/x11_canvas_surface.h"
#if BUILDFLAG(ENABLE_VULKAN)
#include "ui/ozone/platform/x11/vulkan_implementation_x11.h"
#endif
namespace ui {
namespace {
enum class NativePixmapSupportType {
// Importing native pixmaps not supported.
kNone,
// Native pixmaps are imported directly into EGL using the
// EGL_EXT_image_dma_buf_import extension.
kDMABuf,
// Native pixmaps are first imported as X11 pixmaps using DRI3 and then into
// EGL.
kX11Pixmap,
};
NativePixmapSupportType GetNativePixmapSupportType() {
if (gl::GLSurfaceEGL::GetGLDisplayEGL()
->ext->b_EGL_EXT_image_dma_buf_import) {
return NativePixmapSupportType::kDMABuf;
} else if (NativePixmapEGLX11Binding::CanImportNativeGLXPixmap()) {
return NativePixmapSupportType::kX11Pixmap;
} else {
return NativePixmapSupportType::kNone;
}
}
class GLOzoneEGLX11 : public GLOzoneEGL {
public:
GLOzoneEGLX11() = default;
GLOzoneEGLX11(const GLOzoneEGLX11&) = delete;
GLOzoneEGLX11& operator=(const GLOzoneEGLX11&) = delete;
~GLOzoneEGLX11() override = default;
// GLOzone:
bool InitializeStaticGLBindings(
const gl::GLImplementationParts& implementation) override {
is_swiftshader_ = gl::IsSoftwareGLImplementation(implementation);
return GLOzoneEGL::InitializeStaticGLBindings(implementation);
}
bool CanImportNativePixmap(viz::SharedImageFormat format) override {
if (GetNativePixmapSupportType() == NativePixmapSupportType::kNone) {
return false;
}
switch (GetNativePixmapSupportType()) {
case NativePixmapSupportType::kDMABuf: {
return NativePixmapEGLBinding::IsSharedImageFormatSupported(format);
}
case NativePixmapSupportType::kX11Pixmap: {
return NativePixmapEGLX11Binding::IsSharedImageFormatSupported(format);
}
default:
return false;
}
}
scoped_refptr<gl::GLSurface> CreateViewGLSurface(
gl::GLDisplay* display,
gfx::AcceleratedWidget window) override {
if (is_swiftshader_) {
return gl::InitializeGLSurface(
base::MakeRefCounted<GLSurfaceEglReadbackX11>(
display->GetAs<gl::GLDisplayEGL>(), window));
} else {
switch (gl::GetGLImplementation()) {
case gl::kGLImplementationEGLGLES2:
DCHECK(window != gfx::kNullAcceleratedWidget);
return gl::InitializeGLSurface(new gl::NativeViewGLSurfaceEGLX11GLES2(
display->GetAs<gl::GLDisplayEGL>(),
static_cast<x11::Window>(window)));
case gl::kGLImplementationEGLANGLE:
DCHECK(window != gfx::kNullAcceleratedWidget);
return gl::InitializeGLSurface(new gl::NativeViewGLSurfaceEGLX11(
display->GetAs<gl::GLDisplayEGL>(),
static_cast<x11::Window>(window)));
default:
NOTREACHED();
}
}
}
scoped_refptr<gl::GLSurface> CreateOffscreenGLSurface(
gl::GLDisplay* display,
const gfx::Size& size) override {
gl::GLDisplayEGL* egl_display = display->GetAs<gl::GLDisplayEGL>();
if (egl_display->IsEGLSurfacelessContextSupported() && size.width() == 0 &&
size.height() == 0) {
return InitializeGLSurface(new gl::SurfacelessEGL(egl_display, size));
} else {
return InitializeGLSurface(
new gl::PbufferGLSurfaceEGL(egl_display, size));
}
}
protected:
// GLOzoneEGL:
gl::EGLDisplayPlatform GetNativeDisplay() override {
return gl::EGLDisplayPlatform(reinterpret_cast<EGLNativeDisplayType>(
x11::Connection::Get()->GetXlibDisplay().display()));
}
bool LoadGLES2Bindings(
const gl::GLImplementationParts& implementation) override {
return LoadDefaultEGLGLES2Bindings(implementation);
}
private:
std::unique_ptr<NativePixmapGLBinding> ImportNativePixmap(
scoped_refptr<gfx::NativePixmap> pixmap,
viz::SharedImageFormat plane_format,
std::optional<int> plane_index,
gfx::Size plane_size,
const gfx::ColorSpace& color_space,
GLenum target,
GLuint texture_id) override {
switch (GetNativePixmapSupportType()) {
case NativePixmapSupportType::kDMABuf: {
return NativePixmapEGLBinding::Create(pixmap, plane_format, plane_index,
plane_size, color_space, target,
texture_id);
}
case NativePixmapSupportType::kX11Pixmap: {
return NativePixmapEGLX11Binding::Create(
pixmap, plane_format, plane_size, target, texture_id);
}
default:
return nullptr;
}
}
bool is_swiftshader_ = false;
};
} // namespace
X11SurfaceFactory::X11SurfaceFactory(
std::unique_ptr<x11::Connection> connection)
: egl_implementation_(std::make_unique<GLOzoneEGLX11>()),
connection_(std::move(connection)) {}
X11SurfaceFactory::~X11SurfaceFactory() = default;
std::vector<gl::GLImplementationParts>
X11SurfaceFactory::GetAllowedGLImplementations() {
return std::vector<gl::GLImplementationParts>{
gl::GLImplementationParts(gl::kGLImplementationEGLANGLE),
};
}
GLOzone* X11SurfaceFactory::GetGLOzone(
const gl::GLImplementationParts& implementation) {
switch (implementation.gl) {
case gl::kGLImplementationEGLANGLE:
return egl_implementation_.get();
default:
return nullptr;
}
}
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation>
X11SurfaceFactory::CreateVulkanImplementation(bool use_swiftshader,
bool allow_protected_memory) {
return std::make_unique<VulkanImplementationX11>(use_swiftshader);
}
#endif
std::unique_ptr<SurfaceOzoneCanvas> X11SurfaceFactory::CreateCanvasForWidget(
gfx::AcceleratedWidget widget) {
// X11SoftwareBitmapPresenter (created via X11CanvasSurface) requres a
// Connection TLS instance and a PlatformEventSource.
if (connection_) {
auto* connection = connection_.get();
x11::Connection::Set(std::move(connection_));
connection->platform_event_source =
std::make_unique<X11EventSource>(connection);
}
return std::make_unique<X11CanvasSurface>(widget);
}
scoped_refptr<gfx::NativePixmap> X11SurfaceFactory::CreateNativePixmap(
gfx::AcceleratedWidget widget,
gpu::VulkanDeviceQueue* device_queue,
gfx::Size size,
viz::SharedImageFormat format,
gfx::BufferUsage usage,
std::optional<gfx::Size> framebuffer_size) {
scoped_refptr<gfx::NativePixmapDmaBuf> pixmap;
auto buffer =
ui::GBMSupportX11::GetInstance()->CreateBuffer(format, size, usage);
if (buffer) {
gfx::NativePixmapHandle handle = buffer->ExportHandle();
if (handle.planes.empty()) {
return nullptr;
}
pixmap = base::MakeRefCounted<gfx::NativePixmapDmaBuf>(size, format,
std::move(handle));
}
// CreateNativePixmap is non-blocking operation. Thus, it is safe to call it
// and return the result with the provided callback.
return pixmap;
}
bool X11SurfaceFactory::CanCreateNativePixmapForFormat(
viz::SharedImageFormat format) {
return ui::GBMSupportX11::GetInstance()->CanCreateBufferForFormat(format);
}
scoped_refptr<gfx::NativePixmap>
X11SurfaceFactory::CreateNativePixmapFromHandle(
gfx::AcceleratedWidget widget,
gfx::Size size,
viz::SharedImageFormat format,
gfx::NativePixmapHandle handle) {
scoped_refptr<gfx::NativePixmapDmaBuf> pixmap;
auto buffer = ui::GBMSupportX11::GetInstance()->CreateBufferFromHandle(
size, format, std::move(handle));
if (buffer) {
gfx::NativePixmapHandle buffer_handle = buffer->ExportHandle();
if (buffer_handle.planes.empty()) {
return nullptr;
}
pixmap = base::MakeRefCounted<gfx::NativePixmapDmaBuf>(
size, format, std::move(buffer_handle));
}
return pixmap;
}
bool X11SurfaceFactory::IsFormatSupportedForTexturing(
viz::SharedImageFormat format) const {
return ui::GBMSupportX11::GetInstance()->CanCreateBufferForFormat(format);
}
} // namespace ui
@@ -0,0 +1,65 @@
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_X11_X11_SURFACE_FACTORY_H_
#define UI_OZONE_PLATFORM_X11_X11_SURFACE_FACTORY_H_
#include <memory>
#include <vector>
#include "components/viz/common/resources/shared_image_format.h"
#include "gpu/vulkan/buildflags.h"
#include "ui/gfx/x/connection.h"
#include "ui/gl/gl_surface.h"
#include "ui/ozone/public/gl_ozone.h"
#include "ui/ozone/public/surface_factory_ozone.h"
namespace ui {
// Handles GL initialization and surface/context creation for X11.
class X11SurfaceFactory : public SurfaceFactoryOzone {
public:
explicit X11SurfaceFactory(std::unique_ptr<x11::Connection> connection);
X11SurfaceFactory(const X11SurfaceFactory&) = delete;
X11SurfaceFactory& operator=(const X11SurfaceFactory&) = delete;
~X11SurfaceFactory() override;
// SurfaceFactoryOzone:
std::vector<gl::GLImplementationParts> GetAllowedGLImplementations() override;
GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override;
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation(
bool use_swiftshader,
bool allow_protected_memory) override;
#endif
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
gfx::AcceleratedWidget widget) override;
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
gfx::AcceleratedWidget widget,
gpu::VulkanDeviceQueue* device_queue,
gfx::Size size,
viz::SharedImageFormat format,
gfx::BufferUsage usage,
std::optional<gfx::Size> framebuffer_size = std::nullopt) override;
bool CanCreateNativePixmapForFormat(viz::SharedImageFormat format) override;
scoped_refptr<gfx::NativePixmap> CreateNativePixmapFromHandle(
gfx::AcceleratedWidget widget,
gfx::Size size,
viz::SharedImageFormat format,
gfx::NativePixmapHandle handle) override;
bool IsFormatSupportedForTexturing(
viz::SharedImageFormat format) const override;
private:
std::unique_ptr<GLOzone> egl_implementation_;
std::unique_ptr<x11::Connection> connection_;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_X11_X11_SURFACE_FACTORY_H_
@@ -0,0 +1,521 @@
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_X11_X11_WINDOW_H_
#define UI_OZONE_PLATFORM_X11_X11_WINDOW_H_
#include <array>
#include <memory>
#include <string>
#include <vector>
#include "base/cancelable_callback.h"
#include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
#include "ui/base/x/x11_desktop_window_move_client.h"
#include "ui/base/x/x11_drag_drop_client.h"
#include "ui/base/x/x11_move_loop_delegate.h"
#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/event.h"
#include "ui/gfx/x/sync.h"
#include "ui/gfx/x/xfixes.h"
#include "ui/gfx/x/xproto.h"
#include "ui/platform_window/extensions/workspace_extension.h"
#include "ui/platform_window/extensions/x11_extension.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_init_properties.h"
#include "ui/platform_window/wm/wm_drag_handler.h"
#include "ui/platform_window/wm/wm_move_loop_handler.h"
#include "ui/platform_window/wm/wm_move_resize_handler.h"
class SkPath;
namespace x11 {
class GeometryCache;
class WmSync;
} // namespace x11
namespace ui {
class PlatformWindowDelegate;
class X11ExtensionDelegate;
class X11MoveLoop;
class WorkspaceExtensionDelegate;
// PlatformWindow implementation for X11.
class X11Window : public PlatformWindow,
public WmMoveResizeHandler,
public PlatformEventDispatcher,
public x11::EventObserver,
public WorkspaceExtension,
public X11Extension,
public WmDragHandler,
public XDragDropClient::Delegate,
public X11MoveLoopDelegate,
public WmMoveLoopHandler,
public X11DesktopWindowMoveClient::Delegate {
public:
explicit X11Window(PlatformWindowDelegate* platform_window_delegate);
X11Window(const X11Window&) = delete;
X11Window& operator=(const X11Window&) = delete;
~X11Window() override;
virtual void Initialize(PlatformWindowInitProperties properties);
// X11WindowManager calls this.
void OnXWindowLostCapture();
void OnCursorUpdate();
gfx::AcceleratedWidget GetWidget() const;
gfx::Rect GetOuterBounds() const;
void SetTransientWindow(x11::Window window);
bool has_pointer() const { return has_pointer_; }
// PlatformWindow:
void Show(bool inactive) override;
void Hide() override;
void Close() override;
bool IsVisible() const override;
void PrepareForShutdown() override;
void SetBoundsInPixels(const gfx::Rect& bounds) override;
gfx::Rect GetBoundsInPixels() const override;
void SetBoundsInDIP(const gfx::Rect& bounds) override;
gfx::Rect GetBoundsInDIP() const override;
void SetTitle(const std::u16string& title) override;
void SetCapture() override;
void ReleaseCapture() override;
bool HasCapture() const override;
void SetFullscreen(bool fullscreen, int64_t target_display_id) override;
void Maximize() override;
void Minimize() override;
void Restore() override;
void ShowWindowControlsMenu(const gfx::Point& point) override;
PlatformWindowState GetPlatformWindowState() const override;
void Activate() override;
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInDIP(const gfx::Rect& bounds) final;
gfx::Rect GetRestoredBoundsInDIP() const final;
bool ShouldWindowContentsBeTransparent() const override;
void SetZOrderLevel(ZOrderLevel order) override;
ZOrderLevel GetZOrderLevel() const override;
void StackAbove(gfx::AcceleratedWidget widget) override;
void StackAtTop() override;
void FlashFrame(bool flash_frame) override;
void SetShape(std::unique_ptr<ShapeRects> native_shape,
const gfx::Transform& transform) override;
void SetAspectRatio(const gfx::SizeF& aspect_ratio) override;
void SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) override;
void SizeConstraintsChanged() override;
void SetOpacity(float opacity) override;
bool CanSetDecorationInsets() const override;
void SetOpaqueRegion(
std::optional<std::vector<gfx::Rect>> region_px) override;
void SetInputRegion(std::optional<std::vector<gfx::Rect>> region_px) override;
void NotifyStartupComplete(const std::string& startup_id) override;
// WorkspaceExtension:
std::string GetWorkspace() const override;
void SetVisibleOnAllWorkspaces(bool always_visible) override;
bool IsVisibleOnAllWorkspaces() const override;
void SetWorkspaceExtensionDelegate(
WorkspaceExtensionDelegate* delegate) override;
// X11Extension:
bool IsSyncExtensionAvailable() const override;
bool IsWmTiling() const override;
void OnCompleteSwapAfterResize(const gfx::Size& new_size) override;
gfx::Rect GetXRootWindowOuterBounds() const override;
void LowerXWindow() override;
void SetOverrideRedirect(bool override_redirect) override;
bool CanResetOverrideRedirect() const override;
void SetX11ExtensionDelegate(X11ExtensionDelegate* delegate) override;
bool IsWmSyncActiveForTest() override;
// x11::EventObserver:
void OnEvent(const x11::Event& event) override;
protected:
PlatformWindowDelegate* platform_window_delegate() const {
return platform_window_delegate_;
}
void OnXWindowStateChanged();
void OnXWindowDamageEvent(const gfx::Rect& damage_rect);
void OnXWindowCloseRequested();
void OnXWindowIsActiveChanged(bool active);
void OnXWindowWorkspaceChanged();
void OnXWindowLostPointerGrab();
void OnXWindowSelectionEvent(const x11::SelectionNotifyEvent& xev);
void OnXWindowDragDropEvent(const x11::ClientMessageEvent& xev);
std::optional<gfx::Size> GetMinimumSizeForXWindow();
std::optional<gfx::Size> GetMaximumSizeForXWindow();
SkPath GetWindowMaskForXWindow();
private:
FRIEND_TEST_ALL_PREFIXES(X11WindowTest, Shape);
FRIEND_TEST_ALL_PREFIXES(X11WindowTest, WindowManagerTogglesFullscreen);
FRIEND_TEST_ALL_PREFIXES(X11WindowTest,
ToggleMinimizePropogateToPlatformWindowDelegate);
void UpdateDecorationInsets();
// PlatformEventDispatcher:
bool CanDispatchEvent(const PlatformEvent& event) override;
uint32_t DispatchEvent(const PlatformEvent& event) override;
void DispatchUiEvent(ui::Event* event, const x11::Event& xev);
// WmMoveResizeHandler
void DispatchHostWindowDragMovement(
int hittest,
const gfx::Point& pointer_location_in_px) override;
// WmMoveLoopHandler:
bool RunMoveLoop(const gfx::Vector2d& drag_offset) override;
void EndMoveLoop() override;
// WmDragHandler:
bool StartDrag(const OSExchangeData& data,
int operations,
mojom::DragEventSource source,
gfx::NativeCursor cursor,
bool can_grab_pointer,
base::OnceClosure drag_started_callback,
WmDragHandler::DragFinishedCallback drag_finished_callback,
WmDragHandler::LocationDelegate* delegate) override;
void CancelDrag() override;
void UpdateDragImage(const gfx::ImageSkia& image,
const gfx::Vector2d& offset) override;
// XDragDropClient::Delegate
std::optional<gfx::AcceleratedWidget> GetDragWidget() override;
int UpdateDrag(const gfx::Point& screen_point) override;
void UpdateCursor(mojom::DragOperation negotiated_operation) override;
void OnBeginForeignDrag(x11::Window window) override;
void OnEndForeignDrag() override;
void OnBeforeDragLeave() override;
mojom::DragOperation PerformDrop() override;
void EndDragLoop() override;
// X11MoveLoopDelegate
void OnMouseMovement(const gfx::Point& screen_point,
int flags,
base::TimeTicks event_time) override;
void OnMouseReleased() override;
void OnMoveLoopEnded() override;
// X11DesktopWindowMoveClient::Delegate:
void SetBoundsOnMove(const gfx::Rect& requested_bounds) override;
scoped_refptr<X11Cursor> GetLastCursor() override;
gfx::Size GetSize() override;
void QuitDragLoop();
// Handles `event` as an Atk Key Event
bool HandleAsAtkEvent(const x11::Event& event);
// Adjusts |requested_size_in_pixels| to avoid the WM "feature" where setting
// the window size to the monitor size causes the WM to set the EWMH for
// fullscreen.
gfx::Size AdjustSizeForDisplay(const gfx::Size& requested_size_in_pixels);
// Creates the X window with the given properties.
// Depending on presence of the compositing manager and window type, may
// change the opacity, in which case returns the final opacity type through
// |opacity|.
void CreateXWindow(const PlatformWindowInitProperties& properties);
void CloseXWindow();
void Map(bool inactive = false);
void SetWMStateFullscreen(bool fullscreen);
void SetWMStateMaximize(bool maximize);
bool IsActive() const;
bool IsTargetedBy(const x11::Event& xev) const;
void HandleEvent(const x11::Event& xev);
bool IsMinimized() const;
bool IsMaximized() const;
bool IsFullscreen() const;
void SetFlashFrameHint(bool flash_frame);
void UpdateMinAndMaxSize();
void DispatchResize(bool origin_changed);
void CancelResize();
// Resets the window region for the current window bounds if necessary.
void ResetWindowRegion();
x11::Window window() const { return xwindow_; }
x11::Window root_window() const { return x_root_window_; }
std::vector<x11::Rectangle>* shape() const { return window_shape_.get(); }
// Updates |xwindow_|'s _NET_WM_USER_TIME if |xwindow_| is active.
void UpdateWMUserTime(ui::Event* event);
// Called on an XFocusInEvent, XFocusOutEvent, XIFocusInEvent, or an
// XIFocusOutEvent.
void OnFocusEvent(bool focus_in,
x11::NotifyMode mode,
x11::NotifyDetail detail);
// Called on an XEnterWindowEvent, XLeaveWindowEvent, XIEnterEvent, or an
// XILeaveEvent.
void OnCrossingEvent(bool enter,
bool focus_in_window_or_ancestor,
x11::NotifyMode mode,
x11::NotifyDetail detail);
// Called when |xwindow_|'s _NET_WM_STATE property is updated.
void OnWMStateUpdated();
WindowTiledEdges GetTiledState() const;
// Called when |xwindow_|'s _NET_FRAME_EXTENTS property is updated.
void OnFrameExtentsUpdated();
void OnConfigureEvent(const x11::ConfigureNotifyEvent& event);
void OnWorkspaceUpdated();
void OnWindowMapped();
// Record the activation state.
void BeforeActivationStateChanged();
// Handle the state change since BeforeActivationStateChanged().
void AfterActivationStateChanged();
void MaybeUpdateOcclusionState();
void DelayedResize(bool origin_changed);
// If mapped, sends a message to the window manager to enable or disable the
// states |state1| and |state2|. Otherwise, the states will be enabled or
// disabled on the next map. It's the caller's responsibility to make sure
// atoms are set and unset in the appropriate pairs. For example, if a caller
// sets (_NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ), it would
// be invalid to unset the maximized state by making two calls like
// (_NET_WM_STATE_MAXIMIZED_VERT, x11::None), (_NET_WM_STATE_MAXIMIZED_HORZ,
// x11::None).
void SetWMSpecState(bool enabled, x11::Atom state1, x11::Atom state2);
// Updates |window_properties_| with |new_window_properties|.
void UpdateWindowProperties(
const base::flat_set<x11::Atom>& new_window_properties);
void UnconfineCursor();
void UpdateWindowRegion(std::unique_ptr<std::vector<x11::Rectangle>> region);
void NotifyBoundsChanged(bool origin_changed);
// Initializes as a status icon window.
bool InitializeAsStatusIcon();
void SetBoundsWithWmSync(const gfx::Rect& bounds_px);
void OnWmSynced();
void OnBoundsChanged(const std::optional<gfx::Rect>& old_bounds_px,
const gfx::Rect& new_bounds_px);
void MaybeUpdateSyncCounter();
// Stores current state of this window.
PlatformWindowState state_ = PlatformWindowState::kUnknown;
WindowTiledEdges tiled_state_;
const raw_ptr<PlatformWindowDelegate> platform_window_delegate_;
raw_ptr<WorkspaceExtensionDelegate, DanglingUntriaged>
workspace_extension_delegate_ = nullptr;
raw_ptr<X11ExtensionDelegate, DanglingUntriaged> x11_extension_delegate_ =
nullptr;
// Tells if the window got a ::Close call.
bool is_shutting_down_ = false;
// The z-order level of the window; the window exhibits "always on top"
// behavior if > 0.
ui::ZOrderLevel z_order_ = ui::ZOrderLevel::kNormal;
// The bounds of our window before the window was maximized.
gfx::Rect restored_bounds_in_pixels_;
std::unique_ptr<X11DesktopWindowMoveClient> x11_window_move_client_;
// Whether the drop handler has notified that the drag has entered.
bool notified_enter_ = false;
// Keeps the last negotiated operations returned by the drop handler.
int allowed_drag_operations_ = 0;
// Handles XDND events going through this window.
std::unique_ptr<XDragDropClient> drag_drop_client_;
WmDragHandler::DragFinishedCallback drag_finished_callback_;
raw_ptr<WmDragHandler::LocationDelegate, DanglingUntriaged>
drag_location_delegate_ = nullptr;
// Run loop used while dragging from this window.
std::unique_ptr<X11MoveLoop> drag_loop_;
// Events that we have selected on the source window of the incoming drag.
x11::ScopedEventSelector source_window_events_;
// The display and the native X window hosting the root window.
const raw_ref<x11::Connection> connection_;
x11::Window xwindow_ = x11::Window::None;
x11::Window x_root_window_ = x11::Window::None;
// Any native, modal dialog hanging from this window.
x11::Window transient_window_ = x11::Window::None;
// Events selected on |xwindow_|.
x11::ScopedEventSelector xwindow_events_;
// The window manager state bits.
base::flat_set<x11::Atom> window_properties_;
// Is this window able to receive focus?
bool activatable_ = true;
// Was this window initialized with the override_redirect window attribute?
bool override_redirect_ = false;
std::optional<std::u16string> window_title_;
// Whether the window is visible with respect to Aura.
bool window_mapped_in_client_ = false;
// Whether the window is mapped with respect to the X server.
bool window_mapped_in_server_ = false;
// The bounds of `xwindow_`. If `bounds_wm_sync_` is active, then
// `last_set_bounds_px_` should be treated as the current bounds. Otherwise,
// the bounds from `geometry_cache_` should be used.
gfx::Rect last_set_bounds_px_;
std::unique_ptr<x11::WmSync> bounds_wm_sync_;
std::unique_ptr<x11::GeometryCache> geometry_cache_;
x11::VisualId visual_id_{};
// Whether we used an ARGB visual for our window.
bool visual_has_alpha_ = false;
// The workspace containing |xwindow_|. This will be std::nullopt when
// _NET_WM_DESKTOP is unset.
std::optional<int> workspace_;
// True if the window should stay on top of most other windows.
bool is_always_on_top_ = false;
// True if the window is security-sensitive. Implies |is_always_on_top_|.
bool is_security_surface_ = false;
// True if the window is fully obscured by another window.
bool is_occluded_ = false;
PlatformWindowOcclusionState occlusion_state_ =
PlatformWindowOcclusionState::kUnknown;
// Does |xwindow_| have the pointer grab (XI2 or normal)?
bool has_pointer_grab_ = false;
// The focus-tracking state variables are as described in
// gtk/docs/focus_tracking.txt
//
// |xwindow_| is active iff:
// (|has_window_focus_| || |has_pointer_focus_|) &&
// !|ignore_keyboard_input_|
// Is the pointer in |xwindow_| or one of its children?
bool has_pointer_ = false;
// Is |xwindow_| or one of its children focused?
bool has_window_focus_ = false;
// (An ancestor window or the PointerRoot is focused) && |has_pointer_|.
// |has_pointer_focus_| == true is the odd case where we will receive keyboard
// input when |has_window_focus_| == false. |has_window_focus_| and
// |has_pointer_focus_| are mutually exclusive.
bool has_pointer_focus_ = false;
// X11 does not support defocusing windows; you can only focus a different
// window. If we would like to be defocused, we just ignore keyboard input we
// no longer care about.
bool ignore_keyboard_input_ = false;
// Used for tracking activation state in {Before|After}ActivationStateChanged.
bool was_active_ = false;
bool had_pointer_ = false;
bool had_pointer_grab_ = false;
bool had_window_focus_ = false;
// True if a Maximize() call should be done after mapping the window.
bool should_maximize_after_map_ = false;
// True if GrabPointer() should be called after mapping the window.
bool should_grab_pointer_after_map_ = false;
// Whether we currently are flashing our frame. This feature is implemented
// by setting the urgency hint with the window manager, which can draw
// attention to the window or completely ignore the hint. We stop flashing
// the frame when |xwindow_| gains focus or handles a mouse button event.
bool urgency_hint_set_ = false;
// |xwindow_|'s minimum size.
gfx::Size min_size_in_pixels_;
// |xwindow_|'s maximum size.
gfx::Size max_size_in_pixels_;
// The window shape if the window is non-rectangular.
std::unique_ptr<std::vector<x11::Rectangle>> window_shape_;
// Whether |window_shape_| was set via SetShape().
bool custom_window_shape_ = false;
// True if the window has title-bar / borders provided by the window manager.
bool use_native_frame_ = false;
// The size of the window manager provided borders (if any).
gfx::Insets native_window_frame_borders_in_pixels_;
// Used for synchronizing between `xwindow_` and the WM during resizing.
x11::Sync::Counter update_counter_{};
std::optional<x11::Sync::Int64> configure_counter_value_;
std::optional<gfx::Size> last_configure_size_;
std::optional<gfx::Size> last_swapped_size_;
base::CancelableOnceClosure delayed_resize_task_;
// Keep track of barriers to confine cursor.
bool has_pointer_barriers_ = false;
std::array<x11::XFixes::Barrier, 4> pointer_barriers_;
scoped_refptr<X11Cursor> last_cursor_;
base::CancelableOnceCallback<void(x11::Cursor)> on_cursor_loaded_;
base::WeakPtrFactory<X11Window> weak_ptr_factory_{this};
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_X11_X11_WINDOW_H_
@@ -0,0 +1,101 @@
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/x11/x11_window_manager.h"
#include "ui/ozone/platform/x11/x11_window.h"
namespace ui {
namespace {
X11WindowManager* g_instance = nullptr;
} // namespace
X11WindowManager::X11WindowManager() {
DCHECK(!g_instance) << "There should only be a single X11WindowManager";
g_instance = this;
}
X11WindowManager::~X11WindowManager() = default;
// static
X11WindowManager* X11WindowManager::GetInstance() {
if (!g_instance) {
auto manager = std::make_unique<X11WindowManager>();
X11WindowManager* manager_ptr = manager.release();
DCHECK_EQ(g_instance, manager_ptr);
}
return g_instance;
}
void X11WindowManager::GrabEvents(X11Window* window) {
DCHECK_NE(located_events_grabber_, window);
// Grabbing the mouse is asynchronous. However, we synchronously start
// forwarding all mouse events received by Chrome to the
// aura::WindowEventDispatcher which has capture. This makes capture
// synchronous for all intents and purposes if either:
// - |located_events_grabber_| is set to have capture.
// OR
// - The topmost window underneath the mouse is managed by Chrome.
auto* old_grabber = located_events_grabber_.get();
// Update |located_events_grabber_| prior to calling OnXWindowLostCapture() to
// avoid releasing pointer grab.
located_events_grabber_ = window;
if (old_grabber)
old_grabber->OnXWindowLostCapture();
// the X11Window calls GrabPointer by itself.
}
void X11WindowManager::UngrabEvents(X11Window* window) {
DCHECK_EQ(located_events_grabber_, window);
// Release mouse grab asynchronously. A window managed by Chrome is likely
// the topmost window underneath the mouse so the capture release being
// asynchronous is likely inconsequential.
auto* old_grabber = located_events_grabber_.get();
located_events_grabber_ = nullptr;
old_grabber->OnXWindowLostCapture();
}
void X11WindowManager::AddWindow(X11Window* window) {
DCHECK(window);
auto widget = window->GetWidget();
DCHECK_NE(gfx::kNullAcceleratedWidget, widget);
DCHECK(!windows_.contains(widget));
windows_.emplace(widget, window);
}
void X11WindowManager::RemoveWindow(X11Window* window) {
DCHECK(window);
auto widget = window->GetWidget();
auto it = windows_.find(widget);
// The XWindow might not have been initialized due to some errors.
if (widget == gfx::kNullAcceleratedWidget) {
DCHECK(it == windows_.end());
} else {
CHECK(it != windows_.end());
if (window_mouse_currently_on_ == it->second)
window_mouse_currently_on_ = nullptr;
windows_.erase(it);
}
}
X11Window* X11WindowManager::GetWindow(gfx::AcceleratedWidget widget) const {
auto it = windows_.find(widget);
return it != windows_.end() ? it->second : nullptr;
}
void X11WindowManager::MouseOnWindow(X11Window* window) {
if (window_mouse_currently_on_ == window)
return;
window_mouse_currently_on_ = window;
window->OnCursorUpdate();
}
} // namespace ui
@@ -0,0 +1,61 @@
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_X11_X11_WINDOW_MANAGER_H_
#define UI_OZONE_PLATFORM_X11_X11_WINDOW_MANAGER_H_
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "ui/gfx/native_ui_types.h"
namespace ui {
class X11Window;
class X11WindowManager {
public:
X11WindowManager();
X11WindowManager(const X11WindowManager&) = delete;
X11WindowManager& operator=(const X11WindowManager&) = delete;
~X11WindowManager();
// Returns instance of X11WindowManager.
static X11WindowManager* GetInstance();
// Sets a given X11Window as the recipient for events and calls
// OnLostCapture for another |located_events_grabber_| if it has been set
// previously.
void GrabEvents(X11Window* window);
// Unsets a given X11Window as the recipient for events and calls
// OnLostCapture.
void UngrabEvents(X11Window* window);
// Gets the current X11PlatformWindow recipient of mouse events.
X11Window* located_events_grabber() const { return located_events_grabber_; }
// Gets the window corresponding to the AcceleratedWidget |widget|.
void AddWindow(X11Window* window);
void RemoveWindow(X11Window* window);
X11Window* GetWindow(gfx::AcceleratedWidget widget) const;
void MouseOnWindow(X11Window* delegate);
const X11Window* window_mouse_currently_on_for_test() const {
return window_mouse_currently_on_;
}
private:
raw_ptr<X11Window> located_events_grabber_ = nullptr;
raw_ptr<X11Window> window_mouse_currently_on_ = nullptr;
base::flat_map<gfx::AcceleratedWidget, raw_ptr<X11Window, CtnExperimental>>
windows_;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_X11_X11_WINDOW_MANAGER_H_
@@ -0,0 +1,46 @@
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PUBLIC_OVERLAY_MANAGER_OZONE_H_
#define UI_OZONE_PUBLIC_OVERLAY_MANAGER_OZONE_H_
#include <memory>
#include "ui/gfx/native_ui_types.h"
namespace ui {
class OverlayCandidatesOzone;
// Responsible for providing the oracles used to decide when overlays can be
// used.
class OverlayManagerOzone {
public:
virtual ~OverlayManagerOzone() {}
// Get the hal struct to check for overlay support.
virtual std::unique_ptr<OverlayCandidatesOzone> CreateOverlayCandidates(
gfx::AcceleratedWidget w) = 0;
bool allow_sync_and_real_buffer_page_flip_testing() const {
return allow_sync_and_real_buffer_page_flip_testing_;
}
// Tell the manager that the overlay delegation is enabled. This is only
// useful for Wayland as checking for overlay support depends on
// features::IsDelegatedCompositingEnabled, which cannot be accessed from
// //ui/ozone.
// TODO(msisov, petermcneeley): remove this once Wayland uses only delegated
// context.
virtual void SetContextDelegated() {}
protected:
// TODO(fangzhoug): Some Chrome OS boards still use the legacy video decoder.
// Remove this once ChromeOSVideoDecoder is on everywhere.
bool allow_sync_and_real_buffer_page_flip_testing_ = false;
};
} // namespace ui
#endif // UI_OZONE_PUBLIC_OVERLAY_MANAGER_OZONE_H_
@@ -0,0 +1,70 @@
dbus-glib
elementary-icon-theme
exo
garcon
gnome-themes-extra
gtk-layer-shell
gtksourceview4
libburn
libgtop
libisofs
libkeybinder3
libmpd
libwnck3
libxfce4ui
libxfce4util
libxfce4windowing
libxklavier
libxres
mousepad
parole
polkit-gnome
ristretto
thunar
thunar-archive-plugin
thunar-media-tags-plugin
thunar-volman
tumbler
xfburn
xfce4-appfinder
xfce4-battery-plugin
xfce4-clipman-plugin
xfce4-cpufreq-plugin
xfce4-cpugraph-plugin
xfce4-dict
xfce4-diskperf-plugin
xfce4-eyes-plugin
xfce4-fsguard-plugin
xfce4-genmon-plugin
xfce4-mailwatch-plugin
xfce4-mount-plugin
xfce4-mpc-plugin
xfce4-netload-plugin
xfce4-notes-plugin
xfce4-notifyd
xfce4-panel
xfce4-places-plugin
xfce4-power-manager
xfce4-pulseaudio-plugin
xfce4-screensaver
xfce4-screenshooter
xfce4-sensors-plugin
xfce4-session
xfce4-settings
xfce4-smartbookmark-plugin
xfce4-systemload-plugin
xfce4-taskmanager
xfce4-terminal
xfce4-time-out-plugin
xfce4-timer-plugin
xfce4-verve-plugin
xfce4-wavelan-plugin
xfce4-weather-plugin
xfce4-whiskermenu-plugin
xfce4-xkb-plugin
xfconf
xfdesktop
xfwm4
xorg-iceauth
xorg-xinit
xorg-xmodmap
@@ -0,0 +1,227 @@
:: There are 14 members in group xfce4:
:: Repository extra
1) exo 2) garcon 3) thunar 4) thunar-volman 5) tumbler 6) xfce4-appfinder 7) xfce4-panel 8) xfce4-power-manager 9) xfce4-session 10) xfce4-settings 11) xfce4-terminal 12) xfconf 13) xfdesktop 14) xfwm4
Enter a selection (default=all):
:: There are 36 members in group xfce4-goodies:
:: Repository extra
1) mousepad 2) parole 3) ristretto 4) thunar-archive-plugin 5) thunar-media-tags-plugin 6) xfburn 7) xfce4-battery-plugin 8) xfce4-clipman-plugin 9) xfce4-cpufreq-plugin 10) xfce4-cpugraph-plugin 11) xfce4-dict 12) xfce4-diskperf-plugin 13) xfce4-eyes-plugin 14) xfce4-fsguard-plugin 15) xfce4-genmon-plugin 16) xfce4-mailwatch-plugin 17) xfce4-mount-plugin 18) xfce4-mpc-plugin 19) xfce4-netload-plugin 20) xfce4-notes-plugin 21) xfce4-notifyd 22) xfce4-places-plugin 23) xfce4-pulseaudio-plugin 24) xfce4-screensaver 25) xfce4-screenshooter 26) xfce4-sensors-plugin 27) xfce4-smartbookmark-plugin 28) xfce4-systemload-plugin 29) xfce4-taskmanager 30) xfce4-time-out-plugin 31) xfce4-timer-plugin 32) xfce4-verve-plugin 33) xfce4-wavelan-plugin 34) xfce4-weather-plugin 35) xfce4-whiskermenu-plugin 36) xfce4-xkb-plugin
Enter a selection (default=all):
resolving dependencies...
looking for conflicting packages...
Packages (70) dbus-glib-0.114-1 elementary-icon-theme-8.2.0-1 gnome-themes-extra-1:3.28-1 gtk-layer-shell-0.10.1-1 gtksourceview4-4.8.4-2 libburn-1.5.8-1 libgtop-2.41.3-2 libisofs-1.5.8.1-1 libkeybinder3-0.3.2-5 libmpd-11.8.17-7 libwnck3-43.3-1 libxfce4ui-4.20.2-1 libxfce4util-4.20.1-1 libxfce4windowing-4.20.5-3 libxklavier-5.4-7 libxres-1.2.3-1 polkit-gnome-0.105-12 xorg-iceauth-1.0.11-1 xorg-xinit-1.4.4-1 xorg-xmodmap-1.0.11-2 exo-4.20.0-2 garcon-4.20.0-2 mousepad-0.7.0-1 parole-4.20.0-1 ristretto-0.14.0-1 thunar-4.20.8-3 thunar-archive-plugin-0.6.0-1 thunar-media-tags-plugin-0.6.0-1 thunar-volman-4.20.0-2 tumbler-4.20.1-1 xfburn-0.8.0-1 xfce4-appfinder-4.20.0-2 xfce4-battery-plugin-1.2.0-1 xfce4-clipman-plugin-1.7.0-1 xfce4-cpufreq-plugin-1.3.0-1 xfce4-cpugraph-plugin-1.3.0-1 xfce4-dict-0.8.9-1 xfce4-diskperf-plugin-2.8.0-2 xfce4-eyes-plugin-4.7.0-1 xfce4-fsguard-plugin-1.2.0-1 xfce4-genmon-plugin-4.3.0-1 xfce4-mailwatch-plugin-1.4.0-1 xfce4-mount-plugin-1.2.0-1 xfce4-mpc-plugin-0.6.0-1 xfce4-netload-plugin-1.5.0-1 xfce4-notes-plugin-1.12.0-1 xfce4-notifyd-0.9.7-2 xfce4-panel-4.20.7-1 xfce4-places-plugin-1.9.0-1 xfce4-power-manager-4.20.0-3 xfce4-pulseaudio-plugin-0.5.1-1 xfce4-screensaver-4.20.2-1 xfce4-screenshooter-1.11.3-3 xfce4-sensors-plugin-1.4.5-1 xfce4-session-4.20.4-1 xfce4-settings-4.20.4-1 xfce4-smartbookmark-plugin-0.6.0-2 xfce4-systemload-plugin-1.4.0-1 xfce4-taskmanager-1.6.0-1 xfce4-terminal-1.2.0-1 xfce4-time-out-plugin-1.2.0-1 xfce4-timer-plugin-1.8.0-1 xfce4-verve-plugin-2.1.0-1 xfce4-wavelan-plugin-0.7.0-2 xfce4-weather-plugin-0.12.0-2 xfce4-whiskermenu-plugin-2.10.1-2 xfce4-xkb-plugin-0.9.0-1 xfconf-4.20.0-2 xfdesktop-4.20.2-1 xfwm4-4.20.0-2
Total Download Size: 22.20 MiB
Total Installed Size: 136.65 MiB
:: Proceed with installation? [Y/n]
:: Retrieving packages...
elementary-icon-theme-8.2.0-1-any downloading...
gnome-themes-extra-1:3.28-1-any downloading...
xfce4-weather-plugin-0.12.0-2-aarch64 downloading...
thunar-4.20.8-3-aarch64 downloading...
xfdesktop-4.20.2-1-aarch64 downloading...
gtksourceview4-4.8.4-2-aarch64 downloading...
xfce4-settings-4.20.4-1-aarch64 downloading...
xfce4-panel-4.20.7-1-aarch64 downloading...
xfce4-power-manager-4.20.0-3-aarch64 downloading...
xfwm4-4.20.0-2-aarch64 downloading...
mousepad-0.7.0-1-aarch64 downloading...
xfburn-0.8.0-1-aarch64 downloading...
xfce4-terminal-1.2.0-1-aarch64 downloading...
libwnck3-43.3-1-aarch64 downloading...
libxfce4ui-4.20.2-1-aarch64 downloading...
xfce4-session-4.20.4-1-aarch64 downloading...
parole-4.20.0-1-aarch64 downloading...
exo-4.20.0-2-aarch64 downloading...
xfce4-xkb-plugin-0.9.0-1-aarch64 downloading...
libburn-1.5.8-1-aarch64 downloading...
libisofs-1.5.8.1-1-aarch64 downloading...
ristretto-0.14.0-1-aarch64 downloading...
xfce4-screensaver-4.20.2-1-aarch64 downloading...
xfce4-whiskermenu-plugin-2.10.1-2-aarch64 downloading...
xfce4-notifyd-0.9.7-2-aarch64 downloading...
libgtop-2.41.3-2-aarch64 downloading...
xfce4-sensors-plugin-1.4.5-1-aarch64 downloading...
xfconf-4.20.0-2-aarch64 downloading...
xfce4-clipman-plugin-1.7.0-1-aarch64 downloading...
xfce4-dict-0.8.9-1-aarch64 downloading...
tumbler-4.20.1-1-aarch64 downloading...
xfce4-appfinder-4.20.0-2-aarch64 downloading...
libxfce4windowing-4.20.5-3-aarch64 downloading...
garcon-4.20.0-2-aarch64 downloading...
xfce4-mailwatch-plugin-1.4.0-1-aarch64 downloading...
xfce4-screenshooter-1.11.3-3-aarch64 downloading...
xfce4-notes-plugin-1.12.0-1-aarch64 downloading...
libxfce4util-4.20.1-1-aarch64 downloading...
dbus-glib-0.114-1-aarch64 downloading...
thunar-volman-4.20.0-2-aarch64 downloading...
xfce4-taskmanager-1.6.0-1-aarch64 downloading...
xfce4-cpugraph-plugin-1.3.0-1-aarch64 downloading...
xfce4-pulseaudio-plugin-0.5.1-1-aarch64 downloading...
xfce4-cpufreq-plugin-1.3.0-1-aarch64 downloading...
xfce4-battery-plugin-1.2.0-1-aarch64 downloading...
xfce4-mount-plugin-1.2.0-1-aarch64 downloading...
libxklavier-5.4-7-aarch64 downloading...
xfce4-fsguard-plugin-1.2.0-1-aarch64 downloading...
xfce4-places-plugin-1.9.0-1-aarch64 downloading...
gtk-layer-shell-0.10.1-1-aarch64 downloading...
xfce4-genmon-plugin-4.3.0-1-aarch64 downloading...
thunar-media-tags-plugin-0.6.0-1-aarch64 downloading...
polkit-gnome-0.105-12-aarch64 downloading...
xfce4-timer-plugin-1.8.0-1-aarch64 downloading...
xfce4-time-out-plugin-1.2.0-1-aarch64 downloading...
xfce4-diskperf-plugin-2.8.0-2-aarch64 downloading...
xfce4-systemload-plugin-1.4.0-1-aarch64 downloading...
xfce4-netload-plugin-1.5.0-1-aarch64 downloading...
libmpd-11.8.17-7-aarch64 downloading...
xfce4-eyes-plugin-4.7.0-1-aarch64 downloading...
xfce4-verve-plugin-2.1.0-1-aarch64 downloading...
xfce4-mpc-plugin-0.6.0-1-aarch64 downloading...
thunar-archive-plugin-0.6.0-1-aarch64 downloading...
xfce4-wavelan-plugin-0.7.0-2-aarch64 downloading...
xfce4-smartbookmark-plugin-0.6.0-2-aarch64 downloading...
xorg-xmodmap-1.0.11-2-aarch64 downloading...
libkeybinder3-0.3.2-5-aarch64 downloading...
xorg-xinit-1.4.4-1-aarch64 downloading...
xorg-iceauth-1.0.11-1-aarch64 downloading...
libxres-1.2.3-1-aarch64 downloading...
checking keyring...
checking package integrity...
loading package files...
checking for file conflicts...
:: Processing package changes...
installing libxfce4util...
installing xfconf...
installing libgtop...
installing libxfce4ui...
installing exo...
installing garcon...
installing thunar...
Optional dependencies for thunar
catfish: file searching
gvfs: trash support, mounting with udisk and remote filesystems
tumbler: thumbnail previews [pending]
thunar-volman: removable device management [pending]
thunar-archive-plugin: archive creation and extraction [pending]
thunar-media-tags-plugin: view/edit ID3/OGG tags [pending]
installing thunar-volman...
installing tumbler...
Optional dependencies for tumbler
ffmpegthumbnailer: video thumbnails
poppler-glib: PDF thumbnails
libgsf: ODF thumbnails
libgepub: EPUB thumbnails
libopenraw: RAW thumbnails
freetype2: font thumbnails [installed]
installing xfce4-appfinder...
installing gtk-layer-shell...
installing libxres...
installing libwnck3...
installing libxfce4windowing...
installing xfce4-panel...
installing xfce4-notifyd...
installing xfce4-power-manager...
installing xorg-iceauth...
installing xorg-xmodmap...
installing xorg-xinit...
Optional dependencies for xorg-xinit
xorg-twm
xterm
installing polkit-gnome...
installing xfce4-session...
Optional dependencies for xfce4-session
gnome-keyring: for keyring support when GNOME compatibility is enabled
xfce4-screensaver: for locking screen with xflock4 [pending]
xscreensaver: for locking screen with xflock4
light-locker: for locking screen with xflock4
labwc: recommended compositor for the experimental Wayland session
installing libxklavier...
installing elementary-icon-theme...
installing gnome-themes-extra...
installing xfce4-settings...
Optional dependencies for xfce4-settings
python: xfce4-compose-mail -- "mailto:" URI handling [installed]
xiccd: for displays support in xfce4-color-settings
cups: for printers support in xfce4-color-settings [installed]
sane: for scanners support in xfce4-color-settings
installing xfce4-terminal...
installing xfdesktop...
installing xfwm4...
installing gtksourceview4...
installing mousepad...
Optional dependencies for mousepad
gspell: spell checking plugin
libxfce4ui: shortcuts editor plugin [installed]
installing dbus-glib...
installing parole...
Optional dependencies for parole
gst-libav: Extra media codecs
gst-plugins-bad: Extra media codecs [installed]
gst-plugins-ugly: Extra media codecs
installing ristretto...
installing thunar-archive-plugin...
Optional dependencies for thunar-archive-plugin
file-roller
engrampa
ark [installed]
xarchiver
installing thunar-media-tags-plugin...
installing libburn...
installing libisofs...
installing xfburn...
installing xfce4-battery-plugin...
installing xfce4-clipman-plugin...
installing xfce4-cpufreq-plugin...
installing xfce4-cpugraph-plugin...
installing xfce4-dict...
installing xfce4-diskperf-plugin...
installing xfce4-eyes-plugin...
installing xfce4-fsguard-plugin...
installing xfce4-genmon-plugin...
installing xfce4-mailwatch-plugin...
installing xfce4-mount-plugin...
installing libmpd...
installing xfce4-mpc-plugin...
installing xfce4-netload-plugin...
installing xfce4-notes-plugin...
installing xfce4-places-plugin...
installing libkeybinder3...
Optional dependencies for libkeybinder3
lua-lgi: lua bindings
installing xfce4-pulseaudio-plugin...
Optional dependencies for xfce4-pulseaudio-plugin
pavucontrol: default pulseaudio mixer
installing xfce4-screensaver...
Optional dependencies for xfce4-screensaver
onboard: on screen keyboard for unlocking
xscreensaver: additional themes
installing xfce4-screenshooter...
installing xfce4-sensors-plugin...
Optional dependencies for xfce4-sensors-plugin
hddtemp: for monitoring the temperature of hard drives
installing xfce4-smartbookmark-plugin...
installing xfce4-systemload-plugin...
installing xfce4-taskmanager...
installing xfce4-time-out-plugin...
installing xfce4-timer-plugin...
installing xfce4-verve-plugin...
installing xfce4-wavelan-plugin...
installing xfce4-weather-plugin...
installing xfce4-whiskermenu-plugin...
Optional dependencies for xfce4-whiskermenu-plugin
mugshot: Update user details
installing xfce4-xkb-plugin...
Optional dependencies for xfce4-xkb-plugin
xfce4-notifyd: show notifications on layout change [installed]
:: Running post-transaction hooks...
(1/8) Reloading user manager configuration...
(2/8) Arming ConditionNeedsUpdate...
(3/8) Refreshing PackageKit...
(4/8) Updating GIO module cache...
(5/8) Compiling GSettings XML schema files...
(6/8) Updating icon theme caches...
(7/8) Updating the info directory file...
(8/8) Updating the desktop file MIME type cache...
@@ -0,0 +1,30 @@
resolving dependencies...
looking for conflicting packages...
Packages (2) mailcap-2.1.54-2 firefox-150.0.1-1
Total Download Size: 63.40 MiB
Total Installed Size: 256.95 MiB
:: Proceed with installation? [Y/n]
:: Retrieving packages...
firefox-150.0.1-1-aarch64 downloading...
mailcap-2.1.54-2-any downloading...
checking keyring...
checking package integrity...
loading package files...
checking for file conflicts...
:: Processing package changes...
installing mailcap...
installing firefox...
Optional dependencies for firefox
hunspell-en_US: Spell checking, American English
libnotify: Notification integration [installed]
networkmanager: Location detection via available WiFi networks [installed]
speech-dispatcher: Text-to-Speech
xdg-desktop-portal: Screensharing with Wayland [installed]
:: Running post-transaction hooks...
(1/4) Arming ConditionNeedsUpdate...
(2/4) Refreshing PackageKit...
(3/4) Updating icon theme caches...
(4/4) Updating the desktop file MIME type cache...
@@ -0,0 +1,20 @@
loading packages...
resolving dependencies...
looking for conflicting packages...
Packages (1) xtrace-1.4.0-2
Total Installed Size: 0.31 MiB
:: Proceed with installation? [Y/n]
checking keyring...
checking package integrity...
loading package files...
checking for file conflicts...
:: Processing package changes...
installing xtrace...
Optional dependencies for xtrace
xorg-xauth [installed]
:: Running post-transaction hooks...
(1/2) Arming ConditionNeedsUpdate...
(2/2) Refreshing PackageKit...
@@ -0,0 +1,47 @@
resolving dependencies...
looking for conflicting packages...
Packages (11) libadwaita-1:1.9.0-1 libdex-1.1.0-1 libpanel-1.10.4-1 startup-notification-0.12-9 openbox-3.6.1-14 sysprof-50.0-2 xorg-xev-1.2.6-2 xorg-xinput-1.6.4-2 xorg-xkill-1.0.7-1 xorg-xrandr-1.5.4-1 xorg-xwininfo-1.1.6-2
Total Download Size: 2.31 MiB
Total Installed Size: 16.01 MiB
:: Proceed with installation? [Y/n]
:: Retrieving packages...
sysprof-50.0-2-aarch64 downloading...
libadwaita-1:1.9.0-1-aarch64 downloading...
openbox-3.6.1-14-aarch64 downloading...
libpanel-1.10.4-1-aarch64 downloading...
libdex-1.1.0-1-aarch64 downloading...
xorg-xrandr-1.5.4-1-aarch64 downloading...
xorg-xinput-1.6.4-2-aarch64 downloading...
xorg-xwininfo-1.1.6-2-aarch64 downloading...
startup-notification-0.12-9-aarch64 downloading...
xorg-xev-1.2.6-2-aarch64 downloading...
xorg-xkill-1.0.7-1-aarch64 downloading...
checking keyring...
checking package integrity...
loading package files...
checking for file conflicts...
:: Processing package changes...
installing xorg-xrandr...
installing xorg-xev...
installing xorg-xinput...
installing xorg-xwininfo...
installing xorg-xkill...
installing libadwaita...
installing libdex...
installing libpanel...
installing sysprof...
installing startup-notification...
installing openbox...
Optional dependencies for openbox
python-pyxdg: for the openbox-xdg-autostart script
:: Running post-transaction hooks...
(1/7) Reloading system manager configuration...
(2/7) Updating the MIME type database...
(3/7) Arming ConditionNeedsUpdate...
(4/7) Refreshing PackageKit...
(5/7) Reloading system bus configuration...
(6/7) Updating icon theme caches...
(7/7) Updating the desktop file MIME type cache...
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,483 @@
# revert.log — campaign-installed state on ohm
This file lists every change this campaign made to ohm's *system
state* during Phase 0 inventory work that was done **purely for
testing and analysis**. To return ohm to the state it was in
before this campaign opened, run the "Revert" commands at the
bottom of this file in order.
This file is updated whenever the campaign installs a package or
mutates a sysctl/service/config. Closing the campaign without
reverting is a deliberate operator decision; if reverted, this
file is the authoritative record of what to undo.
Inherited state from the predecessor (`kwin_overlay_subsurface`)
is **not** in scope here — those carry-overs are documented in
`README.md` § "Carry-overs from predecessor (system state, not
data)" and would be reverted via that campaign's
`phase1_evidence/ohm_tooling_revert_log.md` instead.
---
## Entry 1 — 2026-05-03 ~09:20 CEST
**Trigger:** Phase 0 deliverables 2 + 4 (`x11_inventory_2026-05-03/inventory.md`)
identified missing measurement tools and the absence of a
non-compositing WM. Operator instructed: "fire the installs."
**Driven from:** `mfritsche@noether` over SSH to `ohm.fritz.box`,
passwordless `sudo` (verified before firing).
**Pre-install snapshot:** `pkglist.pre.txt` (1169 packages,
sha256 `fd72bcf6a7289d2f2dd6ce02706240006b534731540bf63f56ee9b666e7be68f`).
**Post-install snapshot:** `pkglist.post.txt` (1180 packages).
**Full pacman transaction log:** `pacman.install.log`.
### What was installed
Single transaction: `sudo pacman -Sy && sudo pacman -S --needed
xorg-xrandr xorg-xev xorg-xinput xorg-xwininfo xorg-xkill sysprof openbox`
| Package | Version | Reason |
|---|---|---|
| xorg-xrandr | 1.5.4-1 | explicit — RandR CLI for output/vblank probing |
| xorg-xev | 1.2.6-2 | explicit — per-window event capture |
| xorg-xinput | 1.6.4-2 | explicit — input-device probe (touchscreen confound) |
| xorg-xwininfo | 1.1.6-2 | explicit — get browser window geometry/wid |
| xorg-xkill | 1.0.7-1 | explicit — clean kill of stuck X clients between reps |
| sysprof | 50.0-2 | explicit — kernel perf alternative w/ flamegraph default |
| openbox | 3.6.1-14 | explicit — non-compositing WM for the without-KWin matrix cell |
| libadwaita | 1:1.9.0-1 | dep of sysprof |
| libdex | 1.1.0-1 | dep of sysprof |
| libpanel | 1.10.4-1 | dep of sysprof |
| startup-notification | 0.12-9 | dep of openbox |
11 added, 0 removed. Cross-checked via `comm -13
pkglist.pre.txt pkglist.post.txt` — exact same 11.
### What was changed (config, not packages)
- **`/etc/sysctl.d/90-x11-research-perf.conf` was created with
`kernel.perf_event_paranoid = 1`, then reverted same session.**
- Created: applied via `sudo sysctl --system`; effective
value went 2 → 1.
- Verification probe revealed the tweak was **not delivering
the promised behavior**: even with `task-clock` (a software
event that should be allowed at paranoid=1), `perf record
-p <Xorg_pid>` on this aarch64 kernel still failed with
"Failure to open any events for recording". Predecessor
pattern confirmed in
`kwin_overlay_subsurface/phase3_protocol.md:121,158,216`:
they used **`sudo perf record`** per-rep, not a sysctl
tweak. Passwordless sudo over SSH already works on ohm so
this is unattended-friendly.
- Reverted: `sudo rm /etc/sysctl.d/90-x11-research-perf.conf`
and `sudo sysctl kernel.perf_event_paranoid=2` (the
`--system` reapply does not reset removed-file values; an
explicit set was required).
- Net state change: **none** (paranoid back at kernel
default 2; `/etc/sysctl.d/` empty again).
- Lesson: the inventory's "set paranoid=1" recommendation
was wrong. Updated `inventory.md` will reflect that the
actual pattern is `sudo perf record -p <pid>` per-rep.
### What was created as a side effect (no operator action)
- `/usr/share/xsessions/openbox.desktop` (shipped by the
`openbox` package). SDDM will list "Openbox" as a session
choice on next greet. Removing the openbox package removes
the .desktop file.
### What was *not* installed (deliberate, operator-decision-pending)
- **firefox** — 2 of the 6 matrix cells reference Firefox
(`C-W-ff-*`, `C-X-ff-*`). Operator decides whether to install
or to mark those cells N/A. If installed later, append a new
entry below.
- **xtrace (X protocol tracer, AUR)** — explicitly marked
optional in `inventory.md`. The matrix's primary metrics
(effective_fps / drops / latency / CPU%) don't require it.
If installed later, append a new entry below.
---
## Entry 2 — 2026-05-03 ~09:30 CEST
**Trigger:** Operator preference for a desktop-environment-flavored
without-KWin testbed alongside the bare openbox cell ("I like
desktop environments. With respect to the test - should xfce or
cinnamon be our test bed?" → "yes add xfce with goodies").
Cinnamon was excluded because Muffin is a mandatory compositor;
XFCE qualifies if `xfwm4`'s built-in compositor is left disabled.
**Driven from:** `mfritsche@noether` over SSH to `ohm.fritz.box`,
passwordless `sudo`.
**Pre-install snapshot:** `pkglist.entry2.pre.txt` (1180 packages,
sha256 `1f72c7ed2f9d476d24d0dfb53fcb387ea39f882c89375d68fc21298313252d78`).
**Post-install snapshot:** `pkglist.entry2.post.txt` (1250 packages).
**Full pacman transaction log:** `pacman.entry2.log`.
### What was installed
Single transaction: `sudo pacman -S --needed xfce4 xfce4-goodies`
(both are package groups; pacman expanded them).
- **50 explicit packages** (the union of the `xfce4` group's 14
members and the `xfce4-goodies` group's 36 members):
exo, garcon, mousepad, parole, ristretto, thunar, thunar-archive-plugin,
thunar-media-tags-plugin, thunar-volman, tumbler, xfburn,
xfce4-appfinder, xfce4-battery-plugin, xfce4-clipman-plugin,
xfce4-cpufreq-plugin, xfce4-cpugraph-plugin, xfce4-dict,
xfce4-diskperf-plugin, xfce4-eyes-plugin, xfce4-fsguard-plugin,
xfce4-genmon-plugin, xfce4-mailwatch-plugin, xfce4-mount-plugin,
xfce4-mpc-plugin, xfce4-netload-plugin, xfce4-notes-plugin,
xfce4-notifyd, xfce4-panel, xfce4-places-plugin,
xfce4-power-manager, xfce4-pulseaudio-plugin, xfce4-screensaver,
xfce4-screenshooter, xfce4-sensors-plugin, xfce4-session,
xfce4-settings, xfce4-smartbookmark-plugin, xfce4-systemload-plugin,
xfce4-taskmanager, xfce4-terminal, xfce4-time-out-plugin,
xfce4-timer-plugin, xfce4-verve-plugin, xfce4-wavelan-plugin,
xfce4-weather-plugin, xfce4-whiskermenu-plugin, xfce4-xkb-plugin,
xfconf, xfdesktop, xfwm4
- **20 transitive deps**:
dbus-glib, elementary-icon-theme, gnome-themes-extra,
gtk-layer-shell, gtksourceview4, libburn, libgtop, libisofs,
libkeybinder3, libmpd, libwnck3, libxfce4ui, libxfce4util,
libxfce4windowing, libxklavier, libxres, polkit-gnome,
xorg-iceauth, xorg-xinit, xorg-xmodmap
70 added, 0 removed. Cross-checked via
`comm -13 pkglist.entry2.pre.txt pkglist.entry2.post.txt` — full
list in `entry2.added.list` (sourced from same diff).
### What was changed (config)
- **`~/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml` created**
(208 bytes), pre-seeding `general/use_compositing = false`. This
ensures the **first XFCE login lands with xfwm4's built-in GL
compositor disabled**, matching the matrix's "without-KWin =
no compositor in the display path" definition. Without this
pre-seed, `xfwm4` would default to `use_compositing=true` and
the operator would have to remember to toggle it via *Settings
→ Window Manager Tweaks → Compositor* before every measurement
rep — a confound waiting to happen.
The directory tree `~/.config/xfce4/` did not exist before this
write; the entire tree is removable.
### What was created as a side effect (no operator action)
- `/usr/share/xsessions/xfce.desktop` (shipped by `xfce4-session`).
SDDM now lists three X11 sessions: openbox.desktop (entry 1),
plasmax11.desktop (pre-existing), xfce.desktop (this entry).
### After-revert verification
The first-login compositor pre-seed is per-user state in
`~/.config/xfce4/`. The revert procedure deletes the entire
xfce4 user-config tree if (and only if) it contains nothing but
the pre-seeded xfwm4.xml. If the operator logs into XFCE before
revert, xfconfd will populate that tree with other settings
files; the revert then becomes a manual decision.
---
## Entry 3 — 2026-05-03 ~09:45 CEST
**Trigger:** Operator instructed "install both" — closing the two
operator-decision items left open in entry 1's "What was *not*
installed" section: firefox (matrix completeness — 2 of 6 cells
need it) and the X-protocol tracer xtrace.
**Driven from:** `mfritsche@noether` over SSH to `ohm.fritz.box`,
passwordless `sudo` for pacman, regular user for `yay` /
`makepkg`.
**Pre-install snapshot:** `pkglist.entry3.pre.txt` (1250 packages,
sha256 `e73ffdd41b683aaba2ad18efa5ce3e7252577c13b4f0bb14e9de7bdfbfd5e26e`).
**Post-install snapshot:** `pkglist.entry3.post.txt` (1253 packages).
**Transaction logs:** `pacman.entry3a.firefox.log`,
`pacman.entry3b.xtrace.log`.
### What was installed
Two transactions in one entry:
| Package | Version | Source | Reason |
|---|---|---|---|
| firefox | 150.0.1-1 | extra | explicit — matrix's `C-W-ff-*` and `C-X-ff-*` cells |
| mailcap | 2.1.54-2 | extra | dep of firefox |
| xtrace | 1.4.0-2 | AUR | explicit — X protocol tracer (parallel to `WAYLAND_DEBUG=1`) |
3 added, 0 removed.
Firefox was a clean `pacman -S firefox`. xtrace went via
`yay -G xtrace; cd ~/.cache/yay/xtrace; makepkg -s --noconfirm
--ignorearch; sudo pacman -U --noconfirm xtrace-1.4.0-2-aarch64.pkg.tar.zst`.
The `--ignorearch` was needed because the AUR PKGBUILD declares
`arch=('i686' 'x86_64')` only — the package builds cleanly on
aarch64, the maintainer just hasn't updated the array.
### File-conflict probe (no actual conflict)
A pre-install probe suggested AUR `xtrace` would conflict with
glibc's `/usr/bin/xtrace` (glibc ships a syscall-tracer shell
script under that path). Investigation showed the **Arch AUR
PKGBUILD renames the binary to `/usr/bin/x11trace`** specifically
to avoid this collision. Both binaries now coexist:
- `/usr/bin/xtrace` — glibc's syscall/function tracer (5 KB
bash script). Unchanged.
- `/usr/bin/x11trace` — the X protocol tracer (133 KB aarch64
ELF, AUR `xtrace` 1.4.0). New.
The early `pacman -U --overwrite '/usr/bin/xtrace'` flag turned
out to be unnecessary; pacman would have allowed the install
without it because nothing actually overlapped on disk. No
state was overwritten.
### Verification
- `firefox --version` → `Mozilla Firefox 150.0.1`
- `x11trace --version` → `xtrace version 1.4.0`
- `x11trace --help` confirms X-protocol semantics
("Dump all X protocol data being tunneled from a fake X
display to a real one")
- `head -3 /usr/bin/xtrace` still shows the GNU libc copyright
banner — glibc's xtrace untouched.
### What is now fully resolved from earlier "operator-decision-pending"
- ✅ firefox installed → all 6 matrix cells now have a binary
available.
- ✅ xtrace (X protocol tracer) installed at `/usr/bin/x11trace`
→ if any Phase 1 cell wants protocol-level evidence parallel
to the predecessor's `WAYLAND_DEBUG=1`, the instrument is
ready.
---
## Entry 4 — 2026-05-03 ~10:25 CEST
**Trigger:** Operator was in the freshly-switched XFCE session
("Can you rotate the xfce session for me? Right now, left is up
and right is down"). The PineTab2 panel is mounted portrait
(native mode 800×1280@59.98) and XFCE's default rotation
("normal") shows it that way; Plasma X11 / Plasma Wayland have
historically used `right` rotation to present landscape
1280×800. This entry brings XFCE in line.
**Driven from:** `mfritsche@noether` over SSH to `ohm.fritz.box`,
regular user (no sudo needed; per-user state only).
### What was changed
1. **Live rotation applied** to the active XFCE session (session
id 395, Xorg pid 32073, DISPLAY=:0,
XAUTHORITY=/run/user/1001/xauth_QctOSR):
```
xrandr --output DSI-1 --rotate right
```
Result: `Screen 0 ... current 1280 x 800` and `DSI-1
connected 1280x800+0+0 right`. Matches the Plasma X11
orientation.
2. **Persistence: `~/.config/autostart/99-rotate-dsi1.desktop`
created** so every future XFCE login runs the rotation
immediately. File contents:
```
[Desktop Entry]
Type=Application
Name=Rotate DSI-1 to landscape (right)
Comment=Created 2026-05-03 by x11-session-research campaign —
see phase0_evidence/x11_inventory_2026-05-03/revert.log entry 4
Exec=sh -c "xrandr --output DSI-1 --rotate right"
OnlyShowIn=XFCE;
Terminal=false
```
`OnlyShowIn=XFCE` keeps it from running under Plasma X11 /
openbox — those handle their own rotation state.
### Why not via xfconf
XFCE's `displays` xfconf channel was empty
(`xfconf-query -c displays -lv` showed only `/ActiveProfile`
= `Default` with no per-monitor data). xfce4-display-settings
populates that profile on first GUI use; without that population,
writing rotation codes by hand into xfconf is brittle (the
encoding of "right" depends on xfce4-settings version). An
autostart .desktop file is version-independent and easy to
inspect.
If the operator subsequently runs *Settings → Display* in the
XFCE GUI and clicks Save / Apply, xfconf will write a real
profile and the autostart file becomes redundant — at that
point either can stay (no conflict) or the autostart can be
removed.
### What is NOT changed
- No system-wide config touched.
- No package install.
- Plasma X11 and openbox sessions unaffected — `OnlyShowIn=XFCE`
scopes the autostart to XFCE only.
- Touchscreen orientation: **NOT** auto-corrected by this entry.
After rotation, the Goodix Capacitive TouchScreen will likely
report touches in the panel's native (portrait) coordinate
space, so taps land on the wrong screen position. Fix when
it becomes a concern:
```
xinput map-to-output "Goodix Capacitive TouchScreen" DSI-1
```
This is **not auto-applied** in this entry because the matrix
cells use mouse + keyboard for navigation, not touch — and
also because mapping the touchscreen would itself need
another autostart entry. If touch becomes relevant later,
add it as entry 5.
---
## Entry 5 — 2026-05-03 ~10:29 CEST
**Trigger:** Operator confirmed XFCE session alive after entry 4
("xfce-session alive"), then accepted the touchscreen-mapping
follow-up offered in entry 4's "What is NOT changed" note.
**Driven from:** `mfritsche@noether` over SSH to `ohm.fritz.box`,
regular user.
### What was changed
1. **Live mapping applied:**
```
xinput map-to-output "pointer:Goodix Capacitive TouchScreen" DSI-1
```
The `pointer:` prefix is required because the Goodix exposes
both a pointer device (id 13) and a keyboard subdevice
(id 15) — `xinput` needs the disambiguation. Verified by
`xinput list-props`: Coordinate Transformation Matrix
updated to `[0 1 0 / -1 0 1 / 0 0 1]` — the homogeneous
90°-clockwise rotation matrix matching the screen.
2. **Persistence:
`~/.config/autostart/99-rotate-touchscreen.desktop` created**.
Same `OnlyShowIn=XFCE` scoping. The Exec uses `sh -c "sleep 2;
xinput ..."` because XFCE may launch this autostart before
entry 4's xrandr rotation has finished applying — without
the sleep, the xinput remap can race against an unrotated
screen state.
### What is NOT changed
- Other input devices (touchpad, USB mouse, USB keyboard)
unchanged — they don't report panel-relative coordinates so
rotation doesn't affect them.
- Plasma X11 / openbox sessions unaffected
(`OnlyShowIn=XFCE`).
- Wayland sessions unaffected (xinput is X11-only). When KDE
Plasma Wayland next runs, it uses its own
`kwriteconfig5 --file kwinrc` mapping — that's predecessor
state, not touched here.
---
## How to revert this campaign's installs
Entries reverted in **reverse order** (entry 5 → 4 → 3 → 2 → 1):
```sh
ssh ohm.fritz.box '
set -e
# ----- Entry 5 revert: touchscreen mapping -----
rm -f ~/.config/autostart/99-rotate-touchscreen.desktop
# Live revert: reset Coordinate Transformation Matrix to identity.
# Only meaningful in an X11 session; harmless if no XFCE running.
if pgrep -x xfwm4 >/dev/null; then
DISPLAY=:0 XAUTHORITY=$(ls /run/user/$(id -u)/xauth_* 2>/dev/null | head -1) \
xinput set-prop "pointer:Goodix Capacitive TouchScreen" \
"Coordinate Transformation Matrix" \
1 0 0 0 1 0 0 0 1 || true
fi
# ----- Entry 4 revert: XFCE rotation -----
rm -f ~/.config/autostart/99-rotate-dsi1.desktop
# Live rotation revert (only if currently in XFCE):
if pgrep -x xfwm4 >/dev/null; then
DISPLAY=:0 XAUTHORITY=$(ls /run/user/$(id -u)/xauth_* 2>/dev/null | head -1) \
xrandr --output DSI-1 --rotate normal || true
fi
# ----- Entry 3 revert: firefox + xtrace -----
sudo pacman -Rsn --noconfirm firefox xtrace
# mailcap was pulled as a firefox dep; -Rs cleans it up if no other
# dependent remains.
# ----- Entry 2 revert: XFCE -----
sudo pacman -Rsn --noconfirm \
exo garcon mousepad parole ristretto thunar \
thunar-archive-plugin thunar-media-tags-plugin thunar-volman tumbler \
xfburn xfce4-appfinder xfce4-battery-plugin xfce4-clipman-plugin \
xfce4-cpufreq-plugin xfce4-cpugraph-plugin xfce4-dict \
xfce4-diskperf-plugin xfce4-eyes-plugin xfce4-fsguard-plugin \
xfce4-genmon-plugin xfce4-mailwatch-plugin xfce4-mount-plugin \
xfce4-mpc-plugin xfce4-netload-plugin xfce4-notes-plugin \
xfce4-notifyd xfce4-panel xfce4-places-plugin xfce4-power-manager \
xfce4-pulseaudio-plugin xfce4-screensaver xfce4-screenshooter \
xfce4-sensors-plugin xfce4-session xfce4-settings \
xfce4-smartbookmark-plugin xfce4-systemload-plugin xfce4-taskmanager \
xfce4-terminal xfce4-time-out-plugin xfce4-timer-plugin \
xfce4-verve-plugin xfce4-wavelan-plugin xfce4-weather-plugin \
xfce4-whiskermenu-plugin xfce4-xkb-plugin xfconf xfdesktop xfwm4
# Per-user xfconf tree: only safe to remove if the operator never
# logged into XFCE (otherwise xfconfd may have written other settings
# the operator would lose). Manual check:
if [ "$(find ~/.config/xfce4 -type f | sort)" = "$HOME/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml" ]; then
rm -rf ~/.config/xfce4
echo " ~/.config/xfce4 removed (only the pre-seeded xfwm4.xml was there)"
else
echo " ~/.config/xfce4 contains operator-added files; manual review required"
find ~/.config/xfce4 -type f
fi
# ----- Entry 1 revert: measurement tools + openbox -----
sudo pacman -Rsn --noconfirm \
openbox sysprof \
xorg-xrandr xorg-xev xorg-xinput xorg-xwininfo xorg-xkill
# Sysctl: nothing to undo (entry 1's paranoid=1 was already reverted
# in-session — see entry 1 § "What was changed").
# ----- Verification -----
echo "expected pkg count after revert: 1169"
pacman -Qq | wc -l
echo "expected sysctl: kernel.perf_event_paranoid = 2"
sysctl kernel.perf_event_paranoid
echo "expected sessions: only plasmax11.desktop"
ls /usr/share/xsessions/
echo "expected /etc/sysctl.d/: empty"
ls /etc/sysctl.d/
'
```
Sanity-check: `pacman -Qq | wc -l` should report **1169**, matching
`pkglist.pre.txt`. If it reports anything else, the operator
added/removed a package between an entry and the revert;
investigate before declaring revert complete.
---
## Adding a new entry
When a future Phase install/mutation happens, append a new
`## Entry N — YYYY-MM-DD` section above the "How to revert"
section. Re-snapshot `pacman -Qq` into a new
`pkglist.entryN.{pre,post}.txt` so each entry is independently
revertible. Prepend the new entry's revert step to the
"How to revert" block (entries revert in reverse install
order — newest first).
+50 -17
View File
@@ -279,17 +279,48 @@ dominates per browser × decode path.
### Experimental matrix
Six 2-axis cells (3 browsers × 2 decode paths) × 2
session conditions (with-KWin / without-KWin):
Eight 2-axis cells (3 browsers + 1 reference client × 2 decode
paths) × 2 session conditions (with-KWin / without-KWin):
| Browser | Decode | with-KWin (Plasma Wayland) | without-KWin (X11 session, no compositor) |
| Client | Decode | with-KWin (Plasma Wayland) | without-KWin (X11 session, no compositor) |
|---|---|---|---|
| Brave 147 | full SW | C-W-brave-sw | C-X-brave-sw |
| Brave 147 | libva (if it works) | C-W-brave-libva | C-X-brave-libva |
| chromium-fourier 149 (Step 1 + Step 2) | full SW | C-W-chrf-sw | C-X-chrf-sw |
| chromium-fourier 149 | libva (Step 1 enables it) | C-W-chrf-libva | C-X-chrf-libva |
| Firefox | full SW | C-W-ff-sw | C-X-ff-sw |
| Firefox | libva | C-W-ff-libva | C-X-ff-libva |
| Firefox 150 | full SW | C-W-ff-sw | C-X-ff-sw |
| Firefox 150 | libva | C-W-ff-libva | C-X-ff-libva |
| **mpv 0.41 (reference)** | **full SW** | **C-W-mpv-sw** | **C-X-mpv-sw** |
| **mpv 0.41 (reference)** | **libva / v4l2request** | **C-W-mpv-hw** | **C-X-mpv-hw** |
Each mpv cell is run twice — once with `--vo=xv` (XVideo
extension, the legacy X11-hardware-overlay path mpv has used
since the late 1990s) and once with `--vo=gpu --gpu-context=x11`
(modern Mesa GL + DRI3 + XPresent path). Two VOs × 8 mpv cells
= 16 mpv data points. The two mpv VOs probe orthogonal
questions:
- `--vo=xv`: does the X server's XVideo adapter route NV12 to
a hardware plane on rockchip-drm RK3568 at all? If yes,
XVideo is a known-good baseline that the browsers' more
modern overlay paths *should* match or beat.
- `--vo=gpu --gpu-context=x11`: does the Mesa Panfrost
GL+DRI3+XPresent path on rockchip allow the X server to
route an NV12 dmabuf to Plane 39 (the Primary plane, the
only NV12-LINEAR-capable plane on this hardware)? This is
the same plumbing the browsers use, so a positive result
here means the browsers *could* but might not. A negative
result means even mpv can't, in which case the browsers
cannot either.
mpv's role is **reference baseline**, not target. If both mpv
VOs show clean hardware-overlay scanout but the browsers don't,
the campaign verdict is "the X11 path is fast on this hardware,
but the browsers leave the speedup on the table." If even mpv's
two VOs can't engage Plane 39 NV12, the "X11 hardware-overlay
mechanism is structurally avoidable" claim is challenged on
this specific kernel/Mesa stack and the campaign needs to
re-frame.
The "(if it works)" / "where possible" qualifier per the
operator's directive: libva on rockchip-drm RK3568 only works
@@ -298,7 +329,9 @@ stock Brave 147 and stock Firefox, libva probably doesn't
engage and those cells are documented N/A. For Firefox, the
Mesa-side `libva-v4l2-request` may make libva work via Mozilla's
VAAPI backend even on stock Firefox — to be verified in
Phase 0 inventory.
Phase 0 inventory. mpv on this hardware should be able to
engage `--hwdec=v4l2request-copy` (the Mesa libva-v4l2-request
backend) for the libva mpv cells.
### What "cutting out the KWin compositor" means
@@ -357,15 +390,15 @@ unknown:
presentation (rather than internally composing to RGB) is
open. Mozilla has a `MOZ_X11_EGL` hint and a "hardware video
overlay" pref but these are not universally engaged.
- **Reference clients**: mpv with `--vo=xv` or
`--vo=gpu --hwdec=auto-copy --gpu-context=x11`, or `gst-play-1.0`
with `xvimagesink` or `glimagesink`, are known-good X11
hardware-overlay paths. **Adding mpv to the matrix as a
reference client** would isolate "does the X11 hardware-
overlay path work AT ALL on this hardware" from "do
browsers actually use it." If mpv hardware-overlays cleanly
but browsers don't, the conclusion is "the X11 path is fast,
but browsers leave the speedup on the table."
- **Reference clients**: mpv was added to the matrix as a 4th
client (see § "Experimental matrix" above) — two cells, each
run with both `--vo=xv` and `--vo=gpu --gpu-context=x11` to
cover both the legacy XVideo overlay path and the modern
DRI3+XPresent+Mesa-GL path. `gst-play-1.0` with `xvimagesink`
or `glimagesink` would be a possible extension if the mpv
cells produce ambiguous results, but mpv alone covers the
"is the X11 hardware-overlay path even reachable on this
hardware" question.
If the operator agrees, Phase 0 inventory should:
@@ -378,8 +411,8 @@ If the operator agrees, Phase 0 inventory should:
2. Inventory Brave's, chromium-fourier's, and Firefox's X11
overlay-presentation paths to see which (if any) request
hardware-overlay presentation.
3. Add mpv as a reference X11-overlay client to the matrix,
so the campaign has a known-good comparison point.
3. ~~Add mpv as a reference X11-overlay client to the matrix~~
Done — mpv 0.41 added as a 4th client row 2026-05-03.
### What this question does NOT cover
+32 -15
View File
@@ -52,21 +52,38 @@ inventory and baseline-anchor work below.
sessions. Operator action: `pacman -S` a non-compositing WM
(recommend openbox) and create/switch to its SDDM session
before without-KWin cells can run.
- [ ] **NEW: Browser X11-overlay-path inventory.** Per
`phase0_findings.md` § "Open questions": determine whether
Brave 147 ozone-x11, chromium-fourier 149 ozone-x11, and
Firefox X11 backends actually request hardware-overlay
presentation for windowed video, or whether they always
internally composite to RGB. Browser-specific source-grep
+ chrome trace inspection.
- [ ] **NEW: Add mpv as a reference X11-overlay client.**
mpv with `--vo=xv` or `--vo=gpu --gpu-context=x11` is a
known-good X11 hardware-overlay path. Adding mpv to the
matrix as a 4th client provides "is the X11 hardware-overlay
path even reachable on this hardware" baseline, separate
from "do browsers use it." If mpv hits Plane 39 NV12 cleanly
but browsers don't, the answer is "X11 path is fast, but
the browsers don't take advantage of it."
- [x] **Browser X11-overlay-path inventory.** Captured
2026-05-03 in
`phase0_evidence/browser_overlay_inventory_2026-05-03.md`
+ acquired-source subtree
`phase0_evidence/chromium_ozone_x11_2026-05-03/` (Chromium
147 from `chromium-builder` LXD CT on boltzmann via the
his subagent). **Decisive verdict at the source level:**
Chromium ozone-x11 instantiates `StubOverlayManager`
(`ozone_platform_x11.cc:262`) — no overlay candidates ever
promoted; Brave 147 + chromium-fourier 149 inherit this
unchanged (their patches don't touch Ozone). Firefox 150
`WindowSurfaceX11{,Image,SHM}` are RGB-only (zero NV12 /
dmabuf / DRI3 / XPresent references in any X11-surface
file). **No browser in the matrix has a code path to
hand NV12 to the X server for plane scanout.** Only mpv
`--vo=xv` does; mpv `--vo=gpu --gpu-context=x11` is the
same GL-composite shape as the browsers. Implication:
campaign's load-bearing hypothesis is structurally
weakened — the X11-vs-Wayland delta the matrix will
measure for browsers is "browser-side GL composite +
X-scanout-of-RGB" vs "browser-side GL composite +
KWin-RGB-recomposite + scanout". mpv-xv becomes the
matrix's only direct test of the original mechanism.
Runtime-engagement probe deferred to Phase 1 first rep
(design sketched in the inventory doc).
- [x] **mpv added as 4th matrix client** 2026-05-03. Two cells
(full SW, libva/v4l2request) × 2 sessions × 2 VOs (`--vo=xv`
and `--vo=gpu --gpu-context=x11`) = 8 reference data points.
README + `phase0_findings.md` § "Experimental matrix"
updated; matrix grew from 12 → 16 cells (+8 mpv VO sub-points).
mpv 0.41.0 already installed via predecessor (see
`phase0_evidence/x11_inventory_2026-05-03/02_x11_paths.txt`).
- [x] Inventory of X11-side measurement instruments. Captured
2026-05-03 in `phase0_evidence/x11_inventory_2026-05-03/`
(raw `04_measurement_instruments.txt` + summary `inventory.md`