changed resizing window instead of recreating it on window size changes
[rocksndiamonds.git] / src / libgame / sdl.c
index ece4e3f7c0b7beb98a1608a01eead8ec3b671ab3..094b656511e88ae2614a4503345fbe610e46951a 100644 (file)
@@ -69,12 +69,11 @@ static void FinalizeScreen(int draw_target)
 
 static void UpdateScreenExt(SDL_Rect *rect, boolean with_frame_delay)
 {
-  static unsigned int update_screen_delay = 0;
-  unsigned int update_screen_delay_value = 50;         // (milliseconds)
+  static DelayCounter update_screen_delay = { 50 };    // (milliseconds)
   SDL_Surface *screen = backbuffer->surface;
 
   if (limit_screen_updates &&
-      !DelayReached(&update_screen_delay, update_screen_delay_value))
+      !DelayReached(&update_screen_delay))
     return;
 
   LimitScreenUpdates(FALSE);
@@ -151,28 +150,31 @@ static void UpdateScreenExt(SDL_Rect *rect, boolean with_frame_delay)
     dst_rect1 = &dst_rect_screen;
 
 #if defined(HAS_SCREEN_KEYBOARD)
-  if (video.shifted_up || video.shifted_up_delay)
+  SDL_Rect src_rect_up = { 0, 0,  video.width, video.height };
+  SDL_Rect dst_rect_up = dst_rect_screen;
+
+  if (video.shifted_up || video.shifted_up_delay.count)
   {
     int time_current = SDL_GetTicks();
     int pos = video.shifted_up_pos;
     int pos_last = video.shifted_up_pos_last;
 
-    if (!DelayReachedExt(&video.shifted_up_delay, video.shifted_up_delay_value,
-                        time_current))
+    if (!DelayReachedExt(&video.shifted_up_delay, time_current))
     {
-      int delay = time_current - video.shifted_up_delay;
-      int delay_value = video.shifted_up_delay_value;
+      int delay_count = time_current - video.shifted_up_delay.count;
+      int delay_value = video.shifted_up_delay.value;
 
-      pos = pos_last + (pos - pos_last) * delay / delay_value;
+      pos = pos_last + (pos - pos_last) * delay_count / delay_value;
     }
     else
     {
       video.shifted_up_pos_last = pos;
-      video.shifted_up_delay = 0;
+      video.shifted_up_delay.count = 0;
     }
 
-    SDL_Rect src_rect_up = { 0,    pos,  video.width, video.height - pos };
-    SDL_Rect dst_rect_up = { xoff, yoff, video.width, video.height - pos };
+    src_rect_up.y = pos;
+    src_rect_up.h = video.height - pos;
+    dst_rect_up.h = video.height - pos;
 
     if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET ||
        video.screen_rendering_mode == SPECIAL_RENDERING_DOUBLE)
@@ -221,7 +223,7 @@ static void UpdateScreenExt(SDL_Rect *rect, boolean with_frame_delay)
 
   // global synchronization point of the game to align video frame delay
   if (with_frame_delay)
-    WaitUntilDelayReached(&video.frame_delay, video.frame_delay_value);
+    WaitUntilDelayReached(&video.frame_delay);
 
   video.frame_counter++;
 
@@ -260,7 +262,7 @@ static void SDLSetWindowIcon(char *basename)
   // (setting the window icon on Mac OS X would replace the high-quality
   // dock icon with the currently smaller (and uglier) icon from file)
 
-#if !defined(PLATFORM_MACOSX)
+#if !defined(PLATFORM_MAC)
   char *filename = getCustomImageFilename(basename);
   SDL_Surface *surface;
 
@@ -297,19 +299,35 @@ static boolean equalSDLPixelFormat(SDL_PixelFormat *format1,
          format1->Bmask         == format2->Bmask);
 }
 
-static Pixel SDLGetColorKey(SDL_Surface *surface)
+static void SDLCopyColorKey(SDL_Surface *src_surface, SDL_Surface *dst_surface)
 {
   Pixel color_key;
+  Uint8 r, g, b;
+
+  // check if source surface has a color key
+  if (SDL_GetColorKey(src_surface, &color_key) == 0)
+  {
+    // get RGB values of color key of source surface
+    SDL_GetRGB(color_key, src_surface->format, &r, &g, &b);
 
-  if (SDL_GetColorKey(surface, &color_key) != 0)
-    return -1;
+    // get color key from RGB values in destination surface format
+    color_key = SDL_MapRGB(dst_surface->format, r, g, b);
 
-  return color_key;
+    // set color key in destination surface
+    SDL_SetColorKey(dst_surface, SET_TRANSPARENT_PIXEL, color_key);
+  }
+  else
+  {
+    // unset color key in destination surface
+    SDL_SetColorKey(dst_surface, UNSET_TRANSPARENT_PIXEL, 0);
+  }
 }
 
 static boolean SDLHasColorKey(SDL_Surface *surface)
 {
-  return (SDLGetColorKey(surface) != -1);
+  Pixel color_key;
+
+  return (SDL_GetColorKey(surface, &color_key) == 0);
 }
 
 static boolean SDLHasAlpha(SDL_Surface *surface)
