You are working on the current GLDoze repository after the first X11 isolation pass.

The existing implementation already contains components including approximately:

```text
DesktopShell
DesktopX11WindowManager
DesktopX11Embedder
DesktopNativeGLSurface
X11Surface
desktop_x11_surface_input_test
desktop_x11_window_manager_test
```

The previous refactor successfully isolated a meaningful amount of X11 functionality, but `DesktopShell` and `DesktopNativeGLSurface` still know too much about X11.

This task is the **second platform abstraction pass**.

The objective is to make the GLDoze desktop core genuinely platform-neutral so that a Wayland backend can be implemented next without another major rearchitecture.

Do NOT implement the full Wayland compositor in this pass.

However, perform all reasonable architectural, CMake, interface, factory, testing and scaffolding work required so that implementing Wayland afterward is a clean backend implementation task.

---

# PRIMARY TARGET ARCHITECTURE

The resulting architecture should conceptually be:

```text
                         GLDoze Desktop
                              |
                              v
                         DesktopShell
                              |
                              v
                  DesktopPlatformBackend
                    /                  \
                   /                    \
                  v                      v
        DesktopX11Backend       DesktopWaylandBackend
               |                       |
       X11 window management     Wayland compositor
       X11 monitor discovery     wl_output handling
       X11 shortcuts             Wayland/libinput input
       X11 integration           xdg-shell handling
```

Native GL surfaces should separately become:

```text
               DesktopNativeGLSurface
                         |
                         v
                 INativeGLSurface
                    /          \
                   /            \
                  v              v
             X11Surface     WaylandSurface
```

The important rule is:

```text
DesktopShell
Desktop widgets
GLDoze applications
Verdant
GLDeck
terminal
developer console
etc.

MUST NOT care whether the session is X11 or Wayland.
```

The platform backend owns native desktop integration.

---

# CRITICAL DEPENDENCY RULE

After this task, platform-neutral desktop code must not directly include or expose:

```text
X11/Xlib.h
X11/Xatom.h
X11/keysym.h
X11/extensions/*
xcb/*
wl_*
wayland-client*
wayland-server*
```

unless that source file belongs specifically to a platform backend.

Likewise, public desktop-core APIs must not expose:

```text
Window
Display*
Atom
XID
KeySym
unsigned long X11 window IDs
```

as platform identifiers.

GLDoze must own neutral identifier and data types.

---

# FIRST: AUDIT THE CURRENT IMPLEMENTATION

Before changing architecture:

1. Build the current repository.
2. Identify all desktop targets.
3. Identify every file containing X11 headers.
4. Identify every use of:

   * `DesktopX11WindowManager`
   * `DesktopX11Embedder`
   * `X11Surface`
   * X11 `Window`
   * `Display*`
   * X11 monitor structures
   * X11 keyboard symbols
   * X11 global shortcuts
5. Identify all places `DesktopShell` talks directly to X11 classes.
6. Identify all X11 data types leaking through public APIs.
7. Identify where native OpenGL surfaces are created.
8. Identify which native surfaces are used by:

   * terminal
   * developer console
   * dropdown terminal
   * native GL applications
9. Identify the existing render ABI and OpenGL context ownership.
10. Identify X11-specific CMake dependencies.
11. Identify existing compile definitions such as:

* `GLDOZE_DESKTOP_X11_EMBED`
* `GLDOZE_DESKTOP_X11_WM`

12. Run current X11-related tests.

Record the findings internally before making changes.

This is an architectural refactor, not a rewrite.

Preserve current X11 behavior.

---

# PHASE 1 — INTRODUCE GLDOZE-OWNED PLATFORM TYPES

Create neutral desktop types.

Adapt naming to existing repository conventions.

For example:

```cpp
namespace gldoze::desktop {

using DesktopWindowId = std::uint64_t;
using DesktopMonitorId = std::uint64_t;

struct DesktopRect {
    int x = 0;
    int y = 0;
    int width = 0;
    int height = 0;
};

enum class DesktopWindowState {
    Normal,
    Minimized,
    Maximized,
    Fullscreen
};

struct DesktopWindowInfo {
    DesktopWindowId id = 0;

    std::string title;
    std::string applicationName;

    DesktopRect geometry;

    DesktopWindowState state = DesktopWindowState::Normal;

    bool focused = false;
    bool visible = true;
    bool resizable = true;
};

struct DesktopMonitorInfo {
    DesktopMonitorId id = 0;

    std::string name;

    DesktopRect geometry;
    DesktopRect workArea;

    float scale = 1.0f;

    bool primary = false;

    float refreshRateHz = 0.0f;
};

}
```

Use whatever additional fields the current implementation genuinely requires.

