summaryrefslogtreecommitdiff
path: root/gtk/gtkwin32.c
diff options
context:
space:
mode:
authorРуслан Ижбулатов <lrn1986@gmail.com>2014-07-29 08:18:32 +0000
committerРуслан Ижбулатов <lrn1986@gmail.com>2014-08-05 06:41:31 +0000
commit0d02cc8203e1a43506c0e81f392492aedadb6fa3 (patch)
treebd52cdc4add8c43b7aad0017ba54ed432b50ea2a /gtk/gtkwin32.c
parent31d08bd85e312ba05b7890b403c8a50cfdf52c4f (diff)
downloadgtk+-0d02cc8203e1a43506c0e81f392492aedadb6fa3.tar.gz
Make sure native W32 print dialog uses visual styles
For that to happen the libgtk3 is embedded with a manifest that requests common controls library 6.x, and GTK lazily calls InitCommonControlsEx() to initialize those. Then this manifest is used to temporarily override the process activation contest when loading comdlg32 (which contains the code for the print dialog), ensuring that it too depends on common controls 6.x, even if the application that uses GTK does not. https://bugzilla.gnome.org/show_bug.cgi?id=733773
Diffstat (limited to 'gtk/gtkwin32.c')
-rw-r--r--gtk/gtkwin32.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/gtk/gtkwin32.c b/gtk/gtkwin32.c
index e8bd7ef133..c33659e278 100644
--- a/gtk/gtkwin32.c
+++ b/gtk/gtkwin32.c
@@ -30,8 +30,15 @@
#define STRICT
#include <windows.h>
+#include <commctrl.h>
#undef STRICT
+/* In practice, resulting DLL will have manifest resource under index 2.
+ * Fall back to that value if we can't find resource index programmatically.
+ */
+#define EMPIRIC_MANIFEST_RESOURCE_INDEX 2
+
+
static HMODULE gtk_dll;
BOOL WINAPI
@@ -49,6 +56,89 @@ DllMain (HINSTANCE hinstDLL,
return TRUE;
}
+static BOOL CALLBACK
+find_first_manifest (HMODULE module_handle,
+ LPCSTR resource_type,
+ LPSTR resource_name,
+ LONG_PTR user_data)
+{
+ LPSTR *result_name = (LPSTR *) user_data;
+
+ if (resource_type == RT_MANIFEST)
+ {
+ if (IS_INTRESOURCE (resource_name))
+ *result_name = resource_name;
+ else
+ *result_name = g_strdup (resource_name);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Grabs the first manifest it finds in libgtk3 (which is expected to be the
+ * common-controls-6.0.0.0 manifest we embedded to enable visual styles),
+ * uses it to create a process-default activation context, activates that
+ * context, loads up the library passed in @dllname, then deactivates and
+ * releases the context.
+ *
+ * In practice this is used to force system DLLs (like comdlg32) to be
+ * loaded as if the application had the same manifest as libgtk3
+ * (otherwise libgtk3 manifest only affests libgtk3 itself).
+ * This way application does not need to have a manifest or to link
+ * against comctl32.
+ *
+ * Note that loaded library handle leaks, so only use this function in
+ * g_once_init_enter (leaking once is OK, Windows will clean up after us).
+ */
+void
+_gtk_load_dll_with_libgtk3_manifest (const gchar *dll_name)
+{
+ HANDLE activation_ctx_handle;
+ ACTCTXA activation_ctx_descriptor;
+ ULONG_PTR activation_cookie;
+ LPSTR resource_name;
+ BOOL activated;
+
+ resource_name = NULL;
+ EnumResourceNames (gtk_dll, RT_MANIFEST, find_first_manifest,
+ (LONG_PTR) &resource_name);
+
+ if (resource_name == NULL)
+ resource_name = MAKEINTRESOURCEA (EMPIRIC_MANIFEST_RESOURCE_INDEX);
+
+ memset (&activation_ctx_descriptor, 0, sizeof (activation_ctx_descriptor));
+ activation_ctx_descriptor.cbSize = sizeof (activation_ctx_descriptor);
+ activation_ctx_descriptor.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID |
+ ACTCTX_FLAG_HMODULE_VALID |
+ ACTCTX_FLAG_SET_PROCESS_DEFAULT;
+ activation_ctx_descriptor.hModule = gtk_dll;
+ activation_ctx_descriptor.lpResourceName = resource_name;
+ activation_ctx_handle = CreateActCtx (&activation_ctx_descriptor);
+
+ if (activation_ctx_handle == INVALID_HANDLE_VALUE)
+ g_warning ("Failed to CreateActCtx for module %p, resource %p: %lu\n",
+ gtk_dll, resource_name, GetLastError ());
+ else
+ {
+ activation_cookie = 0;
+ activated = ActivateActCtx (activation_ctx_handle, &activation_cookie);
+
+ if (!activated)
+ g_warning ("Failed to ActivateActCtx: %lu\n", GetLastError ());
+
+ LoadLibraryA (dll_name);
+
+ if (activated && !DeactivateActCtx (0, activation_cookie))
+ g_warning ("Failed to DeactivateActCtx: %lu\n", GetLastError ());
+
+ ReleaseActCtx (activation_ctx_handle);
+ }
+
+ if (!IS_INTRESOURCE (resource_name))
+ g_free (resource_name);
+}
+
const gchar *
_gtk_get_libdir (void)
{