video: Return a failure code if the video driver fails to grab the mouse or keyboard

Alter the video driver grab/confinement function signatures to return an int, set and return an error if the grab request fails, and clear the grab flags from the window if the mouse and/or keyboard wasn't actually grabbed.
main
Frank Praznik 2024-03-05 15:26:14 -05:00
parent ae0caeef8d
commit 4c0601b93f
17 changed files with 89 additions and 49 deletions

View File

@ -246,9 +246,9 @@ struct SDL_VideoDevice
int (*SetWindowFullscreen)(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
void *(*GetWindowICCProfile)(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
SDL_DisplayID (*GetDisplayForWindow)(SDL_VideoDevice *_this, SDL_Window *window);
void (*SetWindowMouseRect)(SDL_VideoDevice *_this, SDL_Window *window);
void (*SetWindowMouseGrab)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
void (*SetWindowKeyboardGrab)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
int (*SetWindowMouseRect)(SDL_VideoDevice *_this, SDL_Window *window);
int (*SetWindowMouseGrab)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
int (*SetWindowKeyboardGrab)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
void (*DestroyWindow)(SDL_VideoDevice *_this, SDL_Window *window);
int (*CreateWindowFramebuffer)(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch);
int (*UpdateWindowFramebuffer)(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects);

View File

@ -3309,24 +3309,36 @@ void SDL_UpdateWindowGrab(SDL_Window *window)
}
if (_this->SetWindowMouseGrab) {
_this->SetWindowMouseGrab(_this, window, mouse_grabbed);
if (_this->SetWindowMouseGrab(_this, window, mouse_grabbed) < 0) {
window->flags &= ~SDL_WINDOW_MOUSE_GRABBED;
}
}
if (_this->SetWindowKeyboardGrab) {
_this->SetWindowKeyboardGrab(_this, window, keyboard_grabbed);
if (_this->SetWindowKeyboardGrab(_this, window, keyboard_grabbed) < 0) {
window->flags &= ~SDL_WINDOW_KEYBOARD_GRABBED;
}
}
if (_this->grabbed_window && !(_this->grabbed_window->flags & (SDL_WINDOW_MOUSE_GRABBED | SDL_WINDOW_KEYBOARD_GRABBED))) {
_this->grabbed_window = NULL;
}
}
int SDL_SetWindowGrab(SDL_Window *window, SDL_bool grabbed)
{
int ret_mouse_grab = 0;
int ret_keyboard_grab = 0;
CHECK_WINDOW_MAGIC(window, -1);
CHECK_WINDOW_NOT_POPUP(window, -1);
SDL_SetWindowMouseGrab(window, grabbed);
ret_mouse_grab = SDL_SetWindowMouseGrab(window, grabbed);
if (SDL_GetHintBoolean(SDL_HINT_GRAB_KEYBOARD, SDL_FALSE)) {
SDL_SetWindowKeyboardGrab(window, grabbed);
ret_keyboard_grab = SDL_SetWindowKeyboardGrab(window, grabbed);
}
return 0;
return (!ret_mouse_grab && !ret_keyboard_grab) ? 0 : -1;
}
int SDL_SetWindowKeyboardGrab(SDL_Window *window, SDL_bool grabbed)
@ -3352,6 +3364,10 @@ int SDL_SetWindowKeyboardGrab(SDL_Window *window, SDL_bool grabbed)
window->flags &= ~SDL_WINDOW_KEYBOARD_GRABBED;
}
SDL_UpdateWindowGrab(window);
if (grabbed && !(window->flags & SDL_WINDOW_KEYBOARD_GRABBED)) {
return -1;
}
return 0;
}
@ -3378,6 +3394,10 @@ int SDL_SetWindowMouseGrab(SDL_Window *window, SDL_bool grabbed)
window->flags &= ~SDL_WINDOW_MOUSE_GRABBED;
}
SDL_UpdateWindowGrab(window);
if (grabbed && !(window->flags & SDL_WINDOW_MOUSE_GRABBED)) {
return -1;
}
return 0;
}
@ -3419,7 +3439,7 @@ int SDL_SetWindowMouseRect(SDL_Window *window, const SDL_Rect *rect)
}
if (_this->SetWindowMouseRect) {
_this->SetWindowMouseRect(_this, window);
return _this->SetWindowMouseRect(_this, window);
}
return 0;
}

