egui_overlay

repository·master·Indexed 42 days ago

https://github.com/coderedart/egui_overlay

An egui integration for creating desktop overlays with transparent window surfaces, toggleable decorations, and input passthrough. Version 0.9.0. It includes support for multiple rendering backends including wgpu, three-d, and glow, and provides specific configuration for Emscripten builds targeting wasm32-unknown-emscripten.

Tokens
9.3K
Snippets
38
Records
46
Agent score
53%

What's inside egui_overlay

  1. What is Egui Overlay?

    master

    Egui Overlay is a crate designed to create GUI applications with the following characteristics:

    1. Transparent window surface: The window background is transparent.
    2. Toggleable decorations: Ability to toggle window borders and title bars.
    3. Input passthrough: The ability to let mouse clicks and other inputs pass through the window surface to the applications underneath when egui does not need the input.

    It combines egui_window_glfw_passthrough for windowing management with rendering backends like egui_render_three_d (for general drawing) or egui_render_wgpu (specifically for macOS support).

  2. Configure Emscripten build flags for GLFW support

    master

    When targeting wasm32-unknown-emscripten, you must configure specific linker flags in your .cargo/config.toml to enable GLFW and WebGL2 support.

    Required flags for GLFW and WebGL2:

    • USE_GLFW=3
    • MAX_WEBGL_VERSION=2
    • MIN_WEBGL_VERSION=2 (to disable WebGL1)

    Optional flags:

    • FULL_ES2 or FULL_ES3 for OpenGL ES emulation.
    • ERROR_ON_UNDEFINED_SYMBOLS=0 (may be required for wgpu to ignore certain EGL symbols).
    # inside .cargo/config.toml
    [target.wasm32-unknown-emscripten]
    rustflags = [
        "-C",
        "link-arg=-s",
        "-C",
        "link-arg=USE_GLFW=3",
        "-C",
        "link-arg=-s",
        "-C",
        "link-arg=MAX_WEBGL_VERSION=2 ",
        "-C",
        "link-arg=-s",
        "-C",
        "link-arg=MIN_WEBGL_VERSION=2",
        "-C",
        "link-arg=-s",
        "-C",
        "link-arg=DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1",
    ]
  3. Set up the HTML canvas for Emscripten/SDL2

    master

    For WASM applications using SDL2/GLFW, the HTML canvas element must have specific attributes and a JavaScript Module configuration to ensure the library can find the backing window.

    Requirements:

    1. The <canvas> element must have id="canvas" and data-raw-handle="1".
    2. A Module object must be defined in a <script> tag before the generated .js glue code is loaded. This object must provide a canvas function that returns the canvas element.
    <!DOCTYPE html>
    <html
      <body
        <canvas data-raw-handle="1" id="canvas"></canvas>
        <!-- this script MUST be loaded before the cargo-generated script -->
        <script type="text/javascript">
          var Module = {
            canvas: (function () {
              return document.getElementById("canvas");
            })(),
          };
        </script>
        <script src="my_project_name.js"></script>
      </body>
    </html>
  4. Advanced usage: Using egui_window_glfw_passthrough directly

    master
    If you require more control over the event loop or specific drawing logic, it is recommended to use the egui_window_glfw_passthrough crate directly instead of egui_overlay. This allows you to choose between wgpu, three-d, or glow backends manually.
  5. Build and deploy for Emscripten

    master

    To build and deploy your project, compile for the wasm32-unknown-emscripten target, copy the resulting .wasm, .js, and index.html files to a distribution directory, and serve them using a local server.

    #!/bin/sh
    echo "building for emscripten target"
    # Ensure .cargo/config.toml contains the necessary linker options
    cargo build --target=wasm32-unknown-emscripten --release
    
    echo "copying files to dist directory"
    mkdir -p dist
    
    # Copy the WASM binary
    cp target/wasm32-unknown-emscripten/release/my_project_name.wasm dist
    # Copy the JS glue code generated by cargo
    cp target/wasm32-unknown-emscripten/release/my_project_name.js dist
    # Copy the HTML entry point
    cp index.html dist
    
    # Start a local development server (DO NOT USE IN PRODUCTION)
    (cd dist && python -m http.server)
  6. Platform support and requirements

    master

    Windows

    Supported.

    Linux

    • Display Servers: X11 is supported natively. Wayland works via Xwayland, though support may vary depending on the window manager.
    • Compositing: You must use a compositor that supports transparency (e.g., kwin). If using tiling window managers like i3wm, you will need an external compositor like picom.
    • Window Management: In tiling window managers (like i3wm), you may need to configure the overlay window as "floating" to ensure it stays above other tiled windows.

    macOS

    • Supported, but uses egui_render_wgpu for rendering because Apple does not support OpenGL.
    • Known Bug: When passthrough is enabled, the window titlebar can only be clicked in the bottom half; the top half becomes passthrough.
  7. Implement custom paint callbacks in egui

    master

    To inject custom WGPU rendering commands into the egui draw stream, use the CallbackFn structure. This allows you to run arbitrary code during the render pass.

    CallbackFn consists of two parts:

    1. prepare: A callback used to perform resource allocation or data uploads on the Device and Queue before rendering begins.
    2. paint: A callback that receives the RenderPass and PaintCallbackInfo (containing viewport, clip rect, and screen size) to execute drawing commands.

    Note that CallbackFn must be wrapped in an Arc to be used within the egui callback system.

    // Example structure for a custom callback
    let my_callback = CallbackFn {
        prepare: Arc::new(|device, queue, custom_data| {
            // Perform setup here
        }),
        paint: Arc::new(|info, rpass, custom_data| {
            // Execute WGPU commands here using rpass
        }),
    };
  8. Configure the GLFW window via start()

    master

    While start() provides sensible defaults for an overlay (transparent, no borders, always on top), you can influence window creation by providing a custom GlfwConfig if you were to use the underlying GlfwBackend directly. In the current start() implementation, the following behaviors are hardcoded:

    • transparent_window: Some(true)
    • glfw_callback: Includes a hint to ScaleToMonitor(true).
    • window.set_floating(true): Makes the window always on top.
    • window.set_decorated(false): Removes the title bar and borders.
  9. Initialize EguiPainter for WGPU

    master

    To use egui_render_wgpu, you must initialize an EguiPainter. This struct manages the vertex/index buffers, textures, and the render pipeline required to draw egui primitives using WGPU.

    When creating a new painter, you must provide the WGPU Device and the TextureFormat of your surface. The painter will automatically set up the necessary uniform buffers for screen size, texture bind group layouts, and samplers (linear, nearest, and font).

    let painter = EguiPainter::new(&device, surface_format);
  10. Execute the egui rendering lifecycle

    master

    To render a frame using WgpuBackend, follow this sequence of method calls:

    1. prepare_frame: Prepares the surface texture view and clears the surface. It accepts a closure latest_framebuffer_size_getter that returns the current [u32; 2] size.
    2. render_egui: Uploads egui data (meshes, textures) and executes the render pass. Requires meshes (Vec<egui::ClippedPrimitive>), textures_delta (egui::TexturesDelta), and logical_screen_size ([f32; 2]).
    3. present: Submits all accumulated command_encoders to the wgpu::Queue and presents the image to the surface.

    Note: If you have custom WGPU commands, you can push them into backend.command_encoders before calling present to ensure they are submitted in the same batch.

    // 1. Prepare
    backend.prepare_frame(|| [800, 600]);
    
    // 2. Render
    backend.render_egui(
        meshes,
        textures_delta,
        [800.0, 600.0]
    );
    
    // 3. Present
    backend.present();
  11. Initialize the GlfwBackend with GlfwConfig

    master

    To create a new GlfwBackend, use the GlfwBackend::new(config: GlfwConfig) method. The GlfwConfig struct allows you to specify the window title, initial size, transparency, and whether to use an OpenGL context.

    It also provides two powerful callback hooks:

    1. glfw_callback: Called with &mut Glfw before the window is created. Use this for advanced GLFW configuration (e.g., setting OpenGL versions, depth/stencil bits).
    2. window_callback: Called after window creation and event polling setup. Use this for startup tasks like resizing, changing the title, or entering fullscreen.

    By default, GlfwBackend handles the conversion between GLFW's virtual units and egui's logical points, ensuring correct scaling on HiDPI displays.

    let config = GlfwConfig {
        window_title: "My Overlay".to_string(),
        size: [1280, 720],
        transparent_window: Some(true),
        opengl_window: Some(true),
        glfw_callback: Box::new(|glfw| {
            // Advanced GLFW configuration here
        }),
        window_callback: Box::new(|window| {
            // Post-creation window configuration here
        }),
    };
    
    let mut backend = GlfwBackend::new(config);