Do not blindly expose X11 concepts.

If an X11 value must temporarily be retained internally, keep the mapping private inside the X11 backend:

```text
DesktopWindowId -> X11 Window
```

For example:

```cpp
std::unordered_map<DesktopWindowId, ::Window> NativeWindows;
```

or use a reversible conversion internally if appropriate.

Do not make an XID the public GLDoze API.

---

# PHASE 2 — CREATE DESKTOP PLATFORM INTERFACE

Introduce a neutral interface such as:

```cpp
class IDesktopPlatformBackend
{
public:
    virtual ~IDesktopPlatformBackend() = default;

    virtual bool Initialize() = 0;
    virtual void Shutdown() = 0;

    virtual void PollEvents() = 0;
    virtual void Update() = 0;

    virtual std::vector<DesktopWindowInfo> Windows() const = 0;
    virtual std::vector<DesktopMonitorInfo> Monitors() const = 0;

    virtual bool FocusWindow(DesktopWindowId id) = 0;
    virtual bool CloseWindow(DesktopWindowId id) = 0;

    virtual bool MinimizeWindow(DesktopWindowId id) = 0;
    virtual bool RestoreWindow(DesktopWindowId id) = 0;
    virtual bool ToggleMaximizeWindow(DesktopWindowId id) = 0;

    virtual bool ActivateDesktop() = 0;

    virtual bool SupportsExternalWindowManagement() const = 0;

    virtual const char* BackendName() const noexcept = 0;
};
```

Do not copy this exact API blindly.

Inspect what `DesktopShell` actually needs and design the smallest useful interface.

Potential additional responsibilities include:

```text
global shortcuts
clipboard
cursor
desktop activation
monitor topology
external application windows
focus handling
native window events
```

Keep these cohesive.

If one interface becomes too large, use focused services such as:

```text
IDesktopPlatformBackend
IDesktopWindowManager
IDesktopMonitorProvider
IDesktopGlobalShortcutProvider
```

but do not overengineer unnecessarily.

The key goal is that `DesktopShell` talks only to neutral APIs.

---

# PHASE 3 — INTRODUCE DESKTOP PLATFORM FACTORY

Create one controlled place where the active backend is selected.

For example:

```cpp
enum class DesktopBackendType
{
    Auto,
    X11,
    Wayland
};

std::unique_ptr<IDesktopPlatformBackend>
CreateDesktopPlatformBackend(
    DesktopBackendType requested,
    const DesktopPlatformCreateInfo& info);
```

Support at minimum:

```text
Auto
X11
```

Prepare the enumeration for Wayland.

`Auto` should detect the environment sensibly.

For example, on Linux it may inspect:

```text
WAYLAND_DISPLAY
XDG_SESSION_TYPE
DISPLAY
```

but avoid fragile assumptions.

If both exist because an application is under XWayland, choose the actual intended GLDoze session backend rather than merely checking `DISPLAY`.

Allow an explicit override.

For example:

```text
gldoze_desktop --backend=x11
gldoze_desktop --backend=wayland
```

or an existing GLDoze configuration mechanism.

If command-line parsing architecture already exists, integrate with it.

Do not implement the actual Wayland backend yet.

If `--backend=wayland` is selected while Wayland support is not built, fail clearly with an actionable message.

Example:

```text
Wayland backend requested but this build does not include Wayland support.
```

---

# PHASE 4 — CREATE DESKTOP X11 BACKEND

Create:

```text
DesktopX11Backend
```

or equivalent.

It should implement `IDesktopPlatformBackend`.

Move/coordinate the existing:

```text
DesktopX11WindowManager
DesktopX11Embedder
X11 shortcut support
X11 monitor discovery
```

behind this backend.

Do NOT necessarily merge all existing X11 classes into one giant source file.

It is acceptable and preferable to retain:

```text
DesktopX11Backend
    |
    +-- DesktopX11WindowManager
    +-- DesktopX11Embedder
    +-- DesktopX11GlobalShortcuts
    +-- X11 monitor helpers
```

if this matches current architecture.

The new backend acts as the public X11 adapter.

The desktop core should not reach behind it.

---

# PHASE 5 — REMOVE X11 FROM DESKTOPSHELL

This is one of the most important completion requirements.

Currently `DesktopShell` apparently owns objects similar to:

```cpp
DesktopX11Embedder X11Embedder;
DesktopX11WindowManager X11WindowManager;
```

Remove this direct ownership.

Replace it with platform-neutral ownership such as:

```cpp
std::unique_ptr<IDesktopPlatformBackend> PlatformBackend;
```

or equivalent.

After this phase, `desktop_shell.h` must not include:

