[gtk+/master.fcw: 533/648] GDK-Win32: Implement is_composited() and set_composited()



commit f02e9194bbd157da1aaf6bab87e3da43c850b050
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Wed Jan 21 16:57:44 2015 +0800

    GDK-Win32: Implement is_composited() and set_composited()
    
    This adds implementations for ->is_composited() and set_composited() for
    the Windows GDK backend, with the following notes:
    
    -Compositing is always enabled on Windows 8/Server 2012 and later, and
     one is not allowed to disable it programmatically, hence we check whether
     we are on at least Windows 8/Server 2012 first.
    -XP does not support DWM for compositing, so it is FALSE on XP.  There is
     compatibility code to make sure the code still runs on XP, by only using
     DWM when it is available, but it may be dropped soon.  We would then only
     need to check whether we are on Windows 8+/Server 2012+ when we have DWM.
    -As mentioned, only Windows Vista/7/Server 2008/Server 2008 R2 supports
     enabling and disabling compositing programmatically.
    
    This uses the new GLib-Win32 API g_win32_check_windows_version() so that we
    can use it to check whether we are on XP/Server 2003 or later, and whether
    we are on Windows 8 or Server 2012 or later, for alpha and compositing
    support, so that we can simplify the exising Windows version checking code
    in gdkcursor-win32.c and  gdkwindow-win32.c.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=741849

 gdk/win32/gdkcursor-win32.c  |   18 +--------------
 gdk/win32/gdkglobals-win32.c |    2 +
 gdk/win32/gdkmain-win32.c    |   40 ++++++++++++++++++++++++++++++++++++
 gdk/win32/gdkprivate-win32.h |   46 ++++++++++++++++++++++++++++++++++++++++++
 gdk/win32/gdkscreen-win32.c  |   18 +++++++++++++++-
 gdk/win32/gdkwindow-win32.c  |   31 +++++++++++++++++++++++++--
 6 files changed, 135 insertions(+), 20 deletions(-)
