Added SDL_GetDisplayUsableBounds().

This commit is contained in:
Ryan C. Gordon 2016-01-04 23:52:40 -05:00
parent 8875a4014f
commit c3114975db
20 changed files with 228 additions and 1 deletions

View File

@ -116,6 +116,7 @@ test/testtimer
test/testver
test/testviewport
test/testwm2
test/testbounds
test/torturethread
test/testdisplayinfo
test/*.exe

View File

@ -311,6 +311,25 @@ extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(int displayIndex, SDL_Rect * re
*/
extern DECLSPEC int SDLCALL SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi);
/**
* \brief Get the usable desktop area represented by a display, with the
* primary display located at 0,0
*
* This is the same area as SDL_GetDisplayBounds() reports, but with portions
* reserved by the system removed. For example, on Mac OS X, this subtracts
* the area occupied by the menu bar and dock.
*
* Setting a window to be fullscreen generally bypasses these unusable areas,
* so these are good guidelines for the maximum space available to a
* non-fullscreen window.
*
* \return 0 on success, or -1 if the index is out of range.
*
* \sa SDL_GetDisplayBounds()
* \sa SDL_GetNumVideoDisplays()
*/
extern DECLSPEC int SDLCALL SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect);
/**
* \brief Returns the number of available display modes.
*

View File

@ -597,3 +597,4 @@
#define SDL_JoystickCurrentPowerLevel SDL_JoystickCurrentPowerLevel_REAL
#define SDL_GameControllerFromInstanceID SDL_GameControllerFromInstanceID_REAL
#define SDL_JoystickFromInstanceID SDL_JoystickFromInstanceID_REAL
#define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL

View File

@ -631,3 +631,4 @@ SDL_DYNAPI_PROC(int,SDL_GetDisplayDPI,(int a, float *b, float *c, float *d),(a,b
SDL_DYNAPI_PROC(SDL_JoystickPowerLevel,SDL_JoystickCurrentPowerLevel,(SDL_Joystick *a),(a),return)
SDL_DYNAPI_PROC(SDL_GameController*,SDL_GameControllerFromInstanceID,(SDL_JoystickID a),(a),return)
SDL_DYNAPI_PROC(SDL_Joystick*,SDL_JoystickFromInstanceID,(SDL_JoystickID a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetDisplayUsableBounds,(int a, SDL_Rect *b),(a,b),return)

View File

@ -175,6 +175,11 @@ struct SDL_VideoDevice
*/
int (*GetDisplayDPI) (_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi);
/*
* Get the usable bounds of a display (bounds minus menubar or whatever)
*/
int (*GetDisplayUsableBounds) (_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
/*
* Get a list of the available display modes for a display.
*/

View File

@ -684,7 +684,26 @@ SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
rect->w = display->current_mode.w;
rect->h = display->current_mode.h;
}
return 0;
return 0; /* !!! FIXME: should this be an error if (rect==NULL) ? */
}
int SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect)
{
CHECK_DISPLAY_INDEX(displayIndex, -1);
if (rect) {
SDL_VideoDisplay *display = &_this->displays[displayIndex];
if (_this->GetDisplayUsableBounds) {
if (_this->GetDisplayUsableBounds(_this, display, rect) == 0) {
return 0;
}
}
/* Oh well, just give the entire display bounds. */
return SDL_GetDisplayBounds(displayIndex, rect);
}
return 0; /* !!! FIXME: should this be an error if (rect==NULL) ? */
}
int

View File

@ -35,6 +35,7 @@ typedef struct
extern void Cocoa_InitModes(_THIS);
extern int Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
extern int Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
extern void Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
extern int Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
extern void Cocoa_QuitModes(_THIS);

View File

