wGac
August 9, 2026 · View on GitHub
wGac implements the native GacUI platform layer for Linux Wayland using Wayland, Cairo, Pango, and XKBCommon.
Prerequisites
The committed Import/ and Apps/ snapshots make a normal build self-contained. On Debian or Ubuntu, install:
sudo apt update
sudo apt install build-essential clang cmake pkg-config \
libwayland-dev libxkbcommon-dev \
libdecor-0-dev libdecor-0-plugin-1-gtk \
libcairo2-dev libpango1.0-dev libfontconfig1-dev \
libgdk-pixbuf-2.0-dev libglib2.0-dev liburing-dev
The retained WGacDialogService implementation uses GIO, but current Wayland applications select FakeDialogService and do not require a desktop portal backend.
Run applications from a Wayland desktop session with WAYLAND_DISPLAY and XDG_RUNTIME_DIR available.
wGac requires libdecor and a real runtime decoration plugin at startup; it stops with a diagnostic instead of silently accepting libdecor's undecorated fallback. To make repeated switches between GacUI custom frames and platform frames safe on every compositor, wGac forces libdecor to provide its client-side platform frame even when server-side decorations are available. This libdecor frame is the native platform frame from GacUI's perspective and is distinct from GacUI's custom window template.
For maintenance work, keep the GacUI, Workflow, and Tools repositories beside wGac, or run ./syncOrg.sh. import.sh reads GacUI framework snapshots, and syncProj.sh reads GacUI test resources and builds the Workflow and GacUI generators. The sibling Release repository is not a build or import dependency.
Project Structure
wGac/
├── WGac/ Wayland platform implementation
│ ├── Protocol/ Committed Wayland protocol sources
│ ├── Renderers/ Cairo/Pango GacUI renderer
│ ├── Services/ Native platform and automation services
│ └── Wayland/ Display, seat, and buffer integration
├── WGacShared/ GacUI, wGac, and shared test libraries
├── WGacTest/ Hello World test app
├── WGacFullControlTest/ Full Control Test, standard or hosted
├── WGacCppTestRvm/ Remote View Model Test client
├── RemotingTest_Rendering_Wayland/ Native renderer for RemotingTest_Core
├── Apps/ Synchronized resources and generated C++
├── Import/ Imported GacUI amalgamated sources
├── Import-Test/ Test-only GacUI remoting helper amalgamations
├── import.sh Refresh Import from sibling GacUI
├── syncProj.sh Refresh and generate Apps and shared sources
├── syncOrg.sh Synchronize organization repositories, including wGac
├── build.sh Build all test targets
└── test.sh Launch one test target
Import/ and Import-Test/ are frozen after ./import.sh; framework fixes belong in GacUI, and Wayland compatibility fixes belong in wGac. Import-Test/ contains the dedicated Test.RemotingHelpers pair and an optional Windows pair when GacUI emits one; these files are for platform test targets and are not part of the ordinary GacUI framework snapshot. Files under Apps/*/Resources/ and Apps/*/Source/ are synchronized or generated by ./syncProj.sh and must not be edited directly.
Synchronizing Dependencies
Synchronize the organization repositories, including this wGac checkout:
./syncOrg.sh
Refresh the imported framework snapshot:
./import.sh
This replaces Import/ and Import-Test/, copies the ordinary framework files from ../GacUI/Import/ and ../GacUI/Release/, adds the DarkSkin release sources, moves the required Test.RemotingHelpers pair and any optional Windows pair into Import-Test/, and marks both snapshots read-only.
Refresh the Full Control Test, Remote Protocol Test, and Remote View Model Test projects:
./syncProj.sh
This incrementally builds Workflow's CppMerge and GacUI's GacGen, copies all three upstream resource trees, preserves resource-owned seed C++ files, and regenerates their x64 C++ sources under Apps/. It also refreshes the shared native-renderer and RVM entry points and the RVM initializer. MiniHTTP automation is part of the imported GacUI snapshot, while reusable remoting test helpers come from Import-Test/; neither is maintained as a local WGacShared/Mini*.cpp copy.
Building
./build.sh
./build.sh --rebuild
The first command is incremental. --rebuild removes ignored build output with git clean -xdf and performs a clean build, so commit or stage any new source files before using it.
The root CMake project uses C++23 and builds:
GacUI, the imported GacUI framework.WGac, the Wayland platform layer.WGacShared, imported remoting test helpers shared by the test targets.Test_HellWorld_Cpp.Test_FullControlTest.Test_CppTest_Rvm.RemotingTest_Rendering_Wayland.
Running and Automation
./test.sh --app:simple
./test.sh --app:simple --unblock
./test.sh --app:fct
./test.sh --app:fct --hosted
./test.sh --app:fct --hosted --unblock
./test.sh --app:rvmt
./test.sh --app:rvmt --unblock
./test.sh --app:renderer
./test.sh --app:renderer --port:8890
./test.sh --app:renderer --unblock
--hosted is valid only with --app:fct. --port:<1-65535> is valid only with --app:renderer and selects that renderer's automation listener; it does not change the /MiniHttp connection to Core on port 8888. The default renderer automation port is 8889. --unblock starts the selected executable in the background and prints its PID.
The normal applications expose MiniHTTP automation on port 8888:
- Hello World:
/Automation/Test_HellWorld_Cpp - Full Control Test:
/Automation/Test_FullControlTest - Remote View Model Test:
/Automation/CppTest_Rvm
For example:
curl http://localhost:8888/Automation/Test_HellWorld_Cpp/Controls
curl -H 'Content-Type: application/json; charset=utf8' \
--data '!Exit' \
http://localhost:8888/Automation/Test_HellWorld_Cpp/IO
Use GET .../Controls to inspect the control tree and POST .../IO or POST .../IO/<windowId> to send an IO command. A successful command returns Queued.
Always stop background test processes when verification is complete.
--app:rvmt waits for the matching Workflow RPC host. Start the client first, then run:
../GacUI/Test/Linux/RemotingTest_RvmHost/Bin/RemotingTest_RvmHost /MiniHttp
Native Remote Renderer
Build and start GacUI/Test/Linux/RemotingTest_Core in /MiniHttp mode for either /RPT or /FCT, then run:
./test.sh --app:renderer
The core listens on port 8888. The Wayland renderer connects through /MiniHttp and, by default, exposes its DOM and renderer-side IO on port 8889 at:
/Automation/RemotingTest_Rendering_Native
Renderer replacement can reuse port 8889 after the old renderer stops. For live takeover, keep the existing renderer on 8889 and start the new renderer with --port:8890, then use the same automation prefix on port 8890.
Follow GacUI's native-renderer verification guide for the complete RPT/FCT, replacement, takeover, and cleanup workflow.
Known Limitations
- Native Dialogs:
- The native FileChooser portal is implemented for open and save dialogs.
- Message box not implemented.
- Color picker not implemented.
- Font picker not implemented.
- These are limitations of
WGacDialogService; the Wayland implementation currently always uses GacUI'sFakeDialogService, so applications do not invoke any native dialog.
- Wayland does not allow clients to position normal top-level windows globally; placement requests are compositor-dependent.
- libdecor has no platform-frame window-icon API, so
IconVisibleis unsupported and always reportsfalse. - libdecor cannot independently hide the maximize control. Its maximize affordance follows
SizeBox(the frame's resize capability);MaximizedBoxretains its requested value but cannot override that platform limitation.