From 38994e574cb1f6c866d6f31413ee4dedc1bb0ca1 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 28 Mar 2006 17:28:19 +0000 Subject: [PATCH] Fix drag-selection after double-click. (#323862, Benjamin Berg) 2006-03-28 Matthias Clasen * gtk/gtktextview.c (gtk_text_view_start_selection_drag): (selection_motion_event_handler): Fix drag-selection after double-click. (#323862, Benjamin Berg) * gtk/gtktextview.c (get_iter_at_pointer): Factor this out into a function and use it in move_mark_to_pointer_and_scroll, drag_scan_timeout and selection_motion_event_handler. (Paolo Borelli) --- ChangeLog | 13 ++++- ChangeLog.pre-2-10 | 13 ++++- gtk/gtktextview.c | 141 +++++++++++++++++++++++---------------------- 3 files changed, 95 insertions(+), 72 deletions(-) diff --git a/ChangeLog b/ChangeLog index edae51657..cf464e87f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2006-03-28 Matthias Clasen + + * gtk/gtktextview.c (gtk_text_view_start_selection_drag): + (selection_motion_event_handler): Fix drag-selection after + double-click. (#323862, Benjamin Berg) + + * gtk/gtktextview.c (get_iter_at_pointer): Factor this out + into a function and use it in move_mark_to_pointer_and_scroll, + drag_scan_timeout and selection_motion_event_handler. + (Paolo Borelli) + 2006-03-28 Matthias Clasen * gtk/gtktextview.c (gtk_text_view_do_popup) @@ -7,7 +18,7 @@ for the text views own popup, but also for other ways in which we might become grab-shadowed during a selection drag. (#74620, Li Yuan) - + 2006-03-28 Sven Herzberg reviewed by: Tim Janik diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index edae51657..cf464e87f 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,14 @@ +2006-03-28 Matthias Clasen + + * gtk/gtktextview.c (gtk_text_view_start_selection_drag): + (selection_motion_event_handler): Fix drag-selection after + double-click. (#323862, Benjamin Berg) + + * gtk/gtktextview.c (get_iter_at_pointer): Factor this out + into a function and use it in move_mark_to_pointer_and_scroll, + drag_scan_timeout and selection_motion_event_handler. + (Paolo Borelli) + 2006-03-28 Matthias Clasen * gtk/gtktextview.c (gtk_text_view_do_popup) @@ -7,7 +18,7 @@ for the text views own popup, but also for other ways in which we might become grab-shadowed during a selection drag. (#74620, Li Yuan) - + 2006-03-28 Sven Herzberg reviewed by: Tim Janik diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index 2d1ec400c..35a3ff7b8 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -5435,37 +5435,41 @@ gtk_text_view_unselect (GtkTextView *text_view) } static void -move_mark_to_pointer_and_scroll (GtkTextView *text_view, - const gchar *mark_name) +get_iter_at_pointer (GtkTextView *text_view, + GtkTextIter *iter) { gint x, y; GdkModifierType state; - GtkTextIter newplace; - /* DV(g_print (G_STRLOC": begin\n")); */ - gdk_window_get_pointer (text_view->text_window->bin_window, &x, &y, &state); - - /* DV(g_print (G_STRLOC": get iter at pixel\n"); */ + gtk_text_layout_get_iter_at_pixel (text_view->layout, - &newplace, + iter, x + text_view->xoffset, y + text_view->yoffset); +} - { - GtkTextMark *mark = - gtk_text_buffer_get_mark (get_buffer (text_view), mark_name); +static void +move_mark_to_pointer_and_scroll (GtkTextView *text_view, + const gchar *mark_name) +{ + GtkTextIter newplace; + GtkTextMark *mark; - /* This may invalidate the layout */ - DV(g_print (G_STRLOC": move mark\n")); - gtk_text_buffer_move_mark (get_buffer (text_view), - mark, - &newplace); - - DV(g_print (G_STRLOC": scrolling onscreen\n")); - gtk_text_view_scroll_mark_onscreen (text_view, mark); - } + get_iter_at_pointer (text_view, &newplace); + + mark = gtk_text_buffer_get_mark (get_buffer (text_view), mark_name); + + /* This may invalidate the layout */ + DV(g_print (G_STRLOC": move mark\n")); + + gtk_text_buffer_move_mark (get_buffer (text_view), + mark, + &newplace); + + DV(g_print (G_STRLOC": scrolling onscreen\n")); + gtk_text_view_scroll_mark_onscreen (text_view, mark); DV (g_print ("first validate idle leaving %s is %d\n", G_STRLOC, text_view->first_validate_idle)); @@ -5496,22 +5500,14 @@ static gint drag_scan_timeout (gpointer data) { GtkTextView *text_view; - gint x, y; - GdkModifierType state; GtkTextIter newplace; GDK_THREADS_ENTER (); text_view = GTK_TEXT_VIEW (data); - gdk_window_get_pointer (text_view->text_window->bin_window, - &x, &y, &state); - - gtk_text_layout_get_iter_at_pixel (text_view->layout, - &newplace, - x + text_view->xoffset, - y + text_view->yoffset); - + get_iter_at_pointer (text_view, &newplace); + gtk_text_buffer_move_mark (get_buffer (text_view), text_view->dnd_mark, &newplace); @@ -5643,42 +5639,25 @@ selection_motion_event_handler (GtkTextView *text_view, { gint x, y; GdkModifierType state; - GtkTextIter start, end; - GtkTextIter ins, bound; + GtkTextIter cursor, start, end; + GtkTextIter orig_start, orig_end; GtkTextBuffer *buffer; - gboolean extend; buffer = get_buffer (text_view); - gtk_text_buffer_get_iter_at_mark (buffer, &ins, data->orig_start); - gtk_text_buffer_get_iter_at_mark (buffer, &bound, data->orig_end); + gtk_text_buffer_get_iter_at_mark (buffer, &orig_start, data->orig_start); + gtk_text_buffer_get_iter_at_mark (buffer, &orig_end, data->orig_end); - gdk_window_get_pointer (text_view->text_window->bin_window, - &x, &y, &state); + get_iter_at_pointer (text_view, &cursor); - gtk_text_layout_get_iter_at_pixel (text_view->layout, - &start, - event->x + text_view->xoffset, - event->y + text_view->yoffset); - - extend = !gtk_text_iter_in_range (&start, &ins, &bound); - + start = cursor; extend_selection (text_view, data->granularity, &start, &end); - if (extend) - { - /* Extend selection */ - gtk_text_iter_order (&ins, &start); - gtk_text_iter_order (&end, &bound); - gtk_text_buffer_select_range (buffer, &ins, &bound); - } + /* either the selection extends to the front, or end (or not) */ + if (gtk_text_iter_compare (&cursor, &orig_start) < 0) + gtk_text_buffer_select_range (buffer, &start, &orig_end); else - { - /* Shrink selection */ - gtk_text_iter_order (&ins, &start); - gtk_text_iter_order (&end, &bound); - gtk_text_buffer_select_range (buffer, &ins, &end); - } + gtk_text_buffer_select_range (buffer, &end, &orig_start); gtk_text_view_scroll_mark_onscreen (text_view, gtk_text_buffer_get_insert (buffer)); @@ -5703,7 +5682,8 @@ gtk_text_view_start_selection_drag (GtkTextView *text_view, const GtkTextIter *iter, GdkEventButton *button) { - GtkTextIter start, end; + GtkTextIter cursor, ins, bound; + GtkTextIter orig_start, orig_end; GtkTextBuffer *buffer; SelectionData *data; @@ -5722,31 +5702,52 @@ gtk_text_view_start_selection_drag (GtkTextView *text_view, buffer = get_buffer (text_view); - start = *iter; + cursor = *iter; + ins = cursor; - extend_selection (text_view, data->granularity, &start, &end); + extend_selection (text_view, data->granularity, &ins, &bound); + orig_start = ins; + orig_end = bound; if (button->state & GDK_SHIFT_MASK) { /* Extend selection */ + GtkTextIter old_ins, old_bound; GtkTextIter old_start, old_end; - gtk_text_buffer_get_selection_bounds (buffer, &old_start, &old_end); + gtk_text_buffer_get_iter_at_mark (buffer, &old_ins, gtk_text_buffer_get_insert (buffer)); + gtk_text_buffer_get_iter_at_mark (buffer, &old_bound, gtk_text_buffer_get_selection_bound (buffer)); + old_start = old_ins; + old_end = old_bound; + gtk_text_iter_order (&old_start, &old_end); - gtk_text_iter_order (&start, &old_start); - gtk_text_iter_order (&old_end, &end); - - /* Now start is the first of the starts, and end is the - * last of the ends - */ + /* move the front cursor, if the mouse is in front of the selection. Should the + * cursor however be inside the selection (this happens on tripple click) then we + * move the side which was last moved (current insert mark) */ + if (gtk_text_iter_compare (&cursor, &old_start) <= 0 || + (gtk_text_iter_compare (&cursor, &old_end) < 0 && + gtk_text_iter_compare (&old_ins, &old_bound) <= 0)) + { + bound = old_end; + orig_start = old_end; + orig_end = old_end; + } + else + { + ins = bound; + bound = old_start; + orig_end = bound; + orig_start = bound; + } } - gtk_text_buffer_select_range (buffer, &end, &start); + gtk_text_buffer_select_range (buffer, &ins, &bound); + gtk_text_iter_order (&orig_start, &orig_end); data->orig_start = gtk_text_buffer_create_mark (buffer, NULL, - &start, TRUE); + &orig_start, TRUE); data->orig_end = gtk_text_buffer_create_mark (buffer, NULL, - &end, TRUE); + &orig_end, TRUE); gtk_text_view_check_cursor_blink (text_view);