```cpp
desktop_x11_window_manager.h
desktop_x11_embedder.h
X11/*
```

Its public methods must not return:

```cpp
DesktopX11WindowManager::WindowInfo
DesktopX11WindowManager::DisplayMonitorInfo
```

Replace those with:

```cpp
DesktopWindowInfo
DesktopMonitorInfo
```

or neutral equivalents.

Search thoroughly for X11-specific type leakage.

---

# PHASE 6 — FIX NATIVE SURFACE ABSTRACTION

`DesktopNativeGLSurface` is currently named generically but internally owns an X11-specific `X11Surface`.

Fix this architecture.

Create a true native-surface interface.

For example:

```cpp
class INativeGLSurface
{
public:
    virtual ~INativeGLSurface() = default;

    virtual bool Initialize(
        const NativeSurfaceCreateInfo& info) = 0;

    virtual void Shutdown() = 0;

    virtual void Show() = 0;
    virtual void Hide() = 0;

    virtual void SetPosition(int x, int y) = 0;
    virtual void Resize(int width, int height) = 0;

    virtual void MakeCurrent() = 0;
    virtual void SwapBuffers() = 0;

    virtual bool IsVisible() const = 0;

    virtual int Width() const = 0;
    virtual int Height() const = 0;

    virtual const char* BackendName() const noexcept = 0;
};
```

Again, adapt this to actual GLDoze requirements.

Do not introduce API methods merely because they appear in this prompt.

---

# PHASE 7 — CREATE NATIVE SURFACE FACTORY

Add a factory:

```cpp
std::unique_ptr<INativeGLSurface>
CreateNativeGLSurface(
    DesktopBackendType backend,
    const NativeSurfaceCreateInfo& info);
```

For now:

```text
X11 -> X11Surface
```

Later:

```text
Wayland -> WaylandSurface
```

`DesktopNativeGLSurface` should become a controller/wrapper around `INativeGLSurface`.

Conceptually:

```text
DesktopNativeGLSurface
        |
        v
INativeGLSurface
        |
        +---- X11Surface
        |
        +---- WaylandSurface      future
```

The terminal and developer console should continue creating `DesktopNativeGLSurface`.

They must not instantiate `X11Surface` themselves.

---

# PHASE 8 — REMOVE X11 INPUT TRANSLATION FROM GENERIC SURFACE CODE

The current generic layer apparently contains logic such as:

```cpp
SDLKeyFromX11KeySym(...)
```

This belongs in the X11 implementation.

Move X11 input translation into:

```text
X11Surface
```

or an X11 input translation helper.

The output should use GLDoze-owned neutral input.

For example:

```text
X11 KeySym
   ↓
X11 input translator
   ↓
GLDoze key/input event
```

Future:

```text
Wayland/xkbcommon key
   ↓
Wayland input translator
   ↓
same GLDoze key/input event
```

The generic surface controller must not know what a `KeySym` is.

---

# PHASE 9 — DEFINE NEUTRAL NATIVE-SURFACE INPUT

Reuse existing GLDoze input structures where appropriate.

Do not create duplicate input systems.

If necessary, establish a small native surface input contract such as:

```cpp
struct NativePointerEvent
{
    float x = 0.0f;
    float y = 0.0f;

    float deltaX = 0.0f;
    float deltaY = 0.0f;
};

struct NativeKeyEvent
{
    GLDozeKey key = GLDozeKey::Unknown;

    bool pressed = false;
    bool repeated = false;
};

struct NativeTextInputEvent
{
    std::string utf8;
};

struct NativeFocusEvent
{
    bool focused = false;
};
```

Do not expose:

```text
KeySym
XKeyEvent
XButtonEvent
SDL native events
Wayland event structs
```

to the generic surface layer.

---

# PHASE 10 — KEEP DESKTOPX11EMBEDDER X11-SPECIFIC

Do NOT overgeneralize `DesktopX11Embedder`.

It apparently provides functionality based on:

```text
XComposite
X pixmaps
X11 reparenting
external X11 window capture
X11 input forwarding
```

This is fundamentally X11/XWayland technology.

Keep it explicitly named and implemented as:

```text
DesktopX11Embedder
```

It should simply live behind `DesktopX11Backend`.

Do NOT rename it `DesktopWindowEmbedder` and pretend the same architecture applies to Wayland.

For Wayland, GLDoze will eventually own native application surfaces as compositor objects instead.

That difference should be explicitly documented.

---

# PHASE 11 — DISTINGUISH EXTERNAL WINDOW MODEL FROM WAYLAND SURFACES

Create architecture that does not assume every externally displayed application is an X11 window ID.

For neutral desktop UI, define:

