This can be toggled per-window, so use the individual window flags instead of the global toggle to selectively enable it only for the relevant window in a multi-seat scenario, as is already done with keyboard and pointer grabs.
The main view always reflects the size of the output, so don't use the dimensions of the currently bound render target texture when updating it, or it will reflect an incorrect size when the render target texture is unbound.
This and its related commits introduced some bugs and quirks such as duplicated and delayed/missed key events that can't be easily worked around, so revert this for now.
This reverts commit 47162a4168.
Compositors typically send keyboard, pointer, touch, and tablet leave events when a window is destroyed, however, this is not guaranteed behavior, and at least one compositor in widespread use doesn't always send pointer leave events immediately upon destroying a window. Ensure that all references held by seats to a focused window are removed before the underlying window surface and structs are destroyed to prevent potential segfaults if the seats are immediately destroyed after the window.
IME text events can result in sending duplicate key press events, which will result in undesired repeated key presses. Since the events are exact duplicates, compare the serials to filter out redundant key down events.
The xserver will still send EnterNotify events while the pointer is captured, and the grab shouldn't be updated in these cases, as it will cause the capture to be lost.
If it is known that the window will immediately enter fullscreen upon being shown, set the borderless style when showing the window to hide the borders, or they may linger in the background if the client takes some time to draw the first frame.
Unnecessarily calling ShowWindow with SW_RESTORE when applying the window flags must be suppressed in this case, or the borders can reappear in a weird, partial state.
sdl2-compat will call SDL_GetDisplayForWindow() when querying the display to use for fullscreen, which won't always be correct if the backend can't actually reposition the window. When calling this function, get the ideal fullscreen display and store it in a property for retrieval by sdl2-compat.
Mouse button events that trigger a hit test are not passed to the client, but the client may still query the global mouse button state from within the hit test handler, so the reported buttons need to be accurate. Query the buttons directly from the seat instead of the higher global mouse state to match the behavior of other platforms.
By default, popups are automatically constrained to be completely within display bounds, so as not to cut off information and result in an unusable menu, or unreadable tooltip. In some cases, however, this is not wanted, so a property to toggle this behavior is added.
There are also cases where the client may not want a popup menu to implicitly grab the keyboard focus, as is the default behavior, so popup menus now respect the focusable flag/property, as well as being able to toggle focus grabbing via SDL_SetWindowFocusable().
When showing or hiding a popup menu, manually check and set the focus if the new topmost window under the cursor is an SDL window. Otherwise, the focus won't be updated until the cursor is actually moved.
There is a quirk with XInput2 mouse capture that causes a leave event to be sent if the pointer moves out->in->out, which breaks mouse tracking outside the window. If the mouse leaves the window with buttons pressed, continue tracking it until the buttons are released.
Xfce, unlike every other window manager in existence, sends ConfigureNotify events before PropertyNotify events when toggling the fullscreen and maximized window state. Check the window state when handling ConfigureNotify events, and defer emitting SDL size/position events until the corresponding PropertyNotify event arrives, since SDL and clients expect to get the window state before the new size and position.
This warning is actually wrong, as the variable is only used if the string pointer is valid, in which case it was initialized, but this is needed to quiet MSVC.
Wayland compositors may send recursive clipboard offers to the client, which need to be filtered out to avoid clearing local data. Previously this was worked around with a hack, but this caused the ownership flag to be set incorrectly, which broke some clients.
This introduces a metadata MIME type of application/x-sdl3-source-id to be sent with SDL3 selection offers, which contains a string that is a unique identifier for the instance, and can be used to detect if a received selection offer is originating from the same instance that generated it.
If DBus is available, the unique identifier string is the unique name of the connection, otherwise, the process ID is used.
If a window isn't resizable from specific directions, the compositor can inform clients of the current edge constraints, so they don't display resize cursors for non-resizable edges.
Wayland environments can expose more than one seat for multiple collections of input devices, which can include multiple, simultaneously active, desktop pointers and keyboards with independent layouts. The Wayland input backend previously presumed that only one seat could exist, which caused broken behavior if the compositor exposed more than one, which is possible on wlroots based compositors such as Sway. This introduces support for handling multiple seats, including proper handling of dynamically added and removed seats and capabilities at run time.
The SDL Wayland input system was accreted over time, and the assumption that only one seat will ever exist resulted in state and related objects not always being tied to their most appropriate owner in a multi-seat scenario, so refactoring was required to manage several bits of state per-seat, instead of per-window or globally.
As Wayland keyboards can have per-seat layouts, fast keymap switching is required when multiplexing input from multiple seats to the global SDL keyboard device. A parameter was added to the keymap creation function to specify if the keymap lifetime should be externally managed to facilitate keymap reuse, and some layout info was moved from the global keyboard state to the keymap state to avoid unnecessarily redetermining it whenever a reused keymap is bound. This reduces the overhead of switching keymaps to setting a single pointer.
Multiple seats also means that multiple windows can have keyboard and/or mouse focus at the same time on some compositors, but this is not currently a well-handled case in SDL, and will require more work to support, if necessary.
The window may be initially maximized or made fullscreen by the window manager for various reasons, such as automatically declaring a window that precisely fills the usable desktop space as maximized, or a "kiosk-mode" automatically making the window fullscreen.
Don't redundantly make restored or unset fullscreen calls when initially showing a window, or the expected state can be unset.
It doesn't work well with Vulkan, and Vulkan windows may not have the Vulkan flag set in all circumstances, so only enable it if we explicitly know that OpenGL is being requested instead.
On non-compositing window managers, XIconifyWindow can trigger map/unmap events, which would toggle the window hidden/shown state. This should not be done, as a hidden window in SDL is equivalent to a withdrawn window in X, and SDL will try to set/reset state when it is shown again.
Unless the window is explicitly being withdrawn via X11_HideWindow(), set unmapped windows to the minimized/occluded state, and send a restored event when mapped again.
The window failing to enter/exit fullscreen notifications don't necessarily imply anything about the actual state of the window. On failure, dump pending events, and don't presume anything about the current window state, as it will be handled by subsequent enter/leave notifications.
The accelerated relative coordinates are always relative to the desktop resolution, and need to be scaled with emulated fullscreen resolutions for mouse movement to remain stable. Otherwise, pointer speeds will be too fast on emulated resolutions below the desktop resolution, and too slow on those above.
If the window is flagged with SDL_WINDOW_TRANSPARENT, create the associated swapchain with a composite alpha value that supports blending, if available.
Fixes transparent windows on the Vulkan backend, and prevents possible validation errors by ensuring that the composite alpha value is always a valid bit in VkSurfaceCapabilitiesKHR::supportedCompositeAlpha.
The tm_gmtoff field of the broken-down time 'tm' struct wasn't formally standardized until POSIX.1-2024, but practically it has been available on desktop *nix platforms such as Linux/glibc, FreeBSD, OpenBSD, NetBSD, OSX/macOS (NextStep before that), and others since the 1990s. The notable exception is SunOS/Solaris, where the timezone offset must still be retrieved in the strictly POSIX.1-2008 compliant way.
The existing behavior helps clients that don't expect exclusive fullscreen windows to move by maintaining a consistent size and mode, however, some are aware that this can occur and want to handle mode selection themselves.
Add a hint to disable auto mode switching when an exclusive fullscreen window moves to accommodate this use case, and don't override fullscreen changes that may occur in an event watcher between the display changed event being posted and SDL running the display changed handler, as the mode switch may have already been handled there by the client.
External windows may call this to update the renderer size, but not pump SDL events, either by syncing or running an event loop, so the size event always needs to be synthesized for external windows. If it is wrong, the true size will be sent if/when events are processed.
The bug this appeared to fix turned out to be randomly occurring and has other causes, and the read pipe is already polled for readiness, so this extra overhead isn't necessary.
External windows often handle their own events, and SDL implicitly processing events during synchronization can be unexpected and cause issues. For requests that don't change the window state beyond size or position, use the legacy synchronization method that synthesizes events from the window attributes without processing events.
Openbox doesn't send size events when entering fullscreen, so they must be synthesized. This is not desirable on any other window manager, as it can break fullscreen positioning on multi-monitor configurations.
Changing the mode triggers a display reconfiguration event, which will overwrite the desktop mode with the set fullscreen mode, preventing proper restoration when leaving fullscreen. Don't overwrite the desktop mode if the reconfiguration is due to a fullscreen mode switch.
Fullscreen spaces and miniaturization will always give us some notification that they succeeded or failed, so the timeout isn't required. This prevents errant timeouts when live-resize is active.
Additionally, add a warning about calling the frame visibility function universally during the mapping process, as the libdecor Cairo plugin has a bug that will cause a crash in this scenario.
Use the modifier state supplied with key events to track the system modifier state instead of relying on the state returned by XQueryPointer(), which can be racy when used with automated text entry.
A window may have been maximized by dragging it to the top of another display, in which case the floating position may be out-of-date. If the window is being restored to maximized, and the maximized and floating position are on different displays, try to center the window on the maximized display for restoration, which mimics native Windows behavior.
An undefined position means that the window manager can handle placement, so SDL shouldn't override that by forcing a position when showing a window.
Allows for removing a fair bit of now-unnecessary code as well.
SDL_GetWindowDisplayScale() should be preferred over SDL_GetDisplayForWindow() + SDL_GetDisplayContentScale() for querying the per-window content scale, as the former provides a more accurate and current value for individual windows, as the per-window value can differ from the base display scale value, particularly on high-DPI and multi-monitor desktops.
This needs to be preserved while in fullscreen, or leaving fullscreen for the maximized state can cause the taskbar to disappear with borderless windows.
Always restore the base floating size of a window before possibly entering the maximized state, as base size can be lost during the fullscreen transition, resulting in the window de-maximizing to the wrong size.
Update the mouse state before entering the hit test, in case the global state is queried, or the system menu opened, while in the client hit testing callback.
MonitorFromWindow can fail if called on a window being de-minimized, so fall back to using the monitor from the last window coordinates if initial retrieval fails.