summaryrefslogtreecommitdiff
path: root/gtk/gtktextview.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2006-03-28 17:28:19 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2006-03-28 17:28:19 +0000
commit38994e574cb1f6c866d6f31413ee4dedc1bb0ca1 (patch)
treeac48d30bb0db5d214e0a01d1d88e477e83f08ae8 /gtk/gtktextview.c
parent97c07a14f352ac2e3e80307ddbf11fa25ef04daa (diff)
downloadgtk+-38994e574cb1f6c866d6f31413ee4dedc1bb0ca1.tar.gz
Fix drag-selection after double-click. (#323862, Benjamin Berg)
2006-03-28 Matthias Clasen <mclasen@redhat.com> * 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)
Diffstat (limited to 'gtk/gtktextview.c')
-rw-r--r--gtk/gtktextview.c141
1 files changed, 71 insertions, 70 deletions
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 2d1ec400cb..35a3ff7b87 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);
-
- /* This may invalidate the layout */
- DV(g_print (G_STRLOC": move mark\n"));
- gtk_text_buffer_move_mark (get_buffer (text_view),
- mark,
- &newplace);
+static void
+move_mark_to_pointer_and_scroll (GtkTextView *text_view,
+ const gchar *mark_name)
+{
+ GtkTextIter newplace;
+ GtkTextMark *mark;
- 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);
-
- gtk_text_layout_get_iter_at_pixel (text_view->layout,
- &start,
- event->x + text_view->xoffset,
- event->y + text_view->yoffset);
+ get_iter_at_pointer (text_view, &cursor);
- 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_iter_order (&start, &old_start);
- gtk_text_iter_order (&old_end, &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);
- /* 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);