]> www.fi.muni.cz Git - evince.git/blobdiff - libview/ev-annotation-window.c
[dualscreen] fix crash on ctrl+w and fix control window closing
[evince.git] / libview / ev-annotation-window.c
index f4a39163f7abe689deeec5ce0346fd1880a02fa1..8776dd4cf4cfd520a110690d14fbffb199a25fc3 100644 (file)
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 #include "config.h"
@@ -53,7 +53,7 @@ struct _EvAnnotationWindow {
        GtkWidget    *resize_sw;
 
        gboolean      is_open;
-       EvRectangle  *rect;
+       EvRectangle   rect;
 
        gboolean      in_move;
        gint          x;
@@ -84,22 +84,14 @@ send_focus_change (GtkWidget *widget,
 {
        GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
 
-       g_object_ref (widget);
-
-       if (in)
-               GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
-       else
-               GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
-
        fevent->focus_change.type = GDK_FOCUS_CHANGE;
-       fevent->focus_change.window = g_object_ref (widget->window);
+       fevent->focus_change.window = gtk_widget_get_window (widget);
        fevent->focus_change.in = in;
+       if (fevent->focus_change.window)
+               g_object_ref (fevent->focus_change.window);
 
-       gtk_widget_event (widget, fevent);
+       gtk_widget_send_focus_change (widget, fevent);
 
-       g_object_notify (G_OBJECT (widget), "has-focus");
-
-       g_object_unref (widget);
        gdk_event_free (fevent);
 }
 
@@ -124,7 +116,7 @@ ev_annotation_window_get_icon_size (void)
 }
 
 static void
-ev_annotation_window_check_contents_modified (EvAnnotationWindow *window)
+ev_annotation_window_sync_contents (EvAnnotationWindow *window)
 {
        gchar         *contents;
        GtkTextIter    start, end;
@@ -134,55 +126,61 @@ ev_annotation_window_check_contents_modified (EvAnnotationWindow *window)
        buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->text_view));
        gtk_text_buffer_get_bounds (buffer, &start, &end);
        contents = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
