summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
Diffstat (limited to 'gdk')
-rw-r--r--gdk/x11/gdkclipboard-x11.c233
-rw-r--r--gdk/x11/gdkselectioninputstream-x11.c28
-rw-r--r--gdk/x11/gdkselectioninputstream-x11.h2
-rw-r--r--gdk/x11/gdktextlistconverter-x11.c169
-rw-r--r--gdk/x11/gdktextlistconverter-x11.h44
-rw-r--r--gdk/x11/meson.build1
6 files changed, 444 insertions, 33 deletions
diff --git a/gdk/x11/gdkclipboard-x11.c b/gdk/x11/gdkclipboard-x11.c
index a88c86d1ce..aef23b7ee3 100644
--- a/gdk/x11/gdkclipboard-x11.c
+++ b/gdk/x11/gdkclipboard-x11.c
@@ -19,8 +19,11 @@
#include "gdkclipboardprivate.h"
#include "gdkclipboard-x11.h"
-#include "gdkselectioninputstream-x11.h"
+
+#include "gdkintl.h"
#include "gdkprivate-x11.h"
+#include "gdkselectioninputstream-x11.h"
+#include "gdktextlistconverter-x11.h"
#include <string.h>
#include <X11/Xatom.h>
@@ -57,6 +60,121 @@ G_DEFINE_TYPE (GdkX11Clipboard, gdk_x11_clipboard, GDK_TYPE_CLIPBOARD)
? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
: XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
+static GInputStream *
+text_list_convert (GdkX11Clipboard *cb,
+ GInputStream *stream,
+ const char *encoding,
+ int format)
+{
+ GInputStream *converter_stream;
+ GConverter *converter;
+
+ converter = gdk_x11_text_list_converter_to_utf8_new (gdk_clipboard_get_display (GDK_CLIPBOARD (cb)),
+ encoding,
+ format);
+ converter_stream = g_converter_input_stream_new (stream, converter);
+
+ g_object_unref (converter);
+ g_object_unref (stream);
+
+ return converter_stream;
+}
+
+static GInputStream *
+no_convert (GdkX11Clipboard *cb,
+ GInputStream *stream,
+ const char *encoding,
+ int format)
+{
+ return stream;
+}
+
+static const struct {
+ const char *x_target;
+ const char *mime_type;
+ GInputStream * (* convert) (GdkX11Clipboard *, GInputStream *, const char *, int);
+} special_targets[] = {
+ { "UTF8_STRING", "text/plain;charset=utf-8", no_convert },
+ { "COMPOUND_TEXT", "text/plain;charset=utf-8", text_list_convert },
+ { "TEXT", "text/plain;charset=utf-8", text_list_convert },
+ { "STRING", "text/plain;charset=utf-8", text_list_convert }
+};
+
+static void
+print_atoms (GdkX11Clipboard *cb,
+ const char *prefix,
+ const Atom *atoms,
+ gsize n_atoms)
+{
+ GDK_NOTE(CLIPBOARD,
+ GdkDisplay *display = gdk_clipboard_get_display (GDK_CLIPBOARD (cb));
+ gsize i;
+
+ g_printerr ("%s: %s [ ", cb->selection, prefix);
+ for (i = 0; i < n_atoms; i++)
+ {
+ g_printerr ("%s%s", i > 0 ? ", " : "", gdk_x11_get_xatom_name_for_display (display , atoms[i]));
+ }
+ g_printerr (" ]\n");
+ );
+}
+
+static GSList *
+gdk_x11_clipboard_formats_to_targets (GdkContentFormats *formats)
+{
+ GSList *targets;
+ const char * const *mime_types;
+ gsize i, j, n_mime_types;
+
+ targets = NULL;
+ mime_types = gdk_content_formats_get_mime_types (formats, &n_mime_types);
+
+ for (i = 0; i < n_mime_types; i++)
+ {
+ for (j = 0; j < G_N_ELEMENTS (special_targets); j++)
+ {
+ if (g_str_equal (mime_types[i], special_targets[j].mime_type))
+ targets = g_slist_prepend (targets, (gpointer) g_intern_string (special_targets[i].x_target));
+ }
+ targets = g_slist_prepend (targets, (gpointer) mime_types[i]);
+ }
+
+ return g_slist_reverse (targets);
+}
+
+static GdkContentFormats *
+gdk_x11_clipboard_formats_from_atoms (GdkDisplay *display,
+ const Atom *atoms,
+ gsize n_atoms)
+{
+ GdkContentFormatsBuilder *builder;
+ gsize i, j;
+
+ builder = gdk_content_formats_builder_new ();
+ for (i = 0; i < n_atoms; i++)
+ {
+ const char *name;
+
+ name = gdk_x11_get_xatom_name_for_display (display , atoms[i]);
+ if (strchr (name, '/'))
+ {
+ gdk_content_formats_builder_add_mime_type (builder, name);
+ continue;
+ }
+
+ for (j = 0; j < G_N_ELEMENTS (special_targets); j++)
+ {
+ if (g_str_equal (name, special_targets[j].x_target))
+ {
+ gdk_content_formats_builder_add_mime_type (builder, special_targets[j].mime_type);
+ break;
+ }
+ }
+ }
+
+ return gdk_content_formats_builder_free (builder);
+}
+
static void
gdk_x11_clipboard_request_targets_finish (GObject *source_object,
GAsyncResult *res,
@@ -66,11 +184,8 @@ gdk_x11_clipboard_request_targets_finish (GObject *source_object,
GdkX11Clipboard *cb = user_data;
GdkDisplay *display;
GdkContentFormats *formats;
- GdkContentFormatsBuilder *builder;
GBytes *bytes;
GError *error = NULL;
- const Atom *atoms;
- guint i, n_atoms;
bytes = g_input_stream_read_bytes_finish (stream, res, &error);
if (bytes == NULL)
@@ -88,17 +203,15 @@ gdk_x11_clipboard_request_targets_finish (GObject *source_object,
return;
}
- display = gdk_clipboard_get_display (GDK_CLIPBOARD (cb));
+ print_atoms (cb,
+ "received targets",
+ g_bytes_get_data (bytes, NULL),
+ g_bytes_get_size (bytes) / sizeof (Atom));
- atoms = g_bytes_get_data (bytes, NULL);
- n_atoms = g_bytes_get_size (bytes) / sizeof (Atom);
- builder = gdk_content_formats_builder_new ();
- for (i = 0; i < n_atoms; i++)
- {
- gdk_content_formats_builder_add_mime_type (builder, gdk_x11_get_xatom_name_for_display (display , atoms[i]));
- }
- gdk_content_formats_builder_add_formats (builder, gdk_clipboard_get_formats (GDK_CLIPBOARD (cb)));
- formats = gdk_content_formats_builder_free (builder);
+ display = gdk_clipboard_get_display (GDK_CLIPBOARD (cb));
+ formats = gdk_x11_clipboard_formats_from_atoms (display,
+ g_bytes_get_data (bytes, NULL),
+ g_bytes_get_size (bytes) / sizeof (Atom));
GDK_NOTE(CLIPBOARD, char *s = gdk_content_formats_to_string (formats); g_printerr ("%s: got formats: %s\n", cb->selection, s); g_free (s));
/* union with previously loaded formats */
@@ -122,13 +235,22 @@ gdk_x11_clipboard_request_targets_got_stream (GObject *source,
GInputStream *stream;
GdkDisplay *display;
GError *error = NULL;
+ const char *type;
+ int format;
- stream = gdk_x11_selection_input_stream_new_finish (result, &error);
+ stream = gdk_x11_selection_input_stream_new_finish (result, &type, &format, &error);
if (stream == NULL)
{
g_object_unref (cb);
return;
}
+ else if (!g_str_equal (type, "ATOM") || format != 32)
+ {
+ g_input_stream_close (stream, NULL, NULL);
+ g_object_unref (stream);
+ g_object_unref (cb);
+ return;
+ }
display = gdk_clipboard_get_display (GDK_CLIPBOARD (cb));
@@ -213,13 +335,61 @@ gdk_x11_clipboard_read_got_stream (GObject *source,
GTask *task = data;
GError *error = NULL;
GInputStream *stream;
+ const char *type;
+ int format;
- stream = gdk_x11_selection_input_stream_new_finish (res, &error);
- /* XXX: We could try more types here */
+ stream = gdk_x11_selection_input_stream_new_finish (res, &type, &format, &error);
if (stream == NULL)
- g_task_return_error (task, error);
+ {
+ GSList *targets, *next;
+
+ targets = g_task_get_task_data (task);
+ next = targets->next;
+ if (next)
+ {
+ GdkX11Clipboard *cb = GDK_X11_CLIPBOARD (g_task_get_source_object (task));
+
+ GDK_NOTE(CLIPBOARD, g_printerr ("%s: reading %s failed, trying %s next\n",
+ cb->selection, (char *) targets->data, (char *) next->data));
+ targets->next = NULL;
+ g_task_set_task_data (task, next, (GDestroyNotify) g_slist_free);
+ gdk_x11_selection_input_stream_new_async (gdk_clipboard_get_display (GDK_CLIPBOARD (cb)),
+ cb->selection,
+ next->data,
+ cb->timestamp,
+ g_task_get_priority (task),
+ g_task_get_cancellable (task),
+ gdk_x11_clipboard_read_got_stream,
+ task);
+ g_error_free (error);
+ return;
+ }
+
+ g_task_return_error (task, error);
+ }
else
- g_task_return_pointer (task, stream, g_object_unref);
+ {
+ GdkX11Clipboard *cb = GDK_X11_CLIPBOARD (g_task_get_source_object (task));
+ const char *mime_type = ((GSList *) g_task_get_task_data (task))->data;
+ gsize i;
+
+ for (i = 0; i < G_N_ELEMENTS (special_targets); i++)
+ {
+ if (g_str_equal (mime_type, special_targets[i].x_target))
+ {
+ GDK_NOTE(CLIPBOARD, g_printerr ("%s: reading with converter from %s to %s\n",
+ cb->selection, mime_type, special_targets[i].mime_type));
+ mime_type = g_intern_string (special_targets[i].mime_type);
+ g_task_set_task_data (task, g_slist_prepend (NULL, (gpointer) mime_type), (GDestroyNotify) g_slist_free);
+ stream = special_targets[i].convert (cb, stream, type, format);
+ break;
+ }
+ }
+
+ GDK_NOTE(CLIPBOARD, g_printerr ("%s: reading clipboard as %s now\n",
+ cb->selection, mime_type));
+ g_task_return_pointer (task, stream, g_object_unref);
+ }
g_object_unref (task);
}
@@ -233,20 +403,27 @@ gdk_x11_clipboard_read_async (GdkClipboard *clipboard,
gpointer user_data)
{
GdkX11Clipboard *cb = GDK_X11_CLIPBOARD (clipboard);
- const char * const *mime_types;
+ GSList *targets;
GTask *task;
task = g_task_new (clipboard, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
g_task_set_source_tag (task, gdk_x11_clipboard_read_async);
- g_task_set_task_data (task, gdk_content_formats_ref (formats), (GDestroyNotify) gdk_content_formats_unref);
- /* XXX: Sort differently? */
- mime_types = gdk_content_formats_get_mime_types (formats, NULL);
+ targets = gdk_x11_clipboard_formats_to_targets (formats);
+ g_task_set_task_data (task, targets, (GDestroyNotify) g_slist_free);
+ if (targets == NULL)
+ {
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("No compatible transfer format found"));
+ return;
+ }
+ GDK_NOTE(CLIPBOARD, g_printerr ("%s: new read for %s (%u other options)\n",
+ cb->selection, (char *) targets->data, g_slist_length (targets->next)));
gdk_x11_selection_input_stream_new_async (gdk_clipboard_get_display (GDK_CLIPBOARD (cb)),
cb->selection,
- mime_types[0],
+ targets->data,
cb->timestamp,
io_priority,
cancellable,
@@ -273,12 +450,10 @@ gdk_x11_clipboard_read_finish (GdkClipboard *clipboard,
{
if (out_mime_type)
{
- GdkContentFormats *formats;
- const char * const *mime_types;
+ GSList *targets;
- formats = g_task_get_task_data (task);
- mime_types = gdk_content_formats_get_mime_types (formats, NULL);
- *out_mime_type = mime_types[0];
+ targets = g_task_get_task_data (task);
+ *out_mime_type = targets->data;
}
g_object_ref (stream);
}
diff --git a/gdk/x11/gdkselectioninputstream-x11.c b/gdk/x11/gdkselectioninputstream-x11.c
index a694d05cb7..9ba704d6d0 100644
--- a/gdk/x11/gdkselectioninputstream-x11.c
+++ b/gdk/x11/gdkselectioninputstream-x11.c
@@ -40,6 +40,9 @@ struct GdkX11SelectionInputStreamPrivate {
Atom xtarget;
char *property;
Atom xproperty;
+ const char *type;
+ Atom xtype;
+ int format;
GTask *pending_task;
guchar *pending_data;
@@ -150,6 +153,8 @@ gdk_x11_selection_input_stream_complete (GdkX11SelectionInputStream *stream)
if (priv->complete)
return;
+ GDK_NOTE(SELECTION, g_printerr ("%s:%s: transfer complete\n",
+ priv->selection, priv->target));
priv->complete = TRUE;
g_async_queue_push (priv->chunks, g_bytes_new (NULL, 0));
@@ -457,7 +462,8 @@ gdk_x11_selection_input_stream_filter_event (GdkXEvent *xev,
}
else
{
- bytes = get_selection_property (xdisplay, xwindow, xevent->xselection.property, &type, &format);
+ bytes = get_selection_property (xdisplay, xwindow, xevent->xselection.property, &priv->xtype, &priv->format);
+ priv->type = gdk_x11_get_xatom_name_for_display (priv->display, priv->xtype);
g_task_return_pointer (task, g_object_ref (stream), g_object_unref);
@@ -477,6 +483,9 @@ gdk_x11_selection_input_stream_filter_event (GdkXEvent *xev,
}
else
{
+ GDK_NOTE(SELECTION, g_printerr ("%s:%s: reading %zu bytes\n",
+ priv->selection, priv->target,
+ g_bytes_get_size (bytes)));
g_async_queue_push (priv->chunks, bytes);
gdk_x11_selection_input_stream_complete (stream);
@@ -536,9 +545,11 @@ gdk_x11_selection_input_stream_new_async (GdkDisplay *display,
GInputStream *
gdk_x11_selection_input_stream_new_finish (GAsyncResult *result,
+ const char **type,
+ int *format,
GError **error)
{
- GInputStream *stream;
+ GdkX11SelectionInputStream *stream;
GTask *task;
g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
@@ -547,7 +558,16 @@ gdk_x11_selection_input_stream_new_finish (GAsyncResult *result,
stream = g_task_propagate_pointer (task, error);
if (stream)
- g_object_ref (stream);
- return stream;
+ {
+ GdkX11SelectionInputStreamPrivate *priv = gdk_x11_selection_input_stream_get_instance_private (stream);
+
+ if (type)
+ *type = priv->type;
+ if (format)
+ *format = priv->format;
+ g_object_ref (stream);
+ }
+
+ return G_INPUT_STREAM (stream);
}
diff --git a/gdk/x11/gdkselectioninputstream-x11.h b/gdk/x11/gdkselectioninputstream-x11.h
index c8bd19d55e..18c0763025 100644
--- a/gdk/x11/gdkselectioninputstream-x11.h
+++ b/gdk/x11/gdkselectioninputstream-x11.h
@@ -59,6 +59,8 @@ void gdk_x11_selection_input_stream_new_async (GdkDisplay
GAsyncReadyCallback callback,
gpointer user_data);
GInputStream * gdk_x11_selection_input_stream_new_finish (GAsyncResult *result,
+ const char **type,
+ int *format,
GError **error);
diff --git a/gdk/x11/gdktextlistconverter-x11.c b/gdk/x11/gdktextlistconverter-x11.c
new file mode 100644
index 0000000000..7fe56d1734
--- /dev/null
+++ b/gdk/x11/gdktextlistconverter-x11.c
@@ -0,0 +1,169 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Otte <otte@gnome.org>
+ */
+
+#include "config.h"
+
+#include "gdktextlistconverter-x11.h"
+
+#include "gdkintl.h"
+#include "gdkprivate-x11.h"
+
+#define GDK_X11_TEXT_LIST_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDK_TYPE_X11_TEXT_LIST_CONVERTER, GdkX11TextListConverterClass))
+#define GDK_IS_X11_TEXT_LIST_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDK_TYPE_X11_TEXT_LIST_CONVERTER))
+#define GDK_X11_TEXT_LIST_CONVERTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_X11_TEXT_LIST_CONVERTER, GdkX11TextListConverterClass))
+
+typedef struct _GdkX11TextListConverterClass GdkX11TextListConverterClass;
+
+struct _GdkX11TextListConverter
+{
+ GObject parent_instance;
+
+ GdkDisplay *display;
+
+ const char *encoding; /* interned */
+ gint format;
+};
+
+struct _GdkX11TextListConverterClass
+{
+ GObjectClass parent_class;
+};
+
+static GConverterResult
+gdk_x11_text_list_converter_convert (GConverter *converter,
+ const void *inbuf,
+ gsize inbuf_size,
+ void *outbuf,
+ gsize outbuf_size,
+ GConverterFlags flags,
+ gsize *bytes_read,
+ gsize *bytes_written,
+ GError **error)
+{
+ GdkX11TextListConverter *conv = GDK_X11_TEXT_LIST_CONVERTER (converter);
+ gint count;
+ char **list;
+
+ if (!(flags & G_CONVERTER_INPUT_AT_END))
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT,
+ _("Need complete input to do conversion"));
+ return G_CONVERTER_ERROR;
+ }
+
+ count = _gdk_x11_display_text_property_to_utf8_list (conv->display,
+ conv->encoding,
+ conv->format,
+ inbuf,
+ inbuf_size,
+ &list);
+ if (count < 0)
+ {
+ /* XXX: add error handling from gdkselection-x11.c */
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+ _("Not enough space in destination"));
+ return G_CONVERTER_ERROR;
+ }
+ else if (count == 0)
+ {
+ if (outbuf_size < 1)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+ _("Not enough space in destination"));
+ return G_CONVERTER_ERROR;
+ }
+ ((gchar *) outbuf)[0] = 0;
+ *bytes_read = inbuf_size;
+ *bytes_written = 1;
+ return G_CONVERTER_FINISHED;
+ }
+ else
+ {
+ gsize len = strlen (list[0]) + 1;
+
+ if (outbuf_size < len)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+ _("Not enough space in destination"));
+ return G_CONVERTER_ERROR;
+ }
+ memcpy (outbuf, list[0], len);
+ g_strfreev (list);
+ *bytes_read = inbuf_size;
+ *bytes_written = len;
+ return G_CONVERTER_FINISHED;
+ }
+}
+
+static void
+gdk_x11_text_list_converter_reset (GConverter *converter)
+{
+}
+
+static void
+gdk_x11_text_list_converter_iface_init (GConverterIface *iface)
+{
+ iface->convert = gdk_x11_text_list_converter_convert;
+ iface->reset = gdk_x11_text_list_converter_reset;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GdkX11TextListConverter, gdk_x11_text_list_converter, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
+ gdk_x11_text_list_converter_iface_init))
+
+static void
+gdk_x11_text_list_converter_finalize (GObject *object)
+{
+ GdkX11TextListConverter *conv = GDK_X11_TEXT_LIST_CONVERTER (object);
+
+ g_object_unref (conv->display);
+
+ G_OBJECT_CLASS (gdk_x11_text_list_converter_parent_class)->finalize (object);
+}
+
+static void
+gdk_x11_text_list_converter_class_init (GdkX11TextListConverterClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gdk_x11_text_list_converter_finalize;
+}
+
+static void
+gdk_x11_text_list_converter_init (GdkX11TextListConverter *local)
+{
+}
+
+GConverter *
+gdk_x11_text_list_converter_to_utf8_new (GdkDisplay *display,
+ const char *encoding,
+ int format)
+{
+ GdkX11TextListConverter *conv;
+
+ conv = g_object_new (GDK_TYPE_X11_TEXT_LIST_CONVERTER, NULL);
+
+ conv->display = g_object_ref (display);
+ conv->encoding = g_intern_string (encoding);
+ conv->format = format;
+
+ return G_CONVERTER (conv);
+}
+
diff --git a/gdk/x11/gdktextlistconverter-x11.h b/gdk/x11/gdktextlistconverter-x11.h
new file mode 100644
index 0000000000..9017a8b7e1
--- /dev/null
+++ b/gdk/x11/gdktextlistconverter-x11.h
@@ -0,0 +1,44 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Otte <otte@gnome.org>
+ */
+
+#ifndef __GDK_X11_TEXT_LIST_CONVERTER_H__
+#define __GDK_X11_TEXT_LIST_CONVERTER_H__
+
+#include <gio/gio.h>
+#include <gdk/gdktypes.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_X11_TEXT_LIST_CONVERTER (gdk_x11_text_list_converter_get_type ())
+#define GDK_X11_TEXT_LIST_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_X11_TEXT_LIST_CONVERTER, GdkX11TextListConverter))
+#define GDK_IS_X11_TEXT_LIST_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_X11_TEXT_LIST_CONVERTER))
+
+typedef struct _GdkX11TextListConverter GdkX11TextListConverter;
+
+GType gdk_x11_text_list_converter_get_type (void) G_GNUC_CONST;
+
+GConverter * gdk_x11_text_list_converter_to_utf8_new (GdkDisplay *display,
+ const char *encoding,
+ int format);
+
+
+G_END_DECLS
+
+#endif /* __GDK_X11_TEXT_LIST_CONVERTER_H__ */
diff --git a/gdk/x11/meson.build b/gdk/x11/meson.build
index 57ed429df4..db74295d8a 100644
--- a/gdk/x11/meson.build
+++ b/gdk/x11/meson.build
@@ -22,6 +22,7 @@ gdk_x11_sources = files([
'gdkscreen-x11.c',
'gdkselection-x11.c',
'gdkselectioninputstream-x11.c',
+ 'gdktextlistconverter-x11.c',
'gdkvisual-x11.c',
'gdkvulkancontext-x11.c',
'gdkwindow-x11.c',