static void insert_atom_pair (GdkDisplay *display, GdkAtom virtual_atom, Atom xatom) { GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); if (!display_x11->atom_from_virtual) { display_x11->atom_from_virtual = g_hash_table_new (g_direct_hash, NULL); display_x11->atom_to_virtual = g_hash_table_new (g_direct_hash, NULL); } g_hash_table_insert (display_x11->atom_from_virtual, GDK_ATOM_TO_POINTER (virtual_atom), GUINT_TO_POINTER (xatom)); g_hash_table_insert (display_x11->atom_to_virtual, GUINT_TO_POINTER (xatom), GDK_ATOM_TO_POINTER (virtual_atom)); }
static Atom lookup_cached_xatom (GdkDisplay *display, GdkAtom atom) { GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); if (ATOM_TO_INDEX (atom) < G_N_ELEMENTS (xatoms_offset) - N_CUSTOM_PREDEFINED) return ATOM_TO_INDEX (atom); if (display_x11->atom_from_virtual) return GPOINTER_TO_UINT (g_hash_table_lookup (display_x11->atom_from_virtual, GDK_ATOM_TO_POINTER (atom))); return None; }
static GdkAtom intern_atom (const gchar *atom_name, gboolean dup) { GdkAtom result; virtual_atom_check_init (); result = GDK_POINTER_TO_ATOM (g_hash_table_lookup (virtual_atom_hash, atom_name)); if (!result) { result = INDEX_TO_ATOM (virtual_atom_array->len); g_ptr_array_add (virtual_atom_array, dup ? g_strdup (atom_name) : (gchar *)atom_name); g_hash_table_insert (virtual_atom_hash, g_ptr_array_index (virtual_atom_array, ATOM_TO_INDEX (result)), GDK_ATOM_TO_POINTER (result)); } return result; }
void _gdk_wayland_display_convert_selection (GdkDisplay *display, GdkWindow *requestor, GdkAtom selection, GdkAtom target, guint32 time) { GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display); SelectionBuffer *buffer_data; if (!wayland_selection->offer) { GdkEvent *event; event = gdk_event_new (GDK_SELECTION_NOTIFY); event->selection.window = g_object_ref (requestor); event->selection.send_event = FALSE; event->selection.selection = selection; event->selection.target = target; event->selection.property = GDK_NONE; event->selection.time = GDK_CURRENT_TIME; event->selection.requestor = g_object_ref (requestor); gdk_event_put (event); gdk_event_free (event); return; } wl_data_offer_accept (wayland_selection->offer, _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)), gdk_atom_name (target)); buffer_data = g_hash_table_lookup (wayland_selection->selection_buffers, target); if (buffer_data) selection_buffer_add_requestor (buffer_data, requestor); else { GInputStream *stream = NULL; int pipe_fd[2], natoms = 0; GdkAtom *atoms = NULL; if (target == gdk_atom_intern_static_string ("TARGETS")) { gint i = 0; GList *l; natoms = g_list_length (wayland_selection->targets); atoms = g_new0 (GdkAtom, natoms); for (l = wayland_selection->targets; l; l = l->next) atoms[i++] = l->data; } else { g_unix_open_pipe (pipe_fd, FD_CLOEXEC, NULL); wl_data_offer_receive (wayland_selection->offer, gdk_atom_name (target), pipe_fd[1]); stream = g_unix_input_stream_new (pipe_fd[0], TRUE); close (pipe_fd[1]); } buffer_data = selection_buffer_new (stream, selection, target); selection_buffer_add_requestor (buffer_data, requestor); if (stream) g_object_unref (stream); if (atoms) { /* Store directly the local atoms */ selection_buffer_append_data (buffer_data, atoms, natoms * sizeof (GdkAtom)); g_free (atoms); } g_hash_table_insert (wayland_selection->selection_buffers, GDK_ATOM_TO_POINTER (target), buffer_data); } if (!buffer_data->stream) selection_buffer_notify (buffer_data); }
void _gdk_wayland_display_convert_selection (GdkDisplay *display, GdkWindow *requestor, GdkAtom selection, GdkAtom target, guint32 time) { GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display); const SelectionData *selection_data; SelectionBuffer *buffer_data; gpointer offer; gchar *mimetype; GList *target_list; selection_data = selection_lookup_offer_by_atom (wayland_selection, selection); if (!selection_data) return; offer = gdk_wayland_selection_get_offer (display, selection); target_list = gdk_wayland_selection_get_targets (display, selection); if (!offer || target == gdk_atom_intern_static_string ("DELETE")) { emit_empty_selection_notify (requestor, selection, target); return; } mimetype = gdk_atom_name (target); if (target != gdk_atom_intern_static_string ("TARGETS")) { if (!g_list_find (target_list, GDK_ATOM_TO_POINTER (target))) { emit_empty_selection_notify (requestor, selection, target); return; } if (selection != atoms[ATOM_PRIMARY]) wl_data_offer_accept (offer, _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)), mimetype); } buffer_data = g_hash_table_lookup (selection_data->buffers, target); if (buffer_data) selection_buffer_add_requestor (buffer_data, requestor); else { GInputStream *stream = NULL; int pipe_fd[2], natoms = 0; GdkAtom *targets = NULL; if (target == gdk_atom_intern_static_string ("TARGETS")) { gint i = 0; GList *l; natoms = g_list_length (target_list); targets = g_new0 (GdkAtom, natoms); for (l = target_list; l; l = l->next) targets[i++] = l->data; } else { g_unix_open_pipe (pipe_fd, FD_CLOEXEC, NULL); if (selection == atoms[ATOM_PRIMARY]) gtk_primary_selection_offer_receive (offer, mimetype, pipe_fd[1]); else wl_data_offer_receive (offer, mimetype, pipe_fd[1]); stream = g_unix_input_stream_new (pipe_fd[0], TRUE); close (pipe_fd[1]); } buffer_data = selection_buffer_new (stream, selection, target); selection_buffer_add_requestor (buffer_data, requestor); if (stream) g_object_unref (stream); if (targets) { /* Store directly the local atoms */ selection_buffer_append_data (buffer_data, targets, natoms * sizeof (GdkAtom)); g_free (targets); } g_hash_table_insert (selection_data->buffers, GDK_ATOM_TO_POINTER (target), buffer_data); } if (!buffer_data->stream) selection_buffer_notify (buffer_data); g_free (mimetype); }