-
-       if (contents && annot->contents) {
-               if (strcasecmp (contents, annot->contents) != 0) {
-                       g_free (annot->contents);
-                       annot->contents = contents;
-                       annot->changed = TRUE;
-               } else {
-                       g_free (contents);
-               }
-       } else if (annot->contents) {
-               g_free (annot->contents);
-               annot->contents = NULL;
-               annot->changed = TRUE;
-       } else if (contents) {
-               annot->contents = contents;
-               annot->changed = TRUE;
-       }
+       ev_annotation_set_contents (annot, contents);
+       g_free (contents);
 }
 
 static void
 ev_annotation_window_set_color (EvAnnotationWindow *window,
                                GdkColor           *color)
 {
-       GtkRcStyle *rc_style;
-       GdkColor    gcolor;
-
-       gcolor = *color;
-
-       /* Allocate these colors */
-       gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (window)),
-                                 &gcolor, FALSE, TRUE);
-
-       /* Apply colors to style */
-       rc_style = gtk_widget_get_modifier_style (GTK_WIDGET (window));
-       rc_style->base[GTK_STATE_NORMAL] = gcolor;
-       rc_style->bg[GTK_STATE_PRELIGHT] = gcolor;
-       rc_style->bg[GTK_STATE_NORMAL] = gcolor;
-       rc_style->bg[GTK_STATE_ACTIVE] = gcolor;
-       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_BG;
-       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_BG | GTK_RC_BASE;
-       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_BG;
-
-       /* Apply the style to the widgets */
-       g_object_ref (rc_style);
-       gtk_widget_modify_style (GTK_WIDGET (window), rc_style);
-       gtk_widget_modify_style (window->close_button, rc_style);
-       gtk_widget_modify_style (window->resize_se, rc_style);
-       gtk_widget_modify_style (window->resize_sw, rc_style);
-       g_object_unref (rc_style);
+        GtkStyleProperties *properties;
+        GtkStyleProvider   *provider;
+       GdkRGBA             rgba;
+
+        rgba.red = color->red / 65535.;
+        rgba.green = color->green / 65535.;
+        rgba.blue = color->blue / 65535.;
+        rgba.alpha = 1;
+
+        properties = gtk_style_properties_new ();
+        gtk_style_properties_set (properties, 0,
+                                  "color", &rgba,
+                                  "background-color", &rgba,
+                                  NULL);
+
+        provider = GTK_STYLE_PROVIDER (properties);
+        gtk_style_context_add_provider (gtk_widget_get_style_context (GTK_WIDGET (window)),
+                                        provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+        gtk_style_context_add_provider (gtk_widget_get_style_context (window->close_button),
+                                        provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+        gtk_style_context_add_provider (gtk_widget_get_style_context (window->resize_se),
+                                        provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+        gtk_style_context_add_provider (gtk_widget_get_style_context (window->resize_sw),
+                                        provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+        g_object_unref (properties);
+}
+
+static void
+ev_annotation_window_label_changed (EvAnnotationMarkup *annot,
+                                   GParamSpec         *pspec,
+                                   EvAnnotationWindow *window)
+{
+       const gchar *label = ev_annotation_markup_get_label (annot);
+
+       gtk_window_set_title (GTK_WINDOW (window), label);
+       gtk_label_set_text (GTK_LABEL (window->title), label);
+}
+
+static void
+ev_annotation_window_color_changed (EvAnnotation       *annot,
+                                   GParamSpec         *pspec,
+                                   EvAnnotationWindow *window)
+{
+       GdkColor color;
+
+       ev_annotation_get_color (annot, &color);
+       ev_annotation_window_set_color (window, &color);
 }
 
 static void
@@ -191,16 +189,11 @@ ev_annotation_window_dispose (GObject *object)
        EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (object);
 
        if (window->annotation) {
-               ev_annotation_window_check_contents_modified (window);
+               ev_annotation_window_sync_contents (window);
                g_object_unref (window->annotation);
                window->annotation = NULL;
        }
 
-       if (window->rect) {
-               ev_rectangle_free (window->rect);
-               window->rect = NULL;
-       }
-
        (* G_OBJECT_CLASS (ev_annotation_window_parent_class)->dispose) (object);
 }
 
@@ -246,10 +239,12 @@ static void
 ev_annotation_window_set_resize_cursor (GtkWidget          *widget,
                                        EvAnnotationWindow *window)
 {
-       if (!widget->window)
+       GdkWindow *gdk_window = gtk_widget_get_window (widget);
+
+       if (!gdk_window)
                return;
 
-       if (GTK_WIDGET_IS_SENSITIVE (widget)) {
+       if (gtk_widget_is_sensitive (widget)) {
                GdkDisplay *display = gtk_widget_get_display (widget);
                GdkCursor  *cursor;
 
@@ -257,10 +252,10 @@ ev_annotation_window_set_resize_cursor (GtkWidget          *widget,
                                                     widget == window->resize_sw ?
                                                     GDK_BOTTOM_LEFT_CORNER :
                                                     GDK_BOTTOM_RIGHT_CORNER);
-               gdk_window_set_cursor (widget->window, cursor);
-               gdk_cursor_unref (cursor);
+               gdk_window_set_cursor (gdk_window, cursor);
+               g_object_unref (cursor);
        } else {
-               gdk_window_set_cursor (widget->window, NULL);
+               gdk_window_set_cursor (gdk_window, NULL);
        }
 }
 
@@ -288,7 +283,7 @@ ev_annotation_window_init (EvAnnotationWindow *window)
        GtkWidget *icon;
        GtkWidget *swindow;
 
-       GTK_WIDGET_SET_FLAGS (window, GTK_CAN_FOCUS);
+       gtk_widget_set_can_focus (GTK_WIDGET (window), TRUE);
 
        vbox = gtk_vbox_new (FALSE, 0);
 
@@ -325,6 +320,7 @@ ev_annotation_window_init (EvAnnotationWindow *window)
                                        GTK_POLICY_AUTOMATIC,
                                        GTK_POLICY_AUTOMATIC);
        window->text_view = gtk_text_view_new ();
+       gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (window->text_view), GTK_WRAP_WORD);
        g_signal_connect (window->text_view, "button_press_event",
                          G_CALLBACK (text_view_button_press),
                          window);
@@ -335,6 +331,7 @@ ev_annotation_window_init (EvAnnotationWindow *window)
        gtk_widget_show (swindow);
 
        /* Resize bar */
+       gtk_window_set_has_resize_grip (GTK_WINDOW(window), FALSE);
        hbox = gtk_hbox_new (FALSE, 0);
 
        window->resize_sw = gtk_event_box_new ();
@@ -396,8 +393,10 @@ ev_annotation_window_constructor (GType                  type,
        GObject            *object;
        EvAnnotationWindow *window;
        EvAnnotation       *annot;
-       gchar              *label;
-       gdouble             opacity;
+       EvAnnotationMarkup *markup;
+       const gchar        *contents;
+       const gchar        *label;
+       GdkColor            color;
        EvRectangle        *rect;
        gdouble             scale;
 
@@ -406,37 +405,44 @@ ev_annotation_window_constructor (GType                  type,
                                                                                  construct_params);
        window = EV_ANNOTATION_WINDOW (object);
        annot = window->annotation;
+       markup = EV_ANNOTATION_MARKUP (annot);
 
        gtk_window_set_transient_for (GTK_WINDOW (window), window->parent);
        gtk_window_set_destroy_with_parent (GTK_WINDOW (window), FALSE);
 
-       g_object_get (annot,
-                     "label", &label,
-                     "opacity", &opacity,
-                     "is_open", &window->is_open,
-                     "rectangle", &window->rect,
-                     NULL);
-       rect = window->rect;
+       label = ev_annotation_markup_get_label (markup);
+       window->is_open = ev_annotation_markup_get_popup_is_open (markup);
+       ev_annotation_markup_get_rectangle (markup, &window->rect);
+
+       rect = &window->rect;
 
        /* Rectangle is at doc resolution (72.0) */
        scale = get_screen_dpi (window) / 72.0;
        gtk_window_resize (GTK_WINDOW (window),
                           (gint)((rect->x2 - rect->x1) * scale),
                           (gint)((rect->y2 - rect->y1) * scale));
-       ev_annotation_window_set_color (window, &annot->color);
-       gtk_widget_set_name (GTK_WIDGET (window), annot->name);
+
+       ev_annotation_get_color (annot, &color);
+       ev_annotation_window_set_color (window, &color);
+       gtk_widget_set_name (GTK_WIDGET (window), ev_annotation_get_name (annot));
        gtk_window_set_title (GTK_WINDOW (window), label);
        gtk_label_set_text (GTK_LABEL (window->title), label);
-       gtk_window_set_opacity (GTK_WINDOW (window), opacity);
-       g_free (label);
 
-       if (annot->contents) {
+       contents = ev_annotation_get_contents (annot);
+       if (contents) {
                GtkTextBuffer *buffer;
 
                buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->text_view));
-               gtk_text_buffer_set_text (buffer, annot->contents, -1);
+               gtk_text_buffer_set_text (buffer, contents, -1);
        }
 
+       g_signal_connect (annot, "notify::label",
+                         G_CALLBACK (ev_annotation_window_label_changed),
+                         window);
+       g_signal_connect (annot, "notify::color",
+                         G_CALLBACK (ev_annotation_window_color_changed),
+                         window);
+
        return object;
 }
 