View File

@ -172,8 +172,8 @@ extern void Cocoa_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *windo
extern int Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern void *Cocoa_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
extern SDL_DisplayID Cocoa_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Cocoa_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window);
extern void Cocoa_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern int Cocoa_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window);
extern int Cocoa_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern void Cocoa_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern void Cocoa_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept);

View File

@ -2753,12 +2753,13 @@ SDL_DisplayID Cocoa_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Window *wind
}
}
void Cocoa_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window)
int Cocoa_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window)
{
Cocoa_UpdateClipCursor(window);
return 0;
}
void Cocoa_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
int Cocoa_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
{
@autoreleasepool {
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata;
@ -2777,6 +2778,8 @@ void Cocoa_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bo
}
}
}
return 0;
}
void Cocoa_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)

View File

@ -166,8 +166,9 @@ void HAIKU_SetWindowMinimumSize(SDL_VideoDevice *_this, SDL_Window * window) {
_ToBeWin(window)->PostMessage(&msg);
}
void HAIKU_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window * window, SDL_bool grabbed) {
int HAIKU_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window * window, SDL_bool grabbed) {
/* TODO: Implement this! */
return SDL_Unsupported();
}
void HAIKU_DestroyWindow(SDL_VideoDevice *_this, SDL_Window * window) {

View File

@ -38,7 +38,7 @@ extern void HAIKU_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void HAIKU_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered);
extern void HAIKU_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable);
extern int HAIKU_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern void HAIKU_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern int HAIKU_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern void HAIKU_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
#endif

View File

@ -319,8 +319,9 @@ void VITA_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
void VITA_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
}
void VITA_SetWindowGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
int VITA_SetWindowGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
{
return 0;
}
void VITA_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)

View File

@ -72,7 +72,7 @@ void VITA_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window);
void VITA_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
void VITA_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
void VITA_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window);
void VITA_SetWindowGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
int VITA_SetWindowGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
void VITA_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
#ifdef SDL_VIDEO_DRIVER_VITA

View File

@ -3303,11 +3303,11 @@ int Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *wi
struct wl_region *confine_rect;
if (!d->pointer_constraints) {
return -1;
return SDL_SetError("Failed to confine pointer: compositor lacks support for the required zwp_pointer_constraints_v1 protocol");
}
if (!input->pointer) {
return -1;
return SDL_SetError("No pointer to confine");
}
/* A confine may already be active, in which case we should destroy it and
@ -3375,7 +3375,7 @@ int Wayland_input_grab_keyboard(SDL_Window *window, struct SDL_WaylandInput *inp
SDL_VideoData *d = input->display;
if (!d->key_inhibitor_manager) {
return -1;
return SDL_SetError("Failed to grab keyboard: compositor lacks support for the required zwp_keyboard_shortcuts_inhibit_manager_v1 protocol");
}
if (w->key_inhibitor) {

View File

@ -2095,7 +2095,7 @@ void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
}
void Wayland_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window)
int Wayland_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_VideoData *data = _this->driverdata;
@ -2108,31 +2108,33 @@ void Wayland_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window)
* lets you confine without a rect.
*/
if (SDL_RectEmpty(&window->mouse_rect) && !(window->flags & SDL_WINDOW_MOUSE_GRABBED)) {
Wayland_input_unconfine_pointer(data->input, window);
return Wayland_input_unconfine_pointer(data->input, window);
} else {
Wayland_input_confine_pointer(data->input, window);
return Wayland_input_confine_pointer(data->input, window);
}
}
void Wayland_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
int Wayland_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
{
SDL_VideoData *data = _this->driverdata;
if (grabbed) {
Wayland_input_confine_pointer(data->input, window);
return Wayland_input_confine_pointer(data->input, window);
} else if (SDL_RectEmpty(&window->mouse_rect)) {
Wayland_input_unconfine_pointer(data->input, window);
return Wayland_input_unconfine_pointer(data->input, window);
}
return 0;
}
void Wayland_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
int Wayland_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
{
SDL_VideoData *data = _this->driverdata;
if (grabbed) {
Wayland_input_grab_keyboard(window, data->input);
return Wayland_input_grab_keyboard(window, data->input);
} else {
Wayland_input_ungrab_keyboard(window);
return Wayland_input_ungrab_keyboard(window);
}
}

View File

