Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 209 additions & 0 deletions 0002-Integrate-a-native-file-chooser-into-BlastEm-using-X.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
From e0ad37e6fe205d0ff701458403e1c83e5000c912 Mon Sep 17 00:00:00 2001
From: techmetx11 <techmetx11@disroot.org>
Date: Mon, 2 Feb 2026 23:51:58 +0100
Subject: [PATCH] Integrate a native file chooser into BlastEm using XDG
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This patch is added in this commit, and then modified in a later commit. I'd much rather see a single commit that added the final version of the patch.

desktop portal API (for Flatpak)

Add filters to the file chooser
---
Makefile | 15 +---
default.cfg | 2 +-
nuklear_ui/filechooser_xdg.c | 145 +++++++++++++++++++++++++++++++++++
3 files changed, 148 insertions(+), 14 deletions(-)
create mode 100644 nuklear_ui/filechooser_xdg.c

diff --git a/Makefile b/Makefile
index 6bb9be0..66d0204 100644
--- a/Makefile
+++ b/Makefile
@@ -93,21 +93,10 @@ Z80_DISPATCH:=call
else #CPU=wasm
FONT:=nuklear_ui/font.o
ifneq ($(MAKECMDGOALS),libblastem.$(SO))
-CHOOSER:=nuklear_ui/filechooser_gtk.o
-GTKFLAGS:=$(shell pkg-config --cflags gtk+-3.0 2>/dev/null)
-ifeq ($(GTKFLAGS),)
-GTKFLAGS:=$(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
-ifeq ($(GTKFLAGS),)
-CHOOSER:=nuklear_ui/filechooser_null.o
-endif
-endif
+CHOOSER:=nuklear_ui/filechooser_xdg.o
+LIBS+= libportal
endif #neq ($(MAKECMDGOALS),libblastem.$(SO))
endif #CPU=wasm
-ifeq ($(GTKFLAGS),)
-else
-EXTRA_NUKLEAR_LDFLAGS:=-ldl
-endif
-CFLAGS+= $(GTKFLAGS)
endif #Darwin

ifdef HOST_ZLIB
diff --git a/default.cfg b/default.cfg
index 73df736..7a22f1c 100644
--- a/default.cfg
+++ b/default.cfg
@@ -412,7 +412,7 @@ ui {
#specifies the preferred save-state format, set to gst for Genecyst compatible states
state_format native
#set to on to use the native file picker on your OS instead of the builtin one
- use_native_filechooser off
+ use_native_filechooser on
}

system {
diff --git a/nuklear_ui/filechooser_xdg.c b/nuklear_ui/filechooser_xdg.c
new file mode 100644
index 0000000..bd90286
--- /dev/null
+++ b/nuklear_ui/filechooser_xdg.c
@@ -0,0 +1,145 @@
+#include <stddef.h>
+#include <stdint.h>
+
+#include <libportal/portal.h>
+#include <SDL2/SDL_mutex.h>
+
+static XdpPortal *portal = NULL;
+typedef struct {
+ GMainLoop *loop;
+ char *uri;
+} FileChooserData;
+
+uint8_t native_filechooser_available(void)
+{
+ return 1;
+}
+
+void native_filechooser_callback(GObject *obj, GAsyncResult *res, gpointer data) {
+ FileChooserData *fcdata = data;
+ GVariant *var = xdp_portal_open_file_finish(portal, res, NULL);
+ if (!var) {
+ fcdata->uri = NULL;
+ g_main_loop_quit(fcdata->loop);
+ return;
+ }
+
+ GVariant *uris = g_variant_lookup_value(var, "uris", G_VARIANT_TYPE_STRING_ARRAY);
+
+ GVariant *first_uri = g_variant_get_child_value(uris, 0);
+ gsize length = 0;
+
+ const gchar *uri_string = g_variant_dup_string(first_uri, &length);
+
+ gchar *unespaced_uri = g_filename_from_uri(uri_string, NULL, NULL);
+ fcdata->uri = strndup(unespaced_uri, length);
+
+ g_free(unespaced_uri);
+ g_main_loop_quit(fcdata->loop);
+}
+
+char* native_filechooser_pick(const char *title, const char *start_directory)
+{
+ if (!portal) {
+ portal = xdp_portal_new();
+ }
+ FileChooserData data;
+ GMainContext *context = g_main_context_new();
+ GMainLoop *loop = g_main_loop_new(context, FALSE);
+ GCancellable *cancellable = g_cancellable_new();
+
+ g_main_context_push_thread_default(context);
+
+ data.loop = loop;
+
+ // Filter builder
+ GVariantBuilder filters;
+ GVariantBuilder allfiles_filter;
+ GVariantBuilder allsupported_filter;
+ GVariantBuilder gen_filter;
+ GVariantBuilder scd_filter;
+ GVariantBuilder sms_filter;
+ GVariantBuilder vgm_filter;
+
+ g_variant_builder_init(&filters, G_VARIANT_TYPE("a(sa(us))"));
+ g_variant_builder_init(&allfiles_filter, G_VARIANT_TYPE("a(us)"));
+
+ g_variant_builder_add(&allfiles_filter, "(us)", 0, "*");
+
+ g_variant_builder_init(&allsupported_filter, G_VARIANT_TYPE("a(us)"));
+
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.zip");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.bin");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.bin.gz");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.gen");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.gen.gz");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.md");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.md.gz");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.sms");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.sms.gz");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.gg");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.gg.gz");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.sg");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.sg.gz");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.cue");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.toc");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.flac");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.vgm");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.vgz");
+ g_variant_builder_add(&allsupported_filter, "(us)", 0, "*.vgm.gz");
+
+ g_variant_builder_init(&gen_filter, G_VARIANT_TYPE("a(us)"));
+
+ g_variant_builder_add(&gen_filter, "(us)", 0, "*.zip");
+ g_variant_builder_add(&gen_filter, "(us)", 0, "*.bin");
+ g_variant_builder_add(&gen_filter, "(us)", 0, "*.bin.gz");
+ g_variant_builder_add(&gen_filter, "(us)", 0, "*.gen");
+ g_variant_builder_add(&gen_filter, "(us)", 0, "*.gen.gz");
+ g_variant_builder_add(&gen_filter, "(us)", 0, "*.md");
+ g_variant_builder_add(&gen_filter, "(us)", 0, "*.md.gz");
+
+ g_variant_builder_init(&scd_filter, G_VARIANT_TYPE("a(us)"));
+
+ g_variant_builder_add(&scd_filter, "(us)", 0, "*.cue");
+ g_variant_builder_add(&scd_filter, "(us)", 0, "*.toc");
+
+ g_variant_builder_init(&sms_filter, G_VARIANT_TYPE("a(us)"));
+
+ g_variant_builder_add(&sms_filter, "(us)", 0, "*.sms");
+ g_variant_builder_add(&sms_filter, "(us)", 0, "*.sms.gz");
+ g_variant_builder_add(&sms_filter, "(us)", 0, "*.gg");
+ g_variant_builder_add(&sms_filter, "(us)", 0, "*.gg.gz");
+ g_variant_builder_add(&sms_filter, "(us)", 0, "*.sg");
+ g_variant_builder_add(&sms_filter, "(us)", 0, "*.sg.gz");
+
+ g_variant_builder_init(&vgm_filter, G_VARIANT_TYPE("a(us)"));
+
+ g_variant_builder_add(&vgm_filter, "(us)", 0, "*.flac");
+ g_variant_builder_add(&vgm_filter, "(us)", 0, "*.vgm");
+ g_variant_builder_add(&vgm_filter, "(us)", 0, "*.vgz");
+ g_variant_builder_add(&vgm_filter, "(us)", 0, "*.vgm.gz");
+
+ g_variant_builder_add(&filters, "(sa(us))", "All Files", &allfiles_filter);
+ g_variant_builder_add(&filters, "(sa(us))", "All Supported Files", &allsupported_filter);
+ g_variant_builder_add(&filters, "(sa(us))", "Genesis/MD", &gen_filter);
+ g_variant_builder_add(&filters, "(sa(us))", "Sega/Mega CD", &scd_filter);
+ g_variant_builder_add(&filters, "(sa(us))", "Sega 8-bit", &sms_filter);
+ g_variant_builder_add(&filters, "(sa(us))", "Audio/VGM", &vgm_filter);
+
+ GVariant *filters_var = g_variant_builder_end(&filters);
+
+ // Set Genesis/MD as the default filter
+ xdp_portal_open_file(portal, NULL, title, filters_var, g_variant_get_child_value(filters_var, 2), NULL, 0, cancellable, native_filechooser_callback, &data);
+
+ g_main_loop_run(loop);
+ g_main_context_pop_thread_default(context);
+
+ if (g_cancellable_is_cancelled(cancellable)) {
+ data.uri = NULL;
+ }
+
+ g_main_loop_unref(loop);
+ g_main_context_unref(context);
+
+ return data.uri;
+}
--
2.52.0