---
diff --git a/gdk/win32/gdkcursor-win32.c b/gdk/win32/gdkcursor-win32.c
index 28b2745..d24d0e0 100644
--- a/gdk/win32/gdkcursor-win32.c
+++ b/gdk/win32/gdkcursor-win32.c
@@ -821,22 +821,8 @@ _gdk_win32_pixbuf_to_hcursor (GdkPixbuf *pixbuf,
 gboolean
 _gdk_win32_pixbuf_to_hicon_supports_alpha (void)
 {
-  static gboolean is_win_xp=FALSE, is_win_xp_checked=FALSE;
-
-  if (!is_win_xp_checked)
-    {
-      OSVERSIONINFO version;
-
-      is_win_xp_checked = TRUE;
-
-      memset (&version, 0, sizeof (version));
-      version.dwOSVersionInfoSize = sizeof (version);
-      is_win_xp = GetVersionEx (&version)
-       && version.dwPlatformId == VER_PLATFORM_WIN32_NT
-       && (version.dwMajorVersion > 5
-           || (version.dwMajorVersion == 5 && version.dwMinorVersion >= 1));
-    }
-  return is_win_xp;
+  gdk_win32_set_windowing_capabilities ();
+  return _windowing_capabilities.is_winxp_or_later;
 }
 
 HICON
diff --git a/gdk/win32/gdkglobals-win32.c b/gdk/win32/gdkglobals-win32.c
index 5248a00..c88969f 100644
--- a/gdk/win32/gdkglobals-win32.c
+++ b/gdk/win32/gdkglobals-win32.c
@@ -82,3 +82,5 @@ gboolean        _ignore_destroy_clipboard = FALSE;
 
 HGLOBAL           _delayed_rendering_data = NULL;
 GHashTable       *_format_atom_table = NULL;
+
+GdkWin32WindowingCapabilities _windowing_capabilities = {0};
diff --git a/gdk/win32/gdkmain-win32.c b/gdk/win32/gdkmain-win32.c
index 905c729..00faa5a 100644
--- a/gdk/win32/gdkmain-win32.c
+++ b/gdk/win32/gdkmain-win32.c
@@ -150,6 +150,46 @@ _gdk_other_api_failed (const gchar *where,
   g_warning ("%s: %s failed", where, api);
 }
 
+/* After XP support dropped, just check whether
+ * we are on Windows 8/Server 2012 or later at that time
+ */
+void
+gdk_win32_set_windowing_capabilities (void)
+{
+  static gsize capabilities_inited = 0;
+
+  if (_windowing_capabilities.inited)
+    return;
+
+  if (g_once_init_enter (&capabilities_inited))
+    {
+      HMODULE dwmdll = LoadLibraryW (L"dwmapi.dll");
+
+      _windowing_capabilities.is_winxp_or_later = g_win32_check_windows_version (5, 1, 0, G_WIN32_OS_ANY);
+      _windowing_capabilities.is_win8_or_later = g_win32_check_windows_version (6, 2, 0, G_WIN32_OS_ANY);
+      if (dwmdll == NULL)
+        {
+          _windowing_capabilities.dwmIsCompositionEnabled = NULL;
+          _windowing_capabilities.dwmEnableComposition = NULL;
+          _windowing_capabilities.dwmEnableBlurBehindWindow = NULL;
+        }
+      else
+        {
+          _windowing_capabilities.dwmIsCompositionEnabled =
+            (PFN_DwmIsCompositionEnabled) GetProcAddress (dwmdll, "DwmIsCompositionEnabled");
+          _windowing_capabilities.dwmEnableComposition =
+            (PFN_DwmEnableComposition) GetProcAddress (dwmdll, "DwmEnableComposition");
+          _windowing_capabilities.dwmEnableBlurBehindWindow =
+            (PFN_DwmEnableBlurBehindWindow) GetProcAddress (dwmdll, "DwmEnableBlurBehindWindow");
+
+          FreeLibrary (dwmdll);
+        }
+
+      _windowing_capabilities.inited = TRUE;
+
+      g_once_init_leave (&capabilities_inited, 1);
+    }
+}
 
 #ifdef G_ENABLE_DEBUG
 
diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h
index acc3fca..b251a23 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -508,4 +508,50 @@ void _gdk_events_init (void);
 void _gdk_input_init  (GdkDisplay *display);
 void _gdk_input_wintab_init_check (GdkDeviceManager *device_manager);
 
+/* for XP run-time compatibility, remove once XP support dropped */
+#ifndef DWM_BLURBEHIND
+typedef struct
+{
+  DWORD dwFlags;
+  BOOL fEnable;
+  HRGN hRgnBlur;
+  BOOL fTransitionOnMaximized;
+} DWM_BLURBEHIND;
+#endif
+
+#ifndef DWM_EC_DISABLECOMPOSITION
+#define DWM_EC_DISABLECOMPOSITION 0
+#endif
+#ifndef DWM_EC_ENABLECOMPOSITION
+#define DWM_EC_ENABLECOMPOSITION 1
+#endif
+
+#ifndef DWM_BB_ENABLE
+#define DWM_BB_ENABLE 0x00000001
+#endif
+
+#ifndef DWM_BB_BLURREGION
+#define DWM_BB_BLURREGION 0x00000002
+#endif
+
+typedef HRESULT (WINAPI *PFN_DwmIsCompositionEnabled) (BOOL *);
+typedef HRESULT (WINAPI *PFN_DwmEnableComposition) (UINT);
+typedef HRESULT (WINAPI *PFN_DwmEnableBlurBehindWindow) (HWND, const DWM_BLURBEHIND *);
+
+typedef struct
+{
+  PFN_DwmIsCompositionEnabled dwmIsCompositionEnabled;
+  PFN_DwmEnableComposition dwmEnableComposition;
+  PFN_DwmEnableBlurBehindWindow dwmEnableBlurBehindWindow;
+
+  /* Only check whether we are on Windows 8 or Server 2012 or later after dropping XP support */
+  gboolean is_winxp_or_later;
+  gboolean is_win8_or_later;
+  gboolean inited;
+} GdkWin32WindowingCapabilities;
+
+extern GdkWin32WindowingCapabilities _windowing_capabilities;
+
+void gdk_win32_set_windowing_capabilities (void);
+
 #endif /* __GDK_PRIVATE_WIN32_H__ */
diff --git a/gdk/win32/gdkscreen-win32.c b/gdk/win32/gdkscreen-win32.c
index 8c6fb03..861fe0b 100644
--- a/gdk/win32/gdkscreen-win32.c
+++ b/gdk/win32/gdkscreen-win32.c
@@ -195,9 +195,25 @@ gdk_win32_screen_get_window_stack (GdkScreen *screen)
 static gboolean
 gdk_win32_screen_is_composited (GdkScreen *screen)
 {
+  gboolean is_composited;
+
   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
 
-  return FALSE;
+  gdk_win32_set_windowing_capabilities ();
+
+  /* Windows 8/Server 2012 and later are always composited. */
+  if (_windowing_capabilities.is_win8_or_later)
+    return TRUE;
+
+  /* not Windows 8+/Server 2012+, check further
+     DwmIsCompositionEnabled() is only on Vista and later */
+  if (_windowing_capabilities.dwmIsCompositionEnabled == NULL)
+    return FALSE;
+
+  if (_windowing_capabilities.dwmIsCompositionEnabled (&is_composited) != S_OK)
+    return FALSE;
+
+  return is_composited;
 }
 
 static void
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index 3e568a4..6dd15ec 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -375,8 +375,10 @@ RegisterGdkClass (GdkWindowType wtype, GdkWindowTypeHint wtype_hint)
             {
               wcl.lpszClassName = L"gdkWindowTempShadow";
               wcl.style |= CS_SAVEBITS;
-              if (LOBYTE (g_win32_get_windows_version()) > 0x05 ||
-                 LOWORD (g_win32_get_windows_version()) == 0x0105)
+
+              gdk_win32_set_windowing_capabilities ();
+
+              if (_windowing_capabilities.is_winxp_or_later)
                {
                  /* Windows XP (5.1) or above */
                  wcl.style |= 0x00020000; /* CS_DROPSHADOW */
@@ -3363,6 +3365,29 @@ gdk_win32_ref_cairo_surface (GdkWindow *window)
 }
 
 static void
+gdk_win32_window_set_composited (GdkWindow *window,
+                                 gboolean composited)
+{
+  guint action;
+
+  gdk_win32_set_windowing_capabilities ();
+
+  /* We can't set whether the Window is composited or not on Windows 8+/Server 2012+,
+     as it is always composited, and don't have DWM on Windows XP.  So don't do anything
+     in these cases. */
+  if (_windowing_capabilities.is_win8_or_later ||
+      _windowing_capabilities.dwmEnableComposition == NULL)
+    return;
+
+  if (composited)
+    action = DWM_EC_ENABLECOMPOSITION;
+  else
+    action = DWM_EC_DISABLECOMPOSITION;
+
+  _windowing_capabilities.dwmEnableComposition (action);
+}
+
+static void
 gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -3437,7 +3462,7 @@ gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
   impl_class->begin_resize_drag = gdk_win32_window_begin_resize_drag;
   impl_class->begin_move_drag = gdk_win32_window_begin_move_drag;
   impl_class->set_opacity = gdk_win32_window_set_opacity;
-  //impl_class->set_composited = gdk_win32_window_set_composited;
+  impl_class->set_composited = gdk_win32_window_set_composited;
   impl_class->destroy_notify = gdk_win32_window_destroy_notify;
   impl_class->get_drag_protocol = _gdk_win32_window_get_drag_protocol;
   impl_class->register_dnd = _gdk_win32_window_register_dnd;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]