```cpp
DesktopWindowId
DesktopWindowInfo
```

The X11 backend maps that to X11 `Window`.

The future Wayland backend will map it to something such as:

```text
xdg_toplevel
wl_surface
GLDoze compositor window object
```

Do not make neutral desktop code understand these native objects.

---

# PHASE 12 — MONITOR ABSTRACTION

Remove XRandR/X11 monitor types from `DesktopShell`.

Expose only neutral:

```cpp
DesktopMonitorInfo
```

Include fields currently useful to GLDoze such as:

```text
logical geometry
pixel dimensions if needed
work area
scale
refresh rate
primary monitor
display name
```

The X11 implementation can use XRandR.

The future Wayland backend will use:

```text
wl_output
xdg-output if appropriate
fractional scale protocols if eventually supported
```

Do not attempt Wayland monitor implementation in this task.

---

# PHASE 13 — GLOBAL SHORTCUT ABSTRACTION

Current GLDoze apparently includes native global X11 shortcuts.

Put these behind a neutral API.

For example:

```cpp
enum class DesktopGlobalAction
{
    OpenStartMenu,
    OpenTerminal,
    OpenDeveloperConsole,
    ActivateDesktop,
    Screenshot
};
```

Then platform code maps native shortcuts to GLDoze actions.

Avoid leaking raw X11 keycodes or modifiers into DesktopShell.

Do not build an unnecessarily complex configurable shortcut framework unless GLDoze already has one.

Preserve current behavior.

---

# PHASE 14 — CLIPBOARD BOUNDARY

If clipboard operations currently call X11 directly from desktop/core code, move them behind a neutral abstraction now.

For example:

```cpp
class IDesktopClipboard
{
public:
    virtual ~IDesktopClipboard() = default;

    virtual bool SetText(std::string_view text) = 0;
    virtual std::string GetText() = 0;
};
```

Only do this if clipboard support currently exists or X11 access leaks into core code.

Do not implement speculative functionality unnecessarily.

---

# PHASE 15 — CURSOR AND POINTER BOUNDARY

Likewise, identify:

```text
cursor visibility
cursor shape
pointer capture
pointer confinement
relative mouse mode
```

If any of these are currently implemented directly in core desktop code using X11, move them behind platform/surface interfaces.

This will matter significantly for Wayland.

Do not redesign working cursor behavior.

---

# PHASE 16 — PLATFORM CAPABILITIES

Add a small capabilities mechanism rather than testing concrete backend types.

For example:

```cpp
struct DesktopPlatformCapabilities
{
    bool canManageExternalWindows = false;
    bool canEmbedX11Windows = false;

    bool supportsGlobalShortcuts = false;
    bool supportsNativeGLSurfaces = false;

    bool isCompositor = false;
};
```

Then generic code can do:

```cpp
if (platform.Capabilities().canManageExternalWindows)
```

instead of:

```cpp
if (dynamic_cast<DesktopX11Backend*>(...))
```

Do not scatter backend-type checks throughout desktop core.

---

# PHASE 17 — CMAKE REARCHITECTURE

The current desktop support target apparently links X11 directly.

Split platform-neutral code from X11-specific implementation.

Target architecture should resemble:

```text
gldoze_desktop_core
        |
        +---- gldoze_desktop_x11
        |
        +---- gldoze_desktop_wayland      future
```

or use names that match existing project conventions.

The core target must not require X11.

Introduce options such as:

```cmake
option(
    GLDOZE_ENABLE_X11
    "Build GLDoze X11 desktop backend"
    ON
)

option(
    GLDOZE_ENABLE_WAYLAND
    "Build GLDoze Wayland desktop backend"
    OFF
)
```

Wayland may remain OFF initially because the backend is not implemented yet.

Do not require Wayland dependencies in a normal X11-only build.

Change:

```cmake
find_package(X11 REQUIRED)
```

from unconditional global configuration into the X11-specific branch.

For example:

```cmake
if(GLDOZE_ENABLE_X11)
    find_package(X11 REQUIRED)

    add_library(gldoze_desktop_x11
        ...
    )

    target_link_libraries(
        gldoze_desktop_x11
        PRIVATE
            gldoze_desktop_core
            X11::X11
            X11::Xcomposite
            X11::Xext
            PkgConfig::XFT
    )
endif()
```

Do not use global include directories.

Use target-scoped dependencies.

---

# PHASE 18 — PREPARE WAYLAND DEPENDENCY DISCOVERY

Do not implement the Wayland backend yet.

However, create clean CMake scaffolding so it can be added next.

For example:

