Re: Clipboard improvements



I forgot to attach the patch...

Matthias




Index: docs/reference/gdk/tmpl/events.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gdk/tmpl/events.sgml,v
retrieving revision 1.19
diff -u -r1.19 events.sgml
--- docs/reference/gdk/tmpl/events.sgml	27 Aug 2003 22:59:47 -0000	1.19
+++ docs/reference/gdk/tmpl/events.sgml	6 May 2004 15:20:15 -0000
@@ -84,6 +84,7 @@
 @GDK_SCROLL: 
 @GDK_WINDOW_STATE: 
 @GDK_SETTING: 
+ GDK_OWNER_CHANGE: 
 
 <!-- ##### ENUM GdkEventMask ##### -->
 <para>
Index: gdk/gdkdisplay.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkdisplay.h,v
retrieving revision 1.17
diff -u -r1.17 gdkdisplay.h
--- gdk/gdkdisplay.h	16 Dec 2003 00:56:46 -0000	1.17
+++ gdk/gdkdisplay.h	6 May 2004 15:20:15 -0000
@@ -164,6 +164,8 @@
 
 GdkWindow *gdk_display_get_default_group       (GdkDisplay *display); 
 
+gboolean gdk_display_supports_selection_notification (GdkDisplay *display);
+
 G_END_DECLS
 
-#endif				/* __GDK_DISPLAY_H__ */
+#endif	/* __GDK_DISPLAY_H__ */
Index: gdk/gdkevents.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkevents.h,v
retrieving revision 1.21
diff -u -r1.21 gdkevents.h
--- gdk/gdkevents.h	10 Aug 2003 23:37:29 -0000	1.21
+++ gdk/gdkevents.h	6 May 2004 15:20:15 -0000
@@ -29,6 +29,7 @@
 typedef struct _GdkEventConfigure   GdkEventConfigure;
 typedef struct _GdkEventProperty    GdkEventProperty;
 typedef struct _GdkEventSelection   GdkEventSelection;
+typedef struct _GdkEventOwnerChange GdkEventOwnerChange;
 typedef struct _GdkEventProximity   GdkEventProximity;
 typedef struct _GdkEventClient	    GdkEventClient;
 typedef struct _GdkEventDND         GdkEventDND;
@@ -118,7 +119,8 @@
   GDK_NO_EXPOSE		= 30,
   GDK_SCROLL            = 31,
   GDK_WINDOW_STATE      = 32,
-  GDK_SETTING           = 33
+  GDK_SETTING           = 33,
+  GDK_OWNER_CHANGE      = 34
 } GdkEventType;
 
 /* Event masks. (Used to select what types of events a window
@@ -219,6 +221,13 @@
   GDK_SETTING_ACTION_DELETED
 } GdkSettingAction;
 
+typedef enum
+{
+  GDK_OWNER_CHANGE_NEW_OWNER,
+  GDK_OWNER_CHANGE_DESTROY,
+  GDK_OWNER_CHANGE_CLOSE
+} GdkOwnerChange;
+
 struct _GdkEventAny
 {
   GdkEventType type;
@@ -366,6 +375,18 @@
   GdkNativeWindow requestor;
 };
 
+struct _GdkEventOwnerChange
+{
+  GdkEventType type;
+  GdkWindow *window;
+  gint8 send_event;
+  GdkNativeWindow owner;
+  GdkOwnerChange reason;
+  GdkAtom selection;
+  guint32 time;
+  guint32 selection_time;
+};
+
 /* This event type will be used pretty rarely. It only is important
    for XInput aware programs that are drawing their own cursor */
 
@@ -438,6 +459,7 @@
   GdkEventConfigure	    configure;
   GdkEventProperty	    property;
   GdkEventSelection	    selection;
+  GdkEventOwnerChange  	    owner_change;
   GdkEventProximity	    proximity;
   GdkEventClient	    client;
   GdkEventDND               dnd;
