[gimp] app: better code to handle GimpDeviceInfo axes.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: better code to handle GimpDeviceInfo axes.
- Date: Tue, 8 Dec 2020 19:32:27 +0000 (UTC)
commit de739bde2392d2e052e8976c881fd901609b6351
Author: Jehan <jehan girinstud io>
Date: Tue Dec 8 20:23:14 2020 +0100
app: better code to handle GimpDeviceInfo axes.
Axis names can now be returned with gimp_device_info_get_axis_name() and
I added a dedicated function gimp_device_info_ignore_axis() to handle
the case of an axis to ignore.
I also improved the code with less redundancy to handle the axes data
(both the use and name arrays will always exist and be created and will
be n_axes size, hence avoiding bad out-of-bound reads). This includes
some code refactorization avoiding near code duplication to make sure we
always have the same logics, by creating the gimp_device_info_updated()
static function.
app/widgets/gimpdeviceinfo.c | 305 ++++++++++++++++++++++---------------
app/widgets/gimpdeviceinfo.h | 4 +
app/widgets/gimpdeviceinfoeditor.c | 40 +----
3 files changed, 191 insertions(+), 158 deletions(-)
---
diff --git a/app/widgets/gimpdeviceinfo.c b/app/widgets/gimpdeviceinfo.c
index c1ed7eb18c..43d8454b15 100644
--- a/app/widgets/gimpdeviceinfo.c
+++ b/app/widgets/gimpdeviceinfo.c
@@ -45,6 +45,30 @@
#define GIMP_DEVICE_INFO_DATA_KEY "gimp-device-info"
+/**
+ * Some default names for axis. We will only use them when the device is
+ * not plugged (in which case, we would use names returned by GDK).
+ */
+static const gchar *const axis_use_strings[] =
+{
+ N_("X"),
+ N_("Y"),
+ N_("Pressure"),
+ N_("X tilt"),
+ N_("Y tilt"),
+ /* Wheel as in mouse or input device wheel.
+ * Some pens would use the same axis for their rotation feature.
+ * See bug 791455.
+ * Yet GTK+ has a different axis since v. 3.22.
+ * TODO: this should be actually tested with a device having such
+ * feature.
+ */
+ N_("Wheel"),
+ N_("Distance"),
+ N_("Rotation"),
+ N_("Slider")
+};
+
enum
{
@@ -83,6 +107,8 @@ static void gimp_device_info_tool_changed (GdkDevice *device,
GdkDeviceTool *tool,
GimpDeviceInfo *info);
+static void gimp_device_info_updated (GimpDeviceInfo *info);
+
G_DEFINE_TYPE (GimpDeviceInfo, gimp_device_info, GIMP_TYPE_TOOL_PRESET)
@@ -108,16 +134,18 @@ gimp_device_info_class_init (GimpDeviceInfoClass *klass)
NULL, NULL,
GDK_TYPE_DEVICE,
GIMP_PARAM_STATIC_STRINGS |
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT));
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_EXPLICIT_NOTIFY));
g_object_class_install_property (object_class, PROP_DISPLAY,
g_param_spec_object ("display",
NULL, NULL,
GDK_TYPE_DISPLAY,
GIMP_PARAM_STATIC_STRINGS |
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT));
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_EXPLICIT_NOTIFY));
GIMP_CONFIG_PROP_ENUM (object_class, PROP_MODE,
"mode",
@@ -223,42 +251,10 @@ gimp_device_info_constructed (GObject *object)
G_OBJECT_CLASS (parent_class)->constructed (object);
+ gimp_device_info_updated (info);
+
gimp_assert ((info->device == NULL && info->display == NULL) ||
(GDK_IS_DEVICE (info->device) && GDK_IS_DISPLAY (info->display)));
-
- if (info->device)
- {
- GList *axes;
- GList *iter;
- gint i;
-
- g_object_set_data (G_OBJECT (info->device), GIMP_DEVICE_INFO_DATA_KEY,
- info);
-
- gimp_object_set_name (GIMP_OBJECT (info),
- gdk_device_get_name (info->device));
-
- info->mode = gdk_device_get_mode (info->device);
-
- axes = gdk_device_list_axes (info->device);
- info->n_axes = g_list_length (axes);
-
- info->axes = g_new0 (GdkAxisUse, info->n_axes);
- info->axes_names = g_new0 (gchar *, info->n_axes + 1);
- for (i = 0, iter = axes; i < info->n_axes; i++, iter = iter->next)
- {
- info->axes[i] = gdk_device_get_axis_use (info->device, i);
- info->axes_names[i] = gdk_atom_name (iter->data);
- }
- g_list_free (axes);
-
- info->n_keys = gdk_device_get_n_keys (info->device);
- info->keys = g_new0 (GimpDeviceKey, info->n_keys);
- for (i = 0; i < info->n_keys; i++)
- gdk_device_get_key (info->device, i,
- &info->keys[i].keyval,
- &info->keys[i].modifiers);
- }
}
static void
@@ -289,15 +285,7 @@ gimp_device_info_set_property (GObject *object,
switch (property_id)
{
case PROP_DEVICE:
- if (info->device)
- g_signal_handlers_disconnect_by_func (info->device,
- gimp_device_info_tool_changed,
- info);
info->device = g_value_get_object (value);
- if (info->device)
- g_signal_connect_object (info->device, "tool-changed",
- G_CALLBACK (gimp_device_info_tool_changed),
- G_OBJECT (info), 0);
break;
case PROP_DISPLAY:
@@ -310,6 +298,7 @@ gimp_device_info_set_property (GObject *object,
case PROP_AXES:
{
+ /* Axes information as stored in devicerc. */
GimpValueArray *array = g_value_get_boxed (value);
if (array)
@@ -318,12 +307,20 @@ gimp_device_info_set_property (GObject *object,
gint n_device_values = gimp_value_array_length (array);
if (device)
- n_device_values = MIN (n_device_values,
- gdk_device_get_n_axes (device));
-
- info->n_axes = n_device_values;
- info->axes = g_renew (GdkAxisUse, info->axes, info->n_axes);
- memset (info->axes, 0, info->n_axes * sizeof (GdkAxisUse));
+ {
+ if (info->n_axes != 0 && info->n_axes != n_device_values)
+ g_printerr ("%s: stored 'num-axes' for device '%s' doesn't match "
+ "number of axes present in device\n",
+ G_STRFUNC, gdk_device_get_name (device));
+ n_device_values = MIN (n_device_values,
+ gdk_device_get_n_axes (device));
+ }
+ else if (! info->n_axes)
+ {
+ info->n_axes = n_device_values;
+ info->axes = g_new0 (GdkAxisUse, info->n_axes);
+ info->axes_names = g_new0 (gchar *, info->n_axes + 1);
+ }
for (i = 0; i < n_device_values; i++)
{
@@ -570,6 +567,86 @@ gimp_device_info_tool_changed (GdkDevice *device,
g_object_thaw_notify (G_OBJECT (info));
}
+static void
+gimp_device_info_updated (GimpDeviceInfo *info)
+{
+ g_return_if_fail (GIMP_IS_DEVICE_INFO (info));
+ g_return_if_fail ((info->device == NULL && info->display == NULL) ||
+ (GDK_IS_DEVICE (info->device) && GDK_IS_DISPLAY (info->display)));
+
+ g_object_freeze_notify (G_OBJECT (info));
+
+ if (info->device)
+ {
+ GdkAxisUse *old_uses;
+ GList *axes;
+ GList *iter;
+ gint old_n_axes;
+ gint i;
+
+ GimpDeviceKey *old_keys;
+ gint old_n_keys;
+
+ g_object_set_data (G_OBJECT (info->device), GIMP_DEVICE_INFO_DATA_KEY, info);
+ gimp_object_set_name (GIMP_OBJECT (info),
+ gdk_device_get_name (info->device));
+ gimp_device_info_set_mode (info, gdk_device_get_mode (info->device));
+
+ old_n_axes = info->n_axes;
+ old_uses = info->axes;
+ g_strfreev (info->axes_names);
+ axes = gdk_device_list_axes (info->device);
+ info->n_axes = g_list_length (axes);
+ info->axes = g_new0 (GdkAxisUse, info->n_axes);
+ info->axes_names = g_new0 (gchar *, info->n_axes + 1);
+
+ for (i = 0, iter = axes; i < info->n_axes; i++, iter = iter->next)
+ {
+ GdkAxisUse use;
+
+ use = (i < old_n_axes) ? old_uses[i] : gdk_device_get_axis_use (info->device, i);
+ gimp_device_info_set_axis_use (info, i, use);
+
+ if (iter->data != GDK_NONE)
+ info->axes_names[i] = gdk_atom_name (iter->data);
+ else
+ info->axes_names[i] = NULL;
+ }
+ g_list_free (axes);
+ g_clear_pointer (&old_uses, g_free);
+
+ old_n_keys = info->n_keys;
+ old_keys = info->keys;
+ info->n_keys = gdk_device_get_n_keys (info->device);
+ info->keys = g_new0 (GimpDeviceKey, info->n_keys);
+
+ for (i = 0; i < info->n_keys; i++)
+ {
+ GimpDeviceKey key;
+
+ if (i < old_n_keys)
+ key = old_keys[i];
+ else
+ gdk_device_get_key (info->device, i, &key.keyval, &key.modifiers);
+ gimp_device_info_set_key (info, i, key.keyval, key.modifiers);
+ }
+ g_clear_pointer (&old_keys, g_free);
+ }
+
+ /* sort order depends on device presence */
+ gimp_object_name_changed (GIMP_OBJECT (info));
+
+ g_object_notify (G_OBJECT (info), "source");
+ g_object_notify (G_OBJECT (info), "vendor-id");
+ g_object_notify (G_OBJECT (info), "product-id");
+ g_object_notify (G_OBJECT (info), "tool-type");
+ g_object_notify (G_OBJECT (info), "tool-serial");
+ g_object_notify (G_OBJECT (info), "tool-hardware-id");
+ g_object_notify (G_OBJECT (info), "device");
+ g_object_notify (G_OBJECT (info), "display");
+
+ g_object_thaw_notify (G_OBJECT (info));
+}
/* public functions */
@@ -616,12 +693,15 @@ gimp_device_info_set_device (GimpDeviceInfo *info,
GdkDevice *device,
GdkDisplay *display)
{
- gint i;
+ GdkInputMode mode;
g_return_val_if_fail (GIMP_IS_DEVICE_INFO (info), FALSE);
g_return_val_if_fail ((device == NULL && display == NULL) ||
(GDK_IS_DEVICE (device) && GDK_IS_DISPLAY (display)),
FALSE);
+ g_return_val_if_fail (device == NULL ||
+ strcmp (gdk_device_get_name (device),
+ gimp_object_get_name (info)) == 0, FALSE);
if (device && info->device)
{
@@ -659,90 +739,39 @@ gimp_device_info_set_device (GimpDeviceInfo *info,
/* bail out, unsetting twice makes no sense */
return FALSE;
}
-
- g_return_val_if_fail (device == NULL ||
- strcmp (gdk_device_get_name (device),
- gimp_object_get_name (info)) == 0, FALSE);
-
- g_object_freeze_notify (G_OBJECT (info));
-
- if (device)
+ else if (info->device)
{
- g_object_set (info,
- "device", device,
- "display", display,
- NULL);
-
- g_object_set_data (G_OBJECT (device), GIMP_DEVICE_INFO_DATA_KEY, info);
-
- gimp_device_info_set_mode (info, info->mode);
-
- if (info->n_axes != gdk_device_get_n_axes (device))
+ if (info->n_axes != gdk_device_get_n_axes (info->device))
g_printerr ("%s: stored 'num-axes' for device '%s' doesn't match "
"number of axes present in device\n",
- G_STRFUNC, gdk_device_get_name (device));
-
- for (i = 0; i < MIN (info->n_axes, gdk_device_get_n_axes (device)); i++)
- gimp_device_info_set_axis_use (info, i,
- info->axes[i]);
+ G_STRFUNC, gdk_device_get_name (info->device));
- if (info->n_keys != gdk_device_get_n_keys (device))
+ if (info->n_keys != gdk_device_get_n_keys (info->device))
g_printerr ("%s: stored 'num-keys' for device '%s' doesn't match "
"number of keys present in device\n",
- G_STRFUNC, gdk_device_get_name (device));
-
- for (i = 0; i < MIN (info->n_keys, gdk_device_get_n_keys (device)); i++)
- gimp_device_info_set_key (info, i,
- info->keys[i].keyval,
- info->keys[i].modifiers);
+ G_STRFUNC, gdk_device_get_name (info->device));
}
- else
- {
- device = info->device;
- display = info->display;
-
- g_object_set (info,
- "device", NULL,
- "display", NULL,
- NULL);
-
- g_object_set_data (G_OBJECT (device), GIMP_DEVICE_INFO_DATA_KEY, NULL);
- gimp_device_info_set_mode (info, gdk_device_get_mode (device));
-
- info->n_axes = gdk_device_get_n_axes (device);
- info->axes = g_renew (GdkAxisUse, info->axes, info->n_axes);
- memset (info->axes, 0, info->n_axes * sizeof (GdkAxisUse));
-
- for (i = 0; i < info->n_axes; i++)
- gimp_device_info_set_axis_use (info, i,
- gdk_device_get_axis_use (device, i));
-
- info->n_keys = gdk_device_get_n_keys (device);
- info->keys = g_renew (GimpDeviceKey, info->keys, info->n_keys);
- memset (info->keys, 0, info->n_keys * sizeof (GimpDeviceKey));
-
- for (i = 0; i < info->n_keys; i++)
- {
- guint keyval = 0;
- GdkModifierType modifiers = 0;
-
- gdk_device_get_key (device, i, &keyval, &modifiers);
- gimp_device_info_set_key (info, i, keyval, modifiers);
- }
+ if (info->device)
+ {
+ g_object_set_data (G_OBJECT (info->device),
+ GIMP_DEVICE_INFO_DATA_KEY, NULL);
+ g_signal_handlers_disconnect_by_func (info->device,
+ gimp_device_info_tool_changed,
+ info);
}
+ mode = gimp_device_info_get_mode (info);
- /* sort order depends on device presence */
- gimp_object_name_changed (GIMP_OBJECT (info));
-
- g_object_notify (G_OBJECT (info), "source");
- g_object_notify (G_OBJECT (info), "vendor-id");
- g_object_notify (G_OBJECT (info), "product-id");
- g_object_notify (G_OBJECT (info), "tool-type");
- g_object_notify (G_OBJECT (info), "tool-serial");
- g_object_notify (G_OBJECT (info), "tool-hardware-id");
+ info->device = device;
+ info->display = display;
+ if (info->device)
+ g_signal_connect_object (info->device, "tool-changed",
+ G_CALLBACK (gimp_device_info_tool_changed),
+ G_OBJECT (info), 0);
- g_object_thaw_notify (G_OBJECT (info));
+ gimp_device_info_updated (info);
+ /* The info existed from a previous run. Restore its mode. */
+ gimp_device_info_set_mode (info, mode);
return TRUE;
}
@@ -1036,6 +1065,30 @@ gimp_device_info_get_n_axes (GimpDeviceInfo *info)
return info->n_axes;
}
+gboolean
+gimp_device_info_ignore_axis (GimpDeviceInfo *info,
+ gint axis)
+{
+ g_return_val_if_fail (GIMP_IS_DEVICE_INFO (info), TRUE);
+ g_return_val_if_fail (axis >= 0 && axis < info->n_axes, TRUE);
+
+ return (info->axes_names[axis] == NULL);
+}
+
+const gchar *
+gimp_device_info_get_axis_name (GimpDeviceInfo *info,
+ gint axis)
+{
+ g_return_val_if_fail (GIMP_IS_DEVICE_INFO (info), NULL);
+ g_return_val_if_fail (axis >= 0 && axis < GDK_AXIS_LAST, NULL);
+
+ if (info->device && axis < info->n_axes &&
+ info->axes_names[axis] != NULL)
+ return info->axes_names[axis];
+ else
+ return axis_use_strings[axis];
+}
+
GdkAxisUse
gimp_device_info_get_axis_use (GimpDeviceInfo *info,
gint axis)
diff --git a/app/widgets/gimpdeviceinfo.h b/app/widgets/gimpdeviceinfo.h
index 9ae22b4f3d..32d3c8adc0 100644
--- a/app/widgets/gimpdeviceinfo.h
+++ b/app/widgets/gimpdeviceinfo.h
@@ -104,6 +104,10 @@ guint64 gimp_device_info_get_tool_serial (GimpDeviceInfo *info);
guint64 gimp_device_info_get_tool_hardware_id (GimpDeviceInfo *info);
gint gimp_device_info_get_n_axes (GimpDeviceInfo *info);
+gboolean gimp_device_info_ignore_axis (GimpDeviceInfo *info,
+ gint axis);
+const gchar * gimp_device_info_get_axis_name (GimpDeviceInfo *info,
+ gint axis);
GdkAxisUse gimp_device_info_get_axis_use (GimpDeviceInfo *info,
gint axis);
void gimp_device_info_set_axis_use (GimpDeviceInfo *info,
diff --git a/app/widgets/gimpdeviceinfoeditor.c b/app/widgets/gimpdeviceinfoeditor.c
index 0816a36ac3..fae056acc9 100644
--- a/app/widgets/gimpdeviceinfoeditor.c
+++ b/app/widgets/gimpdeviceinfoeditor.c
@@ -126,27 +126,6 @@ G_DEFINE_TYPE_WITH_PRIVATE (GimpDeviceInfoEditor, gimp_device_info_editor,
#define parent_class gimp_device_info_editor_parent_class
-static const gchar *const axis_use_strings[] =
-{
- N_("X"),
- N_("Y"),
- N_("Pressure"),
- N_("X tilt"),
- N_("Y tilt"),
- /* Wheel as in mouse or input device wheel.
- * Some pens would use the same axis for their rotation feature.
- * See bug 791455.
- * Yet GTK+ has a different axis since v. 3.22.
- * TODO: this should be actually tested with a device having such
- * feature.
- */
- N_("Wheel"),
- N_("Distance"),
- N_("Rotation"),
- N_("Slider")
-};
-
-
static void
gimp_device_info_editor_class_init (GimpDeviceInfoEditorClass *klass)
{
@@ -227,21 +206,17 @@ gimp_device_info_editor_constructed (GObject *object)
if (private->info->device)
{
- use = gimp_device_info_get_axis_use (private->info, i);
- if (use == GDK_AXIS_IGNORE)
- /* Some axis are apparently returned by the driver, yet with use
- * IGNORE. We just pass these.
+ if (gimp_device_info_ignore_axis (private->info, i))
+ /* Some axis are apparently returned by the driver, yet
+ * should be ignored. We just pass these.
*/
continue;
- axis_name = private->info->axes_names[i];
+ use = gimp_device_info_get_axis_use (private->info, i);
has_curve = (gimp_device_info_get_curve (private->info, use) != NULL);
}
- else
- {
- axis_name = axis_use_strings[i];
- }
+ axis_name = gimp_device_info_get_axis_name (private->info, i);
gtk_list_store_insert_with_values (private->axis_store,
/* Set the initially selected
* axis to an axis with curve
@@ -402,7 +377,8 @@ gimp_device_info_editor_constructed (GObject *object)
gchar *title;
/* e.g. "Pressure Curve" for mapping input device axes */
- title = g_strdup_printf (_("%s Curve"), gettext (axis_use_strings[i - 1]));
+ title = g_strdup_printf (_("%s Curve"),
+ gettext (gimp_device_info_get_axis_name (private->info, i - 1)));
frame = gimp_frame_new (title);
gtk_notebook_append_page (GTK_NOTEBOOK (private->notebook), frame, NULL);
@@ -475,7 +451,7 @@ gimp_device_info_editor_constructed (GObject *object)
gchar *string;
string = g_strdup_printf (_("The axis '%s' has no curve"),
- gettext (axis_use_strings[i - 1]));
+ gettext (gimp_device_info_get_axis_name (private->info, i - 1)));
label = gtk_label_new (string);
gtk_container_add (GTK_CONTAINER (frame), label);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]