From 2ebdce98bd98d5b0d994b1633b9c1c258799c905 Mon Sep 17 00:00:00 2001 From: Joan Torres Date: Fri, 6 Oct 2023 17:07:03 +0200 Subject: [PATCH 1/5] wl, x11, gtk4: Add file chooser XdpPortal allows to communicate with all Portal interfaces. In this case it is used the FileChooser portal to get a file chooser. It is used when "run-file-chooser" signal from WebKitWebView is emitted. It should get a XdpParent to keep the new dialog always on top of cog. --- core/cog-config.h.in | 1 + core/meson.build | 1 + meson.build | 1 + platform/common/cog-file-chooser.c | 61 ++++++++++++++++++++++++++++++ platform/common/cog-file-chooser.h | 17 +++++++++ platform/common/meson.build | 7 ++++ platform/gtk4/cog-platform-gtk4.c | 16 ++++++++ platform/wayland/cog-platform-wl.c | 16 ++++++++ platform/wayland/meson.build | 1 + platform/x11/cog-platform-x11.c | 16 ++++++++ 10 files changed, 137 insertions(+) create mode 100644 platform/common/cog-file-chooser.c create mode 100644 platform/common/cog-file-chooser.h diff --git a/core/cog-config.h.in b/core/cog-config.h.in index 3afd903b..6baac9fc 100644 --- a/core/cog-config.h.in +++ b/core/cog-config.h.in @@ -18,6 +18,7 @@ #define COG_DEFAULT_APPID "@COG_DEFAULT_APPID@" #define COG_DEFAULT_HOME_URI "@COG_DEFAULT_HOME_URI@" #define COG_HAVE_MEM_PRESSURE @HAVE_WEBKIT_MEM_PRESSURE_API@ +#define COG_HAVE_LIBPORTAL @HAVE_LIBPORTAL@ #define COG_ENABLE_GAMEPAD_MANETTE @ENABLE_GAMEPAD_MANETTE@ /* FIXME: Perhaps make this a meson define instead. */ diff --git a/core/meson.build b/core/meson.build index c67b9140..5f905a55 100644 --- a/core/meson.build +++ b/core/meson.build @@ -11,6 +11,7 @@ cog_config.set('COG_DEFAULT_APPID', cog_launcher_appid) cog_config.set('COG_DEFAULT_HOME_URI', cog_launcher_home_uri) cog_config.set10('HAVE_WEBKIT_MEM_PRESSURE_API', wpewebkit_dep.version().version_compare('>=2.34.0')) +cog_config.set10('HAVE_LIBPORTAL', libportal_dep.found()) cog_config.set10('ENABLE_GAMEPAD_MANETTE', gamepad_manette) cogcore_config_h = configure_file( diff --git a/meson.build b/meson.build index a27adee0..91c8a34e 100644 --- a/meson.build +++ b/meson.build @@ -152,6 +152,7 @@ endif wpe_dep = dependency('wpe-1.0') manette_dep = dependency('manette-0.2', version: '>=0.2.4', required: false) +libportal_dep = dependency('libportal', required: false) subdir('core') diff --git a/platform/common/cog-file-chooser.c b/platform/common/cog-file-chooser.c new file mode 100644 index 00000000..d275789e --- /dev/null +++ b/platform/common/cog-file-chooser.c @@ -0,0 +1,61 @@ +/* + * cog-file-chooser.c + * Copyright (C) 2023 SUSE Software Solutions Germany GmbH + * + * Distributed under terms of the MIT license. + */ + +#include "cog-file-chooser.h" + +static void +on_file_chooser_response(GObject *object, GAsyncResult *result, gpointer user_data) +{ + g_autoptr(GError) error = NULL; + g_autoptr(XdpPortal) xdp_portal = XDP_PORTAL(object); + g_autoptr(WebKitFileChooserRequest) request = WEBKIT_FILE_CHOOSER_REQUEST(user_data); + g_autoptr(GVariant) val = xdp_portal_open_file_finish(xdp_portal, result, &error); + if (!val) { + g_debug("File chooser failed: %s", error->message); + webkit_file_chooser_request_cancel(request); + return; + } + + g_autofree const char **uris = NULL; + g_variant_lookup(val, "uris", "^a&s", &uris); + webkit_file_chooser_request_select_files(request, uris); +} + +void +run_file_chooser(WebKitWebView *view, WebKitFileChooserRequest *request, XdpParent *xdp_parent) +{ + XdpPortal *xdp_portal = xdp_portal_new(); + if (!xdp_portal) + return; + + GVariantBuilder all_filters_builder; + g_variant_builder_init(&all_filters_builder, G_VARIANT_TYPE("a(sa(us))")); + + // Add "Supported files" filters from mime types + const char *const *mime_types = webkit_file_chooser_request_get_mime_types(request); + if (mime_types) { + GVariantBuilder one_filter_builder; + g_variant_builder_init(&one_filter_builder, G_VARIANT_TYPE("a(us)")); + for (int i = 0; mime_types[i]; i++) { + g_variant_builder_add(&one_filter_builder, "(us)", 1, mime_types[i]); + } + g_variant_builder_add(&all_filters_builder, "(s@a(us))", "Supported files", + g_variant_builder_end(&one_filter_builder)); + } + + // Add "All files" filter + GVariantBuilder one_filter_builder; + g_variant_builder_init(&one_filter_builder, G_VARIANT_TYPE("a(us)")); + g_variant_builder_add(&one_filter_builder, "(us)", 0, "*"); + g_variant_builder_add(&all_filters_builder, "(s@a(us))", "All files", g_variant_builder_end(&one_filter_builder)); + + gboolean select_multiple = webkit_file_chooser_request_get_select_multiple(request); + xdp_portal_open_file(xdp_portal, xdp_parent, select_multiple ? "Select Files" : "Select File", + g_variant_builder_end(&all_filters_builder), NULL, NULL, + select_multiple ? XDP_OPEN_FILE_FLAG_MULTIPLE : XDP_OPEN_FILE_FLAG_NONE, NULL, + on_file_chooser_response, g_object_ref(request)); +} diff --git a/platform/common/cog-file-chooser.h b/platform/common/cog-file-chooser.h new file mode 100644 index 00000000..41599f8c --- /dev/null +++ b/platform/common/cog-file-chooser.h @@ -0,0 +1,17 @@ +/* + * cog-file-chooser.h + * Copyright (C) 2023 SUSE Software Solutions Germany GmbH + * + * Distributed under terms of the MIT license. + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +void run_file_chooser(WebKitWebView *view, WebKitFileChooserRequest *request, XdpParent *xdp_parent); + +G_END_DECLS diff --git a/platform/common/meson.build b/platform/common/meson.build index 92475ac0..200ad871 100644 --- a/platform/common/meson.build +++ b/platform/common/meson.build @@ -1,10 +1,17 @@ cogplatformcommon_dependencies = [ cogcore_dep, + libportal_dep, dependency('epoxy'), ] +cogplatformcommon_sources = [] +if libportal_dep.found() + cogplatformcommon_sources += ['cog-file-chooser.c'] +endif + cogplatformcommon_lib = static_library('cogplatformcommon', 'cog-gl-utils.c', + cogplatformcommon_sources, dependencies: cogplatformcommon_dependencies, build_by_default: false, gnu_symbol_visibility: 'hidden', diff --git a/platform/gtk4/cog-platform-gtk4.c b/platform/gtk4/cog-platform-gtk4.c index 4cf6f9c4..451d1f6e 100644 --- a/platform/gtk4/cog-platform-gtk4.c +++ b/platform/gtk4/cog-platform-gtk4.c @@ -11,6 +11,9 @@ #include #include "../../core/cog.h" +#if COG_HAVE_LIBPORTAL +# include "../common/cog-file-chooser.h" +#endif /* COG_HAVE_LIBPORTAL */ #include "../common/cog-gl-utils.h" #include "cog-gtk-settings-dialog.h" @@ -745,6 +748,16 @@ on_back_forward_changed(WebKitBackForwardList* back_forward_list, webkit_web_view_can_go_forward(win->web_view)); } +#if COG_HAVE_LIBPORTAL +static void +on_run_file_chooser(WebKitWebView *view, WebKitFileChooserRequest *request) +{ + /* TODO: Disable input of main window and keep this new file chooser + * window always on top. This could be done adding an XdpParent. */ + run_file_chooser(view, request, NULL); +} +#endif /* COG_HAVE_LIBPORTAL */ + static void cog_gtk4_platform_init_web_view(CogPlatform* platform, WebKitWebView* view) { @@ -754,6 +767,9 @@ cog_gtk4_platform_init_web_view(CogPlatform* platform, WebKitWebView* view) G_CALLBACK(on_load_progress), &win); g_signal_connect(webkit_web_view_get_back_forward_list(view), "changed", G_CALLBACK(on_back_forward_changed), &win); +#if COG_HAVE_LIBPORTAL + g_signal_connect(view, "run-file-chooser", G_CALLBACK(on_run_file_chooser), NULL); +#endif /* COG_HAVE_LIBPORTAL */ win.web_view = view; win.device_scale_factor = gtk_widget_get_scale_factor(win.gl_drawing_area); diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index 318b3125..fbcb9412 100644 --- a/platform/wayland/cog-platform-wl.c +++ b/platform/wayland/cog-platform-wl.c @@ -33,6 +33,9 @@ #include #include +#if COG_HAVE_LIBPORTAL +# include "../common/cog-file-chooser.h" +#endif /* COG_HAVE_LIBPORTAL */ #include "../common/egl-proc-address.h" #include "os-compatibility.h" @@ -2548,10 +2551,23 @@ on_show_option_menu(WebKitWebView *view, WebKitOptionMenu *menu, WebKitRectangle create_popup (g_object_ref (menu)); } +#if COG_HAVE_LIBPORTAL +static void +on_run_file_chooser(WebKitWebView *view, WebKitFileChooserRequest *request) +{ + /* TODO: Disable input of main window and keep this new file chooser + * window always on top. This could be done adding an XdpParent. */ + run_file_chooser(view, request, NULL); +} +#endif /* COG_HAVE_LIBPORTAL */ + static void cog_wl_platform_init_web_view(CogPlatform *platform, WebKitWebView *view) { g_signal_connect (view, "show-option-menu", G_CALLBACK (on_show_option_menu), NULL); +#if COG_HAVE_LIBPORTAL + g_signal_connect(view, "run-file-chooser", G_CALLBACK(on_run_file_chooser), NULL); +#endif /* COG_HAVE_LIBPORTAL */ COG_WL_PLATFORM(platform)->web_view = view; } diff --git a/platform/wayland/meson.build b/platform/wayland/meson.build index a8984d36..d219b181 100644 --- a/platform/wayland/meson.build +++ b/platform/wayland/meson.build @@ -8,6 +8,7 @@ with_wayland_weston_content_protection = (with_wayland_platform wayland_platform_dependencies = [ cogcore_dep, + cogplatformcommon_dep, wpebackend_fdo_dep, dependency('cairo'), dependency('egl'), diff --git a/platform/x11/cog-platform-x11.c b/platform/x11/cog-platform-x11.c index 06c1c30f..910fd78c 100644 --- a/platform/x11/cog-platform-x11.c +++ b/platform/x11/cog-platform-x11.c @@ -19,6 +19,9 @@ #include #include +#if COG_HAVE_LIBPORTAL +# include "../common/cog-file-chooser.h" +#endif /* COG_HAVE_LIBPORTAL */ #include "../common/cog-gl-utils.h" #include "../common/egl-proc-address.h" @@ -873,9 +876,22 @@ cog_x11_platform_get_view_backend(CogPlatform *platform, WebKitWebView *related_ return wk_view_backend; } +#if COG_HAVE_LIBPORTAL +static void +on_run_file_chooser(WebKitWebView *view, WebKitFileChooserRequest *request) +{ + /* TODO: Disable input of main window and keep this new file chooser + * window always on top. This could be done adding an XdpParent. */ + run_file_chooser(view, request, NULL); +} +#endif /* COG_HAVE_LIBPORTAL */ + static void cog_x11_platform_init_web_view(CogPlatform *platform, WebKitWebView *web_view) { +#if COG_HAVE_LIBPORTAL + g_signal_connect(web_view, "run-file-chooser", G_CALLBACK(on_run_file_chooser), NULL); +#endif /* COG_HAVE_LIBPORTAL */ COG_X11_PLATFORM(platform)->web_view = COG_VIEW(web_view); } From 360e10839c9b6cfc7f2fde3588e085deda5d9e5f Mon Sep 17 00:00:00 2001 From: Joan Torres Date: Fri, 6 Oct 2023 17:36:51 +0200 Subject: [PATCH 2/5] gtk: Add an XdpParent on file chooser dialog On libportal-gtk4 there is a gtk4 implementation of XdpParent which allows keeping the dialog always on top. --- platform/gtk4/cog-platform-gtk4.c | 12 ++++++++---- platform/gtk4/meson.build | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/platform/gtk4/cog-platform-gtk4.c b/platform/gtk4/cog-platform-gtk4.c index 451d1f6e..7903900b 100644 --- a/platform/gtk4/cog-platform-gtk4.c +++ b/platform/gtk4/cog-platform-gtk4.c @@ -5,12 +5,16 @@ * Distributed under terms of the MIT license. */ +#include "../../core/cog.h" + #include #include #include #include +#if COG_HAVE_LIBPORTAL +# include +#endif /* COG_HAVE_LIBPORTAL */ -#include "../../core/cog.h" #if COG_HAVE_LIBPORTAL # include "../common/cog-file-chooser.h" #endif /* COG_HAVE_LIBPORTAL */ @@ -752,9 +756,9 @@ on_back_forward_changed(WebKitBackForwardList* back_forward_list, static void on_run_file_chooser(WebKitWebView *view, WebKitFileChooserRequest *request) { - /* TODO: Disable input of main window and keep this new file chooser - * window always on top. This could be done adding an XdpParent. */ - run_file_chooser(view, request, NULL); + g_autoptr(XdpParent) xdp_parent = xdp_parent_new_gtk(GTK_WINDOW(win.gtk_window)); + + run_file_chooser(view, request, xdp_parent); } #endif /* COG_HAVE_LIBPORTAL */ diff --git a/platform/gtk4/meson.build b/platform/gtk4/meson.build index 5f0b2a51..c6f4747e 100644 --- a/platform/gtk4/meson.build +++ b/platform/gtk4/meson.build @@ -6,6 +6,7 @@ gtk4_platform_plugin = shared_module('cogplatform-gtk4', dependencies: [ cogplatformcommon_dep, wpebackend_fdo_dep, + dependency('libportal-gtk4', required: libportal_dep.found()), dependency('gtk4'), ], gnu_symbol_visibility: 'hidden', From 86f9eb8c0b5c5693c172f8b7001bf4fac147b66c Mon Sep 17 00:00:00 2001 From: Joan Torres Date: Fri, 6 Oct 2023 18:37:27 +0200 Subject: [PATCH 3/5] Add xdp-parent-private.h This is a copy of parent-private.h from libportal. And should be in sync to allow the use of XdpParent functionality from libportal. This is needed for the next commits to implement a different XdpParent, for the moment one for wayland and another one for x11. --- platform/common/xdp-parent-private.h | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 platform/common/xdp-parent-private.h diff --git a/platform/common/xdp-parent-private.h b/platform/common/xdp-parent-private.h new file mode 100644 index 00000000..c2c40cb3 --- /dev/null +++ b/platform/common/xdp-parent-private.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021, Georges Basile Stavracas Neto + * + * This file 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, version 3.0 of the + * License. + * + * This file 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 program. If not, see . + * + * SPDX-License-Identifier: LGPL-3.0-only + */ + +/* + * This must be in sync with parent-private.h header from libportal. + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +typedef void (* XdpParentExported) (XdpParent *parent, + const char *handle, + gpointer data); +typedef gboolean (* XdpParentExport) (XdpParent *parent, + XdpParentExported callback, + gpointer data); +typedef void (* XdpParentUnexport) (XdpParent *parent); + +struct _XdpParent { + /*< private >*/ + XdpParentExport parent_export; + XdpParentUnexport parent_unexport; + GObject *object; + XdpParentExported callback; + gpointer data; +}; + +G_END_DECLS From 0933cb81840371bcd4247f4293d07bf6d311d11d Mon Sep 17 00:00:00 2001 From: Joan Torres Date: Fri, 6 Oct 2023 18:17:06 +0200 Subject: [PATCH 4/5] wl: Add an XdpParent on file chooser dialog The XdpParent needs to know the "parent_window" string to keep the dialog on top. On wayland this "parent_window" can be obtained using the xdg-foreign protocol. This protocol is used on this XdpParent implementation. First it must call export_toplevel method, and then register a callback to receive a handle which is the "parent_window". To store the required data for this XdpParent implementation it is used the private "data" pointer property as a xdp_parent_wl_data. XdpParent isn't responsible of freeing it, so that data is handled at cog-platform-wl. --- platform/wayland/cog-platform-wl.c | 28 +++++++++++++-- platform/wayland/cog-xdp-parent-wl.c | 54 ++++++++++++++++++++++++++++ platform/wayland/cog-xdp-parent-wl.h | 25 +++++++++++++ platform/wayland/meson.build | 5 +++ 4 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 platform/wayland/cog-xdp-parent-wl.c create mode 100644 platform/wayland/cog-xdp-parent-wl.h diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index fbcb9412..84f4f554 100644 --- a/platform/wayland/cog-platform-wl.c +++ b/platform/wayland/cog-platform-wl.c @@ -42,12 +42,16 @@ #include "cog-im-context-wl-v1.h" #include "cog-im-context-wl.h" #include "cog-popup-menu-wl.h" +#if COG_HAVE_LIBPORTAL +# include "cog-xdp-parent-wl.h" +#endif /* COG_HAVE_LIBPORTAL */ #include "fullscreen-shell-unstable-v1-client.h" #include "linux-dmabuf-unstable-v1-client.h" #include "presentation-time-client.h" #include "text-input-unstable-v1-client.h" #include "text-input-unstable-v3-client.h" +#include "xdg-foreign-unstable-v2-client.h" #include "xdg-shell-client.h" #if COG_ENABLE_WESTON_DIRECT_DISPLAY @@ -184,6 +188,7 @@ static struct { struct zwp_text_input_manager_v3 *text_input_manager; struct zwp_text_input_manager_v1 *text_input_manager_v1; + struct zxdg_exporter_v2 *zxdg_exporter; struct wp_presentation *presentation; @@ -245,6 +250,10 @@ static struct { struct xdg_toplevel *xdg_toplevel; struct wl_shell_surface *shell_surface; +#if COG_HAVE_LIBPORTAL + struct xdp_parent_wl_data xdp_parent_wl_data; +#endif /* COG_HAVE_LIBPORTAL */ + uint32_t width; uint32_t height; uint32_t width_before_fullscreen; @@ -834,6 +843,8 @@ registry_global (void *data, wl_data.text_input_manager = wl_registry_bind(registry, name, &zwp_text_input_manager_v3_interface, 1); } else if (strcmp(interface, zwp_text_input_manager_v1_interface.name) == 0) { wl_data.text_input_manager_v1 = wl_registry_bind(registry, name, &zwp_text_input_manager_v1_interface, 1); + } else if (strcmp(interface, zxdg_exporter_v2_interface.name) == 0) { + wl_data.zxdg_exporter = wl_registry_bind(registry, name, &zxdg_exporter_v2_interface, 1); } else if (strcmp(interface, wp_presentation_interface.name) == 0) { wl_data.presentation = wl_registry_bind(registry, name, &wp_presentation_interface, 1); } else { @@ -1988,6 +1999,8 @@ clear_wayland (void) zwp_fullscreen_shell_v1_destroy (wl_data.fshell); if (wl_data.shell != NULL) wl_shell_destroy (wl_data.shell); + if (wl_data.zxdg_exporter != NULL) + zxdg_exporter_v2_destroy(wl_data.zxdg_exporter); g_clear_pointer (&wl_data.shm, wl_shm_destroy); g_clear_pointer (&wl_data.subcompositor, wl_subcompositor_destroy); @@ -2196,6 +2209,11 @@ create_window (GError **error) configure_surface_geometry(0, 0); } +#if COG_HAVE_LIBPORTAL + win_data.xdp_parent_wl_data.zxdg_exporter = wl_data.zxdg_exporter; + win_data.xdp_parent_wl_data.wl_surface = win_data.wl_surface; +#endif /* COG_HAVE_LIBPORTAL */ + const char *env_var; if ((env_var = g_getenv("COG_PLATFORM_WL_VIEW_FULLSCREEN")) && g_ascii_strtoll(env_var, NULL, 10) > 0) { win_data.is_maximized = false; @@ -2555,9 +2573,13 @@ on_show_option_menu(WebKitWebView *view, WebKitOptionMenu *menu, WebKitRectangle static void on_run_file_chooser(WebKitWebView *view, WebKitFileChooserRequest *request) { - /* TODO: Disable input of main window and keep this new file chooser - * window always on top. This could be done adding an XdpParent. */ - run_file_chooser(view, request, NULL); + g_autoptr(XdpParent) xdp_parent = NULL; + + if (win_data.xdp_parent_wl_data.zxdg_exporter && win_data.xdp_parent_wl_data.wl_surface) { + xdp_parent = xdp_parent_new_wl(&win_data.xdp_parent_wl_data); + } + + run_file_chooser(view, request, xdp_parent); } #endif /* COG_HAVE_LIBPORTAL */ diff --git a/platform/wayland/cog-xdp-parent-wl.c b/platform/wayland/cog-xdp-parent-wl.c new file mode 100644 index 00000000..32f66aeb --- /dev/null +++ b/platform/wayland/cog-xdp-parent-wl.c @@ -0,0 +1,54 @@ +/* + * cog-xdp-parent-wl.c + * Copyright (C) 2023 SUSE Software Solutions Germany GmbH + * + * Distributed under terms of the MIT license. + */ + +#include "cog-xdp-parent-wl.h" + +#include "../common/xdp-parent-private.h" + +static void +handle_exported(void *data, struct zxdg_exported_v2 *zxdg_exported_v2, const char *handle) +{ + XdpParent *parent = data; + struct xdp_parent_wl_data *wl_data = (struct xdp_parent_wl_data *) parent->data; + g_autofree char *handle_str = g_strdup_printf("wayland:%s", handle); + + parent->callback(parent, handle_str, wl_data->user_data); +} + +static const struct zxdg_exported_v2_listener zxdg_exported_listener = { + .handle = handle_exported, +}; + +static gboolean +xdp_parent_export_wl(XdpParent *parent, XdpParentExported callback, gpointer user_data) +{ + struct xdp_parent_wl_data *wl_data = (struct xdp_parent_wl_data *) parent->data; + + parent->callback = callback; + wl_data->user_data = user_data; + wl_data->zxdg_exported = zxdg_exporter_v2_export_toplevel(wl_data->zxdg_exporter, wl_data->wl_surface); + + return zxdg_exported_v2_add_listener(wl_data->zxdg_exported, &zxdg_exported_listener, parent); +} + +static void +xdp_parent_unexport_wl(XdpParent *parent) +{ + struct xdp_parent_wl_data *wl_data = (struct xdp_parent_wl_data *) parent->data; + + zxdg_exported_v2_destroy(wl_data->zxdg_exported); +} + +XdpParent * +xdp_parent_new_wl(struct xdp_parent_wl_data *wl_data) +{ + XdpParent *parent = g_new0(XdpParent, 1); + parent->parent_export = xdp_parent_export_wl; + parent->parent_unexport = xdp_parent_unexport_wl; + parent->data = (gpointer) wl_data; + return parent; +} diff --git a/platform/wayland/cog-xdp-parent-wl.h b/platform/wayland/cog-xdp-parent-wl.h new file mode 100644 index 00000000..0e2a18c6 --- /dev/null +++ b/platform/wayland/cog-xdp-parent-wl.h @@ -0,0 +1,25 @@ +/* + * cog-xdp-parent-wl.h + * Copyright (C) 2023 SUSE Software Solutions Germany GmbH + * + * Distributed under terms of the MIT license. + */ + +#pragma once + +#include + +#include "xdg-foreign-unstable-v2-client.h" + +G_BEGIN_DECLS + +struct xdp_parent_wl_data { + struct wl_surface *wl_surface; + struct zxdg_exporter_v2 *zxdg_exporter; + struct zxdg_exported_v2 *zxdg_exported; + gpointer user_data; +}; + +XdpParent *xdp_parent_new_wl(struct xdp_parent_wl_data *wl_data); + +G_END_DECLS diff --git a/platform/wayland/meson.build b/platform/wayland/meson.build index d219b181..c8582ad4 100644 --- a/platform/wayland/meson.build +++ b/platform/wayland/meson.build @@ -39,6 +39,7 @@ wayland_platform_protocols = { ['linux-dmabuf', 1], ['text-input', 1], ['text-input', 3], + ['xdg-foreign', 2], ], 'weston': wayland_platform_weston_protocols, } @@ -118,6 +119,10 @@ if wayland_cursor_dep.found() wayland_platform_c_args += ['-DCOG_USE_WAYLAND_CURSOR=1'] endif +if libportal_dep.found() + wayland_platform_sources += ['cog-xdp-parent-wl.c'] +endif + cc = meson.get_compiler('c') if cc.has_header_symbol('sys/mman.h', 'memfd_create', args : '-D_GNU_SOURCE') wayland_platform_c_args += ['-DHAVE_MEMFD_CREATE'] From cf8d6d8265e14196ecec8619c515b5d921051e4a Mon Sep 17 00:00:00 2001 From: Joan Torres Date: Fri, 6 Oct 2023 19:08:15 +0200 Subject: [PATCH 5/5] x11: Add an XdpParent on file chooser dialog This adds a new implementation of XdpParent. To get the "parent_window" is simpler, it's just the window_id which is the window property of xcb. --- platform/x11/cog-platform-x11.c | 10 +++++---- platform/x11/cog-xdp-parent-x11.c | 35 +++++++++++++++++++++++++++++++ platform/x11/cog-xdp-parent-x11.h | 17 +++++++++++++++ platform/x11/meson.build | 6 ++++++ 4 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 platform/x11/cog-xdp-parent-x11.c create mode 100644 platform/x11/cog-xdp-parent-x11.h diff --git a/platform/x11/cog-platform-x11.c b/platform/x11/cog-platform-x11.c index 910fd78c..c9695fb7 100644 --- a/platform/x11/cog-platform-x11.c +++ b/platform/x11/cog-platform-x11.c @@ -24,7 +24,9 @@ #endif /* COG_HAVE_LIBPORTAL */ #include "../common/cog-gl-utils.h" #include "../common/egl-proc-address.h" - +#if COG_HAVE_LIBPORTAL +# include "cog-xdp-parent-x11.h" +#endif /* COG_HAVE_LIBPORTAL */ #ifndef EGL_EXT_platform_base #define EGL_EXT_platform_base 1 @@ -880,9 +882,9 @@ cog_x11_platform_get_view_backend(CogPlatform *platform, WebKitWebView *related_ static void on_run_file_chooser(WebKitWebView *view, WebKitFileChooserRequest *request) { - /* TODO: Disable input of main window and keep this new file chooser - * window always on top. This could be done adding an XdpParent. */ - run_file_chooser(view, request, NULL); + g_autoptr(XdpParent) xdp_parent = xdp_parent_new_x11(&s_window->xcb.window); + + run_file_chooser(view, request, xdp_parent); } #endif /* COG_HAVE_LIBPORTAL */ diff --git a/platform/x11/cog-xdp-parent-x11.c b/platform/x11/cog-xdp-parent-x11.c new file mode 100644 index 00000000..940bc151 --- /dev/null +++ b/platform/x11/cog-xdp-parent-x11.c @@ -0,0 +1,35 @@ +/* + * cog-xdp-parent-x11.c + * Copyright (C) 2023 SUSE Software Solutions Germany GmbH + * + * Distributed under terms of the MIT license. + */ + +#include "cog-xdp-parent-x11.h" + +#include "../common/xdp-parent-private.h" + +static gboolean +xdp_parent_export_x11(XdpParent *parent, XdpParentExported callback, gpointer user_data) +{ + xcb_window_t *window_id = (xcb_window_t *) parent->data; + guint32 xid = (guint32) *window_id; + g_autofree char *handle = g_strdup_printf("x11:%x", xid); + callback(parent, handle, user_data); + return TRUE; +} + +static void +xdp_parent_unexport_x11(XdpParent *parent) +{ +} + +XdpParent * +xdp_parent_new_x11(xcb_window_t *window_id) +{ + XdpParent *parent = g_new0(XdpParent, 1); + parent->parent_export = xdp_parent_export_x11; + parent->parent_unexport = xdp_parent_unexport_x11; + parent->data = (gpointer) window_id; + return parent; +} diff --git a/platform/x11/cog-xdp-parent-x11.h b/platform/x11/cog-xdp-parent-x11.h new file mode 100644 index 00000000..27b47f8b --- /dev/null +++ b/platform/x11/cog-xdp-parent-x11.h @@ -0,0 +1,17 @@ +/* + * cog-xdp-parent-x11.h + * Copyright (C) 2023 SUSE Software Solutions Germany GmbH + * + * Distributed under terms of the MIT license. + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +XdpParent *xdp_parent_new_x11(xcb_window_t *window); + +G_END_DECLS diff --git a/platform/x11/meson.build b/platform/x11/meson.build index 80bc6e9c..bf34ff68 100644 --- a/platform/x11/meson.build +++ b/platform/x11/meson.build @@ -1,5 +1,11 @@ +x11_platform_sources = [] +if libportal_dep.found() + x11_platform_sources += ['cog-xdp-parent-x11.c'] +endif + x11_platform_plugin = shared_module('cogplatform-x11', 'cog-platform-x11.c', + x11_platform_sources, c_args: ['-DG_LOG_DOMAIN="Cog-X11"'], dependencies: [ wpebackend_fdo_dep,