]> Pileus Git - ~andy/gtk/blob - gtk/gtktexthandle.c
treeview: center expander allocated space
[~andy/gtk] / gtk / gtktexthandle.c
1 /* GTK - The GIMP Toolkit
2  * Copyright © 2012 Carlos Garnacho <carlosg@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19 #include "gtkprivatetypebuiltins.h"
20 #include "gtktexthandleprivate.h"
21 #include "gtkmarshalers.h"
22 #include "gtkprivate.h"
23 #include "gtkintl.h"
24
25 #include <gtk/gtk.h>
26
27 typedef struct _GtkTextHandlePrivate GtkTextHandlePrivate;
28 typedef struct _HandleWindow HandleWindow;
29
30 enum {
31   HANDLE_DRAGGED,
32   DRAG_FINISHED,
33   LAST_SIGNAL
34 };
35
36 enum {
37   PROP_0,
38   PROP_PARENT,
39   PROP_RELATIVE_TO
40 };
41
42 struct _HandleWindow
43 {
44   GdkWindow *window;
45   GdkRectangle pointing_to;
46   gint dx;
47   gint dy;
48   guint dragged : 1;
49 };
50
51 struct _GtkTextHandlePrivate
52 {
53   HandleWindow windows[2];
54   GtkWidget *parent;
55   GdkWindow *relative_to;
56   GtkStyleContext *style_context;
57
58   gulong draw_signal_id;
59   gulong event_signal_id;
60   gulong style_updated_id;
61   gulong composited_changed_id;
62   guint realized : 1;
63   guint mode : 2;
64 };
65
66 G_DEFINE_TYPE (GtkTextHandle, _gtk_text_handle, G_TYPE_OBJECT)
67
68 static guint signals[LAST_SIGNAL] = { 0 };
69
70 static void
71 _gtk_text_handle_get_size (GtkTextHandle *handle,
72                            gint          *width,
73                            gint          *height)
74 {
75   GtkTextHandlePrivate *priv;
76   gint w, h;
77
78   priv = handle->priv;
79
80   gtk_widget_style_get (priv->parent,
81                         "text-handle-width", &w,
82                         "text-handle-height", &h,
83                         NULL);
84   if (width)
85     *width = w;
86
87   if (height)
88     *height = h;
89 }
90
91 static void
92 _gtk_text_handle_draw (GtkTextHandle         *handle,
93                        cairo_t               *cr,
94                        GtkTextHandlePosition  pos)
95 {
96   GtkTextHandlePrivate *priv;
97   gint width, height;
98
99   priv = handle->priv;
100   cairo_save (cr);
101
102   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
103   cairo_set_source_rgba (cr, 0, 0, 0, 0);
104   cairo_paint (cr);
105
106   gtk_style_context_save (priv->style_context);
107   gtk_style_context_add_class (priv->style_context,
108                                GTK_STYLE_CLASS_CURSOR_HANDLE);
109
110   if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_END)
111     {
112       gtk_style_context_add_class (priv->style_context,
113                                    GTK_STYLE_CLASS_BOTTOM);
114
115       if (priv->mode == GTK_TEXT_HANDLE_MODE_CURSOR)
116         gtk_style_context_add_class (priv->style_context,
117                                      GTK_STYLE_CLASS_INSERTION_CURSOR);
118     }
119   else
120     gtk_style_context_add_class (priv->style_context,
121                                  GTK_STYLE_CLASS_TOP);
122
123   _gtk_text_handle_get_size (handle, &width, &height);
124   gtk_render_background (priv->style_context, cr, 0, 0, width, height);
125
126   gtk_style_context_restore (priv->style_context);
127   cairo_restore (cr);
128 }
129
130 static void
131 _gtk_text_handle_update_shape (GtkTextHandle         *handle,
132                                GdkWindow             *window,
133                                GtkTextHandlePosition  pos)
134 {
135   GtkTextHandlePrivate *priv;
136   cairo_surface_t *surface;
137   cairo_region_t *region;
138   cairo_t *cr;
139
140   priv = handle->priv;
141
142   surface =
143     gdk_window_create_similar_surface (window,
144                                        CAIRO_CONTENT_COLOR_ALPHA,
145                                        gdk_window_get_width (window),
146                                        gdk_window_get_height (window));
147
148   cr = cairo_create (surface);
149   _gtk_text_handle_draw (handle, cr, pos);
150   cairo_destroy (cr);
151
152   region = gdk_cairo_region_create_from_surface (surface);
153
154   if (gtk_widget_is_composited (priv->parent))
155     gdk_window_shape_combine_region (window, NULL, 0, 0);
156   else
157     gdk_window_shape_combine_region (window, region, 0, 0);
158
159   gdk_window_input_shape_combine_region (window, region, 0, 0);
160
161   cairo_surface_destroy (surface);
162   cairo_region_destroy (region);
163 }
164
165 static GdkWindow *
166 _gtk_text_handle_create_window (GtkTextHandle         *handle,
167                                 GtkTextHandlePosition  pos)
168 {
169   GtkTextHandlePrivate *priv;
170   GdkRGBA bg = { 0, 0, 0, 0 };
171   GdkWindowAttr attributes;
172   GdkWindow *window;
173   GdkVisual *visual;
174   gint mask;
175
176   priv = handle->priv;
177
178   attributes.x = 0;
179   attributes.y = 0;
180   _gtk_text_handle_get_size (handle, &attributes.width, &attributes.height);
181   attributes.window_type = GDK_WINDOW_TEMP;
182   attributes.wclass = GDK_INPUT_OUTPUT;
183   attributes.event_mask = (GDK_EXPOSURE_MASK |
184                            GDK_BUTTON_PRESS_MASK |
185                            GDK_BUTTON_RELEASE_MASK |
186                            GDK_BUTTON1_MOTION_MASK);
187
188   mask = GDK_WA_X | GDK_WA_Y;
189
190   visual = gdk_screen_get_rgba_visual (gtk_widget_get_screen (priv->parent));
191
192   if (visual)
193     {
194       attributes.visual = visual;
195       mask |= GDK_WA_VISUAL;
196     }
197
198   window = gdk_window_new (gtk_widget_get_root_window (priv->parent),
199                            &attributes, mask);
200   gtk_widget_register_window (priv->parent, window);
201   gdk_window_set_background_rgba (window, &bg);
202
203   _gtk_text_handle_update_shape (handle, window, pos);
204
205   return window;
206 }
207
208 static gboolean
209 gtk_text_handle_widget_draw (GtkWidget     *widget,
210                              cairo_t       *cr,
211                              GtkTextHandle *handle)
212 {
213   GtkTextHandlePrivate *priv;
214   GtkTextHandlePosition pos;
215   HandleWindow *handle_window;
216
217   priv = handle->priv;
218
219   if (!priv->realized)
220     return FALSE;
221
222   if (gtk_cairo_should_draw_window (cr, priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window))
223     pos = GTK_TEXT_HANDLE_POSITION_SELECTION_START;
224   else if (gtk_cairo_should_draw_window (cr, priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window))
225     pos = GTK_TEXT_HANDLE_POSITION_SELECTION_END;
226   else
227     return FALSE;
228
229   handle_window = &priv->windows[pos];
230   if (gdk_window_is_visible (handle_window->window))
231     _gtk_text_handle_draw (handle, cr, pos);
232
233   return FALSE;
234 }
235
236 static gboolean
237 gtk_text_handle_widget_event (GtkWidget     *widget,
238                               GdkEvent      *event,
239                               GtkTextHandle *handle)
240 {
241   GtkTextHandlePrivate *priv;
242   GtkTextHandlePosition pos;
243
244   priv = handle->priv;
245
246   if (event->any.window == priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window)
247     pos = GTK_TEXT_HANDLE_POSITION_SELECTION_START;
248   else if (event->any.window == priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window)
249     pos = GTK_TEXT_HANDLE_POSITION_SELECTION_END;
250   else
251     return FALSE;
252
253   if (event->type == GDK_BUTTON_PRESS)
254     {
255       priv->windows[pos].dx = event->button.x;
256       priv->windows[pos].dy = event->button.y;
257       priv->windows[pos].dragged = TRUE;
258     }
259   else if (event->type == GDK_BUTTON_RELEASE)
260     {
261       g_signal_emit (handle, signals[DRAG_FINISHED], 0, pos);
262       priv->windows[pos].dx =  priv->windows[pos].dy = 0;
263       priv->windows[pos].dragged = FALSE;
264     }
265   else if (event->type == GDK_MOTION_NOTIFY && priv->windows[pos].dragged)
266     {
267       gint x, y, width, height;
268
269       _gtk_text_handle_get_size (handle, &width, &height);
270       gdk_window_get_origin (priv->relative_to, &x, &y);
271
272       x = event->motion.x_root - priv->windows[pos].dx + (width / 2) - x;
273       y = event->motion.y_root - priv->windows[pos].dy - y;
274
275       if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_START)
276         y += height;
277
278       g_signal_emit (handle, signals[HANDLE_DRAGGED], 0, pos, x, y);
279     }
280
281   return TRUE;
282 }
283
284 static void
285 _gtk_text_handle_update_window (GtkTextHandle         *handle,
286                                 GtkTextHandlePosition  pos)
287 {
288   GtkTextHandlePrivate *priv;
289   HandleWindow *handle_window;
290   gboolean visible;
291   gint x, y;
292
293   priv = handle->priv;
294   handle_window = &priv->windows[pos];
295
296   if (!handle_window->window)
297     return;
298
299   /* Get current state and destroy */
300   visible = gdk_window_is_visible (handle_window->window);
301
302   if (visible)
303     {
304       gint width;
305
306       _gtk_text_handle_get_size (handle, &width, NULL);
307       gdk_window_get_root_coords (handle_window->window,
308                                   width / 2, 0, &x, &y);
309     }
310
311   gtk_widget_unregister_window (priv->parent, handle_window->window);
312   gdk_window_destroy (handle_window->window);
313
314   /* Create new window and apply old state */
315   handle_window->window = _gtk_text_handle_create_window (handle, pos);
316
317   if (visible)
318     {
319       gdk_window_show (handle_window->window);
320       _gtk_text_handle_set_position (handle, pos,
321                                      &handle_window->pointing_to);
322     }
323 }
324
325 static void
326 _gtk_text_handle_update_windows (GtkTextHandle *handle)
327 {
328   GtkTextHandlePrivate *priv = handle->priv;
329
330   gtk_style_context_invalidate (priv->style_context);
331   _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
332   _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
333 }
334
335 static void
336 gtk_text_handle_constructed (GObject *object)
337 {
338   GtkTextHandlePrivate *priv;
339
340   priv = GTK_TEXT_HANDLE (object)->priv;
341   g_assert (priv->parent != NULL);
342
343   priv->draw_signal_id =
344     g_signal_connect (priv->parent, "draw",
345                       G_CALLBACK (gtk_text_handle_widget_draw),
346                       object);
347   priv->event_signal_id =
348     g_signal_connect (priv->parent, "event",
349                       G_CALLBACK (gtk_text_handle_widget_event),
350                       object);
351   priv->composited_changed_id =
352     g_signal_connect_swapped (priv->parent, "composited-changed",
353                               G_CALLBACK (_gtk_text_handle_update_windows),
354                               object);
355   priv->style_updated_id =
356     g_signal_connect_swapped (priv->parent, "style-updated",
357                               G_CALLBACK (_gtk_text_handle_update_windows),
358                               object);
359 }
360
361 static void
362 gtk_text_handle_finalize (GObject *object)
363 {
364   GtkTextHandlePrivate *priv;
365
366   priv = GTK_TEXT_HANDLE (object)->priv;
367
368   if (priv->relative_to)
369     g_object_unref (priv->relative_to);
370
371   if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window)
372     {
373       gtk_widget_unregister_window (priv->parent,
374                                     priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
375       gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
376     }
377
378   if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window)
379     {
380       gtk_widget_unregister_window (priv->parent,
381                                     priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
382       gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
383     }
384
385   if (g_signal_handler_is_connected (priv->parent, priv->draw_signal_id))
386     g_signal_handler_disconnect (priv->parent, priv->draw_signal_id);
387
388   if (g_signal_handler_is_connected (priv->parent, priv->event_signal_id))
389     g_signal_handler_disconnect (priv->parent, priv->event_signal_id);
390
391   if (g_signal_handler_is_connected (priv->parent, priv->composited_changed_id))
392     g_signal_handler_disconnect (priv->parent, priv->composited_changed_id);
393
394   if (g_signal_handler_is_connected (priv->parent, priv->style_updated_id))
395     g_signal_handler_disconnect (priv->parent, priv->style_updated_id);
396
397   g_object_unref (priv->style_context);
398
399   G_OBJECT_CLASS (_gtk_text_handle_parent_class)->finalize (object);
400 }
401
402 static void
403 gtk_text_handle_set_property (GObject      *object,
404                               guint         prop_id,
405                               const GValue *value,
406                               GParamSpec   *pspec)
407 {
408   GtkTextHandlePrivate *priv;
409   GtkTextHandle *handle;
410
411   handle = GTK_TEXT_HANDLE (object);
412   priv = handle->priv;
413
414   switch (prop_id)
415     {
416     case PROP_PARENT:
417       priv->parent = g_value_get_object (value);
418       break;
419     case PROP_RELATIVE_TO:
420       _gtk_text_handle_set_relative_to (handle,
421                                         g_value_get_object (value));
422       break;
423     default:
424       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
425     }
426 }
427
428 static void
429 gtk_text_handle_get_property (GObject    *object,
430                               guint       prop_id,
431                               GValue     *value,
432                               GParamSpec *pspec)
433 {
434   GtkTextHandlePrivate *priv;
435
436   priv = GTK_TEXT_HANDLE (object)->priv;
437
438   switch (prop_id)
439     {
440     case PROP_PARENT:
441       g_value_set_object (value, priv->parent);
442       break;
443     case PROP_RELATIVE_TO:
444       g_value_set_object (value, priv->relative_to);
445       break;
446     default:
447       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
448     }
449 }
450
451 static void
452 _gtk_text_handle_class_init (GtkTextHandleClass *klass)
453 {
454   GObjectClass *object_class = G_OBJECT_CLASS (klass);
455
456   object_class->constructed = gtk_text_handle_constructed;
457   object_class->finalize = gtk_text_handle_finalize;
458   object_class->set_property = gtk_text_handle_set_property;
459   object_class->get_property = gtk_text_handle_get_property;
460
461   signals[HANDLE_DRAGGED] =
462     g_signal_new (I_("handle-dragged"),
463                   G_OBJECT_CLASS_TYPE (object_class),
464                   G_SIGNAL_RUN_LAST,
465                   G_STRUCT_OFFSET (GtkTextHandleClass, handle_dragged),
466                   NULL, NULL,
467                   _gtk_marshal_VOID__ENUM_INT_INT,
468                   G_TYPE_NONE, 3,
469                   GTK_TYPE_TEXT_HANDLE_POSITION,
470                   G_TYPE_INT, G_TYPE_INT);
471   signals[DRAG_FINISHED] =
472     g_signal_new (I_("drag-finished"),
473                   G_OBJECT_CLASS_TYPE (object_class),
474                   G_SIGNAL_RUN_LAST, 0,
475                   NULL, NULL,
476                   g_cclosure_marshal_VOID__ENUM,
477                   G_TYPE_NONE, 1,
478                   GTK_TYPE_TEXT_HANDLE_POSITION);
479
480   g_object_class_install_property (object_class,
481                                    PROP_PARENT,
482                                    g_param_spec_object ("parent",
483                                                         P_("Parent widget"),
484                                                         P_("Parent widget"),
485                                                         GTK_TYPE_WIDGET,
486                                                         GTK_PARAM_READWRITE |
487                                                         G_PARAM_CONSTRUCT_ONLY));
488   g_object_class_install_property (object_class,
489                                    PROP_RELATIVE_TO,
490                                    g_param_spec_object ("relative-to",
491                                                         P_("Window"),
492                                                         P_("Window the coordinates are based upon"),
493                                                         GDK_TYPE_WINDOW,
494                                                         GTK_PARAM_READWRITE));
495
496   g_type_class_add_private (object_class, sizeof (GtkTextHandlePrivate));
497 }
498
499 static void
500 _gtk_text_handle_init (GtkTextHandle *handle)
501 {
502   GtkTextHandlePrivate *priv;
503   GtkWidgetPath *path;
504
505   handle->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (handle,
506                                                      GTK_TYPE_TEXT_HANDLE,
507                                                      GtkTextHandlePrivate);
508
509   path = gtk_widget_path_new ();
510   gtk_widget_path_append_type (path, GTK_TYPE_TEXT_HANDLE);
511
512   priv->style_context = gtk_style_context_new ();
513   gtk_style_context_set_path (priv->style_context, path);
514   gtk_widget_path_free (path);
515 }
516
517 GtkTextHandle *
518 _gtk_text_handle_new (GtkWidget *parent)
519 {
520   return g_object_new (GTK_TYPE_TEXT_HANDLE,
521                        "parent", parent,
522                        NULL);
523 }
524
525 void
526 _gtk_text_handle_set_relative_to (GtkTextHandle *handle,
527                                   GdkWindow     *window)
528 {
529   GtkTextHandlePrivate *priv;
530
531   g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
532   g_return_if_fail (!window || GDK_IS_WINDOW (window));
533
534   priv = handle->priv;
535
536   if (priv->relative_to)
537     {
538       gtk_widget_unregister_window (priv->parent,
539                                     priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
540       gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
541       gtk_widget_unregister_window (priv->parent,
542                                     priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
543       gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
544       g_object_unref (priv->relative_to);
545     }
546
547   if (window)
548     {
549       priv->relative_to = g_object_ref (window);
550       priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window =
551         _gtk_text_handle_create_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
552       priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window =
553         _gtk_text_handle_create_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
554       priv->realized = TRUE;
555     }
556   else
557     {
558       priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window = NULL;
559       priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window = NULL;
560       priv->relative_to = NULL;
561       priv->realized = FALSE;
562     }
563
564   g_object_notify (G_OBJECT (handle), "relative-to");
565 }
566
567 void
568 _gtk_text_handle_set_mode (GtkTextHandle     *handle,
569                            GtkTextHandleMode  mode)
570 {
571   GtkTextHandlePrivate *priv;
572
573   g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
574
575   priv = handle->priv;
576
577   if (priv->mode == mode)
578     return;
579
580   switch (mode)
581     {
582     case GTK_TEXT_HANDLE_MODE_CURSOR:
583       /* Only display one handle */
584       gdk_window_show (priv->windows[GTK_TEXT_HANDLE_POSITION_CURSOR].window);
585       gdk_window_hide (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
586       break;
587       case GTK_TEXT_HANDLE_MODE_SELECTION:
588         /* Display both handles */
589       gdk_window_show (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
590       gdk_window_show (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
591       break;
592     case GTK_TEXT_HANDLE_MODE_NONE:
593     default:
594       gdk_window_hide (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
595       gdk_window_hide (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
596       break;
597     }
598
599   priv->mode = mode;
600
601   _gtk_text_handle_update_shape (handle,
602                                  priv->windows[GTK_TEXT_HANDLE_POSITION_CURSOR].window,
603                                  GTK_TEXT_HANDLE_POSITION_CURSOR);
604 }
605
606 GtkTextHandleMode
607 _gtk_text_handle_get_mode (GtkTextHandle *handle)
608 {
609   GtkTextHandlePrivate *priv;
610
611   g_return_val_if_fail (GTK_IS_TEXT_HANDLE (handle), GTK_TEXT_HANDLE_MODE_NONE);
612
613   priv = handle->priv;
614   return priv->mode;
615 }
616
617 void
618 _gtk_text_handle_set_position (GtkTextHandle         *handle,
619                                GtkTextHandlePosition  pos,
620                                GdkRectangle          *rect)
621 {
622   GtkTextHandlePrivate *priv;
623   gint x, y, width, height;
624   HandleWindow *handle_window;
625
626   g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
627
628   priv = handle->priv;
629   pos = CLAMP (pos, GTK_TEXT_HANDLE_POSITION_CURSOR,
630                GTK_TEXT_HANDLE_POSITION_SELECTION_START);
631
632   if (!priv->realized)
633     return;
634
635   if (priv->mode == GTK_TEXT_HANDLE_MODE_NONE ||
636       (priv->mode == GTK_TEXT_HANDLE_MODE_CURSOR &&
637        pos != GTK_TEXT_HANDLE_POSITION_CURSOR))
638     return;
639
640   gdk_window_get_root_coords (priv->relative_to,
641                               rect->x, rect->y,
642                               &x, &y);
643   _gtk_text_handle_get_size (handle, &width, &height);
644   handle_window = &priv->windows[pos];
645
646   if (pos == GTK_TEXT_HANDLE_POSITION_CURSOR)
647     y += rect->height;
648   else
649     y -= height;
650
651   x -= width / 2;
652
653   gdk_window_move (handle_window->window, x, y);
654   handle_window->pointing_to = *rect;
655 }
656
657 void
658 _gtk_text_handle_set_visible (GtkTextHandle         *handle,
659                               GtkTextHandlePosition  pos,
660                               gboolean               visible)
661 {
662   GtkTextHandlePrivate *priv;
663   GdkWindow *window;
664
665   g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
666
667   priv = handle->priv;
668   pos = CLAMP (pos, GTK_TEXT_HANDLE_POSITION_CURSOR,
669                GTK_TEXT_HANDLE_POSITION_SELECTION_START);
670
671   if (!priv->realized)
672     return;
673
674   window = priv->windows[pos].window;
675
676   if (!window)
677     return;
678
679   if (!visible)
680     gdk_window_hide (window);
681   else
682     {
683       if (priv->mode == GTK_TEXT_HANDLE_MODE_NONE ||
684           (priv->mode == GTK_TEXT_HANDLE_MODE_CURSOR &&
685            pos != GTK_TEXT_HANDLE_POSITION_CURSOR))
686         return;
687
688       if (!gdk_window_is_visible (window))
689         gdk_window_show (window);
690     }
691 }
692
693 gboolean
694 _gtk_text_handle_get_is_dragged (GtkTextHandle         *handle,
695                                  GtkTextHandlePosition  pos)
696 {
697   GtkTextHandlePrivate *priv;
698
699   g_return_val_if_fail (GTK_IS_TEXT_HANDLE (handle), FALSE);
700
701   priv = handle->priv;
702   pos = CLAMP (pos, GTK_TEXT_HANDLE_POSITION_CURSOR,
703                GTK_TEXT_HANDLE_POSITION_SELECTION_START);
704
705   return priv->windows[pos].dragged;
706 }