```cmake
if(GLDOZE_ENABLE_WAYLAND)

    pkg_check_modules(
        WAYLAND_SERVER
        REQUIRED
        wayland-server
    )

    pkg_check_modules(
        XKBCOMMON
        REQUIRED
        xkbcommon
    )

    ...
endif()
```

Only add dependencies that are clearly expected for the planned implementation.

Likely future components include:

```text
wayland-server
wayland-protocols
xkbcommon
libinput
libudev
EGL
GBM
DRM
```

But do NOT make all of these required prematurely.

Document likely requirements instead if implementation has not started.

---

# PHASE 19 — OPTIONAL WAYLAND BACKEND STUB

If it improves compile-time architecture validation, create a minimal:

```text
DesktopWaylandBackend
```

that implements the neutral backend interface but returns a clear unsupported/not-yet-implemented result.

For example:

```cpp
bool DesktopWaylandBackend::Initialize()
{
    LogError(
        "Wayland backend architecture is present but compositor "
        "implementation has not yet been implemented.");

    return false;
}
```

Only compile this when:

```text
GLDOZE_ENABLE_WAYLAND
```

is enabled.

This stub should NOT pretend to be a functioning compositor.

Its purpose is simply to verify that DesktopShell can compile against a non-X11 backend.

If a cleaner approach is to leave the implementation entirely absent until the next pass, that is acceptable.

Prioritize clean architecture over ceremonial placeholder code.

---

# PHASE 20 — COMPILATION BOUNDARY TEST

This is extremely important.

Add a build/test configuration proving the desktop core can compile **without X11 headers or libraries**.

For example:

```text
GLDOZE_ENABLE_X11=OFF
```

should still allow:

```text
gldoze_desktop_core
```

and platform-neutral tests to compile.

The complete executable may reasonably require at least one backend.

But the core library itself must compile without X11.

This is one of the strongest tests that the abstraction is real.

---

# PHASE 21 — PLATFORM HEADER LEAK TEST

Where practical, create a source-level or CMake test that verifies platform-neutral directories do not include X11 headers.

At minimum manually search:

```bash
grep -R "#include <X11" ...
grep -R "#include \"X11" ...
```

and report results.

The acceptable X11 references should exist only within clearly X11-specific directories/files.

Likewise search public headers for:

```text
Display*
Window
Atom
KeySym
XEvent
```

and remove leakage where appropriate.

Be careful with generic English words such as `Window`; only identify actual X11 types.

---

# PHASE 22 — TEST X11 BEHAVIOR AFTER EACH MAJOR STEP

The X11 implementation must remain the reference backend.

Test:

```text
desktop startup
desktop shutdown
panel
start menu
external window enumeration
external window focus
minimize
restore
maximize
close
monitor enumeration
multi-monitor behavior if supported
global shortcuts
terminal
developer console
native GL surfaces
mouse input
keyboard input
text input
focus
resize
X11 embedder
GL rendering
plugin applications
```

Do not change visual design.

Do not alter desktop behavior unless correcting an abstraction bug.

---

# PHASE 23 — EXTEND UNIT TESTS

Retain the existing:

```text
desktop_x11_surface_input_test
desktop_x11_window_manager_test
```

and expand test coverage around neutral contracts.

Useful tests may include:

```text
DesktopShell does not require concrete X11 manager
neutral window ID mapping
neutral monitor conversion
native surface input translation
platform factory selection
backend override handling
backend capability handling
surface factory behavior
backend unavailable error handling
```

Use mock/fake platform backends where helpful.

For example:

```cpp
class FakeDesktopPlatformBackend final
    : public IDesktopPlatformBackend
{
    ...
};
```

This should allow significant DesktopShell testing without X11.

---

# PHASE 24 — MAKE DESKTOPSHELL TESTABLE WITHOUT X11

Allow injection of a platform backend where practical.

For example:

```cpp
DesktopShell(
    CoreSDL* sdl,
    std::unique_ptr<IDesktopPlatformBackend> backend);
```

or provide a create-info structure.

Avoid making tests depend on environment detection.

Production can use the factory.

Tests can inject a fake backend.

---

# PHASE 25 — OPENGL CONTEXT OWNERSHIP REVIEW

Document and cleanly establish:

```text
Who creates the primary GLDoze OpenGL context?
Who owns it?
Who swaps the primary desktop?
Who creates secondary native GL surfaces?
Are contexts shared?
Who destroys them?
```

This is important because the Wayland implementation will eventually use EGL/Wayland or another appropriate context path.

Do not rewrite the OpenGL renderer.

Just ensure native context/window ownership is not accidentally embedded throughout generic desktop code.

If necessary, introduce a narrow native graphics-context abstraction.

Only do so if current coupling justifies it.

---

# PHASE 26 — PRESERVE SDL ROLE

