================================================================================
  WebViewCtrl for U++ (UltimatePP) — Technical Knowledge Report
  Session date: May 2026
  Author: Claude Sonnet (Anthropic) + Luigi Forlano
================================================================================

This document captures the technical knowledge acquired during a two-day session
building a cross-platform browser engine Ctrl for U++ (UltimatePP framework).
It is intended to help reconstruct context in future sessions.

--------------------------------------------------------------------------------
1. WHAT WAS BUILT
--------------------------------------------------------------------------------

A reusable U++ Ctrl called WebViewCtrl that embeds a native browser engine:
  - Windows : Microsoft WebView2 (Edge Chromium)
  - macOS   : WKWebView (WebKit/Safari)
  - Linux   : WebKitGTK (webkit2gtk-4.1)

Public API (identical on all platforms):
  WebViewCtrl& SetHtml(const String& html)
  WebViewCtrl& SetUrl(const String& url)
  WebViewCtrl& SetFile(const String& path)   // local HTML file with relative resources
  WebViewCtrl& RunScript(const String& js)
  void         Print()                        // opens native print dialog
  Event<>      WhenLoaded                     // fired when page finishes loading

File structure:
  WebViewCtrl.h               — public interface, cross-platform, no platform types
  WebViewCtrl_Win.cpp         — Windows implementation (guarded by #ifdef _WIN32)
  WebViewCtrl_Linux.cpp       — Linux U++ side, C++ only (guarded by #ifdef __linux__)
  WebViewCtrl_Linux_bridge.h  — C-only bridge header, no U++ or GTK includes
  WebViewCtrl_Linux_gtk.cpp   — Linux GTK/X11 side, no U++ includes
  WebViewCtrl_Mac.cpp         — macOS U++ side, C++ only (guarded by #ifdef __APPLE__)
  WebViewCtrl_Mac_bridge.h    — C-only bridge header
  WebViewCtrl_Mac_objc.mm     — macOS Objective-C++ side, no U++ includes
  WebViewCtrl.upp             — U++ package file
  main.cpp                    — test application

--------------------------------------------------------------------------------
2. KEY U++ INTERNALS DISCOVERED
--------------------------------------------------------------------------------

2.1 CTRL NATIVE HANDLES
  - Child Ctrl instances in U++ do NOT have their own HWND (Windows) or NSView (macOS)
  - Only TopWindow has a real native handle
  - Windows : TopWindow::GetHWND() returns the HWND
  - macOS   : TopWindow::GetNSView() returns NSView* (Cocoa)
  - Linux   : TopWindow::gtk() returns GtkWindow* — confirmed from GtkCtrl.h source
  - Linux   : TopWindow::gdk() returns GdkWindow*

2.2 LINUX GTK INTERNALS (from GtkCtrl.h source analysis)
  The macro GUIPLATFORM_CTRL_TOP_DECLS defines these members on TopWindow:
    GtkWidget* window;
    GtkWidget* header;
    GtkWidget* drawing_area;
  However, these are NOT accessible from user code (not public API).

  DEFINITIVE DISCOVERY (from GtkCreate.cpp source):
  U++ does NOT use a GTK container for child Ctrl layout.
  The real widget tree is:
    GtkWindow
      └── GtkDrawingArea  ← U++ draws EVERYTHING here with Cairo
    (with CSD):
    GtkWindow
      ├── GtkHeaderBar
      └── GtkDrawingArea

  Key line in GtkCreate.cpp:
    gtk_container_add(GTK_CONTAINER(top->window), top->drawing_area);

  GtkDrawingArea is NOT a GtkContainer — cannot add child widgets to it.
  This explains why gtk_container_get_children() always returns 0 children,
  and why all attempts to embed WebKitWebView as a GTK child failed.

  THREE OPTIONS for true embedding:
  A) Replace GtkDrawingArea with GtkFixed in GtkCreate.cpp (invasive U++ fork)
  B) GtkOverlay between GtkWindow and GtkDrawingArea (less invasive U++ fork):
       GtkWindow → GtkOverlay → GtkDrawingArea (U++ draws here)
                              → WebKitWebView  (overlay on top)
     Requires adding top->overlay to Win struct in CtrlCore.
  C) Separate GTK_WINDOW_POPUP overlay (zero U++ modifications) ← CURRENT SOLUTION

  top->window   = the GtkWindow* (also returned by gtk())
  top->drawing_area = the GtkDrawingArea* where U++ renders with Cairo
  gdk() returns gtk_widget_get_window(top->window)
  gdk_window_get_user_data(gdk()) returns top->window (the GtkWindow, not drawing_area)

