https://github.com/libsdl-org/Maelstrom/commit/f2938dad3defb92b9ccad46492b4ca474f7ee1b0
From f2938dad3defb92b9ccad46492b4ca474f7ee1b0 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 15 Sep 2012 00:54:08 -0700
Subject: [PATCH] Added support for resizable windows
---
screenlib/SDL_FrameBuf.cpp | 105 +++++++++++++++++++++++++++++--------
screenlib/SDL_FrameBuf.h | 48 +++++++++++------
screenlib/UIManager.cpp | 19 +++++++
screenlib/UIPanel.h | 1 +
4 files changed, 134 insertions(+), 39 deletions(-)
diff --git a/screenlib/SDL_FrameBuf.cpp b/screenlib/SDL_FrameBuf.cpp
index 6e8d3bad..433e93cc 100644
--- a/screenlib/SDL_FrameBuf.cpp
+++ b/screenlib/SDL_FrameBuf.cpp
@@ -45,14 +45,14 @@ int
FrameBuf:: Init(int width, int height, Uint32 window_flags, Uint32 render_flags,
SDL_Color *colors, SDL_Surface *icon)
{
- int w, h;
-
#ifdef FAST_ITERATION
window_flags &= ~SDL_WINDOW_FULLSCREEN;
#endif
-#ifdef __IPHONEOS__
- window_flags |= SDL_WINDOW_FULLSCREEN;
-#endif
+//#ifdef __IPHONEOS__
+// window_flags |= SDL_WINDOW_FULLSCREEN;
+//#endif
+ window_flags |= SDL_WINDOW_RESIZABLE;
+
window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, window_flags);
if (!window) {
SetError("Couldn't create %dx%d window: %s",
@@ -66,6 +66,9 @@ FrameBuf:: Init(int width, int height, Uint32 window_flags, Uint32 render_flags,
return(-1);
}
+ SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
+
+/*
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, width, height);
if (!texture) {
SetError("Couldn't create target texture: %s", SDL_GetError());
@@ -76,8 +79,7 @@ FrameBuf:: Init(int width, int height, Uint32 window_flags, Uint32 render_flags,
SetError("Couldn't set render target: %s", SDL_GetError());
return(-1);
}
-
- SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
+*/
/* Set the icon, if any */
if ( icon ) {
@@ -85,16 +87,7 @@ FrameBuf:: Init(int width, int height, Uint32 window_flags, Uint32 render_flags,
}
/* Set the output area */
- SDL_GetWindowSize(window, &w, &h);
- output.w = w;
- output.h = (height * w)/width;
- output.x = (w - output.w) / 2;
- output.y = (h - output.h) / 2;
-
- clip.x = rect.x = 0;
- clip.y = rect.y = 0;
- clip.w = rect.w = width;
- clip.h = rect.h = height;
+ UpdateWindowSize(width, height);
/* Copy the image colormap */
if ( colors ) {
@@ -127,6 +120,35 @@ FrameBuf:: SetPalette(SDL_Color *colors)
}
}
+void
+FrameBuf::ProcessEvent(SDL_Event *event)
+{
+ switch (event->type) {
+ case SDL_WINDOWEVENT:
+ if (event->window.event == SDL_WINDOWEVENT_RESIZED) {
+ SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
+ int w, h;
+
+ SDL_GetWindowSize(window, &w, &h);
+ UpdateWindowSize(w, h);
+ }
+ break;
+ case SDL_MOUSEMOTION:
+ event->motion.x -= output.x;
+ event->motion.y -= output.y;
+ event->motion.x = (event->motion.x * rect.w) / output.w;
+ event->motion.y = (event->motion.y * rect.h) / output.h;
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ event->button.x -= output.x;
+ event->button.y -= output.y;
+ event->motion.x = (event->motion.x * rect.w) / output.w;
+ event->motion.y = (event->motion.y * rect.h) / output.h;
+ break;
+ }
+}
+
// This routine or something like it should probably go in SDL
bool
FrameBuf::ConvertTouchCoordinates(const SDL_TouchFingerEvent &finger, int *x, int *y)
@@ -199,17 +221,27 @@ FrameBuf:: QueueBlit(int dstx, int dsty, SDL_Texture *src,
SDL_RenderCopy(renderer, src, &srcrect, &dstrect);
}
+void
+FrameBuf:: StretchBlit(const SDL_Rect *dstrect, SDL_Texture *src, const SDL_Rect *srcrect)
+{
+ SDL_RenderCopy(renderer, src, srcrect, dstrect);
+}
+
void
FrameBuf:: Update(void)
{
/* Copy from our render texture to the screen and show it! */
- SDL_SetRenderTarget(renderer, NULL);
- SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
- SDL_RenderClear(renderer);
- SDL_RenderCopy(renderer, texture, NULL, &output);
+ if (texture) {
+ SDL_SetRenderTarget(renderer, NULL);
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
+ SDL_RenderClear(renderer);
+ SDL_RenderCopy(renderer, texture, NULL, &output);
+ }
SDL_RenderPresent(renderer);
- SDL_SetRenderTarget(renderer, texture);
+ if (texture) {
+ SDL_SetRenderTarget(renderer, texture);
+ }
}
void
@@ -339,3 +371,32 @@ FrameBuf:: FreeImage(SDL_Texture *image)
{
SDL_DestroyTexture(image);
}
+
+SDL_Texture *
+FrameBuf:: CreateRenderTarget(int w, int h)
+{
+ SDL_Texture *texture;
+
+ texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, w, h);
+ if (!texture) {
+ SetError("Couldn't create target texture: %s", SDL_GetError());
+ return NULL;
+ }
+ return texture;
+}
+
+int
+FrameBuf:: SetRenderTarget(SDL_Texture *texture)
+{
+ if (SDL_SetRenderTarget(renderer, texture) < 0) {
+ SetError("Couldn't set render target: %s", SDL_GetError());
+ return(-1);
+ }
+ return 0;
+}
+
+void
+FrameBuf:: FreeRenderTarget(SDL_Texture *texture)
+{
+ SDL_DestroyTexture(texture);
+}
diff --git a/screenlib/SDL_FrameBuf.h b/screenlib/SDL_FrameBuf.h
index a0a4d779..01fecb70 100644
--- a/screenlib/SDL_FrameBuf.h
+++ b/screenlib/SDL_FrameBuf.h
@@ -81,23 +81,8 @@ class FrameBuf : public ErrorBase {
}
return result;
}
- void ProcessEvent(SDL_Event *event) {
- switch (event->type) {
- case SDL_MOUSEMOTION:
- event->motion.x -= output.x;
- event->motion.y -= output.y;
- event->motion.x = (event->motion.x * rect.w) / output.w;
- event->motion.y = (event->motion.y * rect.h) / output.h;
- break;
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONUP:
- event->button.x -= output.x;
- event->button.y -= output.y;
- event->motion.x = (event->motion.x * rect.w) / output.w;
- event->motion.y = (event->motion.y * rect.h) / output.h;
- break;
- }
- }
+ void ProcessEvent(SDL_Event *event);
+
bool ConvertTouchCoordinates(const SDL_TouchFingerEvent &finger, int *x, int *y);
void EnableTextInput();
@@ -130,6 +115,8 @@ class FrameBuf : public ErrorBase {
SDL_QueryTexture(src, NULL, NULL, &w, &h);
QueueBlit(x, y, src, 0, 0, w, h, do_clip);
}
+ void StretchBlit(const SDL_Rect *dstrect, SDL_Texture *src, const SDL_Rect *srcrect);
+
void Update(void);
void FadeOut(void) {
if (!faded) {
@@ -196,6 +183,12 @@ class FrameBuf : public ErrorBase {
}
void FreeImage(SDL_Texture *image);
+ /* Create a render target */
+ SDL_Texture *CreateRenderTarget(int w, int h);
+ int SetRenderTarget(SDL_Texture *texture);
+ void FreeRenderTarget(SDL_Texture *texture);
+
+
/* Screen dump routines */
int ScreenDump(const char *prefix, int x, int y, int w, int h);
@@ -224,6 +217,27 @@ class FrameBuf : public ErrorBase {
SDL_Rect clip;
SDL_Rect output;
+ void UpdateWindowSize(int width, int height) {
+ int w, h;
+ SDL_Rect viewport;
+
+ SDL_GetWindowSize(window, &w, &h);
+ output.w = w;
+ output.h = (height * w)/width;
+ output.x = (w - output.w) / 2;
+ output.y = (h - output.h) / 2;
+
+ clip.x = rect.x = 0;
+ clip.y = rect.y = 0;
+ clip.w = rect.w = width;
+ clip.h = rect.h = height;
+
+ viewport.x = 0;
+ viewport.y = 0;
+ viewport.w = w;
+ viewport.h = h;
+ SDL_RenderSetViewport(renderer, &viewport);
+ }
void UpdateDrawColor(Uint32 color) {
Uint8 r, g, b;
r = (color >> 16) & 0xFF;
diff --git a/screenlib/UIManager.cpp b/screenlib/UIManager.cpp
index 84b98f44..bf9ec5cb 100644
--- a/screenlib/UIManager.cpp
+++ b/screenlib/UIManager.cpp
@@ -246,6 +246,25 @@ UIManager::Draw(bool fullUpdate)
bool
UIManager::HandleEvent(const SDL_Event &event)
{
+ if (event.type == SDL_WINDOWEVENT &&
+ event.window.event == SDL_WINDOWEVENT_RESIZED) {
+ SDL_Window *window = SDL_GetWindowFromID(event.window.windowID);
+ int w, h;
+ SDL_Rect clip;
+
+ SDL_GetWindowSize(window, &w, &h);
+
+ // Reset the clip rectangle
+ clip.x = 0;
+ clip.y = 0;
+ clip.w = w;
+ clip.h = h;
+ m_screen->ClipBlit(&clip);
+
+ // Resize to match window size
+ SetSize(w, h);
+ }
+
for (unsigned i = m_visible.length(); i--; ) {
UIPanel *panel = m_visible[i];
diff --git a/screenlib/UIPanel.h b/screenlib/UIPanel.h
index ed48467a..2f603c6f 100644
--- a/screenlib/UIPanel.h
+++ b/screenlib/UIPanel.h
@@ -37,6 +37,7 @@ class UIPanelDelegate
{
public:
UIPanelDelegate(UIPanel *panel) { m_panel = panel; }
+ virtual ~UIPanelDelegate() { }
// This is called after the panel is loaded
virtual bool OnLoad() { return true; }