3 changes: 2 additions & 1 deletion com.retrodev.blastem.appdata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<component type="desktop">
<id>com.retrodev.blastem</id>
<launchable type="desktop-id">com.retrodev.blastem.desktop</launchable>
<name>Blastem</name>
<name>BlastEm</name>
<summary>A Sega Mega Drive/Genesis, and Master System emulator</summary>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0+</project_license>
Expand All @@ -17,6 +17,7 @@
</p>
</description>
<url type="homepage">https://www.retrodev.com/blastem/</url>
<url type="vcs-browser">https://www.retrodev.com/repos/blastem</url>
<screenshots>
<screenshot width="640" height="517">
<image>https://raw.githubusercontent.com/flathub/com.retrodev.blastem/master/screenshots/blastem-1.png</image>
Expand Down
29 changes: 24 additions & 5 deletions com.retrodev.blastem.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,30 @@
/* Joystick and GPU access */
"--device=all",
/* Get access to the files */
"--filesystem=home:ro",
"--filesystem=xdg-run/gvfs:ro"
],
"modules" : [
"shared-modules/glu/glu-9.json",
"shared-modules/glew/glew.json",
{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent is off.

"name": "libportal",
"buildsystem": "meson",
"config-opts": [
"-Dbackend-gtk3=disabled",
"-Dbackend-gtk4=disabled",
"-Dbackend-qt5=disabled",
"-Dbackend-qt6=disabled",
"-Dvapi=false",
"-Ddocs=false",
"-Dtests=false"
],
"sources": [
{
"type": "git",
"url": "https://github.com/flatpak/libportal.git",
"commit": "086cc57372989117cfb6ef4c565bdd316db2e536"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why isn't this a release?

}]
},
{
"name" : "blastem",
"buildsystem" : "simple",
Expand All @@ -26,7 +44,7 @@
"install -m0755 -D blastem /app/bin/blastem.bin",
"install -m0755 -D blastem.sh /app/bin/blastem",
"install -d /app/share/blastem/",
"cp -r shaders/ images/ gamecontrollerdb.txt rom.db /app/share/blastem/",
"cp -r shaders/ images/ gamecontrollerdb.txt rom.db systems.cfg /app/share/blastem/",
"install -m0644 -D default.cfg /app/etc/default.cfg",
"install -m0644 -D ${FLATPAK_ID}.png /app/share/icons/hicolor/256x256/apps/${FLATPAK_ID}.png",
"install -m0644 -D com.retrodev.blastem.desktop /app/share/applications/com.retrodev.blastem.desktop",
Expand All @@ -35,8 +53,8 @@
"sources" : [
{
"type" : "archive",
"url" : "https://www.retrodev.com/repos/blastem/archive/0013362c320c.tar.bz2",
"sha256" : "4e6a937097c868471507d59e4a5a6f0da8b06af44ee9f3d05d530c5348b2ad9b"
"url" : "https://www.retrodev.com/repos/blastem/archive/0b220095659f.tar.bz2",
"sha256" : "7e02e3ee6547ddb81f049f8b99d1a17288c916cdb169365e60ae91bad33b0f0c"
},
{
"type" : "script",
Expand All @@ -49,7 +67,8 @@
{
"type" : "patch",
"paths" : [
"0001-Add-support-for-Flatpak-config-data-dir-variables.patch"
"0001-Add-support-for-Flatpak-config-data-dir-variables.patch",
"0002-Integrate-a-native-file-chooser-into-BlastEm-using-X.patch"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent is off

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That patch is nice, but what's its upstream status? Is the maintainer going to review it/merge it soon? We would at least want a reference in the commit message.

]
},
{
Expand Down
3 changes: 1 addition & 2 deletions flathub.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"only-arches": [
"x86_64",
"i386"
"x86_64"
]
}