From 012df8514adca82f081e8a11e40b4142c23ed33d Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Tue, 29 Jun 2021 16:11:03 +0200 Subject: [PATCH] Add a config enum for the pointer input API to use on Windows --- app/app.c | 32 +++++++++++++++++++ app/config/gimpcoreconfig.c | 24 ++++++++++++++ app/config/gimpcoreconfig.h | 3 ++ app/config/gimpearlyrc.c | 44 ++++++++++++++++++++++++- app/config/gimpearlyrc.h | 9 ++++++ app/config/gimprc-blurbs.h | 3 ++ app/core/core-enums.c | 29 +++++++++++++++++ app/core/core-enums.h | 11 +++++++ app/core/gimp-utils.c | 38 ++++++++++++++++++++++ app/core/gimp-utils.h | 6 ++++ app/dialogs/preferences-dialog.c | 55 ++++++++++++++++++++++++++++++++ 11 files changed, 253 insertions(+), 1 deletion(-) diff --git a/app/app.c b/app/app.c index 931dc8d833..a1cc35e689 100644 --- a/app/app.c +++ b/app/app.c @@ -34,6 +34,10 @@ #include #include +#ifndef GIMP_CONSOLE_COMPILATION +#include +#endif + #include #ifdef G_OS_WIN32 @@ -240,6 +244,34 @@ app_run (const gchar *full_prog_name, if (language) g_free (language); +#if defined (G_OS_WIN32) && !defined (GIMP_CONSOLE_COMPILATION) + +#if GTK_MAJOR_VERSION > 3 +#warning For GTK4 and above use the proper backend-specific API instead of the GDK_WIN32_TABLET_INPUT_API environment variable +#endif + + /* Support for Windows Ink was introduced in GTK3 3.24.30 + */ + if (gtk_get_major_version () == 3 && + (gtk_get_minor_version () > 24 || + (gtk_get_minor_version () == 24 && + gtk_get_micro_version () >= 30))) + { + GimpWin32PointerInputAPI api = gimp_early_rc_get_win32_pointer_input_api (earlyrc);; + + switch (api) + { + case GIMP_WIN32_POINTER_INPUT_API_WINTAB: + g_setenv ("GDK_WIN32_TABLET_INPUT_API", "wintab", TRUE); + break; + case GIMP_WIN32_POINTER_INPUT_API_WINDOWS_INK: + g_setenv ("GDK_WIN32_TABLET_INPUT_API", "winpointer", TRUE); + break; + } + } + +#endif + g_object_unref (earlyrc); /* Create an instance of the "Gimp" object which is the root of the diff --git a/app/config/gimpcoreconfig.c b/app/config/gimpcoreconfig.c index e7ac85e050..159dea084f 100644 --- a/app/config/gimpcoreconfig.c +++ b/app/config/gimpcoreconfig.c @@ -134,6 +134,9 @@ enum PROP_LAST_RELEASE_COMMENT, PROP_LAST_REVISION, PROP_LAST_KNOWN_RELEASE, +#ifdef G_OS_WIN32 + PROP_WIN32_POINTER_INPUT_API, +#endif /* ignored, only for backward compatibility: */ PROP_INSTALL_COLORMAP, @@ -823,6 +826,17 @@ gimp_core_config_class_init (GimpCoreConfigClass *klass) #endif GIMP_PARAM_STATIC_STRINGS); +#ifdef G_OS_WIN32 + GIMP_CONFIG_PROP_ENUM (object_class, PROP_WIN32_POINTER_INPUT_API, + "win32-pointer-input-api", + "Pointer Input API", + WIN32_POINTER_INPUT_API_BLURB, + GIMP_TYPE_WIN32_POINTER_INPUT_API, + GIMP_WIN32_POINTER_INPUT_API_WINDOWS_INK, + GIMP_PARAM_STATIC_STRINGS | + GIMP_CONFIG_PARAM_RESTART); +#endif + /* only for backward compatibility: */ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_INSTALL_COLORMAP, "install-colormap", @@ -1166,6 +1180,11 @@ gimp_core_config_set_property (GObject *object, case PROP_DEBUG_POLICY: core_config->debug_policy = g_value_get_enum (value); break; +#ifdef G_OS_WIN32 + case PROP_WIN32_POINTER_INPUT_API: + core_config->win32_pointer_input_api = g_value_get_enum (value); + break; +#endif case PROP_INSTALL_COLORMAP: case PROP_MIN_COLORS: @@ -1395,6 +1414,11 @@ gimp_core_config_get_property (GObject *object, case PROP_DEBUG_POLICY: g_value_set_enum (value, core_config->debug_policy); break; +#ifdef G_OS_WIN32 + case PROP_WIN32_POINTER_INPUT_API: + g_value_set_enum (value, core_config->win32_pointer_input_api); + break; +#endif case PROP_INSTALL_COLORMAP: case PROP_MIN_COLORS: diff --git a/app/config/gimpcoreconfig.h b/app/config/gimpcoreconfig.h index 06d79770db..3b9bd49226 100644 --- a/app/config/gimpcoreconfig.h +++ b/app/config/gimpcoreconfig.h @@ -103,6 +103,9 @@ struct _GimpCoreConfig gboolean export_metadata_xmp; gboolean export_metadata_iptc; GimpDebugPolicy debug_policy; +#ifdef G_OS_WIN32 + GimpWin32PointerInputAPI win32_pointer_input_api; +#endif gboolean check_updates; gint64 check_update_timestamp; diff --git a/app/config/gimpearlyrc.c b/app/config/gimpearlyrc.c index f70340722a..b6a42b1f35 100644 --- a/app/config/gimpearlyrc.c +++ b/app/config/gimpearlyrc.c @@ -37,7 +37,10 @@ enum PROP_VERBOSE, PROP_SYSTEM_GIMPRC, PROP_USER_GIMPRC, - PROP_LANGUAGE + PROP_LANGUAGE, +#ifdef G_OS_WIN32 + PROP_WIN32_POINTER_INPUT_API, +#endif }; @@ -96,6 +99,14 @@ gimp_early_rc_class_init (GimpEarlyRcClass *klass) "language", NULL, NULL, NULL, GIMP_PARAM_STATIC_STRINGS); +#ifdef G_OS_WIN32 + GIMP_CONFIG_PROP_ENUM (object_class, PROP_WIN32_POINTER_INPUT_API, + "win32-pointer-input-api", NULL, NULL, + GIMP_TYPE_WIN32_POINTER_INPUT_API, + GIMP_WIN32_POINTER_INPUT_API_WINDOWS_INK, + GIMP_PARAM_STATIC_STRINGS | + GIMP_CONFIG_PARAM_RESTART); +#endif } static void @@ -197,6 +208,12 @@ gimp_early_rc_set_property (GObject *object, rc->language = g_value_dup_string (value); break; +#ifdef G_OS_WIN32 + case PROP_WIN32_POINTER_INPUT_API: + rc->win32_pointer_input_api = g_value_get_enum (value); + break; +#endif + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -226,6 +243,12 @@ gimp_early_rc_get_property (GObject *object, g_value_set_string (value, rc->language); break; +#ifdef G_OS_WIN32 + case PROP_WIN32_POINTER_INPUT_API: + g_value_set_enum (value, rc->win32_pointer_input_api); + break; +#endif + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -280,3 +303,22 @@ gimp_early_rc_get_language (GimpEarlyRc *rc) { return rc->language ? g_strdup (rc->language) : NULL; } + +#ifdef G_OS_WIN32 + +/** + * gimp_early_rc_get_win32_pointer_input_api: + * @rc: a #GimpEarlyRc object. + * + * This function looks up the win32-specific pointer input API + * set in `gimprc`. + * + * Returns: the selected win32-specific pointer input API + **/ +GimpWin32PointerInputAPI +gimp_early_rc_get_win32_pointer_input_api (GimpEarlyRc *rc) +{ + return rc->win32_pointer_input_api; +} + +#endif diff --git a/app/config/gimpearlyrc.h b/app/config/gimpearlyrc.h index 0abbb91659..b10835dac6 100644 --- a/app/config/gimpearlyrc.h +++ b/app/config/gimpearlyrc.h @@ -23,6 +23,7 @@ #ifndef __GIMP_EARLY_RC_H__ #define __GIMP_EARLY_RC_H__ +#include "core/core-enums.h" #define GIMP_TYPE_EARLY_RC (gimp_early_rc_get_type ()) #define GIMP_EARLY_RC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_EARLY_RC, GimpEarlyRc)) @@ -42,6 +43,10 @@ struct _GimpEarlyRc gboolean verbose; gchar *language; + +#ifdef G_OS_WIN32 + GimpWin32PointerInputAPI win32_pointer_input_api; +#endif }; struct _GimpEarlyRcClass @@ -57,6 +62,10 @@ GimpEarlyRc * gimp_early_rc_new (GFile *system_gimprc, gboolean verbose); gchar * gimp_early_rc_get_language (GimpEarlyRc *rc); +#ifdef G_OS_WIN32 +GimpWin32PointerInputAPI gimp_early_rc_get_win32_pointer_input_api (GimpEarlyRc *rc); +#endif + #endif /* GIMP_EARLY_RC_H__ */ diff --git a/app/config/gimprc-blurbs.h b/app/config/gimprc-blurbs.h index daa5b0fe9f..df04e20af4 100644 --- a/app/config/gimprc-blurbs.h +++ b/app/config/gimprc-blurbs.h @@ -247,6 +247,9 @@ _("Export IPTC metadata by default.") #define GENERATE_BACKTRACE_BLURB \ _("Try generating debug data for bug reporting when appropriate.") +#define WIN32_POINTER_INPUT_API_BLURB \ +_("Sets the preferred pen and touch input API.") + #define INITIAL_ZOOM_TO_FIT_BLURB \ _("When enabled, this will ensure that the full image is visible after a " \ "file is opened, otherwise it will be displayed with a scale of 1:1.") diff --git a/app/core/core-enums.c b/app/core/core-enums.c index 1875023b6d..9b459c9320 100644 --- a/app/core/core-enums.c +++ b/app/core/core-enums.c @@ -989,6 +989,35 @@ gimp_paste_type_get_type (void) return type; } +GType +gimp_win32_pointer_input_api_get_type (void) +{ + static const GEnumValue values[] = + { + { GIMP_WIN32_POINTER_INPUT_API_WINTAB, "GIMP_WIN32_POINTER_INPUT_API_WINTAB", "wintab" }, + { GIMP_WIN32_POINTER_INPUT_API_WINDOWS_INK, "GIMP_WIN32_POINTER_INPUT_API_WINDOWS_INK", "windows-ink" }, + { 0, NULL, NULL } + }; + + static const GimpEnumDesc descs[] = + { + { GIMP_WIN32_POINTER_INPUT_API_WINTAB, NC_("win32-pointer-input-api", "Wintab"), NULL }, + { GIMP_WIN32_POINTER_INPUT_API_WINDOWS_INK, NC_("win32-pointer-input-api", "Windows Ink"), NULL }, + { 0, NULL, NULL } + }; + + static GType type = 0; + + if (G_UNLIKELY (! type)) + { + type = g_enum_register_static ("GimpWin32PointerInputAPI", values); + gimp_type_set_translation_context (type, "win32-pointer-input-api"); + gimp_enum_set_value_descriptions (type, descs); + } + + return type; +} + GType gimp_thumbnail_size_get_type (void) { diff --git a/app/core/core-enums.h b/app/core/core-enums.h index 9fef881eae..ead4a09fc8 100644 --- a/app/core/core-enums.h +++ b/app/core/core-enums.h @@ -447,6 +447,17 @@ typedef enum /*< pdb-skip >*/ } GimpPasteType; +#define GIMP_TYPE_WIN32_POINTER_INPUT_API (gimp_win32_pointer_input_api_get_type ()) + +GType gimp_win32_pointer_input_api_get_type (void) G_GNUC_CONST; + +typedef enum /*< pdb-skip >*/ +{ + GIMP_WIN32_POINTER_INPUT_API_WINTAB, /*< desc="Wintab" >*/ + GIMP_WIN32_POINTER_INPUT_API_WINDOWS_INK /*< desc="Windows Ink" >*/ +} GimpWin32PointerInputAPI; + + #define GIMP_TYPE_THUMBNAIL_SIZE (gimp_thumbnail_size_get_type ()) GType gimp_thumbnail_size_get_type (void) G_GNUC_CONST; diff --git a/app/core/gimp-utils.c b/app/core/gimp-utils.c index d36ce0af91..14afd88677 100644 --- a/app/core/gimp-utils.c +++ b/app/core/gimp-utils.c @@ -1137,6 +1137,44 @@ gimp_idle_run_async_full (gint priority, return g_object_ref (data->async); } +#ifdef G_OS_WIN32 + +gboolean +gimp_win32_have_wintab (void) +{ + gunichar2 wchars_buffer[MAX_PATH + 1]; + UINT wchars_count = 0; + + memset (wchars_buffer, 0, sizeof (wchars_buffer)); + wchars_count = GetSystemDirectoryW (wchars_buffer, MAX_PATH); + if (wchars_count > 0 && wchars_count < MAX_PATH) + { + char *system32_directory = g_utf16_to_utf8 (wchars_buffer, -1, NULL, NULL, NULL); + + if (system32_directory) + { + GFile *file = g_file_new_build_filename (system32_directory, "Wintab32.dll", NULL); + gboolean exists = g_file_query_exists (file, NULL); + + g_object_unref (file); + g_free (system32_directory); + + return exists; + } + } + + return FALSE; +} + +gboolean +gimp_win32_have_windows_ink (void) +{ + /* Check for Windows 8 or later */ + return g_win32_check_windows_version (6, 2, 0, G_WIN32_OS_ANY); +} + +#endif + /* debug stuff */ diff --git a/app/core/gimp-utils.h b/app/core/gimp-utils.h index ca60d99017..371c42b920 100644 --- a/app/core/gimp-utils.h +++ b/app/core/gimp-utils.h @@ -118,5 +118,11 @@ GimpImage * gimp_create_image_from_buffer (Gimp *gimp, GeglBuffer *buffer, const gchar *image_name); +#ifdef G_OS_WIN32 + +gboolean gimp_win32_have_wintab (void); +gboolean gimp_win32_have_windows_ink (void); + +#endif #endif /* __APP_GIMP_UTILS_H__ */ diff --git a/app/dialogs/preferences-dialog.c b/app/dialogs/preferences-dialog.c index d93c7102a5..1d77e072c9 100644 --- a/app/dialogs/preferences-dialog.c +++ b/app/dialogs/preferences-dialog.c @@ -34,6 +34,7 @@ #include "core/gimp.h" #include "core/gimptemplate.h" +#include "core/gimp-utils.h" #include "plug-in/gimppluginmanager.h" @@ -757,6 +758,37 @@ prefs_devices_clear_callback (GtkWidget *widget, } } +#ifdef G_OS_WIN32 + +static gboolean +prefs_devices_api_sensitivity_func (gint value, + gpointer data) +{ + static gboolean have_wintab = TRUE; + static gboolean have_windows_ink = TRUE; + static gboolean inited = FALSE; + + if (!inited) + { + have_wintab = gimp_win32_have_wintab (); + have_windows_ink = gimp_win32_have_windows_ink (); + + inited = TRUE; + } + + switch (value) + { + case GIMP_WIN32_POINTER_INPUT_API_WINTAB: + return have_wintab; + case GIMP_WIN32_POINTER_INPUT_API_WINDOWS_INK: + return have_windows_ink; + default: + return TRUE; + } +} + +#endif + static void prefs_search_clear_callback (GtkWidget *widget, Gimp *gimp) @@ -3131,6 +3163,29 @@ prefs_dialog_new (Gimp *gimp, vbox2 = prefs_frame_new (_("Extended Input Devices"), GTK_CONTAINER (vbox), FALSE); +#ifdef G_OS_WIN32 + + if ((gtk_get_major_version () == 3 && + gtk_get_minor_version () > 24) || + (gtk_get_major_version () == 3 && + gtk_get_minor_version () == 24 && + gtk_get_micro_version () >= 30)) + { + GtkWidget *combo; + + grid = prefs_grid_new (GTK_CONTAINER (vbox2)); + + combo = prefs_enum_combo_box_add (object, "win32-pointer-input-api", 0, 0, + _("Pointer Input API:"), + GTK_GRID (grid), 0, NULL); + + gimp_int_combo_box_set_sensitivity (GIMP_INT_COMBO_BOX (combo), + prefs_devices_api_sensitivity_func, + NULL, NULL); + } + +#endif + prefs_check_button_add (object, "devices-share-tool", _("S_hare tool and tool options between input devices"), GTK_BOX (vbox2));