Event names have grown in length and are occasionally truncated when being logged (e.g. SDL_EVENT_WINDOW_PIXEL_SIZE_CHA). Increase the event name buffer size to handle the longer names.
Try to match the requested video mode when a fullscreen window is moved to a new display, or it may not be returned to the requested mode if it is moved to a display with no matching mode, then back to the original display.
The behavior when minimizing a window on Wayland is compositor dependent and clients are not informed when windows enter or leave the minimized state, however we can assume that, when receiving a minimize request from the application, the minimized window should set and keep the minimized status flag until the window regains focus.
This is required when attaching a renderer context to a minimized window, as the renderer creation process destroys and recreates the target window, and without retaining the minimized flag, the recreated window will lose the minimized state.
Hiding the decorations while not unreferencing the frame was a workaround for an internal libdecor use-after-free bug that was fixed some time ago. Revert to unreferencing the window when hiding to ensure that it is properly destroyed.
Reverts dd2e318
The xdg-output spec was updated to clarify its usage rules, and what was previously thought to be a bug is actually valid behavior. Gnome, when not using 'scale-monitor-framebuffer', does not scale the viewport of the display in the global compositor space, and thus the physical and logical sizes of the display will match. This value still needs to be divided by the integer scale value to get the logical output dimensions in screen units though.
Don't throttle window updates until the first swap has occurred, as the window won't actually be shown or receive the frame callback until that point and this causes new window creation to have a full 1 second delay.
Update the popup window creation documentation with additional info, remove the SDL_WINDOW_MOUSE_GRABBED flag check since it isn't a valid window creation flag and will be removed automatically elsewhere, and check for and remove the explicit skip taskbar and borderless flags since they are implicit for popup windows.
Disallow additional window operations on popups where they have no functionality or otherwise don't make sense:
- Popups cannot be set as modal to other windows (they're already child windows of a parent)
- Other windows cannot be set as modal of popups
- Popups cannot explicitly grab the mouse/keyboard (the topmost popup menu takes the keyboard focus implicitly)
- Popups cannot flash or be raised
Set the timeout max to one second from the current time or presentation time will always be greater than the timeout and the application will run unthrottled.
Don't use the cached floating window size for maximized or tiled windows. Fixes the initial window size when creating a window with the maximized flag set.
Right click to create new popup menus. Clicking over an existing popup menu will create a child menu. Left click to close all menus. Hover to display a tooltip that is the child of the window below it. Closing the application closes the root window, which should automatically destroy any open popup windows and exit gracefully.
Add the CreatePopupWindow function to allow the creation of child tooltip and menu popup windows. Popup windows must be created as either a tooltip or popup menu and cannot be minimized, maximized, made fullscreen, or grab the mouse.
Child popup windows are tracked and will be recursively hidden, shown, or destroyed in tandem with the parent window.
Track the current window display ID locally so as not to depend on specific behavior of the video layer, which may change the value at times when it isn't expected.
Track the current window display ID locally so as not to depend on specific behavior of the video layer, which may change the value at times when it isn't expected.
When moving a window programmatically, the move event will be deduplicated due to the window x and y coordinates already being updated, so the window's current display ID needs to be explicitly updated.
Update the target display ID and use SDL_UpdateFullscreenMode() when moving a fullscreen window to handle the case where the target display has an existing fullscreen window.
Use the delta of the target refresh rate and the refresh rate of the mode to select the closest matching display mode, as the actual closest mode may have a slightly lower rate than the target by a small fraction of a hz (e.g 59.98 vs 60.0).
Desktops can move windows, even exclusive fullscreen windows, from one display to another. To handle this, windows now hold two fullscreen modes: the desired mode, which is considered mutable only to the application, and the current mode. When a fullscreen request is made, the current mode is initially set to the desired mode for the initial fullscreen transition. If an exclusive fullscreen window is moved to a new display, the new display is checked to see if it has a mode compatible with the desired mode. If it does, the compatible mode is used so the windows will have the same properties on the new display. If no compatible mode is found, the window becomes desktop fullscreen. This occurs whenever the window is moved to ensure that an attempt will always be made to use the application's requested mode, if possible.
Exiting and reentering fullscreen results in the desired mode being restored on the display specified by it.
When an exclusive fullscreen display is specified, it overrides any positioning, including from driver specific functions. Allows for the proper placement of fullscreen windows on macOS and Windows when the floating window is on a display that differs from the one specified by the exclusive fullscreen mode.
A specific position-only function has been split out for use when a window has been moved.
The Xrandr dot clock value is declared as an unsigned long and the result when multiplying by 100 can overflow on a 32-bit system. Explicitly cast it to Sint64 to ensure that no overflow will occur.
Attempt to retrieve the display for fullscreen windows using the window position so that the correct display ID is returned if an exclusive fullscreen window is moved to another display.
Portrait displays may have native, physical resolutions that are taller than wide. Reverse the mode dimensions when dealing with these displays as well as those rotated via software means.
SDL uses window minimization to determine fullscreen window visibility and hide windows before changing the video mode back to the desktop. Wayland, however, does not have the concept of a minimized window and doesn't set the minimized flag (minimization can be requested, but what actually happens to the window is implementation dependent, and if a window is minimized via a desktop shortcut or decoration control, the application is not notified of any state changes). Make the video core mode setting a no-op so that the Wayland backend can handle reporting the display dimensions using its own internal logic.
Accommodate the new video core changes.
The new video core changes allow for some window geometry calculation refactoring that simplify the system:
- Removal of helper functions
- Eliminate some discrepancies between the libdecor and xdg-toplevel paths
- No need to short-circuit the video core window size event deduplication check
- Exclusive fullscreen windows will always end up on the correct output, even when fullscreen is initiated from the compositor
- Better handling of cases where the desktop is scaled, but does not expose the viewport protocol
- Return the display bounds for the emulated mode if an exclusive fullscreen window has focus
- Fixed cases where changing display properties during runtime wouldn't update the display mode lists
- General cleanup
The C specification states that passing a size of 0 to functions like memcpy is valid, but even if the size is 0 and the function is essentially a no-op, the result when passing any invalid pointers is considered undefined behavior. Don't rely on undefined behavior when copying the display or mode lists.
The display list can contain self-referential pointers if the current mode pointer points to the desktop mode or a fullscreen mode array element, and reallocating the display or fullscreen mode lists without updating the current mode pointer in these cases can leave them pointing to freed memory or garbage data. Manually copy the list items and update the self-referential pointers if necessary.
When adding a display, traverse the list of added fullscreen modes and ensure the display ID is set to its final, valid value, or the modes added before calling SDL_AddVideoDisplay() will have an invalid display ID.
If the window was fully enclosed, GetDisplayForRect() would return the index of the display ID in the array instead of the display ID itself. Return the display ID itself.
Ensure that all hard dependencies are resolved when dynamically loading the libraries required for the Wayland backend and fail gracefully if a required module was not initialized successfully.
Fixes the Wayland backend to report the desktop mode dimensions in pixels instead of screen units, adjusts enumerated fullscreen resolutions to use the correct pixel values and scaling, and changes some nomenclature to reflect the terminology used in the new DPI system.
If an exclusive fullscreen window is moved between displays, SDL_UpdateFullscrrenMode can kick the window out of fullscreen if the display onto which it was moved doesn't have a matching video mode. Check the return code and clear the fullscreen flag and skip the resize if the window is no longer fullscreen.
If SDL_UpdateFullscreenMode() fails to find a matching mode for the window, it will restore the window to its previous state, but still returns a success code of 0. Return an error code of -1 if no matching display mode can be found.
When a driver is emulating mode changes, the display bounds are always the native desktop size, not those of the video mode being emulated. This can result in incorrectly setting the size of fullscreen Wayland windows. Don't resize fullscreen windows to the display dimensions when mode switching is emulated.
Renames the quirk flag from VIDEO_DEVICE_QUIRK_DISABLE_DISPLAY_MODE_SWITCHING to VIDEO_DEVICE_QUIRK_MODE_SWITCHING_EMULATED to better reflect its purpose.
libdecor plugins can change the min/max window size values internally to enforce a minimum window size, and errors and crashes can result if the window size is below the internal limit.
On versions of libdecor >= 0.1.1, the minimum width and height can be queried and the minimum required window size will be enforced. The application requested window size is still respected, however, the actual window may be slightly larger than the drawable area to accommodate the required libdecor minimum size.
On version 0.1.0 of libdecor, which lacks the function to retrieve the minimum size, the internal limits are overridden before committing a frame, so that the internal limits always match the window size as a workaround, even if the window is technically smaller than the plugin would normally allow.
Modifier keys on Wayland can be remapped, latched/locked, and defer the system modifier state changes to key release events instead of key press events, which the default SDL modifier handling code doesn't deal with correctly. Track and set the modifier keys internally to deal with the plethora of various combinations that the system key modifiers can be in and correctly reflect the actual system state to SDL applications.
Add SDL_SendKeyboardKeyIgnoreModifiers() function and repurpose the source parameter for the SDL_SendKeyboardKeyInternal() function to use as a generic set of keyboard flags.
On window focus, look up the pressed modifier keys via keycodes instead of scancodes to handle the case of remapped keys, as xkb remapping changes the associated keycode, not the scancode.
It was previously thought that these function calls were unnecessary as the initial bug and reproduction case that necessitated their addition seemed to be fixed, but apparently there are still cases where this needs to be set explicitly. Set the xdg surface geometry at creation time and when the window size changes.
Partially reverts #6361. This is not needed in the libdecor path, as libdecor calls this for the content surface internally.
Num Lock and Caps Lock always need to be explicitly handled by the modifier handler function, or they won't be correctly set if active at application startup, or if the lock state is changed while the application lacks focus since a key press for these keys will never be received. In these cases, the internal SDL modifier state can end up the inverse of the actual modifier state.
Add the protocol for high-resolution timestamp events and subscribe to them if available.
Event timestamps are now handled natively in nanoseconds as much as possible to avoid error-prone conversions.
Variables have been appended with _ms or _ns where appropriate, to avoid ambiguity.
SDL_HINT_VIDEO_X11_FORCE_EGL was deprecated in favor of the more general SDL_HINT_VIDEO_FORCE_EGL, and Xinerama and Xvidmode support was previously removed from SDL, rendering their associated hints nonfunctional.
Explicitly include the Wayland protocol headers when statically linking against the Wayland libraries or older system headers might be used instead of the local versions.
When changing the window state from non-floating to floating (e.g. leaving fullscreen), libdecor can send bogus content sizes that are +/- the height of the window title bar and start 'walking' the window height in one direction or the other with every transition.
The floating window size is known, so use the cached value instead of the size reported by libdecor when restoring the floating state.
The XKB_KEY_* and XK_* macros resolve to the same constant values, so use the raw values and note what keys they correspond to in the comments, as is done for the other keysym values in this file.
This completely eliminates the need for any X or XKB system headers along with the if/else defines.
SDL is built around the concept of keyboards having a fixed layout with scancodes that correspond to physical keys no matter what linguistic layout is used. Virtual keyboards don't have this concept and can present an arbitrary layout of keys with arbitrary scancodes and names, which don't fit the SDL model. When one of these keyboards is encountered, it requires special handling: use the keysym of the pressed keys to derive their ANSI keyboard scancode equivalents for control keys and ASCII characters. All other characters are passed through as text events only.
Add a helper function to get the keycode for a scancode from the default lookup table. Unlike SDL_GetKeyFromScancode(), this is not affected by the set keymap.
Clamp the wl_seat max version to 5 if being built against a version of libwayland below 1.21.0, or containers that bundle newer versions of SDL with older versions of libwayland can break if the compositor advertises support for a protocol version above 5.
If relative mouse mode is explicitly enabled, don't modify the capture flag on button events or the window might report having lost mouse focus if a button is pressed while moving the cursor.
Exit the fullscreen sequence sooner if it is requested that a popup window be fullscreen.
The surface commit formerly in this path is irrelevant and can be removed as previous changes made it so that SetFullscreen() is no longer called from anywhere except Wayland_SetWindowFullscreen().
Replace instances of fprintf(stderr, ...) with SDL_SetError(), replace C++ comments with C style, use a uniform format for multi-line comments, and remove unused headers as poll and select aren't used in this file (the SDL function which calls them is used instead).
libdecor_dispatch() needs to be called, as libdecor plugins might do some required internal processing within, however care must be taken to avoid double-blocking in the case of a timeout, which can occur if libdecor_dispatch() and the SDL event processing both work on the main Wayland queue. Additionally, assumptions that libdecor will always dispatch the main queue or not process zero-length queues (can occur if a wait is interrupted by the application queueing an event) should not be made, as this behavior is outside the control of SDL and can change.
SDL handles polling for Wayland events and then calls libdecor to do its internal processing and dispatch. If libdecor operates on the main queue, it will dispatch the queued events and the additional wl_display_dispatch_pending() call will be a NOP. If a libdecor plugin uses its own, separate queue, then the wl_display_dispatch_pending() call will ensure that the main queue is always dispatched.
These were needed to fix some buggy behavior regarding committing old buffer sizes when entering fullscreen that has since been corrected. Remove them.
If the compositor is entering fullscreen and hasn't removed any constraints itself, it's already too late at this point. Remove the unnecessary call.
Restoring the limits when exiting fullscreen is still required, though, as they may have been removed when entering fullscreen via an SDL request.
Caches the SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY hint at init time and registers a callback, which is fired when the hint is changed during runtime and toggles the opaque region for existing surfaces.
The preferred method for setting the damage region on compositor protocol versions 4 and above is to use wl_surface.damage_buffer. Use this when available and only fall back to wl_surface.damage on older versions.
Bumps the highest supported version of wl_compositor to version 4.
Adds deduplication logic to ConfigureWindowGeometry() to avoid setting redundant backbuffer, viewport and surface opaque region dimensions. State is now only set when the window and/or backbuffer dimensions change.
This repurposes the viewport rect to always hold the actual size of the window, which can differ from the SDL size if things are being scaled. The SDL_Rect was removed in favor of two ints, as the x/y members of the struct were never used, so they just wasted space.
Since the internal variables always have the true window size, the width/height getter functions are no longer required and can be removed.
Calling SDL_HideWindow() to destroy the window is a NOP if the SDL_WINDOW_SHOWN flag was never set. Bypass it and call the Wayland-specific function directly to ensure that the window is always destroyed before switching from server-side to client-side decorations, even if it hasn't been shown yet.
Likewise, call Wayland_ShowWindow() directly when the window isn't explicitly hidden to ensure that it is always recreated since the SDL_WINDOW_SHOWN flag won't be cleared, which, when set, renders SDL_ShowWindow() a NOP.
The text component of a repeated keystroke is initially set when a key is first pressed and the cached value remains static until the repeated key is released and another repeatable key is pressed. If the state of a modifier such as shift or capslock is changed while a key is being repeated, the text emitted will not have the modifier applied to it until the repeated key is released and pressed again.
Update the text to be repeated by a key if a modifier is changed while a key is actively being repeated.
The XKB keysym to SDL keycode mappings were missing for the Escape and NumLock keys, which prevented them from being remapped. Add them to the table so that the remapping of these keys will work.
If multiple keys were simultaneously depressed and one was being repeated, the repeat flag was being cleared when any of the pressed keys were released, even if the released key wasn't the one being repeated.
This tracks the key currently being repeated and only clears the repeat flag when the particular key being repeated is released.
In some cases, a backbuffer size update may not be accompanied by a resize event if the window size and/or scale were updated before the new backbuffer size was recomputed. Instead of the scale, use the old/new backbuffer sizes to determine if a resize event is required so that a backbuffer size change will always be followed by a resize event.
Instead of wrapping individual calls to SDL_SetDisplayModeForDisplay(), just check the flag in the function itself and make it a NOP that cannot fail if the flag is set. Silences some errant "SDL video driver doesn't support changing display mode" log errors.