]> www.fi.muni.cz Git - evince.git/blob - libview/ev-annotation-window.c
[dualscreen] fix crash on ctrl+w and fix control window closing
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 #include "ev-document-misc.h"
30
31 enum {
32         PROP_0,
33         PROP_ANNOTATION,
34         PROP_PARENT
35 };
36
37 enum {
38         CLOSED,
39         MOVED,
40         N_SIGNALS
41 };
42
43 struct _EvAnnotationWindow {
44         GtkWindow     base_instance;
45
46         EvAnnotation *annotation;
47         GtkWindow    *parent;
48
49         GtkWidget    *title;
50         GtkWidget    *close_button;
51         GtkWidget    *text_view;
52         GtkWidget    *resize_se;
53         GtkWidget    *resize_sw;
54
55         gboolean      is_open;
56         EvRectangle   rect;
57
58         gboolean      in_move;
59         gint          x;
60         gint          y;
61         gint          orig_x;
62         gint          orig_y;
63 };
64
65 struct _EvAnnotationWindowClass {
66         GtkWindowClass base_class;
67
68         void (* closed) (EvAnnotationWindow *window);
69         void (* moved)  (EvAnnotationWindow *window,
70                          gint                x,
71                          gint                y);
72 };
73
74 static guint signals[N_SIGNALS];
75
76 G_DEFINE_TYPE (EvAnnotationWindow, ev_annotation_window, GTK_TYPE_WINDOW)
77
78 #define EV_ICON_SIZE_ANNOT_WINDOW (ev_annotation_window_get_icon_size())
79
80 /* Cut and paste from gtkwindow.c */
81 static void
82 send_focus_change (GtkWidget *widget,
83                    gboolean   in)
84 {
85         GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
86
87         fevent->focus_change.type = GDK_FOCUS_CHANGE;
88         fevent->focus_change.window = gtk_widget_get_window (widget);
89         fevent->focus_change.in = in;
90         if (fevent->focus_change.window)
91                 g_object_ref (fevent->focus_change.window);
92
93         gtk_widget_send_focus_change (widget, fevent);
94
95         gdk_event_free (fevent);
96 }
97
98 static gdouble
99 get_screen_dpi (EvAnnotationWindow *window)
100 {
101         GdkScreen *screen;
102
103         screen = gtk_window_get_screen (GTK_WINDOW (window));
104         return ev_document_misc_get_screen_dpi (screen);
105 }
106
107 static GtkIconSize
108 ev_annotation_window_get_icon_size (void)
109 {
110         static GtkIconSize icon_size = 0;
111
112         if (G_UNLIKELY (icon_size == 0))
113                 icon_size = gtk_icon_size_register ("ev-icon-size-annot-window", 8, 8);
114
115         return icon_size;
116 }
117
118 static void
119 ev_annotation_window_sync_contents (EvAnnotationWindow *window)
120 {
121         gchar         *contents;
122         GtkTextIter    start, end;
123         GtkTextBuffer *buffer;
124         EvAnnotation  *annot = window->annotation;
125
126         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->text_view));
127         gtk_text_buffer_get_bounds (buffer, &start, &end);
128         contents = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
129         ev_annotation_set_contents (annot, contents);
130         g_free (contents);
131 }
132
133 static void
134 ev_annotation_window_set_color (EvAnnotationWindow *window,
135                                 GdkColor           *color)
136 {
137         GtkStyleProperties *properties;
138         GtkStyleProvider   *provider;
139         GdkRGBA             rgba;
140
141         rgba.red = color->red / 65535.;
142         rgba.green = color->green / 65535.;
143         rgba.blue = color->blue / 65535.;
144         rgba.alpha = 1;
145
146         properties = gtk_style_properties_new ();
147         gtk_style_properties_set (properties, 0,
148                                   "color", &rgba,
149                                   "background-color", &rgba,
150                                   NULL);
151
152         provider = GTK_STYLE_PROVIDER (properties);
153         gtk_style_context_add_provider (gtk_widget_get_style_context (GTK_WIDGET (window)),
154                                         provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
155         gtk_style_context_add_provider (gtk_widget_get_style_context (window->close_button),
156                                         provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
157         gtk_style_context_add_provider (gtk_widget_get_style_context (window->resize_se),
158                                         provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
159         gtk_style_context_add_provider (gtk_widget_get_style_context (window->resize_sw),
160                                         provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
161         g_object_unref (properties);
162 }
163
164 static void
165 ev_annotation_window_label_changed (EvAnnotationMarkup *annot,
166                                     GParamSpec         *pspec,
167                                     EvAnnotationWindow *window)
168 {
169         const gchar *label = ev_annotation_markup_get_label (annot);
170
171         gtk_window_set_title (GTK_WINDOW (window), label);
172         gtk_label_set_text (GTK_LABEL (window->title), label);
173 }
174
175 static void
176 ev_annotation_window_color_changed (EvAnnotation       *annot,
177                                     GParamSpec         *pspec,
178                                     EvAnnotationWindow *window)
179 {
180         GdkColor color;
181
182         ev_annotation_get_color (annot, &color);
183         ev_annotation_window_set_color (window, &color);
184 }
185
186 static void
187 ev_annotation_window_dispose (GObject *object)
188 {
189         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (object);
190
191         if (window->annotation) {
192                 ev_annotation_window_sync_contents (window);
193                 g_object_unref (window->annotation);
194                 window->annotation = NULL;
195         }
196
197         (* G_OBJECT_CLASS (ev_annotation_window_parent_class)->dispose) (object);
198 }
199
200 static void
201 ev_annotation_window_set_property (GObject      *object,
202                                    guint         prop_id,
203                                    const GValue *value,
204                                    GParamSpec   *pspec)
205 {
206         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (object);
207
208         switch (prop_id) {
209         case PROP_ANNOTATION:
210                 window->annotation = g_value_dup_object (value);
211                 break;
212         case PROP_PARENT:
213                 window->parent = g_value_get_object (value);
214                 break;
215         default:
216                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
217         }
218 }
219
220 static gboolean
221 ev_annotation_window_resize (EvAnnotationWindow *window,
222                              GdkEventButton     *event,
223                              GtkWidget          *ebox)
224 {
225         if (event->type == GDK_BUTTON_PRESS && event->button == 1) {
226                 gtk_window_begin_resize_drag (GTK_WINDOW (window),
227                                               window->resize_sw == ebox ?
228                                               GDK_WINDOW_EDGE_SOUTH_WEST :
229                                               GDK_WINDOW_EDGE_SOUTH_EAST,
230                                               event->button, event->x_root,
231                                               event->y_root, event->time);
232                 return TRUE;
233         }
234
235         return FALSE;
236 }
237
238 static void
239 ev_annotation_window_set_resize_cursor (GtkWidget          *widget,
240                                         EvAnnotationWindow *window)
241 {
242         GdkWindow *gdk_window = gtk_widget_get_window (widget);
243
244         if (!gdk_window)
245                 return;
246
247         if (gtk_widget_is_sensitive (widget)) {
248                 GdkDisplay *display = gtk_widget_get_display (widget);
249                 GdkCursor  *cursor;
250
251                 cursor = gdk_cursor_new_for_display (display,
252                                                      widget == window->resize_sw ?
253                                                      GDK_BOTTOM_LEFT_CORNER :
254                                                      GDK_BOTTOM_RIGHT_CORNER);
255                 gdk_window_set_cursor (gdk_window, cursor);
256                 g_object_unref (cursor);
257         } else {
258                 gdk_window_set_cursor (gdk_window, NULL);
259         }
260 }
261
262 static gboolean
263 text_view_button_press (GtkWidget          *widget,
264                         GdkEventButton     *event,
265                         EvAnnotationWindow *window)
266 {
267         ev_annotation_window_grab_focus (window);
268
269         return FALSE;
270 }
271
272 static void
273 ev_annotation_window_close (EvAnnotationWindow *window)
274 {
275         gtk_widget_hide (GTK_WIDGET (window));
276         g_signal_emit (window, signals[CLOSED], 0);
277 }
278
279 static void
280 ev_annotation_window_init (EvAnnotationWindow *window)
281 {
282         GtkWidget *vbox, *hbox;
283         GtkWidget *icon;
284         GtkWidget *swindow;
285
286         gtk_widget_set_can_focus (GTK_WIDGET (window), TRUE);
287
288         vbox = gtk_vbox_new (FALSE, 0);
289
290         /* Title bar */
291         hbox = gtk_hbox_new (FALSE, 0);
292
293         icon = gtk_image_new (); /* FIXME: use the annot icon */
294         gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
295         gtk_widget_show (icon);
296
297         window->title = gtk_label_new (NULL);
298         gtk_box_pack_start (GTK_BOX (hbox), window->title, TRUE, TRUE, 0);
299         gtk_widget_show (window->title);
300
301         window->close_button = gtk_button_new ();
302         gtk_button_set_relief (GTK_BUTTON (window->close_button), GTK_RELIEF_NONE);
303         gtk_container_set_border_width (GTK_CONTAINER (window->close_button), 0);
304         g_signal_connect_swapped (window->close_button, "clicked",
305                                   G_CALLBACK (ev_annotation_window_close),
306                                   window);
307         icon = gtk_image_new_from_stock (EV_STOCK_CLOSE, EV_ICON_SIZE_ANNOT_WINDOW);
308         gtk_container_add (GTK_CONTAINER (window->close_button), icon);
309         gtk_widget_show (icon);
310
311         gtk_box_pack_start (GTK_BOX (hbox), window->close_button, FALSE, FALSE, 0);
312         gtk_widget_show (window->close_button);
313
314         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
315         gtk_widget_show (hbox);
316
317         /* Contents */
318         swindow = gtk_scrolled_window_new (NULL, NULL);
319         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
320                                         GTK_POLICY_AUTOMATIC,
321                                         GTK_POLICY_AUTOMATIC);
322         window->text_view = gtk_text_view_new ();
323         gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (window->text_view), GTK_WRAP_WORD);
324         g_signal_connect (window->text_view, "button_press_event",
325                           G_CALLBACK (text_view_button_press),
326                           window);
327         gtk_container_add (GTK_CONTAINER (swindow), window->text_view);
328         gtk_widget_show (window->text_view);
329
330         gtk_box_pack_start (GTK_BOX (vbox), swindow, TRUE, TRUE, 0);
331         gtk_widget_show (swindow);
332
333         /* Resize bar */
334         gtk_window_set_has_resize_grip (GTK_WINDOW(window), FALSE);
335         hbox = gtk_hbox_new (FALSE, 0);
336
337         window->resize_sw = gtk_event_box_new ();
338         gtk_widget_add_events (window->resize_sw, GDK_BUTTON_PRESS_MASK);
339         g_signal_connect_swapped (window->resize_sw, "button-press-event",
340                                   G_CALLBACK (ev_annotation_window_resize),
341                                   window);
342         g_signal_connect (window->resize_sw, "realize",
343                           G_CALLBACK (ev_annotation_window_set_resize_cursor),
344                           window);
345
346         icon = gtk_image_new_from_stock (EV_STOCK_RESIZE_SW, EV_ICON_SIZE_ANNOT_WINDOW);
347         gtk_container_add (GTK_CONTAINER (window->resize_sw), icon);
348         gtk_widget_show (icon);
349         gtk_box_pack_start (GTK_BOX (hbox), window->resize_sw, FALSE, FALSE, 0);
350         gtk_widget_show (window->resize_sw);
351
352         window->resize_se = gtk_event_box_new ();
353         gtk_widget_add_events (window->resize_se, GDK_BUTTON_PRESS_MASK);
354         g_signal_connect_swapped (window->resize_se, "button-press-event",
355                                   G_CALLBACK (ev_annotation_window_resize),
356                                   window);
357         g_signal_connect (window->resize_se, "realize",
358                           G_CALLBACK (ev_annotation_window_set_resize_cursor),
359                           window);
360
361         icon = gtk_image_new_from_stock (EV_STOCK_RESIZE_SE, EV_ICON_SIZE_ANNOT_WINDOW);
362         gtk_container_add (GTK_CONTAINER (window->resize_se), icon);
363         gtk_widget_show (icon);
364         gtk_box_pack_end (GTK_BOX (hbox), window->resize_se, FALSE, FALSE, 0);
365         gtk_widget_show (window->resize_se);
366
367         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
368         gtk_widget_show (hbox);
369
370         gtk_container_add (GTK_CONTAINER (window), vbox);
371         gtk_container_set_border_width (GTK_CONTAINER (window), 0);
372         gtk_widget_show (vbox);
373
374         gtk_widget_add_events (GTK_WIDGET (window),
375                                GDK_BUTTON_PRESS_MASK |
376                                GDK_KEY_PRESS_MASK);
377         gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
378
379         gtk_container_set_border_width (GTK_CONTAINER (window), 2);
380
381         gtk_window_set_accept_focus (GTK_WINDOW (window), FALSE);
382         gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
383         gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE);
384         gtk_window_set_skip_pager_hint (GTK_WINDOW (window), TRUE);
385         gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
386 }
387
388 static GObject *
389 ev_annotation_window_constructor (GType                  type,
390                                   guint                  n_construct_properties,
391                                   GObjectConstructParam *construct_params)
392 {
393         GObject            *object;
394         EvAnnotationWindow *window;
395         EvAnnotation       *annot;
396         EvAnnotationMarkup *markup;
397         const gchar        *contents;
398         const gchar        *label;
399         GdkColor            color;
400         EvRectangle        *rect;
401         gdouble             scale;
402
403         object = G_OBJECT_CLASS (ev_annotation_window_parent_class)->constructor (type,
404                                                                                   n_construct_properties,
405                                                                                   construct_params);
406         window = EV_ANNOTATION_WINDOW (object);
407         annot = window->annotation;
408         markup = EV_ANNOTATION_MARKUP (annot);
409
410         gtk_window_set_transient_for (GTK_WINDOW (window), window->parent);
411         gtk_window_set_destroy_with_parent (GTK_WINDOW (window), FALSE);
412
413         label = ev_annotation_markup_get_label (markup);
414         window->is_open = ev_annotation_markup_get_popup_is_open (markup);
415         ev_annotation_markup_get_rectangle (markup, &window->rect);
416
417         rect = &window->rect;
418
419         /* Rectangle is at doc resolution (72.0) */
420         scale = get_screen_dpi (window) / 72.0;
421         gtk_window_resize (GTK_WINDOW (window),
422                            (gint)((rect->x2 - rect->x1) * scale),
423                            (gint)((rect->y2 - rect->y1) * scale));
424
425         ev_annotation_get_color (annot, &color);
426         ev_annotation_window_set_color (window, &color);
427         gtk_widget_set_name (GTK_WIDGET (window), ev_annotation_get_name (annot));
428         gtk_window_set_title (GTK_WINDOW (window), label);
429         gtk_label_set_text (GTK_LABEL (window->title), label);
430
431         contents = ev_annotation_get_contents (annot);
432         if (contents) {
433                 GtkTextBuffer *buffer;
434
435                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->text_view));
436                 gtk_text_buffer_set_text (buffer, contents, -1);
437         }
438
439         g_signal_connect (annot, "notify::label",
440                           G_CALLBACK (ev_annotation_window_label_changed),
441                           window);
442         g_signal_connect (annot, "notify::color",
443                           G_CALLBACK (ev_annotation_window_color_changed),
444                           window);
445
446         return object;
447 }
448
449 static gboolean
450 ev_annotation_window_button_press_event (GtkWidget      *widget,
451                                          GdkEventButton *event)
452 {
453         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (widget);
454
455         if (event->type == GDK_BUTTON_PRESS && event->button == 1) {
456                 window->in_move = TRUE;
457                 window->x = event->x_root - event->x;
458                 window->y = event->y_root - event->y;
459                 gtk_window_begin_move_drag (GTK_WINDOW (widget),
460                                             event->button,
461                                             event->x_root,
462                                             event->y_root,
463                                             event->time);
464                 return TRUE;
465         }
466
467         return FALSE;
468 }
469
470 static gboolean
471 ev_annotation_window_configure_event (GtkWidget         *widget,
472                                       GdkEventConfigure *event)
473 {
474         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (widget);
475
476         if (window->in_move &&
477             (window->x != event->x || window->y != event->y)) {
478                 window->x = event->x;
479                 window->y = event->y;
480         }
481
482         return GTK_WIDGET_CLASS (ev_annotation_window_parent_class)->configure_event (widget, event);
483 }
484
485 static gboolean
486 ev_annotation_window_focus_in_event (GtkWidget     *widget,
487                                      GdkEventFocus *event)
488 {
489         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (widget);
490
491         if (window->in_move) {
492                 if (window->orig_x != window->x || window->orig_y != window->y) {
493                         window->orig_x = window->x;
494                         window->orig_y = window->y;
495                         g_signal_emit (window, signals[MOVED], 0, window->x, window->y);
496                 }
497                 window->in_move = FALSE;
498         }
499
500         return FALSE;
501 }
502
503 static gboolean
504 ev_annotation_window_focus_out_event (GtkWidget     *widget,
505                                       GdkEventFocus *event)
506 {
507         EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (widget);
508
509         ev_annotation_window_sync_contents (window);
510
511         return FALSE;
512 }
513
514 static gboolean
515 ev_annotation_window_enter_notify_event (GtkWidget        *widget,
516                                          GdkEventCrossing *event)
517 {
518         gtk_window_set_accept_focus (GTK_WINDOW (widget), TRUE);
519
520         return FALSE;
521 }
522
523 static gboolean
524 ev_annotation_window_leave_notify_event (GtkWidget        *widget,
525                                          GdkEventCrossing *event)
526 {
527         gtk_window_set_accept_focus (GTK_WINDOW (widget), FALSE);
528
529         return FALSE;
530 }
531
532 static void
533 ev_annotation_window_class_init (EvAnnotationWindowClass *klass)
534 {
535         GObjectClass   *g_object_class = G_OBJECT_CLASS (klass);
536         GtkWidgetClass *gtk_widget_class = GTK_WIDGET_CLASS (klass);
537
538         g_object_class->constructor = ev_annotation_window_constructor;
539         g_object_class->set_property = ev_annotation_window_set_property;
540         g_object_class->dispose = ev_annotation_window_dispose;
541
542         gtk_widget_class->button_press_event = ev_annotation_window_button_press_event;
543         gtk_widget_class->configure_event = ev_annotation_window_configure_event;
544         gtk_widget_class->focus_in_event = ev_annotation_window_focus_in_event;
545         gtk_widget_class->focus_out_event = ev_annotation_window_focus_out_event;
546         gtk_widget_class->enter_notify_event = ev_annotation_window_enter_notify_event;
547         gtk_widget_class->leave_notify_event = ev_annotation_window_leave_notify_event;
548
549         g_object_class_install_property (g_object_class,
550                                          PROP_ANNOTATION,
551                                          g_param_spec_object ("annotation",
552                                                               "Annotation",
553                                                               "The annotation associated to the window",
554                                                               EV_TYPE_ANNOTATION_MARKUP,
555                                                               G_PARAM_WRITABLE |
556                                                               G_PARAM_CONSTRUCT_ONLY));
557         g_object_class_install_property (g_object_class,
558                                          PROP_PARENT,
559                                          g_param_spec_object ("parent",
560                                                               "Parent",
561                                                               "The parent window",
562                                                               GTK_TYPE_WINDOW,
563                                                               G_PARAM_WRITABLE |
564                                                               G_PARAM_CONSTRUCT_ONLY));
565         signals[CLOSED] =
566                 g_signal_new ("closed",
567                               G_TYPE_FROM_CLASS (g_object_class),
568                               G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
569                               G_STRUCT_OFFSET (EvAnnotationWindowClass, closed),
570                               NULL, NULL,
571                               g_cclosure_marshal_VOID__VOID,
572                               G_TYPE_NONE, 0, G_TYPE_NONE);
573         signals[MOVED] =
574                 g_signal_new ("moved",
575                               G_TYPE_FROM_CLASS (g_object_class),
576                               G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
577                               G_STRUCT_OFFSET (EvAnnotationWindowClass, moved),
578                               NULL, NULL,
579                               ev_view_marshal_VOID__INT_INT,
580                               G_TYPE_NONE, 2,
581                               G_TYPE_INT, G_TYPE_INT);
582 }
583
584 /* Public methods */
585 GtkWidget *
586 ev_annotation_window_new (EvAnnotation *annot,
587                           GtkWindow    *parent)
588 {
589         GtkWidget *window;
590
591         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (annot), NULL);
592         g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
593
594         window = g_object_new (EV_TYPE_ANNOTATION_WINDOW,
595                                "annotation", annot,
596                                "parent", parent,
597                                NULL);
598         return window;
599 }
600
601 EvAnnotation *
602 ev_annotation_window_get_annotation (EvAnnotationWindow *window)
603 {
604         g_return_val_if_fail (EV_IS_ANNOTATION_WINDOW (window), NULL);
605
606         return window->annotation;
607 }
608
609 void
610 ev_annotation_window_set_annotation (EvAnnotationWindow *window,
611                                      EvAnnotation       *annot)
612 {
613         g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
614         g_return_if_fail (EV_IS_ANNOTATION (annot));
615
616         if (annot == window->annotation)
617                 return;
618
619         g_object_unref (window->annotation);
620         window->annotation = g_object_ref (annot);
621         ev_annotation_window_sync_contents (window);
622         g_object_notify (G_OBJECT (window), "annotation");
623 }
624
625 gboolean
626 ev_annotation_window_is_open (EvAnnotationWindow *window)
627 {
628         g_return_val_if_fail (EV_IS_ANNOTATION_WINDOW (window), FALSE);
629
630         return window->is_open;
631 }
632
633 void
634 ev_annotation_window_get_rectangle (EvAnnotationWindow *window,
635                                     EvRectangle        *rect)
636 {
637         g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
638         g_return_if_fail (rect != NULL);
639
640         *rect = window->rect;
641 }
642
643 void
644 ev_annotation_window_set_rectangle (EvAnnotationWindow *window,
645                                     const EvRectangle  *rect)
646 {
647         g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
648         g_return_if_fail (rect != NULL);
649
650         window->rect = *rect;
651 }
652
653 void
654 ev_annotation_window_grab_focus (EvAnnotationWindow *window)
655 {
656         g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
657
658         if (!gtk_widget_has_focus (window->text_view)) {
659                 gtk_widget_grab_focus (GTK_WIDGET (window));
660                 send_focus_change (window->text_view, TRUE);
661         }
662 }
663
664 void
665 ev_annotation_window_ungrab_focus (EvAnnotationWindow *window)
666 {
667         g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
668
669         if (gtk_widget_has_focus (window->text_view)) {
670                 send_focus_change (window->text_view, FALSE);
671         }
672
673         ev_annotation_window_sync_contents (window);
674 }