Last active
August 7, 2026 05:07
-
-
Save LowByteFox/f392bae6e57eb68d04887310a5caa7c2 to your computer and use it in GitHub Desktop.
libportal file open dialog example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #if 0 | |
| set -e | |
| cc -D _GNU_SOURCE -g $(pkg-config --cflags libportal) portal.c -o /tmp/portal $(pkg-config --libs libportal) | |
| /tmp/portal | |
| #endif | |
| /* libportal is licensed under LGPL-3.0-only :/, dynamic linking recommended */ | |
| #include <stdio.h> | |
| #include <stdbool.h> | |
| #include <unistd.h> | |
| #include <libportal/portal.h> | |
| static bool done = false; | |
| static void open_file(XdpPortal *portal); | |
| static void open_files(XdpPortal *portal); | |
| static void save_file(XdpPortal *portal); | |
| static void _files(GObject *src, GAsyncResult *res, gpointer data); | |
| static void _save_file(GObject *src, GAsyncResult *res, gpointer data); | |
| int main() | |
| { | |
| GError *err; | |
| GMainContext *loop = g_main_context_default(); | |
| XdpPortal *portal = xdp_portal_initable_new(&err); | |
| if (!portal) { | |
| fprintf(stderr, "error: %s\n", err->message); | |
| return 1; | |
| } | |
| save_file(portal); | |
| while (g_main_context_pending(loop) || !done) { | |
| /* set this to false to not block */ | |
| g_main_context_iteration(loop, true); | |
| } | |
| g_object_unref(portal); | |
| g_main_context_unref(loop); | |
| return 0; | |
| } | |
| static void open_file(XdpPortal *portal) | |
| { | |
| GVariantBuilder *a1; | |
| GVariantBuilder *a2; | |
| a1 = g_variant_builder_new(G_VARIANT_TYPE("a(us)")); | |
| a2 = g_variant_builder_new(G_VARIANT_TYPE("a(sa(us))")); | |
| g_variant_builder_add(a1, "(us)", 0, "*.opng"); | |
| g_variant_builder_add(a2, "(s@a(us))", "Model", g_variant_builder_end(a1)); | |
| GVariant *filters = g_variant_builder_end(a2); | |
| xdp_portal_open_file(portal, NULL, "Open File", filters, NULL, NULL, | |
| XDP_OPEN_FILE_FLAG_NONE, NULL, _files, portal); | |
| } | |
| static void save_file(XdpPortal *portal) | |
| { | |
| GVariantBuilder *a1; | |
| GVariantBuilder *a2; | |
| a1 = g_variant_builder_new(G_VARIANT_TYPE("a(us)")); | |
| a2 = g_variant_builder_new(G_VARIANT_TYPE("a(sa(us))")); | |
| g_variant_builder_add(a1, "(us)", 0, "*.opng"); | |
| g_variant_builder_add(a2, "(s@a(us))", "Model", g_variant_builder_end(a1)); | |
| GVariant *filters = g_variant_builder_end(a2); | |
| xdp_portal_save_file(portal, NULL, "Save File", "model.opng", NULL, NULL, filters, | |
| NULL, NULL, 0, NULL, _save_file, portal); | |
| } | |
| static void open_files(XdpPortal *portal) | |
| { | |
| GVariantBuilder *a1; | |
| GVariantBuilder *a2; | |
| a1 = g_variant_builder_new(G_VARIANT_TYPE("a(us)")); | |
| a2 = g_variant_builder_new(G_VARIANT_TYPE("a(sa(us))")); | |
| g_variant_builder_add(a1, "(us)", 1, "image/avif"); | |
| g_variant_builder_add(a1, "(us)", 0, "*.jxl"); | |
| g_variant_builder_add(a1, "(us)", 1, "image/webp"); | |
| g_variant_builder_add(a1, "(us)", 0, "*.qoi"); | |
| g_variant_builder_add(a1, "(us)", 1, "image/png"); | |
| g_variant_builder_add(a1, "(us)", 1, "image/bmp"); | |
| g_variant_builder_add(a1, "(us)", 1, "image/jpeg"); | |
| g_variant_builder_add(a1, "(us)", 0, "*.tga"); | |
| g_variant_builder_add(a1, "(us)", 0, "*.psd"); | |
| g_variant_builder_add(a1, "(us)", 0, "*.dds"); | |
| g_variant_builder_add(a1, "(us)", 1, "image/gif"); | |
| g_variant_builder_add(a1, "(us)", 1, "image/png"); | |
| g_variant_builder_add(a1, "(us)", 0, "*.opng"); | |
| g_variant_builder_add(a2, "(s@a(us))", "Images", g_variant_builder_end(a1)); | |
| GVariant *filters = g_variant_builder_end(a2); | |
| xdp_portal_open_file(portal, NULL, "Open Files", filters, NULL, NULL, | |
| XDP_OPEN_FILE_FLAG_MULTIPLE, NULL, _files, portal); | |
| } | |
| static void _files(GObject *src, GAsyncResult *ares, gpointer data) | |
| { | |
| GError *err = NULL; | |
| XdpPortal *portal = data; | |
| GVariant *res = xdp_portal_open_file_finish(portal, ares, &err); | |
| if (err) { | |
| fprintf(stderr, "error: %s\n", err->message); | |
| exit(1); | |
| } | |
| GVariant *uris = g_variant_lookup_value(res, "uris", NULL); | |
| size_t count = g_variant_n_children(uris); | |
| for (int i = 0; i < count; i++) { | |
| GVariant *uri = g_variant_get_child_value(uris, i); | |
| printf("%s\n", g_variant_get_string(uri, NULL)); | |
| g_variant_unref(uri); | |
| } | |
| g_variant_unref(uris); | |
| g_variant_unref(res); | |
| done = true; | |
| } | |
| static void _save_file(GObject *src, GAsyncResult *ares, gpointer data) | |
| { | |
| GError *err = NULL; | |
| XdpPortal *portal = data; | |
| GVariant *res = xdp_portal_save_file_finish(portal, ares, &err); | |
| if (err) { | |
| fprintf(stderr, "error: %s\n", err->message); | |
| exit(1); | |
| } | |
| GVariant *uris = g_variant_lookup_value(res, "uris", NULL); | |
| size_t count = g_variant_n_children(uris); | |
| for (int i = 0; i < count; i++) { | |
| GVariant *uri = g_variant_get_child_value(uris, i); | |
| printf("%s\n", g_variant_get_string(uri, NULL)); | |
| g_variant_unref(uri); | |
| } | |
| g_variant_unref(uris); | |
| g_variant_unref(res); | |
| done = true; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment