Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP7:Update
mutter.23815
mutter-fix-wine-copy-and-paste.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File mutter-fix-wine-copy-and-paste.patch of Package mutter.23815
diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h index 36d4bad38..d53073e11 100644 --- a/src/x11/meta-x11-display-private.h +++ b/src/x11/meta-x11-display-private.h @@ -127,6 +127,7 @@ struct _MetaX11Display struct { Window xwindow; + guint timeout_id; MetaSelectionSource *owners[META_N_SELECTION_TYPES]; GCancellable *cancellables[META_N_SELECTION_TYPES]; diff --git a/src/x11/meta-x11-selection.c b/src/x11/meta-x11-selection.c index 8f068dedc..f9b3607a7 100644 --- a/src/x11/meta-x11-selection.c +++ b/src/x11/meta-x11-selection.c @@ -79,18 +79,49 @@ static GBytes * mimetypes_to_bytes (GList *mimetypes, Display *xdisplay) { - gint i = 0, len = g_list_length (mimetypes) + 2; - Atom *atoms = g_new0 (Atom, len); + GArray *atoms = g_array_new (FALSE, FALSE, sizeof (Atom)); GList *l; + char *mimetype; + Atom atom; + gboolean utf8_string_found = FALSE, utf8_string_mimetype_found = FALSE; + gboolean string_found = FALSE, string_mimetype_found = FALSE; + GBytes *bytes; for (l = mimetypes; l; l = l->next) - atoms[i++] = XInternAtom (xdisplay, l->data, False); + { + mimetype = l->data; + atom = XInternAtom (xdisplay, mimetype, False); + g_array_append_val (atoms, atom); + utf8_string_mimetype_found |= strcmp (mimetype, UTF8_STRING_MIMETYPE) == 0; + utf8_string_found |= strcmp (mimetype, "UTF8_STRING") == 0; + string_mimetype_found |= strcmp (mimetype, STRING_MIMETYPE) == 0; + string_found |= strcmp (mimetype, "STRING") == 0; + } + + /* Some X11 clients can only handle STRING/UTF8_STRING but not the + * corresponding mimetypes. */ + if (utf8_string_mimetype_found && !utf8_string_found) + { + atom = XInternAtom (xdisplay, "UTF8_STRING", False); + g_array_append_val (atoms, atom); + } - atoms[i++] = XInternAtom (xdisplay, "TARGETS", False); - atoms[i++] = XInternAtom (xdisplay, "TIMESTAMP", False); - g_assert (i == len); + if (string_mimetype_found && !string_found) + { + atom = XInternAtom (xdisplay, "STRING", False); + g_array_append_val (atoms, atom); + } + + atom = XInternAtom (xdisplay, "TARGETS", False); + g_array_append_val (atoms, atom); - return g_bytes_new_take (atoms, len * sizeof (Atom)); + atom = XInternAtom (xdisplay, "TIMESTAMP", False); + g_array_append_val (atoms, atom); + + bytes = g_bytes_new_take (atoms->data, atoms->len * sizeof (Atom)); + g_array_free (atoms, FALSE); + + return bytes; } static void @@ -311,6 +342,22 @@ source_new_cb (GObject *object, g_free (data); } +static gboolean +unset_clipboard_owner (gpointer data) +{ + MetaDisplay *display = meta_get_display (); + MetaSelection *selection = meta_display_get_selection (display); + MetaX11Display *x11_display = meta_display_get_x11_display (display); + + meta_selection_unset_owner (selection, META_SELECTION_CLIPBOARD, + x11_display->selection.owners[META_SELECTION_CLIPBOARD]); + g_clear_object (&x11_display->selection.owners[META_SELECTION_CLIPBOARD]); + + x11_display->selection.timeout_id = 0; + + return G_SOURCE_REMOVE; +} + static gboolean meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display, XEvent *xevent) @@ -325,6 +372,9 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display, selection = meta_display_get_selection (meta_get_display ()); + if (selection_type == META_SELECTION_CLIPBOARD) + g_clear_handle_id (&x11_display->selection.timeout_id, g_source_remove); + if (x11_display->selection.cancellables[selection_type]) { g_cancellable_cancel (x11_display->selection.cancellables[selection_type]); @@ -345,6 +395,19 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display, meta_selection_set_owner (selection, selection_type, source); g_object_unref (source); } + else if (event->subtype == XFixesSelectionWindowDestroyNotify && + selection_type == META_SELECTION_CLIPBOARD) + { + /* Selection window might have gotten destroyed as part of application + * shutdown. Trigger restoring clipboard, but wait a bit, because some + * clients, like wine, destroy the old window immediately before a new + * selection. Restoring the clipboard in this case would overwrite the + * new selection, so this will be cancelled when a new selection + * arrives. */ + x11_display->selection.timeout_id = g_timeout_add (10, + unset_clipboard_owner, + NULL); + } else { /* An X client went away, clear the selection */ @@ -422,6 +485,7 @@ meta_x11_selection_init (MetaX11Display *x11_display) attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask; attributes.override_redirect = True; + x11_display->selection.timeout_id = 0; x11_display->selection.xwindow = XCreateWindow (x11_display->xdisplay, x11_display->xroot, @@ -482,4 +546,6 @@ meta_x11_selection_shutdown (MetaX11Display *x11_display) XDestroyWindow (x11_display->xdisplay, x11_display->selection.xwindow); x11_display->selection.xwindow = None; } + + g_clear_handle_id (&x11_display->selection.timeout_id, g_source_remove); }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor