x11: Various clipboard cleanups

(1) Turn X11 clipboard event handling into a regular filter function
(2) Maintain a timestamp in the clipboard, so we can pass it when
    querying selections.
This commit is contained in:
Benjamin Otte 2017-11-19 19:52:07 +01:00
parent a5ab9a9671
commit fe9045d82e
5 changed files with 86 additions and 76 deletions

View File

@ -41,7 +41,7 @@ struct _GdkX11Clipboard
char *selection;
Atom xselection;
guint32 time;
guint32 timestamp;
};
struct _GdkX11ClipboardClass
@ -51,30 +51,6 @@ struct _GdkX11ClipboardClass
G_DEFINE_TYPE (GdkX11Clipboard, gdk_x11_clipboard, GDK_TYPE_CLIPBOARD)
static void
gdk_x11_clipboard_finalize (GObject *object)
{
GdkX11Clipboard *cb = GDK_X11_CLIPBOARD (object);
g_free (cb->selection);
G_OBJECT_CLASS (gdk_x11_clipboard_parent_class)->finalize (object);
}
static void
gdk_x11_clipboard_class_init (GdkX11ClipboardClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
//GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (class);
object_class->finalize = gdk_x11_clipboard_finalize;
}
static void
gdk_x11_clipboard_init (GdkX11Clipboard *clipboard)
{
}
#define SELECTION_MAX_SIZE(display) \
MIN(262144, \
XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
@ -141,7 +117,8 @@ gdk_x11_clipboard_request_targets (GdkX11Clipboard *cb)
stream = gdk_x11_selection_input_stream_new (gdk_clipboard_get_display (GDK_CLIPBOARD (cb)),
cb->selection,
"TARGETS");
"TARGETS",
cb->timestamp);
g_input_stream_read_bytes_async (stream,
SELECTION_MAX_SIZE (display),
@ -151,6 +128,73 @@ gdk_x11_clipboard_request_targets (GdkX11Clipboard *cb)
g_object_ref (cb));
}
static GdkFilterReturn
gdk_x11_clipboard_filter_event (GdkXEvent *xev,
GdkEvent *gdkevent,
gpointer data)
{
GdkX11Clipboard *cb = GDK_X11_CLIPBOARD (data);
GdkDisplay *display;
XEvent *xevent = xev;
Window xwindow;
display = gdk_clipboard_get_display (GDK_CLIPBOARD (cb));
xwindow = GDK_X11_DISPLAY (display)->leader_window;
if (xevent->xany.window != xwindow)
return GDK_FILTER_CONTINUE;
switch (xevent->type)
{
default:
#ifdef HAVE_XFIXES
if (xevent->type - GDK_X11_DISPLAY (display)->xfixes_event_base == XFixesSelectionNotify)
{
XFixesSelectionNotifyEvent *sn = (XFixesSelectionNotifyEvent *) xevent;
if (sn->selection == cb->xselection)
{
GdkContentFormats *empty;
GDK_NOTE(CLIPBOARD, g_printerr ("%s: got FixesSelectionNotify\n", cb->selection));
empty = gdk_content_formats_new (NULL, 0);
gdk_clipboard_claim_remote (GDK_CLIPBOARD (cb), empty);
gdk_content_formats_unref (empty);
cb->timestamp = sn->selection_timestamp;
gdk_x11_clipboard_request_targets (cb);
}
}
#endif
return GDK_FILTER_CONTINUE;
}
}
static void
gdk_x11_clipboard_finalize (GObject *object)
{
GdkX11Clipboard *cb = GDK_X11_CLIPBOARD (object);
gdk_window_remove_filter (NULL, gdk_x11_clipboard_filter_event, cb);
g_free (cb->selection);
G_OBJECT_CLASS (gdk_x11_clipboard_parent_class)->finalize (object);
}
static void
gdk_x11_clipboard_class_init (GdkX11ClipboardClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
//GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (class);
object_class->finalize = gdk_x11_clipboard_finalize;
}
static void
gdk_x11_clipboard_init (GdkX11Clipboard *cb)
{
cb->timestamp = CurrentTime;
}
GdkClipboard *
gdk_x11_clipboard_new (GdkDisplay *display,
const gchar *selection)
@ -165,33 +209,9 @@ gdk_x11_clipboard_new (GdkDisplay *display,
cb->xselection = gdk_x11_get_xatom_by_name_for_display (display, selection);
gdk_display_request_selection_notification (display, gdk_atom_intern (selection, FALSE));
gdk_window_add_filter (NULL, gdk_x11_clipboard_filter_event, cb);
gdk_x11_clipboard_request_targets (cb);
return GDK_CLIPBOARD (cb);
}
gboolean
gdk_x11_clipboard_handle_event (GdkX11Clipboard *cb,
XEvent *xevent)
{
return FALSE;
}
gboolean
gdk_x11_clipboard_handle_selection_notify (GdkX11Clipboard *cb,
XEvent *xevent)
{
#ifdef HAVE_XFIXES
GdkDisplay *display = gdk_clipboard_get_display (GDK_CLIPBOARD (cb));
XFixesSelectionNotifyEvent *event = (XFixesSelectionNotifyEvent *)xevent;
if (event->window != GDK_X11_DISPLAY (display)->leader_window ||
event->selection != cb->xselection)
return FALSE;
return TRUE;
#else
return FALSE;
#endif
}

