Added SDL_SetWindowResizable().  (thanks, Ethan!)
diff --git a/include/SDL_video.h b/include/SDL_video.h
index 0e138a7..0d5c8ad 100644
--- a/include/SDL_video.h
+++ b/include/SDL_video.h
@@ -83,6 +83,7 @@
  *  \sa SDL_SetWindowPosition()
  *  \sa SDL_SetWindowSize()
  *  \sa SDL_SetWindowBordered()
+ *  \sa SDL_SetWindowResizable()
  *  \sa SDL_SetWindowTitle()
  *  \sa SDL_ShowWindow()
  */
@@ -707,6 +708,23 @@
                                                    SDL_bool bordered);
 
 /**
+ *  \brief Set the user-resizable state of a window.
+ *
+ *  This will add or remove the window's SDL_WINDOW_RESIZABLE flag and
+ *  allow/disallow user resizing of the window. This is a no-op if the
+ *  window's resizable state already matches the requested state.
+ *
+ *  \param window The window of which to change the resizable state.
+ *  \param resizable SDL_TRUE to allow resizing, SDL_FALSE to disallow.
+ *
+ *  \note You can't change the resizable state of a fullscreen window.
+ *
+ *  \sa SDL_GetWindowFlags()
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowResizable(SDL_Window * window,
+                                                    SDL_bool resizable);
+
+/**
  *  \brief Show a window.
  *
  *  \sa SDL_HideWindow()
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index dfde8e7..8ae86b0 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -606,3 +606,4 @@
 #define SDL_RenderSetIntegerScale SDL_RenderSetIntegerScale_REAL
 #define SDL_RenderGetIntegerScale SDL_RenderGetIntegerScale_REAL
 #define SDL_DequeueAudio SDL_DequeueAudio_REAL
+#define SDL_SetWindowResizable SDL_SetWindowResizable_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index dabda3d..b2df062 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -640,3 +640,4 @@
 SDL_DYNAPI_PROC(int,SDL_RenderSetIntegerScale,(SDL_Renderer *a, SDL_bool b),(a,b),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_RenderGetIntegerScale,(SDL_Renderer *a),(a),return)
 SDL_DYNAPI_PROC(Uint32,SDL_DequeueAudio,(SDL_AudioDeviceID a, void *b, Uint32 c),(a,b,c),return)
+SDL_DYNAPI_PROC(void,SDL_SetWindowResizable,(SDL_Window *a, SDL_bool b),(a,b),)
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 0b1133b..cd2ed2a 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -219,6 +219,7 @@
     void (*MinimizeWindow) (_THIS, SDL_Window * window);
     void (*RestoreWindow) (_THIS, SDL_Window * window);
     void (*SetWindowBordered) (_THIS, SDL_Window * window, SDL_bool bordered);
+    void (*SetWindowResizable) (_THIS, SDL_Window * window, SDL_bool resizable);
     void (*SetWindowFullscreen) (_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
     int (*SetWindowGammaRamp) (_THIS, SDL_Window * window, const Uint16 * ramp);
     int (*GetWindowGammaRamp) (_THIS, SDL_Window * window, Uint16 * ramp);
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 499e400..c768f6a 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -1842,6 +1842,24 @@
 }
 
 void
+SDL_SetWindowResizable(SDL_Window * window, SDL_bool resizable)
+{
+    CHECK_WINDOW_MAGIC(window,);
+    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
+        const int want = (resizable != SDL_FALSE);  /* normalize the flag. */
+        const int have = ((window->flags & SDL_WINDOW_RESIZABLE) != 0);
+        if ((want != have) && (_this->SetWindowResizable)) {
+            if (want) {
+                window->flags |= SDL_WINDOW_RESIZABLE;
+            } else {
+                window->flags &= ~SDL_WINDOW_RESIZABLE;
+            }
+            _this->SetWindowResizable(_this, window, (SDL_bool) want);
+        }
+    }
+}
+
+void
 SDL_SetWindowSize(SDL_Window * window, int w, int h)
 {
     CHECK_WINDOW_MAGIC(window,);
diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m
index ddf10e2..76d558e 100644
--- a/src/video/cocoa/SDL_cocoavideo.m
+++ b/src/video/cocoa/SDL_cocoavideo.m
@@ -96,6 +96,7 @@
     device->MinimizeWindow = Cocoa_MinimizeWindow;
     device->RestoreWindow = Cocoa_RestoreWindow;
     device->SetWindowBordered = Cocoa_SetWindowBordered;
+    device->SetWindowResizable = Cocoa_SetWindowResizable;
     device->SetWindowFullscreen = Cocoa_SetWindowFullscreen;
     device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
     device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h
index 4e2f7ea..a32de83 100644
--- a/src/video/cocoa/SDL_cocoawindow.h
+++ b/src/video/cocoa/SDL_cocoawindow.h
@@ -133,6 +133,7 @@
 extern void Cocoa_MinimizeWindow(_THIS, SDL_Window * window);
 extern void Cocoa_RestoreWindow(_THIS, SDL_Window * window);
 extern void Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
 extern void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
 extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
 extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index 37f7b7f..25c98a9 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -1492,6 +1492,20 @@
     }
 }}
 