2.3 COORDINATE SYSTEMS
  - U++    : origin top-left, pixels
  - Cocoa  : origin bottom-left, logical points (divide by backingScaleFactor)
  - GTK/X11: origin top-left, pixels (same as U++)
  - Retina : backingScaleFactor = 2.0 on Retina, 1.0 on non-Retina
             U++ uses physical pixels, Cocoa uses logical points
             MUST divide all coordinates by backingScaleFactor for WKWebView

2.4 GETTING SCREEN COORDINATES
  - GetRect()       : coordinates relative to immediate parent Ctrl
  - GetScreenRect() : absolute screen coordinates
  - GetSize()       : size of the Ctrl

--------------------------------------------------------------------------------
3. PLATFORM-SPECIFIC SOLUTIONS
--------------------------------------------------------------------------------

3.1 WINDOWS
  Problem: WebView2LoaderStatic.lib is MSVC-only, incompatible with Clang
  Solution: Use LoadLibrary("WebView2Loader.dll") + GetProcAddress at runtime
            No static linking needed, zero extra dependencies

  Problem: PLATFORM_WIN32 not defined with Clang in U++
  Solution: Use #ifdef _WIN32 (compiler-defined, always works)

  Problem: WString in U++ uses 32-bit wchar, Windows API needs 16-bit wchar_t
  Solution: Use MultiByteToWideChar(CP_UTF8, ...) to convert String to wchar_t

  Problem: Child Ctrl has no HWND
  Solution: GetTopCtrl()->GetHWND() for the parent HWND
            Then create a dedicated child HWND (WS_CHILD|WS_VISIBLE) as WebView2 parent
            WebView2 must be child of an HWND, not directly of the TopWindow HWND

  Problem: WebView2 init is ASYNCHRONOUS (callbacks: EnvHandler -> CtrlHandler)
  Solution: Queue pendingHtml/pendingUrl, apply in CtrlHandler::Invoke when ready
            PostMessage(WM_SIZE) after init to trigger Layout() with correct size

  Printing: window.print() via ExecuteScript opens native Edge print dialog
            Includes Portrait/Landscape, PDF save

  WebView2 bounds: put_Bounds() coordinates are relative to the child HWND,
                   NOT to the TopWindow. Always use {0, 0, w, h}.

3.2 MACOS
  Problem: #import Cocoa.h in same TU as U++ causes type conflicts
           (Font, Time, Display, Point, Rect all conflict between Cocoa and U++)
  Solution: Bridge pattern — separate .mm file with NO U++ includes
            WebViewCtrl_Mac.cpp    : U++ code, includes bridge header only
            WebViewCtrl_Mac_objc.mm: Objective-C++, includes Cocoa/WebKit only
            Bridge uses only C types (void*, int, const char*) — zero conflicts

  Problem: .mm files — does TheIDE compile them as Objective-C++?
  Solution: YES. Clang on macOS automatically compiles .mm as Objective-C++
            No -x objective-c++ flag needed. Just add .mm to the .upp file.

  Problem: Retina display — coordinates are 2x physical pixels
           U++ gives physical pixels, Cocoa wants logical points
           parentBounds.h = 340 while U++ totalH = 680 (exactly 2x)
  Solution: Read backingScaleFactor from [[parent window] backingScaleFactor]
            Divide all coordinates: cx = x/scale, cy = y/scale, etc.
            Then convert Y: cocoaY = parentBounds.h - cy - ch

  Problem: WKWebView init is synchronous but frame must be set after Layout()
  Solution: Create WKWebView with NSZeroRect, NSViewNotSizable
            In Init(): call Layout() first, then ApplyPending()
            This ensures WKWebView has correct frame before content loads

  Printing: [wv printOperationWithPrintInfo:info] with showsPrintPanel=YES
            Use runOperationModalForWindow: (not runOperation) for correct
            integration with existing window event loop
            Portrait/Landscape appears only with a real printer selected;
            with "No Printer Selected" the option is hidden by macOS itself

  GetNSView(): returns NSView* of the TopWindow on macOS (public U++ API)