GLDoze currently uses SDL.

Do not remove SDL merely because Wayland will be implemented later.

Determine exactly what SDL currently provides:

```text
OpenGL loading
input
window
audio
timing
clipboard
joystick
etc.
```

Keep SDL where it is useful and platform-neutral.

However, do not force Wayland compositor functionality through SDL if SDL cannot provide the required compositor/server features.

The likely future architecture may be:

```text
GLDoze application/runtime
    |
    +---- SDL services where appropriate
    |
    +---- native X11 backend
    |
    +---- native Wayland compositor backend
```

Document this clearly.

---

# PHASE 27 — XWAYLAND PREPARATION

Do not implement XWayland management yet unless trivial support already exists.

However, document the future architecture.

When GLDoze runs as a Wayland compositor, legacy X11 applications will likely require:

```text
XWayland
```

The expected future path should be conceptually:

```text
Native Wayland app
       |
       v
GLDoze Wayland compositor
       |
       v
GLDoze scene


X11 application
       |
       v
XWayland
       |
       v
GLDoze Wayland compositor
       |
       v
GLDoze scene
```

Do not assume `DesktopX11Embedder` is automatically the final XWayland strategy.

Document that this will require a dedicated integration pass.

---

# PHASE 28 — DOCUMENT EXPECTED WAYLAND ARCHITECTURE

Add an architecture document such as:

```text
docs/desktop-platform-backends.md
```

or use the repository's existing documentation structure.

Explain:

## Shared Desktop Core

```text
DesktopShell
desktop widgets
desktop applications
window metadata
monitor metadata
neutral input
backend capabilities
```

## X11 Backend

```text
X11 window management
XRandR
XComposite
global X11 shortcuts
external X11 windows
X11 native GL surfaces
```

## Future Wayland Backend

Expected responsibilities:

```text
Wayland server/compositor initialization
wl_display
wl_event_loop
wl_compositor
wl_output
wl_seat
keyboard
pointer
xdg-shell
xdg_toplevel
surface lifecycle
buffer commits
damage
focus
window positioning policy
GLDoze scene integration
```

Potential later protocol support:

```text
xdg-decoration
relative-pointer
pointer-constraints
viewporter
fractional-scale
presentation-time
linux-dmabuf
idle-inhibit
layer-shell where appropriate
data-device clipboard/drag-and-drop
```

Do not implement these protocols in this task.

This documentation is intended to guide the next implementation pass.

---

# PHASE 29 — DO NOT OVERABSTRACT RENDERING

Do not create a giant generic renderer abstraction merely because X11 and Wayland differ.

The GLDoze OpenGL scene renderer should remain largely unchanged.

The platform backend should handle:

```text
native display
native surface
native context integration where necessary
external/native application surfaces
input
monitors
window management
```

The renderer should continue rendering GLDoze geometry through its existing architecture.

Preserve the current render ABI.

---

# PHASE 30 — AVOID PLATFORM IFDEF POLLUTION

One of the major goals is to prevent this architecture:

```cpp
#ifdef GLDOZE_X11
...
#elif GLDOZE_WAYLAND
...
#endif
```

appearing throughout:

```text
DesktopShell
desktop widgets
applications
terminal
GLDeck
Verdant
settings
start menu
panel
```

Platform conditionals belong in:

```text
backend factory
X11 backend
Wayland backend
native platform implementation files
```

Some build-level conditionals are unavoidable.

Application-level conditionals are not acceptable unless clearly justified.

---

# PHASE 31 — LOG ACTIVE PLATFORM BACKEND

At startup, clearly log something similar to:

```text
Desktop platform backend: X11
```

Future:

```text
Desktop platform backend: Wayland
```

Also report useful capabilities:

```text
External native window management: yes
Native GL surfaces: yes
Global shortcuts: yes
Compositor mode: no
```

Do not spam logs.

---

# PHASE 32 — ERROR HANDLING

Backend initialization failures must produce useful diagnostics.

Examples:

```text
Unable to initialize X11 backend: DISPLAY is not available.
```

```text
XComposite extension is required but unavailable.
```

```text
Requested backend 'wayland' was not built.
```

Avoid generic:

```text
Initialization failed.
```

unless accompanied by the actual underlying error.

---

# PHASE 33 — LIFECYCLE

Define and preserve clear lifecycle ordering:

```text
Create backend
    ↓
Initialize backend
    ↓
Initialize DesktopShell
    ↓
Run event/update/render loop
    ↓
Shutdown DesktopShell
    ↓
Shutdown backend
    ↓
Destroy backend
```

For native surfaces:

```text
Create surface
    ↓
Initialize native surface
    ↓
create/use GL context
    ↓
render
    ↓
destroy GL resources
    ↓
destroy native surface/context
```

