Added SDL_SetWindowOpacity() and SDL_GetWindowOpacity(). This is currently implemented for X11, Cocoa, Windows, and DirectFB. This patch is based on work in Unreal Engine 4's fork of SDL, compliments of Epic Games.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
diff --git a/include/SDL_video.h b/include/SDL_video.h
index b439ef9..f4a0269 100644
--- a/include/SDL_video.h
+++ b/include/SDL_video.h
@@ -846,6 +846,34 @@ extern DECLSPEC int SDLCALL SDL_SetWindowBrightness(SDL_Window * window, float b
extern DECLSPEC float SDLCALL SDL_GetWindowBrightness(SDL_Window * window);
/**
+ * \brief Set the opacity for a window
+ *
+ * \param window The window which will be made transparent or opaque
+ * \param opacity Opacity (0.0f - transparent, 1.0f - opaque) This will be
+ * clamped internally between 0.0f and 1.0f.
+ *
+ * \return 0 on success, or -1 if setting the opacity isn't supported.
+ *
+ * \sa SDL_GetWindowOpacity()
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowOpacity(SDL_Window * window, float opacity);
+
+/**
+ * \brief Get the opacity of a window.
+ *
+ * If transparency isn't supported on this platform, opacity will be reported
+ * as 1.0f without error.
+ *
+ * \param window The window in question.
+ * \param opacity Opacity (0.0f - transparent, 1.0f - opaque)
+ *
+ * \return 0 on success, or -1 on error (invalid window, etc).
+ *
+ * \sa SDL_SetWindowOpacity()
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowOpacity(SDL_Window * window, float * out_opacity);
+
+/**
* \brief Set the gamma ramp for a window.
*
* \param window The window for which the gamma ramp should be set.
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index a4dcf78..1c0a34d 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -599,3 +599,5 @@
#define SDL_JoystickFromInstanceID SDL_JoystickFromInstanceID_REAL
#define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL
#define SDL_GetWindowBordersSize SDL_GetWindowBordersSize_REAL
+#define SDL_SetWindowOpacity SDL_SetWindowOpacity_REAL
+#define SDL_GetWindowOpacity SDL_GetWindowOpacity_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index a0191c4..563b2a4 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -633,3 +633,5 @@ SDL_DYNAPI_PROC(SDL_GameController*,SDL_GameControllerFromInstanceID,(SDL_Joysti
SDL_DYNAPI_PROC(SDL_Joystick*,SDL_JoystickFromInstanceID,(SDL_JoystickID a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetDisplayUsableBounds,(int a, SDL_Rect *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_GetWindowBordersSize,(SDL_Window *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return)
+SDL_DYNAPI_PROC(int,SDL_SetWindowOpacity,(SDL_Window *a, float b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_GetWindowOpacity,(SDL_Window *a, float *b),(a,b),return)
diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c
index fee249c..8607cf9 100644
--- a/src/test/SDL_test_common.c
+++ b/src/test/SDL_test_common.c
@@ -1368,6 +1368,24 @@ SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
}
}
break;
+ case SDLK_o:
+ if (withControl) {
+ /* Ctrl-O (or Ctrl-Shift-O) changes window opacity. */
+ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+ if (window) {
+ float opacity;
+ if (SDL_GetWindowOpacity(window, &opacity) == 0) {
+ if (withShift) {
+ opacity += 0.20f;
+ } else {
+ opacity -= 0.20f;
+ }
+ SDL_SetWindowOpacity(window, opacity);
+ }
+ }
+ }
+ break;
+
case SDLK_c:
if (withControl) {
/* Ctrl-C copy awesome text! */
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 25436ca..b8320f3 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -86,6 +86,8 @@ struct SDL_Window
SDL_DisplayMode fullscreen_mode;
+ float opacity;
+
float brightness;
Uint16 *gamma;
Uint16 *saved_gamma; /* (just offset into gamma) */
@@ -207,6 +209,7 @@ struct SDL_VideoDevice
void (*SetWindowMinimumSize) (_THIS, SDL_Window * window);
void (*SetWindowMaximumSize) (_THIS, SDL_Window * window);
int (*GetWindowBordersSize) (_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right);
+ int (*SetWindowOpacity) (_THIS, SDL_Window * window, float opacity);
void (*ShowWindow) (_THIS, SDL_Window * window);
void (*HideWindow) (_THIS, SDL_Window * window);
void (*RaiseWindow) (_THIS, SDL_Window * window);
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 826e9fd..d764e22 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -1415,6 +1415,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
}
window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
window->last_fullscreen_flags = window->flags;
+ window->opacity = 1.0f;
window->brightness = 1.0f;
window->next = _this->windows;
window->is_destroying = SDL_FALSE;
@@ -1475,6 +1476,7 @@ SDL_CreateWindowFrom(const void *data)
window->flags = SDL_WINDOW_FOREIGN;
window->last_fullscreen_flags = window->flags;
window->is_destroying = SDL_FALSE;
+ window->opacity = 1.0f;
window->brightness = 1.0f;
window->next = _this->windows;
if (_this->windows) {
@@ -2191,6 +2193,42 @@ SDL_GetWindowBrightness(SDL_Window * window)
}
int
+SDL_SetWindowOpacity(SDL_Window * window, float opacity)
+{
+ int retval;
+ CHECK_WINDOW_MAGIC(window, -1);
+
+ if (!_this->SetWindowOpacity) {
+ return SDL_Unsupported();
+ }
+
+ if (opacity < 0.0f) {
+ opacity = 0.0f;
+ } else if (opacity > 1.0f) {
+ opacity = 1.0f;
+ }
+
+ retval = _this->SetWindowOpacity(_this, window, opacity);
+ if (retval == 0) {
+ window->opacity = opacity;
+ }
+
+ return retval;
+}
+
+int
+SDL_GetWindowOpacity(SDL_Window * window, float * out_opacity)
+{
+ CHECK_WINDOW_MAGIC(window, -1);
+
+ if (out_opacity) {
+ *out_opacity = window->opacity;
+ }
+
+ return 0;
+}
+
+int
SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
const Uint16 * green,
const Uint16 * blue)
diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m
index dbee221..dd3cf6b 100644
--- a/src/video/cocoa/SDL_cocoavideo.m
+++ b/src/video/cocoa/SDL_cocoavideo.m
@@ -87,6 +87,7 @@ Cocoa_CreateDevice(int devindex)
device->SetWindowSize = Cocoa_SetWindowSize;
device->SetWindowMinimumSize = Cocoa_SetWindowMinimumSize;
device->SetWindowMaximumSize = Cocoa_SetWindowMaximumSize;
+ device->SetWindowOpacity = Cocoa_SetWindowOpacity;
device->ShowWindow = Cocoa_ShowWindow;
device->HideWindow = Cocoa_HideWindow;
device->RaiseWindow = Cocoa_RaiseWindow;
diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h
index 1037bad..4e2f7ea 100644
--- a/src/video/cocoa/SDL_cocoawindow.h
+++ b/src/video/cocoa/SDL_cocoawindow.h
@@ -125,6 +125,7 @@ extern void Cocoa_SetWindowPosition(_THIS, SDL_Window * window);
extern void Cocoa_SetWindowSize(_THIS, SDL_Window * window);
extern void Cocoa_SetWindowMinimumSize(_THIS, SDL_Window * window);
extern void Cocoa_SetWindowMaximumSize(_THIS, SDL_Window * window);
+extern int Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
extern void Cocoa_ShowWindow(_THIS, SDL_Window * window);
extern void Cocoa_HideWindow(_THIS, SDL_Window * window);
extern void Cocoa_RaiseWindow(_THIS, SDL_Window * window);
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index a74d97f..16b617b 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -1782,6 +1782,14 @@ Cocoa_SetWindowHitTest(SDL_Window * window, SDL_bool enabled)
return 0; /* just succeed, the real work is done elsewhere. */
}
+int
+Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ [data->nswindow setAlphaValue:opacity];
+ return 0;
+}
+
#endif /* SDL_VIDEO_DRIVER_COCOA */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/directfb/SDL_DirectFB_video.c b/src/video/directfb/SDL_DirectFB_video.c
index 5579759..d339dd7 100644
--- a/src/video/directfb/SDL_DirectFB_video.c
+++ b/src/video/directfb/SDL_DirectFB_video.c
@@ -121,6 +121,7 @@ DirectFB_CreateDevice(int devindex)
device->SetWindowIcon = DirectFB_SetWindowIcon;
device->SetWindowPosition = DirectFB_SetWindowPosition;
device->SetWindowSize = DirectFB_SetWindowSize;
+ device->SetWindowOpacity = DirectFB_SetWindowOpacity;
device->ShowWindow = DirectFB_ShowWindow;
device->HideWindow = DirectFB_HideWindow;
device->RaiseWindow = DirectFB_RaiseWindow;
diff --git a/src/video/directfb/SDL_DirectFB_window.c b/src/video/directfb/SDL_DirectFB_window.c
index 3b8b45d..40bbe6a 100644
--- a/src/video/directfb/SDL_DirectFB_window.c
+++ b/src/video/directfb/SDL_DirectFB_window.c
@@ -529,4 +529,17 @@ DirectFB_AdjustWindowSurface(SDL_Window * window)
return;
}
+int
+DirectFB_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+ const Uint8 alpha = (Uint8) ((unsigned int) (opacity * 255.0f));
+ SDL_DFB_WINDOWDATA(window);
+ SDL_DFB_CHECKERR(windata->dfbwin->SetOpacity(windata->dfbwin, alpha));
+ windata->opacity = alpha;
+ return 0;
+
+error:
+ return -1;
+}
+
#endif /* SDL_VIDEO_DRIVER_DIRECTFB */
diff --git a/src/video/directfb/SDL_DirectFB_window.h b/src/video/directfb/SDL_DirectFB_window.h
index 658cc87..4b99708 100644
--- a/src/video/directfb/SDL_DirectFB_window.h
+++ b/src/video/directfb/SDL_DirectFB_window.h
@@ -75,6 +75,7 @@ extern SDL_bool DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo *info);
extern void DirectFB_AdjustWindowSurface(SDL_Window * window);
+extern int DirectFB_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
#endif /* _SDL_directfb_window_h */
diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c
index dc444bc..41100fb 100644
--- a/src/video/windows/SDL_windowsvideo.c
+++ b/src/video/windows/SDL_windowsvideo.c
@@ -137,6 +137,7 @@ WIN_CreateDevice(int devindex)
device->SetWindowIcon = WIN_SetWindowIcon;
device->SetWindowPosition = WIN_SetWindowPosition;
device->SetWindowSize = WIN_SetWindowSize;
+ device->SetWindowOpacity = WIN_SetWindowOpacity;
device->ShowWindow = WIN_ShowWindow;
device->HideWindow = WIN_HideWindow;
device->RaiseWindow = WIN_RaiseWindow;
diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c
index 26683a0..b8f24db 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -826,6 +826,39 @@ WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
return 0; /* just succeed, the real work is done elsewhere. */
}
+int
+WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+ const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ const HWND hwnd = data->hwnd;
+ const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
+
+ SDL_assert(style != 0);
+
+ if (opacity == 1.0f) {
+ /* want it fully opaque, just mark it unlayered if necessary. */
+ if (style & WS_EX_LAYERED) {
+ if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_LAYERED) == 0) {
+ return WIN_SetError("SetWindowLong()");
+ }
+ }
+ } else {
+ const BYTE alpha = (BYTE) ((int) (opacity * 255.0f));
+ /* want it transparent, mark it layered if necessary. */
+ if ((style & WS_EX_LAYERED) == 0) {
+ if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_LAYERED) == 0) {
+ return WIN_SetError("SetWindowLong()");
+ }
+ }
+
+ if (SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA) == 0) {
+ return WIN_SetError("SetLayeredWindowAttributes()");
+ }
+ }
+
+ return 0;
+}
+
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h
index f91aa0e..e7b13c7 100644
--- a/src/video/windows/SDL_windowswindow.h
+++ b/src/video/windows/SDL_windowswindow.h
@@ -56,6 +56,7 @@ extern void WIN_SetWindowTitle(_THIS, SDL_Window * window);
extern void WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
extern void WIN_SetWindowPosition(_THIS, SDL_Window * window);
extern void WIN_SetWindowSize(_THIS, SDL_Window * window);
+extern int WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
extern void WIN_ShowWindow(_THIS, SDL_Window * window);
extern void WIN_HideWindow(_THIS, SDL_Window * window);
extern void WIN_RaiseWindow(_THIS, SDL_Window * window);
diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c
index e085cf7..b3ff291 100644
--- a/src/video/x11/SDL_x11video.c
+++ b/src/video/x11/SDL_x11video.c
@@ -233,6 +233,7 @@ X11_CreateDevice(int devindex)
device->SetWindowMinimumSize = X11_SetWindowMinimumSize;
device->SetWindowMaximumSize = X11_SetWindowMaximumSize;
device->GetWindowBordersSize = X11_GetWindowBordersSize;
+ device->SetWindowOpacity = X11_SetWindowOpacity;
device->ShowWindow = X11_ShowWindow;
device->HideWindow = X11_HideWindow;
device->RaiseWindow = X11_RaiseWindow;
@@ -407,6 +408,7 @@ X11_VideoInit(_THIS)
GET_ATOM(_NET_WM_ICON_NAME);
GET_ATOM(_NET_WM_ICON);
GET_ATOM(_NET_WM_PING);
+ GET_ATOM(_NET_WM_WINDOW_OPACITY);
GET_ATOM(_NET_WM_USER_TIME);
GET_ATOM(_NET_ACTIVE_WINDOW);
GET_ATOM(UTF8_STRING);
diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h
index de991ca..9bd37f4 100644
--- a/src/video/x11/SDL_x11video.h
+++ b/src/video/x11/SDL_x11video.h
@@ -104,6 +104,7 @@ typedef struct SDL_VideoData
Atom _NET_WM_ICON_NAME;
Atom _NET_WM_ICON;
Atom _NET_WM_PING;
+ Atom _NET_WM_WINDOW_OPACITY;
Atom _NET_WM_USER_TIME;
Atom _NET_ACTIVE_WINDOW;
Atom UTF8_STRING;
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index 9c1fc64..cc1198c 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -923,6 +923,25 @@ X11_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *b
return result;
}
+int
+X11_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ Atom _NET_WM_WINDOW_OPACITY = data->videodata->_NET_WM_WINDOW_OPACITY;
+
+ if (opacity == 1.0f) {
+ X11_XDeleteProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY);
+ } else {
+ const Uint32 FullyOpaque = 0xFFFFFFFF;
+ const long alpha = (long) ((double)opacity * (double)FullyOpaque);
+ X11_XChangeProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)&alpha, 1);
+ }
+
+ return 0;
+}
+
void
X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
{
diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h
index 24e4438..cc636e0 100644
--- a/src/video/x11/SDL_x11window.h
+++ b/src/video/x11/SDL_x11window.h
@@ -80,6 +80,7 @@ extern void X11_SetWindowPosition(_THIS, SDL_Window * window);
extern void X11_SetWindowMinimumSize(_THIS, SDL_Window * window);
extern void X11_SetWindowMaximumSize(_THIS, SDL_Window * window);
extern int X11_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right);
+extern int X11_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
extern void X11_SetWindowSize(_THIS, SDL_Window * window);
extern void X11_ShowWindow(_THIS, SDL_Window * window);
extern void X11_HideWindow(_THIS, SDL_Window * window);