mirror of https://github.com/GNOME/gimp.git
app: fix text tool drawing for good this time (hopefully)
Earlier I claimed that drawing would work now because we make sure that buffer and layout are always in sync. This was nonsense. In fact, we constantly ran into the sutiation where the buffer was modified, and we were drawing with the previous layout. It's unclear why this didn't cause drawing artifacts, but it did cause e.g. the cursor temporarily jumping to the next position while editing in the middle of text (especially visible at line ends). Several underlying problems existed: first, we now modify the buffer from outside the text tool (from GimpTextStyleEditor) where we can't pause the tool; second, proxy changes are handled asymetrically (property changes are queued and processed all together in an idle function) so we can't pause/resume drawing across the entire operation because it has many beginnings and only one end. Therefore: - add gimp_text_tool_block_drawing()/unblock_drawing(), where block() can be called as many times as needed, and a single unblock() enables drawing again. block() also clears the layout, because it served its purpose (it was just used to pause drawing, and we know the buffer will change, so kill it). - connect to GtkTextBuffer::begin-user-action and call block() from the callback, so we undraw stuff and kill the cached layout before any buffer change happens. - call unblock() at the end of gimp_text_tool_apply() because then the text and the buffer are in sync again, the tool is undrawn and we can safely create the layout again to draw our stuff. - also call block()/unblock() from some other places, like when a new text layer is created. - get rid of *all* calls to draw_tool_pause()/resume() around buffer modifications, they are not needed any longer. - add calls to begin/end_user_action() where they were missing.
This commit is contained in:
parent
e54a05f78f
commit
5284c9c836
|
@ -416,15 +416,11 @@ gimp_text_tool_editor_key_press (GimpTextTool *text_tool,
|
|||
gint x_pos = -1;
|
||||
gboolean retval = TRUE;
|
||||
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
if (gtk_im_context_filter_keypress (text_tool->im_context, kevent))
|
||||
{
|
||||
text_tool->needs_im_reset = TRUE;
|
||||
text_tool->x_pos = -1;
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -435,8 +431,6 @@ gimp_text_tool_editor_key_press (GimpTextTool *text_tool,
|
|||
{
|
||||
GIMP_LOG (TEXT_EDITING, "binding handled event");
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -473,8 +467,6 @@ gimp_text_tool_editor_key_press (GimpTextTool *text_tool,
|
|||
|
||||
text_tool->x_pos = x_pos;
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -833,11 +825,7 @@ static void
|
|||
gimp_text_tool_insert_at_cursor (GimpTextTool *text_tool,
|
||||
const gchar *str)
|
||||
{
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
gimp_text_buffer_insert (text_tool->buffer, str);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -896,11 +884,7 @@ gimp_text_tool_delete_from_cursor (GimpTextTool *text_tool,
|
|||
case GTK_DELETE_CHARS:
|
||||
if (gtk_text_buffer_get_has_selection (buffer))
|
||||
{
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
gtk_text_buffer_delete_selection (buffer, TRUE, TRUE);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -962,11 +946,7 @@ gimp_text_tool_delete_from_cursor (GimpTextTool *text_tool,
|
|||
|
||||
if (! gtk_text_iter_equal (&cursor, &end))
|
||||
{
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
gtk_text_buffer_delete_interactive (buffer, &cursor, &end, TRUE);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -977,8 +957,6 @@ gimp_text_tool_backspace (GimpTextTool *text_tool)
|
|||
|
||||
gimp_text_tool_reset_im_context (text_tool);
|
||||
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
if (gtk_text_buffer_get_has_selection (buffer))
|
||||
{
|
||||
gtk_text_buffer_delete_selection (buffer, TRUE, TRUE);
|
||||
|
@ -992,8 +970,6 @@ gimp_text_tool_backspace (GimpTextTool *text_tool)
|
|||
|
||||
gtk_text_buffer_backspace (buffer, &cursor, TRUE, TRUE);
|
||||
}
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1048,13 +1024,9 @@ gimp_text_tool_change_baseline (GimpTextTool *text_tool,
|
|||
gtk_text_buffer_get_end_iter (buffer, &end);
|
||||
}
|
||||
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
gtk_text_iter_order (&start, &end);
|
||||
gimp_text_buffer_change_baseline (text_tool->buffer, &start, &end,
|
||||
count * PANGO_SCALE);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1073,13 +1045,9 @@ gimp_text_tool_change_kerning (GimpTextTool *text_tool,
|
|||
gtk_text_iter_forward_char (&end);
|
||||
}
|
||||
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
gtk_text_iter_order (&start, &end);
|
||||
gimp_text_buffer_change_kerning (text_tool->buffer, &start, &end,
|
||||
count * PANGO_SCALE);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1167,7 +1135,7 @@ gimp_text_tool_enter_text (GimpTextTool *text_tool,
|
|||
|
||||
had_selection = gtk_text_buffer_get_has_selection (buffer);
|
||||
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
gtk_text_buffer_begin_user_action (buffer);
|
||||
|
||||
gimp_text_tool_delete_selection (text_tool);
|
||||
|
||||
|
@ -1184,7 +1152,7 @@ gimp_text_tool_enter_text (GimpTextTool *text_tool,
|
|||
|
||||
gimp_text_buffer_insert (text_tool->buffer, str);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
gtk_text_buffer_end_user_action (buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -163,7 +163,12 @@ static gboolean gimp_text_tool_set_drawable (GimpTextTool *text_tool,
|
|||
GimpDrawable *drawable,
|
||||
gboolean confirm);
|
||||
|
||||
static void gimp_text_tool_buffer_edited (GimpTextBuffer *buffer,
|
||||
static void gimp_text_tool_block_drawing (GimpTextTool *text_tool);
|
||||
static void gimp_text_tool_unblock_drawing (GimpTextTool *text_tool);
|
||||
|
||||
static void gimp_text_tool_buffer_begin_edit (GimpTextBuffer *buffer,
|
||||
GimpTextTool *text_tool);
|
||||
static void gimp_text_tool_buffer_end_edit (GimpTextBuffer *buffer,
|
||||
GimpTextTool *text_tool);
|
||||
|
||||
|
||||
|
@ -246,8 +251,11 @@ gimp_text_tool_init (GimpTextTool *text_tool)
|
|||
|
||||
text_tool->buffer = gimp_text_buffer_new ();
|
||||
|
||||
g_signal_connect (text_tool->buffer, "begin-user-action",
|
||||
G_CALLBACK (gimp_text_tool_buffer_begin_edit),
|
||||
text_tool);
|
||||
g_signal_connect (text_tool->buffer, "end-user-action",
|
||||
G_CALLBACK (gimp_text_tool_buffer_edited),
|
||||
G_CALLBACK (gimp_text_tool_buffer_end_edit),
|
||||
text_tool);
|
||||
|
||||
text_tool->handle_rectangle_change_complete = TRUE;
|
||||
|
@ -496,13 +504,19 @@ gimp_text_tool_button_release (GimpTool *tool,
|
|||
* can we do...
|
||||
*/
|
||||
g_signal_handlers_block_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_edited,
|
||||
gimp_text_tool_buffer_begin_edit,
|
||||
text_tool);
|
||||
g_signal_handlers_block_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_end_edit,
|
||||
text_tool);
|
||||
|
||||
gimp_text_tool_editor_button_release (text_tool);
|
||||
|
||||
g_signal_handlers_unblock_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_edited,
|
||||
gimp_text_tool_buffer_end_edit,
|
||||
text_tool);
|
||||
g_signal_handlers_unblock_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_begin_edit,
|
||||
text_tool);
|
||||
|
||||
text_tool->selecting = FALSE;
|
||||
|
@ -872,6 +886,8 @@ gimp_text_tool_rectangle_change_complete (GimpRectangleTool *rect_tool)
|
|||
|
||||
gimp_image_get_resolution (text_tool->image, &xres, &yres);
|
||||
|
||||
gimp_text_tool_block_drawing (text_tool);
|
||||
|
||||
g_object_set (text_tool->proxy,
|
||||
"box-mode", GIMP_TEXT_BOX_FIXED,
|
||||
"box-width", gimp_pixels_to_units (x2 - x1,
|
||||
|
@ -924,7 +940,10 @@ gimp_text_tool_connect (GimpTextTool *text_tool,
|
|||
GimpTextOptions *options = GIMP_TEXT_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
g_signal_handlers_block_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_edited,
|
||||
gimp_text_tool_buffer_begin_edit,
|
||||
text_tool);
|
||||
g_signal_handlers_block_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_end_edit,
|
||||
text_tool);
|
||||
|
||||
if (text_tool->text)
|
||||
|
@ -977,7 +996,10 @@ gimp_text_tool_connect (GimpTextTool *text_tool,
|
|||
}
|
||||
|
||||
g_signal_handlers_unblock_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_edited,
|
||||
gimp_text_tool_buffer_end_edit,
|
||||
text_tool);
|
||||
g_signal_handlers_unblock_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_begin_edit,
|
||||
text_tool);
|
||||
}
|
||||
|
||||
|
@ -1036,7 +1058,7 @@ gimp_text_tool_text_notify (GimpText *text,
|
|||
{
|
||||
g_return_if_fail (text == text_tool->text);
|
||||
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
gimp_text_tool_block_drawing (text_tool);
|
||||
|
||||
if ((pspec->flags & G_PARAM_READWRITE) == G_PARAM_READWRITE)
|
||||
{
|
||||
|
@ -1066,7 +1088,10 @@ gimp_text_tool_text_notify (GimpText *text,
|
|||
strcmp (pspec->name, "markup") == 0)
|
||||
{
|
||||
g_signal_handlers_block_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_edited,
|
||||
gimp_text_tool_buffer_begin_edit,
|
||||
text_tool);
|
||||
g_signal_handlers_block_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_end_edit,
|
||||
text_tool);
|
||||
|
||||
if (pspec->name[0] == 't')
|
||||
|
@ -1075,27 +1100,24 @@ gimp_text_tool_text_notify (GimpText *text,
|
|||
gimp_text_buffer_set_markup (text_tool->buffer, text->markup);
|
||||
|
||||
g_signal_handlers_unblock_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_edited,
|
||||
gimp_text_tool_buffer_end_edit,
|
||||
text_tool);
|
||||
g_signal_handlers_unblock_by_func (text_tool->buffer,
|
||||
gimp_text_tool_buffer_begin_edit,
|
||||
text_tool);
|
||||
}
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_text_tool_text_changed (GimpText *text,
|
||||
GimpTextTool *text_tool)
|
||||
{
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
/* we need to redraw the rectangle in any case because whatever
|
||||
* changes to the text can change its size
|
||||
*/
|
||||
gimp_text_tool_frame_item (text_tool);
|
||||
|
||||
gimp_text_tool_clear_layout (text_tool);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
gimp_text_tool_unblock_drawing (text_tool);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -1168,8 +1190,6 @@ gimp_text_tool_apply (GimpTextTool *text_tool)
|
|||
}
|
||||
}
|
||||
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
if (push_undo)
|
||||
{
|
||||
if (layer->modified)
|
||||
|
@ -1242,9 +1262,7 @@ gimp_text_tool_apply (GimpTextTool *text_tool)
|
|||
|
||||
gimp_image_flush (image);
|
||||
|
||||
gimp_text_tool_clear_layout (text_tool);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
gimp_text_tool_unblock_drawing (text_tool);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1260,6 +1278,8 @@ gimp_text_tool_create_layer (GimpTextTool *text_tool,
|
|||
gint x1, y1;
|
||||
gint x2, y2;
|
||||
|
||||
gimp_text_tool_block_drawing (text_tool);
|
||||
|
||||
if (text)
|
||||
{
|
||||
text = gimp_config_duplicate (GIMP_CONFIG (text));
|
||||
|
@ -1344,10 +1364,14 @@ gimp_text_tool_create_layer (GimpTextTool *text_tool,
|
|||
text_tool->proxy->box_unit,
|
||||
yres),
|
||||
NULL);
|
||||
|
||||
gimp_text_tool_apply (text_tool); /* unblocks drawing */
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_text_tool_frame_item (text_tool);
|
||||
|
||||
gimp_text_tool_unblock_drawing (text_tool);
|
||||
}
|
||||
|
||||
gimp_image_undo_group_end (image);
|
||||
|
@ -1582,8 +1606,38 @@ gimp_text_tool_set_drawable (GimpTextTool *text_tool,
|
|||
}
|
||||
|
||||
static void
|
||||
gimp_text_tool_buffer_edited (GimpTextBuffer *buffer,
|
||||
GimpTextTool *text_tool)
|
||||
gimp_text_tool_block_drawing (GimpTextTool *text_tool)
|
||||
{
|
||||
if (! text_tool->drawing_blocked)
|
||||
{
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
gimp_text_tool_clear_layout (text_tool);
|
||||
|
||||
text_tool->drawing_blocked = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_text_tool_unblock_drawing (GimpTextTool *text_tool)
|
||||
{
|
||||
g_return_if_fail (text_tool->drawing_blocked == TRUE);
|
||||
|
||||
text_tool->drawing_blocked = FALSE;
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_text_tool_buffer_begin_edit (GimpTextBuffer *buffer,
|
||||
GimpTextTool *text_tool)
|
||||
{
|
||||
gimp_text_tool_block_drawing (text_tool);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_text_tool_buffer_end_edit (GimpTextBuffer *buffer,
|
||||
GimpTextTool *text_tool)
|
||||
{
|
||||
if (text_tool->text)
|
||||
{
|
||||
|
@ -1713,11 +1767,7 @@ gimp_text_tool_delete_selection (GimpTextTool *text_tool)
|
|||
|
||||
if (gtk_text_buffer_get_has_selection (buffer))
|
||||
{
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
gtk_text_buffer_delete_selection (buffer, TRUE, TRUE);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1734,12 +1784,8 @@ gimp_text_tool_cut_clipboard (GimpTextTool *text_tool)
|
|||
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (shell),
|
||||
GDK_SELECTION_CLIPBOARD);
|
||||
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
gtk_text_buffer_cut_clipboard (GTK_TEXT_BUFFER (text_tool->buffer),
|
||||
clipboard, TRUE);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1772,12 +1818,8 @@ gimp_text_tool_paste_clipboard (GimpTextTool *text_tool)
|
|||
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (shell),
|
||||
GDK_SELECTION_CLIPBOARD);
|
||||
|
||||
gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));
|
||||
|
||||
gtk_text_buffer_paste_clipboard (GTK_TEXT_BUFFER (text_tool->buffer),
|
||||
clipboard, NULL, TRUE);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -62,6 +62,7 @@ struct _GimpTextTool
|
|||
gboolean text_box_fixed;
|
||||
|
||||
GimpTextLayout *layout;
|
||||
gboolean drawing_blocked;
|
||||
|
||||
/* text editor state: */
|
||||
|
||||
|
|
Loading…
Reference in New Issue