]> www.fi.muni.cz Git - evince.git/blob - libview/ev-annotation-window.c
[libview] Add EvAnnotationWindow widget that implements popup annotations
[evince.git] / libview / ev-annotation-window.c
1 /* ev-annotation-window.c
2  *  this file is part of evince, a gnome document viewer
3  *
4  * Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
5  * Copyright (C) 2007 IƱigo Martinez <inigomartinez@gmail.com>
6  *
7  * Evince is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * Evince is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23
24 #include <string.h>
25
26 #include "ev-annotation-window.h"
27 #include "ev-stock-icons.h"
28 #include "ev-view-marshal.h"
29
30 enum {
31         PROP_0,
32         PROP_ANNOTATION,
33         PROP_PARENT
34 };
35
36 enum {
37         CLOSED,
38         MOVED,
39         N_SIGNALS
40 };
41
42 struct _EvAnnotationWindow {
43         GtkWindow     base_instance;
44
45         EvAnnotation *annotation;
46         GtkWindow    *parent;
47
48         GtkWidget    *title;
49         GtkWidget    *close_button;
50         GtkWidget    *text_view;
51         GtkWidget    *resize_se;
52         GtkWidget    *resize_sw;
53
54         gboolean      is_open;
55         EvRectangle  *rect;
56
57         gboolean      in_move;
58         gint          x;
59         gint          y;
60         gint          orig_x;
61         gint          orig_y;
62 };
63
64 struct _EvAnnotationWindowClass {
65         GtkWindowClass base_class;
66
67         void (* closed) (EvAnnotationWindow *window);
68         void (* moved)  (EvAnnotationWindow *window,
69                          gint                x,
70                          gint                y);
71 };
72
73 static guint signals[N_SIGNALS];
74
75 G_DEFINE_TYPE (EvAnnotationWindow, ev_annotation_window, GTK_TYPE_WINDOW)
76
77 #define EV_ICON_SIZE_ANNOT_WINDOW (ev_annotation_window_get_icon_size())
78
79 /* Cut and paste from gtkwindow.c */
80 static void
81 send_focus_change (GtkWidget *widget,
82                    gboolean   in)
83 {
84         GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
85
86         g_object_ref (widget);
87
88         if (in)
89                 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
90         else
91                 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
92
93         fevent->focus_change.type = GDK_FOCUS_CHANGE;
94         fevent->focus_change.window = g_object_ref (widget->window);
95         fevent->focus_change.in = in;
96
97         gtk_widget_event (widget, fevent);
98
99         g_object_notify (G_OBJECT (widget), "has-focus");
100
101         g_object_unref (widget);
102         gdk_event_free (fevent);
103 }
104
105 static gdouble
106 get_screen_dpi (GtkWindow *window)
107 {
108         GdkScreen *screen;
109         gdouble    xdpi, ydpi;
110
111         screen = gtk_window_get_screen (window);
112
113         xdpi = 25.4 * gdk_screen_get_width (screen) / gdk_screen_get_width_mm (screen);
114         ydpi = 25.4 * gdk_screen_get_height (screen) / gdk_screen_get_height_mm (screen);
115
116         return (xdpi + ydpi) / 2.0;
117 }
118
119 static GtkIconSize
120 ev_annotation_window_get_icon_size (void)
121 {
122         static GtkIconSize icon_size = 0;
123
124         if (G_UNLIKELY (icon_size == 0))
125                 icon_size = gtk_icon_size_register ("ev-icon-size-annot-window", 8, 8);
126
127         return icon_size;
128 }
129
130 static void
131 ev_annotation_window_check_contents_modified (EvAnnotationWindow *window)
132 {
133         gchar         *contents;
134         GtkTextIter    start, end;
135         GtkTextBuffer *buffer;
136         EvAnnotation  *annot = window->annotation;
137
138         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->text_view));
139         gtk_text_buffer_get_bounds (buffer, &start, &end);
140         contents = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
141
142         if (contents && annot->contents) {
143                 if (strcasecmp (contents, annot->contents) != 0) {
144                         g_free (annot->contents);
145                         annot->contents = contents;
146                         annot->changed = TRUE;
147                 } else {
148                         g_free (contents);
149                 }
150         } else if (annot->contents) {
151                 g_free (annot->contents);
152                 annot->contents = NULL;
153                 annot->changed = TRUE;
154         } else if (contents) {
155                 annot->contents = contents;
156                 annot->changed = TRUE;
157         }
158 }
159
160 static void
161 ev_annotation_window_set_color (EvAnnotationWindow *window,
162                                 GdkColor           *color)
163 {
164         GtkRcStyle *rc_style;
165         GdkColor    gcolor;
166
167         gcolor = *color;
168
169         /* Allocate these colors */
170         gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (window)),
171                                   &gcolor, FALSE, TRUE);
172
173         /* Apply colors to style */
174         rc_style = gtk_widget_get_modifier_style (GTK_WIDGET (window));
175         rc_style->base[GTK_STATE_NORMAL] = gcolor;
176         rc_style->bg[GTK_STATE_PRELIGHT] = gcolor;
177         rc_style->bg[GTK_STATE_NORMAL] = gcolor;
178         rc_style->bg[GTK_STATE_ACTIVE] = gcolor;
179         rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_BG;
180         rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_BG | GTK_RC_BASE;
181         rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_BG;
182
183         /* Apply the style to the widgets */
184         g_object_ref (rc_style);
185         gtk_widget_modify_style (GTK_WIDGET (window), rc_style);
186         gtk_widget_modify_style (window->close_button, rc_style);
187         gtk_widget_modify_style (window->resize_se, rc_style);
188         gtk_widget_modify_style (window->resize_sw, rc_style);
189         g_object_unref (rc_style);
190 }
191
192 static void
193 ev_annotation_window_dispose (GObject *object)
194 {
195         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (object);
196
197         if (window->annotation) {
198                 ev_annotation_window_check_contents_modified (window);
199                 g_object_unref (window->annotation);
200                 window->annotation = NULL;
201         }
202
203         if (window->rect) {
204                 ev_rectangle_free (window->rect);
205                 window->rect = NULL;
206         }
207
208         (* G_OBJECT_CLASS (ev_annotation_window_parent_class)->dispose) (object);
209 }
210
211 static void
212 ev_annotation_window_set_property (GObject      *object,
213                                    guint         prop_id,
214                                    const GValue *value,
215                                    GParamSpec   *pspec)
216 {
217         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (object);
218
219         switch (prop_id) {
220         case PROP_ANNOTATION:
221                 window->annotation = g_value_dup_object (value);
222                 break;
223         case PROP_PARENT:
224                 window->parent = g_value_get_object (value);
225                 break;
226         default:
227                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
228         }
229 }
230
231 static gboolean
232 ev_annotation_window_resize (EvAnnotationWindow *window,
233                              GdkEventButton     *event,
234                              GtkWidget          *ebox)
235 {
236         if (event->type == GDK_BUTTON_PRESS && event->button == 1) {
237                 gtk_window_begin_resize_drag (GTK_WINDOW (window),
238                                               window->resize_sw == ebox ?
239                                               GDK_WINDOW_EDGE_SOUTH_WEST :
240                                               GDK_WINDOW_EDGE_SOUTH_EAST,
241                                               event->button, event->x_root,
242                                               event->y_root, event->time);
243                 return TRUE;
244         }
245
246         return FALSE;
247 }
248
249 static void
250 ev_annotation_window_set_resize_cursor (GtkWidget          *widget,
251                                         EvAnnotationWindow *window)
252 {
253         if (!widget->window)
254                 return;
255
256         if (GTK_WIDGET_IS_SENSITIVE (widget)) {
257                 GdkDisplay *display = gtk_widget_get_display (widget);
258                 GdkCursor  *cursor;
259
260                 cursor = gdk_cursor_new_for_display (display,
261                                                      widget == window->resize_sw ?
262                                                      GDK_BOTTOM_LEFT_CORNER :
263                                                      GDK_BOTTOM_RIGHT_CORNER);
264                 gdk_window_set_cursor (widget->window, cursor);
265                 gdk_cursor_unref (cursor);
266         } else {
267                 gdk_window_set_cursor (widget->window, NULL);
268         }
269 }
270
271 static gboolean
272 text_view_button_press (GtkWidget          *widget,
273                         GdkEventButton     *event,
274                         EvAnnotationWindow *window)
275 {
276         ev_annotation_window_grab_focus (window);
277
278         return FALSE;
279 }
280
281 static void
282 ev_annotation_window_close (EvAnnotationWindow *window)
283 {
284         gtk_widget_hide (GTK_WIDGET (window));
285         g_signal_emit (window, signals[CLOSED], 0);
286 }
287
288 static void
289 ev_annotation_window_init (EvAnnotationWindow *window)
290 {
291         GtkWidget *vbox, *hbox;
292         GtkWidget *icon;
293         GtkWidget *swindow;
294
295         GTK_WIDGET_SET_FLAGS (window, GTK_CAN_FOCUS);
296
297         vbox = gtk_vbox_new (FALSE, 0);
298
299         /* Title bar */
300         hbox = gtk_hbox_new (FALSE, 0);
301
302         icon = gtk_image_new (); /* FIXME: use the annot icon */
303         gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
304         gtk_widget_show (icon);
305
306         window->title = gtk_label_new (NULL);
307         gtk_box_pack_start (GTK_BOX (hbox), window->title, TRUE, TRUE, 0);
308         gtk_widget_show (window->title);
309
310         window->close_button = gtk_button_new ();
311         gtk_button_set_relief (GTK_BUTTON (window->close_button), GTK_RELIEF_NONE);
312         gtk_container_set_border_width (GTK_CONTAINER (window->close_button), 0);
313         g_signal_connect_swapped (window->close_button, "clicked",
314                                   G_CALLBACK (ev_annotation_window_close),
315                                   window);
316         icon = gtk_image_new_from_stock (EV_STOCK_CLOSE, EV_ICON_SIZE_ANNOT_WINDOW);
317         gtk_container_add (GTK_CONTAINER (window->close_button), icon);
318         gtk_widget_show (icon);
319
320         gtk_box_pack_start (GTK_BOX (hbox), window->close_button, FALSE, FALSE, 0);
321         gtk_widget_show (window->close_button);
322
323         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
324         gtk_widget_show (hbox);
325
326         /* Contents */
327         swindow = gtk_scrolled_window_new (NULL, NULL);
328         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
329                                         GTK_POLICY_AUTOMATIC,
330                                         GTK_POLICY_AUTOMATIC);
331         window->text_view = gtk_text_view_new ();
332         g_signal_connect (window->text_view, "button_press_event",
333                           G_CALLBACK (text_view_button_press),
334                           window);
335         gtk_container_add (GTK_CONTAINER (swindow), window->text_view);
336         gtk_widget_show (window->text_view);
337
338         gtk_box_pack_start (GTK_BOX (vbox), swindow, TRUE, TRUE, 0);
339         gtk_widget_show (swindow);
340
341         /* Resize bar */
342         hbox = gtk_hbox_new (FALSE, 0);
343
344         window->resize_sw = gtk_event_box_new ();
345         gtk_widget_add_events (window->resize_sw, GDK_BUTTON_PRESS_MASK);
346         g_signal_connect_swapped (window->resize_sw, "button-press-event",
347                                   G_CALLBACK (ev_annotation_window_resize),
348                                   window);
349         g_signal_connect (window->resize_sw, "realize",
350                           G_CALLBACK (ev_annotation_window_set_resize_cursor),
351                           window);
352
353         icon = gtk_image_new_from_stock (EV_STOCK_RESIZE_SW, EV_ICON_SIZE_ANNOT_WINDOW);
354         gtk_container_add (GTK_CONTAINER (window->resize_sw), icon);
355         gtk_widget_show (icon);
356         gtk_box_pack_start (GTK_BOX (hbox), window->resize_sw, FALSE, FALSE, 0);
357         gtk_widget_show (window->resize_sw);
358
359         window->resize_se = gtk_event_box_new ();
360         gtk_widget_add_events (window->resize_se, GDK_BUTTON_PRESS_MASK);
361         g_signal_connect_swapped (window->resize_se, "button-press-event",
362                                   G_CALLBACK (ev_annotation_window_resize),
363                                   window);
364         g_signal_connect (window->resize_se, "realize",
365                           G_CALLBACK (ev_annotation_window_set_resize_cursor),
366                           window);
367
368         icon = gtk_image_new_from_stock (EV_STOCK_RESIZE_SE, EV_ICON_SIZE_ANNOT_WINDOW);
369         gtk_container_add (GTK_CONTAINER (window->resize_se), icon);
370         gtk_widget_show (icon);
371         gtk_box_pack_end (GTK_BOX (hbox), window->resize_se, FALSE, FALSE, 0);
372         gtk_widget_show (window->resize_se);
373
374         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
375         gtk_widget_show (hbox);
376
377         gtk_container_add (GTK_CONTAINER (window), vbox);
378         gtk_container_set_border_width (GTK_CONTAINER (window), 0);
379         gtk_widget_show (vbox);
380
381         gtk_widget_add_events (GTK_WIDGET (window),
382                                GDK_BUTTON_PRESS_MASK |
383                                GDK_KEY_PRESS_MASK);
384         gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
385
386         gtk_container_set_border_width (GTK_CONTAINER (window), 2);
387
388         gtk_window_set_accept_focus (GTK_WINDOW (window), FALSE);
389         gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
390         gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE);
391         gtk_window_set_skip_pager_hint (GTK_WINDOW (window), TRUE);
392         gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
393 }
394
395 static GObject *
396 ev_annotation_window_constructor (GType                  type,
397                                   guint                  n_construct_properties,
398                                   GObjectConstructParam *construct_params)
399 {
400         GObject            *object;
401         EvAnnotationWindow *window;
402         EvAnnotation       *annot;
403         gchar              *label;
404         gdouble             opacity;
405         EvRectangle        *rect;
406         gdouble             scale;
407
408         object = G_OBJECT_CLASS (ev_annotation_window_parent_class)->constructor (type,
409                                                                                   n_construct_properties,
410                                                                                   construct_params);
411         window = EV_ANNOTATION_WINDOW (object);
412         annot = window->annotation;
413
414         gtk_window_set_transient_for (GTK_WINDOW (window), window->parent);
415         gtk_window_set_destroy_with_parent (GTK_WINDOW (window), FALSE);
416
417         g_object_get (annot,
418                       "label", &label,
419                       "opacity", &opacity,
420                       "is_open", &window->is_open,
421                       "rectangle", &window->rect,
422                       NULL);
423         rect = window->rect;
424
425         /* Rectangle is at doc resolution (72.0) */
426         scale = get_screen_dpi (GTK_WINDOW (window)) / 72.0;
427         gtk_window_resize (GTK_WINDOW (window),
428                            (gint)((rect->x2 - rect->x1) * scale),
429                            (gint)((rect->y2 - rect->y1) * scale));
430         ev_annotation_window_set_color (window, &annot->color);
431         gtk_widget_set_name (GTK_WIDGET (window), annot->name);
432         gtk_window_set_title (GTK_WINDOW (window), label);
433         gtk_label_set_text (GTK_LABEL (window->title), label);
434         gtk_window_set_opacity (GTK_WINDOW (window), opacity);
435         g_free (label);
436
437         if (annot->contents) {
438                 GtkTextBuffer *buffer;
439
440                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->text_view));
441                 gtk_text_buffer_set_text (buffer, annot->contents, -1);
442         }
443
444         return object;
445 }
446
447 static gboolean
448 ev_annotation_window_button_press_event (GtkWidget      *widget,
449                                          GdkEventButton *event)
450 {
451         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (widget);
452
453         if (event->type == GDK_BUTTON_PRESS && event->button == 1) {
454                 window->in_move = TRUE;
455                 window->x = event->x;
456                 window->y = event->y;
457                 gtk_window_begin_move_drag (GTK_WINDOW (widget),
458                                             event->button,
459                                             event->x_root,
460                                             event->y_root,
461                                             event->time);
462                 return TRUE;
463         }
464
465         return FALSE;
466 }
467
468 static gboolean
469 ev_annotation_window_configure_event (GtkWidget         *widget,
470                                       GdkEventConfigure *event)
471 {
472         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (widget);
473
474         if (window->in_move &&
475             (window->x != event->x || window->y != event->y)) {
476                 window->x = event->x;
477                 window->y = event->y;
478         }
479
480         return GTK_WIDGET_CLASS (ev_annotation_window_parent_class)->configure_event (widget, event);
481 }
482
483 static gboolean
484 ev_annotation_window_focus_in_event (GtkWidget     *widget,
485                                      GdkEventFocus *event)
486 {
487         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (widget);
488
489         if (window->in_move) {
490                 window->orig_x = window->x;
491                 window->orig_y = window->y;
492         }
493
494         return FALSE;
495 }
496
497 static gboolean
498 ev_annotation_window_focus_out_event (GtkWidget     *widget,
499                                       GdkEventFocus *event)
500 {
501         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (widget);
502
503         if (window->in_move &&
504             (window->orig_x != window->x || window->orig_y != window->y)) {
505                 window->in_move = FALSE;
506                 g_signal_emit (window, signals[MOVED], 0, window->x, window->y);
507         }
508
509         return FALSE;
510 }
511
512 static void
513 ev_annotation_window_class_init (EvAnnotationWindowClass *klass)
514 {
515         GObjectClass   *g_object_class = G_OBJECT_CLASS (klass);
516         GtkWidgetClass *gtk_widget_class = GTK_WIDGET_CLASS (klass);
517
518         g_object_class->constructor = ev_annotation_window_constructor;
519         g_object_class->set_property = ev_annotation_window_set_property;
520         g_object_class->dispose = ev_annotation_window_dispose;
521
522         gtk_widget_class->button_press_event = ev_annotation_window_button_press_event;
523         gtk_widget_class->configure_event = ev_annotation_window_configure_event;
524         gtk_widget_class->focus_in_event = ev_annotation_window_focus_in_event;
525         gtk_widget_class->focus_out_event = ev_annotation_window_focus_out_event;
526
527         g_object_class_install_property (g_object_class,
528                                          PROP_ANNOTATION,
529                                          g_param_spec_object ("annotation",
530                                                               "Annotation",
531                                                               "The annotation associated to the window",
532                                                               EV_TYPE_ANNOTATION_MARKUP,
533                                                               G_PARAM_WRITABLE |
534                                                               G_PARAM_CONSTRUCT_ONLY));
535         g_object_class_install_property (g_object_class,
536                                          PROP_PARENT,
537                                          g_param_spec_object ("parent",
538                                                               "Parent",
539                                                               "The parent window",
540                                                               GTK_TYPE_WINDOW,
541                                                               G_PARAM_WRITABLE |
542                                                               G_PARAM_CONSTRUCT_ONLY));
543         signals[CLOSED] =
544                 g_signal_new ("closed",
545                               G_TYPE_FROM_CLASS (g_object_class),
546                               G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
547                               G_STRUCT_OFFSET (EvAnnotationWindowClass, closed),
548                               NULL, NULL,
549                               g_cclosure_marshal_VOID__VOID,
550                               G_TYPE_NONE, 0, G_TYPE_NONE);
551         signals[MOVED] =
552                 g_signal_new ("moved",
553                               G_TYPE_FROM_CLASS (g_object_class),
554                               G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
555                               G_STRUCT_OFFSET (EvAnnotationWindowClass, moved),
556                               NULL, NULL,
557                               ev_view_marshal_VOID__INT_INT,
558                               G_TYPE_NONE, 2,
559                               G_TYPE_INT, G_TYPE_INT);
560 }
561
562 /* Public methods */
563 GtkWidget *
564 ev_annotation_window_new (EvAnnotation *annot,
565                           GtkWindow    *parent)
566 {
567         GtkWidget *window;
568
569         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (annot), NULL);
570         g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
571
572         window = g_object_new (EV_TYPE_ANNOTATION_WINDOW,
573                                "annotation", annot,
574                                "parent", parent,
575                                NULL);
576         return window;
577 }
578
579 EvAnnotation *
580 ev_annotation_window_get_annotation (EvAnnotationWindow *window)
581 {
582         g_return_val_if_fail (EV_IS_ANNOTATION_WINDOW (window), NULL);
583
584         return window->annotation;
585 }
586
587 void
588 ev_annotation_window_set_annotation (EvAnnotationWindow *window,
589                                      EvAnnotation       *annot)
590 {
591         g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
592         g_return_if_fail (EV_IS_ANNOTATION (annot));
593
594         if (annot == window->annotation)
595                 return;
596
597         g_object_unref (window->annotation);
598         window->annotation = g_object_ref (annot);
599         ev_annotation_window_check_contents_modified (window);
600         g_object_notify (G_OBJECT (window), "annotation");
601 }
602
603 gboolean
604 ev_annotation_window_is_open (EvAnnotationWindow *window)
605 {
606         g_return_val_if_fail (EV_IS_ANNOTATION_WINDOW (window), FALSE);
607
608         return window->is_open;
609 }
610
611 const EvRectangle *
612 ev_annotation_window_get_rectangle (EvAnnotationWindow *window)
613 {
614         g_return_val_if_fail (EV_IS_ANNOTATION_WINDOW (window), NULL);
615
616         return window->rect;
617 }
618
619 void
620 ev_annotation_window_set_rectangle (EvAnnotationWindow *window,
621                                     EvRectangle        *rect)
622 {
623         g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
624         g_return_if_fail (rect != NULL);
625
626         *window->rect = *rect;
627 }
628
629 void
630 ev_annotation_window_grab_focus (EvAnnotationWindow *window)
631 {
632         g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
633
634         if (!GTK_WIDGET_HAS_FOCUS (window->text_view)) {
635                 gtk_widget_grab_focus (GTK_WIDGET (window));
636                 send_focus_change (window->text_view, TRUE);
637         }
638 }
639
640 void
641 ev_annotation_window_ungrab_focus (EvAnnotationWindow *window)
642 {
643         g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
644
645         if (GTK_WIDGET_HAS_FOCUS (window->text_view)) {
646                 send_focus_change (window->text_view, FALSE);
647         }
648
649         ev_annotation_window_check_contents_modified (window);
650 }