@ -184,9 +184,9 @@ extern int Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *windo
SDL_bool fullscreen);
extern void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Wayland_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window);
extern void Wayland_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern void Wayland_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern int Wayland_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window);
extern int Wayland_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern int Wayland_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Wayland_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered);
extern void Wayland_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable);

View File

@ -1376,23 +1376,27 @@ void WIN_UngrabKeyboard(SDL_Window *window)
}
}
void WIN_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window)
int WIN_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window)
{
WIN_UpdateClipCursor(window);
return 0;
}
void WIN_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
int WIN_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
{
WIN_UpdateClipCursor(window);
return 0;
}
void WIN_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
int WIN_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
{
if (grabbed) {
WIN_GrabKeyboard(window);
} else {
WIN_UngrabKeyboard(window);
}
return 0;
}
#endif /*!defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)*/

View File

@ -111,9 +111,9 @@ extern void WIN_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window,
extern int WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern void WIN_UpdateWindowICCProfile(SDL_Window *window, SDL_bool send_event);
extern void *WIN_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
extern void WIN_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window);
extern void WIN_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern void WIN_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern int WIN_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window);
extern int WIN_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern int WIN_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern void WIN_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void WIN_OnWindowEnter(SDL_VideoDevice *_this, SDL_Window *window);
extern void WIN_UpdateClipCursor(SDL_Window *window);

View File

@ -1705,13 +1705,13 @@ void *X11_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t
return ret_icc_profile_data;
}
void X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
int X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
{
SDL_WindowData *data = window->driverdata;
Display *display;
if (!data) {
return;
return SDL_SetError("Invalid window data");
}
data->mouse_grabbed = SDL_FALSE;
@ -1722,7 +1722,7 @@ void X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool
so when we get a MapNotify later, we'll try to update the grab as
appropriate. */
if (window->flags & SDL_WINDOW_HIDDEN) {
return;
return 0;
}
/* Try to grab the mouse */
@ -1743,7 +1743,6 @@ void X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool
}
if (result != GrabSuccess) {
SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "The X server refused to let us grab the mouse. You might experience input bugs.");
data->videodata->broken_pointer_grab = SDL_TRUE; /* don't try again. */
}
}
@ -1758,15 +1757,21 @@ void X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool
X11_Xinput2UngrabTouch(_this, window);
}
X11_XSync(display, False);
if (!data->videodata->broken_pointer_grab) {
return 0;
} else {
return SDL_SetError("The X server refused to let us grab the mouse. You might experience input bugs.");
}
}
void X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
int X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
{
SDL_WindowData *data = window->driverdata;
Display *display;
if (!data) {
return;
return SDL_SetError("Invalid window data");
}
display = data->videodata->display;
@ -1776,7 +1781,7 @@ void X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_b
so when we get a MapNotify later, we'll try to update the grab as
appropriate. */
if (window->flags & SDL_WINDOW_HIDDEN) {
return;
return 0;
}
X11_XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
@ -1785,6 +1790,8 @@ void X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_b
X11_XUngrabKeyboard(display, CurrentTime);
}
X11_XSync(display, False);
return 0;
}
void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)

View File

@ -126,8 +126,8 @@ extern void X11_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, S
extern void X11_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top);
extern int X11_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern void *X11_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
extern void X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern void X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern int X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern int X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern void X11_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept);

View File

@ -84,7 +84,7 @@ int X11_GetXFixesSelectionNotifyEvent()
return xfixes_selection_notify_event;
}
void X11_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window)
int X11_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window)
{
if (SDL_RectEmpty(&window->mouse_rect)) {
X11_ConfineCursorWithFlags(_this, window, NULL, 0);
@ -100,6 +100,8 @@ void X11_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window)
wdata->pointer_barrier_active = SDL_TRUE;
}
}
return 0;
}
int X11_ConfineCursorWithFlags(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rect, int flags)

View File

@ -30,7 +30,7 @@
extern void X11_InitXfixes(SDL_VideoDevice *_this);
extern int X11_XfixesIsInitialized(void);
extern void X11_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window);
extern int X11_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window);
extern int X11_ConfineCursorWithFlags(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rect, int flags);
extern void X11_DestroyPointerBarrier(SDL_VideoDevice *_this, SDL_Window *window);
extern int X11_GetXFixesSelectionNotifyEvent(void);