@@ -448,8 +454,8 @@ ev_annotation_window_button_press_event (GtkWidget      *widget,
 
        if (event->type == GDK_BUTTON_PRESS && event->button == 1) {
                window->in_move = TRUE;
-               window->x = event->x;
-               window->y = event->y;
+               window->x = event->x_root - event->x;
+               window->y = event->y_root - event->y;
                gtk_window_begin_move_drag (GTK_WINDOW (widget),
                                            event->button,
                                            event->x_root,
@@ -483,8 +489,12 @@ ev_annotation_window_focus_in_event (GtkWidget     *widget,
        EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (widget);
 
        if (window->in_move) {
-               window->orig_x = window->x;
-               window->orig_y = window->y;
+               if (window->orig_x != window->x || window->orig_y != window->y) {
+                       window->orig_x = window->x;
+                       window->orig_y = window->y;
+                       g_signal_emit (window, signals[MOVED], 0, window->x, window->y);
+               }
+               window->in_move = FALSE;
        }
 
        return FALSE;
@@ -496,15 +506,29 @@ ev_annotation_window_focus_out_event (GtkWidget     *widget,
 {
        EvAnnotationWindow *window = EV_ANNOTATION_WINDOW (widget);
 
-       if (window->in_move &&
-           (window->orig_x != window->x || window->orig_y != window->y)) {
-               window->in_move = FALSE;
-               g_signal_emit (window, signals[MOVED], 0, window->x, window->y);
-       }
+       ev_annotation_window_sync_contents (window);
 
        return FALSE;
 }
 
+static gboolean
+ev_annotation_window_enter_notify_event (GtkWidget        *widget,
+                                         GdkEventCrossing *event)
+{
+        gtk_window_set_accept_focus (GTK_WINDOW (widget), TRUE);
+
+        return FALSE;
+}
+
+static gboolean
+ev_annotation_window_leave_notify_event (GtkWidget        *widget,
+                                         GdkEventCrossing *event)
+{
+        gtk_window_set_accept_focus (GTK_WINDOW (widget), FALSE);
+
+        return FALSE;
+}
+
 static void
 ev_annotation_window_class_init (EvAnnotationWindowClass *klass)
 {
@@ -519,6 +543,8 @@ ev_annotation_window_class_init (EvAnnotationWindowClass *klass)
        gtk_widget_class->configure_event = ev_annotation_window_configure_event;
        gtk_widget_class->focus_in_event = ev_annotation_window_focus_in_event;
        gtk_widget_class->focus_out_event = ev_annotation_window_focus_out_event;
+        gtk_widget_class->enter_notify_event = ev_annotation_window_enter_notify_event;
+        gtk_widget_class->leave_notify_event = ev_annotation_window_leave_notify_event;
 
        g_object_class_install_property (g_object_class,
                                         PROP_ANNOTATION,
@@ -592,7 +618,7 @@ ev_annotation_window_set_annotation (EvAnnotationWindow *window,
 
        g_object_unref (window->annotation);
        window->annotation = g_object_ref (annot);
-       ev_annotation_window_check_contents_modified (window);
+       ev_annotation_window_sync_contents (window);
        g_object_notify (G_OBJECT (window), "annotation");
 }
 
@@ -604,22 +630,24 @@ ev_annotation_window_is_open (EvAnnotationWindow *window)
        return window->is_open;
 }
 
-const EvRectangle *
-ev_annotation_window_get_rectangle (EvAnnotationWindow *window)
+void
+ev_annotation_window_get_rectangle (EvAnnotationWindow *window,
+                                   EvRectangle        *rect)
 {
-       g_return_val_if_fail (EV_IS_ANNOTATION_WINDOW (window), NULL);
+       g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
+       g_return_if_fail (rect != NULL);
 
-       return window->rect;
+       *rect = window->rect;
 }
 
 void
 ev_annotation_window_set_rectangle (EvAnnotationWindow *window,
-                                   EvRectangle        *rect)
+                                   const EvRectangle  *rect)
 {
        g_return_if_fail (EV_IS_ANNOTATION_WINDOW (window));
        g_return_if_fail (rect != NULL);
 
-       *window->rect = *rect;
+       window->rect = *rect;
 }
 
 void
@@ -642,5 +670,5 @@ ev_annotation_window_ungrab_focus (EvAnnotationWindow *window)
                send_focus_change (window->text_view, FALSE);
        }
 
-       ev_annotation_window_check_contents_modified (window);
+       ev_annotation_window_sync_contents (window);
 }