iGac

August 10, 2026 · View on GitHub

macOS implementation of GacUI using Cocoa and CoreGraphics/Quartz2D.

Ask DeepWiki

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 entryPurpose
cmakeConfigures the native build. This project requires CMake 3.20 or newer.
coreutilsProvides grealpath, used by syncProj.sh and the upstream helper build scripts.
nodeInstalls Node.js and its bundled npm for JavaScript tooling. The native CMake build does not invoke them.
visual-studio-codeInstalls 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 applicationAutomation serviceEndpoint base
SimpleCocoaAutomationServicehttp://127.0.0.1:8888/Automation/Test_HellWorld_Cpp
Full Control TestCocoaAutomationService or CocoaAutomationServiceHostedhttp://127.0.0.1:8888/Automation/Test_FullControlTest
Remote View Model TestCocoaAutomationServiceHostedhttp://127.0.0.1:8888/Automation/CppTest_Rvm
Native remote rendererCocoaAutomationServiceRendererhttp://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::WaitForTime
    • CoreGraphicsResourceManager::CreateRawElement
    • CocoaInputService::(R|Unr)egisterGlobalShortcutKey
    • CocoaWindow::GetIcon and SetIcon

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