Added an API function to query geometry of multiple monitors:
authorSam Lantinga <slouken@libsdl.org>
Sun, 06 Dec 2009 08:03:38 +0000
changeset 352859ff7a2beb57
parent 3527 444cb12cadb6
child 3529 09155ec3e291
Added an API function to query geometry of multiple monitors:
SDL_GetDisplayBounds()

Implemented multi-monitor window positions on Windows
include/SDL_video.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/cocoa/SDL_cocoamodes.h
src/video/cocoa/SDL_cocoamodes.m
src/video/cocoa/SDL_cocoamouse.m
src/video/cocoa/SDL_cocoavideo.m
src/video/cocoa/SDL_cocoawindow.m
src/video/win32/SDL_win32modes.c
src/video/win32/SDL_win32modes.h
src/video/win32/SDL_win32video.c
src/video/win32/SDL_win32window.c
test/testvidinfo.c
     1.1 --- a/include/SDL_video.h	Sun Dec 06 06:21:39 2009 +0000
     1.2 +++ b/include/SDL_video.h	Sun Dec 06 08:03:38 2009 +0000
     1.3 @@ -343,11 +343,22 @@
     1.4  /**
     1.5   *  \brief Returns the number of available video displays.
     1.6   *  
     1.7 + *  \sa SDL_GetDisplayBounds()
     1.8   *  \sa SDL_SelectVideoDisplay()
     1.9   */
    1.10  extern DECLSPEC int SDLCALL SDL_GetNumVideoDisplays(void);
    1.11  
    1.12  /**
    1.13 + *  \brief Get the desktop area represented by a display, with the primary
    1.14 + *         display located at 0,0
    1.15 + *  
    1.16 + *  \return 0 on success, or -1 if the index is out of range.
    1.17 + *  
    1.18 + *  \sa SDL_GetNumVideoDisplays()
    1.19 + */
    1.20 +extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(int index, SDL_Rect * rect);
    1.21 +
    1.22 +/**
    1.23   *  \brief Set the index of the currently selected display.
    1.24   *  
    1.25   *  \return 0 on success, or -1 if the index is out of range.
     2.1 --- a/src/video/SDL_sysvideo.h	Sun Dec 06 06:21:39 2009 +0000
     2.2 +++ b/src/video/SDL_sysvideo.h	Sun Dec 06 08:03:38 2009 +0000
     2.3 @@ -213,6 +213,11 @@
     2.4       */
     2.5  
     2.6      /*
     2.7 +     * Get the bounds of a display
     2.8 +     */
     2.9 +    int (*GetDisplayBounds) (_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
    2.10 +
    2.11 +    /*
    2.12       * Get a list of the available display modes. e.g.
    2.13       * SDL_AddDisplayMode(_this->current_display, mode)
    2.14       */
     3.1 --- a/src/video/SDL_video.c	Sun Dec 06 06:21:39 2009 +0000
     3.2 +++ b/src/video/SDL_video.c	Sun Dec 06 08:03:38 2009 +0000
     3.3 @@ -335,6 +335,41 @@
     3.4  }
     3.5  
     3.6  int
     3.7 +SDL_GetDisplayBounds(int index, SDL_Rect * rect)
     3.8 +{
     3.9 +    if (!_this) {
    3.10 +        SDL_UninitializedVideo();
    3.11 +        return -1;
    3.12 +    }
    3.13 +    if (index < 0 || index >= _this->num_displays) {
    3.14 +        SDL_SetError("index must be in the range 0 - %d",
    3.15 +                     _this->num_displays - 1);
    3.16 +        return -1;
    3.17 +    }
    3.18 +    if (rect) {
    3.19 +        SDL_VideoDisplay *display = &_this->displays[index];
    3.20 +
    3.21 +        if (_this->GetDisplayBounds) {
    3.22 +            if (_this->GetDisplayBounds(_this, display, rect) < 0) {
    3.23 +                return -1;
    3.24 +            }
    3.25 +        } else {
    3.26 +            /* Assume that the displays are left to right */
    3.27 +            if (index == 0) {
    3.28 +                rect->x = 0;
    3.29 +                rect->y = 0;
    3.30 +            } else {
    3.31 +                SDL_GetDisplayBounds(index-1, rect);
    3.32 +                rect->x += rect->w;
    3.33 +            }
    3.34 +            rect->w = display->desktop_mode.w;
    3.35 +            rect->h = display->desktop_mode.h;
    3.36 +        }
    3.37 +    }
    3.38 +    return 0;
    3.39 +}
    3.40 +
    3.41 +int
    3.42  SDL_SelectVideoDisplay(int index)
    3.43  {
    3.44      if (!_this) {
     4.1 --- a/src/video/cocoa/SDL_cocoamodes.h	Sun Dec 06 06:21:39 2009 +0000
     4.2 +++ b/src/video/cocoa/SDL_cocoamodes.h	Sun Dec 06 08:03:38 2009 +0000
     4.3 @@ -35,7 +35,7 @@
     4.4  } SDL_DisplayModeData;
     4.5  
     4.6  extern void Cocoa_InitModes(_THIS);
     4.7 -extern NSRect Cocoa_DisplayBounds(CGDirectDisplayID display);
     4.8 +extern int Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
     4.9  extern void Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
    4.10  extern int Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
    4.11  extern void Cocoa_QuitModes(_THIS);
     5.1 --- a/src/video/cocoa/SDL_cocoamodes.m	Sun Dec 06 06:21:39 2009 +0000
     5.2 +++ b/src/video/cocoa/SDL_cocoamodes.m	Sun Dec 06 08:03:38 2009 +0000
     5.3 @@ -200,19 +200,18 @@
     5.4      SDL_stack_free(displays);
     5.5  }
     5.6  
     5.7 -/* This is needed on 10.4, where NSRect and CGRect are different */
     5.8 -NSRect
     5.9 -Cocoa_DisplayBounds(CGDirectDisplayID display)
    5.10 +int
    5.11 +Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
    5.12  {
    5.13 -    NSRect nsrect;
    5.14 +    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
    5.15      CGRect cgrect;
    5.16  
    5.17 -    cgrect = CGDisplayBounds(display);
    5.18 -    nsrect.origin.x = cgrect.origin.x;
    5.19 -    nsrect.origin.y = cgrect.origin.y;
    5.20 -    nsrect.size.width = cgrect.size.width;
    5.21 -    nsrect.size.height = cgrect.size.height;
    5.22 -    return nsrect;
    5.23 +    cgrect = CGDisplayBounds(displaydata->display);
    5.24 +    rect->x = (int)cgrect.origin.x;
    5.25 +    rect->y = (int)cgrect.origin.y;
    5.26 +    rect->w = (int)cgrect.size.width;
    5.27 +    rect->h = (int)cgrect.size.height;
    5.28 +    return 0;
    5.29  }
    5.30  
    5.31  static void
     6.1 --- a/src/video/cocoa/SDL_cocoamouse.m	Sun Dec 06 06:21:39 2009 +0000
     6.2 +++ b/src/video/cocoa/SDL_cocoamouse.m	Sun Dec 06 08:03:38 2009 +0000
     6.3 @@ -67,12 +67,12 @@
     6.4          SDL_Window *candidate = display->fullscreen_window;
     6.5  
     6.6          if (candidate) {
     6.7 -            SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
     6.8 -            NSRect rect = Cocoa_DisplayBounds(displaydata->display);
     6.9 +            SDL_Rect bounds;
    6.10  
    6.11 +            Cocoa_GetDisplayBounds(_this, display, &bounds);
    6.12              point = [NSEvent mouseLocation];
    6.13 -            point.x = point.x - rect.origin.x;
    6.14 -            point.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - point.y - rect.origin.y;
    6.15 +            point.x = point.x - bounds.x;
    6.16 +            point.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - point.y - bounds.y;
    6.17              if (point.x < 0 || point.x >= candidate->w ||
    6.18                  point.y < 0 || point.y >= candidate->h) {
    6.19                  /* The mouse is out of this fullscreen display */
     7.1 --- a/src/video/cocoa/SDL_cocoavideo.m	Sun Dec 06 06:21:39 2009 +0000
     7.2 +++ b/src/video/cocoa/SDL_cocoavideo.m	Sun Dec 06 08:03:38 2009 +0000
     7.3 @@ -72,6 +72,7 @@
     7.4      /* Set the function pointers */
     7.5      device->VideoInit = Cocoa_VideoInit;
     7.6      device->VideoQuit = Cocoa_VideoQuit;
     7.7 +    device->GetDisplayBounds = Cocoa_GetDisplayBounds;
     7.8      device->GetDisplayModes = Cocoa_GetDisplayModes;
     7.9      device->SetDisplayMode = Cocoa_SetDisplayMode;
    7.10      device->PumpEvents = Cocoa_PumpEvents;
     8.1 --- a/src/video/cocoa/SDL_cocoawindow.m	Sun Dec 06 06:21:39 2009 +0000
     8.2 +++ b/src/video/cocoa/SDL_cocoawindow.m	Sun Dec 06 08:03:38 2009 +0000
     8.3 @@ -378,23 +378,28 @@
     8.4  {
     8.5      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     8.6      NSWindow *nswindow;
     8.7 -    SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata;
     8.8 +    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
     8.9      NSRect rect;
    8.10 +    SDL_Rect bounds;
    8.11      unsigned int style;
    8.12      NSString *title;
    8.13      int status;
    8.14  
    8.15 -    rect = Cocoa_DisplayBounds(displaydata->display);
    8.16 +    Cocoa_GetDisplayBounds(_this, display, &bounds);
    8.17      if ((window->flags & SDL_WINDOW_FULLSCREEN)
    8.18          || window->x == SDL_WINDOWPOS_CENTERED) {
    8.19 -        rect.origin.x += (rect.size.width - window->w) / 2;
    8.20 -    } else if (window->x != SDL_WINDOWPOS_UNDEFINED) {
    8.21 +        rect.origin.x = bounds.x + (bounds.w - window->w) / 2;
    8.22 +    } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
    8.23 +        rect.origin.x = bounds.x;
    8.24 +    } else {
    8.25          rect.origin.x = window->x;
    8.26      }
    8.27      if ((window->flags & SDL_WINDOW_FULLSCREEN)
    8.28          || window->y == SDL_WINDOWPOS_CENTERED) {
    8.29 -        rect.origin.y += (rect.size.height - window->h) / 2;
    8.30 -    } else if (window->x != SDL_WINDOWPOS_UNDEFINED) {
    8.31 +        rect.origin.y = bounds.y + (bounds.h - window->h) / 2;
    8.32 +    } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
    8.33 +        rect.origin.y = bounds.y;
    8.34 +    } else {
    8.35          rect.origin.y = window->y;
    8.36      }
    8.37      rect.size.width = window->w;
    8.38 @@ -482,19 +487,20 @@
    8.39  {
    8.40      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    8.41      NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window;
    8.42 -    SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata;
    8.43 +    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
    8.44      NSRect rect;
    8.45 +    SDL_Rect bounds;
    8.46  
    8.47 -    rect = Cocoa_DisplayBounds(displaydata->display);
    8.48 +    Cocoa_GetDisplayBounds(_this, display, &bounds);
    8.49      if ((window->flags & SDL_WINDOW_FULLSCREEN)
    8.50          || window->x == SDL_WINDOWPOS_CENTERED) {
    8.51 -        rect.origin.x += (rect.size.width - window->w) / 2;
    8.52 +        rect.origin.x = bounds.x + (bounds.w - window->w) / 2;
    8.53      } else {
    8.54          rect.origin.x = window->x;
    8.55      }
    8.56      if ((window->flags & SDL_WINDOW_FULLSCREEN)
    8.57          || window->y == SDL_WINDOWPOS_CENTERED) {
    8.58 -        rect.origin.y += (rect.size.height - window->h) / 2;
    8.59 +        rect.origin.y = bounds.y + (bounds.h - window->h) / 2;
    8.60      } else {
    8.61          rect.origin.y = window->y;
    8.62      }
     9.1 --- a/src/video/win32/SDL_win32modes.c	Sun Dec 06 06:21:39 2009 +0000
     9.2 +++ b/src/video/win32/SDL_win32modes.c	Sun Dec 06 08:03:38 2009 +0000
     9.3 @@ -54,7 +54,7 @@
     9.4      mode->driverdata = data;
     9.5  #ifdef _WIN32_WCE
     9.6      /* In WinCE EnumDisplaySettings(ENUM_CURRENT_SETTINGS) doesn't take the user defined orientation
     9.7 -       into account but GetSystemMetrixs does. */
     9.8 +       into account but GetSystemMetrics does. */
     9.9      if (index == ENUM_CURRENT_SETTINGS) {
    9.10          mode->w = GetSystemMetrics(SM_CXSCREEN);
    9.11          mode->h = GetSystemMetrics(SM_CYSCREEN);
    9.12 @@ -199,6 +199,18 @@
    9.13      return 0;
    9.14  }
    9.15  
    9.16 +int
    9.17 +WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
    9.18 +{
    9.19 +    SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->desktop_mode.driverdata;
    9.20 +
    9.21 +    rect->x = (int)data->DeviceMode.dmPosition.x;
    9.22 +    rect->y = (int)data->DeviceMode.dmPosition.y;
    9.23 +    rect->w = data->DeviceMode.dmPelsWidth;
    9.24 +    rect->h = data->DeviceMode.dmPelsHeight;
    9.25 +    return 0;
    9.26 +}
    9.27 +
    9.28  void
    9.29  WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
    9.30  {
    10.1 --- a/src/video/win32/SDL_win32modes.h	Sun Dec 06 06:21:39 2009 +0000
    10.2 +++ b/src/video/win32/SDL_win32modes.h	Sun Dec 06 08:03:38 2009 +0000
    10.3 @@ -35,6 +35,7 @@
    10.4  } SDL_DisplayModeData;
    10.5  
    10.6  extern int WIN_InitModes(_THIS);
    10.7 +extern int WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
    10.8  extern void WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
    10.9  extern int WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
   10.10  extern void WIN_QuitModes(_THIS);
    11.1 --- a/src/video/win32/SDL_win32video.c	Sun Dec 06 06:21:39 2009 +0000
    11.2 +++ b/src/video/win32/SDL_win32video.c	Sun Dec 06 08:03:38 2009 +0000
    11.3 @@ -160,6 +160,7 @@
    11.4      /* Set the function pointers */
    11.5      device->VideoInit = WIN_VideoInit;
    11.6      device->VideoQuit = WIN_VideoQuit;
    11.7 +    device->GetDisplayBounds = WIN_GetDisplayBounds;
    11.8      device->GetDisplayModes = WIN_GetDisplayModes;
    11.9      device->SetDisplayMode = WIN_SetDisplayMode;
   11.10      device->SetDisplayGammaRamp = WIN_SetDisplayGammaRamp;
    12.1 --- a/src/video/win32/SDL_win32window.c	Sun Dec 06 06:21:39 2009 +0000
    12.2 +++ b/src/video/win32/SDL_win32window.c	Sun Dec 06 08:03:38 2009 +0000
    12.3 @@ -185,12 +185,14 @@
    12.4  WIN_CreateWindow(_THIS, SDL_Window * window)
    12.5  {
    12.6      SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    12.7 +    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
    12.8      RAWINPUTDEVICE Rid;
    12.9      AXIS TabX, TabY;
   12.10      LOGCONTEXTA lc;
   12.11      HWND hwnd;
   12.12      HWND top;
   12.13      RECT rect;
   12.14 +    SDL_Rect bounds;
   12.15      DWORD style = (WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
   12.16      int x, y;
   12.17      int w, h;
   12.18 @@ -219,19 +221,28 @@
   12.19      w = (rect.right - rect.left);
   12.20      h = (rect.bottom - rect.top);
   12.21  
   12.22 +    WIN_GetDisplayBounds(_this, display, &bounds);
   12.23      if ((window->flags & SDL_WINDOW_FULLSCREEN)
   12.24          || window->x == SDL_WINDOWPOS_CENTERED) {
   12.25 -        x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
   12.26 +        x = bounds.x + (bounds.w - window->w) / 2;
   12.27      } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   12.28 -        x = CW_USEDEFAULT;
   12.29 +        if (bounds.x == 0) {
   12.30 +            x = CW_USEDEFAULT;
   12.31 +        } else {
   12.32 +            x = bounds.x;
   12.33 +        }
   12.34      } else {
   12.35          x = window->x + rect.left;
   12.36      }
   12.37      if ((window->flags & SDL_WINDOW_FULLSCREEN)
   12.38          || window->y == SDL_WINDOWPOS_CENTERED) {
   12.39 -        y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
   12.40 -    } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
   12.41 -        y = CW_USEDEFAULT;
   12.42 +        y = bounds.y + (bounds.h - window->h) / 2;
   12.43 +    } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   12.44 +        if (bounds.x == 0) {
   12.45 +            y = CW_USEDEFAULT;
   12.46 +        } else {
   12.47 +            y = bounds.y;
   12.48 +        }
   12.49      } else {
   12.50          y = window->y + rect.top;
   12.51      }
   12.52 @@ -416,8 +427,10 @@
   12.53  void
   12.54  WIN_SetWindowPosition(_THIS, SDL_Window * window)
   12.55  {
   12.56 +    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   12.57      HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   12.58      RECT rect;
   12.59 +    SDL_Rect bounds;
   12.60      DWORD style;
   12.61      HWND top;
   12.62      BOOL menu;
   12.63 @@ -441,15 +454,16 @@
   12.64  #endif
   12.65      AdjustWindowRectEx(&rect, style, menu, 0);
   12.66  
   12.67 +    WIN_GetDisplayBounds(_this, display, &bounds);
   12.68      if ((window->flags & SDL_WINDOW_FULLSCREEN)
   12.69          || window->x == SDL_WINDOWPOS_CENTERED) {
   12.70 -        x = (GetSystemMetrics(SM_CXSCREEN) - window->w) / 2;
   12.71 +        x = bounds.x + (bounds.w - window->w) / 2;
   12.72      } else {
   12.73          x = window->x + rect.left;
   12.74      }
   12.75      if ((window->flags & SDL_WINDOW_FULLSCREEN)
   12.76          || window->y == SDL_WINDOWPOS_CENTERED) {
   12.77 -        y = (GetSystemMetrics(SM_CYSCREEN) - window->h) / 2;
   12.78 +        y = bounds.y + (bounds.h - window->h) / 2;
   12.79      } else {
   12.80          y = window->y + rect.top;
   12.81      }
    13.1 --- a/test/testvidinfo.c	Sun Dec 06 06:21:39 2009 +0000
    13.2 +++ b/test/testvidinfo.c	Sun Dec 06 08:03:38 2009 +0000
    13.3 @@ -449,7 +449,12 @@
    13.4      }
    13.5      printf("Number of displays: %d\n", SDL_GetNumVideoDisplays());
    13.6      for (d = 0; d < SDL_GetNumVideoDisplays(); ++d) {
    13.7 -        printf("Display %d:\n", d);
    13.8 +        SDL_Rect bounds;
    13.9 +
   13.10 +        SDL_GetDisplayBounds(d, &bounds);
   13.11 +        printf("Display %d: %dx%d at %d,%d\n", d,
   13.12 +               bounds.w, bounds.h, bounds.x, bounds.y);
   13.13 +
   13.14          SDL_SelectVideoDisplay(d);
   13.15  
   13.16          SDL_GetDesktopDisplayMode(&mode);