Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Added an API function to query geometry of multiple monitors:
Browse files Browse the repository at this point in the history
	SDL_GetDisplayBounds()

Implemented multi-monitor window positions on Windows
  • Loading branch information
slouken committed Dec 6, 2009
1 parent 5a8df56 commit 25eb8c8
Show file tree
Hide file tree
Showing 13 changed files with 124 additions and 34 deletions.
11 changes: 11 additions & 0 deletions include/SDL_video.h
Expand Up @@ -343,10 +343,21 @@ extern DECLSPEC const char *SDLCALL SDL_GetCurrentVideoDriver(void);
/**
* \brief Returns the number of available video displays.
*
* \sa SDL_GetDisplayBounds()
* \sa SDL_SelectVideoDisplay()
*/
extern DECLSPEC int SDLCALL SDL_GetNumVideoDisplays(void);

/**
* \brief Get the desktop area represented by a display, with the primary
* display located at 0,0
*
* \return 0 on success, or -1 if the index is out of range.
*
* \sa SDL_GetNumVideoDisplays()
*/
extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(int index, SDL_Rect * rect);

/**
* \brief Set the index of the currently selected display.
*
Expand Down
5 changes: 5 additions & 0 deletions src/video/SDL_sysvideo.h
Expand Up @@ -212,6 +212,11 @@ struct SDL_VideoDevice
* Display functions
*/

/*
* Get the bounds of a display
*/
int (*GetDisplayBounds) (_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);

/*
* Get a list of the available display modes. e.g.
* SDL_AddDisplayMode(_this->current_display, mode)
Expand Down
35 changes: 35 additions & 0 deletions src/video/SDL_video.c
Expand Up @@ -334,6 +334,41 @@ SDL_GetNumVideoDisplays(void)
return _this->num_displays;
}

int
SDL_GetDisplayBounds(int index, SDL_Rect * rect)
{
if (!_this) {
SDL_UninitializedVideo();
return -1;
}
if (index < 0 || index >= _this->num_displays) {
SDL_SetError("index must be in the range 0 - %d",
_this->num_displays - 1);
return -1;
}
if (rect) {
SDL_VideoDisplay *display = &_this->displays[index];

if (_this->GetDisplayBounds) {
if (_this->GetDisplayBounds(_this, display, rect) < 0) {
return -1;
}
} else {
/* Assume that the displays are left to right */
if (index == 0) {
rect->x = 0;
rect->y = 0;
} else {
SDL_GetDisplayBounds(index-1, rect);
rect->x += rect->w;
}
rect->w = display->desktop_mode.w;
rect->h = display->desktop_mode.h;
}
}
return 0;
}

int
SDL_SelectVideoDisplay(int index)
{
Expand Down
2 changes: 1 addition & 1 deletion src/video/cocoa/SDL_cocoamodes.h
Expand Up @@ -35,7 +35,7 @@ typedef struct
} SDL_DisplayModeData;

extern void Cocoa_InitModes(_THIS);
extern NSRect Cocoa_DisplayBounds(CGDirectDisplayID display);
extern int Cocoa_GetDisplayBounds(_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
19 changes: 9 additions & 10 deletions src/video/cocoa/SDL_cocoamodes.m
Expand Up @@ -200,19 +200,18 @@ - (void) setFrame:(NSRect)frame;
SDL_stack_free(displays);
}

/* This is needed on 10.4, where NSRect and CGRect are different */
NSRect
Cocoa_DisplayBounds(CGDirectDisplayID display)
int
Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
{
NSRect nsrect;
SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
CGRect cgrect;

cgrect = CGDisplayBounds(display);
nsrect.origin.x = cgrect.origin.x;
nsrect.origin.y = cgrect.origin.y;
nsrect.size.width = cgrect.size.width;
nsrect.size.height = cgrect.size.height;
return nsrect;
cgrect = CGDisplayBounds(displaydata->display);
rect->x = (int)cgrect.origin.x;
rect->y = (int)cgrect.origin.y;
rect->w = (int)cgrect.size.width;
rect->h = (int)cgrect.size.height;
return 0;
}

static void
Expand Down
8 changes: 4 additions & 4 deletions src/video/cocoa/SDL_cocoamouse.m
Expand Up @@ -67,12 +67,12 @@
SDL_Window *candidate = display->fullscreen_window;