Index: gdk/x11/gdkdisplay-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdisplay-x11.c,v
retrieving revision 1.41
diff -u -r1.41 gdkdisplay-x11.c
--- gdk/x11/gdkdisplay-x11.c	18 Apr 2004 14:33:07 -0000	1.41
+++ gdk/x11/gdkdisplay-x11.c	6 May 2004 15:20:16 -0000
@@ -43,6 +43,10 @@
 #include <X11/XKBlib.h>
 #endif
 
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+
 static void                 gdk_display_x11_class_init         (GdkDisplayX11Class *class);
 static void                 gdk_display_x11_dispose            (GObject            *object);
 static void                 gdk_display_x11_finalize           (GObject            *object);
@@ -147,6 +151,7 @@
   XClassHint *class_hint;
   gulong pid;
   gint i;
+  gint ignore;
 
   xdisplay = XOpenDisplay (display_name);
   if (!xdisplay)
@@ -193,6 +198,21 @@
 
   display_x11->have_render = GDK_UNKNOWN;
 
+#ifdef HAVE_XFIXES
+  if (XFixesQueryExtension (display_x11->xdisplay, 
+			    &display_x11->xfixes_event_base, 
+			    &ignore))
+    {
+      display_x11->have_xfixes = TRUE;
+
+      gdk_x11_register_standard_event_type (display,
+					    display_x11->xfixes_event_base, 
+					    XFixesNumberEvents);
+    }
+  else
+#endif
+  display_x11->have_xfixes = FALSE;
+
   if (_gdk_synchronize)
     XSynchronize (display_x11->xdisplay, True);
   
@@ -968,4 +988,25 @@
                       message);
 
   g_free (message);
+}
+
+
+/**
+ * gdk_display_supports_selection_notification:
+ * @display: a #GdkDisplay
+ * 
+ * Returns whether #GdkEventOwnerChange events will be 
+ * sent when the owner of a selection changes.
+ * 
+ * Return value: whether #GdkEventOwnerChange events will 
+ *               be sent.
+ *
+ * Since: 2.6
+ **/
+gboolean 
+gdk_display_supports_selection_notification (GdkDisplay *display)
+{
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+
+  return display_x11->have_xfixes;
 }
Index: gdk/x11/gdkdisplay-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdisplay-x11.h,v
retrieving revision 1.16
diff -u -r1.16 gdkdisplay-x11.h
--- gdk/x11/gdkdisplay-x11.h	18 Apr 2004 14:33:07 -0000	1.16
+++ gdk/x11/gdkdisplay-x11.h	6 May 2004 15:20:16 -0000
@@ -78,7 +78,9 @@
   gboolean use_xshm;
   gboolean have_shm_pixmaps;
   GdkTristate have_render;
