diff --git a/include/SDL_video.h b/include/SDL_video.h index 8e6d317a6..cf733e4b9 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -597,6 +597,31 @@ extern DECLSPEC int SDLCALL SDL_GetCurrentDisplayMode(int displayIndex, SDL_Disp */ extern DECLSPEC SDL_DisplayMode * SDLCALL SDL_GetClosestDisplayMode(int displayIndex, const SDL_DisplayMode * mode, SDL_DisplayMode * closest); +/** + * Get the index of the display containing a point + * + * \param point the point to query + * \returns the index of the display containing the point or a negative + * error code on failure; call SDL_GetError() for more information. + * + * \sa SDL_GetDisplayBounds + * \sa SDL_GetNumVideoDisplays + */ +extern DECLSPEC int SDLCALL SDL_GetPointDisplayIndex(const SDL_Point * point); + +/** + * Get the index of the display primarily containing a rect + * + * \param rect the rect to query + * \returns the index of the display entirely containing the rect or closest + * to the center of the rect on success or a negative error code on + * failure; call SDL_GetError() for more information. + * + * \sa SDL_GetDisplayBounds + * \sa SDL_GetNumVideoDisplays + */ +extern DECLSPEC int SDLCALL SDL_GetRectDisplayIndex(const SDL_Rect * rect); + /** * Get the index of the display associated with a window. * diff --git a/src/dynapi/SDL2.exports b/src/dynapi/SDL2.exports index e5aed22d0..80d15ee5a 100644 --- a/src/dynapi/SDL2.exports +++ b/src/dynapi/SDL2.exports @@ -854,3 +854,5 @@ ++'_SDL_GetOriginalMemoryFunctions'.'SDL2.dll'.'SDL_GetOriginalMemoryFunctions' ++'_SDL_ResetKeyboard'.'SDL2.dll'.'SDL_ResetKeyboard' ++'_SDL_GetDefaultAudioInfo'.'SDL2.dll'.'SDL_GetDefaultAudioInfo' +++'_SDL_GetPointDisplayIndex'.'SDL2.dll'.'SDL_GetPointDisplayIndex' +++'_SDL_GetRectDisplayIndex'.'SDL2.dll'.'SDL_GetRectDisplayIndex' diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 8e26c34ac..91f13c3e3 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -880,3 +880,5 @@ #define SDL_GetOriginalMemoryFunctions SDL_GetOriginalMemoryFunctions_REAL #define SDL_ResetKeyboard SDL_ResetKeyboard_REAL #define SDL_GetDefaultAudioInfo SDL_GetDefaultAudioInfo_REAL +#define SDL_GetPointDisplayIndex SDL_GetPointDisplayIndex_REAL +#define SDL_GetRectDisplayIndex SDL_GetRectDisplayIndex_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 6b4c5c7dd..f23cdf7c9 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -963,3 +963,5 @@ SDL_DYNAPI_PROC(int,SDL_GDKRunApp,(SDL_main_func a, void *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_GetOriginalMemoryFunctions,(SDL_malloc_func *a, SDL_calloc_func *b, SDL_realloc_func *c, SDL_free_func *d),(a,b,c,d),) SDL_DYNAPI_PROC(void,SDL_ResetKeyboard,(void),(),) SDL_DYNAPI_PROC(int,SDL_GetDefaultAudioInfo,(char **a, SDL_AudioSpec *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_GetPointDisplayIndex,(const SDL_Point *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_GetRectDisplayIndex,(const SDL_Rect *a),(a),return) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 435ab12dc..cf0ab8c44 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -506,6 +506,8 @@ extern float SDL_ComputeDiagonalDPI(int hpix, int vpix, float hinches, float vin extern void SDL_ToggleDragAndDropSupport(void); +extern int SDL_GetPointDisplayIndex(const SDL_Point * point); + #endif /* SDL_sysvideo_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index ecce5516c..92896bf38 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1072,6 +1072,82 @@ SDL_GetDisplay(int displayIndex) return &_this->displays[displayIndex]; } +/** + * If x, y are outside of rect, snaps them to the closest point inside rect + * (between rect->x, rect->y, inclusive, and rect->x + w, rect->y + h, exclusive) + */ +static void +SDL_GetClosestPointOnRect(const SDL_Rect *rect, SDL_Point *point) +{ + const int right = rect->x + rect->w - 0; + const int bottom = rect->y + rect->h - 0; + + if (point->x < rect->x) { + point->x = rect->x; + } else if (point->x > right) { + point->x = right; + } + + if (point->y < rect->y) { + point->y = rect->y; + } else if (point->y > bottom) { + point->y = bottom; + } +} + +static int +GetRectDisplayIndex(int x, int y, int w, int h) +{ + int i, dist; + int closest = -1; + int closest_dist = 0x7FFFFFFF; + SDL_Point closest_point_on_display; + SDL_Point delta; + SDL_Point center; + center.x = x + w / 2; + center.y = y + h / 2; + + for (i = 0; i < _this->num_displays; ++i) { + SDL_Rect display_rect; + SDL_GetDisplayBounds(i, &display_rect); + + /* Check if the window is fully enclosed */ + if (SDL_EnclosePoints(¢er, 1, &display_rect, NULL)) { + return i; + } + + /* Snap window center to the display rect */ + closest_point_on_display = center; + SDL_GetClosestPointOnRect(&display_rect, &closest_point_on_display); + + delta.x = center.x - closest_point_on_display.x; + delta.y = center.y - closest_point_on_display.y; + dist = (delta.x*delta.x + delta.y*delta.y); + if (dist < closest_dist) { + closest = i; + closest_dist = dist; + } + } + + if (closest < 0) { + SDL_SetError("Couldn't find any displays"); + } + + return closest; +} + +int +SDL_GetPointDisplayIndex(const SDL_Point *point) +{ + return GetRectDisplayIndex(point->x, point->y, 1, 1); +} + +int +SDL_GetRectDisplayIndex(const SDL_Rect *rect) +{ + return GetRectDisplayIndex(rect->x, rect->y, rect->w, rect->h); +} + int SDL_GetWindowDisplayIndex(SDL_Window * window) { @@ -1089,13 +1165,7 @@ SDL_GetWindowDisplayIndex(SDL_Window * window) if (displayIndex >= 0) { return displayIndex; } else { - int i, dist; - int closest = -1; - int closest_dist = 0x7FFFFFFF; - SDL_Point center; - SDL_Point delta; - SDL_Rect rect; - + int i; if (SDL_WINDOWPOS_ISUNDEFINED(window->x) || SDL_WINDOWPOS_ISCENTERED(window->x)) { displayIndex = (window->x & 0xFFFF); @@ -1113,7 +1183,7 @@ SDL_GetWindowDisplayIndex(SDL_Window * window) return displayIndex; } - /* Find the display containing the window */ + /* Find the display containing the window if fullscreen */ for (i = 0; i < _this->num_displays; ++i) { SDL_VideoDisplay *display = &_this->displays[i]; @@ -1121,26 +1191,8 @@ SDL_GetWindowDisplayIndex(SDL_Window * window) return i; } } - center.x = window->x + window->w / 2; - center.y = window->y + window->h / 2; - for (i = 0; i < _this->num_displays; ++i) { - SDL_GetDisplayBounds(i, &rect); - if (SDL_EnclosePoints(¢er, 1, &rect, NULL)) { - return i; - } - delta.x = center.x - (rect.x + rect.w / 2); - delta.y = center.y - (rect.y + rect.h / 2); - dist = (delta.x*delta.x + delta.y*delta.y); - if (dist < closest_dist) { - closest = i; - closest_dist = dist; - } - } - if (closest < 0) { - SDL_SetError("Couldn't find any displays"); - } - return closest; + return GetRectDisplayIndex(window->x, window->y, window->w, window->h); } } diff --git a/src/video/windows/SDL_windowsmodes.c b/src/video/windows/SDL_windowsmodes.c index 16cba5114..098b253bb 100644 --- a/src/video/windows/SDL_windowsmodes.c +++ b/src/video/windows/SDL_windowsmodes.c @@ -552,72 +552,6 @@ WIN_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect) return 0; } -/** - * If x, y are outside of rect, snaps them to the closest point inside rect - * (between rect->x, rect->y, inclusive, and rect->x + w, rect->y + h, exclusive) - */ -static void -SDL_GetClosestPointOnRect(const SDL_Rect *rect, int *x, int *y) -{ - const int right = rect->x + rect->w - 1; - const int bottom = rect->y + rect->h - 1; - - if (*x < rect->x) { - *x = rect->x; - } else if (*x > right) { - *x = right; - } - - if (*y < rect->y) { - *y = rect->y; - } else if (*y > bottom) { - *y = bottom; - } -} - -/** - * Returns the display index of the display which either encloses the given point - * or is closest to it. The point is in SDL screen coordinates. - */ -static int -SDL_GetPointDisplayIndex(int x, int y) -{ - int i, dist; - int closest = -1; - int closest_dist = 0x7FFFFFFF; - SDL_Point closest_point_on_display; - SDL_Point delta; - SDL_Rect rect; - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - SDL_Point point; - point.x = x; - point.y = y; - - for (i = 0; i < _this->num_displays; ++i) { - /* Check for an exact match */ - SDL_GetDisplayBounds(i, &rect); - if (SDL_EnclosePoints(&point, 1, &rect, NULL)) { - return i; - } - - /* Snap x, y to the display rect */ - closest_point_on_display = point; - SDL_GetClosestPointOnRect(&rect, &closest_point_on_display.x, &closest_point_on_display.y); - - delta.x = point.x - closest_point_on_display.x; - delta.y = point.y - closest_point_on_display.y; - dist = (delta.x*delta.x + delta.y*delta.y); - if (dist < closest_dist) { - closest = i; - closest_dist = dist; - } - } - if (closest < 0) { - SDL_SetError("Couldn't find any displays"); - } - return closest; -} - /** * Convert a point from the SDL coordinate system (monitor origins are in pixels, * offset within a monitor in DPI-scaled points) to Windows virtual screen coordinates (pixels). @@ -634,6 +568,9 @@ void WIN_ScreenPointFromSDL(int *x, int *y, int *dpiOut) SDL_Rect bounds; float ddpi, hdpi, vdpi; int x_sdl, y_sdl; + SDL_Point point; + point.x = *x; + point.y = *y; if (dpiOut) { *dpiOut = 96; @@ -649,7 +586,7 @@ void WIN_ScreenPointFromSDL(int *x, int *y, int *dpiOut) } /* Can't use MonitorFromPoint for this because we currently have SDL coordinates, not pixels */ - displayIndex = SDL_GetPointDisplayIndex(*x, *y); + displayIndex = SDL_GetPointDisplayIndex(&point); if (displayIndex < 0) { return;