Ensure native resources are destroyed while required display/context objects remain valid.

---

# PHASE 34 — NO BEHAVIORAL REWRITE

Do not change:

```text
window decorations
panel appearance
start menu appearance
input bindings
terminal appearance
GL rendering style
external window behavior
desktop layout
status bar
existing application behavior
```

except where necessary to preserve existing behavior after abstraction.

This task is infrastructure.

---

# PHASE 35 — CODE ORGANIZATION

Prefer a structure similar to:

```text
desktop/
├── core/
│   ├── desktop_shell.*
│   ├── desktop_platform.*
│   ├── desktop_platform_types.*
│   ├── desktop_backend_factory.*
│   ├── desktop_native_gl_surface.*
│   └── ...
│
├── platform/
│   ├── x11/
│   │   ├── desktop_x11_backend.*
│   │   ├── desktop_x11_window_manager.*
│   │   ├── desktop_x11_embedder.*
│   │   ├── x11_surface.*
│   │   ├── x11_input.*
│   │   └── ...
│   │
│   └── wayland/
│       └── future / optional stub
```

Do not force directory movement if existing repository structure makes another layout cleaner.

The architectural boundary matters more than directory aesthetics.

---

# PHASE 36 — BUILD MODES TO VERIFY

At minimum verify:

## Normal X11 build

```text
GLDOZE_ENABLE_X11=ON
GLDOZE_ENABLE_WAYLAND=OFF
```

Expected:

```text
desktop core builds
X11 backend builds
gldoze_desktop builds
tests build
X11 session works
```

## Core-only platform test

```text
GLDOZE_ENABLE_X11=OFF
GLDOZE_ENABLE_WAYLAND=OFF
```

Expected:

```text
desktop core library builds
platform-neutral tests build
```

The final desktop executable may be disabled in this configuration because no backend exists.

This is acceptable.

## Optional backend architecture test

If a Wayland stub is added:

```text
GLDOZE_ENABLE_X11=OFF
GLDOZE_ENABLE_WAYLAND=ON
```

The architecture should compile as far as appropriate.

The stub should fail gracefully at runtime rather than pretending to be complete.

---

# PHASE 37 — RUN STATIC SEARCHES AFTER REFACTOR

Perform searches for:

```text
X11
Xlib
XComposite
XRandR
KeySym
XEvent
Display*
Atom
::Window
DesktopX11WindowManager
DesktopX11Embedder
X11Surface
```

Classify every remaining occurrence.

The expected result is:

```text
X11-specific files       -> allowed
X11-specific tests       -> allowed
backend factory          -> backend name references allowed
documentation            -> allowed
desktop-neutral core     -> no native X11 types/includes
```

Report any intentional exceptions.

---

# PHASE 38 — TEST TERMINAL AND DEVELOPER CONSOLE CAREFULLY

Because native GL surfaces are used here, specifically test:

```text
open
close
show
hide
focus
unfocus
move
resize
keyboard
mouse
text entry
OpenGL rendering
context sharing
repeated open/close
application shutdown while surface exists
```

Ensure `DesktopNativeGLSurface` no longer contains X11-specific implementation details.

---

# PHASE 39 — DO NOT BREAK PLUGIN APPLICATIONS

Test representative GLDoze applications and plugins after refactor.

Particularly test applications that interact strongly with rendering or native desktop surfaces.

Examples from the project may include:

```text
Verdant
GLDeck
terminal
developer console
browser
plugin manager
profiler
```

Do not modify those applications unless necessary to replace a platform-specific API with the new neutral API.

---

# PHASE 40 — PREPARE FOR NEXT WAYLAND PASS

At the end of this refactor, the following should be true:

```text
DesktopShell
    ↓
IDesktopPlatformBackend
    ↓
DesktopX11Backend
```

and:

```text
DesktopNativeGLSurface
    ↓
INativeGLSurface
    ↓
X11Surface
```

The next task should therefore be able to begin with:

```text
Implement DesktopWaylandBackend
Implement WaylandSurface
```

without modifying `DesktopShell` architecture again.

That is the primary success metric.

---

# IMPORTANT DESIGN PRINCIPLE

Do NOT attempt to make X11 and Wayland look identical internally.

They are not.

X11 mode:

```text
X server
   ↓
GLDoze window manager
   ↓
DesktopX11WindowManager
```

Wayland mode:

```text
GLDoze
   ↓
Wayland compositor/server
   ↓
client surfaces
```

The abstraction should unify what `DesktopShell` needs, not artificially unify the native implementation details.

This distinction is critical.

---

# BUILD AND VALIDATION REQUIREMENTS