-  
+  gboolean have_xfixes;
+  gint xfixes_event_base;
+
   /* Information about current pointer and keyboard grabs held by this
    * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window
    * window is NULL, then the other associated fields are ignored
Index: gdk/x11/gdkevents-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkevents-x11.c,v
retrieving revision 1.131
diff -u -r1.131 gdkevents-x11.c
--- gdk/x11/gdkevents-x11.c	6 May 2004 02:57:01 -0000	1.131
+++ gdk/x11/gdkevents-x11.c	6 May 2004 15:20:17 -0000
@@ -46,6 +46,10 @@
 #include <X11/XKBlib.h>
 #endif
 
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+
 #include <X11/Xatom.h>
 
 typedef struct _GdkIOClosure GdkIOClosure;
@@ -1952,6 +1956,24 @@
 	      _gdk_keymap_state_changed (display);
 	      break;
 	    }
+	}
+      else
+#endif
+#ifdef HAVE_XFIXES
+      if (xevent->type - display_x11->xfixes_event_base == XFixesSelectionNotify)
+	{
+	  XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)xevent;
+	  event->owner_change.type = GDK_OWNER_CHANGE;
+	  event->owner_change.window = window;
+	  event->owner_change.owner = selection_notify->owner;
+	  event->owner_change.reason = selection_notify->subtype;
+	  event->owner_change.selection = 
+	    gdk_x11_xatom_to_atom_for_display (display, 
+					       selection_notify->selection);
+	  event->owner_change.time = selection_notify->timestamp;
+	  event->owner_change.selection_time = selection_notify->selection_timestamp;
+
+	  return_val = TRUE;
 	}
       else
 #endif
Index: gtk/gtkclipboard.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkclipboard.c,v
retrieving revision 1.26
diff -u -r1.26 gtkclipboard.c
--- gtk/gtkclipboard.c	23 Apr 2004 20:01:53 -0000	1.26
+++ gtk/gtkclipboard.c	6 May 2004 15:20:17 -0000
@@ -25,6 +25,7 @@
 #include "gtkclipboard.h"
 #include "gtkinvisible.h"
 #include "gtkmain.h"
+#include "gtkmarshalers.h"
 
 #ifdef GDK_WINDOWING_X11
 #include "x11/gdkx.h"
@@ -34,6 +35,11 @@
 #include "win32/gdkwin32.h"
 #endif
 
+enum {
+  OWNER_CHANGE,
+  LAST_SIGNAL
+};
+
 typedef struct _GtkClipboardClass GtkClipboardClass;
 
 typedef struct _RequestContentsInfo RequestContentsInfo;
@@ -60,6 +66,9 @@
 struct _GtkClipboardClass
 {
   GObjectClass parent_class;
+
+  gboolean (*owner_change) (GtkClipboard        *clipboard,
+			    GdkEventOwnerChange *event);
 };
 
 struct _RequestContentsInfo
@@ -83,11 +92,13 @@
 static void gtk_clipboard_class_init (GtkClipboardClass *class);
 static void gtk_clipboard_finalize   (GObject           *object);
 
-static void clipboard_unset    (GtkClipboard     *clipboard);
-static void selection_received (GtkWidget        *widget,
-				GtkSelectionData *selection_data,
-				guint             time);
-
+static void clipboard_unset          (GtkClipboard      *clipboard);
+static void selection_received       (GtkWidget         *widget,
+				      GtkSelectionData  *selection_data,
+				      guint              time);
+static GtkClipboard *clipboard_peek  (GdkDisplay        *display,
+				      GdkAtom            selection,
+				      gboolean           only_if_exists);
 enum {
   TARGET_STRING,
   TARGET_TEXT,
@@ -102,6 +113,7 @@
 static GQuark clipboards_owned_key_id = 0;
 
 static GObjectClass *parent_class;
+static guint         clipboard_signals[LAST_SIGNAL] = { 0 };
 
 GType
 gtk_clipboard_get_type (void)
@@ -138,10 +150,22 @@
   parent_class = g_type_class_peek_parent (class);
   
   gobject_class->finalize = gtk_clipboard_finalize;
+
+  class->owner_change = NULL;
+
+  clipboard_signals[OWNER_CHANGE] =
+    g_signal_new ("owner_change",
+		  G_TYPE_FROM_CLASS (gobject_class),
+		  G_SIGNAL_RUN_FIRST,
+		  G_STRUCT_OFFSET (GtkClipboardClass, owner_change),
+		  _gtk_boolean_handled_accumulator, NULL,
+		  _gtk_marshal_BOOLEAN__BOXED,
+		  G_TYPE_BOOLEAN, 1,
+		  GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 }
 
 static void
-gtk_clipboard_finalize   (GObject *object)
+gtk_clipboard_finalize (GObject *object)
 {
   clipboard_unset (GTK_CLIPBOARD (object));
 
@@ -204,44 +228,16 @@
  * Since: 2.2
  **/
 GtkClipboard *