@ -19,6 +19,7 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#include "SDL_assert.h"
#if SDL_VIDEO_DRIVER_COCOA
@ -338,6 +339,41 @@ Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
return 0;
}
int
Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
{
SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
const CGDirectDisplayID cgdisplay = displaydata->display;
NSArray *screens = [NSScreen screens];
NSScreen *screen = nil;
/* !!! FIXME: maybe track the NSScreen in SDL_DisplayData? */
for (NSScreen *i in screens) {
const CGDirectDisplayID thisDisplay = (CGDirectDisplayID) [[[i deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
if (thisDisplay == cgdisplay) {
screen = i;
break;
}
}
SDL_assert(screen != nil); /* didn't find it?! */
if (screen == nil) {
return -1;
}
const CGRect cgrect = CGDisplayBounds(cgdisplay);
const NSRect frame = [screen visibleFrame];
// !!! FIXME: I assume -[NSScreen visibleFrame] is relative to the origin of the screen in question and not the whole desktop.
// !!! FIXME: The math vs CGDisplayBounds might be incorrect if that's not the case, though. Check this.
rect->x = (int)(cgrect.origin.x + frame.origin.x);
rect->y = (int)(cgrect.origin.y + frame.origin.y);
rect->w = (int)frame.size.width;
rect->h = (int)frame.size.height;
return 0;
}
void
Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
{

View File

@ -73,6 +73,7 @@ Cocoa_CreateDevice(int devindex)
device->VideoInit = Cocoa_VideoInit;
device->VideoQuit = Cocoa_VideoQuit;
device->GetDisplayBounds = Cocoa_GetDisplayBounds;
device->GetDisplayUsableBounds = Cocoa_GetDisplayUsableBounds;
device->GetDisplayModes = Cocoa_GetDisplayModes;
device->SetDisplayMode = Cocoa_SetDisplayMode;
device->PumpEvents = Cocoa_PumpEvents;

View File

@ -43,6 +43,7 @@ extern int UIKit_InitModes(_THIS);
extern void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
extern int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
extern void UIKit_QuitModes(_THIS);
extern int UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
#endif /* _SDL_uikitmodes_h */

View File

@ -242,6 +242,26 @@ UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
return 0;
}
int
UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
{
/* the default function iterates displays to make a fake offset,
as if all the displays were side-by-side, which is fine for iOS. */
const int displayIndex = (int) (display - _this->displays);
if (SDL_GetDisplayBounds(displayIndex, rect) < 0) {
return -1;
}
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
const CGRect frame = [data->uiscreen applicationFrame];
const float scale = (float) data->scale;
rect->x += (int) (frame.origin.x * scale);
rect->y += (int) (frame.origin.y * scale);
rect->w = (int) (frame.size.width * scale);
rect->h = (int) (frame.size.height * scale);
return 0;
}
void
UIKit_QuitModes(_THIS)
{

View File

@ -85,6 +85,7 @@ UIKit_CreateDevice(int devindex)
device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
device->DestroyWindow = UIKit_DestroyWindow;
device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds;
#if SDL_IPHONE_KEYBOARD
device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;

View File

@ -332,6 +332,43 @@ WIN_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi,
return data->DiagDPI != 0.0f ? 0 : -1;
}
int
WIN_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
{
const SDL_DisplayModeData *data = (const SDL_DisplayModeData *) display->current_mode.driverdata;
const DEVMODE *pDevMode = &data->DeviceMode;
POINT pt = {
/* !!! FIXME: no scale, right? */
(LONG) (pDevMode->dmPosition.x + (pDevMode->dmPelsWidth / 2)),
(LONG) (pDevMode->dmPosition.y + (pDevMode->dmPelsHeight / 2))
};
HMONITOR hmon = MonitorFromPoint(&pt, MONITOR_DEFAULTTONULL);
MONITORINFO minfo;
const RECT *work;
BOOL rc = FALSE;
SDL_assert(hmon != NULL);
if (hmon != NULL) {
SDL_zero(minfo);
minfo.cbSize = sizeof (MONITORINFO);
rc = GetMonitorInfo(hmon, &minfo);
SDL_assert(rc);
}
if (!rc) {
return SDL_SetError("Couldn't find monitor data");
}
work = &minfo->rcWork;
rect->x = (int)SDL_ceil(work->left * data->ScaleX);
rect->y = (int)SDL_ceil(work->top * data->ScaleY);
rect->w = (int)SDL_ceil((work->right - work->left) * data->ScaleX);
rect->h = (int)SDL_ceil((work->bottom - work->top) * data->ScaleY);
return 0;
}
void
WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
{

View File

@ -40,6 +40,7 @@ typedef struct
extern int WIN_InitModes(_THIS);
extern int WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
extern int WIN_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
extern int WIN_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi);
extern void WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
extern int WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);

View File

@ -124,6 +124,7 @@ WIN_CreateDevice(int devindex)
device->VideoInit = WIN_VideoInit;
device->VideoQuit = WIN_VideoQuit;
device->GetDisplayBounds = WIN_GetDisplayBounds;
device->GetDisplayUsableBounds = WIN_GetDisplayUsableBounds;
device->GetDisplayDPI = WIN_GetDisplayDPI;
device->GetDisplayModes = WIN_GetDisplayModes;
device->SetDisplayMode = WIN_SetDisplayMode;

View File

@ -1073,6 +1073,43 @@ X11_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * h
return data->ddpi != 0.0f ? 0 : -1;
}
int
X11_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
Display *display = data->display;
Atom _NET_WORKAREA;
int status, real_format;
int retval = -1;
Atom real_type;
unsigned long items_read = 0, items_left = 0;
unsigned char *propdata = NULL;
if (X11_GetDisplayBounds(_this, sdl_display, rect) < 0) {
return -1;
}
_NET_WORKAREA = X11_XInternAtom(display, "_NET_WORKAREA", False);
status = X11_XGetWindowProperty(display, DefaultRootWindow(display),
_NET_WORKAREA, 0L, 4L, False, XA_CARDINAL,
&real_type, &real_format, &items_read,
&items_left, &propdata);
if ((status == Success) && (items_read >= 4)) {
retval = 0;
const long *p = (long*) propdata;
const SDL_Rect usable = { (int)p[0], (int)p[1], (int)p[2], (int)p[3] };
if (!SDL_IntersectRect(rect, &usable, rect)) {
SDL_zerop(rect);
}
}
if (propdata) {
X11_XFree(propdata);
}
return retval;
}
#endif /* SDL_VIDEO_DRIVER_X11 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -77,6 +77,7 @@ extern int X11_GetVisualInfoFromVisual(Display * display, Visual * visual,
extern Uint32 X11_GetPixelFormatFromVisualInfo(Display * display,
XVisualInfo * vinfo);
extern int X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect);
extern int X11_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect);
extern int X11_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * hdpi, float * vdpi);
#endif /* _SDL_x11modes_h */

