src/video/SDL_video.c
changeset 8145 663d7d9de9bf
parent 8117 988502081380
child 8149 681eb46b8ac4
equal deleted inserted replaced
8144:855b1d6d7d8e 8145:663d7d9de9bf
   475 
   475 
   476 
   476 
   477     /* Set some very sane GL defaults */
   477     /* Set some very sane GL defaults */
   478     _this->gl_config.driver_loaded = 0;
   478     _this->gl_config.driver_loaded = 0;
   479     _this->gl_config.dll_handle = NULL;
   479     _this->gl_config.dll_handle = NULL;
       
   480     SDL_GL_ResetAttributes();
       
   481 
       
   482     _this->current_glwin_tls = SDL_TLSCreate();
       
   483     _this->current_glctx_tls = SDL_TLSCreate();
       
   484 
       
   485     /* Initialize the video subsystem */
       
   486     if (_this->VideoInit(_this) < 0) {
       
   487         SDL_VideoQuit();
       
   488         return -1;
       
   489     }
       
   490 
       
   491     /* Make sure some displays were added */
       
   492     if (_this->num_displays == 0) {
       
   493         SDL_VideoQuit();
       
   494         return SDL_SetError("The video driver did not add any displays");
       
   495     }
       
   496 
       
   497     /* Add the renderer framebuffer emulation if desired */
       
   498     if (ShouldUseTextureFramebuffer()) {
       
   499         _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
       
   500         _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
       
   501         _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
       
   502     }
       
   503 
       
   504     /* If we don't use a screen keyboard, turn on text input by default,
       
   505        otherwise programs that expect to get text events without enabling
       
   506        UNICODE input won't get any events.
       
   507 
       
   508        Actually, come to think of it, you needed to call SDL_EnableUNICODE(1)
       
   509        in SDL 1.2 before you got text input events.  Hmm...
       
   510      */
       
   511     if (!SDL_HasScreenKeyboardSupport()) {
       
   512         SDL_StartTextInput();
       
   513     }
       
   514 
       
   515     /* We're ready to go! */
       
   516     return 0;
       
   517 }
       
   518 
       
   519 const char *
       
   520 SDL_GetCurrentVideoDriver()
       
   521 {
       
   522     if (!_this) {
       
   523         SDL_UninitializedVideo();
       
   524         return NULL;
       
   525     }
       
   526     return _this->name;
       
   527 }
       
   528 
       
   529 SDL_VideoDevice *
       
   530 SDL_GetVideoDevice(void)
       
   531 {
       
   532     return _this;
       
   533 }
       
   534 
       
   535 int
       
   536 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
       
   537 {
       
   538     SDL_VideoDisplay display;
       
   539 
       
   540     SDL_zero(display);
       
   541     if (desktop_mode) {
       
   542         display.desktop_mode = *desktop_mode;
       
   543     }
       
   544     display.current_mode = display.desktop_mode;
       
   545 
       
   546     return SDL_AddVideoDisplay(&display);
       
   547 }
       
   548 
       
   549 int
       
   550 SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
       
   551 {
       
   552     SDL_VideoDisplay *displays;
       
   553     int index = -1;
       
   554 
       
   555     displays =
       
   556         SDL_realloc(_this->displays,
       
   557                     (_this->num_displays + 1) * sizeof(*displays));
       
   558     if (displays) {
       
   559         index = _this->num_displays++;
       
   560         displays[index] = *display;
       
   561         displays[index].device = _this;
       
   562         _this->displays = displays;
       
   563 
       
   564         if (display->name) {
       
   565             displays[index].name = SDL_strdup(display->name);
       
   566         } else {
       
   567             char name[32];
       
   568 
       
   569             SDL_itoa(index, name, 10);
       
   570             displays[index].name = SDL_strdup(name);
       
   571         }
       
   572     } else {
       
   573         SDL_OutOfMemory();
       
   574     }
       
   575     return index;
       
   576 }
       
   577 
       
   578 int
       
   579 SDL_GetNumVideoDisplays(void)
       
   580 {
       
   581     if (!_this) {
       
   582         SDL_UninitializedVideo();
       
   583         return 0;
       
   584     }
       
   585     return _this->num_displays;
       
   586 }
       
   587 
       
   588 static int
       
   589 SDL_GetIndexOfDisplay(SDL_VideoDisplay *display)
       
   590 {
       
   591     int displayIndex;
       
   592 
       
   593     for (displayIndex = 0; displayIndex < _this->num_displays; ++displayIndex) {
       
   594         if (display == &_this->displays[displayIndex]) {
       
   595             return displayIndex;
       
   596         }
       
   597     }
       
   598 
       
   599     /* Couldn't find the display, just use index 0 */
       
   600     return 0;
       
   601 }
       
   602 
       
   603 void *
       
   604 SDL_GetDisplayDriverData( int displayIndex )
       
   605 {
       
   606     CHECK_DISPLAY_INDEX( displayIndex, NULL );
       
   607 
       
   608     return _this->displays[displayIndex].driverdata;
       
   609 }
       
   610 
       
   611 const char *
       
   612 SDL_GetDisplayName(int displayIndex)
       
   613 {
       
   614     CHECK_DISPLAY_INDEX(displayIndex, NULL);
       
   615 
       
   616     return _this->displays[displayIndex].name;
       
   617 }
       
   618 
       
   619 int
       
   620 SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
       
   621 {
       
   622     CHECK_DISPLAY_INDEX(displayIndex, -1);
       
   623 
       
   624     if (rect) {
       
   625         SDL_VideoDisplay *display = &_this->displays[displayIndex];
       
   626 
       
   627         if (_this->GetDisplayBounds) {
       
   628             if (_this->GetDisplayBounds(_this, display, rect) == 0) {
       
   629                 return 0;
       
   630             }
       
   631         }
       
   632 
       
   633         /* Assume that the displays are left to right */
       
   634         if (displayIndex == 0) {
       
   635             rect->x = 0;
       
   636             rect->y = 0;
       
   637         } else {
       
   638             SDL_GetDisplayBounds(displayIndex-1, rect);
       
   639             rect->x += rect->w;
       
   640         }
       
   641         rect->w = display->current_mode.w;
       
   642         rect->h = display->current_mode.h;
       
   643     }
       
   644     return 0;
       
   645 }
       
   646 
       
   647 SDL_bool
       
   648 SDL_AddDisplayMode(SDL_VideoDisplay * display,  const SDL_DisplayMode * mode)
       
   649 {
       
   650     SDL_DisplayMode *modes;
       
   651     int i, nmodes;
       
   652 
       
   653     /* Make sure we don't already have the mode in the list */
       
   654     modes = display->display_modes;
       
   655     nmodes = display->num_display_modes;
       
   656     for (i = 0; i < nmodes; ++i) {
       
   657         if (cmpmodes(mode, &modes[i]) == 0) {
       
   658             return SDL_FALSE;
       
   659         }
       
   660     }
       
   661 
       
   662     /* Go ahead and add the new mode */
       
   663     if (nmodes == display->max_display_modes) {
       
   664         modes =
       
   665             SDL_realloc(modes,
       
   666                         (display->max_display_modes + 32) * sizeof(*modes));
       
   667         if (!modes) {
       
   668             return SDL_FALSE;
       
   669         }
       
   670         display->display_modes = modes;
       
   671         display->max_display_modes += 32;
       
   672     }
       
   673     modes[nmodes] = *mode;
       
   674     display->num_display_modes++;
       
   675 
       
   676     /* Re-sort video modes */
       
   677     SDL_qsort(display->display_modes, display->num_display_modes,
       
   678               sizeof(SDL_DisplayMode), cmpmodes);
       
   679 
       
   680     return SDL_TRUE;
       
   681 }
       
   682 
       
   683 static int
       
   684 SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)
       
   685 {
       
   686     if (!display->num_display_modes && _this->GetDisplayModes) {
       
   687         _this->GetDisplayModes(_this, display);
       
   688         SDL_qsort(display->display_modes, display->num_display_modes,
       
   689                   sizeof(SDL_DisplayMode), cmpmodes);
       
   690     }
       
   691     return display->num_display_modes;
       
   692 }
       
   693 
       
   694 int
       
   695 SDL_GetNumDisplayModes(int displayIndex)
       
   696 {
       
   697     CHECK_DISPLAY_INDEX(displayIndex, -1);
       
   698 
       
   699     return SDL_GetNumDisplayModesForDisplay(&_this->displays[displayIndex]);
       
   700 }
       
   701 
       
   702 int
       
   703 SDL_GetDisplayMode(int displayIndex, int index, SDL_DisplayMode * mode)
       
   704 {
       
   705     SDL_VideoDisplay *display;
       
   706 
       
   707     CHECK_DISPLAY_INDEX(displayIndex, -1);
       
   708 
       
   709     display = &_this->displays[displayIndex];
       
   710     if (index < 0 || index >= SDL_GetNumDisplayModesForDisplay(display)) {
       
   711         return SDL_SetError("index must be in the range of 0 - %d",
       
   712                             SDL_GetNumDisplayModesForDisplay(display) - 1);
       
   713     }
       
   714     if (mode) {
       
   715         *mode = display->display_modes[index];
       
   716     }
       
   717     return 0;
       
   718 }
       
   719 
       
   720 int
       
   721 SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode)
       
   722 {
       
   723     SDL_VideoDisplay *display;
       
   724 
       
   725     CHECK_DISPLAY_INDEX(displayIndex, -1);
       
   726 
       
   727     display = &_this->displays[displayIndex];
       
   728     if (mode) {
       
   729         *mode = display->desktop_mode;
       
   730     }
       
   731     return 0;
       
   732 }
       
   733 
       
   734 int
       
   735 SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode)
       
   736 {
       
   737     SDL_VideoDisplay *display;
       
   738 
       
   739     CHECK_DISPLAY_INDEX(displayIndex, -1);
       
   740 
       
   741     display = &_this->displays[displayIndex];
       
   742     if (mode) {
       
   743         *mode = display->current_mode;
       
   744     }
       
   745     return 0;
       
   746 }
       
   747 
       
   748 static SDL_DisplayMode *
       
   749 SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,
       
   750                                     const SDL_DisplayMode * mode,
       
   751                                     SDL_DisplayMode * closest)
       
   752 {
       
   753     Uint32 target_format;
       
   754     int target_refresh_rate;
       
   755     int i;
       
   756     SDL_DisplayMode *current, *match;
       
   757 
       
   758     if (!mode || !closest) {
       
   759         SDL_SetError("Missing desired mode or closest mode parameter");
       
   760         return NULL;
       
   761     }
       
   762 
       
   763     /* Default to the desktop format */
       
   764     if (mode->format) {
       
   765         target_format = mode->format;
       
   766     } else {
       
   767         target_format = display->desktop_mode.format;
       
   768     }
       
   769 
       
   770     /* Default to the desktop refresh rate */
       
   771     if (mode->refresh_rate) {
       
   772         target_refresh_rate = mode->refresh_rate;
       
   773     } else {
       
   774         target_refresh_rate = display->desktop_mode.refresh_rate;
       
   775     }
       
   776 
       
   777     match = NULL;
       
   778     for (i = 0; i < SDL_GetNumDisplayModesForDisplay(display); ++i) {
       
   779         current = &display->display_modes[i];
       
   780 
       
   781         if (current->w && (current->w < mode->w)) {
       
   782             /* Out of sorted modes large enough here */
       
   783             break;
       
   784         }
       
   785         if (current->h && (current->h < mode->h)) {
       
   786             if (current->w && (current->w == mode->w)) {
       
   787                 /* Out of sorted modes large enough here */
       
   788                 break;
       
   789             }
       
   790             /* Wider, but not tall enough, due to a different
       
   791                aspect ratio. This mode must be skipped, but closer
       
   792                modes may still follow. */
       
   793             continue;
       
   794         }
       
   795         if (!match || current->w < match->w || current->h < match->h) {
       
   796             match = current;
       
   797             continue;
       
   798         }
       
   799         if (current->format != match->format) {
       
   800             /* Sorted highest depth to lowest */
       
   801             if (current->format == target_format ||
       
   802                 (SDL_BITSPERPIXEL(current->format) >=
       
   803                  SDL_BITSPERPIXEL(target_format)
       
   804                  && SDL_PIXELTYPE(current->format) ==
       
   805                  SDL_PIXELTYPE(target_format))) {
       
   806                 match = current;
       
   807             }
       
   808             continue;
       
   809         }
       
   810         if (current->refresh_rate != match->refresh_rate) {
       
   811             /* Sorted highest refresh to lowest */
       
   812             if (current->refresh_rate >= target_refresh_rate) {
       
   813                 match = current;
       
   814             }
       
   815         }
       
   816     }
       
   817     if (match) {
       
   818         if (match->format) {
       
   819             closest->format = match->format;
       
   820         } else {
       
   821             closest->format = mode->format;
       
   822         }
       
   823         if (match->w && match->h) {
       
   824             closest->w = match->w;
       
   825             closest->h = match->h;
       
   826         } else {
       
   827             closest->w = mode->w;
       
   828             closest->h = mode->h;
       
   829         }
       
   830         if (match->refresh_rate) {
       
   831             closest->refresh_rate = match->refresh_rate;
       
   832         } else {
       
   833             closest->refresh_rate = mode->refresh_rate;
       
   834         }
       
   835         closest->driverdata = match->driverdata;
       
   836 
       
   837         /*
       
   838          * Pick some reasonable defaults if the app and driver don't
       
   839          * care
       
   840          */
       
   841         if (!closest->format) {
       
   842             closest->format = SDL_PIXELFORMAT_RGB888;
       
   843         }
       
   844         if (!closest->w) {
       
   845             closest->w = 640;
       
   846         }
       
   847         if (!closest->h) {
       
   848             closest->h = 480;
       
   849         }
       
   850         return closest;
       
   851     }
       
   852     return NULL;
       
   853 }
       
   854 
       
   855 SDL_DisplayMode *
       
   856 SDL_GetClosestDisplayMode(int displayIndex,
       
   857                           const SDL_DisplayMode * mode,
       
   858                           SDL_DisplayMode * closest)
       
   859 {
       
   860     SDL_VideoDisplay *display;
       
   861 
       
   862     CHECK_DISPLAY_INDEX(displayIndex, NULL);
       
   863 
       
   864     display = &_this->displays[displayIndex];
       
   865     return SDL_GetClosestDisplayModeForDisplay(display, mode, closest);
       
   866 }
       
   867 
       
   868 static int
       
   869 SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
       
   870 {
       
   871     SDL_DisplayMode display_mode;
       
   872     SDL_DisplayMode current_mode;
       
   873 
       
   874     if (mode) {
       
   875         display_mode = *mode;
       
   876 
       
   877         /* Default to the current mode */
       
   878         if (!display_mode.format) {
       
   879             display_mode.format = display->current_mode.format;
       
   880         }
       
   881         if (!display_mode.w) {
       
   882             display_mode.w = display->current_mode.w;
       
   883         }
       
   884         if (!display_mode.h) {
       
   885             display_mode.h = display->current_mode.h;
       
   886         }
       
   887         if (!display_mode.refresh_rate) {
       
   888             display_mode.refresh_rate = display->current_mode.refresh_rate;
       
   889         }
       
   890 
       
   891         /* Get a good video mode, the closest one possible */
       
   892         if (!SDL_GetClosestDisplayModeForDisplay(display, &display_mode, &display_mode)) {
       
   893             return SDL_SetError("No video mode large enough for %dx%d",
       
   894                                 display_mode.w, display_mode.h);
       
   895         }
       
   896     } else {
       
   897         display_mode = display->desktop_mode;
       
   898     }
       
   899 
       
   900     /* See if there's anything left to do */
       
   901     current_mode = display->current_mode;
       
   902     if (SDL_memcmp(&display_mode, &current_mode, sizeof(display_mode)) == 0) {
       
   903         return 0;
       
   904     }
       
   905 
       
   906     /* Actually change the display mode */
       
   907     if (!_this->SetDisplayMode) {
       
   908         return SDL_SetError("Video driver doesn't support changing display mode");
       
   909     }
       
   910     if (_this->SetDisplayMode(_this, display, &display_mode) < 0) {
       
   911         return -1;
       
   912     }
       
   913     display->current_mode = display_mode;
       
   914     return 0;
       
   915 }
       
   916 
       
   917 int
       
   918 SDL_GetWindowDisplayIndex(SDL_Window * window)
       
   919 {
       
   920     int displayIndex;
       
   921     int i, dist;
       
   922     int closest = -1;
       
   923     int closest_dist = 0x7FFFFFFF;
       
   924     SDL_Point center;
       
   925     SDL_Point delta;
       
   926     SDL_Rect rect;
       
   927 
       
   928     CHECK_WINDOW_MAGIC(window, -1);
       
   929 
       
   930     if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
       
   931         SDL_WINDOWPOS_ISCENTERED(window->x)) {
       
   932         displayIndex = (window->x & 0xFFFF);
       
   933         if (displayIndex >= _this->num_displays) {
       
   934             displayIndex = 0;
       
   935         }
       
   936         return displayIndex;
       
   937     }
       
   938     if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
       
   939         SDL_WINDOWPOS_ISCENTERED(window->y)) {
       
   940         displayIndex = (window->y & 0xFFFF);
       
   941         if (displayIndex >= _this->num_displays) {
       
   942             displayIndex = 0;
       
   943         }
       
   944         return displayIndex;
       
   945     }
       
   946 
       
   947     /* Find the display containing the window */
       
   948     for (i = 0; i < _this->num_displays; ++i) {
       
   949         SDL_VideoDisplay *display = &_this->displays[i];
       
   950 
       
   951         if (display->fullscreen_window == window) {
       
   952             return i;
       
   953         }
       
   954     }
       
   955     center.x = window->x + window->w / 2;
       
   956     center.y = window->y + window->h / 2;
       
   957     for (i = 0; i < _this->num_displays; ++i) {
       
   958         SDL_GetDisplayBounds(i, &rect);
       
   959         if (SDL_EnclosePoints(&center, 1, &rect, NULL)) {
       
   960             return i;
       
   961         }
       
   962 
       
   963         delta.x = center.x - (rect.x + rect.w / 2);
       
   964         delta.y = center.y - (rect.y + rect.h / 2);
       
   965         dist = (delta.x*delta.x + delta.y*delta.y);
       
   966         if (dist < closest_dist) {
       
   967             closest = i;
       
   968             closest_dist = dist;
       
   969         }
       
   970     }
       
   971     if (closest < 0) {
       
   972         SDL_SetError("Couldn't find any displays");
       
   973     }
       
   974     return closest;
       
   975 }
       
   976 
       
   977 SDL_VideoDisplay *
       
   978 SDL_GetDisplayForWindow(SDL_Window *window)
       
   979 {
       
   980     int displayIndex = SDL_GetWindowDisplayIndex(window);
       
   981     if (displayIndex >= 0) {
       
   982         return &_this->displays[displayIndex];
       
   983     } else {
       
   984         return NULL;
       
   985     }
       
   986 }
       
   987 
       
   988 int
       
   989 SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
       
   990 {
       
   991     CHECK_WINDOW_MAGIC(window, -1);
       
   992 
       
   993     if (mode) {
       
   994         window->fullscreen_mode = *mode;
       
   995     } else {
       
   996         SDL_zero(window->fullscreen_mode);
       
   997     }
       
   998     return 0;
       
   999 }
       
  1000 
       
  1001 int
       
  1002 SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
       
  1003 {
       
  1004     SDL_DisplayMode fullscreen_mode;
       
  1005     SDL_VideoDisplay *display;
       
  1006 
       
  1007     if (!mode) {
       
  1008       return SDL_InvalidParamError("mode");
       
  1009     }
       
  1010 
       
  1011     CHECK_WINDOW_MAGIC(window, -1);
       
  1012 
       
  1013     fullscreen_mode = window->fullscreen_mode;
       
  1014     if (!fullscreen_mode.w) {
       
  1015         fullscreen_mode.w = window->w;
       
  1016     }
       
  1017     if (!fullscreen_mode.h) {
       
  1018         fullscreen_mode.h = window->h;
       
  1019     }
       
  1020 
       
  1021     display = SDL_GetDisplayForWindow(window);
       
  1022 
       
  1023     /* if in desktop size mode, just return the size of the desktop */
       
  1024     if ( ( window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP )
       
  1025     {
       
  1026         fullscreen_mode = display->desktop_mode;
       
  1027     }
       
  1028     else if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
       
  1029                                              &fullscreen_mode,
       
  1030                                              &fullscreen_mode)) {
       
  1031         return SDL_SetError("Couldn't find display mode match");
       
  1032     }
       
  1033 
       
  1034     if (mode) {
       
  1035         *mode = fullscreen_mode;
       
  1036     }
       
  1037     return 0;
       
  1038 }
       
  1039 
       
  1040 Uint32
       
  1041 SDL_GetWindowPixelFormat(SDL_Window * window)
       
  1042 {
       
  1043     SDL_VideoDisplay *display;
       
  1044 
       
  1045     CHECK_WINDOW_MAGIC(window, SDL_PIXELFORMAT_UNKNOWN);
       
  1046 
       
  1047     display = SDL_GetDisplayForWindow(window);
       
  1048     return display->current_mode.format;
       
  1049 }
       
  1050 
       
  1051 static void
       
  1052 SDL_RestoreMousePosition(SDL_Window *window)
       
  1053 {
       
  1054     int x, y;
       
  1055 
       
  1056     if (window == SDL_GetMouseFocus()) {
       
  1057         SDL_GetMouseState(&x, &y);
       
  1058         SDL_WarpMouseInWindow(window, x, y);
       
  1059     }
       
  1060 }
       
  1061 
       
  1062 static void
       
  1063 SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
       
  1064 {
       
  1065     SDL_VideoDisplay *display;
       
  1066     SDL_Window *other;
       
  1067 
       
  1068 #ifdef __MACOSX__
       
  1069     if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) {
       
  1070         window->last_fullscreen_flags = window->flags;
       
  1071         return;
       
  1072     }
       
  1073 #endif
       
  1074 
       
  1075     display = SDL_GetDisplayForWindow(window);
       
  1076 
       
  1077     if (fullscreen) {
       
  1078         /* Hide any other fullscreen windows */
       
  1079         if (display->fullscreen_window &&
       
  1080             display->fullscreen_window != window) {
       
  1081             SDL_MinimizeWindow(display->fullscreen_window);
       
  1082         }
       
  1083     }
       
  1084 
       
  1085     /* See if anything needs to be done now */
       
  1086     if ((display->fullscreen_window == window) == fullscreen) {
       
  1087         if ((window->last_fullscreen_flags & FULLSCREEN_MASK) == (window->flags & FULLSCREEN_MASK)) {
       
  1088             return;
       
  1089         }
       
  1090     }
       
  1091 
       
  1092     /* See if there are any fullscreen windows */
       
  1093     for (other = _this->windows; other; other = other->next) {
       
  1094         SDL_bool setDisplayMode = SDL_FALSE;
       
  1095 
       
  1096         if (other == window) {
       
  1097             setDisplayMode = fullscreen;
       
  1098         } else if (FULLSCREEN_VISIBLE(other) &&
       
  1099                    SDL_GetDisplayForWindow(other) == display) {
       
  1100             setDisplayMode = SDL_TRUE;
       
  1101         }
       
  1102 
       
  1103         if (setDisplayMode) {
       
  1104             SDL_DisplayMode fullscreen_mode;
       
  1105 
       
  1106             if (SDL_GetWindowDisplayMode(other, &fullscreen_mode) == 0) {
       
  1107                 SDL_bool resized = SDL_TRUE;
       
  1108 
       
  1109                 if (other->w == fullscreen_mode.w && other->h == fullscreen_mode.h) {
       
  1110                     resized = SDL_FALSE;
       
  1111                 }
       
  1112 
       
  1113                 /* only do the mode change if we want exclusive fullscreen */
       
  1114                 if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
       
  1115                     SDL_SetDisplayModeForDisplay(display, &fullscreen_mode);
       
  1116                 } else {
       
  1117                     SDL_SetDisplayModeForDisplay(display, NULL);
       
  1118                 }
       
  1119 
       
  1120                 if (_this->SetWindowFullscreen) {
       
  1121                     _this->SetWindowFullscreen(_this, other, display, SDL_TRUE);
       
  1122                 }
       
  1123                 display->fullscreen_window = other;
       
  1124 
       
  1125                 /* Generate a mode change event here */
       
  1126                 if (resized) {
       
  1127                     SDL_SendWindowEvent(other, SDL_WINDOWEVENT_RESIZED,
       
  1128                                         fullscreen_mode.w, fullscreen_mode.h);
       
  1129                 } else {
       
  1130                     SDL_OnWindowResized(other);
       
  1131                 }
       
  1132 
       
  1133                 SDL_RestoreMousePosition(other);
       
  1134 
       
  1135                 window->last_fullscreen_flags = window->flags;
       
  1136                 return;
       
  1137             }
       
  1138         }
       
  1139     }
       
  1140 
       
  1141     /* Nope, restore the desktop mode */
       
  1142     SDL_SetDisplayModeForDisplay(display, NULL);
       
  1143 
       
  1144     if (_this->SetWindowFullscreen) {
       
  1145         _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
       
  1146     }
       
  1147     display->fullscreen_window = NULL;
       
  1148 
       
  1149     /* Generate a mode change event here */
       
  1150     SDL_OnWindowResized(window);
       
  1151 
       
  1152     /* Restore the cursor position */
       
  1153     SDL_RestoreMousePosition(window);
       
  1154 
       
  1155     window->last_fullscreen_flags = window->flags;
       
  1156 }
       
  1157 
       
  1158 #define CREATE_FLAGS \
       
  1159     (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI)
       
  1160 
       
  1161 static void
       
  1162 SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
       
  1163 {
       
  1164     window->windowed.x = window->x;
       
  1165     window->windowed.y = window->y;
       
  1166     window->windowed.w = window->w;
       
  1167     window->windowed.h = window->h;
       
  1168 
       
  1169     if (flags & SDL_WINDOW_MAXIMIZED) {
       
  1170         SDL_MaximizeWindow(window);
       
  1171     }
       
  1172     if (flags & SDL_WINDOW_MINIMIZED) {
       
  1173         SDL_MinimizeWindow(window);
       
  1174     }
       
  1175     if (flags & SDL_WINDOW_FULLSCREEN) {
       
  1176         SDL_SetWindowFullscreen(window, flags);
       
  1177     }
       
  1178     if (flags & SDL_WINDOW_INPUT_GRABBED) {
       
  1179         SDL_SetWindowGrab(window, SDL_TRUE);
       
  1180     }
       
  1181     if (!(flags & SDL_WINDOW_HIDDEN)) {
       
  1182         SDL_ShowWindow(window);
       
  1183     }
       
  1184 }
       
  1185 
       
  1186 SDL_Window *
       
  1187 SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
       
  1188 {
       
  1189     SDL_Window *window;
       
  1190     const char *hint;
       
  1191 
       
  1192     if (!_this) {
       
  1193         /* Initialize the video system if needed */
       
  1194         if (SDL_VideoInit(NULL) < 0) {
       
  1195             return NULL;
       
  1196         }
       
  1197     }
       
  1198 
       
  1199     /* Some platforms can't create zero-sized windows */
       
  1200     if (w < 1) {
       
  1201         w = 1;
       
  1202     }
       
  1203     if (h < 1) {
       
  1204         h = 1;
       
  1205     }
       
  1206 
       
  1207     /* Some platforms have OpenGL enabled by default */
       
  1208 #if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__
       
  1209     flags |= SDL_WINDOW_OPENGL;
       
  1210 #endif
       
  1211     if (flags & SDL_WINDOW_OPENGL) {
       
  1212         if (!_this->GL_CreateContext) {
       
  1213             SDL_SetError("No OpenGL support in video driver");
       
  1214             return NULL;
       
  1215         }
       
  1216         if (SDL_GL_LoadLibrary(NULL) < 0) {
       
  1217             return NULL;
       
  1218         }
       
  1219     }
       
  1220 
       
  1221     /* Unless the user has specified the high-DPI disabling hint, respect the
       
  1222      * SDL_WINDOW_ALLOW_HIGHDPI flag.
       
  1223      */
       
  1224     if (flags & SDL_WINDOW_ALLOW_HIGHDPI) {
       
  1225         hint = SDL_GetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED);
       
  1226         if (hint && SDL_atoi(hint) > 0) {
       
  1227             flags &= ~SDL_WINDOW_ALLOW_HIGHDPI;
       
  1228         }
       
  1229     }
       
  1230 
       
  1231     window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
       
  1232     if (!window) {
       
  1233         SDL_OutOfMemory();
       
  1234         return NULL;
       
  1235     }
       
  1236     window->magic = &_this->window_magic;
       
  1237     window->id = _this->next_object_id++;
       
  1238     window->x = x;
       
  1239     window->y = y;
       
  1240     window->w = w;
       
  1241     window->h = h;
       
  1242     if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) ||
       
  1243         SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
       
  1244         SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
       
  1245         int displayIndex;
       
  1246         SDL_Rect bounds;
       
  1247 
       
  1248         displayIndex = SDL_GetIndexOfDisplay(display);
       
  1249         SDL_GetDisplayBounds(displayIndex, &bounds);
       
  1250         if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
       
  1251             window->x = bounds.x + (bounds.w - w) / 2;
       
  1252         }
       
  1253         if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
       
  1254             window->y = bounds.y + (bounds.h - h) / 2;
       
  1255         }
       
  1256     }
       
  1257     window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
       
  1258     window->last_fullscreen_flags = window->flags;
       
  1259     window->brightness = 1.0f;
       
  1260     window->next = _this->windows;
       
  1261     window->is_destroying = SDL_FALSE;
       
  1262 
       
  1263     if (_this->windows) {
       
  1264         _this->windows->prev = window;
       
  1265     }
       
  1266     _this->windows = window;
       
  1267 
       
  1268     if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
       
  1269         SDL_DestroyWindow(window);
       
  1270         return NULL;
       
  1271     }
       
  1272 
       
  1273     if (title) {
       
  1274         SDL_SetWindowTitle(window, title);
       
  1275     }
       
  1276     SDL_FinishWindowCreation(window, flags);
       
  1277 
       
  1278     /* If the window was created fullscreen, make sure the mode code matches */
       
  1279     SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
       
  1280 
       
  1281     return window;
       
  1282 }
       
  1283 
       
  1284 SDL_Window *
       
  1285 SDL_CreateWindowFrom(const void *data)
       
  1286 {
       
  1287     SDL_Window *window;
       
  1288 
       
  1289     if (!_this) {
       
  1290         SDL_UninitializedVideo();
       
  1291         return NULL;
       
  1292     }
       
  1293     window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
       
  1294     if (!window) {
       
  1295         SDL_OutOfMemory();
       
  1296         return NULL;
       
  1297     }
       
  1298     window->magic = &_this->window_magic;
       
  1299     window->id = _this->next_object_id++;
       
  1300     window->flags = SDL_WINDOW_FOREIGN;
       
  1301     window->last_fullscreen_flags = window->flags;
       
  1302     window->is_destroying = SDL_FALSE;
       
  1303     window->brightness = 1.0f;
       
  1304     window->next = _this->windows;
       
  1305     if (_this->windows) {
       
  1306         _this->windows->prev = window;
       
  1307     }
       
  1308     _this->windows = window;
       
  1309 
       
  1310     if (!_this->CreateWindowFrom ||
       
  1311         _this->CreateWindowFrom(_this, window, data) < 0) {
       
  1312         SDL_DestroyWindow(window);
       
  1313         return NULL;
       
  1314     }
       
  1315     return window;
       
  1316 }
       
  1317 
       
  1318 int
       
  1319 SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
       
  1320 {
       
  1321     char *title = window->title;
       
  1322     SDL_Surface *icon = window->icon;
       
  1323 
       
  1324     if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
       
  1325         return SDL_SetError("No OpenGL support in video driver");
       
  1326     }
       
  1327 
       
  1328     if (window->flags & SDL_WINDOW_FOREIGN) {
       
  1329         /* Can't destroy and re-create foreign windows, hrm */
       
  1330         flags |= SDL_WINDOW_FOREIGN;
       
  1331     } else {
       
  1332         flags &= ~SDL_WINDOW_FOREIGN;
       
  1333     }
       
  1334 
       
  1335     /* Restore video mode, etc. */
       
  1336     SDL_HideWindow(window);
       
  1337 
       
  1338     /* Tear down the old native window */
       
  1339     if (window->surface) {
       
  1340         window->surface->flags &= ~SDL_DONTFREE;
       
  1341         SDL_FreeSurface(window->surface);
       
  1342     }
       
  1343     if (_this->DestroyWindowFramebuffer) {
       
  1344         _this->DestroyWindowFramebuffer(_this, window);
       
  1345     }
       
  1346     if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
       
  1347         _this->DestroyWindow(_this, window);
       
  1348     }
       
  1349 
       
  1350     if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
       
  1351         if (flags & SDL_WINDOW_OPENGL) {
       
  1352             if (SDL_GL_LoadLibrary(NULL) < 0) {
       
  1353                 return -1;
       
  1354             }
       
  1355         } else {
       
  1356             SDL_GL_UnloadLibrary();
       
  1357         }
       
  1358     }
       
  1359 
       
  1360     window->title = NULL;
       
  1361     window->icon = NULL;
       
  1362     window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
       
  1363     window->last_fullscreen_flags = window->flags;
       
  1364     window->is_destroying = SDL_FALSE;
       
  1365 
       
  1366     if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
       
  1367         if (_this->CreateWindow(_this, window) < 0) {
       
  1368             if (flags & SDL_WINDOW_OPENGL) {
       
  1369                 SDL_GL_UnloadLibrary();
       
  1370             }
       
  1371             return -1;
       
  1372         }
       
  1373     }
       
  1374 
       
  1375     if (title) {
       
  1376         SDL_SetWindowTitle(window, title);
       
  1377         SDL_free(title);
       
  1378     }
       
  1379     if (icon) {
       
  1380         SDL_SetWindowIcon(window, icon);
       
  1381         SDL_FreeSurface(icon);
       
  1382     }
       
  1383     SDL_FinishWindowCreation(window, flags);
       
  1384 
       
  1385     return 0;
       
  1386 }
       
  1387 
       
  1388 Uint32
       
  1389 SDL_GetWindowID(SDL_Window * window)
       
  1390 {
       
  1391     CHECK_WINDOW_MAGIC(window, 0);
       
  1392 
       
  1393     return window->id;
       
  1394 }
       
  1395 
       
  1396 SDL_Window *
       
  1397 SDL_GetWindowFromID(Uint32 id)
       
  1398 {
       
  1399     SDL_Window *window;
       
  1400 
       
  1401     if (!_this) {
       
  1402         return NULL;
       
  1403     }
       
  1404     for (window = _this->windows; window; window = window->next) {
       
  1405         if (window->id == id) {
       
  1406             return window;
       
  1407         }
       
  1408     }
       
  1409     return NULL;
       
  1410 }
       
  1411 
       
  1412 Uint32
       
  1413 SDL_GetWindowFlags(SDL_Window * window)
       
  1414 {
       
  1415     CHECK_WINDOW_MAGIC(window, 0);
       
  1416 
       
  1417     return window->flags;
       
  1418 }
       
  1419 
       
  1420 void
       
  1421 SDL_SetWindowTitle(SDL_Window * window, const char *title)
       
  1422 {
       
  1423     CHECK_WINDOW_MAGIC(window, );
       
  1424 
       
  1425     if (title == window->title) {
       
  1426         return;
       
  1427     }
       
  1428     SDL_free(window->title);
       
  1429     if (title && *title) {
       
  1430         window->title = SDL_strdup(title);
       
  1431     } else {
       
  1432         window->title = NULL;
       
  1433     }
       
  1434 
       
  1435     if (_this->SetWindowTitle) {
       
  1436         _this->SetWindowTitle(_this, window);
       
  1437     }
       
  1438 }
       
  1439 
       
  1440 const char *
       
  1441 SDL_GetWindowTitle(SDL_Window * window)
       
  1442 {
       
  1443     CHECK_WINDOW_MAGIC(window, "");
       
  1444 
       
  1445     return window->title ? window->title : "";
       
  1446 }
       
  1447 
       
  1448 void
       
  1449 SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon)
       
  1450 {
       
  1451     CHECK_WINDOW_MAGIC(window, );
       
  1452 
       
  1453     if (!icon) {
       
  1454         return;
       
  1455     }
       
  1456 
       
  1457     SDL_FreeSurface(window->icon);
       
  1458 
       
  1459     /* Convert the icon into ARGB8888 */
       
  1460     window->icon = SDL_ConvertSurfaceFormat(icon, SDL_PIXELFORMAT_ARGB8888, 0);
       
  1461     if (!window->icon) {
       
  1462         return;
       
  1463     }
       
  1464 
       
  1465     if (_this->SetWindowIcon) {
       
  1466         _this->SetWindowIcon(_this, window, window->icon);
       
  1467     }
       
  1468 }
       
  1469 
       
  1470 void*
       
  1471 SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata)
       
  1472 {
       
  1473     SDL_WindowUserData *prev, *data;
       
  1474 
       
  1475     CHECK_WINDOW_MAGIC(window, NULL);
       
  1476 
       
  1477     /* Input validation */
       
  1478     if (name == NULL || name[0] == '\0') {
       
  1479       SDL_InvalidParamError("name");
       
  1480       return NULL;
       
  1481     }
       
  1482 
       
  1483     /* See if the named data already exists */
       
  1484     prev = NULL;
       
  1485     for (data = window->data; data; prev = data, data = data->next) {
       
  1486         if (data->name && SDL_strcmp(data->name, name) == 0) {
       
  1487             void *last_value = data->data;
       
  1488 
       
  1489             if (userdata) {
       
  1490                 /* Set the new value */
       
  1491                 data->data = userdata;
       
  1492             } else {
       
  1493                 /* Delete this value */
       
  1494                 if (prev) {
       
  1495                     prev->next = data->next;
       
  1496                 } else {
       
  1497                     window->data = data->next;
       
  1498                 }
       
  1499                 SDL_free(data->name);
       
  1500                 SDL_free(data);
       
  1501             }
       
  1502             return last_value;
       
  1503         }
       
  1504     }
       
  1505 
       
  1506     /* Add new data to the window */
       
  1507     if (userdata) {
       
  1508         data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data));
       
  1509         data->name = SDL_strdup(name);
       
  1510         data->data = userdata;
       
  1511         data->next = window->data;
       
  1512         window->data = data;
       
  1513     }
       
  1514     return NULL;
       
  1515 }
       
  1516 
       
  1517 void *
       
  1518 SDL_GetWindowData(SDL_Window * window, const char *name)
       
  1519 {
       
  1520     SDL_WindowUserData *data;
       
  1521 
       
  1522     CHECK_WINDOW_MAGIC(window, NULL);
       
  1523 
       
  1524     /* Input validation */
       
  1525     if (name == NULL || name[0] == '\0') {
       
  1526       SDL_InvalidParamError("name");
       
  1527       return NULL;
       
  1528     }
       
  1529 
       
  1530     for (data = window->data; data; data = data->next) {
       
  1531         if (data->name && SDL_strcmp(data->name, name) == 0) {
       
  1532             return data->data;
       
  1533         }
       
  1534     }
       
  1535     return NULL;
       
  1536 }
       
  1537 
       
  1538 void
       
  1539 SDL_SetWindowPosition(SDL_Window * window, int x, int y)
       
  1540 {
       
  1541     CHECK_WINDOW_MAGIC(window, );
       
  1542 
       
  1543     if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
       
  1544         SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
       
  1545         int displayIndex;
       
  1546         SDL_Rect bounds;
       
  1547 
       
  1548         displayIndex = SDL_GetIndexOfDisplay(display);
       
  1549         SDL_GetDisplayBounds(displayIndex, &bounds);
       
  1550         if (SDL_WINDOWPOS_ISCENTERED(x)) {
       
  1551             x = bounds.x + (bounds.w - window->w) / 2;
       
  1552         }
       
  1553         if (SDL_WINDOWPOS_ISCENTERED(y)) {
       
  1554             y = bounds.y + (bounds.h - window->h) / 2;
       
  1555         }
       
  1556     }
       
  1557 
       
  1558     if ((window->flags & SDL_WINDOW_FULLSCREEN)) {
       
  1559         if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
       
  1560             window->windowed.x = x;
       
  1561         }
       
  1562         if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
       
  1563             window->windowed.y = y;
       
  1564         }
       
  1565     } else {
       
  1566         if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
       
  1567             window->x = x;
       
  1568         }
       
  1569         if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
       
  1570             window->y = y;
       
  1571         }
       
  1572 
       
  1573         if (_this->SetWindowPosition) {
       
  1574             _this->SetWindowPosition(_this, window);
       
  1575         }
       
  1576         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
       
  1577     }
       
  1578 }
       
  1579 
       
  1580 void
       
  1581 SDL_GetWindowPosition(SDL_Window * window, int *x, int *y)
       
  1582 {
       
  1583     CHECK_WINDOW_MAGIC(window, );
       
  1584 
       
  1585     /* Fullscreen windows are always at their display's origin */
       
  1586     if (window->flags & SDL_WINDOW_FULLSCREEN) {
       
  1587         if (x) {
       
  1588             *x = 0;
       
  1589         }
       
  1590         if (y) {
       
  1591             *y = 0;
       
  1592         }
       
  1593     } else {
       
  1594         if (x) {
       
  1595             *x = window->x;
       
  1596         }
       
  1597         if (y) {
       
  1598             *y = window->y;
       
  1599         }
       
  1600     }
       
  1601 }
       
  1602 
       
  1603 void
       
  1604 SDL_SetWindowBordered(SDL_Window * window, SDL_bool bordered)
       
  1605 {
       
  1606     CHECK_WINDOW_MAGIC(window, );
       
  1607     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
       
  1608         const int want = (bordered != SDL_FALSE);  /* normalize the flag. */
       
  1609         const int have = ((window->flags & SDL_WINDOW_BORDERLESS) == 0);
       
  1610         if ((want != have) && (_this->SetWindowBordered)) {
       
  1611             if (want) {
       
  1612                 window->flags &= ~SDL_WINDOW_BORDERLESS;
       
  1613             } else {
       
  1614                 window->flags |= SDL_WINDOW_BORDERLESS;
       
  1615             }
       
  1616             _this->SetWindowBordered(_this, window, (SDL_bool) want);
       
  1617         }
       
  1618     }
       
  1619 }
       
  1620 
       
  1621 void
       
  1622 SDL_SetWindowSize(SDL_Window * window, int w, int h)
       
  1623 {
       
  1624     CHECK_WINDOW_MAGIC(window, );
       
  1625     if (w <= 0) {
       
  1626         SDL_InvalidParamError("w");
       
  1627         return;
       
  1628     }
       
  1629     if (h <= 0) {
       
  1630         SDL_InvalidParamError("h");
       
  1631         return;
       
  1632     }
       
  1633 
       
  1634     /* Make sure we don't exceed any window size limits */
       
  1635     if (window->min_w && w < window->min_w)
       
  1636     {
       
  1637         w = window->min_w;
       
  1638     }
       
  1639     if (window->max_w && w > window->max_w)
       
  1640     {
       
  1641         w = window->max_w;
       
  1642     }
       
  1643     if (window->min_h && h < window->min_h)
       
  1644     {
       
  1645         h = window->min_h;
       
  1646     }
       
  1647     if (window->max_h && h > window->max_h)
       
  1648     {
       
  1649         h = window->max_h;
       
  1650     }
       
  1651 
       
  1652     /* FIXME: Should this change fullscreen modes? */
       
  1653     if (window->flags & SDL_WINDOW_FULLSCREEN) {
       
  1654         window->windowed.w = w;
       
  1655         window->windowed.h = h;
       
  1656     } else {
       
  1657         window->w = w;
       
  1658         window->h = h;
       
  1659         if (_this->SetWindowSize) {
       
  1660             _this->SetWindowSize(_this, window);
       
  1661         }
       
  1662         if (window->w == w && window->h == h) {
       
  1663             /* We didn't get a SDL_WINDOWEVENT_RESIZED event (by design) */
       
  1664             SDL_OnWindowResized(window);
       
  1665         }
       
  1666     }
       
  1667 }
       
  1668 
       
  1669 void
       
  1670 SDL_GetWindowSize(SDL_Window * window, int *w, int *h)
       
  1671 {
       
  1672     CHECK_WINDOW_MAGIC(window, );
       
  1673     if (w) {
       
  1674         *w = window->w;
       
  1675     }
       
  1676     if (h) {
       
  1677         *h = window->h;
       
  1678     }
       
  1679 }
       
  1680 
       
  1681 void
       
  1682 SDL_SetWindowMinimumSize(SDL_Window * window, int min_w, int min_h)
       
  1683 {
       
  1684     CHECK_WINDOW_MAGIC(window, );
       
  1685     if (min_w <= 0) {
       
  1686         SDL_InvalidParamError("min_w");
       
  1687         return;
       
  1688     }
       
  1689     if (min_h <= 0) {
       
  1690         SDL_InvalidParamError("min_h");
       
  1691         return;
       
  1692     }
       
  1693 
       
  1694     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
       
  1695         window->min_w = min_w;
       
  1696         window->min_h = min_h;
       
  1697         if (_this->SetWindowMinimumSize) {
       
  1698             _this->SetWindowMinimumSize(_this, window);
       
  1699         }
       
  1700         /* Ensure that window is not smaller than minimal size */
       
  1701         SDL_SetWindowSize(window, SDL_max(window->w, window->min_w), SDL_max(window->h, window->min_h));
       
  1702     }
       
  1703 }
       
  1704 
       
  1705 void
       
  1706 SDL_GetWindowMinimumSize(SDL_Window * window, int *min_w, int *min_h)
       
  1707 {
       
  1708     CHECK_WINDOW_MAGIC(window, );
       
  1709     if (min_w) {
       
  1710         *min_w = window->min_w;
       
  1711     }
       
  1712     if (min_h) {
       
  1713         *min_h = window->min_h;
       
  1714     }
       
  1715 }
       
  1716 
       
  1717 void
       
  1718 SDL_SetWindowMaximumSize(SDL_Window * window, int max_w, int max_h)
       
  1719 {
       
  1720     CHECK_WINDOW_MAGIC(window, );
       
  1721     if (max_w <= 0) {
       
  1722         SDL_InvalidParamError("max_w");
       
  1723         return;
       
  1724     }
       
  1725     if (max_h <= 0) {
       
  1726         SDL_InvalidParamError("max_h");
       
  1727         return;
       
  1728     }
       
  1729 
       
  1730     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
       
  1731         window->max_w = max_w;
       
  1732         window->max_h = max_h;
       
  1733         if (_this->SetWindowMaximumSize) {
       
  1734             _this->SetWindowMaximumSize(_this, window);
       
  1735         }
       
  1736         /* Ensure that window is not larger than maximal size */
       
  1737         SDL_SetWindowSize(window, SDL_min(window->w, window->max_w), SDL_min(window->h, window->max_h));
       
  1738     }
       
  1739 }
       
  1740 
       
  1741 void
       
  1742 SDL_GetWindowMaximumSize(SDL_Window * window, int *max_w, int *max_h)
       
  1743 {
       
  1744     CHECK_WINDOW_MAGIC(window, );
       
  1745     if (max_w) {
       
  1746         *max_w = window->max_w;
       
  1747     }
       
  1748     if (max_h) {
       
  1749         *max_h = window->max_h;
       
  1750     }
       
  1751 }
       
  1752 
       
  1753 void
       
  1754 SDL_ShowWindow(SDL_Window * window)
       
  1755 {
       
  1756     CHECK_WINDOW_MAGIC(window, );
       
  1757 
       
  1758     if (window->flags & SDL_WINDOW_SHOWN) {
       
  1759         return;
       
  1760     }
       
  1761 
       
  1762     if (_this->ShowWindow) {
       
  1763         _this->ShowWindow(_this, window);
       
  1764     }
       
  1765     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
       
  1766 }
       
  1767 
       
  1768 void
       
  1769 SDL_HideWindow(SDL_Window * window)
       
  1770 {
       
  1771     CHECK_WINDOW_MAGIC(window, );
       
  1772 
       
  1773     if (!(window->flags & SDL_WINDOW_SHOWN)) {
       
  1774         return;
       
  1775     }
       
  1776 
       
  1777     SDL_UpdateFullscreenMode(window, SDL_FALSE);
       
  1778 
       
  1779     if (_this->HideWindow) {
       
  1780         _this->HideWindow(_this, window);
       
  1781     }
       
  1782     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
       
  1783 }
       
  1784 
       
  1785 void
       
  1786 SDL_RaiseWindow(SDL_Window * window)
       
  1787 {
       
  1788     CHECK_WINDOW_MAGIC(window, );
       
  1789 
       
  1790     if (!(window->flags & SDL_WINDOW_SHOWN)) {
       
  1791         return;
       
  1792     }
       
  1793     if (_this->RaiseWindow) {
       
  1794         _this->RaiseWindow(_this, window);
       
  1795     }
       
  1796 }
       
  1797 
       
  1798 void
       
  1799 SDL_MaximizeWindow(SDL_Window * window)
       
  1800 {
       
  1801     CHECK_WINDOW_MAGIC(window, );
       
  1802 
       
  1803     if (window->flags & SDL_WINDOW_MAXIMIZED) {
       
  1804         return;
       
  1805     }
       
  1806 
       
  1807     /* !!! FIXME: should this check if the window is resizable? */
       
  1808 
       
  1809     if (_this->MaximizeWindow) {
       
  1810         _this->MaximizeWindow(_this, window);
       
  1811     }
       
  1812 }
       
  1813 
       
  1814 void
       
  1815 SDL_MinimizeWindow(SDL_Window * window)
       
  1816 {
       
  1817     CHECK_WINDOW_MAGIC(window, );
       
  1818 
       
  1819     if (window->flags & SDL_WINDOW_MINIMIZED) {
       
  1820         return;
       
  1821     }
       
  1822 
       
  1823     SDL_UpdateFullscreenMode(window, SDL_FALSE);
       
  1824 
       
  1825     if (_this->MinimizeWindow) {
       
  1826         _this->MinimizeWindow(_this, window);
       
  1827     }
       
  1828 }
       
  1829 
       
  1830 void
       
  1831 SDL_RestoreWindow(SDL_Window * window)
       
  1832 {
       
  1833     CHECK_WINDOW_MAGIC(window, );
       
  1834 
       
  1835     if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
       
  1836         return;
       
  1837     }
       
  1838 
       
  1839     if (_this->RestoreWindow) {
       
  1840         _this->RestoreWindow(_this, window);
       
  1841     }
       
  1842 }
       
  1843 
       
  1844 int
       
  1845 SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags)
       
  1846 {
       
  1847     CHECK_WINDOW_MAGIC(window, -1);
       
  1848 
       
  1849     flags &= FULLSCREEN_MASK;
       
  1850 
       
  1851     if ( flags == (window->flags & FULLSCREEN_MASK) ) {
       
  1852         return 0;
       
  1853     }
       
  1854 
       
  1855     /* clear the previous flags and OR in the new ones */
       
  1856     window->flags &= ~FULLSCREEN_MASK;
       
  1857     window->flags |= flags;
       
  1858 
       
  1859     SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
       
  1860 
       
  1861     return 0;
       
  1862 }
       
  1863 
       
  1864 static SDL_Surface *
       
  1865 SDL_CreateWindowFramebuffer(SDL_Window * window)
       
  1866 {
       
  1867     Uint32 format;
       
  1868     void *pixels;
       
  1869     int pitch;
       
  1870     int bpp;
       
  1871     Uint32 Rmask, Gmask, Bmask, Amask;
       
  1872 
       
  1873     if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
       
  1874         return NULL;
       
  1875     }
       
  1876 
       
  1877     if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
       
  1878         return NULL;
       
  1879     }
       
  1880 
       
  1881     if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
       
  1882         return NULL;
       
  1883     }
       
  1884 
       
  1885     return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
       
  1886 }
       
  1887 
       
  1888 SDL_Surface *
       
  1889 SDL_GetWindowSurface(SDL_Window * window)
       
  1890 {
       
  1891     CHECK_WINDOW_MAGIC(window, NULL);
       
  1892 
       
  1893     if (!window->surface_valid) {
       
  1894         if (window->surface) {
       
  1895             window->surface->flags &= ~SDL_DONTFREE;
       
  1896             SDL_FreeSurface(window->surface);
       
  1897         }
       
  1898         window->surface = SDL_CreateWindowFramebuffer(window);
       
  1899         if (window->surface) {
       
  1900             window->surface_valid = SDL_TRUE;
       
  1901             window->surface->flags |= SDL_DONTFREE;
       
  1902         }
       
  1903     }
       
  1904     return window->surface;
       
  1905 }
       
  1906 
       
  1907 int
       
  1908 SDL_UpdateWindowSurface(SDL_Window * window)
       
  1909 {
       
  1910     SDL_Rect full_rect;
       
  1911 
       
  1912     CHECK_WINDOW_MAGIC(window, -1);
       
  1913 
       
  1914     full_rect.x = 0;
       
  1915     full_rect.y = 0;
       
  1916     full_rect.w = window->w;
       
  1917     full_rect.h = window->h;
       
  1918     return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
       
  1919 }
       
  1920 
       
  1921 int
       
  1922 SDL_UpdateWindowSurfaceRects(SDL_Window * window, const SDL_Rect * rects,
       
  1923                              int numrects)
       
  1924 {
       
  1925     CHECK_WINDOW_MAGIC(window, -1);
       
  1926 
       
  1927     if (!window->surface_valid) {
       
  1928         return SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
       
  1929     }
       
  1930 
       
  1931     return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
       
  1932 }
       
  1933 
       
  1934 int
       
  1935 SDL_SetWindowBrightness(SDL_Window * window, float brightness)
       
  1936 {
       
  1937     Uint16 ramp[256];
       
  1938     int status;
       
  1939 
       
  1940     CHECK_WINDOW_MAGIC(window, -1);
       
  1941 
       
  1942     SDL_CalculateGammaRamp(brightness, ramp);
       
  1943     status = SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
       
  1944     if (status == 0) {
       
  1945         window->brightness = brightness;
       
  1946     }
       
  1947     return status;
       
  1948 }
       
  1949 
       
  1950 float
       
  1951 SDL_GetWindowBrightness(SDL_Window * window)
       
  1952 {
       
  1953     CHECK_WINDOW_MAGIC(window, 1.0f);
       
  1954 
       
  1955     return window->brightness;
       
  1956 }
       
  1957 
       
  1958 int
       
  1959 SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
       
  1960                                             const Uint16 * green,
       
  1961                                             const Uint16 * blue)
       
  1962 {
       
  1963     CHECK_WINDOW_MAGIC(window, -1);
       
  1964 
       
  1965     if (!_this->SetWindowGammaRamp) {
       
  1966         return SDL_Unsupported();
       
  1967     }
       
  1968 
       
  1969     if (!window->gamma) {
       
  1970         if (SDL_GetWindowGammaRamp(window, NULL, NULL, NULL) < 0) {
       
  1971             return -1;
       
  1972         }
       
  1973     }
       
  1974 
       
  1975     if (red) {
       
  1976         SDL_memcpy(&window->gamma[0*256], red, 256*sizeof(Uint16));
       
  1977     }
       
  1978     if (green) {
       
  1979         SDL_memcpy(&window->gamma[1*256], green, 256*sizeof(Uint16));
       
  1980     }
       
  1981     if (blue) {
       
  1982         SDL_memcpy(&window->gamma[2*256], blue, 256*sizeof(Uint16));
       
  1983     }
       
  1984     if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
       
  1985         return _this->SetWindowGammaRamp(_this, window, window->gamma);
       
  1986     } else {
       
  1987         return 0;
       
  1988     }
       
  1989 }
       
  1990 
       
  1991 int
       
  1992 SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
       
  1993                                             Uint16 * green,
       
  1994                                             Uint16 * blue)
       
  1995 {
       
  1996     CHECK_WINDOW_MAGIC(window, -1);
       
  1997 
       
  1998     if (!window->gamma) {
       
  1999         int i;
       
  2000 
       
  2001         window->gamma = (Uint16 *)SDL_malloc(256*6*sizeof(Uint16));
       
  2002         if (!window->gamma) {
       
  2003             return SDL_OutOfMemory();
       
  2004         }
       
  2005         window->saved_gamma = window->gamma + 3*256;
       
  2006 
       
  2007         if (_this->GetWindowGammaRamp) {
       
  2008             if (_this->GetWindowGammaRamp(_this, window, window->gamma) < 0) {
       
  2009                 return -1;
       
  2010             }
       
  2011         } else {
       
  2012             /* Create an identity gamma ramp */
       
  2013             for (i = 0; i < 256; ++i) {
       
  2014                 Uint16 value = (Uint16)((i << 8) | i);
       
  2015 
       
  2016                 window->gamma[0*256+i] = value;
       
  2017                 window->gamma[1*256+i] = value;
       
  2018                 window->gamma[2*256+i] = value;
       
  2019             }
       
  2020         }
       
  2021         SDL_memcpy(window->saved_gamma, window->gamma, 3*256*sizeof(Uint16));
       
  2022     }
       
  2023 
       
  2024     if (red) {
       
  2025         SDL_memcpy(red, &window->gamma[0*256], 256*sizeof(Uint16));
       
  2026     }
       
  2027     if (green) {
       
  2028         SDL_memcpy(green, &window->gamma[1*256], 256*sizeof(Uint16));
       
  2029     }
       
  2030     if (blue) {
       
  2031         SDL_memcpy(blue, &window->gamma[2*256], 256*sizeof(Uint16));
       
  2032     }
       
  2033     return 0;
       
  2034 }
       
  2035 
       
  2036 void
       
  2037 SDL_UpdateWindowGrab(SDL_Window * window)
       
  2038 {
       
  2039     if (_this->SetWindowGrab) {
       
  2040         SDL_bool grabbed;
       
  2041         if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
       
  2042              (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
       
  2043             grabbed = SDL_TRUE;
       
  2044         } else {
       
  2045             grabbed = SDL_FALSE;
       
  2046         }
       
  2047         _this->SetWindowGrab(_this, window, grabbed);
       
  2048     }
       
  2049 }
       
  2050 
       
  2051 void
       
  2052 SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
       
  2053 {
       
  2054     CHECK_WINDOW_MAGIC(window, );
       
  2055 
       
  2056     if (!!grabbed == !!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
       
  2057         return;
       
  2058     }
       
  2059     if (grabbed) {
       
  2060         window->flags |= SDL_WINDOW_INPUT_GRABBED;
       
  2061     } else {
       
  2062         window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
       
  2063     }
       
  2064     SDL_UpdateWindowGrab(window);
       
  2065 }
       
  2066 
       
  2067 SDL_bool
       
  2068 SDL_GetWindowGrab(SDL_Window * window)
       
  2069 {
       
  2070     CHECK_WINDOW_MAGIC(window, SDL_FALSE);
       
  2071 
       
  2072     return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
       
  2073 }
       
  2074 
       
  2075 void
       
  2076 SDL_OnWindowShown(SDL_Window * window)
       
  2077 {
       
  2078     SDL_OnWindowRestored(window);
       
  2079 }
       
  2080 
       
  2081 void
       
  2082 SDL_OnWindowHidden(SDL_Window * window)
       
  2083 {
       
  2084     SDL_UpdateFullscreenMode(window, SDL_FALSE);
       
  2085 }
       
  2086 
       
  2087 void
       
  2088 SDL_OnWindowResized(SDL_Window * window)
       
  2089 {
       
  2090     window->surface_valid = SDL_FALSE;
       
  2091     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
       
  2092 }
       
  2093 
       
  2094 void
       
  2095 SDL_OnWindowMinimized(SDL_Window * window)
       
  2096 {
       
  2097     SDL_UpdateFullscreenMode(window, SDL_FALSE);
       
  2098 }
       
  2099 
       
  2100 void
       
  2101 SDL_OnWindowRestored(SDL_Window * window)
       
  2102 {
       
  2103     SDL_RaiseWindow(window);
       
  2104 
       
  2105     if (FULLSCREEN_VISIBLE(window)) {
       
  2106         SDL_UpdateFullscreenMode(window, SDL_TRUE);
       
  2107     }
       
  2108 }
       
  2109 
       
  2110 void
       
  2111 SDL_OnWindowEnter(SDL_Window * window)
       
  2112 {
       
  2113     if (_this->OnWindowEnter) {
       
  2114         _this->OnWindowEnter(_this, window);
       
  2115     }
       
  2116 }
       
  2117 
       
  2118 void
       
  2119 SDL_OnWindowLeave(SDL_Window * window)
       
  2120 {
       
  2121 }
       
  2122 
       
  2123 void
       
  2124 SDL_OnWindowFocusGained(SDL_Window * window)
       
  2125 {
       
  2126     SDL_Mouse *mouse = SDL_GetMouse();
       
  2127 
       
  2128     if (window->gamma && _this->SetWindowGammaRamp) {
       
  2129         _this->SetWindowGammaRamp(_this, window, window->gamma);
       
  2130     }
       
  2131 
       
  2132     if (mouse && mouse->relative_mode) {
       
  2133         SDL_SetMouseFocus(window);
       
  2134         SDL_WarpMouseInWindow(window, window->w/2, window->h/2);
       
  2135     }
       
  2136 
       
  2137     SDL_UpdateWindowGrab(window);
       
  2138 }
       
  2139 
       
  2140 static SDL_bool
       
  2141 ShouldMinimizeOnFocusLoss(SDL_Window * window)
       
  2142 {
       
  2143     const char *hint;
       
  2144 
       
  2145     if (!(window->flags & SDL_WINDOW_FULLSCREEN) || window->is_destroying) {
       
  2146         return SDL_FALSE;
       
  2147     }
       
  2148 
       
  2149 #ifdef __MACOSX__
       
  2150     if (Cocoa_IsWindowInFullscreenSpace(window)) {
       
  2151         return SDL_FALSE;
       
  2152     }
       
  2153 #endif
       
  2154 
       
  2155     hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS);
       
  2156     if (hint) {
       
  2157         if (*hint == '0') {
       
  2158             return SDL_FALSE;
       
  2159         } else {
       
  2160             return SDL_TRUE;
       
  2161         }
       
  2162     }
       
  2163 
       
  2164     return SDL_TRUE;
       
  2165 }
       
  2166 
       
  2167 void
       
  2168 SDL_OnWindowFocusLost(SDL_Window * window)
       
  2169 {
       
  2170     if (window->gamma && _this->SetWindowGammaRamp) {
       
  2171         _this->SetWindowGammaRamp(_this, window, window->saved_gamma);
       
  2172     }
       
  2173 
       
  2174     SDL_UpdateWindowGrab(window);
       
  2175 
       
  2176     if (ShouldMinimizeOnFocusLoss(window)) {
       
  2177         SDL_MinimizeWindow(window);
       
  2178     }
       
  2179 }
       
  2180 
       
  2181 SDL_Window *
       
  2182 SDL_GetFocusWindow(void)
       
  2183 {
       
  2184     SDL_Window *window;
       
  2185 
       
  2186     if (!_this) {
       
  2187         return NULL;
       
  2188     }
       
  2189     for (window = _this->windows; window; window = window->next) {
       
  2190         if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
       
  2191             return window;
       
  2192         }
       
  2193     }
       
  2194     return NULL;
       
  2195 }
       
  2196 
       
  2197 void
       
  2198 SDL_DestroyWindow(SDL_Window * window)
       
  2199 {
       
  2200     SDL_VideoDisplay *display;
       
  2201 
       
  2202     CHECK_WINDOW_MAGIC(window, );
       
  2203 
       
  2204     window->is_destroying = SDL_TRUE;
       
  2205 
       
  2206     /* Restore video mode, etc. */
       
  2207     SDL_HideWindow(window);
       
  2208 
       
  2209     /* Make sure this window no longer has focus */
       
  2210     if (SDL_GetKeyboardFocus() == window) {
       
  2211         SDL_SetKeyboardFocus(NULL);
       
  2212     }
       
  2213     if (SDL_GetMouseFocus() == window) {
       
  2214         SDL_SetMouseFocus(NULL);
       
  2215     }
       
  2216 
       
  2217     /* make no context current if this is the current context window. */
       
  2218     if (window->flags & SDL_WINDOW_OPENGL) {
       
  2219         if (_this->current_glwin == window) {
       
  2220             SDL_GL_MakeCurrent(window, NULL);
       
  2221         }
       
  2222     }
       
  2223 
       
  2224     if (window->surface) {
       
  2225         window->surface->flags &= ~SDL_DONTFREE;
       
  2226         SDL_FreeSurface(window->surface);
       
  2227     }
       
  2228     if (_this->DestroyWindowFramebuffer) {
       
  2229         _this->DestroyWindowFramebuffer(_this, window);
       
  2230     }
       
  2231     if (_this->DestroyWindow) {
       
  2232         _this->DestroyWindow(_this, window);
       
  2233     }
       
  2234     if (window->flags & SDL_WINDOW_OPENGL) {
       
  2235         SDL_GL_UnloadLibrary();
       
  2236     }
       
  2237 
       
  2238     display = SDL_GetDisplayForWindow(window);
       
  2239     if (display->fullscreen_window == window) {
       
  2240         display->fullscreen_window = NULL;
       
  2241     }
       
  2242 
       
  2243     /* Now invalidate magic */
       
  2244     window->magic = NULL;
       
  2245 
       
  2246     /* Free memory associated with the window */
       
  2247     SDL_free(window->title);
       
  2248     SDL_FreeSurface(window->icon);
       
  2249     SDL_free(window->gamma);
       
  2250     while (window->data) {
       
  2251         SDL_WindowUserData *data = window->data;
       
  2252 
       
  2253         window->data = data->next;
       
  2254         SDL_free(data->name);
       
  2255         SDL_free(data);
       
  2256     }
       
  2257 
       
  2258     /* Unlink the window from the list */
       
  2259     if (window->next) {
       
  2260         window->next->prev = window->prev;
       
  2261     }
       
  2262     if (window->prev) {
       
  2263         window->prev->next = window->next;
       
  2264     } else {
       
  2265         _this->windows = window->next;
       
  2266     }
       
  2267 
       
  2268     SDL_free(window);
       
  2269 }
       
  2270 
       
  2271 SDL_bool
       
  2272 SDL_IsScreenSaverEnabled()
       
  2273 {
       
  2274     if (!_this) {
       
  2275         return SDL_TRUE;
       
  2276     }
       
  2277     return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE;
       
  2278 }
       
  2279 
       
  2280 void
       
  2281 SDL_EnableScreenSaver()
       
  2282 {
       
  2283     if (!_this) {
       
  2284         return;
       
  2285     }
       
  2286     if (!_this->suspend_screensaver) {
       
  2287         return;
       
  2288     }
       
  2289     _this->suspend_screensaver = SDL_FALSE;
       
  2290     if (_this->SuspendScreenSaver) {
       
  2291         _this->SuspendScreenSaver(_this);
       
  2292     }
       
  2293 }
       
  2294 
       
  2295 void
       
  2296 SDL_DisableScreenSaver()
       
  2297 {
       
  2298     if (!_this) {
       
  2299         return;
       
  2300     }
       
  2301     if (_this->suspend_screensaver) {
       
  2302         return;
       
  2303     }
       
  2304     _this->suspend_screensaver = SDL_TRUE;
       
  2305     if (_this->SuspendScreenSaver) {
       
  2306         _this->SuspendScreenSaver(_this);
       
  2307     }
       
  2308 }
       
  2309 
       
  2310 void
       
  2311 SDL_VideoQuit(void)
       
  2312 {
       
  2313     int i, j;
       
  2314 
       
  2315     if (!_this) {
       
  2316         return;
       
  2317     }
       
  2318 
       
  2319     /* Halt event processing before doing anything else */
       
  2320     SDL_TouchQuit();
       
  2321     SDL_MouseQuit();
       
  2322     SDL_KeyboardQuit();
       
  2323     SDL_QuitSubSystem(SDL_INIT_EVENTS);
       
  2324 
       
  2325     SDL_EnableScreenSaver();
       
  2326 
       
  2327     /* Clean up the system video */
       
  2328     while (_this->windows) {
       
  2329         SDL_DestroyWindow(_this->windows);
       
  2330     }
       
  2331     _this->VideoQuit(_this);
       
  2332 
       
  2333     for (i = 0; i < _this->num_displays; ++i) {
       
  2334         SDL_VideoDisplay *display = &_this->displays[i];
       
  2335         for (j = display->num_display_modes; j--;) {
       
  2336             SDL_free(display->display_modes[j].driverdata);
       
  2337             display->display_modes[j].driverdata = NULL;
       
  2338         }
       
  2339         SDL_free(display->display_modes);
       
  2340         display->display_modes = NULL;
       
  2341         SDL_free(display->desktop_mode.driverdata);
       
  2342         display->desktop_mode.driverdata = NULL;
       
  2343         SDL_free(display->driverdata);
       
  2344         display->driverdata = NULL;
       
  2345     }
       
  2346     if (_this->displays) {
       
  2347         for (i = 0; i < _this->num_displays; ++i) {
       
  2348             SDL_free(_this->displays[i].name);
       
  2349         }
       
  2350         SDL_free(_this->displays);
       
  2351         _this->displays = NULL;
       
  2352         _this->num_displays = 0;
       
  2353     }
       
  2354     SDL_free(_this->clipboard_text);
       
  2355     _this->clipboard_text = NULL;
       
  2356     _this->free(_this);
       
  2357     _this = NULL;
       
  2358 }
       
  2359 
       
  2360 int
       
  2361 SDL_GL_LoadLibrary(const char *path)
       
  2362 {
       
  2363     int retval;
       
  2364 
       
  2365     if (!_this) {
       
  2366         return SDL_UninitializedVideo();
       
  2367     }
       
  2368     if (_this->gl_config.driver_loaded) {
       
  2369         if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) {
       
  2370             return SDL_SetError("OpenGL library already loaded");
       
  2371         }
       
  2372         retval = 0;
       
  2373     } else {
       
  2374         if (!_this->GL_LoadLibrary) {
       
  2375             return SDL_SetError("No dynamic GL support in video driver");
       
  2376         }
       
  2377         retval = _this->GL_LoadLibrary(_this, path);
       
  2378     }
       
  2379     if (retval == 0) {
       
  2380         ++_this->gl_config.driver_loaded;
       
  2381     } else {
       
  2382         if (_this->GL_UnloadLibrary) {
       
  2383             _this->GL_UnloadLibrary(_this);
       
  2384         }
       
  2385     }
       
  2386     return (retval);
       
  2387 }
       
  2388 
       
  2389 void *
       
  2390 SDL_GL_GetProcAddress(const char *proc)
       
  2391 {
       
  2392     void *func;
       
  2393 
       
  2394     if (!_this) {
       
  2395         SDL_UninitializedVideo();
       
  2396         return NULL;
       
  2397     }
       
  2398     func = NULL;
       
  2399     if (_this->GL_GetProcAddress) {
       
  2400         if (_this->gl_config.driver_loaded) {
       
  2401             func = _this->GL_GetProcAddress(_this, proc);
       
  2402         } else {
       
  2403             SDL_SetError("No GL driver has been loaded");
       
  2404         }
       
  2405     } else {
       
  2406         SDL_SetError("No dynamic GL support in video driver");
       
  2407     }
       
  2408     return func;
       
  2409 }
       
  2410 
       
  2411 void
       
  2412 SDL_GL_UnloadLibrary(void)
       
  2413 {
       
  2414     if (!_this) {
       
  2415         SDL_UninitializedVideo();
       
  2416         return;
       
  2417     }
       
  2418     if (_this->gl_config.driver_loaded > 0) {
       
  2419         if (--_this->gl_config.driver_loaded > 0) {
       
  2420             return;
       
  2421         }
       
  2422         if (_this->GL_UnloadLibrary) {
       
  2423             _this->GL_UnloadLibrary(_this);
       
  2424         }
       
  2425     }
       
  2426 }
       
  2427 
       
  2428 static SDL_INLINE SDL_bool
       
  2429 isAtLeastGL3(const char *verstr)
       
  2430 {
       
  2431     return ( verstr && (SDL_atoi(verstr) >= 3) );
       
  2432 }
       
  2433 
       
  2434 SDL_bool
       
  2435 SDL_GL_ExtensionSupported(const char *extension)
       
  2436 {
       
  2437 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
       
  2438     const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
       
  2439     const char *extensions;
       
  2440     const char *start;
       
  2441     const char *where, *terminator;
       
  2442 
       
  2443     /* Extension names should not have spaces. */
       
  2444     where = SDL_strchr(extension, ' ');
       
  2445     if (where || *extension == '\0') {
       
  2446         return SDL_FALSE;
       
  2447     }
       
  2448     /* See if there's an environment variable override */
       
  2449     start = SDL_getenv(extension);
       
  2450     if (start && *start == '0') {
       
  2451         return SDL_FALSE;
       
  2452     }
       
  2453 
       
  2454     /* Lookup the available extensions */
       
  2455 
       
  2456     glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
       
  2457     if (!glGetStringFunc) {
       
  2458         return SDL_FALSE;
       
  2459     }
       
  2460 
       
  2461     if (isAtLeastGL3((const char *) glGetStringFunc(GL_VERSION))) {
       
  2462         const GLubyte *(APIENTRY * glGetStringiFunc) (GLenum, GLuint);
       
  2463         void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
       
  2464         GLint num_exts = 0;
       
  2465         GLint i;
       
  2466 
       
  2467         glGetStringiFunc = SDL_GL_GetProcAddress("glGetStringi");
       
  2468         glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
       
  2469         if ((!glGetStringiFunc) || (!glGetIntegervFunc)) {
       
  2470             return SDL_FALSE;
       
  2471         }
       
  2472 
       
  2473         #ifndef GL_NUM_EXTENSIONS
       
  2474         #define GL_NUM_EXTENSIONS 0x821D
       
  2475         #endif
       
  2476         glGetIntegervFunc(GL_NUM_EXTENSIONS, &num_exts);
       
  2477         for (i = 0; i < num_exts; i++) {
       
  2478             const char *thisext = (const char *) glGetStringiFunc(GL_EXTENSIONS, i);
       
  2479             if (SDL_strcmp(thisext, extension) == 0) {
       
  2480                 return SDL_TRUE;
       
  2481             }
       
  2482         }
       
  2483 
       
  2484         return SDL_FALSE;
       
  2485     }
       
  2486 
       
  2487     /* Try the old way with glGetString(GL_EXTENSIONS) ... */
       
  2488 
       
  2489     extensions = (const char *) glGetStringFunc(GL_EXTENSIONS);
       
  2490     if (!extensions) {
       
  2491         return SDL_FALSE;
       
  2492     }
       
  2493     /*
       
  2494      * It takes a bit of care to be fool-proof about parsing the OpenGL
       
  2495      * extensions string. Don't be fooled by sub-strings, etc.
       
  2496      */
       
  2497 
       
  2498     start = extensions;
       
  2499 
       
  2500     for (;;) {
       
  2501         where = SDL_strstr(start, extension);
       
  2502         if (!where)
       
  2503             break;
       
  2504 
       
  2505         terminator = where + SDL_strlen(extension);
       
  2506         if (where == start || *(where - 1) == ' ')
       
  2507             if (*terminator == ' ' || *terminator == '\0')
       
  2508                 return SDL_TRUE;
       
  2509 
       
  2510         start = terminator;
       
  2511     }
       
  2512     return SDL_FALSE;
       
  2513 #else
       
  2514     return SDL_FALSE;
       
  2515 #endif
       
  2516 }
       
  2517 
       
  2518 void
       
  2519 SDL_GL_ResetAttributes()
       
  2520 {
       
  2521     if (!_this) {
       
  2522         return;
       
  2523     }
       
  2524 
   480     _this->gl_config.red_size = 3;
  2525     _this->gl_config.red_size = 3;
   481     _this->gl_config.green_size = 3;
  2526     _this->gl_config.green_size = 3;
   482     _this->gl_config.blue_size = 2;
  2527     _this->gl_config.blue_size = 2;
   483     _this->gl_config.alpha_size = 0;
  2528     _this->gl_config.alpha_size = 0;
   484     _this->gl_config.buffer_size = 0;
  2529     _this->gl_config.buffer_size = 0;
   499     _this->gl_config.major_version = 2;
  2544     _this->gl_config.major_version = 2;
   500     _this->gl_config.minor_version = 1;
  2545     _this->gl_config.minor_version = 1;
   501 #elif SDL_VIDEO_OPENGL_ES2
  2546 #elif SDL_VIDEO_OPENGL_ES2
   502     _this->gl_config.major_version = 2;
  2547     _this->gl_config.major_version = 2;
   503     _this->gl_config.minor_version = 0;
  2548     _this->gl_config.minor_version = 0;
   504     _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;   
  2549     _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
   505 #elif SDL_VIDEO_OPENGL_ES
  2550 #elif SDL_VIDEO_OPENGL_ES
   506     _this->gl_config.major_version = 1;
  2551     _this->gl_config.major_version = 1;
   507     _this->gl_config.minor_version = 1;
  2552     _this->gl_config.minor_version = 1;
   508     _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
  2553     _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
   509 #endif
  2554 #endif
   510     _this->gl_config.flags = 0;
  2555     _this->gl_config.flags = 0;
   511     
  2556     _this->gl_config.framebuffer_srgb_capable = 0;
       
  2557 
   512     _this->gl_config.share_with_current_context = 0;
  2558     _this->gl_config.share_with_current_context = 0;
   513 
       
   514     _this->current_glwin_tls = SDL_TLSCreate();
       
   515     _this->current_glctx_tls = SDL_TLSCreate();
       
   516 
       
   517     /* Initialize the video subsystem */
       
   518     if (_this->VideoInit(_this) < 0) {
       
   519         SDL_VideoQuit();
       
   520         return -1;
       
   521     }
       
   522 
       
   523     /* Make sure some displays were added */
       
   524     if (_this->num_displays == 0) {
       
   525         SDL_VideoQuit();
       
   526         return SDL_SetError("The video driver did not add any displays");
       
   527     }
       
   528 
       
   529     /* Add the renderer framebuffer emulation if desired */
       
   530     if (ShouldUseTextureFramebuffer()) {
       
   531         _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
       
   532         _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
       
   533         _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
       
   534     }
       
   535 
       
   536     /* If we don't use a screen keyboard, turn on text input by default,
       
   537        otherwise programs that expect to get text events without enabling
       
   538        UNICODE input won't get any events.
       
   539 
       
   540        Actually, come to think of it, you needed to call SDL_EnableUNICODE(1)
       
   541        in SDL 1.2 before you got text input events.  Hmm...
       
   542      */
       
   543     if (!SDL_HasScreenKeyboardSupport()) {
       
   544         SDL_StartTextInput();
       
   545     }
       
   546 
       
   547     /* We're ready to go! */
       
   548     return 0;
       
   549 }
       
   550 
       
   551 const char *
       
   552 SDL_GetCurrentVideoDriver()
       
   553 {
       
   554     if (!_this) {
       
   555         SDL_UninitializedVideo();
       
   556         return NULL;
       
   557     }
       
   558     return _this->name;
       
   559 }
       
   560 
       
   561 SDL_VideoDevice *
       
   562 SDL_GetVideoDevice(void)
       
   563 {
       
   564     return _this;
       
   565 }
       
   566 
       
   567 int
       
   568 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
       
   569 {
       
   570     SDL_VideoDisplay display;
       
   571 
       
   572     SDL_zero(display);
       
   573     if (desktop_mode) {
       
   574         display.desktop_mode = *desktop_mode;
       
   575     }
       
   576     display.current_mode = display.desktop_mode;
       
   577 
       
   578     return SDL_AddVideoDisplay(&display);
       
   579 }
       
   580 
       
   581 int
       
   582 SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
       
   583 {
       
   584     SDL_VideoDisplay *displays;
       
   585     int index = -1;
       
   586 
       
   587     displays =
       
   588         SDL_realloc(_this->displays,
       
   589                     (_this->num_displays + 1) * sizeof(*displays));
       
   590     if (displays) {
       
   591         index = _this->num_displays++;
       
   592         displays[index] = *display;
       
   593         displays[index].device = _this;
       
   594         _this->displays = displays;
       
   595 
       
   596         if (display->name) {
       
   597             displays[index].name = SDL_strdup(display->name);
       
   598         } else {
       
   599             char name[32];
       
   600 
       
   601             SDL_itoa(index, name, 10);
       
   602             displays[index].name = SDL_strdup(name);
       
   603         }
       
   604     } else {
       
   605         SDL_OutOfMemory();
       
   606     }
       
   607     return index;
       
   608 }
       
   609 
       
   610 int
       
   611 SDL_GetNumVideoDisplays(void)
       
   612 {
       
   613     if (!_this) {
       
   614         SDL_UninitializedVideo();
       
   615         return 0;
       
   616     }
       
   617     return _this->num_displays;
       
   618 }
       
   619 
       
   620 static int
       
   621 SDL_GetIndexOfDisplay(SDL_VideoDisplay *display)
       
   622 {
       
   623     int displayIndex;
       
   624 
       
   625     for (displayIndex = 0; displayIndex < _this->num_displays; ++displayIndex) {
       
   626         if (display == &_this->displays[displayIndex]) {
       
   627             return displayIndex;
       
   628         }
       
   629     }
       
   630 
       
   631     /* Couldn't find the display, just use index 0 */
       
   632     return 0;
       
   633 }
       
   634 
       
   635 void *
       
   636 SDL_GetDisplayDriverData( int displayIndex )
       
   637 {
       
   638     CHECK_DISPLAY_INDEX( displayIndex, NULL );
       
   639 
       
   640     return _this->displays[displayIndex].driverdata;
       
   641 }
       
   642 
       
   643 const char *
       
   644 SDL_GetDisplayName(int displayIndex)
       
   645 {
       
   646     CHECK_DISPLAY_INDEX(displayIndex, NULL);
       
   647 
       
   648     return _this->displays[displayIndex].name;
       
   649 }
       
   650 
       
   651 int
       
   652 SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
       
   653 {
       
   654     CHECK_DISPLAY_INDEX(displayIndex, -1);
       
   655 
       
   656     if (rect) {
       
   657         SDL_VideoDisplay *display = &_this->displays[displayIndex];
       
   658 
       
   659         if (_this->GetDisplayBounds) {
       
   660             if (_this->GetDisplayBounds(_this, display, rect) == 0) {
       
   661                 return 0;
       
   662             }
       
   663         }
       
   664 
       
   665         /* Assume that the displays are left to right */
       
   666         if (displayIndex == 0) {
       
   667             rect->x = 0;
       
   668             rect->y = 0;
       
   669         } else {
       
   670             SDL_GetDisplayBounds(displayIndex-1, rect);
       
   671             rect->x += rect->w;
       
   672         }
       
   673         rect->w = display->current_mode.w;
       
   674         rect->h = display->current_mode.h;
       
   675     }
       
   676     return 0;
       
   677 }
       
   678 
       
   679 SDL_bool
       
   680 SDL_AddDisplayMode(SDL_VideoDisplay * display,  const SDL_DisplayMode * mode)
       
   681 {
       
   682     SDL_DisplayMode *modes;
       
   683     int i, nmodes;
       
   684 
       
   685     /* Make sure we don't already have the mode in the list */
       
   686     modes = display->display_modes;
       
   687     nmodes = display->num_display_modes;
       
   688     for (i = 0; i < nmodes; ++i) {
       
   689         if (cmpmodes(mode, &modes[i]) == 0) {
       
   690             return SDL_FALSE;
       
   691         }
       
   692     }
       
   693 
       
   694     /* Go ahead and add the new mode */
       
   695     if (nmodes == display->max_display_modes) {
       
   696         modes =
       
   697             SDL_realloc(modes,
       
   698                         (display->max_display_modes + 32) * sizeof(*modes));
       
   699         if (!modes) {
       
   700             return SDL_FALSE;
       
   701         }
       
   702         display->display_modes = modes;
       
   703         display->max_display_modes += 32;
       
   704     }
       
   705     modes[nmodes] = *mode;
       
   706     display->num_display_modes++;
       
   707 
       
   708     /* Re-sort video modes */
       
   709     SDL_qsort(display->display_modes, display->num_display_modes,
       
   710               sizeof(SDL_DisplayMode), cmpmodes);
       
   711 
       
   712     return SDL_TRUE;
       
   713 }
       
   714 
       
   715 static int
       
   716 SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)
       
   717 {
       
   718     if (!display->num_display_modes && _this->GetDisplayModes) {
       
   719         _this->GetDisplayModes(_this, display);
       
   720         SDL_qsort(display->display_modes, display->num_display_modes,
       
   721                   sizeof(SDL_DisplayMode), cmpmodes);
       
   722     }
       
   723     return display->num_display_modes;
       
   724 }
       
   725 
       
   726 int
       
   727 SDL_GetNumDisplayModes(int displayIndex)
       
   728 {
       
   729     CHECK_DISPLAY_INDEX(displayIndex, -1);
       
   730 
       
   731     return SDL_GetNumDisplayModesForDisplay(&_this->displays[displayIndex]);
       
   732 }
       
   733 
       
   734 int
       
   735 SDL_GetDisplayMode(int displayIndex, int index, SDL_DisplayMode * mode)
       
   736 {
       
   737     SDL_VideoDisplay *display;
       
   738 
       
   739     CHECK_DISPLAY_INDEX(displayIndex, -1);
       
   740 
       
   741     display = &_this->displays[displayIndex];
       
   742     if (index < 0 || index >= SDL_GetNumDisplayModesForDisplay(display)) {
       
   743         return SDL_SetError("index must be in the range of 0 - %d",
       
   744                             SDL_GetNumDisplayModesForDisplay(display) - 1);
       
   745     }
       
   746     if (mode) {
       
   747         *mode = display->display_modes[index];
       
   748     }
       
   749     return 0;
       
   750 }
       
   751 
       
   752 int
       
   753 SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode)
       
   754 {
       
   755     SDL_VideoDisplay *display;
       
   756 
       
   757     CHECK_DISPLAY_INDEX(displayIndex, -1);
       
   758 
       
   759     display = &_this->displays[displayIndex];
       
   760     if (mode) {
       
   761         *mode = display->desktop_mode;
       
   762     }
       
   763     return 0;
       
   764 }
       
   765 
       
   766 int
       
   767 SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode)
       
   768 {
       
   769     SDL_VideoDisplay *display;
       
   770 
       
   771     CHECK_DISPLAY_INDEX(displayIndex, -1);
       
   772 
       
   773     display = &_this->displays[displayIndex];
       
   774     if (mode) {
       
   775         *mode = display->current_mode;
       
   776     }
       
   777     return 0;
       
   778 }
       
   779 
       
   780 static SDL_DisplayMode *
       
   781 SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,
       
   782                                     const SDL_DisplayMode * mode,
       
   783                                     SDL_DisplayMode * closest)
       
   784 {
       
   785     Uint32 target_format;
       
   786     int target_refresh_rate;
       
   787     int i;
       
   788     SDL_DisplayMode *current, *match;
       
   789 
       
   790     if (!mode || !closest) {
       
   791         SDL_SetError("Missing desired mode or closest mode parameter");
       
   792         return NULL;
       
   793     }
       
   794 
       
   795     /* Default to the desktop format */
       
   796     if (mode->format) {
       
   797         target_format = mode->format;
       
   798     } else {
       
   799         target_format = display->desktop_mode.format;
       
   800     }
       
   801 
       
   802     /* Default to the desktop refresh rate */
       
   803     if (mode->refresh_rate) {
       
   804         target_refresh_rate = mode->refresh_rate;
       
   805     } else {
       
   806         target_refresh_rate = display->desktop_mode.refresh_rate;
       
   807     }
       
   808 
       
   809     match = NULL;
       
   810     for (i = 0; i < SDL_GetNumDisplayModesForDisplay(display); ++i) {
       
   811         current = &display->display_modes[i];
       
   812 
       
   813         if (current->w && (current->w < mode->w)) {
       
   814             /* Out of sorted modes large enough here */
       
   815             break;
       
   816         }
       
   817         if (current->h && (current->h < mode->h)) {
       
   818             if (current->w && (current->w == mode->w)) {
       
   819                 /* Out of sorted modes large enough here */
       
   820                 break;
       
   821             }
       
   822             /* Wider, but not tall enough, due to a different
       
   823                aspect ratio. This mode must be skipped, but closer
       
   824                modes may still follow. */
       
   825             continue;
       
   826         }
       
   827         if (!match || current->w < match->w || current->h < match->h) {
       
   828             match = current;
       
   829             continue;
       
   830         }
       
   831         if (current->format != match->format) {
       
   832             /* Sorted highest depth to lowest */
       
   833             if (current->format == target_format ||
       
   834                 (SDL_BITSPERPIXEL(current->format) >=
       
   835                  SDL_BITSPERPIXEL(target_format)
       
   836                  && SDL_PIXELTYPE(current->format) ==
       
   837                  SDL_PIXELTYPE(target_format))) {
       
   838                 match = current;
       
   839             }
       
   840             continue;
       
   841         }
       
   842         if (current->refresh_rate != match->refresh_rate) {
       
   843             /* Sorted highest refresh to lowest */
       
   844             if (current->refresh_rate >= target_refresh_rate) {
       
   845                 match = current;
       
   846             }
       
   847         }
       
   848     }
       
   849     if (match) {
       
   850         if (match->format) {
       
   851             closest->format = match->format;
       
   852         } else {
       
   853             closest->format = mode->format;
       
   854         }
       
   855         if (match->w && match->h) {
       
   856             closest->w = match->w;
       
   857             closest->h = match->h;
       
   858         } else {
       
   859             closest->w = mode->w;
       
   860             closest->h = mode->h;
       
   861         }
       
   862         if (match->refresh_rate) {
       
   863             closest->refresh_rate = match->refresh_rate;
       
   864         } else {
       
   865             closest->refresh_rate = mode->refresh_rate;
       
   866         }
       
   867         closest->driverdata = match->driverdata;
       
   868 
       
   869         /*
       
   870          * Pick some reasonable defaults if the app and driver don't
       
   871          * care
       
   872          */
       
   873         if (!closest->format) {
       
   874             closest->format = SDL_PIXELFORMAT_RGB888;
       
   875         }
       
   876         if (!closest->w) {
       
   877             closest->w = 640;
       
   878         }
       
   879         if (!closest->h) {
       
   880             closest->h = 480;
       
   881         }
       
   882         return closest;
       
   883     }
       
   884     return NULL;
       
   885 }
       
   886 
       
   887 SDL_DisplayMode *
       
   888 SDL_GetClosestDisplayMode(int displayIndex,
       
   889                           const SDL_DisplayMode * mode,
       
   890                           SDL_DisplayMode * closest)
       
   891 {
       
   892     SDL_VideoDisplay *display;
       
   893 
       
   894     CHECK_DISPLAY_INDEX(displayIndex, NULL);
       
   895 
       
   896     display = &_this->displays[displayIndex];
       
   897     return SDL_GetClosestDisplayModeForDisplay(display, mode, closest);
       
   898 }
       
   899 
       
   900 static int
       
   901 SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
       
   902 {
       
   903     SDL_DisplayMode display_mode;
       
   904     SDL_DisplayMode current_mode;
       
   905 
       
   906     if (mode) {
       
   907         display_mode = *mode;
       
   908 
       
   909         /* Default to the current mode */
       
   910         if (!display_mode.format) {
       
   911             display_mode.format = display->current_mode.format;
       
   912         }
       
   913         if (!display_mode.w) {
       
   914             display_mode.w = display->current_mode.w;
       
   915         }
       
   916         if (!display_mode.h) {
       
   917             display_mode.h = display->current_mode.h;
       
   918         }
       
   919         if (!display_mode.refresh_rate) {
       
   920             display_mode.refresh_rate = display->current_mode.refresh_rate;
       
   921         }
       
   922 
       
   923         /* Get a good video mode, the closest one possible */
       
   924         if (!SDL_GetClosestDisplayModeForDisplay(display, &display_mode, &display_mode)) {
       
   925             return SDL_SetError("No video mode large enough for %dx%d",
       
   926                                 display_mode.w, display_mode.h);
       
   927         }
       
   928     } else {
       
   929         display_mode = display->desktop_mode;
       
   930     }
       
   931 
       
   932     /* See if there's anything left to do */
       
   933     current_mode = display->current_mode;
       
   934     if (SDL_memcmp(&display_mode, &current_mode, sizeof(display_mode)) == 0) {
       
   935         return 0;
       
   936     }
       
   937 
       
   938     /* Actually change the display mode */
       
   939     if (!_this->SetDisplayMode) {
       
   940         return SDL_SetError("Video driver doesn't support changing display mode");
       
   941     }
       
   942     if (_this->SetDisplayMode(_this, display, &display_mode) < 0) {
       
   943         return -1;
       
   944     }
       
   945     display->current_mode = display_mode;
       
   946     return 0;
       
   947 }
       
   948 
       
   949 int
       
   950 SDL_GetWindowDisplayIndex(SDL_Window * window)
       
   951 {
       
   952     int displayIndex;
       
   953     int i, dist;
       
   954     int closest = -1;
       
   955     int closest_dist = 0x7FFFFFFF;
       
   956     SDL_Point center;
       
   957     SDL_Point delta;
       
   958     SDL_Rect rect;
       
   959 
       
   960     CHECK_WINDOW_MAGIC(window, -1);
       
   961 
       
   962     if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
       
   963         SDL_WINDOWPOS_ISCENTERED(window->x)) {
       
   964         displayIndex = (window->x & 0xFFFF);
       
   965         if (displayIndex >= _this->num_displays) {
       
   966             displayIndex = 0;
       
   967         }
       
   968         return displayIndex;
       
   969     }
       
   970     if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
       
   971         SDL_WINDOWPOS_ISCENTERED(window->y)) {
       
   972         displayIndex = (window->y & 0xFFFF);
       
   973         if (displayIndex >= _this->num_displays) {
       
   974             displayIndex = 0;
       
   975         }
       
   976         return displayIndex;
       
   977     }
       
   978 
       
   979     /* Find the display containing the window */
       
   980     for (i = 0; i < _this->num_displays; ++i) {
       
   981         SDL_VideoDisplay *display = &_this->displays[i];
       
   982 
       
   983         if (display->fullscreen_window == window) {
       
   984             return i;
       
   985         }
       
   986     }
       
   987     center.x = window->x + window->w / 2;
       
   988     center.y = window->y + window->h / 2;
       
   989     for (i = 0; i < _this->num_displays; ++i) {
       
   990         SDL_GetDisplayBounds(i, &rect);
       
   991         if (SDL_EnclosePoints(&center, 1, &rect, NULL)) {
       
   992             return i;
       
   993         }
       
   994 
       
   995         delta.x = center.x - (rect.x + rect.w / 2);
       
   996         delta.y = center.y - (rect.y + rect.h / 2);
       
   997         dist = (delta.x*delta.x + delta.y*delta.y);
       
   998         if (dist < closest_dist) {
       
   999             closest = i;
       
  1000             closest_dist = dist;
       
  1001         }
       
  1002     }
       
  1003     if (closest < 0) {
       
  1004         SDL_SetError("Couldn't find any displays");
       
  1005     }
       
  1006     return closest;
       
  1007 }
       
  1008 
       
  1009 SDL_VideoDisplay *
       
  1010 SDL_GetDisplayForWindow(SDL_Window *window)
       
  1011 {
       
  1012     int displayIndex = SDL_GetWindowDisplayIndex(window);
       
  1013     if (displayIndex >= 0) {
       
  1014         return &_this->displays[displayIndex];
       
  1015     } else {
       
  1016         return NULL;
       
  1017     }
       
  1018 }
       
  1019 
       
  1020 int
       
  1021 SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
       
  1022 {
       
  1023     CHECK_WINDOW_MAGIC(window, -1);
       
  1024 
       
  1025     if (mode) {
       
  1026         window->fullscreen_mode = *mode;
       
  1027     } else {
       
  1028         SDL_zero(window->fullscreen_mode);
       
  1029     }
       
  1030     return 0;
       
  1031 }
       
  1032 
       
  1033 int
       
  1034 SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
       
  1035 {
       
  1036     SDL_DisplayMode fullscreen_mode;
       
  1037     SDL_VideoDisplay *display;
       
  1038 
       
  1039     if (!mode) {
       
  1040       return SDL_InvalidParamError("mode");
       
  1041     }
       
  1042 
       
  1043     CHECK_WINDOW_MAGIC(window, -1);
       
  1044 
       
  1045     fullscreen_mode = window->fullscreen_mode;
       
  1046     if (!fullscreen_mode.w) {
       
  1047         fullscreen_mode.w = window->w;
       
  1048     }
       
  1049     if (!fullscreen_mode.h) {
       
  1050         fullscreen_mode.h = window->h;
       
  1051     }
       
  1052 
       
  1053     display = SDL_GetDisplayForWindow(window);
       
  1054 
       
  1055     /* if in desktop size mode, just return the size of the desktop */
       
  1056     if ( ( window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP )
       
  1057     {
       
  1058         fullscreen_mode = display->desktop_mode;
       
  1059     }
       
  1060     else if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
       
  1061                                              &fullscreen_mode,
       
  1062                                              &fullscreen_mode)) {
       
  1063         return SDL_SetError("Couldn't find display mode match");
       
  1064     }
       
  1065 
       
  1066     if (mode) {
       
  1067         *mode = fullscreen_mode;
       
  1068     }
       
  1069     return 0;
       
  1070 }
       
  1071 
       
  1072 Uint32
       
  1073 SDL_GetWindowPixelFormat(SDL_Window * window)
       
  1074 {
       
  1075     SDL_VideoDisplay *display;
       
  1076 
       
  1077     CHECK_WINDOW_MAGIC(window, SDL_PIXELFORMAT_UNKNOWN);
       
  1078 
       
  1079     display = SDL_GetDisplayForWindow(window);
       
  1080     return display->current_mode.format;
       
  1081 }
       
  1082 
       
  1083 static void
       
  1084 SDL_RestoreMousePosition(SDL_Window *window)
       
  1085 {
       
  1086     int x, y;
       
  1087 
       
  1088     if (window == SDL_GetMouseFocus()) {
       
  1089         SDL_GetMouseState(&x, &y);
       
  1090         SDL_WarpMouseInWindow(window, x, y);
       
  1091     }
       
  1092 }
       
  1093 
       
  1094 static void
       
  1095 SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
       
  1096 {
       
  1097     SDL_VideoDisplay *display;
       
  1098     SDL_Window *other;
       
  1099 
       
  1100 #ifdef __MACOSX__
       
  1101     if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) {
       
  1102         window->last_fullscreen_flags = window->flags;
       
  1103         return;
       
  1104     }
       
  1105 #endif
       
  1106 
       
  1107     display = SDL_GetDisplayForWindow(window);
       
  1108 
       
  1109     if (fullscreen) {
       
  1110         /* Hide any other fullscreen windows */
       
  1111         if (display->fullscreen_window &&
       
  1112             display->fullscreen_window != window) {
       
  1113             SDL_MinimizeWindow(display->fullscreen_window);
       
  1114         }
       
  1115     }
       
  1116 
       
  1117     /* See if anything needs to be done now */
       
  1118     if ((display->fullscreen_window == window) == fullscreen) {
       
  1119         if ((window->last_fullscreen_flags & FULLSCREEN_MASK) == (window->flags & FULLSCREEN_MASK)) {
       
  1120             return;
       
  1121         }
       
  1122     }
       
  1123 
       
  1124     /* See if there are any fullscreen windows */
       
  1125     for (other = _this->windows; other; other = other->next) {
       
  1126         SDL_bool setDisplayMode = SDL_FALSE;
       
  1127 
       
  1128         if (other == window) {
       
  1129             setDisplayMode = fullscreen;
       
  1130         } else if (FULLSCREEN_VISIBLE(other) &&
       
  1131                    SDL_GetDisplayForWindow(other) == display) {
       
  1132             setDisplayMode = SDL_TRUE;
       
  1133         }
       
  1134 
       
  1135         if (setDisplayMode) {
       
  1136             SDL_DisplayMode fullscreen_mode;
       
  1137 
       
  1138             if (SDL_GetWindowDisplayMode(other, &fullscreen_mode) == 0) {
       
  1139                 SDL_bool resized = SDL_TRUE;
       
  1140 
       
  1141                 if (other->w == fullscreen_mode.w && other->h == fullscreen_mode.h) {
       
  1142                     resized = SDL_FALSE;
       
  1143                 }
       
  1144 
       
  1145                 /* only do the mode change if we want exclusive fullscreen */
       
  1146                 if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
       
  1147                     SDL_SetDisplayModeForDisplay(display, &fullscreen_mode);
       
  1148                 } else {
       
  1149                     SDL_SetDisplayModeForDisplay(display, NULL);
       
  1150                 }
       
  1151 
       
  1152                 if (_this->SetWindowFullscreen) {
       
  1153                     _this->SetWindowFullscreen(_this, other, display, SDL_TRUE);
       
  1154                 }
       
  1155                 display->fullscreen_window = other;
       
  1156 
       
  1157                 /* Generate a mode change event here */
       
  1158                 if (resized) {
       
  1159                     SDL_SendWindowEvent(other, SDL_WINDOWEVENT_RESIZED,
       
  1160                                         fullscreen_mode.w, fullscreen_mode.h);
       
  1161                 } else {
       
  1162                     SDL_OnWindowResized(other);
       
  1163                 }
       
  1164 
       
  1165                 SDL_RestoreMousePosition(other);
       
  1166 
       
  1167                 window->last_fullscreen_flags = window->flags;
       
  1168                 return;
       
  1169             }
       
  1170         }
       
  1171     }
       
  1172 
       
  1173     /* Nope, restore the desktop mode */
       
  1174     SDL_SetDisplayModeForDisplay(display, NULL);
       
  1175 
       
  1176     if (_this->SetWindowFullscreen) {
       
  1177         _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
       
  1178     }
       
  1179     display->fullscreen_window = NULL;
       
  1180 
       
  1181     /* Generate a mode change event here */
       
  1182     SDL_OnWindowResized(window);
       
  1183 
       
  1184     /* Restore the cursor position */
       
  1185     SDL_RestoreMousePosition(window);
       
  1186 
       
  1187     window->last_fullscreen_flags = window->flags;
       
  1188 }
       
  1189 
       
  1190 #define CREATE_FLAGS \
       
  1191     (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI)
       
  1192 
       
  1193 static void
       
  1194 SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
       
  1195 {
       
  1196     window->windowed.x = window->x;
       
  1197     window->windowed.y = window->y;
       
  1198     window->windowed.w = window->w;
       
  1199     window->windowed.h = window->h;
       
  1200 
       
  1201     if (flags & SDL_WINDOW_MAXIMIZED) {
       
  1202         SDL_MaximizeWindow(window);
       
  1203     }
       
  1204     if (flags & SDL_WINDOW_MINIMIZED) {
       
  1205         SDL_MinimizeWindow(window);
       
  1206     }
       
  1207     if (flags & SDL_WINDOW_FULLSCREEN) {
       
  1208         SDL_SetWindowFullscreen(window, flags);
       
  1209     }
       
  1210     if (flags & SDL_WINDOW_INPUT_GRABBED) {
       
  1211         SDL_SetWindowGrab(window, SDL_TRUE);
       
  1212     }
       
  1213     if (!(flags & SDL_WINDOW_HIDDEN)) {
       
  1214         SDL_ShowWindow(window);
       
  1215     }
       
  1216 }
       
  1217 
       
  1218 SDL_Window *
       
  1219 SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
       
  1220 {
       
  1221     SDL_Window *window;
       
  1222     const char *hint;
       
  1223 
       
  1224     if (!_this) {
       
  1225         /* Initialize the video system if needed */
       
  1226         if (SDL_VideoInit(NULL) < 0) {
       
  1227             return NULL;
       
  1228         }
       
  1229     }
       
  1230 
       
  1231     /* Some platforms can't create zero-sized windows */
       
  1232     if (w < 1) {
       
  1233         w = 1;
       
  1234     }
       
  1235     if (h < 1) {
       
  1236         h = 1;
       
  1237     }
       
  1238 
       
  1239     /* Some platforms have OpenGL enabled by default */
       
  1240 #if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__
       
  1241     flags |= SDL_WINDOW_OPENGL;
       
  1242 #endif
       
  1243     if (flags & SDL_WINDOW_OPENGL) {
       
  1244         if (!_this->GL_CreateContext) {
       
  1245             SDL_SetError("No OpenGL support in video driver");
       
  1246             return NULL;
       
  1247         }
       
  1248         if (SDL_GL_LoadLibrary(NULL) < 0) {
       
  1249             return NULL;
       
  1250         }
       
  1251     }
       
  1252 
       
  1253     /* Unless the user has specified the high-DPI disabling hint, respect the
       
  1254      * SDL_WINDOW_ALLOW_HIGHDPI flag.
       
  1255      */
       
  1256     if (flags & SDL_WINDOW_ALLOW_HIGHDPI) {
       
  1257         hint = SDL_GetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED);
       
  1258         if (hint && SDL_atoi(hint) > 0) {
       
  1259             flags &= ~SDL_WINDOW_ALLOW_HIGHDPI;
       
  1260         }
       
  1261     }
       
  1262 
       
  1263     window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
       
  1264     if (!window) {
       
  1265         SDL_OutOfMemory();
       
  1266         return NULL;
       
  1267     }
       
  1268     window->magic = &_this->window_magic;
       
  1269     window->id = _this->next_object_id++;
       
  1270     window->x = x;
       
  1271     window->y = y;
       
  1272     window->w = w;
       
  1273     window->h = h;
       
  1274     if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) ||
       
  1275         SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
       
  1276         SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
       
  1277         int displayIndex;
       
  1278         SDL_Rect bounds;
       
  1279 
       
  1280         displayIndex = SDL_GetIndexOfDisplay(display);
       
  1281         SDL_GetDisplayBounds(displayIndex, &bounds);
       
  1282         if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
       
  1283             window->x = bounds.x + (bounds.w - w) / 2;
       
  1284         }
       
  1285         if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
       
  1286             window->y = bounds.y + (bounds.h - h) / 2;
       
  1287         }
       
  1288     }
       
  1289     window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
       
  1290     window->last_fullscreen_flags = window->flags;
       
  1291     window->brightness = 1.0f;
       
  1292     window->next = _this->windows;
       
  1293     window->is_destroying = SDL_FALSE;
       
  1294 
       
  1295     if (_this->windows) {
       
  1296         _this->windows->prev = window;
       
  1297     }
       
  1298     _this->windows = window;
       
  1299 
       
  1300     if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
       
  1301         SDL_DestroyWindow(window);
       
  1302         return NULL;
       
  1303     }
       
  1304 
       
  1305     if (title) {
       
  1306         SDL_SetWindowTitle(window, title);
       
  1307     }
       
  1308     SDL_FinishWindowCreation(window, flags);
       
  1309 
       
  1310     /* If the window was created fullscreen, make sure the mode code matches */
       
  1311     SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
       
  1312 
       
  1313     return window;
       
  1314 }
       
  1315 
       
  1316 SDL_Window *
       
  1317 SDL_CreateWindowFrom(const void *data)
       
  1318 {
       
  1319     SDL_Window *window;
       
  1320 
       
  1321     if (!_this) {
       
  1322         SDL_UninitializedVideo();
       
  1323         return NULL;
       
  1324     }
       
  1325     window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
       
  1326     if (!window) {
       
  1327         SDL_OutOfMemory();
       
  1328         return NULL;
       
  1329     }
       
  1330     window->magic = &_this->window_magic;
       
  1331     window->id = _this->next_object_id++;
       
  1332     window->flags = SDL_WINDOW_FOREIGN;
       
  1333     window->last_fullscreen_flags = window->flags;
       
  1334     window->is_destroying = SDL_FALSE;
       
  1335     window->brightness = 1.0f;
       
  1336     window->next = _this->windows;
       
  1337     if (_this->windows) {
       
  1338         _this->windows->prev = window;
       
  1339     }
       
  1340     _this->windows = window;
       
  1341 
       
  1342     if (!_this->CreateWindowFrom ||
       
  1343         _this->CreateWindowFrom(_this, window, data) < 0) {
       
  1344         SDL_DestroyWindow(window);
       
  1345         return NULL;
       
  1346     }
       
  1347     return window;
       
  1348 }
       
  1349 
       
  1350 int
       
  1351 SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
       
  1352 {
       
  1353     char *title = window->title;
       
  1354     SDL_Surface *icon = window->icon;
       
  1355 
       
  1356     if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
       
  1357         return SDL_SetError("No OpenGL support in video driver");
       
  1358     }
       
  1359 
       
  1360     if (window->flags & SDL_WINDOW_FOREIGN) {
       
  1361         /* Can't destroy and re-create foreign windows, hrm */
       
  1362         flags |= SDL_WINDOW_FOREIGN;
       
  1363     } else {
       
  1364         flags &= ~SDL_WINDOW_FOREIGN;
       
  1365     }
       
  1366 
       
  1367     /* Restore video mode, etc. */
       
  1368     SDL_HideWindow(window);
       
  1369 
       
  1370     /* Tear down the old native window */
       
  1371     if (window->surface) {
       
  1372         window->surface->flags &= ~SDL_DONTFREE;
       
  1373         SDL_FreeSurface(window->surface);
       
  1374     }
       
  1375     if (_this->DestroyWindowFramebuffer) {
       
  1376         _this->DestroyWindowFramebuffer(_this, window);
       
  1377     }
       
  1378     if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
       
  1379         _this->DestroyWindow(_this, window);
       
  1380     }
       
  1381 
       
  1382     if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
       
  1383         if (flags & SDL_WINDOW_OPENGL) {
       
  1384             if (SDL_GL_LoadLibrary(NULL) < 0) {
       
  1385                 return -1;
       
  1386             }
       
  1387         } else {
       
  1388             SDL_GL_UnloadLibrary();
       
  1389         }
       
  1390     }
       
  1391 
       
  1392     window->title = NULL;
       
  1393     window->icon = NULL;
       
  1394     window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
       
  1395     window->last_fullscreen_flags = window->flags;
       
  1396     window->is_destroying = SDL_FALSE;
       
  1397 
       
  1398     if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
       
  1399         if (_this->CreateWindow(_this, window) < 0) {
       
  1400             if (flags & SDL_WINDOW_OPENGL) {
       
  1401                 SDL_GL_UnloadLibrary();
       
  1402             }
       
  1403             return -1;
       
  1404         }
       
  1405     }
       
  1406 
       
  1407     if (title) {
       
  1408         SDL_SetWindowTitle(window, title);
       
  1409         SDL_free(title);
       
  1410     }
       
  1411     if (icon) {
       
  1412         SDL_SetWindowIcon(window, icon);
       
  1413         SDL_FreeSurface(icon);
       
  1414     }
       
  1415     SDL_FinishWindowCreation(window, flags);
       
  1416 
       
  1417     return 0;
       
  1418 }
       
  1419 
       
  1420 Uint32
       
  1421 SDL_GetWindowID(SDL_Window * window)
       
  1422 {
       
  1423     CHECK_WINDOW_MAGIC(window, 0);
       
  1424 
       
  1425     return window->id;
       
  1426 }
       
  1427 
       
  1428 SDL_Window *
       
  1429 SDL_GetWindowFromID(Uint32 id)
       
  1430 {
       
  1431     SDL_Window *window;
       
  1432 
       
  1433     if (!_this) {
       
  1434         return NULL;
       
  1435     }
       
  1436     for (window = _this->windows; window; window = window->next) {
       
  1437         if (window->id == id) {
       
  1438             return window;
       
  1439         }
       
  1440     }
       
  1441     return NULL;
       
  1442 }
       
  1443 
       
  1444 Uint32
       
  1445 SDL_GetWindowFlags(SDL_Window * window)
       
  1446 {
       
  1447     CHECK_WINDOW_MAGIC(window, 0);
       
  1448 
       
  1449     return window->flags;
       
  1450 }
       
  1451 
       
  1452 void
       
  1453 SDL_SetWindowTitle(SDL_Window * window, const char *title)
       
  1454 {
       
  1455     CHECK_WINDOW_MAGIC(window, );
       
  1456 
       
  1457     if (title == window->title) {
       
  1458         return;
       
  1459     }
       
  1460     SDL_free(window->title);
       
  1461     if (title && *title) {
       
  1462         window->title = SDL_strdup(title);
       
  1463     } else {
       
  1464         window->title = NULL;
       
  1465     }
       
  1466 
       
  1467     if (_this->SetWindowTitle) {
       
  1468         _this->SetWindowTitle(_this, window);
       
  1469     }
       
  1470 }
       
  1471 
       
  1472 const char *
       
  1473 SDL_GetWindowTitle(SDL_Window * window)
       
  1474 {
       
  1475     CHECK_WINDOW_MAGIC(window, "");
       
  1476 
       
  1477     return window->title ? window->title : "";
       
  1478 }
       
  1479 
       
  1480 void
       
  1481 SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon)
       
  1482 {
       
  1483     CHECK_WINDOW_MAGIC(window, );
       
  1484 
       
  1485     if (!icon) {
       
  1486         return;
       
  1487     }
       
  1488 
       
  1489     SDL_FreeSurface(window->icon);
       
  1490 
       
  1491     /* Convert the icon into ARGB8888 */
       
  1492     window->icon = SDL_ConvertSurfaceFormat(icon, SDL_PIXELFORMAT_ARGB8888, 0);
       
  1493     if (!window->icon) {
       
  1494         return;
       
  1495     }
       
  1496 
       
  1497     if (_this->SetWindowIcon) {
       
  1498         _this->SetWindowIcon(_this, window, window->icon);
       
  1499     }
       
  1500 }
       
  1501 
       
  1502 void*
       
  1503 SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata)
       
  1504 {
       
  1505     SDL_WindowUserData *prev, *data;
       
  1506 
       
  1507     CHECK_WINDOW_MAGIC(window, NULL);
       
  1508 
       
  1509     /* Input validation */
       
  1510     if (name == NULL || name[0] == '\0') {
       
  1511       SDL_InvalidParamError("name");
       
  1512       return NULL;
       
  1513     }
       
  1514 
       
  1515     /* See if the named data already exists */
       
  1516     prev = NULL;
       
  1517     for (data = window->data; data; prev = data, data = data->next) {
       
  1518         if (data->name && SDL_strcmp(data->name, name) == 0) {
       
  1519             void *last_value = data->data;
       
  1520 
       
  1521             if (userdata) {
       
  1522                 /* Set the new value */
       
  1523                 data->data = userdata;
       
  1524             } else {
       
  1525                 /* Delete this value */
       
  1526                 if (prev) {
       
  1527                     prev->next = data->next;
       
  1528                 } else {
       
  1529                     window->data = data->next;
       
  1530                 }
       
  1531                 SDL_free(data->name);
       
  1532                 SDL_free(data);
       
  1533             }
       
  1534             return last_value;
       
  1535         }
       
  1536     }
       
  1537 
       
  1538     /* Add new data to the window */
       
  1539     if (userdata) {
       
  1540         data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data));
       
  1541         data->name = SDL_strdup(name);
       
  1542         data->data = userdata;
       
  1543         data->next = window->data;
       
  1544         window->data = data;
       
  1545     }
       
  1546     return NULL;
       
  1547 }
       
  1548 
       
  1549 void *
       
  1550 SDL_GetWindowData(SDL_Window * window, const char *name)
       
  1551 {
       
  1552     SDL_WindowUserData *data;
       
  1553 
       
  1554     CHECK_WINDOW_MAGIC(window, NULL);
       
  1555 
       
  1556     /* Input validation */
       
  1557     if (name == NULL || name[0] == '\0') {
       
  1558       SDL_InvalidParamError("name");
       
  1559       return NULL;
       
  1560     }
       
  1561 
       
  1562     for (data = window->data; data; data = data->next) {
       
  1563         if (data->name && SDL_strcmp(data->name, name) == 0) {
       
  1564             return data->data;
       
  1565         }
       
  1566     }
       
  1567     return NULL;
       
  1568 }
       
  1569 
       
  1570 void
       
  1571 SDL_SetWindowPosition(SDL_Window * window, int x, int y)
       
  1572 {
       
  1573     CHECK_WINDOW_MAGIC(window, );
       
  1574 
       
  1575     if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
       
  1576         SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
       
  1577         int displayIndex;
       
  1578         SDL_Rect bounds;
       
  1579 
       
  1580         displayIndex = SDL_GetIndexOfDisplay(display);
       
  1581         SDL_GetDisplayBounds(displayIndex, &bounds);
       
  1582         if (SDL_WINDOWPOS_ISCENTERED(x)) {
       
  1583             x = bounds.x + (bounds.w - window->w) / 2;
       
  1584         }
       
  1585         if (SDL_WINDOWPOS_ISCENTERED(y)) {
       
  1586             y = bounds.y + (bounds.h - window->h) / 2;
       
  1587         }
       
  1588     }
       
  1589 
       
  1590     if ((window->flags & SDL_WINDOW_FULLSCREEN)) {
       
  1591         if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
       
  1592             window->windowed.x = x;
       
  1593         }
       
  1594         if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
       
  1595             window->windowed.y = y;
       
  1596         }
       
  1597     } else {
       
  1598         if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
       
  1599             window->x = x;
       
  1600         }
       
  1601         if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
       
  1602             window->y = y;
       
  1603         }
       
  1604 
       
  1605         if (_this->SetWindowPosition) {
       
  1606             _this->SetWindowPosition(_this, window);
       
  1607         }
       
  1608         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
       
  1609     }
       
  1610 }
       
  1611 
       
  1612 void
       
  1613 SDL_GetWindowPosition(SDL_Window * window, int *x, int *y)
       
  1614 {
       
  1615     CHECK_WINDOW_MAGIC(window, );
       
  1616 
       
  1617     /* Fullscreen windows are always at their display's origin */
       
  1618     if (window->flags & SDL_WINDOW_FULLSCREEN) {
       
  1619         if (x) {
       
  1620             *x = 0;
       
  1621         }
       
  1622         if (y) {
       
  1623             *y = 0;
       
  1624         }
       
  1625     } else {
       
  1626         if (x) {
       
  1627             *x = window->x;
       
  1628         }
       
  1629         if (y) {
       
  1630             *y = window->y;
       
  1631         }
       
  1632     }
       
  1633 }
       
  1634 
       
  1635 void
       
  1636 SDL_SetWindowBordered(SDL_Window * window, SDL_bool bordered)
       
  1637 {
       
  1638     CHECK_WINDOW_MAGIC(window, );
       
  1639     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
       
  1640         const int want = (bordered != SDL_FALSE);  /* normalize the flag. */
       
  1641         const int have = ((window->flags & SDL_WINDOW_BORDERLESS) == 0);
       
  1642         if ((want != have) && (_this->SetWindowBordered)) {
       
  1643             if (want) {
       
  1644                 window->flags &= ~SDL_WINDOW_BORDERLESS;
       
  1645             } else {
       
  1646                 window->flags |= SDL_WINDOW_BORDERLESS;
       
  1647             }
       
  1648             _this->SetWindowBordered(_this, window, (SDL_bool) want);
       
  1649         }
       
  1650     }
       
  1651 }
       
  1652 
       
  1653 void
       
  1654 SDL_SetWindowSize(SDL_Window * window, int w, int h)
       
  1655 {
       
  1656     CHECK_WINDOW_MAGIC(window, );
       
  1657     if (w <= 0) {
       
  1658         SDL_InvalidParamError("w");
       
  1659         return;
       
  1660     }
       
  1661     if (h <= 0) {
       
  1662         SDL_InvalidParamError("h");
       
  1663         return;
       
  1664     }
       
  1665 
       
  1666     /* Make sure we don't exceed any window size limits */
       
  1667     if (window->min_w && w < window->min_w)
       
  1668     {
       
  1669         w = window->min_w;
       
  1670     }
       
  1671     if (window->max_w && w > window->max_w)
       
  1672     {
       
  1673         w = window->max_w;
       
  1674     }
       
  1675     if (window->min_h && h < window->min_h)
       
  1676     {
       
  1677         h = window->min_h;
       
  1678     }
       
  1679     if (window->max_h && h > window->max_h)
       
  1680     {
       
  1681         h = window->max_h;
       
  1682     }
       
  1683 
       
  1684     /* FIXME: Should this change fullscreen modes? */
       
  1685     if (window->flags & SDL_WINDOW_FULLSCREEN) {
       
  1686         window->windowed.w = w;
       
  1687         window->windowed.h = h;
       
  1688     } else {
       
  1689         window->w = w;
       
  1690         window->h = h;
       
  1691         if (_this->SetWindowSize) {
       
  1692             _this->SetWindowSize(_this, window);
       
  1693         }
       
  1694         if (window->w == w && window->h == h) {
       
  1695             /* We didn't get a SDL_WINDOWEVENT_RESIZED event (by design) */
       
  1696             SDL_OnWindowResized(window);
       
  1697         }
       
  1698     }
       
  1699 }
       
  1700 
       
  1701 void
       
  1702 SDL_GetWindowSize(SDL_Window * window, int *w, int *h)
       
  1703 {
       
  1704     CHECK_WINDOW_MAGIC(window, );
       
  1705     if (w) {
       
  1706         *w = window->w;
       
  1707     }
       
  1708     if (h) {
       
  1709         *h = window->h;
       
  1710     }
       
  1711 }
       
  1712 
       
  1713 void
       
  1714 SDL_SetWindowMinimumSize(SDL_Window * window, int min_w, int min_h)
       
  1715 {
       
  1716     CHECK_WINDOW_MAGIC(window, );
       
  1717     if (min_w <= 0) {
       
  1718         SDL_InvalidParamError("min_w");
       
  1719         return;
       
  1720     }
       
  1721     if (min_h <= 0) {
       
  1722         SDL_InvalidParamError("min_h");
       
  1723         return;
       
  1724     }
       
  1725 
       
  1726     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
       
  1727         window->min_w = min_w;
       
  1728         window->min_h = min_h;
       
  1729         if (_this->SetWindowMinimumSize) {
       
  1730             _this->SetWindowMinimumSize(_this, window);
       
  1731         }
       
  1732         /* Ensure that window is not smaller than minimal size */
       
  1733         SDL_SetWindowSize(window, SDL_max(window->w, window->min_w), SDL_max(window->h, window->min_h));
       
  1734     }
       
  1735 }
       
  1736 
       
  1737 void
       
  1738 SDL_GetWindowMinimumSize(SDL_Window * window, int *min_w, int *min_h)
       
  1739 {
       
  1740     CHECK_WINDOW_MAGIC(window, );
       
  1741     if (min_w) {
       
  1742         *min_w = window->min_w;
       
  1743     }
       
  1744     if (min_h) {
       
  1745         *min_h = window->min_h;
       
  1746     }
       
  1747 }
       
  1748 
       
  1749 void
       
  1750 SDL_SetWindowMaximumSize(SDL_Window * window, int max_w, int max_h)
       
  1751 {
       
  1752     CHECK_WINDOW_MAGIC(window, );
       
  1753     if (max_w <= 0) {
       
  1754         SDL_InvalidParamError("max_w");
       
  1755         return;
       
  1756     }
       
  1757     if (max_h <= 0) {
       
  1758         SDL_InvalidParamError("max_h");
       
  1759         return;
       
  1760     }
       
  1761 
       
  1762     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
       
  1763         window->max_w = max_w;
       
  1764         window->max_h = max_h;
       
  1765         if (_this->SetWindowMaximumSize) {
       
  1766             _this->SetWindowMaximumSize(_this, window);
       
  1767         }
       
  1768         /* Ensure that window is not larger than maximal size */
       
  1769         SDL_SetWindowSize(window, SDL_min(window->w, window->max_w), SDL_min(window->h, window->max_h));
       
  1770     }
       
  1771 }
       
  1772 
       
  1773 void
       
  1774 SDL_GetWindowMaximumSize(SDL_Window * window, int *max_w, int *max_h)
       
  1775 {
       
  1776     CHECK_WINDOW_MAGIC(window, );
       
  1777     if (max_w) {
       
  1778         *max_w = window->max_w;
       
  1779     }
       
  1780     if (max_h) {
       
  1781         *max_h = window->max_h;
       
  1782     }
       
  1783 }
       
  1784 
       
  1785 void
       
  1786 SDL_ShowWindow(SDL_Window * window)
       
  1787 {
       
  1788     CHECK_WINDOW_MAGIC(window, );
       
  1789 
       
  1790     if (window->flags & SDL_WINDOW_SHOWN) {
       
  1791         return;
       
  1792     }
       
  1793 
       
  1794     if (_this->ShowWindow) {
       
  1795         _this->ShowWindow(_this, window);
       
  1796     }
       
  1797     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
       
  1798 }
       
  1799 
       
  1800 void
       
  1801 SDL_HideWindow(SDL_Window * window)
       
  1802 {
       
  1803     CHECK_WINDOW_MAGIC(window, );
       
  1804 
       
  1805     if (!(window->flags & SDL_WINDOW_SHOWN)) {
       
  1806         return;
       
  1807     }
       
  1808 
       
  1809     SDL_UpdateFullscreenMode(window, SDL_FALSE);
       
  1810 
       
  1811     if (_this->HideWindow) {
       
  1812         _this->HideWindow(_this, window);
       
  1813     }
       
  1814     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
       
  1815 }
       
  1816 
       
  1817 void
       
  1818 SDL_RaiseWindow(SDL_Window * window)
       
  1819 {
       
  1820     CHECK_WINDOW_MAGIC(window, );
       
  1821 
       
  1822     if (!(window->flags & SDL_WINDOW_SHOWN)) {
       
  1823         return;
       
  1824     }
       
  1825     if (_this->RaiseWindow) {
       
  1826         _this->RaiseWindow(_this, window);
       
  1827     }
       
  1828 }
       
  1829 
       
  1830 void
       
  1831 SDL_MaximizeWindow(SDL_Window * window)
       
  1832 {
       
  1833     CHECK_WINDOW_MAGIC(window, );
       
  1834 
       
  1835     if (window->flags & SDL_WINDOW_MAXIMIZED) {
       
  1836         return;
       
  1837     }
       
  1838 
       
  1839     /* !!! FIXME: should this check if the window is resizable? */
       
  1840 
       
  1841     if (_this->MaximizeWindow) {
       
  1842         _this->MaximizeWindow(_this, window);
       
  1843     }
       
  1844 }
       
  1845 
       
  1846 void
       
  1847 SDL_MinimizeWindow(SDL_Window * window)
       
  1848 {
       
  1849     CHECK_WINDOW_MAGIC(window, );
       
  1850 
       
  1851     if (window->flags & SDL_WINDOW_MINIMIZED) {
       
  1852         return;
       
  1853     }
       
  1854 
       
  1855     SDL_UpdateFullscreenMode(window, SDL_FALSE);
       
  1856 
       
  1857     if (_this->MinimizeWindow) {
       
  1858         _this->MinimizeWindow(_this, window);
       
  1859     }
       
  1860 }
       
  1861 
       
  1862 void
       
  1863 SDL_RestoreWindow(SDL_Window * window)
       
  1864 {
       
  1865     CHECK_WINDOW_MAGIC(window, );
       
  1866 
       
  1867     if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
       
  1868         return;
       
  1869     }
       
  1870 
       
  1871     if (_this->RestoreWindow) {
       
  1872         _this->RestoreWindow(_this, window);
       
  1873     }
       
  1874 }
       
  1875 
       
  1876 int
       
  1877 SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags)
       
  1878 {
       
  1879     CHECK_WINDOW_MAGIC(window, -1);
       
  1880 
       
  1881     flags &= FULLSCREEN_MASK;
       
  1882 
       
  1883     if ( flags == (window->flags & FULLSCREEN_MASK) ) {
       
  1884         return 0;
       
  1885     }
       
  1886 
       
  1887     /* clear the previous flags and OR in the new ones */
       
  1888     window->flags &= ~FULLSCREEN_MASK;
       
  1889     window->flags |= flags;
       
  1890 
       
  1891     SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
       
  1892 
       
  1893     return 0;
       
  1894 }
       
  1895 
       
  1896 static SDL_Surface *
       
  1897 SDL_CreateWindowFramebuffer(SDL_Window * window)
       
  1898 {
       
  1899     Uint32 format;
       
  1900     void *pixels;
       
  1901     int pitch;
       
  1902     int bpp;
       
  1903     Uint32 Rmask, Gmask, Bmask, Amask;
       
  1904 
       
  1905     if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
       
  1906         return NULL;
       
  1907     }
       
  1908 
       
  1909     if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
       
  1910         return NULL;
       
  1911     }
       
  1912 
       
  1913     if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
       
  1914         return NULL;
       
  1915     }
       
  1916 
       
  1917     return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
       
  1918 }
       
  1919 
       
  1920 SDL_Surface *
       
  1921 SDL_GetWindowSurface(SDL_Window * window)
       
  1922 {
       
  1923     CHECK_WINDOW_MAGIC(window, NULL);
       
  1924 
       
  1925     if (!window->surface_valid) {
       
  1926         if (window->surface) {
       
  1927             window->surface->flags &= ~SDL_DONTFREE;
       
  1928             SDL_FreeSurface(window->surface);
       
  1929         }
       
  1930         window->surface = SDL_CreateWindowFramebuffer(window);
       
  1931         if (window->surface) {
       
  1932             window->surface_valid = SDL_TRUE;
       
  1933             window->surface->flags |= SDL_DONTFREE;
       
  1934         }
       
  1935     }
       
  1936     return window->surface;
       
  1937 }
       
  1938 
       
  1939 int
       
  1940 SDL_UpdateWindowSurface(SDL_Window * window)
       
  1941 {
       
  1942     SDL_Rect full_rect;
       
  1943 
       
  1944     CHECK_WINDOW_MAGIC(window, -1);
       
  1945 
       
  1946     full_rect.x = 0;
       
  1947     full_rect.y = 0;
       
  1948     full_rect.w = window->w;
       
  1949     full_rect.h = window->h;
       
  1950     return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
       
  1951 }
       
  1952 
       
  1953 int
       
  1954 SDL_UpdateWindowSurfaceRects(SDL_Window * window, const SDL_Rect * rects,
       
  1955                              int numrects)
       
  1956 {
       
  1957     CHECK_WINDOW_MAGIC(window, -1);
       
  1958 
       
  1959     if (!window->surface_valid) {
       
  1960         return SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
       
  1961     }
       
  1962 
       
  1963     return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
       
  1964 }
       
  1965 
       
  1966 int
       
  1967 SDL_SetWindowBrightness(SDL_Window * window, float brightness)
       
  1968 {
       
  1969     Uint16 ramp[256];
       
  1970     int status;
       
  1971 
       
  1972     CHECK_WINDOW_MAGIC(window, -1);
       
  1973 
       
  1974     SDL_CalculateGammaRamp(brightness, ramp);
       
  1975     status = SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
       
  1976     if (status == 0) {
       
  1977         window->brightness = brightness;
       
  1978     }
       
  1979     return status;
       
  1980 }
       
  1981 
       
  1982 float
       
  1983 SDL_GetWindowBrightness(SDL_Window * window)
       
  1984 {
       
  1985     CHECK_WINDOW_MAGIC(window, 1.0f);
       
  1986 
       
  1987     return window->brightness;
       
  1988 }
       
  1989 
       
  1990 int
       
  1991 SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
       
  1992                                             const Uint16 * green,
       
  1993                                             const Uint16 * blue)
       
  1994 {
       
  1995     CHECK_WINDOW_MAGIC(window, -1);
       
  1996 
       
  1997     if (!_this->SetWindowGammaRamp) {
       
  1998         return SDL_Unsupported();
       
  1999     }
       
  2000 
       
  2001     if (!window->gamma) {
       
  2002         if (SDL_GetWindowGammaRamp(window, NULL, NULL, NULL) < 0) {
       
  2003             return -1;
       
  2004         }
       
  2005     }
       
  2006 
       
  2007     if (red) {
       
  2008         SDL_memcpy(&window->gamma[0*256], red, 256*sizeof(Uint16));
       
  2009     }
       
  2010     if (green) {
       
  2011         SDL_memcpy(&window->gamma[1*256], green, 256*sizeof(Uint16));
       
  2012     }
       
  2013     if (blue) {
       
  2014         SDL_memcpy(&window->gamma[2*256], blue, 256*sizeof(Uint16));
       
  2015     }
       
  2016     if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
       
  2017         return _this->SetWindowGammaRamp(_this, window, window->gamma);
       
  2018     } else {
       
  2019         return 0;
       
  2020     }
       
  2021 }
       
  2022 
       
  2023 int
       
  2024 SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
       
  2025                                             Uint16 * green,
       
  2026                                             Uint16 * blue)
       
  2027 {
       
  2028     CHECK_WINDOW_MAGIC(window, -1);
       
  2029 
       
  2030     if (!window->gamma) {
       
  2031         int i;
       
  2032 
       
  2033         window->gamma = (Uint16 *)SDL_malloc(256*6*sizeof(Uint16));
       
  2034         if (!window->gamma) {
       
  2035             return SDL_OutOfMemory();
       
  2036         }
       
  2037         window->saved_gamma = window->gamma + 3*256;
       
  2038 
       
  2039         if (_this->GetWindowGammaRamp) {
       
  2040             if (_this->GetWindowGammaRamp(_this, window, window->gamma) < 0) {
       
  2041                 return -1;
       
  2042             }
       
  2043         } else {
       
  2044             /* Create an identity gamma ramp */
       
  2045             for (i = 0; i < 256; ++i) {
       
  2046                 Uint16 value = (Uint16)((i << 8) | i);
       
  2047 
       
  2048                 window->gamma[0*256+i] = value;
       
  2049                 window->gamma[1*256+i] = value;
       
  2050                 window->gamma[2*256+i] = value;
       
  2051             }
       
  2052         }
       
  2053         SDL_memcpy(window->saved_gamma, window->gamma, 3*256*sizeof(Uint16));
       
  2054     }
       
  2055 
       
  2056     if (red) {
       
  2057         SDL_memcpy(red, &window->gamma[0*256], 256*sizeof(Uint16));
       
  2058     }
       
  2059     if (green) {
       
  2060         SDL_memcpy(green, &window->gamma[1*256], 256*sizeof(Uint16));
       
  2061     }
       
  2062     if (blue) {
       
  2063         SDL_memcpy(blue, &window->gamma[2*256], 256*sizeof(Uint16));
       
  2064     }
       
  2065     return 0;
       
  2066 }
       
  2067 
       
  2068 void
       
  2069 SDL_UpdateWindowGrab(SDL_Window * window)
       
  2070 {
       
  2071     if (_this->SetWindowGrab) {
       
  2072         SDL_bool grabbed;
       
  2073         if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
       
  2074              (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
       
  2075             grabbed = SDL_TRUE;
       
  2076         } else {
       
  2077             grabbed = SDL_FALSE;
       
  2078         }
       
  2079         _this->SetWindowGrab(_this, window, grabbed);
       
  2080     }
       
  2081 }
       
  2082 
       
  2083 void
       
  2084 SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
       
  2085 {
       
  2086     CHECK_WINDOW_MAGIC(window, );
       
  2087 
       
  2088     if (!!grabbed == !!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
       
  2089         return;
       
  2090     }
       
  2091     if (grabbed) {
       
  2092         window->flags |= SDL_WINDOW_INPUT_GRABBED;
       
  2093     } else {
       
  2094         window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
       
  2095     }
       
  2096     SDL_UpdateWindowGrab(window);
       
  2097 }
       
  2098 
       
  2099 SDL_bool
       
  2100 SDL_GetWindowGrab(SDL_Window * window)
       
  2101 {
       
  2102     CHECK_WINDOW_MAGIC(window, SDL_FALSE);
       
  2103 
       
  2104     return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
       
  2105 }
       
  2106 
       
  2107 void
       
  2108 SDL_OnWindowShown(SDL_Window * window)
       
  2109 {
       
  2110     SDL_OnWindowRestored(window);
       
  2111 }
       
  2112 
       
  2113 void
       
  2114 SDL_OnWindowHidden(SDL_Window * window)
       
  2115 {
       
  2116     SDL_UpdateFullscreenMode(window, SDL_FALSE);
       
  2117 }
       
  2118 
       
  2119 void
       
  2120 SDL_OnWindowResized(SDL_Window * window)
       
  2121 {
       
  2122     window->surface_valid = SDL_FALSE;
       
  2123     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
       
  2124 }
       
  2125 
       
  2126 void
       
  2127 SDL_OnWindowMinimized(SDL_Window * window)
       
  2128 {
       
  2129     SDL_UpdateFullscreenMode(window, SDL_FALSE);
       
  2130 }
       
  2131 
       
  2132 void
       
  2133 SDL_OnWindowRestored(SDL_Window * window)
       
  2134 {
       
  2135     SDL_RaiseWindow(window);
       
  2136 
       
  2137     if (FULLSCREEN_VISIBLE(window)) {
       
  2138         SDL_UpdateFullscreenMode(window, SDL_TRUE);
       
  2139     }
       
  2140 }
       
  2141 
       
  2142 void
       
  2143 SDL_OnWindowEnter(SDL_Window * window)
       
  2144 {
       
  2145     if (_this->OnWindowEnter) {
       
  2146         _this->OnWindowEnter(_this, window);
       
  2147     }
       
  2148 }
       
  2149 
       
  2150 void
       
  2151 SDL_OnWindowLeave(SDL_Window * window)
       
  2152 {
       
  2153 }
       
  2154 
       
  2155 void
       
  2156 SDL_OnWindowFocusGained(SDL_Window * window)
       
  2157 {
       
  2158     SDL_Mouse *mouse = SDL_GetMouse();
       
  2159 
       
  2160     if (window->gamma && _this->SetWindowGammaRamp) {
       
  2161         _this->SetWindowGammaRamp(_this, window, window->gamma);
       
  2162     }
       
  2163 
       
  2164     if (mouse && mouse->relative_mode) {
       
  2165         SDL_SetMouseFocus(window);
       
  2166         SDL_WarpMouseInWindow(window, window->w/2, window->h/2);
       
  2167     }
       
  2168 
       
  2169     SDL_UpdateWindowGrab(window);
       
  2170 }
       
  2171 
       
  2172 static SDL_bool
       
  2173 ShouldMinimizeOnFocusLoss(SDL_Window * window)
       
  2174 {
       
  2175     const char *hint;
       
  2176 
       
  2177     if (!(window->flags & SDL_WINDOW_FULLSCREEN) || window->is_destroying) {
       
  2178         return SDL_FALSE;
       
  2179     }
       
  2180 
       
  2181 #ifdef __MACOSX__
       
  2182     if (Cocoa_IsWindowInFullscreenSpace(window)) {
       
  2183         return SDL_FALSE;
       
  2184     }
       
  2185 #endif
       
  2186 
       
  2187     hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS);
       
  2188     if (hint) {
       
  2189         if (*hint == '0') {
       
  2190             return SDL_FALSE;
       
  2191         } else {
       
  2192             return SDL_TRUE;
       
  2193         }
       
  2194     }
       
  2195 
       
  2196     return SDL_TRUE;
       
  2197 }
       
  2198 
       
  2199 void
       
  2200 SDL_OnWindowFocusLost(SDL_Window * window)
       
  2201 {
       
  2202     if (window->gamma && _this->SetWindowGammaRamp) {
       
  2203         _this->SetWindowGammaRamp(_this, window, window->saved_gamma);
       
  2204     }
       
  2205 
       
  2206     SDL_UpdateWindowGrab(window);
       
  2207 
       
  2208     if (ShouldMinimizeOnFocusLoss(window)) {
       
  2209         SDL_MinimizeWindow(window);
       
  2210     }
       
  2211 }
       
  2212 
       
  2213 SDL_Window *
       
  2214 SDL_GetFocusWindow(void)
       
  2215 {
       
  2216     SDL_Window *window;
       
  2217 
       
  2218     if (!_this) {
       
  2219         return NULL;
       
  2220     }
       
  2221     for (window = _this->windows; window; window = window->next) {
       
  2222         if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
       
  2223             return window;
       
  2224         }
       
  2225     }
       
  2226     return NULL;
       
  2227 }
       
  2228 
       
  2229 void
       
  2230 SDL_DestroyWindow(SDL_Window * window)
       
  2231 {
       
  2232     SDL_VideoDisplay *display;
       
  2233 
       
  2234     CHECK_WINDOW_MAGIC(window, );
       
  2235 
       
  2236     window->is_destroying = SDL_TRUE;
       
  2237 
       
  2238     /* Restore video mode, etc. */
       
  2239     SDL_HideWindow(window);
       
  2240 
       
  2241     /* Make sure this window no longer has focus */
       
  2242     if (SDL_GetKeyboardFocus() == window) {
       
  2243         SDL_SetKeyboardFocus(NULL);
       
  2244     }
       
  2245     if (SDL_GetMouseFocus() == window) {
       
  2246         SDL_SetMouseFocus(NULL);
       
  2247     }
       
  2248 
       
  2249     /* make no context current if this is the current context window. */
       
  2250     if (window->flags & SDL_WINDOW_OPENGL) {
       
  2251         if (_this->current_glwin == window) {
       
  2252             SDL_GL_MakeCurrent(window, NULL);
       
  2253         }
       
  2254     }
       
  2255 
       
  2256     if (window->surface) {
       
  2257         window->surface->flags &= ~SDL_DONTFREE;
       
  2258         SDL_FreeSurface(window->surface);
       
  2259     }
       
  2260     if (_this->DestroyWindowFramebuffer) {
       
  2261         _this->DestroyWindowFramebuffer(_this, window);
       
  2262     }
       
  2263     if (_this->DestroyWindow) {
       
  2264         _this->DestroyWindow(_this, window);
       
  2265     }
       
  2266     if (window->flags & SDL_WINDOW_OPENGL) {
       
  2267         SDL_GL_UnloadLibrary();
       
  2268     }
       
  2269 
       
  2270     display = SDL_GetDisplayForWindow(window);
       
  2271     if (display->fullscreen_window == window) {
       
  2272         display->fullscreen_window = NULL;
       
  2273     }
       
  2274 
       
  2275     /* Now invalidate magic */
       
  2276     window->magic = NULL;
       
  2277 
       
  2278     /* Free memory associated with the window */
       
  2279     SDL_free(window->title);
       
  2280     SDL_FreeSurface(window->icon);
       
  2281     SDL_free(window->gamma);
       
  2282     while (window->data) {
       
  2283         SDL_WindowUserData *data = window->data;
       
  2284 
       
  2285         window->data = data->next;
       
  2286         SDL_free(data->name);
       
  2287         SDL_free(data);
       
  2288     }
       
  2289 
       
  2290     /* Unlink the window from the list */
       
  2291     if (window->next) {
       
  2292         window->next->prev = window->prev;
       
  2293     }
       
  2294     if (window->prev) {
       
  2295         window->prev->next = window->next;
       
  2296     } else {
       
  2297         _this->windows = window->next;
       
  2298     }
       
  2299 
       
  2300     SDL_free(window);
       
  2301 }
       
  2302 
       
  2303 SDL_bool
       
  2304 SDL_IsScreenSaverEnabled()
       
  2305 {
       
  2306     if (!_this) {
       
  2307         return SDL_TRUE;
       
  2308     }
       
  2309     return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE;
       
  2310 }
       
  2311 
       
  2312 void
       
  2313 SDL_EnableScreenSaver()
       
  2314 {
       
  2315     if (!_this) {
       
  2316         return;
       
  2317     }
       
  2318     if (!_this->suspend_screensaver) {
       
  2319         return;
       
  2320     }
       
  2321     _this->suspend_screensaver = SDL_FALSE;
       
  2322     if (_this->SuspendScreenSaver) {
       
  2323         _this->SuspendScreenSaver(_this);
       
  2324     }
       
  2325 }
       
  2326 
       
  2327 void
       
  2328 SDL_DisableScreenSaver()
       
  2329 {
       
  2330     if (!_this) {
       
  2331         return;
       
  2332     }
       
  2333     if (_this->suspend_screensaver) {
       
  2334         return;
       
  2335     }
       
  2336     _this->suspend_screensaver = SDL_TRUE;
       
  2337     if (_this->SuspendScreenSaver) {
       
  2338         _this->SuspendScreenSaver(_this);
       
  2339     }
       
  2340 }
       
  2341 
       
  2342 void
       
  2343 SDL_VideoQuit(void)
       
  2344 {
       
  2345     int i, j;
       
  2346 
       
  2347     if (!_this) {
       
  2348         return;
       
  2349     }
       
  2350 
       
  2351     /* Halt event processing before doing anything else */
       
  2352     SDL_TouchQuit();
       
  2353     SDL_MouseQuit();
       
  2354     SDL_KeyboardQuit();
       
  2355     SDL_QuitSubSystem(SDL_INIT_EVENTS);
       
  2356 
       
  2357     SDL_EnableScreenSaver();
       
  2358 
       
  2359     /* Clean up the system video */
       
  2360     while (_this->windows) {
       
  2361         SDL_DestroyWindow(_this->windows);
       
  2362     }
       
  2363     _this->VideoQuit(_this);
       
  2364 
       
  2365     for (i = 0; i < _this->num_displays; ++i) {
       
  2366         SDL_VideoDisplay *display = &_this->displays[i];
       
  2367         for (j = display->num_display_modes; j--;) {
       
  2368             SDL_free(display->display_modes[j].driverdata);
       
  2369             display->display_modes[j].driverdata = NULL;
       
  2370         }
       
  2371         SDL_free(display->display_modes);
       
  2372         display->display_modes = NULL;
       
  2373         SDL_free(display->desktop_mode.driverdata);
       
  2374         display->desktop_mode.driverdata = NULL;
       
  2375         SDL_free(display->driverdata);
       
  2376         display->driverdata = NULL;
       
  2377     }
       
  2378     if (_this->displays) {
       
  2379         for (i = 0; i < _this->num_displays; ++i) {
       
  2380             SDL_free(_this->displays[i].name);
       
  2381         }
       
  2382         SDL_free(_this->displays);
       
  2383         _this->displays = NULL;
       
  2384         _this->num_displays = 0;
       
  2385     }
       
  2386     SDL_free(_this->clipboard_text);
       
  2387     _this->clipboard_text = NULL;
       
  2388     _this->free(_this);
       
  2389     _this = NULL;
       
  2390 }
       
  2391 
       
  2392 int
       
  2393 SDL_GL_LoadLibrary(const char *path)
       
  2394 {
       
  2395     int retval;
       
  2396 
       
  2397     if (!_this) {
       
  2398         return SDL_UninitializedVideo();
       
  2399     }
       
  2400     if (_this->gl_config.driver_loaded) {
       
  2401         if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) {
       
  2402             return SDL_SetError("OpenGL library already loaded");
       
  2403         }
       
  2404         retval = 0;
       
  2405     } else {
       
  2406         if (!_this->GL_LoadLibrary) {
       
  2407             return SDL_SetError("No dynamic GL support in video driver");
       
  2408         }
       
  2409         retval = _this->GL_LoadLibrary(_this, path);
       
  2410     }
       
  2411     if (retval == 0) {
       
  2412         ++_this->gl_config.driver_loaded;
       
  2413     } else {
       
  2414         if (_this->GL_UnloadLibrary) {
       
  2415             _this->GL_UnloadLibrary(_this);
       
  2416         }
       
  2417     }
       
  2418     return (retval);
       
  2419 }
       
  2420 
       
  2421 void *
       
  2422 SDL_GL_GetProcAddress(const char *proc)
       
  2423 {
       
  2424     void *func;
       
  2425 
       
  2426     if (!_this) {
       
  2427         SDL_UninitializedVideo();
       
  2428         return NULL;
       
  2429     }
       
  2430     func = NULL;
       
  2431     if (_this->GL_GetProcAddress) {
       
  2432         if (_this->gl_config.driver_loaded) {
       
  2433             func = _this->GL_GetProcAddress(_this, proc);
       
  2434         } else {
       
  2435             SDL_SetError("No GL driver has been loaded");
       
  2436         }
       
  2437     } else {
       
  2438         SDL_SetError("No dynamic GL support in video driver");
       
  2439     }
       
  2440     return func;
       
  2441 }
       
  2442 
       
  2443 void
       
  2444 SDL_GL_UnloadLibrary(void)
       
  2445 {
       
  2446     if (!_this) {
       
  2447         SDL_UninitializedVideo();
       
  2448         return;
       
  2449     }
       
  2450     if (_this->gl_config.driver_loaded > 0) {
       
  2451         if (--_this->gl_config.driver_loaded > 0) {
       
  2452             return;
       
  2453         }
       
  2454         if (_this->GL_UnloadLibrary) {
       
  2455             _this->GL_UnloadLibrary(_this);
       
  2456         }
       
  2457     }
       
  2458 }
       
  2459 
       
  2460 static SDL_INLINE SDL_bool
       
  2461 isAtLeastGL3(const char *verstr)
       
  2462 {
       
  2463     return ( verstr && (SDL_atoi(verstr) >= 3) );
       
  2464 }
       
  2465 
       
  2466 SDL_bool
       
  2467 SDL_GL_ExtensionSupported(const char *extension)
       
  2468 {
       
  2469 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
       
  2470     const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
       
  2471     const char *extensions;
       
  2472     const char *start;
       
  2473     const char *where, *terminator;
       
  2474 
       
  2475     /* Extension names should not have spaces. */
       
  2476     where = SDL_strchr(extension, ' ');
       
  2477     if (where || *extension == '\0') {
       
  2478         return SDL_FALSE;
       
  2479     }
       
  2480     /* See if there's an environment variable override */
       
  2481     start = SDL_getenv(extension);
       
  2482     if (start && *start == '0') {
       
  2483         return SDL_FALSE;
       
  2484     }
       
  2485 
       
  2486     /* Lookup the available extensions */
       
  2487 
       
  2488     glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
       
  2489     if (!glGetStringFunc) {
       
  2490         return SDL_FALSE;
       
  2491     }
       
  2492 
       
  2493     if (isAtLeastGL3((const char *) glGetStringFunc(GL_VERSION))) {
       
  2494         const GLubyte *(APIENTRY * glGetStringiFunc) (GLenum, GLuint);
       
  2495         void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
       
  2496         GLint num_exts = 0;
       
  2497         GLint i;
       
  2498 
       
  2499         glGetStringiFunc = SDL_GL_GetProcAddress("glGetStringi");
       
  2500         glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
       
  2501         if ((!glGetStringiFunc) || (!glGetIntegervFunc)) {
       
  2502             return SDL_FALSE;
       
  2503         }
       
  2504 
       
  2505         #ifndef GL_NUM_EXTENSIONS
       
  2506         #define GL_NUM_EXTENSIONS 0x821D
       
  2507         #endif
       
  2508         glGetIntegervFunc(GL_NUM_EXTENSIONS, &num_exts);
       
  2509         for (i = 0; i < num_exts; i++) {
       
  2510             const char *thisext = (const char *) glGetStringiFunc(GL_EXTENSIONS, i);
       
  2511             if (SDL_strcmp(thisext, extension) == 0) {
       
  2512                 return SDL_TRUE;
       
  2513             }
       
  2514         }
       
  2515 
       
  2516         return SDL_FALSE;
       
  2517     }
       
  2518 
       
  2519     /* Try the old way with glGetString(GL_EXTENSIONS) ... */
       
  2520 
       
  2521     extensions = (const char *) glGetStringFunc(GL_EXTENSIONS);
       
  2522     if (!extensions) {
       
  2523         return SDL_FALSE;
       
  2524     }
       
  2525     /*
       
  2526      * It takes a bit of care to be fool-proof about parsing the OpenGL
       
  2527      * extensions string. Don't be fooled by sub-strings, etc.
       
  2528      */
       
  2529 
       
  2530     start = extensions;
       
  2531 
       
  2532     for (;;) {
       
  2533         where = SDL_strstr(start, extension);
       
  2534         if (!where)
       
  2535             break;
       
  2536 
       
  2537         terminator = where + SDL_strlen(extension);
       
  2538         if (where == start || *(where - 1) == ' ')
       
  2539             if (*terminator == ' ' || *terminator == '\0')
       
  2540                 return SDL_TRUE;
       
  2541 
       
  2542         start = terminator;
       
  2543     }
       
  2544     return SDL_FALSE;
       
  2545 #else
       
  2546     return SDL_FALSE;
       
  2547 #endif
       
  2548 }
  2559 }
  2549 
  2560 
  2550 int
  2561 int
  2551 SDL_GL_SetAttribute(SDL_GLattr attr, int value)
  2562 SDL_GL_SetAttribute(SDL_GLattr attr, int value)
  2552 {
  2563 {