-gtk_clipboard_get_for_display (GdkDisplay *display, GdkAtom selection)
+gtk_clipboard_get_for_display (GdkDisplay *display, 
+			       GdkAtom     selection)
 {
-  GtkClipboard *clipboard = NULL;
-  GSList *clipboards;
-  GSList *tmp_list;
-
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
   g_return_val_if_fail (!display->closed, NULL);
 
-  if (selection == GDK_NONE)
-    selection = GDK_SELECTION_CLIPBOARD;
-
-  clipboards = g_object_get_data (G_OBJECT (display), "gtk-clipboard-list");
-
-  tmp_list = clipboards;
-  while (tmp_list)
-    {
-      clipboard = tmp_list->data;
-      if (clipboard->selection == selection)
-	break;
-
-      tmp_list = tmp_list->next;
-    }
-
-  if (!tmp_list)
-    {
-      clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL);
-      clipboard->selection = selection;
-      clipboard->display = display;
-      clipboards = g_slist_prepend (clipboards, clipboard);
-      g_object_set_data (G_OBJECT (display), "gtk-clipboard-list", clipboards);
-      g_signal_connect (display, "closed",
-			G_CALLBACK (clipboard_display_closed), clipboard);
-    }
-  
-  return clipboard;
+  return clipboard_peek (display, selection, FALSE);
 }
 
+
 /**
  * gtk_clipboard_get():
  * @selection: a #GdkAtom which identifies the clipboard
@@ -1107,4 +1103,69 @@
     }
 
   return result;
+}
+
+static GtkClipboard *
+clipboard_peek (GdkDisplay *display, 
+		GdkAtom     selection,
+		gboolean    only_if_exists)
+{
+  GtkClipboard *clipboard = NULL;
+  GSList *clipboards;
+  GSList *tmp_list;
+
+  if (selection == GDK_NONE)
+    selection = GDK_SELECTION_CLIPBOARD;
+
+  clipboards = g_object_get_data (G_OBJECT (display), "gtk-clipboard-list");
+
+  tmp_list = clipboards;
+  while (tmp_list)
+    {
+      clipboard = tmp_list->data;
+      if (clipboard->selection == selection)
+	break;
+
+      tmp_list = tmp_list->next;
+    }
+
+  if (!tmp_list && !only_if_exists)
+    {
+      clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL);
+      clipboard->selection = selection;
+      clipboard->display = display;
+      clipboards = g_slist_prepend (clipboards, clipboard);
+      g_object_set_data (G_OBJECT (display), "gtk-clipboard-list", clipboards);
+      g_signal_connect (display, "closed",
+			G_CALLBACK (clipboard_display_closed), clipboard);
+    }
+  
+  return clipboard;
+}
+
+
+/**
+ * _gtk_clipboard_handle_event:
+ * @event: a owner change event
+ * 
+ * Emits the ::owner_change signal on the appropriate @clipboard.
+ *
+ * Since: 2.6
+ **/
+void 
+_gtk_clipboard_handle_event (GdkEventOwnerChange *event)
+{
+  GdkDisplay *display;
+  GtkClipboard *clipboard;
+  
+  display = gdk_drawable_get_display (event->window);
+  clipboard = clipboard_peek (display, event->selection, TRUE);
+      
+  if (clipboard)
+    {
+      gboolean return_val = FALSE;
+
+      g_signal_emit (clipboard, 
+		     clipboard_signals[OWNER_CHANGE], 0, event, &return_val);
+    }
 }
Index: gtk/gtkclipboard.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkclipboard.h,v
retrieving revision 1.7
diff -u -r1.7 gtkclipboard.h
--- gtk/gtkclipboard.h	24 Dec 2003 00:14:13 -0000	1.7
+++ gtk/gtkclipboard.h	6 May 2004 15:20:17 -0000
@@ -104,6 +104,9 @@
 					 GdkAtom      **targets,
 					 gint          *n_targets);
 
+/* private */
+void     _gtk_clipboard_handle_event    (GdkEventOwnerChange *event);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
Index: gtk/gtkmain.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmain.c,v
retrieving revision 1.234
diff -u -r1.234 gtkmain.c
--- gtk/gtkmain.c	6 Mar 2004 03:37:59 -0000	1.234
+++ gtk/gtkmain.c	6 May 2004 15:20:17 -0000
@@ -1438,6 +1438,12 @@
       return;
     }
 
+  if (event->type == GDK_OWNER_CHANGE)
+    {
+      _gtk_clipboard_handle_event (&event->owner_change);
+      return;
+    }
+
   /* Find the widget which got the event. We store the widget
    *  in the user_data field of GdkWindow's.
    *  Ignore the event if we don't have a widget for it, except


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