[glabels] Don't intercept copy/paste operations intended for other widgets



commit 2d0b321b49e0dcf8701d000bc2c5f9f4673689f8
Author: Jim Evins <evins snaught com>
Date:   Wed Dec 2 23:04:09 2009 -0500

    Don't intercept copy/paste operations intended for other widgets
    
    Fixes bugs 1683799, 2833194 and probably 1978142.  Only enable copy/paste
    verbs if the focused widget is the glView.  Otherwise let these operations
    propagate to the focused widget to be handled natively.

 .gitignore        |    2 +
 src/label.c       |   30 +++++----------
 src/label.h       |    9 +++-
 src/ui-commands.c |   36 +++++++++++++----
 src/ui.c          |   28 +++++++++----
 src/ui.h          |    4 ++
 src/window.c      |  110 +++++++++++++++++++++++++++++++++++++++++++++++------
 7 files changed, 167 insertions(+), 52 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index b89e7e4..bbfdd15 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,6 +80,8 @@ glabels-*.tar.gz
 #
 *~
 *.bak
+\#*\#
+.\#*
 .*.swp
 *.orig
 *.rej
diff --git a/src/label.c b/src/label.c
index b361685..770ecbc 100644
--- a/src/label.c
+++ b/src/label.c
@@ -38,8 +38,6 @@
 /* Private macros and constants.                          */
 /*========================================================*/
 
-#define GLABELS_CLIPBOARD gdk_atom_intern ("GLABELS", FALSE)
-
 
 /*========================================================*/
 /* Private types.                                         */
@@ -2164,14 +2162,14 @@ gl_label_set_selection_line_width (glLabel  *label,
 /*****************************************************************************/
 void
 gl_label_cut_selection (glLabel       *label,
-                        GtkWidget     *owner)
+                        GtkClipboard  *glabels_clipboard,
+                        GtkClipboard  *std_clipboard)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
-	g_return_if_fail (owner && GTK_IS_WIDGET (owner));
 
