Usage Examples#

Managing cursor shapes#

from omni.kit.window.cursor import get_main_window_cursor
import carb.settings

# Override the current cursor shape with a custom extended shape
main_window_cursor = get_main_window_cursor()
if main_window_cursor:
    # Register a cursor
    settings = carb.settings.get_settings()
    cursors = settings.get_settings_dictionary("/exts/omni.kit.window.cursor/cursors")
    # via setting
    cursors["Rotate_object"] = "${omni.kit.window.cursor}/data/icons/usage/rotateObject.png"
    # or method
    main_window_cursor.register_cursor_shape_extend("Rotate_object", "${omni.kit.window.cursor}/data/icons/usage/rotateObject.png")

    # override the current cursor with cursors we registered
    main_window_cursor.override_cursor_shape_extend("Rotate_object")

    # do something....
    main_window_cursor.get_cursor_shape_override_extend() # should be "Rotate_object"

    # restore the cursor to default
    main_window_cursor.clear_overridden_cursor_shape()
    # unregister the cursor
    main_window_cursor.unregister_cursor_shape_extend("Rotate_object")

Observing cursor changes (e.g. for streaming)#

The ImGui renderer dispatches an omni.kit.renderer.imgui.cursorChanged eventdispatcher (Events 2.0) event whenever the effective cursor shape changes — from ImGui hover state (Arrow, IBeam, Hand, Crosshair, VerticalResize, HorizontalResize) or from an explicit override set through this extension (including custom cursors, which are reported by the name they were registered with). This works in headless / streaming mode as well, so a web front end can reflect the Kit-side cursor — including custom cursors, which it maps by name to its own images.

The event is addressed by name, so a consumer subscribes with just the event-name string — no dependency on the IImGuiRenderer interface (the subscription compiles and runs against any Kit version; on a Kit that doesn’t dispatch it, the event simply never fires).

from carb.eventdispatcher import get_eventdispatcher

def _on_cursor(e):
    cursor_name = e["cursor_name"]            # e.g. "Arrow", "IBeam", or "Rotate_object"
    app_window_title = e["app_window_title"]
    # A streaming extension forwards this to the client as an 'onCursor' message; the client
    # maps standard names to CSS cursors and custom names to its own custom cursor images.
    print(f"cursor changed to '{cursor_name}' on window '{app_window_title}'")

# Keep the returned ObserverGuard alive for as long as you want events.
cursor_sub = get_eventdispatcher().observe_event(
    observer_name="my.extension",
    event_name="omni.kit.renderer.imgui.cursorChanged",
    on_event=_on_cursor,
)

The event is edge-triggered (it only fires on a change). A consumer that subscribes at startup sees every change from then on, so it can assume the default Arrow cursor initially and update from there — e.g. a streaming server tracks the latest value and seeds it into a new client’s handshake, so a client connecting to an already-running app still gets the current cursor.

The built-in cursor names are Arrow, IBeam, Hand, Crosshair, HorizontalResize and VerticalResize; any other value is a custom cursor registered via register_cursor_shape_extend.