@@ -322,7 +340,7 @@ static boolean SDLHasAlpha(SDL_Surface *surface)
   return (blend_mode == SDL_BLENDMODE_BLEND);
 }
 
-static void SDLSetAlpha(SDL_Surface *surface, boolean set, int alpha)
+void SDLSetAlpha(SDL_Surface *surface, boolean set, int alpha)
 {
   SDL_BlendMode blend_mode = (set ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE);
 
@@ -360,12 +378,11 @@ SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
   new_surface = SDL_ConvertSurface(surface, &format, 0);
 
   if (new_surface == NULL)
-    Error(ERR_EXIT, "SDL_ConvertSurface() failed: %s", SDL_GetError());
+    Fail("SDL_ConvertSurface() failed: %s", SDL_GetError());
 
   // workaround for a bug in SDL 2.0.12 (which does not convert the color key)
   if (SDLHasColorKey(surface) && !SDLHasColorKey(new_surface))
-    SDL_SetColorKey(new_surface, SET_TRANSPARENT_PIXEL,
-                   SDLGetColorKey(surface));
+    SDLCopyColorKey(surface, new_surface);
 
   return new_surface;
 }
@@ -401,8 +418,7 @@ static SDL_Texture *SDLCreateTextureFromSurface(SDL_Surface *surface)
   SDL_Texture *texture = SDL_CreateTextureFromSurface(sdl_renderer, surface);
 
   if (texture == NULL)
-    Error(ERR_EXIT, "SDL_CreateTextureFromSurface() failed: %s",
-         SDL_GetError());
+    Fail("SDL_CreateTextureFromSurface() failed: %s", SDL_GetError());
 
   return texture;
 }
@@ -443,7 +459,7 @@ void SDLInitVideoDisplay(void)
 
   // initialize SDL video
   if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
-    Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
+    Fail("SDL_InitSubSystem() failed: %s", SDL_GetError());
 
   // set default SDL depth
   video.default_depth = 32;    // (how to determine video depth in SDL2?)
@@ -467,7 +483,7 @@ static void SDLInitVideoBuffer_VideoBuffer(boolean fullscreen)
 
   // open SDL video output device (window or fullscreen mode)
   if (!SDLSetVideoMode(fullscreen))
-    Error(ERR_EXIT, "setting video mode failed");
+    Fail("setting video mode failed");
 
   // !!! SDL2 can only set the window icon if the window already exists !!!
   // set window icon
@@ -537,6 +553,7 @@ static boolean SDLCreateScreen(boolean fullscreen)
   int screen_height = video.screen_height;
   int surface_flags = (fullscreen ? surface_flags_fullscreen :
                       surface_flags_window);
+  int display_nr = options.display_nr;
 
   // default window size is unscaled
   video.window_width  = screen_width;
@@ -572,15 +589,14 @@ static boolean SDLCreateScreen(boolean fullscreen)
 
     if (sdl_window)
     {
-      SDL_DestroyWindow(sdl_window);
-      sdl_window = NULL;
+      SDL_SetWindowSize(sdl_window, video.window_width, video.window_height);
     }
   }
 
   if (sdl_window == NULL)
     sdl_window = SDL_CreateWindow(program.window_title,
-                                 SDL_WINDOWPOS_CENTERED,
-                                 SDL_WINDOWPOS_CENTERED,
+                                 SDL_WINDOWPOS_CENTERED_DISPLAY(display_nr),
+                                 SDL_WINDOWPOS_CENTERED_DISPLAY(display_nr),
                                  video.window_width,
                                  video.window_height,
                                  surface_flags);
@@ -780,7 +796,8 @@ void SDLSetWindowFullscreen(boolean fullscreen)
   {
     SDLSetWindowScaling(setup.window_scaling_percent);
     SDL_SetWindowPosition(sdl_window,
-                         SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+                         SDL_WINDOWPOS_CENTERED_DISPLAY(options.display_nr),
+                         SDL_WINDOWPOS_CENTERED_DISPLAY(options.display_nr));
 
     video.fullscreen_initial = FALSE;
   }
@@ -862,6 +879,8 @@ void SDLSetScreenProperties(void)
   SDLSetDisplaySize();
   SDLSetScreenSizeAndOffsets(video.width, video.height);
   SDLSetScreenSizeForRenderer(video.screen_width, video.screen_height);
