diff -r bc074eca6597 include/SDL_video.h --- a/include/SDL_video.h Sat Nov 15 15:07:55 2014 -0500 +++ b/include/SDL_video.h Wed Nov 19 08:45:03 2014 -0600 @@ -290,6 +290,16 @@ extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect); /** + * \brief Get the display's working area exclusive of taskbars and docks. + * + * \return 0 on success, or -1 if the index is out of range or + * the working area could not be determined. + * + * \sa SDL_GetNumVideoDisplays() + */ +extern DECLSPEC int SDLCALL SDL_GetDisplayWorkingAreaBounds(int displayIndex, SDL_Rect * rect); + +/** * \brief Returns the number of available display modes. * * \sa SDL_GetDisplayMode() diff -r bc074eca6597 src/video/SDL_sysvideo.h --- a/src/video/SDL_sysvideo.h Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/SDL_sysvideo.h Wed Nov 19 08:45:03 2014 -0600 @@ -171,6 +171,12 @@ int (*GetDisplayBounds) (_THIS, SDL_VideoDisplay * display, SDL_Rect * rect); /* + * Get the bounds of the display working area exclusive of things like + * taskbars and docks. + */ + int (*GetDisplayWorkingAreaBounds) (_THIS, SDL_VideoDisplay * display, SDL_Rect * rect); + + /* * Get a list of the available display modes for a display. */ void (*GetDisplayModes) (_THIS, SDL_VideoDisplay * display); diff -r bc074eca6597 src/video/SDL_video.c --- a/src/video/SDL_video.c Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/SDL_video.c Wed Nov 19 08:45:03 2014 -0600 @@ -680,6 +680,23 @@ return 0; } +int +SDL_GetDisplayWorkingAreaBounds(int displayIndex, SDL_Rect * rect) +{ + CHECK_DISPLAY_INDEX(displayIndex, -1); + + if (rect) { + SDL_VideoDisplay *display = &_this->displays[displayIndex]; + + if (_this->GetDisplayWorkingAreaBounds) { + if (_this->GetDisplayWorkingAreaBounds(_this, display, rect) == 0) { + return 0; + } + } + } + return -1; +} + SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay * display, const SDL_DisplayMode * mode) { diff -r bc074eca6597 src/video/cocoa/SDL_cocoamodes.h --- a/src/video/cocoa/SDL_cocoamodes.h Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/cocoa/SDL_cocoamodes.h Wed Nov 19 08:45:03 2014 -0600 @@ -35,6 +35,7 @@ extern void Cocoa_InitModes(_THIS); extern int Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect); +extern int Cocoa_GetDisplayWorkingAreaBounds(_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); diff -r bc074eca6597 src/video/cocoa/SDL_cocoamodes.m --- a/src/video/cocoa/SDL_cocoamodes.m Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/cocoa/SDL_cocoamodes.m Wed Nov 19 08:45:03 2014 -0600 @@ -337,6 +337,13 @@ return 0; } +int +Cocoa_GetDisplayWorkingAreaBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect) +{ + /* Maybe use AppKit's screen visibleFrame */ + return -1; +} + void Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display) { diff -r bc074eca6597 src/video/cocoa/SDL_cocoavideo.m --- a/src/video/cocoa/SDL_cocoavideo.m Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/cocoa/SDL_cocoavideo.m Wed Nov 19 08:45:03 2014 -0600 @@ -73,6 +73,7 @@ device->VideoInit = Cocoa_VideoInit; device->VideoQuit = Cocoa_VideoQuit; device->GetDisplayBounds = Cocoa_GetDisplayBounds; + device->GetDisplayWorkingAreaBounds = Cocoa_GetDisplayWorkingAreaBounds; device->GetDisplayModes = Cocoa_GetDisplayModes; device->SetDisplayMode = Cocoa_SetDisplayMode; device->PumpEvents = Cocoa_PumpEvents; diff -r bc074eca6597 src/video/windows/SDL_windowsmodes.c --- a/src/video/windows/SDL_windowsmodes.c Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/windows/SDL_windowsmodes.c Wed Nov 19 08:45:03 2014 -0600 @@ -241,6 +241,34 @@ return 0; } +int +WIN_GetDisplayWorkingAreaBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect) +{ + MONITORINFO info; + HMONITOR hmon; + RECT r; + SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->current_mode.driverdata; + + r.left = (int)SDL_ceil(data->DeviceMode.dmPosition.x * data->ScaleX); + r.top = (int)SDL_ceil(data->DeviceMode.dmPosition.y * data->ScaleY); + r.right = (int)SDL_ceil(data->DeviceMode.dmPelsWidth * data->ScaleX) + r.left; + r.bottom = (int)SDL_ceil(data->DeviceMode.dmPelsHeight * data->ScaleY) + r.top; + + hmon = MonitorFromRect(&r, MONITOR_DEFAULTTONULL); + info.cbSize = sizeof(info); + + if (hmon && GetMonitorInfo(hmon, &info)) { + rect->x = info.rcWork.left; + rect->y = info.rcWork.top; + rect->w = info.rcWork.right - info.rcWork.left; + rect->h = info.rcWork.bottom - info.rcWork.top; + + return 0; + } + + return -1; +} + void WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display) { diff -r bc074eca6597 src/video/windows/SDL_windowsmodes.h --- a/src/video/windows/SDL_windowsmodes.h Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/windows/SDL_windowsmodes.h Wed Nov 19 08:45:03 2014 -0600 @@ -37,6 +37,7 @@ extern int WIN_InitModes(_THIS); extern int WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect); +extern int WIN_GetDisplayWorkingAreaBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect); extern void WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display); extern int WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); extern void WIN_QuitModes(_THIS); diff -r bc074eca6597 src/video/windows/SDL_windowsvideo.c --- a/src/video/windows/SDL_windowsvideo.c Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/windows/SDL_windowsvideo.c Wed Nov 19 08:45:03 2014 -0600 @@ -116,6 +116,7 @@ device->VideoInit = WIN_VideoInit; device->VideoQuit = WIN_VideoQuit; device->GetDisplayBounds = WIN_GetDisplayBounds; + device->GetDisplayWorkingAreaBounds = WIN_GetDisplayWorkingAreaBounds; device->GetDisplayModes = WIN_GetDisplayModes; device->SetDisplayMode = WIN_SetDisplayMode; device->PumpEvents = WIN_PumpEvents; diff -r bc074eca6597 src/video/x11/SDL_x11modes.c --- a/src/video/x11/SDL_x11modes.c Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/x11/SDL_x11modes.c Wed Nov 19 08:45:03 2014 -0600 @@ -896,6 +896,62 @@ return 0; } +int +X11_GetDisplayWorkingAreaBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect) +{ + SDL_VideoData *videodata = (SDL_VideoData *) sdl_display->device->driverdata; + Display *display = videodata->display; + Atom _NET_WORKAREA = videodata->_NET_WORKAREA; + int status, real_format; + Atom real_type; + unsigned long items_read = 0, items_left = 0; + unsigned char *propdata = NULL; + + status = X11_XGetWindowProperty(display, DefaultRootWindow(display), _NET_WORKAREA, 0L, ~0, False, XA_CARDINAL, &real_type, &real_format, &items_read, &items_left, &propdata); + if (status == Success) { + int found_workarea = 0; + + if (real_type == XA_CARDINAL && real_format == 32 && items_read >= 4) { + SDL_Rect area; + SDL_Rect full_bounds; + int i; + + if (X11_GetDisplayBounds(_this, sdl_display, &full_bounds) != 0) { + SDL_zero(full_bounds); + } + + /* Round down to a multiple of four */ + items_read &= ~0x4; + + /* Find a work area belonging to the display */ + for (i = 0; i < items_read; i += 4) { + area.x = ((long*)propdata)[i + 0]; + area.y = ((long*)propdata)[i + 1]; + area.w = ((long*)propdata)[i + 2]; + area.h = ((long*)propdata)[i + 3]; + + if (SDL_HasIntersection(&full_bounds, &area)) { + /* The working area is set by the window manager. + * With multiple monitors, some window managers + * return basically the entire virtual desktop. So + * only use the intersection with the desired display. + */ + SDL_IntersectRect(&full_bounds, &area, rect); + found_workarea = 1; + break; + } + } + } + X11_XFree(propdata); + + if (found_workarea) { + return 0; + } + } + + return -1; +} + #endif /* SDL_VIDEO_DRIVER_X11 */ /* vi: set ts=4 sw=4 expandtab: */ diff -r bc074eca6597 src/video/x11/SDL_x11modes.h --- a/src/video/x11/SDL_x11modes.h Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/x11/SDL_x11modes.h Wed Nov 19 08:45:03 2014 -0600 @@ -74,6 +74,7 @@ extern Uint32 X11_GetPixelFormatFromVisualInfo(Display * display, XVisualInfo * vinfo); extern int X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect); +extern int X11_GetDisplayWorkingAreaBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect); #endif /* _SDL_x11modes_h */ diff -r bc074eca6597 src/video/x11/SDL_x11video.c --- a/src/video/x11/SDL_x11video.c Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/x11/SDL_x11video.c Wed Nov 19 08:45:03 2014 -0600 @@ -216,6 +216,7 @@ device->VideoQuit = X11_VideoQuit; device->GetDisplayModes = X11_GetDisplayModes; device->GetDisplayBounds = X11_GetDisplayBounds; + device->GetDisplayWorkingAreaBounds = X11_GetDisplayWorkingAreaBounds; device->SetDisplayMode = X11_SetDisplayMode; device->SuspendScreenSaver = X11_SuspendScreenSaver; device->PumpEvents = X11_PumpEvents; @@ -397,6 +398,7 @@ GET_ATOM(_NET_WM_ICON); GET_ATOM(_NET_WM_PING); GET_ATOM(_NET_ACTIVE_WINDOW); + GET_ATOM(_NET_WORKAREA); GET_ATOM(UTF8_STRING); GET_ATOM(PRIMARY); GET_ATOM(XdndEnter); diff -r bc074eca6597 src/video/x11/SDL_x11video.h --- a/src/video/x11/SDL_x11video.h Sat Nov 15 15:07:55 2014 -0500 +++ b/src/video/x11/SDL_x11video.h Wed Nov 19 08:45:03 2014 -0600 @@ -98,6 +98,7 @@ Atom _NET_WM_ICON; Atom _NET_WM_PING; Atom _NET_ACTIVE_WINDOW; + Atom _NET_WORKAREA; Atom UTF8_STRING; Atom PRIMARY; Atom XdndEnter;