Skip to content

Commit

Permalink
Added SDL_GetDisplayUsableBounds().
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Jan 5, 2016
1 parent 8875a40 commit c311497
Show file tree
Hide file tree
Showing 20 changed files with 228 additions and 1 deletion.
1 change: 1 addition & 0 deletions .hgignore
Expand Up @@ -116,6 +116,7 @@ test/testtimer
test/testver
test/testviewport
test/testwm2
test/testbounds
test/torturethread
test/testdisplayinfo
test/*.exe
Expand Down
19 changes: 19 additions & 0 deletions include/SDL_video.h
Expand Up @@ -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.
*
Expand Down
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Expand Up @@ -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
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_procs.h
Expand Up @@ -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)
5 changes: 5 additions & 0 deletions src/video/SDL_sysvideo.h
Expand Up @@ -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.
*/
Expand Down
21 changes: 20 additions & 1 deletion src/video/SDL_video.c
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/video/cocoa/SDL_cocoamodes.h
Expand Up @@ -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);
Expand Down
36 changes: 36 additions & 0 deletions src/video/cocoa/SDL_cocoamodes.m
Expand Up @@ -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

Expand Down Expand Up @@ -338,6 +339,41 @@
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)
{
Expand Down
1 change: 1 addition & 0 deletions src/video/cocoa/SDL_cocoavideo.m
Expand Up @@ -73,6 +73,7 @@
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;
Expand Down
1 change: 1 addition & 0 deletions src/video/uikit/SDL_uikitmodes.h
Expand Up @@ -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 */

Expand Down
20 changes: 20 additions & 0 deletions src/video/uikit/SDL_uikitmodes.m
Expand Up @@ -242,6 +242,26 @@ @implementation SDL_DisplayModeData
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)
{
Expand Down
1 change: 1 addition & 0 deletions src/video/uikit/SDL_uikitvideo.m
Expand Up @@ -85,6 +85,7 @@ static void UIKit_DeleteDevice(SDL_VideoDevice * device)
device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
device->DestroyWindow = UIKit_DestroyWindow;
device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds;

#if SDL_IPHONE_KEYBOARD
device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
Expand Down
37 changes: 37 additions & 0 deletions src/video/windows/SDL_windowsmodes.c
Expand Up @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions src/video/windows/SDL_windowsmodes.h
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/video/windows/SDL_windowsvideo.c
Expand Up @@ -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;
Expand Down
37 changes: 37 additions & 0 deletions src/video/x11/SDL_x11modes.c
Expand Up @@ -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: */
1 change: 1 addition & 0 deletions src/video/x11/SDL_x11modes.h
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions src/video/x11/SDL_x11video.c
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions test/Makefile.in
Expand Up @@ -14,6 +14,7 @@ TARGETS = \
testatomic$(EXE) \
testaudioinfo$(EXE) \
testautomation$(EXE) \
testbounds$(EXE) \
testdraw2$(EXE) \
testdrawchessboard$(EXE) \
testdropfile$(EXE) \
Expand Down Expand Up @@ -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)

Expand Down
39 changes: 39 additions & 0 deletions test/testbounds.c
@@ -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: */

0 comments on commit c311497

Please sign in to comment.