View File

@ -218,6 +218,7 @@ X11_CreateDevice(int devindex)
device->VideoQuit = X11_VideoQuit;
device->GetDisplayModes = X11_GetDisplayModes;
device->GetDisplayBounds = X11_GetDisplayBounds;
device->GetDisplayUsableBounds = X11_GetDisplayUsableBounds;
device->GetDisplayDPI = X11_GetDisplayDPI;
device->SetDisplayMode = X11_SetDisplayMode;
device->SuspendScreenSaver = X11_SuspendScreenSaver;

View File

@ -14,6 +14,7 @@ TARGETS = \
testatomic$(EXE) \
testaudioinfo$(EXE) \
testautomation$(EXE) \
testbounds$(EXE) \
testdraw2$(EXE) \
testdrawchessboard$(EXE) \
testdropfile$(EXE) \
@ -270,6 +271,9 @@ testmessage$(EXE): $(srcdir)/testmessage.c
testdisplayinfo$(EXE): $(srcdir)/testdisplayinfo.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
testbounds$(EXE): $(srcdir)/testbounds.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
controllermap$(EXE): $(srcdir)/controllermap.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)

39
test/testbounds.c Normal file
View File

@ -0,0 +1,39 @@
/*
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely.
*/
#include "SDL.h"
int main(int argc, char **argv)
{
int total, i;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
SDL_Log("SDL_Init(SDL_INIT_VIDEO) failed: %s", SDL_GetError());
}
total = SDL_GetNumVideoDisplays();
for (i = 0; i < total; i++) {
SDL_Rect bounds = { -1,-1,-1,-1 }, usable = { -1,-1,-1,-1 };
SDL_GetDisplayBounds(i, &bounds);
SDL_GetDisplayUsableBounds(i, &usable);
SDL_Log("Display #%d ('%s'): bounds={(%d,%d),%dx%d}, usable={(%d,%d),%dx%d}",
i, SDL_GetDisplayName(i),
bounds.x, bounds.y, bounds.w, bounds.h,
usable.x, usable.y, usable.w, usable.h);
}
SDL_Quit();
return 0;
}
/* vi: set ts=4 sw=4 expandtab: */