if (candidate) {
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
NSRect rect = Cocoa_DisplayBounds(displaydata->display);
SDL_Rect bounds;

Cocoa_GetDisplayBounds(_this, display, &bounds);
point = [NSEvent mouseLocation];
point.x = point.x - rect.origin.x;
point.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - point.y - rect.origin.y;
point.x = point.x - bounds.x;
point.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - point.y - bounds.y;
if (point.x < 0 || point.x >= candidate->w ||
point.y < 0 || point.y >= candidate->h) {
/* The mouse is out of this fullscreen display */
Expand Down
1 change: 1 addition & 0 deletions src/video/cocoa/SDL_cocoavideo.m
Expand Up @@ -72,6 +72,7 @@
/* Set the function pointers */
device->VideoInit = Cocoa_VideoInit;
device->VideoQuit = Cocoa_VideoQuit;
device->GetDisplayBounds = Cocoa_GetDisplayBounds;
device->GetDisplayModes = Cocoa_GetDisplayModes;
device->SetDisplayMode = Cocoa_SetDisplayMode;
device->PumpEvents = Cocoa_PumpEvents;
Expand Down
26 changes: 16 additions & 10 deletions src/video/cocoa/SDL_cocoawindow.m
Expand Up @@ -378,23 +378,28 @@ - (BOOL)canBecomeMainWindow
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSWindow *nswindow;
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata;
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
NSRect rect;
SDL_Rect bounds;
unsigned int style;
NSString *title;
int status;

rect = Cocoa_DisplayBounds(displaydata->display);
Cocoa_GetDisplayBounds(_this, display, &bounds);
if ((window->flags & SDL_WINDOW_FULLSCREEN)
|| window->x == SDL_WINDOWPOS_CENTERED) {
rect.origin.x += (rect.size.width - window->w) / 2;
} else if (window->x != SDL_WINDOWPOS_UNDEFINED) {
rect.origin.x = bounds.x + (bounds.w - window->w) / 2;
} else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
rect.origin.x = bounds.x;
} else {
rect.origin.x = window->x;
}
if ((window->flags & SDL_WINDOW_FULLSCREEN)
|| window->y == SDL_WINDOWPOS_CENTERED) {
rect.origin.y += (rect.size.height - window->h) / 2;
} else if (window->x != SDL_WINDOWPOS_UNDEFINED) {
rect.origin.y = bounds.y + (bounds.h - window->h) / 2;
} else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
rect.origin.y = bounds.y;
} else {
rect.origin.y = window->y;
}
rect.size.width = window->w;
Expand Down Expand Up @@ -482,19 +487,20 @@ - (BOOL)canBecomeMainWindow
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window;
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata;
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
NSRect rect;
SDL_Rect bounds;

