Copy pressed_keys list before sending released/cancelled signal (RHBZ#737396).

This commit is contained in:
Daiki Ueno
2011-09-12 11:06:26 +09:00
parent 0d93f31eea
commit f72e9f5293
2 changed files with 30 additions and 17 deletions

View File

@ -229,12 +229,17 @@ eek_gtk_keyboard_real_button_release_event (GtkWidget *self,
GdkEventButton *event) GdkEventButton *event)
{ {
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self); EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
GList *head; GList *head = eek_keyboard_get_pressed_keys (priv->keyboard);
head = eek_keyboard_get_pressed_keys (priv->keyboard); /* Make a copy of HEAD before sending "released" signal on
for (; head; head = g_list_next (head)) { elements, so that the default handler of
EekKeyboard::key-released signal can remove elements from its
internal copy */
head = g_list_copy (head);
for (; head; head = g_list_next (head))
g_signal_emit_by_name (head->data, "released", priv->keyboard); g_signal_emit_by_name (head->data, "released", priv->keyboard);
} g_list_free (head);
return TRUE; return TRUE;
} }
@ -251,12 +256,20 @@ eek_gtk_keyboard_real_motion_notify_event (GtkWidget *self,
if (key) { if (key) {
GList *head = eek_keyboard_get_pressed_keys (priv->keyboard); GList *head = eek_keyboard_get_pressed_keys (priv->keyboard);
gboolean found = FALSE; gboolean found = FALSE;
/* Make a copy of HEAD before sending "cancelled" signal on
elements, so that the default handler of
EekKeyboard::key-cancelled signal can remove elements from its
internal copy */
head = g_list_copy (head);
for (; head; head = g_list_next (head)) { for (; head; head = g_list_next (head)) {
if (head->data == key) if (head->data == key)
found = TRUE; found = TRUE;
else else
g_signal_emit_by_name (head->data, "cancelled", priv->keyboard); g_signal_emit_by_name (head->data, "cancelled", priv->keyboard);
} }
g_list_free (head);
if (!found) if (!found)
g_signal_emit_by_name (key, "pressed", priv->keyboard); g_signal_emit_by_name (key, "pressed", priv->keyboard);
} }
@ -269,12 +282,16 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self)
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self); EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
if (priv->keyboard) { if (priv->keyboard) {
GList *head; GList *head = eek_keyboard_get_pressed_keys (priv->keyboard);
head = eek_keyboard_get_pressed_keys (priv->keyboard); /* Make a copy of HEAD before sending "released" signal on
for (; head; head = g_list_next (head)) { elements, so that the default handler of
EekKeyboard::key-released signal can remove elements from its
internal copy */
head = g_list_copy (head);
for (; head; head = g_list_next (head))
g_signal_emit_by_name (head->data, "released", priv->keyboard); g_signal_emit_by_name (head->data, "released", priv->keyboard);
} g_list_free (head);
} }
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->unmap (self); GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->unmap (self);

View File

@ -331,16 +331,12 @@ eek_keyboard_real_key_cancelled (EekKeyboard *self,
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self); EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
GList *head; GList *head;
for (head = priv->pressed_keys; head; ) { for (head = priv->pressed_keys; head; head = g_list_next (head)) {
EekKey *pressed_key = head->data; if (head->data == key) {
if (pressed_key == key) { priv->pressed_keys = g_list_remove_link (priv->pressed_keys, head);
GList *next = g_list_next (head);
priv->pressed_keys =
g_list_remove_link (priv->pressed_keys, head);
g_list_free1 (head); g_list_free1 (head);
head = next; break;
} else }
head = g_list_next (head);
} }
} }