View File

@ -36,10 +36,6 @@ GType gdk_x11_clipboard_get_type (void) G_GNUC_CO
GdkClipboard * gdk_x11_clipboard_new (GdkDisplay *display,
const gchar *selection);
gboolean gdk_x11_clipboard_handle_event (GdkX11Clipboard *clipboard,
XEvent *xevent);
gboolean gdk_x11_clipboard_handle_selection_notify(GdkX11Clipboard *clipboard,
XEvent *xevent);
G_END_DECLS

View File

@ -1142,24 +1142,16 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
gdk_display_set_composited (display, composited);
}
if (gdk_x11_clipboard_handle_selection_notify (GDK_X11_CLIPBOARD (display->clipboard), xevent) ||
gdk_x11_clipboard_handle_selection_notify (GDK_X11_CLIPBOARD (display->primary_clipboard), xevent))
{
return_val = FALSE;
}
else
{
event->owner_change.type = GDK_OWNER_CHANGE;
event->owner_change.window = window;
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;
event->owner_change.type = GDK_OWNER_CHANGE;
event->owner_change.window = window;
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;
}
return_val = TRUE;
}
else
#endif

View File

@ -134,7 +134,7 @@ gdk_x11_selection_input_stream_complete (GdkX11SelectionInputStream *stream)
gdk_x11_selection_input_stream_flush (stream);
GDK_X11_DISPLAY (priv->display)->input_streams = g_slist_remove (GDK_X11_DISPLAY (priv->display)->input_streams, stream);
gdk_window_remove_filter (GDK_X11_DISPLAY (priv->display)->leader_gdk_window, gdk_x11_selection_input_stream_filter_event, stream);
gdk_window_remove_filter (NULL, gdk_x11_selection_input_stream_filter_event, stream);
g_object_unref (stream);
}
@ -412,7 +412,8 @@ gdk_x11_selection_input_stream_filter_event (GdkXEvent *xev,
GInputStream *
gdk_x11_selection_input_stream_new (GdkDisplay *display,
const char *selection,
const char *target)
const char *target,
guint32 timestamp)
{
GdkX11SelectionInputStream *stream;
GdkX11SelectionInputStreamPrivate *priv;
@ -436,7 +437,7 @@ gdk_x11_selection_input_stream_new (GdkDisplay *display,
priv->xtarget,
priv->xproperty,
GDK_X11_DISPLAY (display)->leader_window,
CurrentTime);
timestamp);
return g_object_ref (stream);
}

View File

@ -52,7 +52,8 @@ GType gdk_x11_selection_input_stream_get_type (void) G_GNUC_CONST;
GInputStream * gdk_x11_selection_input_stream_new (GdkDisplay *display,
const char *selection,
const char *target);
const char *target,
guint32 timestamp);
G_END_DECLS