This page documents the DisplayServer abstraction layer and its platform-specific implementations. DisplayServer handles window creation and management, input event collection, clipboard, cursor shapes, native dialogs, screen queries, and related OS-level display functions. For how the rendering pipeline produces frames into those windows, see RenderingServer (7.1) and RenderingDevice (7.2). For how the Window scene node interacts with DisplayServer, see Window Management (4.5).
DisplayServer is a server singleton (like RenderingServer and AudioServer) that abstracts every platform's native windowing and input stack behind a single API. The engine calls it directly for:
The abstract base is declared in servers/display/display_server.h. Each platform provides exactly one concrete subclass, registered at startup.
DisplayServer class hierarchy
Sources: platform/windows/display_server_windows.h200-201 platform/linuxbsd/x11/display_server_x11.h104-105 platform/linuxbsd/wayland/display_server_wayland.h61-62 platform/macos/display_server_macos.h83-84 platform/android/display_server_android.h43-44
Every concrete implementation overrides has_feature(Feature p_feature) const. This lets calling code check platform capability at runtime before calling an optional API.
| Feature Constant | Windows | X11 | Wayland | macOS | Android |
|---|---|---|---|---|---|
FEATURE_MOUSE | ✓ | ✓ | ✓ | ✓ | ✓ |
FEATURE_TOUCHSCREEN | ✓ | ✓ | — | — | ✓ |
FEATURE_CLIPBOARD | ✓ | ✓ | ✓ | ✓ | ✓ |
FEATURE_IME | ✓ | ✓ | ✓ | ✓ | — |
FEATURE_NATIVE_DIALOG_FILE | ✓ | ✓ (DBus) | ✓ (DBus) | ✓ | ✓ |
FEATURE_TEXT_TO_SPEECH | ✓ | ✓ (SpeechD) | ✓ (SpeechD) | ✓ | ✓ |
FEATURE_HDR_OUTPUT | ✓ | — | — | — | — |
FEATURE_STATUS_INDICATOR | ✓ | — | — | ✓ | — |
FEATURE_ACCESSIBILITY_SCREEN_READER | ✓ (AccessKit) | ✓ (AccessKit) | ✓ (AccessKit) | ✓ (AccessKit) | — |
FEATURE_SCREEN_CAPTURE | ✓ | ✓ (non-XWayland) | — | — | — |
FEATURE_HIDPI | ✓ | — | ✓ | ✓ | — |
Sources: platform/windows/display_server_windows.cpp123-168 platform/linuxbsd/x11/display_server_x11.cpp184-247 platform/linuxbsd/wayland/display_server_wayland.cpp196-251 platform/android/display_server_android.cpp67-98
Each created OS window is identified by a WindowID (integer). Windows with MAIN_WINDOW_ID are the primary application window. Implementations maintain a map from WindowID to a platform-specific WindowData struct that holds:
HWND on Windows, Window on X11, xdg_toplevel on Wayland, NSWindow* on macOS)fullscreen, borderless, maximized, etc.)rect_changed_callback, event_callback, input_event_callback, input_text_callback, drop_files_callbackWindow lifecycle (Windows platform)
Sources: platform/windows/display_server_windows.h294-395 platform/windows/display_server_windows.cpp217-273
All platforms implement the WindowMode enum:
| Mode | Description |
|---|---|
WINDOW_MODE_WINDOWED | Normal floating window |
WINDOW_MODE_MINIMIZED | Minimized to taskbar |
WINDOW_MODE_MAXIMIZED | Maximized within desktop bounds |
WINDOW_MODE_FULLSCREEN | Exclusive fullscreen |
WINDOW_MODE_EXCLUSIVE_FULLSCREEN | Exclusive with display mode change |
On macOS, _update_window_style() adjusts NSWindowStyleMask and window level when borderless fills the screen. On Windows, _get_window_style() computes DWORD style and style_ex flags from the current mode fields.
Sources: platform/macos/display_server_macos.mm268-295 platform/windows/display_server_windows.h476
All implementations maintain three fields:
| Field | Role |
|---|---|
mouse_mode_base | The mode requested by user code |
mouse_mode_override | Temporary override (e.g., during drag operations) |
mouse_mode_override_enabled | Whether override is active |
mouse_mode | The currently applied effective mode |
_mouse_update_mode() reconciles these and calls _set_mouse_mode_impl() (Windows) or equivalent logic (X11: XGrabPointer, Wayland: zwp_pointer_constraints, macOS: CGAssociateMouseAndMouseCursorPosition).
MOUSE_MODE_CAPTURED centers the cursor, clamps it in place, and enables raw input (Windows: RegisterRawInputDevices; X11: XGrabPointer + XI_RawMotion). Relative motion is computed from deltas rather than absolute positions.
Sources: platform/windows/display_server_windows.cpp217-273 platform/linuxbsd/x11/display_server_x11.cpp541-610 platform/linuxbsd/wayland/display_server_wayland.cpp127-164
The clipboard API is:
clipboard_set(String) / clipboard_get() → Stringclipboard_get_image() → Ref<Image>clipboard_has() → boolclipboard_set_primary() / clipboard_get_primary() — X11/Wayland only (primary selection)| Platform | Mechanism |
|---|---|
| Windows | OpenClipboard / SetClipboardData(CF_UNICODETEXT) / GetClipboardData |
| X11 | XSetSelectionOwner / XConvertSelection with INCR protocol for large data |
| Wayland | wl_data_device / zwp_primary_selection_device_v1 |
| macOS | NSPasteboard |
| Android | GodotJavaWrapper::set_clipboard / get_clipboard |
On X11, _clipboard_get_impl() handles the INCR protocol for clipboard contents larger than a single X property chunk, assembling data incrementally across PropertyNotify events.
Sources: platform/windows/display_server_windows.cpp999-1076 platform/linuxbsd/x11/display_server_x11.cpp713-892 platform/android/display_server_android.cpp166-197
Each WindowData stores an input_event_callback Callable that _dispatch_input_event() calls. On popup-with-keyboard-focus situations, keyboard events are redirected to the topmost popup window's callback rather than the originating window.
Sources: platform/macos/display_server_macos.mm441-488 platform/linuxbsd/wayland/display_server_wayland.cpp127-164
DisplayServerWindows)Located in platform/windows/display_server_windows.h and platform/windows/display_server_windows.cpp
Key subsystems:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM) processes all Win32 messages. Touch input (WM_POINTER*), pen tablet (WM_TABLET_* via WinTab or Windows Ink), IME (WM_IME_*), and DnD (IDropTarget via DropTargetWindows) are handled here.WTPacket (WinTab API, loaded dynamically) or Windows Pointer API (WM_POINTER). The tablet_driver string field selects between them.MOUSE_MODE_CAPTURED, _register_raw_input_devices() calls RegisterRawInputDevices so motion comes via WM_INPUT as deltas.ShouldAppsUseDarkMode, GetImmersiveColorFromColorSetEx) is loaded dynamically from uxtheme.dll. The DwmSetWindowAttribute(DWMWA_USE_IMMERSIVE_DARK_MODE) call controls the title bar._thread_fd_monitor) via COM IFileDialog. Results are posted back via pending_cbs and processed on the main thread in process_file_dialog_callbacks().Sources: platform/windows/display_server_windows.h200-520 platform/windows/display_server_windows.cpp293-319 platform/windows/display_server_windows.cpp538-803
DisplayServerX11)Located in platform/linuxbsd/x11/display_server_x11.h and platform/linuxbsd/x11/display_server_x11.cpp
Key subsystems:
_refresh_device_info() enumerates XI devices to identify touch screens (direct-touch XITouchClass) and absolute pointing devices (tablets). Motion events come via XI_RawMotion generic events on the xi.opcode extension.XRRGetMonitors for accurate physical screen layout.DBUS_ENABLED, FreeDesktopPortalDesktop provides native file dialogs (org.freedesktop.portal.FileChooser) and FreeDesktopScreenSaver handles screen-keep-on.xwayland bool flag disables screen capture since pixel readback is unreliable under XWayland._NET_WM_STATE atoms sent via XSendEvent to the root window.Sources: platform/linuxbsd/x11/display_server_x11.cpp271-388 platform/linuxbsd/x11/display_server_x11.h104-240
DisplayServerWayland)Located in platform/linuxbsd/wayland/display_server_wayland.h and platform/linuxbsd/wayland/display_server_wayland.cpp
Key subsystem: WaylandThread
Wayland's client library is not thread-safe, so all protocol I/O runs in a dedicated WaylandThread. It communicates with the main thread via a message queue of typed Ref<Message> subclasses:
WaylandThread owns all Wayland objects: wl_compositor, xdg_wm_base, wl_seat, zwp_pointer_constraints_v1, wp_fractional_scale_manager_v1, wp_cursor_shape_manager_v1, zxdg_decoration_manager_v1, and more. Each is acquired via the registry listener.wl_surface + xdg_surface + xdg_toplevel (for top-level windows) or xdg_popup (for popups).libdecor (optional): When LIBDECOR_ENABLED, server-side decoration negotiation is handled via libdecor rather than the xdg_decoration protocol.wp_fractional_scale_v1 reports non-integer DPI scales; the implementation applies them via wp_viewport.FreeDesktopPortalDesktop as X11 for file dialogs.godot_embedding_compositor Wayland protocol (defined in platform/linuxbsd/wayland/godot-embedding-compositor.xml) allows embedding child Wayland surfaces into Godot editor windows for the run-in-editor feature.Sources: platform/linuxbsd/wayland/display_server_wayland.h61-200 platform/linuxbsd/wayland/wayland_thread.h96-200 platform/linuxbsd/wayland/wayland_thread.cpp1-370
DisplayServerMacOS)Located in platform/macos/display_server_macos.h and platform/macos/display_server_macos.mm
Key subsystems:
WindowData holds a GodotWindow* (subclass of NSWindow), a GodotContentView* (subclass of NSView), and a GodotWindowDelegate*. The delegate receives NSWindowDelegate callbacks (resize, close, fullscreen transitions) and forwards them to DisplayServerMacOS._create_window(): Allocates and configures the Cocoa window, attaches a CAMetalLayer (for Metal/Vulkan) or sets up the GL context via GLManagerLegacy_MacOS or GLManagerANGLE_MacOS._get_screens_origin() computes the offset to translate to Godot's top-left convention._process_key_events() consumes from a buffered key_event_buffer to correctly interleave IME composition events with raw key events.menu_callback() appends to deferred_menu_calls rather than executing immediately, to avoid corrupting the Cocoa event queue.Sources: platform/macos/display_server_macos.mm91-266 platform/macos/display_server_macos.mm382-404 platform/macos/display_server_macos.mm495-551 platform/macos/godot_window_delegate.mm38-60
DisplayServerAndroid)Located in platform/android/display_server_android.h and platform/android/display_server_android.cpp
Android does not use a multi-window model. There is effectively one full-screen surface. All display operations delegate to Java-side implementations via JNI:
GodotJavaWrapper — main app wrapper (clipboard_set, is_dark_mode, show_dialog, show_file_picker)GodotIOJavaWrapper — I/O wrapper for screen metrics, orientation, virtual keyboardTTS uses TTS_Android which calls the Android TextToSpeech Java class. Cursor shapes map to Android's PointerIcon integer constants stored in android_cursors[].
Sources: platform/android/display_server_android.cpp63-230 platform/android/display_server_android.h43-100
All implementations provide:
| Method | Description |
|---|---|
get_screen_count() | Number of connected monitors |
get_primary_screen() | Index of primary monitor |
screen_get_position(screen) | Top-left corner in virtual desktop space |
screen_get_size(screen) | Pixel resolution |
screen_get_dpi(screen) | Dots per inch |
screen_get_scale(screen) | Fractional scale factor (HiDPI) |
screen_get_refresh_rate(screen) | Refresh rate in Hz |
screen_get_usable_rect(screen) | Rect excluding taskbars and docks |
On Windows, _get_screen_expand_offset() compensates for sub-pixel boundary mismatches between logical and physical screen coordinates when multiple monitors have different DPI settings.
Sources: platform/windows/display_server_windows.cpp182-215 platform/macos/display_server_macos.mm363-411
TTS is optional and feature-gated. Each platform delegates to a dedicated helper class:
| Platform | Class | Backend |
|---|---|---|
| Windows | TTS_Windows | SAPI (ISpVoice) |
| Linux/X11 | TTS_Linux | speech-dispatcher |
| Linux/Wayland | TTS_Linux | speech-dispatcher |
| macOS | TTS_MacOS | AVSpeechSynthesizer |
| Android | TTS_Android | Android TextToSpeech API |
On Linux, TTS_Linux is lazily constructed on first tts_is_speaking() call via initialize_tts(). The same lazy pattern applies on Windows.
Sources: platform/windows/display_server_windows.cpp321-379 platform/linuxbsd/x11/display_server_x11.cpp413-473 platform/android/display_server_android.cpp104-130
All desktop platforms support the AccessKit-based accessibility driver when compiled with ACCESSKIT_ENABLED. The DisplayServer exposes an accessibility element API:
accessibility_create_element(window_id, role) — allocates a new RID-identified accessibility nodeaccessibility_update_set_*() — sets attributes (name, role, bounds, value, flags)accessibility_update_add_action(id, action, callable) — registers assistive action callbacksaccessibility_set_window_focused(window_id, focused) — notifies the accessibility tree of focus changesAccessibilityDriverAccessKit (in drivers/accesskit/) translates these RID-based elements into AccessKit's platform-native tree representations.
Sources: doc/classes/DisplayServer.xml13-107 platform/windows/display_server_windows.cpp160-164 platform/linuxbsd/x11/display_server_x11.cpp237-241
DisplayServer creates and owns the rendering surface handles that the rendering backend writes to. The pattern is consistent across platforms:
On each platform, a WindowPlatformData union (or equivalent) passes the native surface handle to the RenderingContextDriver:
| Platform | Handle type | Driver |
|---|---|---|
| Windows Vulkan | HINSTANCE + HWND | RenderingContextDriverVulkanWindows |
| Windows D3D12 | HWND | RenderingContextDriverD3D12 |
| Linux X11 Vulkan | Display* + Window | RenderingContextDriverVulkanX11 |
| Linux Wayland Vulkan | wl_display* + wl_surface* | RenderingContextDriverVulkanWayland |
| macOS Metal | CA::MetalLayer* | RenderingContextDriverMetal |
| macOS Vulkan | CAMetalLayer* | RenderingContextDriverVulkanMacOS |
| Android Vulkan | ANativeWindow* | RenderingContextDriverVulkanAndroid |
Sources: platform/macos/display_server_macos.mm173-203 platform/windows/display_server_windows.h265-274 platform/linuxbsd/wayland/display_server_wayland.cpp177-181
| Platform | Mechanism |
|---|---|
| Windows | COM IFileDialog / IFileOpenDialog / IFileSaveDialog via _thread_fd_monitor worker thread |
| X11 (DBus) | org.freedesktop.portal.FileChooser via FreeDesktopPortalDesktop |
| Wayland (DBus) | Same portal as X11 |
| macOS | NSOpenPanel / NSSavePanel via GodotOpenSaveDelegate |
| Android | GodotJavaWrapper::show_file_picker → Android Intent.ACTION_OPEN_DOCUMENT |
On Windows, FileDialogData carries all parameters and is passed to a background Thread; results are posted to pending_cbs (a List<FileDialogCallback>) and flushed on the main thread by process_file_dialog_callbacks().
The file_dialog_with_options_show() variant adds custom checkbox/combobox controls to the dialog via IFileDialogCustomize, with results passed back through the callback as a Dictionary.
Sources: platform/windows/display_server_windows.cpp538-888 platform/linuxbsd/x11/display_server_x11.cpp511-533 platform/android/display_server_android.cpp225-231
VSyncMode is per-window on all platforms that support it:
| Mode | Behavior |
|---|---|
VSYNC_DISABLED | No frame pacing |
VSYNC_ENABLED | Standard VSync |
VSYNC_ADAPTIVE | Drops to immediate when behind |
VSYNC_MAILBOX | Triple-buffering / latest-frame |
The mode is forwarded through rendering_context->window_set_vsync_mode(window_id, mode) to the GPU driver. On Wayland, emulate_vsync in WindowData enables a software fallback when the compositor does not provide wp_fifo_manager_v1.
Sources: platform/linuxbsd/wayland/display_server_wayland.h90 platform/android/display_server_android.h77
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.