+void
+Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{ @autoreleasepool
+{
+    /* Don't set this if we're in a space!
+     * The window will get permanently stuck if resizable is false.
+     * -flibit
+     */
+    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+    Cocoa_WindowListener *listener = data->listener;
+    if (![listener isInFullscreenSpace]) {
+        SetWindowStyle(window, GetWindowStyle(window));
+    }
+}}
 
 void
 Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
diff --git a/src/video/haiku/SDL_BWin.h b/src/video/haiku/SDL_BWin.h
index dade664..b3b94dc 100644
--- a/src/video/haiku/SDL_BWin.h
+++ b/src/video/haiku/SDL_BWin.h
@@ -56,6 +56,7 @@
     BWIN_RESTORE_WINDOW,
     BWIN_SET_TITLE,
     BWIN_SET_BORDERED,
+    BWIN_SET_RESIZABLE,
     BWIN_FULLSCREEN
 };
 
@@ -378,6 +379,9 @@
             case BWIN_SET_BORDERED:
                 _SetBordered(message);
                 break;
+            case BWIN_SET_RESIZABLE:
+                _SetResizable(message);
+                break;
             case BWIN_SHOW_WINDOW:
                 Show();
                 break;
@@ -568,6 +572,18 @@
         SetLook(bEnabled ? B_BORDERED_WINDOW_LOOK : B_NO_BORDER_WINDOW_LOOK);
     }
 
+    void _SetResizable(BMessage *msg) {
+        bool bEnabled;
+        if(msg->FindBool("window-resizable", &bEnabled) != B_OK) {
+            return;
+        }
+        if (bEnabled) {
+            SetFlags(GetFlags() & ~(B_NOT_RESIZABLE | B_NOT_ZOOMABLE));
+        } else {
+            SetFlags(GetFlags() | (B_NOT_RESIZABLE | B_NOT_ZOOMABLE));
+        }
+    }
+
     void _Restore() {
         if(IsMinimized()) {
             Minimize(false);
diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc
index 8c243b7..8986c60 100644
--- a/src/video/haiku/SDL_bvideo.cc
+++ b/src/video/haiku/SDL_bvideo.cc
@@ -81,6 +81,7 @@
     device->MinimizeWindow = BE_MinimizeWindow;
     device->RestoreWindow = BE_RestoreWindow;
     device->SetWindowBordered = BE_SetWindowBordered;
+    device->SetWindowResizable = BE_SetWindowResizable;
     device->SetWindowFullscreen = BE_SetWindowFullscreen;
     device->SetWindowGammaRamp = BE_SetWindowGammaRamp;
     device->GetWindowGammaRamp = BE_GetWindowGammaRamp;
diff --git a/src/video/haiku/SDL_bwindow.cc b/src/video/haiku/SDL_bwindow.cc
index 287eac9..a35471d 100644
--- a/src/video/haiku/SDL_bwindow.cc
+++ b/src/video/haiku/SDL_bwindow.cc
@@ -145,6 +145,12 @@
 	_ToBeWin(window)->PostMessage(&msg);
 }
 
+void BE_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable) {
+	BMessage msg(BWIN_SET_RESIZABLE);
+	msg.AddBool("window-resizable", resizable != SDL_FALSE);
+	_ToBeWin(window)->PostMessage(&msg);
+}
+
 void BE_ShowWindow(_THIS, SDL_Window * window) {
 	BMessage msg(BWIN_SHOW_WINDOW);
 	_ToBeWin(window)->PostMessage(&msg);
diff --git a/src/video/haiku/SDL_bwindow.h b/src/video/haiku/SDL_bwindow.h
index f64530a..388443d 100644
--- a/src/video/haiku/SDL_bwindow.h
+++ b/src/video/haiku/SDL_bwindow.h
@@ -39,6 +39,7 @@
 extern void BE_MinimizeWindow(_THIS, SDL_Window * window);
 extern void BE_RestoreWindow(_THIS, SDL_Window * window);
 extern void BE_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void BE_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
 extern void BE_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
 extern int BE_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
 extern int BE_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
diff --git a/src/video/mir/SDL_mirvideo.c b/src/video/mir/SDL_mirvideo.c
index 886cee7..6a8f9e4 100644
--- a/src/video/mir/SDL_mirvideo.c
+++ b/src/video/mir/SDL_mirvideo.c
@@ -186,6 +186,7 @@
     device->SetWindowIcon        = NULL;
     device->RaiseWindow          = NULL;
     device->SetWindowBordered    = NULL;
+    device->SetWindowResizable   = NULL;
     device->OnWindowEnter        = NULL;
     device->SetWindowPosition    = NULL;
 
diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c
index 41100fb..21f63a0 100644
--- a/src/video/windows/SDL_windowsvideo.c
+++ b/src/video/windows/SDL_windowsvideo.c
@@ -145,6 +145,7 @@
     device->MinimizeWindow = WIN_MinimizeWindow;
     device->RestoreWindow = WIN_RestoreWindow;
     device->SetWindowBordered = WIN_SetWindowBordered;
+    device->SetWindowResizable = WIN_SetWindowResizable;
     device->SetWindowFullscreen = WIN_SetWindowFullscreen;
     device->SetWindowGammaRamp = WIN_SetWindowGammaRamp;
     device->GetWindowGammaRamp = WIN_GetWindowGammaRamp;
diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c
index b8f24db..fe52a54 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -520,6 +520,22 @@
 }
 
 void
+WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{
+    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+    HWND hwnd = data->hwnd;
+    DWORD style = GetWindowLong(hwnd, GWL_STYLE);
+
+    if (resizable) {
+        style |= STYLE_RESIZABLE;
+    } else {
+        style &= ~STYLE_RESIZABLE;
+    }
+
+    SetWindowLong(hwnd, GWL_STYLE, style);
+}
+
+void
 WIN_RestoreWindow(_THIS, SDL_Window * window)
 {
     SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h
index 0f6a87e..7d50ba6 100644
--- a/src/video/windows/SDL_windowswindow.h
+++ b/src/video/windows/SDL_windowswindow.h
@@ -64,6 +64,7 @@
 extern void WIN_MinimizeWindow(_THIS, SDL_Window * window);
 extern void WIN_RestoreWindow(_THIS, SDL_Window * window);
 extern void WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
 extern void WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
 extern int WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
 extern int WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c
index b2136da..4be6b37 100644
--- a/src/video/x11/SDL_x11video.c
+++ b/src/video/x11/SDL_x11video.c
@@ -243,6 +243,7 @@
     device->MinimizeWindow = X11_MinimizeWindow;
     device->RestoreWindow = X11_RestoreWindow;
     device->SetWindowBordered = X11_SetWindowBordered;
+    device->SetWindowResizable = X11_SetWindowResizable;
     device->SetWindowFullscreen = X11_SetWindowFullscreen;
     device->SetWindowGammaRamp = X11_SetWindowGammaRamp;
     device->SetWindowGrab = X11_SetWindowGrab;
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index 8659961..db10a89 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -982,6 +982,44 @@
 }
 
 void
+X11_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{
+    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+    Display *display = data->videodata->display;
+
+    XSizeHints *sizehints = X11_XAllocSizeHints();
+    long userhints;
+
+    X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
+
+    if (resizable) {
+        /* FIXME: Is there a better way to get max window size from X? -flibit */
+        const int maxsize = 0x7FFFFFFF;
+        sizehints->min_width = window->min_w;
+        sizehints->min_height = window->min_h;
+        sizehints->max_width = (window->max_w == 0) ? maxsize : window->max_w;
+        sizehints->max_height = (window->max_h == 0) ? maxsize : window->max_h;
+    } else {
+        sizehints->min_width = window->w;
+        sizehints->min_height = window->h;
+        sizehints->max_width = window->w;
+        sizehints->max_height = window->h;
+    }
+    sizehints->flags |= PMinSize | PMaxSize;
+
+    X11_XSetWMNormalHints(display, data->xwindow, sizehints);
+
+    X11_XFree(sizehints);
+
+    /* See comment in X11_SetWindowSize. */
+    X11_XResizeWindow(display, data->xwindow, window->w, window->h);
+    X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
+    X11_XRaiseWindow(display, data->xwindow);
+
+    X11_XFlush(display);
+}
+
+void
 X11_ShowWindow(_THIS, SDL_Window * window)
 {
     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h
index 5c5f7d5..50a739d 100644
--- a/src/video/x11/SDL_x11window.h
+++ b/src/video/x11/SDL_x11window.h
@@ -96,6 +96,7 @@
 extern void X11_MinimizeWindow(_THIS, SDL_Window * window);
 extern void X11_RestoreWindow(_THIS, SDL_Window * window);
 extern void X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void X11_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
 extern void X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
 extern int X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
 extern void X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);