diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | gtk/Makefile.am | 3 | ||||
-rw-r--r-- | gtk/gtk-win32.rc.in | 1 | ||||
-rw-r--r-- | gtk/gtkprintoperation-win32.c | 19 | ||||
-rw-r--r-- | gtk/gtkprivate.h | 4 | ||||
-rw-r--r-- | gtk/gtkwin32.c | 90 | ||||
-rw-r--r-- | gtk/libgtk3.manifest.in | 21 |
7 files changed, 138 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 891094db72..314dacf82b 100644 --- a/configure.ac +++ b/configure.ac @@ -1894,6 +1894,7 @@ gtk/Makefile gtk/makefile.msc gtk/gtkversion.h gtk/gtk-win32.rc +gtk/libgtk3.manifest gtk/inspector/Makefile gtk/native/Makefile util/Makefile diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 2f74d2e862..5c31084a7a 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -90,7 +90,7 @@ gtk_win32_symbols = -export-symbols $(srcdir)/gtk.def gtk_win32_res = gtk-win32-res.o gtk_win32_res_ldflag = -Wl,gtk-win32-res.o -gtk-win32-res.o : gtk-win32.rc +gtk-win32-res.o : gtk-win32.rc libgtk3.manifest $(WINDRES) gtk-win32.rc $@ gtk.def: libgtk-3.la @@ -1726,6 +1726,7 @@ EXTRA_DIST += \ $(adwaita_sources) \ $(win32_theme_sources) \ $(gsettings_SCHEMAS) \ + libgtk3.manifest.in \ gtk-win32.rc.in \ gtkwin32embed.h \ gtkwin32embedwidget.h \ diff --git a/gtk/gtk-win32.rc.in b/gtk/gtk-win32.rc.in index 4a42d5a666..dc9464a2c1 100644 --- a/gtk/gtk-win32.rc.in +++ b/gtk/gtk-win32.rc.in @@ -28,3 +28,4 @@ VS_VERSION_INFO VERSIONINFO VALUE "Translation", 0x409, 1200 END END +ISOLATIONAWARE_MANIFEST_RESOURCE_ID RT_MANIFEST libgtk3.manifest diff --git a/gtk/gtkprintoperation-win32.c b/gtk/gtkprintoperation-win32.c index e59eb9f675..3ac6bc47bf 100644 --- a/gtk/gtkprintoperation-win32.c +++ b/gtk/gtkprintoperation-win32.c @@ -1657,6 +1657,25 @@ gtk_print_operation_run_with_dialog (GtkPrintOperation *op, GtkPrintOperationPrivate *priv; IPrintDialogCallback *callback; HPROPSHEETPAGE prop_page; + static volatile gsize common_controls_initialized = 0; + + if (g_once_init_enter (&common_controls_initialized)) + { + BOOL initialized; + INITCOMMONCONTROLSEX icc; + + memset (&icc, 0, sizeof (icc)); + icc.dwSize = sizeof (icc); + icc.dwICC = ICC_WIN95_CLASSES; + + initialized = InitCommonControlsEx (&icc); + if (!initialized) + g_warning ("Failed to InitCommonControlsEx: %lu\n", GetLastError ()); + + _gtk_load_dll_with_libgtk3_manifest ("comdlg32.dll"); + + g_once_init_leave (&common_controls_initialized, initialized ? 1 : 0); + } *do_print = FALSE; diff --git a/gtk/gtkprivate.h b/gtk/gtkprivate.h index a07f7292ba..5fe7d88eae 100644 --- a/gtk/gtkprivate.h +++ b/gtk/gtkprivate.h @@ -91,6 +91,10 @@ gboolean _gtk_propagate_captured_event (GtkWidget *widget, GdkEvent *event, GtkWidget *topmost); +#ifdef G_OS_WIN32 +void _gtk_load_dll_with_libgtk3_manifest (const char *dllname); +#endif + G_END_DECLS #endif /* __GTK_PRIVATE_H__ */ 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) { diff --git a/gtk/libgtk3.manifest.in b/gtk/libgtk3.manifest.in new file mode 100644 index 0000000000..6e1677eb1f --- /dev/null +++ b/gtk/libgtk3.manifest.in @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity + version="1.0.0.0" + processorArchitecture="@EXE_MANIFEST_ARCHITECTURE@" + name="libgtk3" + type="win32" + /> + <dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="@EXE_MANIFEST_ARCHITECTURE@" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> + </dependency> +</assembly> |