3.3 LINUX
  Problem: #include <gdk/gdkx.h> after U++ headers causes massive conflicts
           (XLib defines Font, Time, Display, Complex as macros/types)
  Solution: Same bridge pattern as macOS:
            WebViewCtrl_Linux.cpp    : U++ code only
            WebViewCtrl_Linux_gtk.cpp: GTK/X11 code only, no U++ includes
            Compile order does not matter since they are separate TUs

  Problem: Cannot embed WebKitWebView as GTK child of U++ window
           gtk_container_get_children(top->gtk()) returns 0 children always
           U++ does not use GTK widget hierarchy for child Ctrl layout on X11
  Solution: Use GTK_WINDOW_POPUP as overlay window
            Position it over the U++ Ctrl using absolute screen coordinates

  Problem: Popup window does not follow U++ window when moved
  Solution: Connect to "configure-event" signal on top->gtk() (the GtkWindow)
            OnConfigure receives new window position (ev->x, ev->y)
            Store offX/offY = Ctrl screen position - TopWindow screen position
            New popup position = ev->x + offX, ev->y + offY

  Problem: XReparentWindow on WebKitWebView causes segfault
  Reason: WebKit2 uses multi-process architecture with IPC between UI process
          and Web process. The XWindow cannot be reparented after creation
          without breaking this IPC channel.
  Solution: Do NOT use XReparentWindow with WebKit2. Use popup overlay instead.

  Problem: gtk_offscreen_window_new() has no real XWindow
           gtk_widget_get_window() returns null on offscreen windows
  Solution: Use gtk_window_new(GTK_WINDOW_POPUP) positioned at (-10000,-10000)
            This creates a real XWindow that can be found after realize

  Problem: Heap leak reported in Debug mode
  Solution: It is a FALSE POSITIVE. WebKit2 intentionally retains memory
            for its GPU process and web process at shutdown.
            In Release mode the leak check is not performed — no leak reported.
            Can suppress with MemoryIgnoreLeaksBegin/End around app lifetime.

  Problem: Popup window covers the print dialog on Linux
  Solution: Hide popup before webkit_print_operation_run_dialog(), show after.
            run_dialog() is blocking so the popup is restored only when the
            user closes the print dialog. CONFIRMED WORKING.

  Problem: GTK_WINDOW_POPUP always stays on top of other applications
  Reason:  POPUP windows are not managed by the window manager — they ignore
           gdk_window_raise() and gdk_window_lower() completely.
  Solution: Use GTK_WINDOW_TOPLEVEL with GDK_WINDOW_TYPE_HINT_UTILITY instead.
            Utility windows ARE managed by the WM and respect z-order calls.
            Combined with focus-in-event/focus-out-event on the U++ GtkWindow:
              OnFocusIn  → gdk_window_raise(popup)  — bring up with U++ app
              OnFocusOut → gdk_window_lower(popup)  — lower when U++ loses focus
            CONFIRMED WORKING on Wayland (XWayland session).
  gdk_window_get_user_data(gdkwin, &data) returns the associated GtkWidget*
  which is a GtkWindow (not GtkFixed) on X11.

  webkit2gtk-4.1: deprecated API webkit_web_view_run_javascript()
  Use webkit_web_view_evaluate_javascript() for WEBKIT_CHECK_VERSION >= 2.40.0

  pkg-config is needed for header paths. Add to .upp options:
    "`pkg-config --cflags webkit2gtk-4.1`"

--------------------------------------------------------------------------------
4. THINGS STILL UNKNOWN / WAITING FOR FORUM RESPONSE
--------------------------------------------------------------------------------

  - The correct official way to embed a GtkWidget as child of a U++ Ctrl on Linux.
    DHCtrl (GtkDHCtrl) exists in some U++ projects but uses X11/Xlib directly
    and its GTK implementation is reportedly unfinished ("draft with undefined symbols").
  - Whether there is a supported API to get the drawing_area GtkWidget from outside.
  - Whether SetupWidget() mentioned in forum analysis is a real U++ API.

--------------------------------------------------------------------------------
5. DEPENDENCIES SUMMARY
--------------------------------------------------------------------------------

  Windows : WebView2Loader.dll (ships with Edge, preinstalled on Win10/11)
            WebView2.h from NuGet package Microsoft.Web.WebView2
            No static lib needed — loaded via LoadLibrary at runtime
            Compiler: CLANG (MSC incompatible with our approach)

  macOS   : WebKit.framework (preinstalled on every macOS)
            Link: -framework WebKit (Cocoa already linked by U++)
            Compiler: Clang (standard on macOS)

  Linux   : libwebkit2gtk-4.1-dev (apt install libwebkit2gtk-4.1-dev)
            pkg-config --cflags webkit2gtk-4.1 for include paths
            Include: <webkitgtk-4.1/webkit2/webkit2.h>
            Compiler: Clang or GCC

--------------------------------------------------------------------------------
6. TEST APPLICATION
--------------------------------------------------------------------------------

  main.cpp implements WebViewTestWindow with:
  - URL bar + "Go" button (detects local file paths vs URLs)
  - "Open" button using SelectFileOpen() for local HTML files
  - Central WebViewCtrl
  - Status bar with "Stampa/PDF", "Reload", "Close" buttons

  Runtime on Windows: copy WebView2Loader.dll to the exe directory.

================================================================================