+
+  SetOverlayGridSizeAndButtons();
 }
 
 void SDLSetScreenRenderingMode(char *screen_rendering_mode)
@@ -913,7 +932,7 @@ void SDLCreateBitmapContent(Bitmap *bitmap, int width, int height,
     SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth, 0,0,0, 0);
 
   if (surface == NULL)
-    Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
+    Fail("SDL_CreateRGBSurface() failed: %s", SDL_GetError());
 
   SDLSetNativeSurface(&surface);
 
@@ -1209,6 +1228,9 @@ void SDLFadeRectangle(int x, int y, int width, int height,
          draw_border_function();
 
        UpdateScreen_WithFrameDelay(&dst_rect2);
+
+       if (PendingEscapeKeyEvent())
+         break;
       }
     }
   }
@@ -1265,6 +1287,9 @@ void SDLFadeRectangle(int x, int y, int width, int height,
 
       // only update the region of the screen that is affected from fading
       UpdateScreen_WithFrameDelay(&dst_rect2);
+
+      if (PendingEscapeKeyEvent())
+       break;
     }
   }
   else         // fading in, fading out or cross-fading
@@ -1291,6 +1316,9 @@ void SDLFadeRectangle(int x, int y, int width, int height,
 
       // only update the region of the screen that is affected from fading
       UpdateScreen_WithFrameDelay(&dst_rect);
+
+      if (PendingEscapeKeyEvent())
+       break;
     }
   }
 
@@ -2237,7 +2265,7 @@ static SDL_Surface *SDLGetOpaqueSurface(SDL_Surface *surface)
     return NULL;
 
   if ((new_surface = SDLGetNativeSurface(surface)) == NULL)
-    Error(ERR_EXIT, "SDLGetNativeSurface() failed");
+    Fail("SDLGetNativeSurface() failed");
 
   // remove alpha channel from native non-transparent surface, if defined
   SDLSetAlpha(new_surface, FALSE, 0);
@@ -2268,8 +2296,7 @@ Bitmap *SDLZoomBitmap(Bitmap *src_bitmap, int dst_width, int dst_height)
 
   // set color key for zoomed surface from source surface, if defined
   if (SDLHasColorKey(src_surface))
-    SDL_SetColorKey(dst_surface, SET_TRANSPARENT_PIXEL,
-                   SDLGetColorKey(src_surface));
+    SDLCopyColorKey(src_surface, dst_surface);
 
   // create native non-transparent surface for opaque blitting
   dst_bitmap->surface = SDLGetOpaqueSurface(dst_surface);
@@ -2304,8 +2331,7 @@ Bitmap *SDLLoadImage(char *filename)
 
   // load image to temporary surface
   if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
-    Error(ERR_EXIT, "IMG_Load('%s') failed: %s", getBaseNamePtr(filename),
-         SDL_GetError());
+    Fail("IMG_Load('%s') failed: %s", getBaseNamePtr(filename), SDL_GetError());
 
   print_timestamp_time("IMG_Load");
 
@@ -2313,7 +2339,7 @@ Bitmap *SDLLoadImage(char *filename)
 
   // create native non-transparent surface for current image
   if ((new_bitmap->surface = SDLGetOpaqueSurface(sdl_image_tmp)) == NULL)
-    Error(ERR_EXIT, "SDLGetOpaqueSurface() failed");
+    Fail("SDLGetOpaqueSurface() failed");
 
   print_timestamp_time("SDLGetNativeSurface (opaque)");
 
@@ -2327,7 +2353,7 @@ Bitmap *SDLLoadImage(char *filename)
 
   // create native transparent surface for current image
   if ((new_bitmap->surface_masked = SDLGetNativeSurface(sdl_image_tmp)) == NULL)
-    Error(ERR_EXIT, "SDLGetNativeSurface() failed");
+    Fail("SDLGetNativeSurface() failed");
 
   print_timestamp_time("SDLGetNativeSurface (masked)");
 
@@ -2695,7 +2721,7 @@ void SDLInitJoysticks(void)
   boolean print_warning = !sdl_joystick_subsystem_initialized;
   char *mappings_file_base = getPath2(options.conf_directory,
                                      GAMECONTROLLER_BASENAME);
-  char *mappings_file_user = getPath2(getUserGameDataDir(),
+  char *mappings_file_user = getPath2(getMainUserGameDataDir(),
                                      GAMECONTROLLER_BASENAME);
   int num_mappings;
   int i;
@@ -2707,11 +2733,7 @@ void SDLInitJoysticks(void)
     SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
 
     if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0)
-    {
-      Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
-
-      return;
-    }
+      Fail("SDL_Init() failed: %s", SDL_GetError());
 
     num_mappings = SDL_GameControllerAddMappingsFromFile(mappings_file_base);