rect = Cocoa_DisplayBounds(displaydata->display);
Cocoa_GetDisplayBounds(_this, display, &bounds);
if ((window->flags & SDL_WINDOW_FULLSCREEN)
|| window->x == SDL_WINDOWPOS_CENTERED) {
rect.origin.x += (rect.size.width - window->w) / 2;
rect.origin.x = bounds.x + (bounds.w - window->w) / 2;
} else {
rect.origin.x = window->x;
}
if ((window->flags & SDL_WINDOW_FULLSCREEN)
|| window->y == SDL_WINDOWPOS_CENTERED) {
rect.origin.y += (rect.size.height - window->h) / 2;
rect.origin.y = bounds.y + (bounds.h - window->h) / 2;
} else {
rect.origin.y = window->y;
}
Expand Down
14 changes: 13 additions & 1 deletion src/video/win32/SDL_win32modes.c
Expand Up @@ -54,7 +54,7 @@ WIN_GetDisplayMode(LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
mode->driverdata = data;
#ifdef _WIN32_WCE
/* In WinCE EnumDisplaySettings(ENUM_CURRENT_SETTINGS) doesn't take the user defined orientation
into account but GetSystemMetrixs does. */
into account but GetSystemMetrics does. */
if (index == ENUM_CURRENT_SETTINGS) {
mode->w = GetSystemMetrics(SM_CXSCREEN);
mode->h = GetSystemMetrics(SM_CYSCREEN);
Expand Down Expand Up @@ -199,6 +199,18 @@ WIN_InitModes(_THIS)
return 0;
}

int
WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
{
SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->desktop_mode.driverdata;

rect->x = (int)data->DeviceMode.dmPosition.x;
rect->y = (int)data->DeviceMode.dmPosition.y;
rect->w = data->DeviceMode.dmPelsWidth;
rect->h = data->DeviceMode.dmPelsHeight;
return 0;
}

void
WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
{
Expand Down
1 change: 1 addition & 0 deletions src/video/win32/SDL_win32modes.h
Expand Up @@ -35,6 +35,7 @@ typedef struct
} SDL_DisplayModeData;

extern int WIN_InitModes(_THIS);
extern int WIN_GetDisplayBounds(_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);
Expand Down
1 change: 1 addition & 0 deletions src/video/win32/SDL_win32video.c
Expand Up @@ -160,6 +160,7 @@ WIN_CreateDevice(int devindex)
/* Set the function pointers */
device->VideoInit = WIN_VideoInit;
device->VideoQuit = WIN_VideoQuit;
device->GetDisplayBounds = WIN_GetDisplayBounds;
device->GetDisplayModes = WIN_GetDisplayModes;
device->SetDisplayMode = WIN_SetDisplayMode;
device->SetDisplayGammaRamp = WIN_SetDisplayGammaRamp;
Expand Down
28 changes: 21 additions & 7 deletions src/video/win32/SDL_win32window.c
Expand Up @@ -185,12 +185,14 @@ int
WIN_CreateWindow(_THIS, SDL_Window * window)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
RAWINPUTDEVICE Rid;
AXIS TabX, TabY;
LOGCONTEXTA lc;
HWND hwnd;
HWND top;
RECT rect;
SDL_Rect bounds;
DWORD style = (WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
int x, y;
int w, h;
Expand Down Expand Up @@ -219,19 +221,28 @@ WIN_CreateWindow(_THIS, SDL_Window * window)
w = (rect.right - rect.left);
h = (rect.bottom - rect.top);

WIN_GetDisplayBounds(_this, display, &bounds);
if ((window->flags & SDL_WINDOW_FULLSCREEN)
|| window->x == SDL_WINDOWPOS_CENTERED) {
x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
x = bounds.x + (bounds.w - window->w) / 2;
} else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
x = CW_USEDEFAULT;
if (bounds.x == 0) {
x = CW_USEDEFAULT;
} else {
x = bounds.x;
}
} else {
x = window->x + rect.left;
}
if ((window->flags & SDL_WINDOW_FULLSCREEN)
|| window->y == SDL_WINDOWPOS_CENTERED) {
y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
} else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
y = CW_USEDEFAULT;
y = bounds.y + (bounds.h - window->h) / 2;
} else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
if (bounds.x == 0) {
y = CW_USEDEFAULT;
} else {
y = bounds.y;
}
} else {
y = window->y + rect.top;
}
Expand Down Expand Up @@ -416,8 +427,10 @@ WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
void
WIN_SetWindowPosition(_THIS, SDL_Window * window)
{
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
RECT rect;
SDL_Rect bounds;
DWORD style;
HWND top;
BOOL menu;
Expand All @@ -441,15 +454,16 @@ WIN_SetWindowPosition(_THIS, SDL_Window * window)
#endif
AdjustWindowRectEx(&rect, style, menu, 0);

WIN_GetDisplayBounds(_this, display, &bounds);
if ((window->flags & SDL_WINDOW_FULLSCREEN)
|| window->x == SDL_WINDOWPOS_CENTERED) {
x = (GetSystemMetrics(SM_CXSCREEN) - window->w) / 2;
x = bounds.x + (bounds.w - window->w) / 2;
} else {
x = window->x + rect.left;
}
if ((window->flags & SDL_WINDOW_FULLSCREEN)
|| window->y == SDL_WINDOWPOS_CENTERED) {
y = (GetSystemMetrics(SM_CYSCREEN) - window->h) / 2;
y = bounds.y + (bounds.h - window->h) / 2;
} else {
y = window->y + rect.top;
}
Expand Down
7 changes: 6 additions & 1 deletion test/testvidinfo.c
Expand Up @@ -449,7 +449,12 @@ main(int argc, char *argv[])
}
printf("Number of displays: %d\n", SDL_GetNumVideoDisplays());
for (d = 0; d < SDL_GetNumVideoDisplays(); ++d) {
printf("Display %d:\n", d);
SDL_Rect bounds;

SDL_GetDisplayBounds(d, &bounds);
printf("Display %d: %dx%d at %d,%d\n", d,
bounds.w, bounds.h, bounds.x, bounds.y);

SDL_SelectVideoDisplay(d);

SDL_GetDesktopDisplayMode(&mode);
Expand Down

0 comments on commit 25eb8c8

Please sign in to comment.