Skip to content

Commit

Permalink
Added SDL_SetWindowOpacity() and SDL_GetWindowOpacity().
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
icculus committed Jan 5, 2016
1 parent 5696e88 commit 3bdaf4c
Show file tree
Hide file tree
Showing 19 changed files with 174 additions and 0 deletions.
28 changes: 28 additions & 0 deletions include/SDL_video.h
Expand Up @@ -845,6 +845,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.
*
Expand Down
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Expand Up @@ -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
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi_procs.h
Expand Up @@ -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)
18 changes: 18 additions & 0 deletions src/test/SDL_test_common.c
Expand Up @@ -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! */
Expand Down
3 changes: 3 additions & 0 deletions src/video/SDL_sysvideo.h
Expand Up @@ -86,6 +86,8 @@ struct SDL_Window

SDL_DisplayMode fullscreen_mode;

float opacity;

float brightness;
Uint16 *gamma;
Uint16 *saved_gamma; /* (just offset into gamma) */
Expand Down Expand Up @@ -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);
Expand Down
38 changes: 38 additions & 0 deletions src/video/SDL_video.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -2190,6 +2192,42 @@ SDL_GetWindowBrightness(SDL_Window * window)
return window->brightness;
}

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,
Expand Down
1 change: 1 addition & 0 deletions src/video/cocoa/SDL_cocoavideo.m
Expand Up @@ -87,6 +87,7 @@
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;
Expand Down
1 change: 1 addition & 0 deletions src/video/cocoa/SDL_cocoawindow.h
Expand Up @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions src/video/cocoa/SDL_cocoawindow.m
Expand Up @@ -1782,6 +1782,14 @@ take effect properly (e.g. setting the window size, etc.)
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: */
1 change: 1 addition & 0 deletions src/video/directfb/SDL_DirectFB_video.c
Expand Up @@ -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;
Expand Down
13 changes: 13 additions & 0 deletions src/video/directfb/SDL_DirectFB_window.c
Expand Up @@ -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 */
1 change: 1 addition & 0 deletions src/video/directfb/SDL_DirectFB_window.h
Expand Up @@ -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 */

Expand Down
1 change: 1 addition & 0 deletions src/video/windows/SDL_windowsvideo.c
Expand Up @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions src/video/windows/SDL_windowswindow.c
Expand Up @@ -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: */
1 change: 1 addition & 0 deletions src/video/windows/SDL_windowswindow.h
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/video/x11/SDL_x11video.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/video/x11/SDL_x11video.h
Expand Up @@ -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;
Expand Down
19 changes: 19 additions & 0 deletions src/video/x11/SDL_x11window.c
Expand Up @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions src/video/x11/SDL_x11window.h
Expand Up @@ -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);
Expand Down

0 comments on commit 3bdaf4c

Please sign in to comment.