-	gl_label_copy_selection (label, owner);
+	gl_label_copy_selection (label, glabels_clipboard, std_clipboard);
 	gl_label_delete_selection (label);
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -2183,10 +2181,10 @@ gl_label_cut_selection (glLabel       *label,
 /*****************************************************************************/
 void
 gl_label_copy_selection (glLabel       *label,
-                         GtkWidget     *owner)
+                         GtkClipboard  *glabels_clipboard,
+                         GtkClipboard  *std_clipboard)
 {
 	GList             *selection_list;
-        GtkClipboard      *clipboard;
         glLabel           *label_copy;
 	GList             *p;
 	glLabelObject     *object;
@@ -2197,13 +2195,11 @@ gl_label_copy_selection (glLabel       *label,
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
-	g_return_if_fail (owner && GTK_IS_WIDGET (owner));
 
         selection_list = gl_label_get_selection_list (label);
 
 	if (selection_list)
         {
-                clipboard = gtk_widget_get_clipboard (owner, GLABELS_CLIPBOARD);
 		label_copy = GL_LABEL(gl_label_new ());
 
 		gl_label_set_template (label_copy, label->priv->template);
@@ -2218,7 +2214,7 @@ gl_label_copy_selection (glLabel       *label,
 
                 buffer = gl_xml_label_save_buffer (label_copy, &status);
                 
-                gtk_clipboard_set_text (clipboard, buffer, -1);
+                gtk_clipboard_set_text (glabels_clipboard, buffer, -1);
 
                 g_free (buffer);
                 g_object_unref (G_OBJECT (label_copy));
@@ -2231,11 +2227,9 @@ gl_label_copy_selection (glLabel       *label,
          */
         if ( gl_label_is_selection_atomic (label) )
         {
-                clipboard = gtk_widget_get_clipboard (owner, GDK_SELECTION_CLIPBOARD);
-
                 object = GL_LABEL_OBJECT (selection_list->data);
 
-                gl_label_object_copy_to_clipboard (object, clipboard);
+                gl_label_object_copy_to_clipboard (object, std_clipboard);
         }
 
         g_list_free (selection_list);
@@ -2249,18 +2243,14 @@ gl_label_copy_selection (glLabel       *label,
 /*****************************************************************************/
 void
 gl_label_paste (glLabel       *label,
-                GtkWidget     *owner)
+                GtkClipboard  *glabels_clipboard,
+                GtkClipboard  *std_clipboard)
 {
-        GtkClipboard      *clipboard;
-
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
-	g_return_if_fail (owner && GTK_IS_WIDGET (owner));
-
-        clipboard = gtk_widget_get_clipboard (owner, GLABELS_CLIPBOARD);
 
-        gtk_clipboard_request_text (clipboard,
+        gtk_clipboard_request_text (glabels_clipboard,
                                     (GtkClipboardTextReceivedFunc)paste_received_cb,
                                     label);
 
diff --git a/src/label.h b/src/label.h
index 0eb73cd..35b86c4 100644
--- a/src/label.h
+++ b/src/label.h
@@ -253,13 +253,16 @@ void          gl_label_set_selection_line_width (glLabel        *label,
  * Clipboard operations
  */
 void          gl_label_cut_selection             (glLabel       *label,
-                                                  GtkWidget     *owner);
+                                                  GtkClipboard  *glabels_clipboard,
+                                                  GtkClipboard  *std_clipboard);
 
 void          gl_label_copy_selection            (glLabel       *label,
-                                                  GtkWidget     *owner);
+                                                  GtkClipboard  *glabels_clipboard,
+                                                  GtkClipboard  *std_clipboard);
 
 void          gl_label_paste                     (glLabel       *label,
-                                                  GtkWidget     *owner);
+                                                  GtkClipboard  *glabels_clipboard,
+                                                  GtkClipboard  *std_clipboard);
 
 
 /*
diff --git a/src/ui-commands.c b/src/ui-commands.c
index d87f9a5..28db965 100644
--- a/src/ui-commands.c
+++ b/src/ui-commands.c
@@ -25,6 +25,7 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
+#include "ui.h"
 #include "view.h"
 #include "file.h"
 #include "template-designer.h"
@@ -257,14 +258,21 @@ void
 gl_ui_cmd_edit_cut (GtkAction *action,
                     glWindow  *window)
 {
+        GtkClipboard  *glabels_clipboard;
+        GtkClipboard  *std_clipboard;
+
         gl_debug (DEBUG_COMMANDS, "START");
 
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        gl_label_cut_selection (GL_VIEW(window->view)->label,
-                                GTK_WIDGET (window));
+        glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                                      GL_UI_GLABELS_CLIPBOARD);
+
+        std_clipboard     = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                                      GDK_SELECTION_CLIPBOARD);
 
+        gl_label_cut_selection (window->label, glabels_clipboard, std_clipboard);
 
         gl_debug (DEBUG_COMMANDS, "END");
 }
@@ -277,15 +285,21 @@ void
 gl_ui_cmd_edit_copy (GtkAction *action,
                      glWindow  *window)
 {
-        GtkClipboard *clipboard;
+        GtkClipboard  *glabels_clipboard;
+        GtkClipboard  *std_clipboard;
 
         gl_debug (DEBUG_COMMANDS, "START");
 
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        gl_label_copy_selection (GL_VIEW(window->view)->label,
-                                 GTK_WIDGET (window));
+        glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                                      GL_UI_GLABELS_CLIPBOARD);
+
+        std_clipboard     = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                                      GDK_SELECTION_CLIPBOARD);
+
+        gl_label_copy_selection (window->label, glabels_clipboard, std_clipboard);
 
         gl_debug (DEBUG_COMMANDS, "END");
 }
@@ -298,15 +312,21 @@ void
 gl_ui_cmd_edit_paste (GtkAction *action,
                       glWindow  *window)
 {
-        GtkClipboard *clipboard;
+        GtkClipboard  *glabels_clipboard;
+        GtkClipboard  *std_clipboard;
 
         gl_debug (DEBUG_COMMANDS, "START");
 
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        gl_label_paste (GL_VIEW(window->view)->label,
-                        GTK_WIDGET (window));
+        glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                                      GL_UI_GLABELS_CLIPBOARD);
+
+        std_clipboard     = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                                      GDK_SELECTION_CLIPBOARD);
+
+        gl_label_paste (window->label, glabels_clipboard, std_clipboard);
 
         gl_debug (DEBUG_COMMANDS, "END");
 }
diff --git a/src/ui.c b/src/ui.c
index 34b1121..ae190dc 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -866,15 +866,25 @@ gl_ui_update_selection_verbs (GtkUIManager *ui,
 {
 	gl_debug (DEBUG_UI, "START");
 
-	gl_ui_util_set_verb_list_sensitive (ui, selection_verbs,
-					    !gl_label_is_selection_empty (view->label));
-
-	gl_ui_util_set_verb_list_sensitive (ui, atomic_selection_verbs,
-					    gl_label_is_selection_atomic (view->label));
-
-	gl_ui_util_set_verb_list_sensitive (ui, multi_selection_verbs,
-					    !gl_label_is_selection_empty (view->label)
-					    && !gl_label_is_selection_atomic (view->label));
+        if ( gtk_widget_has_focus (GTK_WIDGET (view->canvas)) )
+        {
+
+                gl_ui_util_set_verb_list_sensitive (ui, selection_verbs,
+                                                    !gl_label_is_selection_empty (view->label));
+
+                gl_ui_util_set_verb_list_sensitive (ui, atomic_selection_verbs,
+                                                    gl_label_is_selection_atomic (view->label));
+
+                gl_ui_util_set_verb_list_sensitive (ui, multi_selection_verbs,
+                                                    !gl_label_is_selection_empty (view->label)
+                                                    && !gl_label_is_selection_atomic (view->label));
+        }
+        else
+        {
+                gl_ui_util_set_verb_list_sensitive (ui, selection_verbs, FALSE);
+                gl_ui_util_set_verb_list_sensitive (ui, atomic_selection_verbs, FALSE);
+                gl_ui_util_set_verb_list_sensitive (ui, multi_selection_verbs, FALSE);
+        }
 
 	gl_debug (DEBUG_UI, "END");
 }
diff --git a/src/ui.h b/src/ui.h
index 158daaf..81f3667 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -28,6 +28,10 @@
 
 G_BEGIN_DECLS
 
+
+#define GL_UI_GLABELS_CLIPBOARD gdk_atom_intern ("GLABELS", FALSE)
+
+
 GtkUIManager *gl_ui_new                    (glWindow          *window);
 
 void          gl_ui_unref                  (GtkUIManager      *ui);
diff --git a/src/window.c b/src/window.c
index 4206dda..7a7f7a6 100644
--- a/src/window.c
+++ b/src/window.c
@@ -46,8 +46,6 @@
 #define CURSOR_INFO_WIDTH     150
 #define ZOOM_INFO_WIDTH        50
 
-#define GLABELS_CLIPBOARD gdk_atom_intern ("GLABELS", FALSE)
-
 
 /*===========================================================================*/
 /* Private globals                                                           */
@@ -100,6 +98,13 @@ static void     clipboard_changed_cb   (GtkClipboard  *clipboard,
                                         GdkEvent      *event,
 					glWindow      *window);
 
+static void     focus_widget_changed_cb(GtkWindow     *gtk_window,
+                                        GtkWidget     *widget,
+					glWindow      *window);
+
+static void     set_paste_sensitivity  (glWindow      *window,
+                                        GtkWidget     *focus_widget);
+
 
 /****************************************************************************/
 /* Boilerplate Object stuff.                                                */
@@ -226,7 +231,9 @@ gl_window_finalize (GObject *object)
 static void
 gl_window_destroy (GtkObject *gtk_object)
 {
-	glWindow *window;
+	glWindow          *window;
+        GtkClipboard      *glabels_clipboard;
+        GtkClipboard      *std_clipboard;
 
 	gl_debug (DEBUG_WINDOW, "START");
 
@@ -241,6 +248,18 @@ gl_window_destroy (GtkObject *gtk_object)
 		window->ui = NULL;
         }
 
+        if (window->label)
+        {
+                glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                                              GL_UI_GLABELS_CLIPBOARD);
+
+                g_signal_handlers_disconnect_by_func (G_OBJECT (glabels_clipboard),
+                                                      G_CALLBACK (clipboard_changed_cb),
+                                                      window);
+
+		g_object_unref (window->label);
+        }
+
 	if (GTK_OBJECT_CLASS (gl_window_parent_class)->destroy) {
 		GTK_OBJECT_CLASS (gl_window_parent_class)->destroy (gtk_object);
 	}
@@ -340,14 +359,15 @@ gl_window_set_label (glWindow    *window,
 		     glLabel     *label)
 {
 	gchar             *string;
-        GtkClipboard      *clipboard;
+        GtkClipboard      *glabels_clipboard;
+        GtkWidget         *focus_widget;
 
 	gl_debug (DEBUG_WINDOW, "START");
 
 	g_return_if_fail (GL_IS_WINDOW (window));
 	g_return_if_fail (GL_IS_LABEL (label));
 
-        window->label = label;
+        window->label = g_object_ref (label);
 
 	gl_label_clear_modified (label);
 
@@ -387,9 +407,9 @@ gl_window_set_label (glWindow    *window,
 	gtk_label_set_text (GTK_LABEL(window->zoom_info), string);
 	g_free (string);
 
-        clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GLABELS_CLIPBOARD);
-        gl_ui_update_paste_verbs (window->ui,
-                                  gtk_clipboard_wait_is_text_available (clipboard));
+
+        glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                                      GL_UI_GLABELS_CLIPBOARD);
 
 
 	g_signal_connect (G_OBJECT(window->label), "selection_changed",
@@ -413,9 +433,16 @@ gl_window_set_label (glWindow    *window,
 	g_signal_connect (G_OBJECT(label), "modified_changed",
 			  G_CALLBACK(modified_changed_cb), window);
 
-	g_signal_connect (G_OBJECT(clipboard), "owner_change",
+	g_signal_connect (G_OBJECT(glabels_clipboard), "owner_change",
 			  G_CALLBACK(clipboard_changed_cb), window);
 
+	g_signal_connect (G_OBJECT(window), "set_focus",
+			  G_CALLBACK(focus_widget_changed_cb), window);
+
+        /* Initialize "Paste" sensitivity. */
+        focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
+        set_paste_sensitivity (window, focus_widget);
+
 	gl_debug (DEBUG_WINDOW, "END");
 }
 
@@ -496,7 +523,7 @@ selection_changed_cb (glLabel  *label,
 	g_return_if_fail (label && GL_IS_LABEL (label));
 	g_return_if_fail (window && GL_IS_WINDOW (window));
 
-	gl_ui_update_selection_verbs (window->ui, GL_VIEW (window->view));
+        gl_ui_update_selection_verbs (window->ui, GL_VIEW (window->view));
 
 	gl_debug (DEBUG_WINDOW, "END");
 }
@@ -646,22 +673,81 @@ modified_changed_cb (glLabel  *label,
 }
 
 
+/*---------------------------------------------------------------------------*/
+/** PRIVATE.  Clipboard "owner change" callback.                             */
+/*---------------------------------------------------------------------------*/
 static void
 clipboard_changed_cb (GtkClipboard *clipboard,
                       GdkEvent     *event,
                       glWindow     *window)
 {
+        GtkWidget    *focus_widget;
+
+	gl_debug (DEBUG_WINDOW, "START");
+
+	g_return_if_fail (window && GL_IS_WINDOW (window));
+
+        focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
+        set_paste_sensitivity (window, focus_widget);
+
+	gl_debug (DEBUG_WINDOW, "END");
+}
+
+
+/*---------------------------------------------------------------------------*/
+/** PRIVATE.  Window "set-focus" callback.                                   */
+/*---------------------------------------------------------------------------*/
+static void
+focus_widget_changed_cb (GtkWindow *gtk_window,
+                         GtkWidget *widget,
+                         glWindow  *window)
+{
 	gl_debug (DEBUG_WINDOW, "START");
 
 	g_return_if_fail (window && GL_IS_WINDOW (window));
 
-        gl_ui_update_paste_verbs (window->ui,
-                                  gtk_clipboard_wait_is_text_available (clipboard));
+        if (widget)
+        {
+                gl_debug (DEBUG_WINDOW, "SET-FOCUS %x %s\n",
+                          widget,
+                          G_OBJECT_TYPE_NAME (widget));
+
+                set_paste_sensitivity (window, widget);
+        }
 
 	gl_debug (DEBUG_WINDOW, "END");
 }
 
 
+/*---------------------------------------------------------------------------*/
+/** PRIVATE.  Set paste sensitivity.                                         */
+/*---------------------------------------------------------------------------*/
+static void
+set_paste_sensitivity (glWindow  *window,
+                       GtkWidget *focus_widget)
+{
+        GtkClipboard *glabels_clipboard;
+
+	gl_debug (DEBUG_WINDOW, "START");
+
+	g_return_if_fail (window && GL_IS_WINDOW (window));
+
+        glabels_clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
+                                                      GL_UI_GLABELS_CLIPBOARD);
+
+        if ( focus_widget == GL_VIEW(window->view)->canvas )
+        {
+                gl_ui_update_paste_verbs (window->ui,
+                                          gtk_clipboard_wait_is_text_available (glabels_clipboard));
+        }
+        else
+        {
+                gl_ui_update_paste_verbs (window->ui, FALSE);
+        }
+
+	gl_debug (DEBUG_WINDOW, "END");
+}
+
 
 /*
  * Local Variables:       -- emacs



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]