Before finishing:

1. Perform a clean configure.
2. Perform a clean build.
3. Build all changed targets.
4. Run unit tests.
5. Run X11 desktop manually if runtime is available.
6. Open terminal.
7. Open developer console.
8. Exercise external window management.
9. Exercise input.
10. Exercise monitor enumeration.
11. Exercise global shortcuts.
12. Check GL rendering.
13. Shut down cleanly.
14. Rebuild core with X11 disabled.
15. Search neutral code for X11 leakage.
16. Fix warnings introduced by this work.
17. Do not hide failures by disabling tests.

---

# REQUIRED FINAL ARCHITECTURE REPORT

When the task is complete, provide a detailed report.

Include:

## 1. Original coupling discovered

List all important locations where:

```text
DesktopShell depended on X11
native surface code depended on X11
public APIs exposed X11
CMake required X11
```

## 2. New architecture

Show the actual resulting dependency graph.

Example:

```text
gldoze_desktop
       |
       v
gldoze_desktop_core
       |
       v
IDesktopPlatformBackend
       |
       +---- DesktopX11Backend
       |
       +---- DesktopWaylandBackend (future)
```

and:

```text
DesktopNativeGLSurface
       |
       v
INativeGLSurface
       |
       +---- X11Surface
       |
       +---- WaylandSurface (future)
```

## 3. Files created

List and explain them.

## 4. Files moved

List and explain them.

## 5. Files modified

Summarize major changes.

## 6. DesktopShell changes

Explain exactly how X11 knowledge was removed.

## 7. Neutral types introduced

Document:

```text
DesktopWindowId
DesktopWindowInfo
DesktopMonitorInfo
capabilities
input structures
```

or actual equivalents.

## 8. X11 backend

Explain how existing:

```text
DesktopX11WindowManager
DesktopX11Embedder
X11Surface
```

fit behind the new boundary.

## 9. Native GL surface architecture

Explain lifecycle and input translation.

## 10. Backend selection

Explain:

```text
Auto
X11
Wayland
```

behavior.

## 11. CMake changes

Document options and target graph.

## 12. Tests

List new and existing tests run.

## 13. Runtime validation

Describe behavior tested.

## 14. Remaining X11 references

List any X11-specific references outside platform directories and justify them.

## 15. Wayland readiness

Explicitly state what is now ready for the Wayland implementation.

## 16. Remaining Wayland prerequisites

Identify likely next dependencies and implementation components.

## 17. Recommended next implementation sequence

Give a concrete next-pass plan, likely beginning with:

```text
Wayland server initialization
wl_display
event loop
wl_compositor
wl_output
wl_seat
xkbcommon
xdg-shell
basic xdg_toplevel window
surface-to-GLDoze scene integration
```

---

# COMPLETION CRITERIA

Do not call this task complete unless all reasonable criteria below are met:

* `DesktopShell` no longer owns `DesktopX11WindowManager`.
* `DesktopShell` no longer owns `DesktopX11Embedder`.
* `DesktopShell` does not expose X11-specific public types.
* `DesktopShell` does not include X11 headers.
* `DesktopNativeGLSurface` no longer directly owns `X11Surface` as its hardcoded implementation.
* X11 key translation is no longer in generic native-surface code.
* Neutral window metadata exists.
* Neutral monitor metadata exists.
* Neutral backend interface exists.
* X11 backend implements the neutral interface.
* Native surface interface exists.
* X11 native surface implements that interface.
* Backend selection is centralized.
* X11 dependencies are isolated in CMake.
* X11 can be disabled when compiling platform-neutral desktop core.
* Existing X11 desktop behavior remains operational.
* Existing X11 tests remain operational.
* New neutral-interface tests exist where appropriate.
* Architecture documentation describes the future Wayland backend.
* No full Wayland compositor implementation is attempted in this pass.
* The next pass can implement Wayland without another major DesktopShell refactor.

---

# FINAL INSTRUCTION

Treat this as a careful architectural migration.

Do not perform a broad rewrite.

Do not replace working subsystems unnecessarily.

Do not redesign GLDoze.

Do not simplify away existing functionality.

Preserve the current X11 implementation and move it behind clearly defined interfaces.

Prefer incremental, compilable changes.

Build and test repeatedly during the refactor.

When faced with a choice between:

```text
A) a slightly more verbose architecture with a clean platform boundary

and

B) leaking X11 assumptions back into DesktopShell
```

choose A.

The desired outcome is that GLDoze's desktop core becomes genuinely independent of X11, while the existing X11 backend behaves exactly as it does now.

Once this pass is complete, stop before implementing the actual Wayland compositor and provide the full architecture report.
