The joystick subsystem has complex precedence logic to deal multiple competing
backends like XInput, RawInput, and WGI. Let it fire the MaybeAdd callbacks
for joystick devices, since it knows which backend will end up managing them.
This resolves a situation where the RawInput joystick backend would take
control of an XInput device but the XInput haptic backend would still create
a haptic device. Since the XInput joystick backend didn't own the underlying
joystick device, we'd end up with an orphaned haptic device that didn't work
with SDL_HapticOpenFromJoystick() on the associated joystick device.
A racing reader could read from our fd between SDL_IOReady()/X11_Pending()
and our call to XNextEvent() which will cause XNextEvent() to block for
more data. Avoid this by using XCheckIfEvent() which will never block.
This also fixes a bug where we could poll() for data, even when events were
already read and pending in the queue. Unlike the Wayland implementation,
this isn't totally thread-safe because nothing prevents a racing reader
from reading events into the queue between our XCheckIfEvent() and
SDL_IOReady() calls, but I think this is the best we can do with Xlib.
This API and implementation comes from the Unreal Engine branch of SDL, which
originally called this "SDL_ConfineCursor".
Some minor cleanup and changes for consistency with the rest of SDL_video, but
there are two major changes:
1. The coordinate system has been changed so that `rect` is _window_ relative
and not _screen_ relative, making it easier to implement without having
global access to the display.
2. The UE version unset all rects when passing `NULL` as a parameter for
`window`, this has been removed as it was an unused feature anyhow.
Currently this is only implemented for X, but can be supported on Wayland and
Windows at minimum too.
This prevents conflicts with hidapi linked with applications, as well as allowing applications to make use of HIDAPI on Android and other platforms that might not normally have an implementation available.
Enabling the RawInput backend causes SDL_XINPUT_Enabled() to return false.
That causes WGI and DInput backends to take ownership of XInput-compatible
controllers, because they think there's no XInput-specific backend enabled.
In WGI's case, it will actually race with RawInput to open the device. By
properly excluding XInput devices from WGI, we can ensure that the sets of
devices managed by WGI and RawInput don't intersect. This makes the race
harmless, since they'll never both go after the same device.
The Xbox One driver stack doesn't propagate the VID/PID down to the
HID devices that end up in the GetRawInputDeviceList() output. This
means we end up matching against the wrong VID/PID and can't properly
exclude Xbox One controllers from WGI.
Fortunately, it is possible to walk back up the device tree to find
the parent with the matching VID/PID.
In this case we'll get WM_KILLFOCUS when the child window is focused, but we'll retain focus on the top level window, but when we Alt-Tab away, we won't get another WM_KILLFOCUS or WM_NCACTIVATE, we get WM_ACTIVATE instead, so we need to check for focus updates in response to that as well.
* SDL_OpenURL (macOS): try to open path if the url cannot be opened
* SDL_OpenURL (macOS): use CFURLCreateWithBytes & LSOpenCFURLRef to correctly escape input
* fix type casting + indentation
It's marked as being a public symbol internally, however, it was missing from the header files and not visible in the shared library. This adds it to the necessary headers and to the DynAPI list to expose it for use by applications.
Co-authored-by: Frank Praznik <frank.praznik@oh.rr.com>
Note that this removes the timeGetTime() fallback on Windows; it is a
32-bit counter and SDL2 should never choose to use it, as it only is needed
if QueryPerformanceCounter() isn't available, and QPC is _always_ available
on Windows XP and later.
OS/2 has a similar situation, but since it isn't clear to me that similar
promises can be made about DosTmrQueryTime() even in modern times, I decided
to leave the fallback in, with some heroic measures added to try to provide a
true 64-bit tick counter despite the 49-day wraparound. That approach can
migrate to Windows too, if we discover some truly broken install that doesn't
have QPC and still depends on timeGetTime().
Fixes#4870.
Add a new flag to avoid suppressing EINTR in SDL_IOReady(). Pass the
flag in WaitEventTimeout() to ensure that a SIGINT will wake up
SDL_WaitEvent() without another event coming in.
Even without the thread, it'll do an initial hardware detection at startup,
but there won't be any further hotplug events after that. But for many cases,
that is likely complete sufficient.
In either case, this cleaned up the code to no longer need a semaphore at
startup.
Fixes#4862.
We can have spurious wakeups in WaitEventTimeout() due to Wayland events
that don't end up causing us to generate an SDL event. Fortunately for us,
SDL_WaitEventTimeout_Device() handles this situation properly by calling
WaitEventTimeout() again with an adjusted timeout.
There are two issues which are stopping the SDL tests from building on
my machine:
- libunwind is not being linked
- Even if it is, it is missing several symbols.
The first is fixed by having the test programs link against libunwind if
available. Technically, SDL2_test should be linking against it, as it's
used in SDL_test_memory.c, but as SDL2_test is a static library, it
can't itself import libunwind. We just assume that if it's present on
the system, we should link it directly to the test programs. This should
strictly be an improvement, as the only case where this'd fail is if
SDL2 was compiled when libunwind was present, but the tests are being
compiled without it, and that'd fail anyway.
The second is fixed by #define-ing UNW_LOCAL_ONLY before including
libunwind.h: this is required to make libunwind link to predicatable
symbols, in what can only be described as a bit of a farce. There are a
few more details in the libunwind man page, but the gist of it is that
it disables support for "remote unwinding": unwinding stack frames in a
different process (and possibly from a different architecture?):
http://www.nongnu.org/libunwind/man/libunwind(3).html
Note that I haven't tried this with CMake: I suspect that it'll work,
though, as the CMakeLists.txt seems to have SDL2 link against libunwind if
it's present. This adds an ugly extra dependency to SDL2, but does mean
that issue 1 isn't present. The UNW_LOCAL_ONLY change shouldn't be
build-system-specific.
Wayland provides the prepare_read()/read_events() family of APIs for
reading from the display fd in a deadlock-free manner across multiple
threads in a multi-threaded application. Let's use those instead of
trying to roll our own solution using a mutex.
This fixes an issue where a call to SDL_GL_SwapWindow() doesn't swap
buffers if it happens to collide with SDL_PumpEvents() in the main
thread. It also allows coexistence with other code or toolkits in
our process that may want read and dispatch events themselves.
- Factorize PrepQueueCmdDraw{,DrawTexture,Solid) into one single function
- Change SDL_Texture/Renderer r,g,b,a Uint8 into an SDL_Color, so that it can be passed directly to RenderGeometry
- Don't automatically queue a SET_DRAW_COLOR cmd for RenderGeometry (and update GLES2 renderer)
Instead of taking a direct copy of the mouse cursor surface, and then
premultiplying on every BO upload (using the custom
legacy_alpha_premultiply_ARGB8888 function), use the new
SDL_PremultiplySurfaceAlphaToARGB8888() function, which converts a whole
surface at a time, once and save the result.
The already-premultiplied data is then copied from that to the BO on
each upload, adjusting for the stride (which the previous implementation
required to be equal to the width), thereby making the extra copy
slightly useful..
This also adds support for non-SDL_PIXELFORMAT_ARGB8888 surfaces.
It turns out that Wayland's WL_SHM_FORMAT_ARGB8888 format (and, indeed,
all wayland RGBA formats) should be treated as premultiplied. SDL
surfaces tend not to be premultiplied, and this is assumed by other
backends when dealing with cursors.
This change premultiplies the cursor surface in Wayland_CreateCursor()
using the new SDL_PremultiplySurfaceAlphaToARGB8888(). In so doing, it
also adds support for a wider range of input surfaces, including those
with non-ARGB8888 pixel formats, and those which don't have
pitch==width.
This should fix#4856
A number of video backends need to get ARGB8888 formatted surfaces with
premultiplied alpha, typically for mouse cursors. Add a new function to
do this, based loosely on legacy_alpha_premultiply_ARGB8888() from the
KMSDRM backend.
The new function, SDL_PremultiplySurfaceAlphaToARGB8888() takes two
arguments:
- src: an SDL_Surface to be converted.
- dst: a buffer which is filled with premultiplied ARGB8888 data of the
same size as the surface (assuming pitch = w).
This is not heavily optimised: it just repeatedly calls SDL_GetRGBA() to
do the conversion, but should do for now.
This fixes a specific issue seen on macOS 10.14.6 where a DELL E248WFP
Display connected to a 2014 Mac Mini with a scaled 1920x1080 resolution
selected and SDL_Init(SDL_INIT_VIDEO) failed with the error: "The video
driver did not add any displays".
The underlying cause was that the current 1080p display mode did not
have the flag kDisplayModeSafeFlag, the check for which was added in
a963e36, with the idea that certain display modes should not be
candidates for switching to in fullscreen exclusive mode. That may well
be the right thing to do for filtering down a list of candidate modes,
but it doesn't pay to be so picky about the current mode. After all,
this current mode was set by System Preferences, the picture does appear
correctly on screen, and other non-SDL based applications launch and run
correctly in this mode.
Therefore the fix is to have GetDisplayMode only filter out a mode based
on flags if it's part of a candidate list, but if it's the current mode
and it can possibly be converted to an SDL_DisplayMode, do so.
* Avoid unnecessary SDL_PumpEvents calls in SDL_WaitEventTimeout
* Add a sentinel event to avoid infinite poll loops
* Move SDL_POLLSENTINEL to new internal event category
* Tweak documentation to indicate SDL_PumpEvents isn't always called
* Avoid shadowing event variable
* Ignore poll sentinel if more (user) events have been added after
Co-authored-by: Sam Lantinga <slouken@libsdl.org>
Instead do an absolute elapsed time check since the start of the wait. If that is exceeded during any iteration the routine exits as the timeout has elapsed.
The observed behavior is that any nonzero timeout value would hang until the device was paused and resumed. And a zero timeout value would always return 0 frames written even when audio fragments could be heard. Making a manual timeout system unworkable.
None of the straightforward systems imply that there's a detectable problem before the call to AAudioStream_write(). And the callback set within AAudioStreamBuilder_setErrorCallback() does not get called as we enter the hang state.
I've found that AAudioStream_getTimestamp() will report an error state from another thread. So this change codifies that behavior a bit until a better fix or more root cause can be found.
Dispatching all events in Wayland_GLES_SwapWindow leads to resizes being
acked before the program has a chance to handle the resize. This change
reduces jumping on fullscreen transition with apps that call
SDL_PollEvent before issuing any render calls.
This has been better fixed by b28ed02 or another related relative mouse mode change of @slouken in SDL 2.0.17 and as such can be reverted to reduce unneeded processing in WM_MOUSEMOVE
wl_display_dispatch() will block if there are no events available, and
while we try to avoid this by using SDL_IOReady() to verify there are
events before calling it, there is a race condition between
SDL_IOReady() and wl_display_dispatch() if multiple threads are
involved.
This is made more likely by the fact that SDL_GL_SwapWindow() calls
wl_display_dispatch() if vsync is enabled, in order to wait for frame
events. Therefore any program which pumps events on a different thread
from SDL_GL_SwapWindow() could end up blocking in one or other of them
until another event arrives.
This change fixes this by wrapping wl_display_dispatch() in a new mutex,
which ensures only one thread can compete for wayland events at a time,
and hence the SDL_IOReady() check should successfully prevent either
from blocking.
Direct3D 9 dictates that caps.NumSimultaneousRTs must always be at least 1,
which is to say that Direct3D 9 level hardware must always support render
targets.
(caps.NumSimultaneousRTs is meant to show if you can draw to multiple render
targets in a single draw call.)
We had already hardcoded SDL_RENDERER_TARGETTEXTURE as available earlier in
the function anyhow.
Fixes#4781.
Some wayland compositors report the refresh rate as 0. Since we want to
force a minimum refresh rate of 10 frames worth, we were dividing by the
reported refresh rate, causing a divide-by-zero.
If the refresh rate is 0, instead force a frame every second if no frame
callbacks are received.
This fixes bug #4785
This will still happen occasionally as the mouse is whipped around, if there is a window overlapping the game window, but it should happen less often now. This could even happen with the original code that warped the mouse every frame, so this should be a good compromise where we don't warp the mouse continously and we still keep the mouse in the safe area of the game window.
Note that notifications can be any size, so the safe area may need to be adjusted or even dynamically defined via a hint.
We don't use it, it was a leftover from 1.2, I think, and it doesn't exist
on Solaris, so this should hopefully fix the build there.
This also means we don't need the configure/cmake checks for
SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY, so that was removed also.
Fixes#1666.
One place known to differ in a significant way is a single line segment that
starts and ends on the same point; the GL renderers will light up a single
pixel here, whereas the software renderer will not. My current belief is this
is a bug in the software renderer, based on the wording of the docs:
"SDL_RenderDrawLine() draws the line to include both end points."
You can see an example program that triggers that difference in Bug #2006.
As it stands, the GL renderers might _also_ render diagonal lines differently,
as the the Bresenham step might vary between implementations (one does three
pixels and then two, the other does two and then three, etc). But this patch
causes those lines to start and end on the correct pixel, and that's the best
we can do, and all anyone really needs here.
Not closing any bugs with this patch (yet!), but here are several that it
appears to fix. If no other corner cases pop up, we'll call this done.
Reference Bug #2006.
Reference Bug #1626.
Reference Bug #4001.
...and probably others...
Vista and later provide the SleepConditionVariableCS() function for this.
Since SDL_syscond_srw.c doesn't require SRW locks anymore, rename it to
SDL_syscond_cv.c which better reflects the implementation of condition
variables rather than the implementation of mutexes.
Fixes#4051.
* Fixed: Whitespace being striped from the end of IME strings incorrectly
* Fixed: Google IME Candidate Window not placing correctly
* Why are PostBuild events stored in the vcxproj and not a user file?
* Revert SDL.vcxproj properly...
* Remove whitespace as per code review
* Fix Werror=declaration-after-statement error in code
In the future, we might want to support special swap intervals. To
prevent applications from expecting nonzero values of vsync to be the
same as "on", fail with SDL_Unsupported() if the value passed is neither
0 nor 1.
Currently, if an application wants to toggle VSync, they'd have to tear
down the renderer and recreate it. This patch fixes that by letting
applications call SDL_RenderSetVSync().
This is the same as the patch in #3673, except it applies to all
renderers (including PSP, even thought it seems that the VSync flag is
disabled for that renderer). Furthermore, the renderer flags also change
as well, which #3673 didn't do. It is also an API instead of using hint
callbacks (which could be potentially dangerous).
Closes#3673.
See SDL bug #4703. This implements two new hints:
- SDL_APP_NAME
- SDL_SCREENSAVER_INHIBIT_ACTIVITY_NAME
The former is the successor to SDL_HINT_AUDIO_DEVICE_APP_NAME, and acts
as a generic "application name" used both by audio drivers and DBUS
screensaver inhibition. If SDL_AUDIO_DEVICE_APP_NAME is set, it will
still take priority over SDL_APP_NAME.
The second allows the "activity name" used by
org.freedesktop.ScreenSavver's Inhibit method, which are often shown in
the UI as the reason the screensaver (and/or suspend/other
power-managment features) are disabled.
The recent change to make SDL_AUDIODRIVER support comma-separated lists
broke the previous behavior where an SDL_AUDIODRIVER that was empty
behaved the same as if it was not set at all. This old behavior was
necessary to paper over differences in platforms where SDL_setenv may
or may not actually delete the env var if an empty string is specified.
This patch just adds a simple check to ensure SDL_AUDIODRIVER is not
empty before using it, restoring the old interpretation of the empty
var.
Originally, SDL 1.2 used "pulse" as the name for its PulseAudio driver.
While it now supports "pulseaudio" as well for compatibility with SDL
2.0 [1], there are still scripts and distro packages which set
SDL_AUDIODRIVER=pulse [2]. While it's possible to remove this in most
circumstances or replace it with "pulseaudio" or a comma-separated list,
this may still conflict if the environment variable is set globally and
old binary builds of SDL 1.2 (e.g. packaged with older games) are being
used.
To fix this on SDL 2.0, add a hardcoded check for "pulse" as an audio
driver name, and replace it with "pulseaudio". This mimics what SDL 1.2
does (but in reverse). Note that setting driver_attempt{,_len} is safe
here as they're reset correctly based on driver_attempt_end on the next
loop.
[1] d951409784
[2] https://bugzilla.opensuse.org/show_bug.cgi?id=1189778
This change corrects the mappings for the Atari gamecontroller and
adds support for the Atari Xbox 360 compatible gamecontroller. The Atari
game controller can switch between Atari and Xbox 360 mappings.
This might have changed at some point in the Pulse API, or this might have
always been wrong, but we didn't notice because the dynamic loading code
hides it by casting things to void *. The static path, where it
assigns the function pointer directly, puts out a clear compiler warning,
though.
With Dear ImGui + software renderer, it draws:
- by default at 250 fps
- drops to 70 fps if you show the color picker
- drops to 10 fps if put the color picker fullscreen
There were a few places throughout the SDL code where values were
clamped using SDL_min() and SDL_max(). Now that we have an SDL_clamp()
macro, use this instead.
This was the original intent (note SDL_UpdateWindowGrab() in SDL_OnWindowFocusGained() and SDL_OnWindowFocusLost()) and fixes a bug where relative motion unexpectedly stops if the task bar is covering the bottom of the game window and the mouse happens to move over it while relative mode is enabled.
Another alternative would be to confine the mouse when relative mode is enabled, but that generates mouse motion which would need to be ignored, and it's possible for the user moving the mouse to combine with the mouse moving into the confined area so you can't easily tell whether to ignore the mouse motion. See https://github.com/libsdl-org/SDL/issues/4165 for a case where this is problematic.
This is the mouse focus except in the case where relative motion is enabled and the mouse is over a window floating on top of the application window (e.g. the taskbar)
This fixes restoring the cursor clip rectangle after the mouse has moved off of the window.
Also try to better synchronize cursor visibility with mouse position changes when changing relative mode. This doesn't work perfectly, but it seems to improve things on Windows.
Don't rely on checking __clang_major__ since it is not comparable
between different vendors. Don't use "#pragma clang attribute" since it
is only available in relatively recent versions, there's no obvious way
to check if it's supported, and just using __attribute__ directly (for
gcc as well) results in simpler code anyway.
If we are already in the desired mode, changing it is a no-op at best,
and harmful at worst: on Xwayland, it sometimes happens that we disable
the crtc and cannot re-enable it.
Resolves: https://github.com/libsdl-org/SDL/issues/4630
Signed-off-by: Simon McVittie <smcv@collabora.com>
- cmake, configure (CheckDLOPEN): --enable-sdl-dlopen is now history..
detach the dl api discovery from SDL_LOADSO_DLOPEN functionality.
define HAVE_DLOPEN. also define DYNAPI_NEEDS_DLOPEN (CheckDLOPEN is
called only for relevant platforms.)
- update SDL_config.in and SDL_config.cmake accordingly.
- SDL_dynapi.h: set SDL_DYNAMIC_API to 0 if DYNAPI_NEEDS_DLOPEN is
defined, but HAVE_DLOPEN is not.
- pthread/SDL_systhread.c: conditionalize dl api use to HAVE_DLOPEN
- SDL_x11opengl.c, SDL_DirectFB_opengl.c, SDL_naclopengles.c: rely
on HAVE_DLOPEN, not SDL_LOADSO_DLOPEN.
- SDL_config_android.h, SDL_config_iphoneos.h, SDL_config_macosx.h,
SDL_config_pandora.h, and SDL_config_wiz.h: define HAVE_DLOPEN.
Closes: https://github.com/libsdl-org/SDL/pull/4351
Without this change, driver names don't get matched correctly;
for example "a" can get matched with "alsa" since it only checks
whether the string matches up to the length of the requested
driver name.
Without this change, driver names don't get matched correctly;
for example "x" can get matched with "x11" since it only checks
whether the string matches up to the length of the requested
driver name.
b08b1bde introduced a subtle bug. Despite not using D-Bus types directly,
the code used the SDL_USE_LIBDBUS definition set by SDL_dbus.h to conditionally
compile calls SDL_DBus_ScreensaverTickle() and SDL_DBus_ScreensaverInhibit().
As a result, it still compiled without SDL_dbus.h included, but screensaver
suspension silently failed to work.
The D-Bus stuff could probably use some tweaks to be harder to accidentally
break, but for now just restore the header includes.
Configure events from compositors have an extremely annoying habit of giving us
completely bogus sizes, from all sorts of places. Thankfully, the protocol
gives us the ability to completely ignore the width/height and just stick with
what we know, so for all windows that are not meant to be resized, pretend we
never even got the width/height at all, the compositor is required to respect
our dimensions whether they match configure's suggestion or not.
Otherwise only the display resolution is changed, but the SDL window size
(and for example the window-surface size) aren't adjusted accordingly
and thus don't fill the whole screen.
See #3313
.. and maybe other platforms as well (though X11 was not affected)?
The issue was that passing a higher resolution than the current desktop
resolution to SDL_CreateWindow() with SDL_WINDOW_FULLSCREEN didn't switch
to that resolution (even though it did switch to lower resolutions).
When creating a fullscreen window, window->fullscreen wasn't even set
at all (only zeroed out), setting it only happened if the user explicitly
called SDL_SetWindowDisplayMode(). So without that, SDL_CreateWindow()
-> SDL_UpdateFullscreenMode() -> SDL_GetWindowDisplayMode() used the
resolution from window->windowed.w/h which were limited to the desktop size
due to some weird combination of WIN_AdjustWindowRectWithStyle() and
WIN_WindowProc() being called after a call to SetWindowPos().
fixes#3313
This prevents a race if two threads that need d-bus try to init it at the
same time. Note that SDL_Init will likely handle this from a single thread
at startup, but there are places outside of init where one might trigger
D-Bus init, like setting thread priority (a common first thing for a new
thread to do) resulting in SDL trying to use RTKit.
Fixes#4587.
This reintroduces the fix from 0e16ee8330, but just marks
the viewport state as dirty after a clear that needs to expand the
viewport to fill the render target, as we'll need to also reset
the orthographic projection state elsewhere, and that won't
happen if we clear the dirty flag here.
Fixes#4210.
(again.)
(...sorry...!)
The Renderer logical scaling code scales mouse coordinates, and needs to
take the window DPI into account on HIGHDPI windows. However, the
variable which tracks this, renderer->dpi_scale, is set once when the
renderer is created, and then not updated. In the event that the window
is moved to another screen, or the screen DPI otherwise changes, this
will be outdates, and potentially the coordinates will be all wrong.
So let's update the dpi_scale on the SIZE_CHANGED event: it's at least a
possibility that this will be issued on some OSes when DPI changes, and
it's otherwise already handled by SDL_Renderer's event filter.
Otherwise you might have set the viewport to the full size of
the render target in SDL's API but this change hasn't been
transmitted to Direct3D yet by the time we attempt to clear.
Fixes#4210.
SDL_AddHintCallback() uses SDL_malloc(), which means this would
run before main(), so the app wouldn't be able to supply its own
replacement SDL_malloc() implementation in time.
This code was moved to under SDL_Init. Since the hint callback
already makes efforts to not override the app manifest's
orientation settings, this is safe to move until after pre-main()
startup.
Fixes#4449.
This removes the CM_Register_Notification code on WinRT. Note
that this API _is_ available to UWP apps as of Windows 10.0.17763
(version 1809, released October 2018), according to:
https://docs.microsoft.com/en-us/uwp/win32-and-com/win32-apis#apis-from-api-ms-win-devices-config-l1-1-1dll
So it might be worth readding with some sort of preprocessor check
for minimum targeted version, or whatever is appropriate for WinRT
development.
This was causing configure events to not inform SDL of window size
changes, even when they were based on resizes that we fully expected. The
result was fullscreen->windowed not working at all, because it would
retain the desktop resolution instead of reverting to the floating size
that it had before moving to fullscreen mode.
Fixes Super Hexagon fullscreen toggling.
The flush has been removed in e5f9fae034.
Unfortunately, even though ideally the flush shouldn't be necessary,
our resize sequence isn't... well, perfect, and removing that flush causes
tons of troubles.
We're also still flushing in other paths where the window size can be
changed by the compositor and where we may potentially have to obey that
change, like in Wayland_MaximizeWindow.
This also removes the hack introduced in 7f261d3b76,
which introduces problems with protocol violations and seems to not be
necessary when flushing.
We have issues with correct resize sequence and happen to commit old-sized
buffers even after configure event for the new size has been already
acknowledged. While the reason for that stays unknown, let's at least
workaround the problem by faking window geometry into expected size.
This does not fix visual glitch on e.g. fullscreen toggling, but having
a split-second glitch is still a much better outcome than being
terminated by the compositor for protocol violation.
This was causing window changes to completely break, resulting in broken
decorations and bizarre frame timing, I don't know what exactly it's doing
but it's not good. Kept the libdecor_frame_is_floating logic, at least.
Commit 871c11191b removed delayed
resize handling, but it left the whole structure untouched that
now became unnecessary. To help with code clarity, get rid
of the structure where pending resize state used to be stored
and pass all the data directly to Wayland_HandlePendingResize
(now renamed to Wayland_HandleResize, since it's not "pending"
anymore but applied immediately)
Otherwise our windows have no window decoration on compositors that
support xdg-decoration-unstable-v1, but default to client-side mode.
Contrary to what the comment was stating, there is nothing in the protocol
that would make redundant calls to zxdg_toplevel_decoration_v1::set_mode
problematic.
Some Wayland compositors send (0,0) as "suggested" configure event sizes to
indicate that the client has to decide on its own which sizes to used. This
is commonly done when restoring from maximised, fullscreen or tiles states
to fullscreen.
We now store the last known floating states in a new set of variables and
restore them when we receive such a (0,0) configure event.
From the vfork manpage:
> The vfork() function has the same effect as fork(2), except that
> the behavior is undefined if the process created by vfork() either
> modifies any data other than a variable of type pid_t used to store
> the return value from vfork(), or returns from the function in which
> vfork() was called, or calls any other function before successfully
> calling _exit(2) or one of the exec(3) family of functions.
unsetenv is still called inside a child process, so it does not
influence the rest of the application.
This fixes a crash on pressing keyboard button when compositor sends
zero as repeat rate, indicating that key repeat should be disabled.
From Wayland protocol spec:
> Negative values for either rate or delay are illegal. A rate of zero
> will disable any repeating (regardless of the value of delay).
This is a workaround and not a proper fix, but this is possibly complicated,
and possibly a corner case, so this will do for 2.0.16, if not the
foreseeable future.
Reference issue #4561
When we removed the OpenGL resize workaround it introduced a problem for
fullscreen windows in particular: When leaving fullscreen we tried to send a
resize event, but UpdateFullscreenMode would send a SIZE_CHANGED immediately
after, deleting our resize event and causing the following configure event's
resize to be ignored. This timing issue resulted in fullscreen windows not
being resized at all when becoming a floating window.
By always forcing resize events from configure events, we ensure that RESIZED
always makes it through. SetWindowSize-type changes should be unaffected as
they do not fire configure events.
The RenderDrawLinesWithRects and RenderDrawLinesWithRectsF functions can
sometimes call QueueCmdFillRects() with the data pointed to by frects
uninitialised. This can occur if none of the lines can be replaced with
rects, in which case the frects array is empty, and nrects is 0.
gcc 10.3.0 will detect this possibility, and print a warning like:
/home/david/Development/SDL/src/render/SDL_render.c: In function 'RenderDrawLinesWithRectsF':
/home/david/Development/SDL/src/render/SDL_render.c:2725:15: warning: '<unknown>' may be used uninitialized [-Wmaybe-uninitialized]
2725 | retval += QueueCmdFillRects(renderer, frects, nrects);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/david/Development/SDL/src/render/SDL_render.c:499:1: note: by argument 2 of type 'const SDL_FRect *' to 'QueueCmdFillRects' declared here
499 | QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect * rects, const int count)
| ^~~~~~~~~~~~~~~~~
This is harmless, because when this is uninitialised, nrects is always
0, so QueueCmdFillRects() does nothing anyway. We therefore can work
around this by only calling QueueCmdFillRects() when nrects is nonzero.
Somewhat impressively, gcc recognises that this is now safe.
This is needed to support CHERI, and thus Arm's experimental Morello
prototype, where pointers are implemented using unforgeable capabilities
that include bounds and permissions metadata to provide fine-grained
spatial and referential memory safety, as well as revocation by sweeping
memory to provide heap temporal memory safety.
The C standard does not guarantee that if two pointers compare equal
they are the same pointer, as C pointers have a notion of provenance,
and compilers have been known to exploit this during optimisation. For
CHERI, this becomes even more important, as in-place expansion can
result in realloc returning a capability to the same address but with
increased capability bounds, and so reusing the old capability will trap
trying to access outside the bounds of the original allocation.
In the case that ptr == mem, memdiff and ptrdiff should still be equal,
so the only overhead is a small amount of pointer arithmetic and a store
of the new pointer (which is required per the C standard in order to not
be undefined behaviour when next loaded).
This also fixes the calculation of oldmem to use uintptr_t rather than
size_t as casting the pointer to size_t on CHERI will strip the
capability metadata, including the validity tag, with the subsequent
cast back to void * resulting in a null-derived capability whose
validity tag is clear and thus cannot be dereferenced without trapping.
This is needed to support CHERI, and thus Arm's experimental Morello
prototype, where pointers are implemented using unforgeable capabilities
that include bounds and permissions metadata to provide fine-grained
spatial and referential memory safety, as well as revocation by sweeping
memory to provide heap temporal memory safety.
On most systems (anything with a flat memory hierarchy rather than using
segment-based addressing), size_t and uintptr_t are the same type.
However, on CHERI, size_t is just an integer offset, whereas uintptr_t
is still a capability as described above. Casting a pointer to size_t
will strip the metadata and validity tag, and casting from size_t to a
pointer will result in a null-derived capability whose validity tag is
not set, and thus cannot be dereferenced without faulting.
The audio and cursor casts were harmless as they intend to stuff an
integer into a pointer, but using uintptr_t is the idiomatic way to do
that and silences our compiler warnings (which our build tool makes
fatal by default as they often indicate real problems). The iconv and
egl casts were true positives as SDL_iconv_t and iconv_t are pointer
types, as is NativeDisplayType on most OSes, so this would have trapped
at run time when using the round-tripped pointers. The gles2 casts were
also harmless; the OpenGL API defines this argument to be a pointer type
(and uses the argument name "pointer"), but it in fact represents an
integer offset, so like audio and cursor the additional idiomatic cast
is needed to silence the warning.
When choosing an X11 Visual for a window based on its GLX capabilities, first
try glXChooseFBConfig (if available) before falling back to glXChooseVisual.
This normally does not make a difference because most GLX drivers create a
Visual for every GLXFBConfig, exposing all of the same capabilities.
For GLX render offload configurations (also know as "PRIME") where one GPU is
providing GLX rendering support for windows on an X screen running on a
different GPU, the GPU doing the offloading needs to use the Visuals that were
created by the host GPU's driver rather than being able to add its own. This
means that there may be fewer Visuals available for all of the GLXFBConfigs the
guest driver wants to expose. In order to handle that situation, the NVIDIA GLX
driver creates many GLXFBConfigs that map to the same Visual when running in a
render offload configuration.
This can result in a glXChooseVisual request failing to find a supported Visual
when there is a GLXFBConfig for that configuration that would have worked. For
example, when the game "Unnamed SDVX Clone" [1] tries to create a configuration
with multisample, glXChooseVisual fails because the Visual assigned to the
multisample GLXFBConfigs is shared with the GLXFBConfigs without multisample.
Avoid this problem by using glXChooseFBConfig, when available, to find a
GLXFBConfig with the requested capabilities and then using
glXGetVisualFromFBConfig to find the corresponding X11 Visual. This allows the
game to run, although it doesn't make me any better at actually playing it...
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Fixes: https://forums.developer.nvidia.com/t/prime-run-cannot-create-window-x-glxcreatecontext/180214
[1] https://github.com/Drewol/unnamed-sdvx-clone
As of [1], SDL now compiles with a warning in SDL_waylandevents.c on
32-bit systems under gcc 10.3.0:
/tmp/SDL/src/video/wayland/SDL_waylandevents.c: In function 'seat_handle_capabilities':
/tmp/SDL/src/video/wayland/SDL_waylandevents.c:958:22: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
958 | SDL_AddTouch((SDL_TouchID)seat, SDL_TOUCH_DEVICE_DIRECT, "wayland_touch");
| ^
/tmp/SDL/src/video/wayland/SDL_waylandevents.c:964:22: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
964 | SDL_DelTouch((SDL_TouchID)seat);
| ^
This is due to SDL_TouchID always being 32-bit, but seat being a pointer
which is (obviously) only 32-bit on 32-bit systems. The conversion is
therefore harmless, so silence it with an extra cast via intptr_t.
This is what the cocoa backend does (and is similar to what the Win32
backend does, except with size_t).
Fixes: 03c19efbd1 ("Added support for multiple seats with touch input on Wayland")
[1]: 03c19efbd1
When wayland is not dynamically loaded (--enable-wayland-shared=no)
libdecor.h is not included unless SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
is set, so it fails to build. We can't simply move the libdecor.h
include above the #ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC block, as
libdecor.h itself #includes wayland headers we need to replace with
#defines. Instead, duplicate the #include.
Fixes https://github.com/libsdl-org/SDL/issues/4543
Note that this doesn't fix any of the underlying issues of libdecor
being treated as part of wayland, it just fixes the build. A better
solution would probably be to decouple the wayland dynamic loading
from the libdecor dynamic loading completely, though that is a lot
more work...
Each window can have at most one zxdg toplevel decoration, but as of
[1], we accidentally create two. (If libdecor is not in use). This
causes wayland windows with server-side decorations (e.g. on KDE/KWin)
to crash with the message:
zxdg_decoration_manager_v1@7: error 1: decoration has been already constructed
This extra zxdg_decoration_manager_v1.get_toplevel_decoration() call was
introduced while deprecating wl-shell and xdg-shell-stable[1] support,
and possibly was a bad interaction with [2], which moved the decoration
creation around.
Fixes: 6aae5b44f8 ("Remove wl-shell and xdg-shell-unstable-v6 support (#4323)")
[1]: https://github.com/libsdl-org/SDL/pull/4323
[2]: https://github.com/libsdl-org/SDL/pull/4374
WASAPI_WaitDevice is used for audio playback and capture, but needs to
behave slighty different.
For playback `GetCurrentPadding` returns the padding which is already
queued, so WaitDevice should return when buffer length falls below the
buffer threshold (`maxpadding`).
For capture `GetCurrentPadding` returns the available data which can be
read, so WaitDevice can return as soon as any data is available.
In the old implementation WaitDevice could suddenly hang. This is
because on many capture devices the buffer (`padding`) wasn't filled
fast enough to surpass `maxpadding`. But if at one point (due to unlucky
timing) more than maxpadding frames were available, WaitDevice would not
return anymore.
Issue #3234 is probably related to this.
On modern CPUs, there's no penalty for using the unaligned instruction on
aligned memory, but now it can vectorize unaligned data too, which even if
it's not optimal, is still going to be faster than the scalar fallback.
Fixes#4532.
The Game Controller Kit doesn't show the controllers at startup, so the HIDAPI driver sees them first and therefore gets preference when a controller is supported by both drivers.
This fixes bug https://github.com/libsdl-org/SDL/issues/4209
This prevents an assertion whem LINUX_JoystickGetGamepadMapping tried to
open the stick temporarily and messed with global state by doing so. Now
the global state is only set in LINUX_JoystickOpen, but the common code
is shared by both interfaces.
Fixes#4198.
Wayland video subsystem uses a mix of libc and SDL function.
This patch switches libc functions to SDL ones and fixes a mismatch in memory
allocation/dealoccation of SDL_Cursor in SDL_waylandmouse.c (calloc on line 201
and SDL_free on line 313) which caused memory corruption if custom memory
allocator where provided to SDL.
As written, these contain undefined stack contents, which in practice
causes crashes/hangs and/or triggers the validation layers (they
complain about `pNext` and `flags` not being NULL).
When hint SDL_HINT_OPENGL_ES_DRIVER is set to "1" (e.g. for ANGLE support), assertion due to !_this->gl_config.driver_loaded can be causes while EGL is available.
When relative mode is enabled and not using warp mode, the cursor is
being clipped to the window. Therefore there is no reason to restore the
cursor position to the center.
Avoiding the warp to center simplifies mouse position event flow, as we
are no longer potentially receiving mouse events for the automated
movement of the cursor and can be (mostly) assured that an incoming
event from the windowing system is that of external means.
The implementation of clip logic for relative mode seemed to
unnecessarily limit the usable area to the middle of the window, in a
2x2 pixel region. This has the adverse side effect of moving the
operating system cursor to that location, even if it is in a valid
location in the window.
While in most scenarios this is handled correctly (by storing the
original position of the cursor in the window and restoring when leaving
relative mode), there are edge cases where this clip operation can cause
WM_MOUSEMOVE to fire at a point in time where it counts as a relative
delta from SDL's perspective.
X11_SetDisplayMode currently calls X11_XRRSetCrtcConfig alone. This results
in the monitor's viewport getting changed, but the underlying screen dimensions
stay the same.
The spec indicates that RRSetCrtcConfig only changes the crtc mode and has no effect
on the screen dimensions, only mentioning that the new crtc must fit entirely within the
screen size. For the size to change, RRSetScreenSize also needs to be called.
This affects Metro Exodus on Linux, when changing the resolution in the in-game settings
Metro gets stuck in a loop waiting for the size of its vulkan surface to change. Because
XRRSetScreenSize is not called the screen size is never changed, the vulkan surface dimensions
do not change, and Metro hangs forever watching for a surface size update that will
never come.
This change disables the CRTC, calls XRRSetScreenSize, and then updates the
CRTC configuration. This fixes changing the resolution from the Metro settings.
Tested with:
Metro Exodus, Portal 2
To enter Bluetooth pairing mode hold B and Action (button with circle) buttons for 3 seconds.
It works via usual HIDAPI if special filter driver is not installed:
https://www.amazon.com/gp/help/customer/display.html?nodeId=GZCT4CTFHXLHEB9T
With that driver installed it mimics Xbox One controller and works via XInput under Windows.
Under DInput this controller is not usable at all.
It is called from WGI before the normal joystick detection has been run, so it needs to actually enumerate currently connected devices.
We can skip the logic checking for other drivers also supporting this device, because that logic is duplicated from the call site.
Not only is it more efficient to batch process pending events, it is
necessary for correctness with the Win32 backend. WIN_PumpEvents() runs
periodic updates of the cursor clip region and disambiguation of
left and right shift keys in addition to standard event processing.
SDL_GetBasePath grows its path buffer for long paths, but GetModuleFileNameExW always truncates and succeeds,
so `len` was always equal to (buflen - 1) which is 127. This is easily fixed by checking for (buflen - 1) instead of buflen.
For paths longer than MAX_PATH, this problem sometimes got hidden by Windows path shortening ("C:\PROGRA~1\" etc.).
Tested on Windows 10 x64 19041 and 10586.
SDL_JoystickSetVirtualAxisInner() and SDL_JoystickSetVirtualHatInner()
did not properly sanitize the 'axis' and 'hat' parameters.
Signed-off-by: Paul Cercueil <paul@crapouillou.net>
Based on a patch by Jochen Schäfer <josch1710@live.de> :
The problem is, that in the initialization code uses the same structure for
desktop_mode and current_mode. See SDL_os2video.c:OS2_VideoInit():
stSDLDisplay.desktop_mode = stSDLDisplayMode;
stSDLDisplay.current_mode = stSDLDisplayMode;
...
stSDLDisplayMode.driverdata = pDisplayData;
Then, if you call GetDisplayModes, current_mode will added to the modes
list, with the same driverdata pointer to desktop_mode.
SDL_AddDisplayMode( display, &display->current_mode );
When VideoQuit gets called, first the modes list gets freed including the
driverdata, the desktop_mode gets freed. See SDL_video.c:SDL_VideoQuit():
for (j = display->num_display_modes; j--;) {
SDL_free(display->display_modes[j].driverdata);
display->display_modes[j].driverdata = NULL;
}
SDL_free(display->display_modes);
display->display_modes = NULL;
SDL_free(display->desktop_mode.driverdata);
display->desktop_mode.driverdata = NULL;
So, the display_modes[j].driverdata gets freed, but desktop_mode->driverdata
points to the same memory, but is not NULL'ed. When desktop_mode->driverdata
gets freed the memory is already freed, and libcx crashes the application on
SDL_Quit.
Based on a patch by Jochen Schäfer <josch1710@live.de> :
On a T420 pressing the ACPI button for volume control, big scancodes
were emitted. This was causing an overflow, because missing guards.
- Do not call IDirectInputDevice8_QueryInterface(device, &IID_IDirectInputDevice8,...) on DIRECTINPUTDEVICE8 device
- Get joystick VendorID and ProductID via IDirectInputDevice8_GetProperty(.., DIPROP_VIDPID, ..) call instead of messing with DIDEVICEINSTANCE.guidProduct
- Normalize HID device interface path to upper case for stable operation of XInput check
- Remove useless RawInput calls in SDL_IsXInputDevice() - just check for "IG_" string in HID device interface path that we already have
There shouldn't be any observable behavior changes.
We can be in a situation where we receive a win32 hook callback on the same
thread that is currently waiting. In that case, we do still need to trigger
a wakeup when an event is pushed because the hook itself won't necessarily
do that (depending on what we return from the hook).
When possible use native os functions to make a blocking call waiting for
an incoming event. Previous behavior was to continuously poll the event
queue with a small delay between each poll.
The blocking call uses a new optional video driver event,
WaitEventTimeout, if available. It is called only if an window
already shown is available. If present the window is designated
using the variable wakeup_window to receive a wakeup event if
needed.
The WaitEventTimeout function accept a timeout parameter. If
positive the call will wait for an event or return if the timeout
expired without any event. If the timeout is zero it will
implement a polling behavior. If the timeout is negative the
function will block indefinetely waiting for an event.
To let the main thread sees events sent form a different thread
a "wake-up" signal is sent to the main thread if the main thread
is in a blocking state. The wake-up event is sent to the designated
wakeup_window if present.
The wake-up event is sent only if the PushEvent call is coming
from a different thread. Before sending the wake-up event
the ID of the thread making the blocking call is saved using the
variable blocking_thread_id and it is compared to the current
thread's id to decide if the wake-up event should be sent.
Two new optional video device methods are introduced:
WaitEventTimeout
SendWakeupEvent
in addition the mutex
wakeup_lock
which is defined and initialized but only for the drivers supporting the
methods above.
If the methods are not present the system behaves as previously
performing a periodic polling of the events queue.
The blocking call is disabled if a joystick or sensor is detected
and falls back to previous behavior.
This add controller mappings for the Atari vcs (modern) controller as
well as the classic controller, for both bluetooth and USB connectivity.
Signed-off-by: Sjoerd Simons <sjoerd@collabora.com>
At least on bluetooth the guid user the version reported by the
bluetooth device. Which for Atari vcs controllers is the firmware
version. However the mapping will stay the same regardless of firmware
version, so ignore the version entirely to avoid needing a new mapping
entry for each firmware version.
Signed-off-by: Sjoerd Simons <sjoerd@collabora.com>
this variable was added in commit 2067a7db8e and
ultimately tracks if this is a surface's first present. checking if the current
bo is NULL provides the same functionality and cuts down on a redundant piece
of state potentially getting out of sync in the future
SetDisplayMode needs to recreate the EGL surfaces, which then need to be
bound along with the correct context in each rendering thread
commit 3a1d7d9c9a removed this behavior which
has broken using SetDisplayMode when rendering with multiple contexts
the commit message was rather vague, but if the surfaces do need to be
created immediately, this process probably needs to be split such that
surface is created immediately, but the binding is deferred