Added SDL_SetWindowOpacity() and SDL_GetWindowOpacity().
authorRyan C. Gordon <icculus@icculus.org>
Tue, 05 Jan 2016 02:46:10 -0500
changeset 10025bf4f8cde1c54
parent 10024 9a1189c7b891
child 10026 5f73f513b9f5
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.
include/SDL_video.h
src/dynapi/SDL_dynapi_overrides.h
src/dynapi/SDL_dynapi_procs.h
src/test/SDL_test_common.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/cocoa/SDL_cocoavideo.m
src/video/cocoa/SDL_cocoawindow.h
src/video/cocoa/SDL_cocoawindow.m
src/video/directfb/SDL_DirectFB_video.c
src/video/directfb/SDL_DirectFB_window.c
src/video/directfb/SDL_DirectFB_window.h
src/video/windows/SDL_windowsvideo.c
src/video/windows/SDL_windowswindow.c
src/video/windows/SDL_windowswindow.h
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11video.h
src/video/x11/SDL_x11window.c
src/video/x11/SDL_x11window.h
     1.1 --- a/include/SDL_video.h	Tue Jan 05 02:29:06 2016 -0500
     1.2 +++ b/include/SDL_video.h	Tue Jan 05 02:46:10 2016 -0500
     1.3 @@ -846,6 +846,34 @@
     1.4  extern DECLSPEC float SDLCALL SDL_GetWindowBrightness(SDL_Window * window);
     1.5  
     1.6  /**
     1.7 + *  \brief Set the opacity for a window
     1.8 + *
     1.9 + *  \param window The window which will be made transparent or opaque
    1.10 + *  \param opacity Opacity (0.0f - transparent, 1.0f - opaque) This will be
    1.11 + *                 clamped internally between 0.0f and 1.0f.
    1.12 + * 
    1.13 + *  \return 0 on success, or -1 if setting the opacity isn't supported.
    1.14 + *
    1.15 + *  \sa SDL_GetWindowOpacity()
    1.16 + */
    1.17 +extern DECLSPEC int SDLCALL SDL_SetWindowOpacity(SDL_Window * window, float opacity);
    1.18 +
    1.19 +/**
    1.20 + *  \brief Get the opacity of a window.
    1.21 + *
    1.22 + *  If transparency isn't supported on this platform, opacity will be reported
    1.23 + *  as 1.0f without error.
    1.24 + *
    1.25 + *  \param window The window in question.
    1.26 + *  \param opacity Opacity (0.0f - transparent, 1.0f - opaque)
    1.27 + *
    1.28 + *  \return 0 on success, or -1 on error (invalid window, etc).
    1.29 + *
    1.30 + *  \sa SDL_SetWindowOpacity()
    1.31 + */
    1.32 +extern DECLSPEC int SDLCALL SDL_GetWindowOpacity(SDL_Window * window, float * out_opacity);
    1.33 +
    1.34 +/**
    1.35   *  \brief Set the gamma ramp for a window.
    1.36   *
    1.37   *  \param window The window for which the gamma ramp should be set.
     2.1 --- a/src/dynapi/SDL_dynapi_overrides.h	Tue Jan 05 02:29:06 2016 -0500
     2.2 +++ b/src/dynapi/SDL_dynapi_overrides.h	Tue Jan 05 02:46:10 2016 -0500
     2.3 @@ -599,3 +599,5 @@
     2.4  #define SDL_JoystickFromInstanceID SDL_JoystickFromInstanceID_REAL
     2.5  #define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL
     2.6  #define SDL_GetWindowBordersSize SDL_GetWindowBordersSize_REAL
     2.7 +#define SDL_SetWindowOpacity SDL_SetWindowOpacity_REAL
     2.8 +#define SDL_GetWindowOpacity SDL_GetWindowOpacity_REAL
     3.1 --- a/src/dynapi/SDL_dynapi_procs.h	Tue Jan 05 02:29:06 2016 -0500
     3.2 +++ b/src/dynapi/SDL_dynapi_procs.h	Tue Jan 05 02:46:10 2016 -0500
     3.3 @@ -633,3 +633,5 @@
     3.4  SDL_DYNAPI_PROC(SDL_Joystick*,SDL_JoystickFromInstanceID,(SDL_JoystickID a),(a),return)
     3.5  SDL_DYNAPI_PROC(int,SDL_GetDisplayUsableBounds,(int a, SDL_Rect *b),(a,b),return)
     3.6  SDL_DYNAPI_PROC(int,SDL_GetWindowBordersSize,(SDL_Window *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return)
     3.7 +SDL_DYNAPI_PROC(int,SDL_SetWindowOpacity,(SDL_Window *a, float b),(a,b),return)
     3.8 +SDL_DYNAPI_PROC(int,SDL_GetWindowOpacity,(SDL_Window *a, float *b),(a,b),return)
     4.1 --- a/src/test/SDL_test_common.c	Tue Jan 05 02:29:06 2016 -0500
     4.2 +++ b/src/test/SDL_test_common.c	Tue Jan 05 02:46:10 2016 -0500
     4.3 @@ -1368,6 +1368,24 @@
     4.4                  }
     4.5              }
     4.6              break;
     4.7 +        case SDLK_o:
     4.8 +            if (withControl) {
     4.9 +                /* Ctrl-O (or Ctrl-Shift-O) changes window opacity. */
    4.10 +                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
    4.11 +                if (window) {
    4.12 +                    float opacity;
    4.13 +                    if (SDL_GetWindowOpacity(window, &opacity) == 0) {
    4.14 +                        if (withShift) {
    4.15 +                            opacity += 0.20f;
    4.16 +                        } else {
    4.17 +                            opacity -= 0.20f;
    4.18 +                        }
    4.19 +                        SDL_SetWindowOpacity(window, opacity);
    4.20 +                    }
    4.21 +                }
    4.22 +            }
    4.23 +            break;
    4.24 +
    4.25          case SDLK_c:
    4.26              if (withControl) {
    4.27                  /* Ctrl-C copy awesome text! */
     5.1 --- a/src/video/SDL_sysvideo.h	Tue Jan 05 02:29:06 2016 -0500
     5.2 +++ b/src/video/SDL_sysvideo.h	Tue Jan 05 02:46:10 2016 -0500
     5.3 @@ -86,6 +86,8 @@
     5.4  
     5.5      SDL_DisplayMode fullscreen_mode;
     5.6  
     5.7 +    float opacity;
     5.8 +
     5.9      float brightness;
    5.10      Uint16 *gamma;
    5.11      Uint16 *saved_gamma;        /* (just offset into gamma) */
    5.12 @@ -207,6 +209,7 @@
    5.13      void (*SetWindowMinimumSize) (_THIS, SDL_Window * window);
    5.14      void (*SetWindowMaximumSize) (_THIS, SDL_Window * window);
    5.15      int (*GetWindowBordersSize) (_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right);
    5.16 +    int (*SetWindowOpacity) (_THIS, SDL_Window * window, float opacity);
    5.17      void (*ShowWindow) (_THIS, SDL_Window * window);
    5.18      void (*HideWindow) (_THIS, SDL_Window * window);
    5.19      void (*RaiseWindow) (_THIS, SDL_Window * window);
     6.1 --- a/src/video/SDL_video.c	Tue Jan 05 02:29:06 2016 -0500
     6.2 +++ b/src/video/SDL_video.c	Tue Jan 05 02:46:10 2016 -0500
     6.3 @@ -1415,6 +1415,7 @@
     6.4      }
     6.5      window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
     6.6      window->last_fullscreen_flags = window->flags;
     6.7 +    window->opacity = 1.0f;
     6.8      window->brightness = 1.0f;
     6.9      window->next = _this->windows;
    6.10      window->is_destroying = SDL_FALSE;
    6.11 @@ -1475,6 +1476,7 @@
    6.12      window->flags = SDL_WINDOW_FOREIGN;
    6.13      window->last_fullscreen_flags = window->flags;
    6.14      window->is_destroying = SDL_FALSE;
    6.15 +    window->opacity = 1.0f;
    6.16      window->brightness = 1.0f;
    6.17      window->next = _this->windows;
    6.18      if (_this->windows) {
    6.19 @@ -2191,6 +2193,42 @@
    6.20  }
    6.21  
    6.22  int
    6.23 +SDL_SetWindowOpacity(SDL_Window * window, float opacity)
    6.24 +{
    6.25 +    int retval;
    6.26 +    CHECK_WINDOW_MAGIC(window, -1);
    6.27 +
    6.28 +    if (!_this->SetWindowOpacity) {
    6.29 +        return SDL_Unsupported();
    6.30 +    }
    6.31 +
    6.32 +    if (opacity < 0.0f) {
    6.33 +        opacity = 0.0f;
    6.34 +    } else if (opacity > 1.0f) {
    6.35 +        opacity = 1.0f;
    6.36 +    }
    6.37 +
    6.38 +    retval = _this->SetWindowOpacity(_this, window, opacity);
    6.39 +    if (retval == 0) {
    6.40 +        window->opacity = opacity;
    6.41 +    }
    6.42 +
    6.43 +    return retval;
    6.44 +}
    6.45 +
    6.46 +int
    6.47 +SDL_GetWindowOpacity(SDL_Window * window, float * out_opacity)
    6.48 +{
    6.49 +    CHECK_WINDOW_MAGIC(window, -1);
    6.50 +
    6.51 +    if (out_opacity) {
    6.52 +        *out_opacity = window->opacity;
    6.53 +    }
    6.54 +
    6.55 +    return 0;
    6.56 +}
    6.57 +
    6.58 +int
    6.59  SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
    6.60                                              const Uint16 * green,
    6.61                                              const Uint16 * blue)
     7.1 --- a/src/video/cocoa/SDL_cocoavideo.m	Tue Jan 05 02:29:06 2016 -0500
     7.2 +++ b/src/video/cocoa/SDL_cocoavideo.m	Tue Jan 05 02:46:10 2016 -0500
     7.3 @@ -87,6 +87,7 @@
     7.4      device->SetWindowSize = Cocoa_SetWindowSize;
     7.5      device->SetWindowMinimumSize = Cocoa_SetWindowMinimumSize;
     7.6      device->SetWindowMaximumSize = Cocoa_SetWindowMaximumSize;
     7.7 +    device->SetWindowOpacity = Cocoa_SetWindowOpacity;
     7.8      device->ShowWindow = Cocoa_ShowWindow;
     7.9      device->HideWindow = Cocoa_HideWindow;
    7.10      device->RaiseWindow = Cocoa_RaiseWindow;
     8.1 --- a/src/video/cocoa/SDL_cocoawindow.h	Tue Jan 05 02:29:06 2016 -0500
     8.2 +++ b/src/video/cocoa/SDL_cocoawindow.h	Tue Jan 05 02:46:10 2016 -0500
     8.3 @@ -125,6 +125,7 @@
     8.4  extern void Cocoa_SetWindowSize(_THIS, SDL_Window * window);
     8.5  extern void Cocoa_SetWindowMinimumSize(_THIS, SDL_Window * window);
     8.6  extern void Cocoa_SetWindowMaximumSize(_THIS, SDL_Window * window);
     8.7 +extern int Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
     8.8  extern void Cocoa_ShowWindow(_THIS, SDL_Window * window);
     8.9  extern void Cocoa_HideWindow(_THIS, SDL_Window * window);
    8.10  extern void Cocoa_RaiseWindow(_THIS, SDL_Window * window);
     9.1 --- a/src/video/cocoa/SDL_cocoawindow.m	Tue Jan 05 02:29:06 2016 -0500
     9.2 +++ b/src/video/cocoa/SDL_cocoawindow.m	Tue Jan 05 02:46:10 2016 -0500
     9.3 @@ -1782,6 +1782,14 @@
     9.4      return 0;  /* just succeed, the real work is done elsewhere. */
     9.5  }
     9.6  
     9.7 +int
     9.8 +Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
     9.9 +{
    9.10 +    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
    9.11 +    [data->nswindow setAlphaValue:opacity];
    9.12 +    return 0;
    9.13 +}
    9.14 +
    9.15  #endif /* SDL_VIDEO_DRIVER_COCOA */
    9.16  
    9.17  /* vi: set ts=4 sw=4 expandtab: */
    10.1 --- a/src/video/directfb/SDL_DirectFB_video.c	Tue Jan 05 02:29:06 2016 -0500
    10.2 +++ b/src/video/directfb/SDL_DirectFB_video.c	Tue Jan 05 02:46:10 2016 -0500
    10.3 @@ -121,6 +121,7 @@
    10.4      device->SetWindowIcon = DirectFB_SetWindowIcon;
    10.5      device->SetWindowPosition = DirectFB_SetWindowPosition;
    10.6      device->SetWindowSize = DirectFB_SetWindowSize;
    10.7 +    device->SetWindowOpacity = DirectFB_SetWindowOpacity;
    10.8      device->ShowWindow = DirectFB_ShowWindow;
    10.9      device->HideWindow = DirectFB_HideWindow;
   10.10      device->RaiseWindow = DirectFB_RaiseWindow;
    11.1 --- a/src/video/directfb/SDL_DirectFB_window.c	Tue Jan 05 02:29:06 2016 -0500
    11.2 +++ b/src/video/directfb/SDL_DirectFB_window.c	Tue Jan 05 02:46:10 2016 -0500
    11.3 @@ -529,4 +529,17 @@
    11.4      return;
    11.5  }
    11.6  
    11.7 +int
    11.8 +DirectFB_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
    11.9 +{
   11.10 +    const Uint8 alpha = (Uint8) ((unsigned int) (opacity * 255.0f));
   11.11 +    SDL_DFB_WINDOWDATA(window);
   11.12 +    SDL_DFB_CHECKERR(windata->dfbwin->SetOpacity(windata->dfbwin, alpha));
   11.13 +    windata->opacity = alpha;
   11.14 +    return 0;
   11.15 +
   11.16 +error:
   11.17 +    return -1;
   11.18 +}
   11.19 +
   11.20  #endif /* SDL_VIDEO_DRIVER_DIRECTFB */
    12.1 --- a/src/video/directfb/SDL_DirectFB_window.h	Tue Jan 05 02:29:06 2016 -0500
    12.2 +++ b/src/video/directfb/SDL_DirectFB_window.h	Tue Jan 05 02:46:10 2016 -0500
    12.3 @@ -75,6 +75,7 @@
    12.4                                           struct SDL_SysWMinfo *info);
    12.5  
    12.6  extern void DirectFB_AdjustWindowSurface(SDL_Window * window);
    12.7 +extern int DirectFB_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
    12.8  
    12.9  #endif /* _SDL_directfb_window_h */
   12.10  
    13.1 --- a/src/video/windows/SDL_windowsvideo.c	Tue Jan 05 02:29:06 2016 -0500
    13.2 +++ b/src/video/windows/SDL_windowsvideo.c	Tue Jan 05 02:46:10 2016 -0500
    13.3 @@ -137,6 +137,7 @@
    13.4      device->SetWindowIcon = WIN_SetWindowIcon;
    13.5      device->SetWindowPosition = WIN_SetWindowPosition;
    13.6      device->SetWindowSize = WIN_SetWindowSize;
    13.7 +    device->SetWindowOpacity = WIN_SetWindowOpacity;
    13.8      device->ShowWindow = WIN_ShowWindow;
    13.9      device->HideWindow = WIN_HideWindow;
   13.10      device->RaiseWindow = WIN_RaiseWindow;
    14.1 --- a/src/video/windows/SDL_windowswindow.c	Tue Jan 05 02:29:06 2016 -0500
    14.2 +++ b/src/video/windows/SDL_windowswindow.c	Tue Jan 05 02:46:10 2016 -0500
    14.3 @@ -826,6 +826,39 @@
    14.4      return 0;  /* just succeed, the real work is done elsewhere. */
    14.5  }
    14.6  
    14.7 +int
    14.8 +WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
    14.9 +{
   14.10 +    const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   14.11 +    const HWND hwnd = data->hwnd;
   14.12 +    const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
   14.13 +
   14.14 +    SDL_assert(style != 0);
   14.15 +
   14.16 +    if (opacity == 1.0f) {
   14.17 +        /* want it fully opaque, just mark it unlayered if necessary. */
   14.18 +        if (style & WS_EX_LAYERED) {
   14.19 +            if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_LAYERED) == 0) {
   14.20 +                return WIN_SetError("SetWindowLong()");
   14.21 +            }
   14.22 +        }
   14.23 +    } else {
   14.24 +        const BYTE alpha = (BYTE) ((int) (opacity * 255.0f));
   14.25 +        /* want it transparent, mark it layered if necessary. */
   14.26 +        if ((style & WS_EX_LAYERED) == 0) {
   14.27 +            if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_LAYERED) == 0) {
   14.28 +                return WIN_SetError("SetWindowLong()");
   14.29 +            }
   14.30 +        }
   14.31 +
   14.32 +        if (SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA) == 0) {
   14.33 +            return WIN_SetError("SetLayeredWindowAttributes()");
   14.34 +        }
   14.35 +    }
   14.36 +
   14.37 +    return 0;
   14.38 +}
   14.39 +
   14.40  #endif /* SDL_VIDEO_DRIVER_WINDOWS */
   14.41  
   14.42  /* vi: set ts=4 sw=4 expandtab: */
    15.1 --- a/src/video/windows/SDL_windowswindow.h	Tue Jan 05 02:29:06 2016 -0500
    15.2 +++ b/src/video/windows/SDL_windowswindow.h	Tue Jan 05 02:46:10 2016 -0500
    15.3 @@ -56,6 +56,7 @@
    15.4  extern void WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
    15.5  extern void WIN_SetWindowPosition(_THIS, SDL_Window * window);
    15.6  extern void WIN_SetWindowSize(_THIS, SDL_Window * window);
    15.7 +extern int WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
    15.8  extern void WIN_ShowWindow(_THIS, SDL_Window * window);
    15.9  extern void WIN_HideWindow(_THIS, SDL_Window * window);
   15.10  extern void WIN_RaiseWindow(_THIS, SDL_Window * window);
    16.1 --- a/src/video/x11/SDL_x11video.c	Tue Jan 05 02:29:06 2016 -0500
    16.2 +++ b/src/video/x11/SDL_x11video.c	Tue Jan 05 02:46:10 2016 -0500
    16.3 @@ -233,6 +233,7 @@
    16.4      device->SetWindowMinimumSize = X11_SetWindowMinimumSize;
    16.5      device->SetWindowMaximumSize = X11_SetWindowMaximumSize;
    16.6      device->GetWindowBordersSize = X11_GetWindowBordersSize;
    16.7 +    device->SetWindowOpacity = X11_SetWindowOpacity;
    16.8      device->ShowWindow = X11_ShowWindow;
    16.9      device->HideWindow = X11_HideWindow;
   16.10      device->RaiseWindow = X11_RaiseWindow;
   16.11 @@ -407,6 +408,7 @@
   16.12      GET_ATOM(_NET_WM_ICON_NAME);
   16.13      GET_ATOM(_NET_WM_ICON);
   16.14      GET_ATOM(_NET_WM_PING);
   16.15 +    GET_ATOM(_NET_WM_WINDOW_OPACITY);
   16.16      GET_ATOM(_NET_WM_USER_TIME);
   16.17      GET_ATOM(_NET_ACTIVE_WINDOW);
   16.18      GET_ATOM(UTF8_STRING);
    17.1 --- a/src/video/x11/SDL_x11video.h	Tue Jan 05 02:29:06 2016 -0500
    17.2 +++ b/src/video/x11/SDL_x11video.h	Tue Jan 05 02:46:10 2016 -0500
    17.3 @@ -104,6 +104,7 @@
    17.4      Atom _NET_WM_ICON_NAME;
    17.5      Atom _NET_WM_ICON;
    17.6      Atom _NET_WM_PING;
    17.7 +    Atom _NET_WM_WINDOW_OPACITY;
    17.8      Atom _NET_WM_USER_TIME;
    17.9      Atom _NET_ACTIVE_WINDOW;
   17.10      Atom UTF8_STRING;
    18.1 --- a/src/video/x11/SDL_x11window.c	Tue Jan 05 02:29:06 2016 -0500
    18.2 +++ b/src/video/x11/SDL_x11window.c	Tue Jan 05 02:46:10 2016 -0500
    18.3 @@ -923,6 +923,25 @@
    18.4      return result;
    18.5  }
    18.6  
    18.7 +int
    18.8 +X11_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
    18.9 +{
   18.10 +    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   18.11 +    Display *display = data->videodata->display;
   18.12 +    Atom _NET_WM_WINDOW_OPACITY = data->videodata->_NET_WM_WINDOW_OPACITY;
   18.13 +
   18.14 +    if (opacity == 1.0f) {
   18.15 +        X11_XDeleteProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY);
   18.16 +    } else  {
   18.17 +        const Uint32 FullyOpaque = 0xFFFFFFFF;
   18.18 +        const long alpha = (long) ((double)opacity * (double)FullyOpaque);
   18.19 +        X11_XChangeProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
   18.20 +            PropModeReplace, (unsigned char *)&alpha, 1);
   18.21 +    }
   18.22 +
   18.23 +    return 0;
   18.24 +}
   18.25 +
   18.26  void
   18.27  X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
   18.28  {
    19.1 --- a/src/video/x11/SDL_x11window.h	Tue Jan 05 02:29:06 2016 -0500
    19.2 +++ b/src/video/x11/SDL_x11window.h	Tue Jan 05 02:46:10 2016 -0500
    19.3 @@ -80,6 +80,7 @@
    19.4  extern void X11_SetWindowMinimumSize(_THIS, SDL_Window * window);
    19.5  extern void X11_SetWindowMaximumSize(_THIS, SDL_Window * window);
    19.6  extern int X11_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right);
    19.7 +extern int X11_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
    19.8  extern void X11_SetWindowSize(_THIS, SDL_Window * window);
    19.9  extern void X11_ShowWindow(_THIS, SDL_Window * window);
   19.10  extern void X11_HideWindow(_THIS, SDL_Window * window);