diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 56a78c7fc3..533178086f 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -506,7 +506,7 @@ static void X11_DispatchUnmapNotify(SDL_WindowData *data) SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); } -static void InitiateWindowMove(SDL_VideoDevice *_this, const SDL_WindowData *data, const SDL_Point *point) +static void DispatchWindowMove(SDL_VideoDevice *_this, const SDL_WindowData *data, const SDL_Point *point) { SDL_VideoData *viddata = _this->driverdata; SDL_Window *window = data->window; @@ -531,6 +531,12 @@ static void InitiateWindowMove(SDL_VideoDevice *_this, const SDL_WindowData *dat X11_XSync(display, 0); } +static void ScheduleWindowMove(SDL_VideoDevice *_this, SDL_WindowData *data, const SDL_Point *point) +{ + data->pending_move = SDL_TRUE; + data->pending_move_point = *point; +} + static void InitiateWindowResize(SDL_VideoDevice *_this, const SDL_WindowData *data, const SDL_Point *point, int direction) { SDL_VideoData *viddata = _this->driverdata; @@ -574,7 +580,7 @@ SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const return SDL_TRUE; } -SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y) +SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y) { SDL_Window *window = data->window; @@ -589,7 +595,14 @@ SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, const SDL_WindowData * switch (data->hit_test_result) { case SDL_HITTEST_DRAGGABLE: - InitiateWindowMove(_this, data, &point); + /* Some window managers get in a bad state when a move event starts while input is transitioning + to the SDL window. This can happen when clicking on a drag region of an unfocused window + where the same mouse down event will trigger a drag event and a window activate. */ + if (data->window->flags & SDL_WINDOW_INPUT_FOCUS) { + DispatchWindowMove(_this, data, &point); + } else { + ScheduleWindowMove(_this, data, &point); + } return SDL_TRUE; case SDL_HITTEST_RESIZE_TOPLEFT: @@ -1719,6 +1732,12 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h); } } + if ((flags & SDL_WINDOW_INPUT_FOCUS)) { + if (data->pending_move) { + DispatchWindowMove(_this, data, &data->pending_move_point); + data->pending_move = SDL_FALSE; + } + } } if (changed & SDL_WINDOW_OCCLUDED) { SDL_SendWindowEvent(data->window, (flags & SDL_WINDOW_OCCLUDED) ? SDL_EVENT_WINDOW_OCCLUDED : SDL_EVENT_WINDOW_EXPOSED, 0, 0); diff --git a/src/video/x11/SDL_x11events.h b/src/video/x11/SDL_x11events.h index 4863a2435a..3e34064e05 100644 --- a/src/video/x11/SDL_x11events.h +++ b/src/video/x11/SDL_x11events.h @@ -33,6 +33,6 @@ extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *wdata, extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button); extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window); extern SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, SDL_bool force_new_result); -extern SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y); +extern SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y); #endif /* SDL_x11events_h_ */ diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index e0f7549b94..454e92a56a 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -63,6 +63,8 @@ struct SDL_WindowData Uint64 last_focus_event_time; PendingFocusEnum pending_focus; Uint64 pending_focus_time; + SDL_bool pending_move; + SDL_Point pending_move_point; XConfigureEvent last_xconfigure; struct SDL_VideoData *videodata; unsigned long user_time;