iGac
August 10, 2026 · View on GitHub
macOS implementation of GacUI using Cocoa and CoreGraphics/Quartz2D.
License
Read the LICENSE first.
Maintenance Prerequisite
This repo is stand alone, all dependencies are in the repo for building.
To run RemotingTest_Rendering_macOS by test.sh --app:renderer, the GacUI repo is needed to run Test/Linux/RemotingTest_Core as an HTTP server.
For developers maintaining this repo, run ./syncOrg.sh, or clone the upstream repositories beside this repository. iGac reads framework imports, release sources, test resources, generated-code metadata, and the Knowledge Base directly from ../GacUI; import.sh to take latest code from GacUI/(Import|Release) to Import; syncProj.sh also builds Workflow's CppMerge from ../Workflow. The Release repository is not an iGac maintenance dependency.
Install Homebrew and Development Tools
Install Apple's Command Line Tools if they are not already installed:
xcode-select --install
Install Homebrew with the command from the official Homebrew installation page:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Follow the installer's Next steps to add Homebrew to your shell environment, then run this command from the repository root:
brew update
brew bundle
brew bundle installs the tools declared in Brewfile:
| Brewfile entry | Purpose |
|---|---|
cmake | Configures the native build. This project requires CMake 3.20 or newer. |
coreutils | Provides grealpath, used by syncProj.sh and the upstream helper build scripts. |
node | Installs Node.js and its bundled npm for JavaScript tooling. The native CMake build does not invoke them. |
visual-studio-code | Installs Visual Studio Code as an optional development editor; it is not required by the build or test scripts. |
Apple's Command Line Tools provide clang++, lldb, make, git, and the
macOS SDK and frameworks. No separate Homebrew LLVM or Git installation is
needed. The helper scripts call Coreutils' grealpath name explicitly, so its
gnubin directory does not need to be added to PATH.
To update Homebrew and these tools later:
brew update
brew bundle
See Homebrew's package update instructions for upgrading all installed packages instead.
Project Structure
iGac/
├── Brewfile Homebrew formulae and development-tool casks
├── Mac/ macOS platform implementation
│ ├── NativeWindow/OSX/ Cocoa windowing (controller, window, view, input)
│ │ ├── ServicesImpl/ Service implementations (screen, clipboard, dialog, ...)
│ │ └── CoreGraphics/ CoreGraphics app entry point
│ └── GraphicsElement/
│ └── CoreGraphics/ CoreGraphics rendering engine (renderers, layout, resource manager)
│
├── MacShared/ Shared static libraries and test utilities
│ ├── CMakeLists.txt Builds GacUI, GacOSX, GacOSXShared static libraries
│ ├── gac_include.h Convenience header: includes GacUI, registers DarkSkin theme
│ ├── osx_shared.h/mm OS X helpers (string conversion, file utils, resource folder)
│ └── UnixFileSystemInfo.* Cross-platform file system utilities
│
├── MacTest/ Simple test app (Hello World)
│ ├── CMakeLists.txt
│ └── HelloWorlds/Cpp/Main.cpp
│
├── MacFullControlTest/ Full-featured test app using BlackSkin control template
│ ├── CMakeLists.txt
│ └── Main.mm
├── MacCppTestRvm/ Hosted Remote View Model Test client
├── RemotingTest_Rendering_macOS/ Native `/MiniHttp` renderer for GacUI's RemotingTest_Core
│
├── Apps/ Upstream test resources and generated x64 C++
│ ├── FullControlTest/
│ │ ├── Resources/ Copied from ../GacUI/Test/Resources/App
│ │ └── Source/ Generated by GacGen, including embedded resources
│ ├── RemoteProtocolTest/
│ │ ├── Resources/
│ │ └── Source/
│ └── RemoteViewModelTest/
│ ├── Resources/
│ └── Source/
│
├── Import/ Amalgamated GacUI source files (Vlpp, GacUI, Workflow, ...)
├── Import-Test/ Test-only GacUI remoting helper amalgamations
│
├── doc/ Documentation
│ ├── OSProvider.md macOS OS provider: controller, services, entry point
│ ├── OSProvider_Window.md macOS OS provider: INativeWindow, CocoaWindow, popups
│ ├── OSProvider_Graphics.md macOS OS provider: CoreGraphics rendering, elements, fonts
│ ├── OSProvider_HostedMode.md macOS hosted mode: virtual windows, render lifecycle
│ └── lldb.md Direct LLDB debugging and launch validation
│
├── CMakeLists.txt Root CMake config (project GacOSX, C++23)
├── import.sh Refresh Import/ from the sibling GacUI repository
├── syncOrg.sh Clone and synchronize sibling organization repositories
├── syncProj.sh Sync test resources and regenerate x64 C++ sources
├── build.sh Build script (incremental by default, --rebuild for clean)
└── test.sh Run test apps or the native remote renderer
The generated Import/, Import-Test/, and Apps/ snapshots are committed so a normal iGac build does not require code generation. Run the synchronization scripts when updating upstream dependencies or test resources.
Synchronizing Organization Repositories
./syncOrg.sh
This synchronizes the Vlpp, VlppOS, VlppRegex, VlppReflection,
VlppParser2, Workflow, GacUI, GacJS, Release, Tools, wGac, and
iGac repositories, including the repository containing the script itself.
Missing repositories are cloned from the vczh-libraries GitHub organization.
Existing repositories are updated only when they are on master with no
uncommitted tracked files, untracked files, or unpushed commits. A repository
that fails any check is reported in red and skipped while the script continues
with the remaining repositories.
Refreshing GacUI Imports
./import.sh
This removes and recreates Import/ and Import-Test/, copies dependency amalgamations from ../GacUI/Import/, adds the ordinary GacUI amalgamations from ../GacUI/Release/, places the DarkSkin release files under Import/Skins/DarkSkin/, and moves the required Test.RemotingHelpers pair plus any optional Windows pair into Import-Test/. Both snapshots are marked read-only. Import/ and Import-Test/ are frozen after import: compatibility fixes belong in this repository's CMake or macOS integration code. The helper pair is only for platform test targets and is not part of the ordinary framework snapshot. Review and commit the vendor update together with those integration changes.
Synchronizing Test Projects
./syncProj.sh
This performs incremental builds of ../Workflow/Tools/CppMerge and
../GacUI/Tools/GacGen, copies the FullControlTest, RemoteProtocolTest, and
RemoteViewModelTest resource trees from ../GacUI/Test/Resources/App/,
preserves resource-owned seed C++ files, and invokes GacGen /C64 for each
application. 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 test remoting helpers come from Import-Test/;
neither is maintained as a local MacShared/Mini*.cpp copy. Generated
reflection files are retained in Apps/*/Source, but test targets compile with
VCZH_DEBUG_NO_REFLECTION and do not include them.
Each generated application also has an embedded-resource .cpp file. Full Control Test links FullControlTestResource.cpp, whose plugin loads the resource from compiled data; no .bin file is bundled or located at runtime.
Building
./build.sh # Incremental build
./build.sh --rebuild # Clean build (git clean -xdf + full rebuild)
Build output goes to build/. The build system requires CMake 3.20 or newer and uses C++23.
Static Libraries (built by MacShared/CMakeLists.txt)
- GacUI — Core GacUI amalgamated sources (Vlpp, VlppOS, VlppRegex, VlppReflection, VlppGlrParser, VlppWorkflowLibrary, GacUI, DarkSkin)
- GacOSX — All macOS platform code (Cocoa windowing, CoreGraphics rendering, services)
- GacOSXShared — Imported remoting test helpers plus shared macOS test utilities (osx_shared, UnixFileSystemInfo)
Code is compiled with VCZH_DEBUG_NO_REFLECTION. If reflection is needed, remove this define from MacShared/CMakeLists.txt and add all reflection .cpp files.
Running
./test.sh --app:simple # Run Hello World
./test.sh --app:simple --unblock # Run Hello World in background
./test.sh --app:fct # Run Full Control Test
./test.sh --app:fct --hosted # Run Full Control Test in hosted mode
./test.sh --app:fct --hosted --unblock # Combine hosted and background modes
./test.sh --app:rvmt # Run the hosted Remote View Model Test client
./test.sh --app:rvmt --unblock # Start the RVM client and print its PID
./test.sh --app:renderer # Connect to RemotingTest_Core with /MiniHttp
./test.sh --app:renderer --port:8890 # Start a takeover renderer on automation port 8890
./test.sh --app:renderer --unblock # Start the renderer and print its PID
--unblock starts the selected executable in the background and prints its
PID. --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 Core connection on port 8888. The default
renderer automation port is 8889.
Every test application owns a mode-specific Cocoa automation service and a
MiniHTTP endpoint. Append /Controls for control-tree applications, /Dom
for the native renderer, or /IO for input:
| Test application | Automation service | Endpoint base |
|---|---|---|
| Simple | CocoaAutomationService | http://127.0.0.1:8888/Automation/Test_HellWorld_Cpp |
| Full Control Test | CocoaAutomationService or CocoaAutomationServiceHosted | http://127.0.0.1:8888/Automation/Test_FullControlTest |
| Remote View Model Test | CocoaAutomationServiceHosted | http://127.0.0.1:8888/Automation/CppTest_Rvm |
| Native remote renderer | CocoaAutomationServiceRenderer | http://127.0.0.1:<renderer-port>/Automation/RemotingTest_Rendering_Native |
--app:rvmt waits for the matching Workflow RPC host. Start the client first,
then run:
../GacUI/Test/Linux/RemotingTest_RvmHost/Bin/RemotingTest_RvmHost /MiniHttp
The RVM client exposes its control tree after the host connects.
For the native renderer, start
GacUI/Test/Linux/RemotingTest_Core/Bin/RemotingTest_Core /MiniHttp /RPT
(or /FCT) before ./test.sh --app:renderer. The renderer exposes its DOM and
renderer-side IO on its selected automation port. A replacement can reuse 8889
after the old renderer stops; for live takeover, keep the old renderer on 8889
and start the new one with --port:8890.
Follow GacUI's native-renderer verification guide for the complete RPT/FCT, replacement, takeover, and cleanup workflow.
Documentation
- doc/OSProvider.md — Controller, services, entry point, and overall architecture of the macOS platform layer.
- doc/OSProvider_Window.md — INativeWindow implementation (CocoaWindow): window lifecycle, Show/Hide, popups, child windows, custom frame, key differences from Windows.
- doc/OSProvider_Graphics.md — CoreGraphics rendering backend: render targets, element renderers, text layout, font management.
- doc/OSProvider_HostedMode.md — Hosted mode: single-window rendering, hosted controller, virtual windows, render target lifecycle.
- doc/lldb.md — Direct LLDB command-line debugging and launch-validation workflow.
TODO
IGuiGraphicsParagraph- Need to test inserting image.
- Test CocoaClipboardService when image is tested.
Known Issues
- VKEY mapping is quite big, should be shorter
- Not Implemented:
AsyncService::Semaphore::WaitForTimeCoreGraphicsResourceManager::CreateRawElementCocoaInputService::(R|Unr)egisterGlobalShortcutKeyCocoaWindow::GetIconandSetIcon
Upstream Issues
FakeDialogService- File dialog shows empty local disk. The issue is in VlppOS, fix it and test here again.
Planning
- Replace CGLayer with Metal for rendering