Control: tags -1 confirmed On 2023-03-07 01:12:58 +0000, Simon McVittie wrote: > Package: release.debian.org > Severity: normal > User: release.debian....@packages.debian.org > Usertags: unblock > X-Debbugs-Cc: gtk+...@packages.debian.org > Control: affects -1 + src:gtk+3.0 > > gtk+3.0_3.24.37 is in experimental at the moment, and we'd like to > include it in bookworm if possible. > > [ Reason ] > Resync with upstream release. What we have in bookworm at the moment > is GTK 3.24.36 and something like half of 3.24.37; rebasing on 3.24.37 > seems a better basis for a stable release.
Agreed. Please go ahead. Are there any other stable releases planned for the 3.24.x series during the freeze? Cheers > > We could apply selected changes from 3.24.37 as patches, but at some > point we're just reconstructing 3.24.37 with extra steps. > > [ Impact ] > Updating to the version in experimental will give us: > - support for transparent drag-and-drop of files between sandboxed > Flatpak GTK 3/GTK 4 apps (hopefully also Qt in future), and > non-sandboxed GTK 3 apps from Debian > - the upstream fix for an annoying regression where spurious startup > notifications appear in the GNOME top bar and newly-launched GTK 3 apps > don't reliably appear in Alt+Tab, replacing our previous > upstream-rejected workaround which didn't completely solve this > - various smaller bug fixes, some of which resolve potential crashes > > Also, the patches added in 3.24.36-3 and 3.24.36-4 are now part of the > upstream source, giving users a better picture of what version we're > actually providing. > > [ Tests ] > Installed in a GNOME desktop for manual testing with > no obvious regressions, and I can no longer reproduce > https://gitlab.gnome.org/GNOME/gtk/-/issues/5386. > > I was also able to drag-and-drop a file from Nautilus onto the > org.gtk.Demo4 Flatpak app from <https://wiki.gnome.org/Apps/Nightly> > (specifically the Clipboard window), where it appears as an > xdg-document-portal filename when dropped on the bottom half of the demo. > > autopkgtest reports one apparent regression for gnome-photos, but I think > it might be spurious (the test getting stuck). I'll try to investigate it > if it turns out to be reproducible. > > [ Risks ] > I wouldn't normally be adding the file transfer portal (drag-and-drop > to/from sandboxes) at this stage in the release cycle, but it's a good > feature to have if we want users to be able to run more sandboxed apps > over the next 2 years, and surprisingly little code. It does have one > potential interop issue (using a non-standard MIME type) which I've > reported upstream. I hope fixing that should be a simple change > (< 10 lines). > > Similarly I wouldn't normally be adding the changes in gdk/broadway/ at > this stage in the release cycle, but hardly anyone uses the GTK broadway > backend (it's a mechanism for displaying apps via a web browser) and > patching them out seems like it would be more disruptive than helpful. > > [ Checklist ] > [x] all changes are documented in the d/changelog > [x] I reviewed all changes and I approve them > [x] attach debdiff against the package in testing > > The attached diff is between the patched trees, excluding the actual > patches and some Windows- and macOS-specific changes to avoid noise. > I normally upload using dgit, so the contents of git and the debdiff > will match exactly. > diff --git a/NEWS b/NEWS > index fdd44e6e77..c4191123a9 100644 > --- a/NEWS > +++ b/NEWS > @@ -1,3 +1,25 @@ > +Overview of Changes in GTK+ 3.24.37, 02-03-2023 > +=============================================== > + > +* Support the file transfer portal for copy-paste and DND > + > +* Treat XKB_MODE_NAME_LODO as super key > + > +* Refactor startup notification handling to be in sync with GTK 4 > + > +* GL: Synchronie when calling MakeCurrent > + > +* CSS: Fix a problem with stopping animations > + > +* Wayland: Drop the legacy text input module > + > +* Windows: Set the default file extension in the native file chooser > + > +* Translation updates: > + Abkhazian > + Turkish > + > + > Overview of Changes in GTK+ 3.24.36, 12-22-2022 > =============================================== > > diff --git a/debian/changelog b/debian/changelog > index c7c69ef1c0..d115481e26 100644 > --- a/debian/changelog > +++ b/debian/changelog > @@ -1,3 +1,43 @@ > +gtk+3.0 (3.24.37-2) UNRELEASED; urgency=medium > + > + * d/copyright: Remove gtk-text-input.xml. > + This file is no longer present in the source package. > + * Remove Lintian overrides for lintian/lintian!452, no longer necessary > + > + -- Simon McVittie <s...@debian.org> Tue, 07 Mar 2023 00:07:09 +0000 > + > +gtk+3.0 (3.24.37-1) experimental; urgency=medium > + > + * New upstream release > + - Add support for xdg-desktop-portal file transfer API, allowing > + copy/paste and drag-and-drop of files where one of the apps involved > + is sandboxed by Flatpak, Snap or similar (GNOME/gtk!5554) > + - Fix a regression for startup notifications (GNOME/gtk!5581) > + - Fix potential invalid pointer dereference when checking whether a > + list store iterator is valid > + - Simple input method: Silence a warning from newer GLib by correctly > + returning a value from a task > + - Search engine: Reduce severity of the warning when Tracker > + initialization failed, avoiding crashes when run with > + G_DEBUG=fatal-criticals and without Tracker (GNOME/gtk!5490) > + - Wayland backend: Drop support for an obsolete text input protocol, > + which was only used by GNOME versions prior to Debian 10 > + - Broadway backend: Implement modal dialogs, preventing issues > + with focus loss in complex UIs (GNOME/gtk!3990) > + - Tests: Stop using GTestDBus, avoiding test timeouts if a dependency > + leaks a bus connection > + - Windows and macOS fixes not directly relevant to Debian > + * d/patches: Drop patches that were applied upstream > + * d/p/gdk-wayland-save-custom-xdg-activation-startup_id.patch, > + d/p/window-focus-on-window-show-for-wayland-activation.patch: > + Drop temporary fixes for GNOME/gtk#5386 (see 3.24.36-2, 3.24.35-3 > + changelogs). These were rejected upstream, and the change from > + GNOME/gtk!5581 included in 3.24.37 should fix the issue more > + correctly. > + * Upload to experimental for further testing > + > + -- Simon McVittie <s...@debian.org> Fri, 03 Mar 2023 20:27:28 +0000 > + > gtk+3.0 (3.24.36-4) unstable; urgency=medium > > * Team upload. > diff --git a/debian/copyright b/debian/copyright > index aad40ca787..215606a578 100644 > --- a/debian/copyright > +++ b/debian/copyright > @@ -461,7 +461,6 @@ Copyright: Copyright (C) 1992-1994 The Regents of the > University of California. > License: LGPL-2+ or SWL > > Files: > - modules/input/gtk-text-input.xml > modules/input/text-input-unstable-v3.xml > Copyright: > 2012-2013 Intel Corporation > diff --git a/debian/libgtk-3-dev.lintian-overrides > b/debian/libgtk-3-dev.lintian-overrides > deleted file mode 100644 > index 570f53b902..0000000000 > diff --git a/debian/patches/Fix-build_gir-logic.patch > b/debian/patches/Fix-build_gir-logic.patch > diff --git a/debian/patches/Fix-build_gir-logic.patch > b/debian/patches/Fix-build_gir-logic.patch > deleted file mode 100644 > index 221f07691a..0000000000 > diff --git > a/debian/patches/Fixes-incorrect-grabbing-behaviour-causing-subsequent-rej.patch > > b/debian/patches/Fixes-incorrect-grabbing-behaviour-causing-subsequent-rej.patch > diff --git > a/debian/patches/Fixes-incorrect-grabbing-behaviour-causing-subsequent-rej.patch > > b/debian/patches/Fixes-incorrect-grabbing-behaviour-causing-subsequent-rej.patch > deleted file mode 100644 > index 0b9f3dc23a..0000000000 > diff --git a/debian/patches/Mark-surface-as-dirty-before-flushing-it.patch > b/debian/patches/Mark-surface-as-dirty-before-flushing-it.patch > diff --git a/debian/patches/Mark-surface-as-dirty-before-flushing-it.patch > b/debian/patches/Mark-surface-as-dirty-before-flushing-it.patch > deleted file mode 100644 > index c0c97625b2..0000000000 > diff --git a/debian/patches/Remove-warning.patch > b/debian/patches/Remove-warning.patch > diff --git a/debian/patches/Remove-warning.patch > b/debian/patches/Remove-warning.patch > deleted file mode 100644 > index 557c93f3d9..0000000000 > diff --git > a/debian/patches/Take-UI-scale-into-acount-when-loading-image-missing-fall.patch > > b/debian/patches/Take-UI-scale-into-acount-when-loading-image-missing-fall.patch > diff --git > a/debian/patches/Take-UI-scale-into-acount-when-loading-image-missing-fall.patch > > b/debian/patches/Take-UI-scale-into-acount-when-loading-image-missing-fall.patch > deleted file mode 100644 > index 25f187035a..0000000000 > diff --git a/debian/patches/Treat-XKB_MOD_NAME_LOGO-as-super-key.patch > b/debian/patches/Treat-XKB_MOD_NAME_LOGO-as-super-key.patch > diff --git a/debian/patches/Treat-XKB_MOD_NAME_LOGO-as-super-key.patch > b/debian/patches/Treat-XKB_MOD_NAME_LOGO-as-super-key.patch > deleted file mode 100644 > index c3e79db53d..0000000000 > diff --git a/debian/patches/Update-Abkhazian-translation-1.patch > b/debian/patches/Update-Abkhazian-translation-1.patch > diff --git a/debian/patches/Update-Abkhazian-translation-1.patch > b/debian/patches/Update-Abkhazian-translation-1.patch > deleted file mode 100644 > index a1f9b65352..0000000000 > diff --git a/debian/patches/Update-Abkhazian-translation.patch > b/debian/patches/Update-Abkhazian-translation.patch > diff --git a/debian/patches/Update-Abkhazian-translation.patch > b/debian/patches/Update-Abkhazian-translation.patch > deleted file mode 100644 > index 8a6e2b5c0f..0000000000 > diff --git a/debian/patches/Update-Lithuanian-translation.patch > b/debian/patches/Update-Lithuanian-translation.patch > diff --git a/debian/patches/Update-Lithuanian-translation.patch > b/debian/patches/Update-Lithuanian-translation.patch > deleted file mode 100644 > index d675b6efc6..0000000000 > diff --git a/debian/patches/Update-Turkish-translation.patch > b/debian/patches/Update-Turkish-translation.patch > diff --git a/debian/patches/Update-Turkish-translation.patch > b/debian/patches/Update-Turkish-translation.patch > deleted file mode 100644 > index 1fb517febd..0000000000 > diff --git > a/debian/patches/gdk-wayland-Perform-xdg_activation-on-gdk_window_set_star.patch > > b/debian/patches/gdk-wayland-Perform-xdg_activation-on-gdk_window_set_star.patch > diff --git > a/debian/patches/gdk-wayland-Perform-xdg_activation-on-gdk_window_set_star.patch > > b/debian/patches/gdk-wayland-Perform-xdg_activation-on-gdk_window_set_star.patch > deleted file mode 100644 > index 2082fc190d..0000000000 > diff --git > a/debian/patches/gdk-wayland-save-custom-xdg-activation-startup_id.patch > b/debian/patches/gdk-wayland-save-custom-xdg-activation-startup_id.patch > diff --git > a/debian/patches/gdk-wayland-save-custom-xdg-activation-startup_id.patch > b/debian/patches/gdk-wayland-save-custom-xdg-activation-startup_id.patch > deleted file mode 100644 > index 0764693706..0000000000 > diff --git > a/debian/patches/gdk-wayland-set-requesting-surface-to-xdg-activation.patch > b/debian/patches/gdk-wayland-set-requesting-surface-to-xdg-activation.patch > diff --git > a/debian/patches/gdk-wayland-set-requesting-surface-to-xdg-activation.patch > b/debian/patches/gdk-wayland-set-requesting-surface-to-xdg-activation.patch > deleted file mode 100644 > index 63a5062878..0000000000 > diff --git > a/debian/patches/gdk-x11-Emit-remove-s-n-message-from-gdk_toplevel_set_sta.patch > > b/debian/patches/gdk-x11-Emit-remove-s-n-message-from-gdk_toplevel_set_sta.patch > diff --git > a/debian/patches/gdk-x11-Emit-remove-s-n-message-from-gdk_toplevel_set_sta.patch > > b/debian/patches/gdk-x11-Emit-remove-s-n-message-from-gdk_toplevel_set_sta.patch > deleted file mode 100644 > index f00f4e2b72..0000000000 > diff --git a/debian/patches/gl-Synchronize-when-calling-MakeCurrent.patch > b/debian/patches/gl-Synchronize-when-calling-MakeCurrent.patch > diff --git a/debian/patches/gl-Synchronize-when-calling-MakeCurrent.patch > b/debian/patches/gl-Synchronize-when-calling-MakeCurrent.patch > deleted file mode 100644 > index 43336ee28c..0000000000 > diff --git > a/debian/patches/gtkapplication-Do-not-call-gdk_display_notify_startup_com.patch > > b/debian/patches/gtkapplication-Do-not-call-gdk_display_notify_startup_com.patch > diff --git > a/debian/patches/gtkapplication-Do-not-call-gdk_display_notify_startup_com.patch > > b/debian/patches/gtkapplication-Do-not-call-gdk_display_notify_startup_com.patch > deleted file mode 100644 > index 341777c1ee..0000000000 > diff --git > a/debian/patches/gtkcssanimatedstyle-Fix-return-of-new_advance.patch > b/debian/patches/gtkcssanimatedstyle-Fix-return-of-new_advance.patch > diff --git > a/debian/patches/gtkcssanimatedstyle-Fix-return-of-new_advance.patch > b/debian/patches/gtkcssanimatedstyle-Fix-return-of-new_advance.patch > deleted file mode 100644 > index 387ee9e7d6..0000000000 > diff --git a/debian/patches/gtkwindow-Minor-refactor.patch > b/debian/patches/gtkwindow-Minor-refactor.patch > diff --git a/debian/patches/gtkwindow-Minor-refactor.patch > b/debian/patches/gtkwindow-Minor-refactor.patch > deleted file mode 100644 > index 6493ef7952..0000000000 > diff --git > a/debian/patches/gtkwindow-Shuffle-gdk_window_set_startup_id-calls.patch > b/debian/patches/gtkwindow-Shuffle-gdk_window_set_startup_id-calls.patch > diff --git > a/debian/patches/gtkwindow-Shuffle-gdk_window_set_startup_id-calls.patch > b/debian/patches/gtkwindow-Shuffle-gdk_window_set_startup_id-calls.patch > deleted file mode 100644 > index 95514796d6..0000000000 > diff --git a/debian/patches/series b/debian/patches/series > diff --git a/debian/patches/series b/debian/patches/series > index 324fadbe64..75e2a23964 100644 > --- a/debian/patches/series > +++ b/debian/patches/series > @@ -1,26 +1,5 @@ > -Fix-build_gir-logic.patch > -tests-make-accel-tests-easier-to-debug.patch > -Treat-XKB_MOD_NAME_LOGO-as-super-key.patch > -Update-Abkhazian-translation.patch > -Update-Abkhazian-translation-1.patch > -Update-Turkish-translation.patch > -gtkcssanimatedstyle-Fix-return-of-new_advance.patch > -Update-Lithuanian-translation.patch > -Take-UI-scale-into-acount-when-loading-image-missing-fall.patch > -gtkwindow-Minor-refactor.patch > -gdk-wayland-Perform-xdg_activation-on-gdk_window_set_star.patch > -gdk-x11-Emit-remove-s-n-message-from-gdk_toplevel_set_sta.patch > -gtkwindow-Shuffle-gdk_window_set_startup_id-calls.patch > -gtkapplication-Do-not-call-gdk_display_notify_startup_com.patch > -gl-Synchronize-when-calling-MakeCurrent.patch > -gdk-wayland-set-requesting-surface-to-xdg-activation.patch > -Fixes-incorrect-grabbing-behaviour-causing-subsequent-rej.patch > -Remove-warning.patch > 016_no_offscreen_widgets_grabbing.patch > 017_no_offscreen_device_grabbing.patch > 060_ignore-random-icons.patch > reftest_compare_surfaces-Report-how-much-the-images-diffe.patch > reftests-Allow-minor-differences-to-be-tolerated.patch > -window-focus-on-window-show-for-wayland-activation.patch > -gdk-wayland-save-custom-xdg-activation-startup_id.patch > -Mark-surface-as-dirty-before-flushing-it.patch > diff --git a/debian/patches/tests-make-accel-tests-easier-to-debug.patch > b/debian/patches/tests-make-accel-tests-easier-to-debug.patch > deleted file mode 100644 > index b2b33d2183..0000000000 > diff --git > a/debian/patches/window-focus-on-window-show-for-wayland-activation.patch > b/debian/patches/window-focus-on-window-show-for-wayland-activation.patch > diff --git > a/debian/patches/window-focus-on-window-show-for-wayland-activation.patch > b/debian/patches/window-focus-on-window-show-for-wayland-activation.patch > deleted file mode 100644 > index 4ad8445a22..0000000000 > diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides > diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides > deleted file mode 100644 > index 1b38d3611c..0000000000 > diff --git a/gdk/broadway/broadway-protocol.h > b/gdk/broadway/broadway-protocol.h > diff --git a/gdk/broadway/broadway-protocol.h > b/gdk/broadway/broadway-protocol.h > index 0e82e94297..2573e9083a 100644 > --- a/gdk/broadway/broadway-protocol.h > +++ b/gdk/broadway/broadway-protocol.h > @@ -157,7 +157,8 @@ typedef enum { > BROADWAY_REQUEST_GRAB_POINTER, > BROADWAY_REQUEST_UNGRAB_POINTER, > BROADWAY_REQUEST_FOCUS_WINDOW, > - BROADWAY_REQUEST_SET_SHOW_KEYBOARD > + BROADWAY_REQUEST_SET_SHOW_KEYBOARD, > + BROADWAY_REQUEST_SET_MODAL_HINT > } BroadwayRequestType; > > typedef struct { > @@ -231,6 +232,12 @@ typedef struct { > guint32 show_keyboard; > } BroadwayRequestSetShowKeyboard; > > +typedef struct { > + BroadwayRequestBase base; > + guint32 id; > + gboolean modal_hint; > +} BroadwayRequestSetModalHint; > + > typedef union { > BroadwayRequestBase base; > BroadwayRequestNewWindow new_window; > @@ -248,6 +255,7 @@ typedef union { > BroadwayRequestTranslate translate; > BroadwayRequestFocusWindow focus_window; > BroadwayRequestSetShowKeyboard set_show_keyboard; > + BroadwayRequestSetModalHint set_modal_hint; > } BroadwayRequest; > > typedef enum { > diff --git a/gdk/broadway/broadway-server.c b/gdk/broadway/broadway-server.c > index b53f4edf12..9b99dd66de 100644 > --- a/gdk/broadway/broadway-server.c > +++ b/gdk/broadway/broadway-server.c > @@ -113,6 +113,7 @@ struct BroadwayWindow { > gboolean is_temp; > gboolean visible; > gint32 transient_for; > + gboolean modal_hint; > > BroadwayBuffer *buffer; > gboolean buffer_synced; > @@ -276,6 +277,14 @@ update_event_state (BroadwayServer *server, > { > window->x = message->configure_notify.x; > window->y = message->configure_notify.y; > + > + if (server->focused_window_id != message->configure_notify.id && > + server->pointer_grab_window_id == -1 && window->modal_hint) > + { > + broadway_server_window_raise (server, message->configure_notify.id); > + broadway_server_focus_window (server, message->configure_notify.id); > + broadway_server_flush (server); > + } > } > break; > case BROADWAY_EVENT_DELETE_NOTIFY: > @@ -1435,6 +1444,7 @@ broadway_server_destroy_window (BroadwayServer *server, > gint id) > { > BroadwayWindow *window; > + gint transient_for = -1; > > if (server->mouse_in_toplevel_id == id) > { > @@ -1453,6 +1463,9 @@ broadway_server_destroy_window (BroadwayServer *server, > GINT_TO_POINTER (id)); > if (window != NULL) > { > + if (server->focused_window_id == id) > + transient_for = window->transient_for; > + > server->toplevels = g_list_remove (server->toplevels, window); > g_hash_table_remove (server->id_ht, > GINT_TO_POINTER (id)); > @@ -1463,6 +1476,17 @@ broadway_server_destroy_window (BroadwayServer *server, > > g_free (window); > } > + > + if (transient_for != -1) > + { > + window = g_hash_table_lookup (server->id_ht, > + GINT_TO_POINTER (transient_for)); > + if (window != NULL) > + { > + broadway_server_focus_window (server, transient_for); > + broadway_server_flush (server); > + } > + } > } > > gboolean > @@ -1588,6 +1612,20 @@ broadway_server_window_set_transient_for > (BroadwayServer *server, > } > } > > +void > +broadway_server_window_set_modal_hint (BroadwayServer *server, > + gint id, gboolean modal_hint) > +{ > + BroadwayWindow *window; > + > + window = g_hash_table_lookup (server->id_ht, > + GINT_TO_POINTER (id)); > + if (window == NULL) > + return; > + > + window->modal_hint = modal_hint; > +} > + > gboolean > broadway_server_has_client (BroadwayServer *server) > { > diff --git a/gdk/broadway/broadway-server.h b/gdk/broadway/broadway-server.h > index b5d319133a..d266685820 100644 > --- a/gdk/broadway/broadway-server.h > +++ b/gdk/broadway/broadway-server.h > @@ -95,5 +95,8 @@ cairo_surface_t * broadway_server_open_surface > (BroadwayServer *server, > char *name, > int width, > int height); > +void broadway_server_window_set_modal_hint (BroadwayServer > *server, > + gint id, > + gboolean > modal_hint); > > #endif /* __BROADWAY_SERVER__ */ > diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c > index 84a9c3f3c1..90f4d3206b 100644 > --- a/gdk/broadway/broadwayd.c > +++ b/gdk/broadway/broadwayd.c > @@ -301,6 +301,11 @@ client_handle_request (BroadwayClient *client, > case BROADWAY_REQUEST_SET_SHOW_KEYBOARD: > broadway_server_set_show_keyboard (server, > request->set_show_keyboard.show_keyboard); > break; > + case BROADWAY_REQUEST_SET_MODAL_HINT: > + broadway_server_window_set_modal_hint (server, > + request->set_modal_hint.id, > + > request->set_modal_hint.modal_hint); > + break; > default: > g_warning ("Unknown request of type %d", request->base.type); > } > diff --git a/gdk/broadway/gdkbroadway-server.c > b/gdk/broadway/gdkbroadway-server.c > index 2aa98abfab..9398428857 100644 > --- a/gdk/broadway/gdkbroadway-server.c > +++ b/gdk/broadway/gdkbroadway-server.c > @@ -523,6 +523,18 @@ _gdk_broadway_server_window_set_transient_for > (GdkBroadwayServer *server, > BROADWAY_REQUEST_SET_TRANSIENT_FOR); > } > > +void > +_gdk_broadway_server_window_set_modal_hint (GdkBroadwayServer *server, > + gint id, gboolean modal_hint) > +{ > + BroadwayRequestSetModalHint msg; > + > + msg.id = id; > + msg.modal_hint = modal_hint; > + gdk_broadway_server_send_message (server, msg, > + BROADWAY_REQUEST_SET_MODAL_HINT); > +} > + > static void * > map_named_shm (char *name, gsize size, gboolean *is_shm) > { > diff --git a/gdk/broadway/gdkbroadway-server.h > b/gdk/broadway/gdkbroadway-server.h > index 89a3076992..a961bb0358 100644 > --- a/gdk/broadway/gdkbroadway-server.h > +++ b/gdk/broadway/gdkbroadway-server.h > @@ -71,5 +71,8 @@ gboolean _gdk_broadway_server_window_move_resize > (GdkBroadwaySer > int > y, > int > width, > int > height); > +void _gdk_broadway_server_window_set_modal_hint > (GdkBroadwayServer *server, > + gint > id, > + gboolean > modal_hint); > > #endif /* __GDK_BROADWAY_SERVER__ */ > diff --git a/gdk/broadway/gdkeventsource.c b/gdk/broadway/gdkeventsource.c > index e946778483..07c74f6d43 100644 > --- a/gdk/broadway/gdkeventsource.c > +++ b/gdk/broadway/gdkeventsource.c > @@ -89,6 +89,24 @@ gdk_event_source_check (GSource *source) > return retval; > } > > +static void > +handle_focus_change (GdkEventCrossing *event) > +{ > + gboolean focus_in = (event->type != GDK_ENTER_NOTIFY); > + GdkEvent *focus_event; > + > + if (event->window->parent) { > + focus_event = gdk_event_new (GDK_FOCUS_CHANGE); > + focus_event->focus_change.window = g_object_ref > (event->window->parent); > + focus_event->focus_change.send_event = FALSE; > + focus_event->focus_change.in = focus_in; > + gdk_event_set_device (focus_event, gdk_event_get_device ((GdkEvent *) > event)); > + > + gdk_event_put (focus_event); > + gdk_event_free (focus_event); > + } > +} > + > void > _gdk_broadway_events_got_input (BroadwayInputMsg *message) > { > @@ -160,6 +178,8 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message) > gdk_event_set_device (event, device_manager->core_pointer); > gdk_event_set_seat (event, gdk_device_get_seat > (device_manager->core_pointer)); > > + handle_focus_change (&event->crossing); > + > node = _gdk_event_queue_append (display, event); > _gdk_windowing_got_event (display, node, event, message->base.serial); > } > diff --git a/gdk/broadway/gdkwindow-broadway.c > b/gdk/broadway/gdkwindow-broadway.c > index 32d1a0771c..39ef2ee353 100644 > --- a/gdk/broadway/gdkwindow-broadway.c > +++ b/gdk/broadway/gdkwindow-broadway.c > @@ -584,6 +584,15 @@ static void > gdk_broadway_window_set_modal_hint (GdkWindow *window, > gboolean modal) > { > + GdkBroadwayDisplay *display; > + GdkWindowImplBroadway *impl; > + > + impl = GDK_WINDOW_IMPL_BROADWAY (window->impl); > + > + impl->modal_hint = modal; > + > + display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (impl->wrapper)); > + _gdk_broadway_server_window_set_modal_hint (display->server, impl->id, > impl->modal_hint); > } > > static void > diff --git a/gdk/broadway/gdkwindow-broadway.h > b/gdk/broadway/gdkwindow-broadway.h > index f6a9ec1c65..ce1b3f1019 100644 > --- a/gdk/broadway/gdkwindow-broadway.h > +++ b/gdk/broadway/gdkwindow-broadway.h > @@ -73,6 +73,7 @@ struct _GdkWindowImplBroadway > > GdkGeometry geometry_hints; > GdkWindowHints geometry_hints_mask; > + gboolean modal_hint; > }; > > struct _GdkWindowImplBroadwayClass > diff --git a/gdk/wayland/gdkdisplay-wayland.c > b/gdk/wayland/gdkdisplay-wayland.c > index da366d7235..55c0388ec6 100644 > --- a/gdk/wayland/gdkdisplay-wayland.c > +++ b/gdk/wayland/gdkdisplay-wayland.c > @@ -952,13 +952,7 @@ gdk_wayland_display_notify_startup_complete (GdkDisplay > *display, > #ifdef HAVE_XDG_ACTIVATION > /* Will be signaled with focus activation */ > if (display_wayland->xdg_activation) > - { > - if (startup_id != NULL) > - { > - display_wayland->startup_notification_id = g_strdup (startup_id); > - } > - return; > - } > + return; > #endif > > if (startup_id == NULL) > diff --git a/gtk/filetransferportal.c b/gtk/filetransferportal.c > new file mode 100644 > index 0000000000..30afaeed97 > --- /dev/null > +++ b/gtk/filetransferportal.c > @@ -0,0 +1,498 @@ > +/* > + * Copyright (C) 2018 Matthias Clasen > + * > + * 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 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/>. > + */ > + > +#include "config.h" > + > +#include <errno.h> > + > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <fcntl.h> > + > +#include <gio/gio.h> > + > +#ifdef G_OS_UNIX > + > +#include <gio/gunixfdlist.h> > + > +#ifndef O_PATH > +#define O_PATH 0 > +#endif > + > +#ifndef O_CLOEXEC > +#define O_CLOEXEC 0 > +#else > +#define HAVE_O_CLOEXEC 1 > +#endif > + > +#include "filetransferportalprivate.h" > + > +static GDBusProxy *file_transfer_proxy = NULL; > + > +typedef struct { > + GTask *task; > + char **files; > + int len; > + int start; > +} AddFileData; > + > +static void > +free_add_file_data (gpointer data) > +{ > + AddFileData *afd = data; > + > + g_object_unref (afd->task); > + g_free (afd->files); > + g_free (afd); > +} > + > +static void add_files (GDBusProxy *proxy, > + AddFileData *afd); > + > +static void > +add_files_done (GObject *object, > + GAsyncResult *result, > + gpointer data) > +{ > + GDBusProxy *proxy = G_DBUS_PROXY (object); > + AddFileData *afd = data; > + GError *error = NULL; > + GVariant *ret; > + > + ret = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, NULL, result, > &error); > + if (ret == NULL) > + { > + g_task_return_error (afd->task, error); > + free_add_file_data (afd); > + return; > + } > + > + g_variant_unref (ret); > + > + if (afd->start >= afd->len) > + { > + g_task_return_boolean (afd->task, TRUE); > + free_add_file_data (afd); > + return; > + } > + > + add_files (proxy, afd); > +} > + > +/* We call AddFiles in chunks of 16 to avoid running into > + * the per-message fd limit of the bus. > + */ > +static void > +add_files (GDBusProxy *proxy, > + AddFileData *afd) > +{ > + GUnixFDList *fd_list; > + GVariantBuilder fds, options; > + int i; > + char *key; > + > + g_variant_builder_init (&fds, G_VARIANT_TYPE ("ah")); > + fd_list = g_unix_fd_list_new (); > + > + for (i = 0; afd->files[afd->start + i]; i++) > + { > + int fd; > + int fd_in; > + GError *error = NULL; > + > + if (i == 16) > + break; > + > + fd = open (afd->files[afd->start + i], O_PATH | O_CLOEXEC); > + if (fd == -1) > + { > + g_task_return_new_error (afd->task, G_IO_ERROR, > g_io_error_from_errno (errno), > + "Failed to open %s", > afd->files[afd->start + i]); > + free_add_file_data (afd); > + g_object_unref (fd_list); > + return; > + } > + > +#ifndef HAVE_O_CLOEXEC > + fcntl (fd, F_SETFD, FD_CLOEXEC); > +#endif > + fd_in = g_unix_fd_list_append (fd_list, fd, &error); > + close (fd); > + > + if (fd_in == -1) > + { > + g_task_return_error (afd->task, error); > + free_add_file_data (afd); > + g_object_unref (fd_list); > + return; > + } > + > + g_variant_builder_add (&fds, "h", fd_in); > + } > + > + afd->start += 16; > + > + key = (char *)g_object_get_data (G_OBJECT (afd->task), "key"); > + > + g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); > + g_dbus_proxy_call_with_unix_fd_list (proxy, > + "AddFiles", > + g_variant_new ("(saha{sv})", key, > &fds, &options), > + 0, -1, > + fd_list, > + NULL, > + add_files_done, afd); > + > + g_object_unref (fd_list); > +} > + > +static void > +start_session_done (GObject *object, > + GAsyncResult *result, > + gpointer data) > +{ > + GDBusProxy *proxy = G_DBUS_PROXY (object); > + AddFileData *afd = data; > + GError *error = NULL; > + GVariant *ret; > + const char *key; > + > + ret = g_dbus_proxy_call_finish (proxy, result, &error); > + if (ret == NULL) > + { > + g_task_return_error (afd->task, error); > + free_add_file_data (afd); > + return; > + } > + > + g_variant_get (ret, "(&s)", &key); > + > + g_object_set_data_full (G_OBJECT (afd->task), "key", g_strdup (key), > g_free); > + > + g_variant_unref (ret); > + > + add_files (proxy, afd); > +} > + > +void > +file_transfer_portal_register_files (const char **files, > + gboolean writable, > + GAsyncReadyCallback callback, > + gpointer data) > +{ > + GTask *task; > + AddFileData *afd; > + GVariantBuilder options; > + > + task = g_task_new (NULL, NULL, callback, data); > + > + if (file_transfer_proxy == NULL) > + { > + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, > + "No portal found"); > + g_object_unref (task); > + return; > + } > + > + afd = g_new (AddFileData, 1); > + afd->task = task; > + afd->files = g_strdupv ((char **)files); > + afd->len = g_strv_length (afd->files); > + afd->start = 0; > + > + g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); > + g_variant_builder_add (&options, "{sv}", "writable", g_variant_new_boolean > (writable)); > + g_variant_builder_add (&options, "{sv}", "autostop", g_variant_new_boolean > (TRUE)); > + > + g_dbus_proxy_call (file_transfer_proxy, "StartTransfer", > + g_variant_new ("(a{sv})", &options), > + 0, -1, NULL, start_session_done, afd); > +} > + > +gboolean > +file_transfer_portal_register_files_finish (GAsyncResult *result, > + char **key, > + GError **error) > +{ > + if (g_task_propagate_boolean (G_TASK (result), error)) > + { > + *key = g_strdup (g_object_get_data (G_OBJECT (result), "key")); > + return TRUE; > + } > + > + return FALSE; > +} > + > +char * > +file_transfer_portal_register_files_sync (const char **files, > + gboolean writable, > + GError **error) > +{ > + const char *value; > + char *key; > + GUnixFDList *fd_list; > + GVariantBuilder fds, options; > + int i; > + GVariant *ret; > + > + g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); > + ret = g_dbus_proxy_call_sync (file_transfer_proxy, > + "StartTransfer", > + g_variant_new ("(a{sv})", &options), > + 0, > + -1, > + NULL, > + error); > + if (ret == NULL) > + return NULL; > + > + g_variant_get (ret, "(&s)", &value); > + key = g_strdup (value); > + g_variant_unref (ret); > + > + fd_list = NULL; > + > + for (i = 0; files[i]; i++) > + { > + int fd; > + int fd_in; > + > + if (fd_list == NULL) > + { > + g_variant_builder_init (&fds, G_VARIANT_TYPE ("ah")); > + fd_list = g_unix_fd_list_new (); > + } > + > + fd = open (files[i], O_PATH | O_CLOEXEC); > + if (fd == -1) > + { > + g_set_error (error, > + G_IO_ERROR, g_io_error_from_errno (errno), > + "Failed to open %s", files[i]); > + g_variant_builder_clear (&fds); > + g_object_unref (fd_list); > + g_free (key); > + return NULL; > + } > + > +#ifndef HAVE_O_CLOEXEC > + fcntl (fd, F_SETFD, FD_CLOEXEC); > +#endif > + fd_in = g_unix_fd_list_append (fd_list, fd, error); > + close (fd); > + > + if (fd_in == -1) > + { > + g_variant_builder_clear (&fds); > + g_object_unref (fd_list); > + g_free (key); > + return NULL; > + } > + > + g_variant_builder_add (&fds, "h", fd_in); > + > + if ((i + 1) % 16 == 0 || files[i + 1] == NULL) > + { > + g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); > + ret = g_dbus_proxy_call_with_unix_fd_list_sync > (file_transfer_proxy, > + "AddFiles", > + g_variant_new > ("(saha{sv})", > + key, > + > &fds, > + > &options), > + 0, > + -1, > + fd_list, > + NULL, > + NULL, > + error); > + g_clear_object (&fd_list); > + > + if (ret == NULL) > + { > + g_free (key); > + return NULL; > + } > + > + g_variant_unref (ret); > + } > + } > + > + return key; > +} > + > +static void > +retrieve_files_done (GObject *object, > + GAsyncResult *result, > + gpointer data) > +{ > + GDBusProxy *proxy = G_DBUS_PROXY (object); > + GTask *task = data; > + GError *error = NULL; > + GVariant *ret; > + char **files; > + > + ret = g_dbus_proxy_call_finish (proxy, result, &error); > + if (ret == NULL) > + { > + g_task_return_error (task, error); > + g_object_unref (task); > + return; > + } > + > + g_variant_get (ret, "(^a&s)", &files); > + > + g_object_set_data_full (G_OBJECT (task), "files", g_strdupv (files), > (GDestroyNotify)g_strfreev); > + > + g_variant_unref (ret); > + > + g_task_return_boolean (task, TRUE); > +} > + > +void > +file_transfer_portal_retrieve_files (const char *key, > + GAsyncReadyCallback callback, > + gpointer data) > +{ > + GTask *task; > + GVariantBuilder options; > + > + task = g_task_new (NULL, NULL, callback, data); > + > + if (file_transfer_proxy == NULL) > + { > + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, > + "No portal found"); > + g_object_unref (task); > + return; > + } > + > + g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); > + g_dbus_proxy_call (file_transfer_proxy, > + "RetrieveFiles", > + g_variant_new ("(sa{sv})", key, &options), > + 0, -1, NULL, > + retrieve_files_done, task); > +} > + > +gboolean > +file_transfer_portal_retrieve_files_finish (GAsyncResult *result, > + char ***files, > + GError **error) > +{ > + if (g_task_propagate_boolean (G_TASK (result), error)) > + { > + *files = g_strdupv (g_object_get_data (G_OBJECT (result), "files")); > + return TRUE; > + } > + > + return FALSE; > +} > + > +char ** > +file_transfer_portal_retrieve_files_sync (const char *key, > + GError **error) > +{ > + GVariantBuilder options; > + GVariant *ret; > + char **files = NULL; > + > + g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); > + ret = g_dbus_proxy_call_sync (file_transfer_proxy, > + "RetrieveFiles", > + g_variant_new ("(sa{sv})", key, &options), > + 0, -1, NULL, > + error); > + if (ret) > + { > + const char **value; > + g_variant_get (ret, "(^a&s)", &value); > + files = g_strdupv ((char **)value); > + g_variant_unref (ret); > + } > + > + return files; > +} > + > +static void > +connection_closed (GDBusConnection *connection, > + gboolean remote_peer_vanished, > + GError *error) > +{ > + g_clear_object (&file_transfer_proxy); > +} > + > +static void > +finish_registration (void) > +{ > + /* Free the singleton when the connection closes, important for test */ > + g_signal_connect (g_dbus_proxy_get_connection (G_DBUS_PROXY > (file_transfer_proxy)), > + "closed", G_CALLBACK (connection_closed), NULL); > +} > + > +static gboolean > +proxy_has_owner (GDBusProxy *proxy) > +{ > + char *owner; > + > + owner = g_dbus_proxy_get_name_owner (proxy); > + if (owner) > + { > + g_free (owner); > + return TRUE; > + } > + > + return FALSE; > +} > + > +void > +file_transfer_portal_register (void) > +{ > + static gboolean called; > + > + if (!called) > + { > + called = TRUE; > + > + file_transfer_proxy = g_dbus_proxy_new_for_bus_sync > (G_BUS_TYPE_SESSION, > + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES > + | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS > + | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, > + NULL, > + "org.freedesktop.portal.Documents", > + "/org/freedesktop/portal/documents", > + "org.freedesktop.portal.FileTransfer", > + NULL, > + NULL); > + > + if (file_transfer_proxy && !proxy_has_owner (file_transfer_proxy)) > + g_clear_object (&file_transfer_proxy); > + > + if (file_transfer_proxy) > + finish_registration (); > + } > +} > + > +gboolean > +file_transfer_portal_supported (void) > +{ > + file_transfer_portal_register (); > + > + return file_transfer_proxy != NULL; > +} > + > +#endif /* G_OS_UNIX */ > diff --git a/gtk/filetransferportalprivate.h b/gtk/filetransferportalprivate.h > new file mode 100644 > index 0000000000..d136b53345 > --- /dev/null > +++ b/gtk/filetransferportalprivate.h > @@ -0,0 +1,49 @@ > +/* > + * Copyright (C) 2018 Matthias Clasen > + * > + * 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 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/>. > + */ > + > +#ifndef __FILE_TRANSFER_PROTOCOL_H__ > +#define __FILE_TRANSFER_PROTOCOL_H__ > + > + > +void file_transfer_portal_register (void); > + > +void file_transfer_portal_register_files (const char > **files, > + gboolean > writable, > + GAsyncReadyCallback > callback, > + gpointer > data); > +gboolean file_transfer_portal_register_files_finish (GAsyncResult > *result, > + char > **key, > + GError > **error); > + > +void file_transfer_portal_retrieve_files (const char > *key, > + GAsyncReadyCallback > callback, > + gpointer > data); > +gboolean file_transfer_portal_retrieve_files_finish (GAsyncResult > *result, > + char > ***files, > + GError > **error); > + > + > +char * file_transfer_portal_register_files_sync (const char > **files, > + gboolean > writable, > + GError > **error); > + > +char ** file_transfer_portal_retrieve_files_sync (const char > *key, > + GError > **error); > + > +gboolean file_transfer_portal_supported (void); > + > +#endif > diff --git a/gtk/gtkfilechoosernativewin32.c b/gtk/gtkfilechoosernativewin32.c > index bec7ca4be3..d2f1769210 100644 > --- a/gtk/gtkfilechoosernativewin32.c > +++ b/gtk/gtkfilechoosernativewin32.c > @@ -610,6 +610,10 @@ filechooser_win32_thread (gpointer _data) > if (FAILED (hr)) > g_warning_hr ("Can't set file types", hr); > > + hr = IFileDialog_SetDefaultExtension (pfd, L""); > + if (FAILED (hr)) > + g_warning_hr ("Can't set default extension", hr); > + > if (data->self->current_filter) > { > GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER > (data->self)); > diff --git a/gtk/gtkimcontextsimple.c b/gtk/gtkimcontextsimple.c > index a788426ceb..ccf9687ba6 100644 > --- a/gtk/gtkimcontextsimple.c > +++ b/gtk/gtkimcontextsimple.c > @@ -253,6 +253,8 @@ init_compose_table_thread_cb (GTask *task, > return; > > gtk_im_context_simple_init_compose_table (); > + > + g_task_return_boolean (task, TRUE); > } > > static void > diff --git a/gtk/gtkliststore.c b/gtk/gtkliststore.c > index e4c50e6aae..7fac96ad72 100644 > --- a/gtk/gtkliststore.c > +++ b/gtk/gtkliststore.c > @@ -1454,10 +1454,34 @@ gboolean > gtk_list_store_iter_is_valid (GtkListStore *list_store, > GtkTreeIter *iter) > { > + GtkListStorePrivate *priv; > + GSequenceIter *seq_iter; > + > g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE); > g_return_val_if_fail (iter != NULL, FALSE); > > - return iter_is_valid (iter, list_store); > + /* can't use iter_is_valid() here, because iter might point > + * to random memory. > + * > + * We MUST NOT dereference it. > + */ > + > + priv = list_store->priv; > + > + if (iter == NULL || > + iter->user_data == NULL || > + priv->stamp != iter->stamp) > + return FALSE; > + > + for (seq_iter = g_sequence_get_begin_iter (priv->seq); > + !g_sequence_iter_is_end (seq_iter); > + seq_iter = g_sequence_iter_next (seq_iter)) > + { > + if (seq_iter == iter->user_data) > + return TRUE; > + } > + > + return FALSE; > } > > static gboolean real_gtk_list_store_row_draggable (GtkTreeDragSource > *drag_source, > diff --git a/gtk/gtksearchenginetracker3.c b/gtk/gtksearchenginetracker3.c > index bbc2a7752d..3f054110b5 100644 > --- a/gtk/gtksearchenginetracker3.c > +++ b/gtk/gtksearchenginetracker3.c > @@ -100,8 +100,11 @@ finalize (GObject *object) > g_clear_object (&engine->search_query); > g_clear_object (&engine->search_location_query); > g_clear_object (&engine->file_check_query); > - tracker_sparql_connection_close (engine->sparql_conn); > - g_clear_object (&engine->sparql_conn); > + if (engine->sparql_conn != NULL) > + { > + tracker_sparql_connection_close (engine->sparql_conn); > + g_clear_object (&engine->sparql_conn); > + } > > G_OBJECT_CLASS (gtk_search_engine_tracker3_parent_class)->finalize > (object); > } > @@ -391,8 +394,8 @@ gtk_search_engine_tracker3_new (void) > NULL, &error, NULL); > if (!engine) > { > - g_critical ("Could not init tracker3 search engine: %s", > - error->message); > + g_warning ("Could not init tracker3 search engine: %s", > + error->message); > g_error_free (error); > } > > diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c > index 32d9de88bf..048b4ad496 100644 > --- a/gtk/gtkselection.c > +++ b/gtk/gtkselection.c > @@ -116,6 +116,10 @@ > #include "broadway/gdkbroadway.h" > #endif > > +#ifndef G_OS_WIN32 > +#include "filetransferportalprivate.h" > +#endif > + > #undef DEBUG_SELECTION > > /* Maximum size of a sent chunk, in bytes. Also the default size of > @@ -338,6 +342,7 @@ static GdkAtom text_plain_atom; > static GdkAtom text_plain_utf8_atom; > static GdkAtom text_plain_locale_atom; > static GdkAtom text_uri_list_atom; > +static GdkAtom portal_files_atom; > > static void > init_atoms (void) > @@ -358,6 +363,7 @@ init_atoms (void) > g_free (tmp); > > text_uri_list_atom = gdk_atom_intern_static_string ("text/uri-list"); > + portal_files_atom = gdk_atom_intern_static_string > ("application/vnd.portal.files"); > } > } > > @@ -502,6 +508,10 @@ gtk_target_list_add_image_targets (GtkTargetList *list, > * Appends the URI targets supported by #GtkSelectionData to > * the target list. All targets are added with the same @info. > * > + * Since 3.24.37, this includes the application/vnd.portal.files > + * target when possible, to allow sending files between sandboxed > + * apps via the FileTransfer portal. > + * > * Since: 2.6 > **/ > void > @@ -512,7 +522,12 @@ gtk_target_list_add_uri_targets (GtkTargetList *list, > > init_atoms (); > > - gtk_target_list_add (list, text_uri_list_atom, 0, info); > + gtk_target_list_add (list, text_uri_list_atom, 0, info); > + > +#ifndef G_OS_WIN32 > + if (file_transfer_portal_supported ()) > + gtk_target_list_add (list, portal_files_atom, 0, info); > +#endif > } > > /** > @@ -1835,6 +1850,9 @@ gtk_selection_data_get_pixbuf (const GtkSelectionData > *selection_data) > * Sets the contents of the selection from a list of URIs. > * The string is converted to the form determined by > * @selection_data->target. > + * > + * Since 3.24.37, this may involve using the FileTransfer > + * portal to send files between sandboxed apps. > * > * Returns: %TRUE if the selection was successfully set, > * otherwise %FALSE. > @@ -1880,6 +1898,57 @@ gtk_selection_data_set_uris (GtkSelectionData > *selection_data, > return TRUE; > } > } > +#ifndef G_OS_WIN32 > + else if (selection_data->target == portal_files_atom && > + file_transfer_portal_supported ()) > + { > + GPtrArray *a; > + char **files; > + char *key; > + GError *error = NULL; > + > + a = g_ptr_array_new (); > + > + for (int i = 0; uris[i]; i++) > + { > + GFile *file; > + char *path; > + > + file = g_file_new_for_uri (uris[i]); > + path = g_file_get_path (file); > + g_object_unref (file); > + > + if (path == NULL) > + { > + g_ptr_array_unref (a); > + return FALSE; > + } > + > + g_ptr_array_add (a, path); > + } > + > + g_ptr_array_add (a, NULL); > + files = (char **) g_ptr_array_free (a, FALSE); > + > + key = file_transfer_portal_register_files_sync ((const char **)files, > TRUE, &error); > + if (key == NULL) > + { > + g_strfreev (files); > + g_warning ("%s", error->message); > + g_error_free (error); > + return FALSE; > + } > + > + gtk_selection_data_set (selection_data, > + portal_files_atom, > + 8, (guchar *)key, strlen (key)); > + > + g_strfreev (files); > + g_free (key); > + > + return TRUE; > + } > +#endif > > return FALSE; > } > @@ -1890,6 +1959,9 @@ gtk_selection_data_set_uris (GtkSelectionData > *selection_data, > * > * Gets the contents of the selection data as array of URIs. > * > + * Since 3.24.37, this may involve using the FileTransfer > + * portal to send files between sandboxed apps. > + * > * Returns: (array zero-terminated=1) (element-type utf8) (transfer full): > if > * the selection data contains a list of > * URIs, a newly allocated %NULL-terminated string array > @@ -1922,6 +1994,40 @@ gtk_selection_data_get_uris (const GtkSelectionData > *selection_data) > > g_strfreev (list); > } > +#ifndef G_OS_WIN32 > + else if (selection_data->length >= 0 && > + selection_data->type == portal_files_atom && > + file_transfer_portal_supported ()) > + { > + char *key; > + GError *error = NULL; > + char **files; > + > + key = g_strndup ((char *) selection_data->data, > selection_data->length); > + files = file_transfer_portal_retrieve_files_sync (key, &error); > + if (error) > + { > + g_warning ("%s", error->message); > + g_error_free (error); > + } > + g_free (key); > + > + if (files) > + { > + GPtrArray *uris = g_ptr_array_new (); > + > + for (int i = 0; files[i]; i++) > + { > + GFile *file = g_file_new_for_path (files[i]); > + g_ptr_array_add (uris, g_file_get_uri (file)); > + g_object_unref (file); > + } > + > + g_ptr_array_add (uris, NULL); > + result = (char **) g_ptr_array_free (uris, FALSE); > + } > + } > +#endif > > return result; > } > @@ -2246,7 +2352,8 @@ gtk_targets_include_uri (GdkAtom *targets, > > for (i = 0; i < n_targets; i++) > { > - if (targets[i] == text_uri_list_atom) > + if (targets[i] == text_uri_list_atom || > + targets[i] == portal_files_atom) > { > result = TRUE; > break; > diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c > index ded0a8e23b..39b01eeb66 100644 > --- a/gtk/gtkwindow.c > +++ b/gtk/gtkwindow.c > @@ -6227,16 +6227,6 @@ gtk_window_show (GtkWidget *widget) > > if (priv->modal) > gtk_grab_add (widget); > - > -#ifdef GDK_WINDOWING_WAYLAND > - if (GDK_IS_WAYLAND_WINDOW (gtk_widget_get_window (widget))) > - { > - // Submits the activation token / startup id to the compositor > - gdk_window_focus (gtk_widget_get_window (widget), > priv->initial_timestamp); > - // Use gtk_window_present's timestamp only once > - priv->initial_timestamp = GDK_CURRENT_TIME; > - } > -#endif > } > > static void > @@ -6297,19 +6287,23 @@ gtk_window_notify_startup (GtkWindow *window) > !GTK_IS_OFFSCREEN_WINDOW (window) && > priv->type != GTK_WINDOW_POPUP) > { > + GdkWindow *gdk_window; > + > + gdk_window = _gtk_widget_get_window (GTK_WIDGET (window)); > + > /* Do we have a custom startup-notification id? */ > if (priv->startup_id != NULL) > { > /* Make sure we have a "real" id */ > if (!startup_id_is_fake (priv->startup_id)) > - gdk_notify_startup_complete_with_id (priv->startup_id); > + gdk_window_set_startup_id (gdk_window, priv->startup_id); > > g_free (priv->startup_id); > priv->startup_id = NULL; > } > else > { > - gdk_notify_startup_complete (); > + gdk_window_set_startup_id (gdk_window, NULL); > } > } > } > diff --git a/gtk/meson.build b/gtk/meson.build > index 21540dd93b..4b7a453e11 100644 > --- a/gtk/meson.build > +++ b/gtk/meson.build > @@ -659,6 +659,10 @@ if os_unix and tracker3_enabled > gtk_unix_sources += 'gtksearchenginetracker3.c' > endif > > +if os_unix > + gtk_unix_sources += 'filetransferportal.c' > +endif > + > if os_unix > gtk_sources += gtk_unix_sources > endif > diff --git a/meson.build b/meson.build > index 6c711e9e9a..5444fa112e 100644 > --- a/meson.build > +++ b/meson.build > @@ -1,5 +1,5 @@ > project('gtk+', 'c', > - version: '3.24.36', > + version: '3.24.37', > default_options: [ > 'buildtype=debugoptimized', > 'warning_level=1' > @@ -706,7 +706,6 @@ endif > > proto_sources = [ > 'text-input-unstable-v3', > - 'gtk-text-input', > ] > proto_sources_outputs = [] > > @@ -760,7 +759,6 @@ immodules = [ > [ 'ime', files([ immodule_srcdir + 'gtkimcontextime.c', immodule_srcdir + > 'imime.c' ]), win32_enabled ], > [ 'quartz', files([ immodule_srcdir + 'imquartz.c' ]), quartz_enabled, [ > '-xobjective-c' ] ], > [ 'wayland', files([ immodule_srcdir + 'imwayland.c' ]) + > proto_sources_outputs[0], wayland_enabled ], > - [ 'waylandgtk', files([ immodule_srcdir + 'imwaylandgtk.c']) + > proto_sources_outputs[1], wayland_enabled ], > [ 'xim', files([ immodule_srcdir + 'gtkimcontextxim.c', immodule_srcdir + > 'imxim.c' ]), x11_enabled ], > ] > > diff --git a/modules/input/gtk-text-input.xml > b/modules/input/gtk-text-input.xml > deleted file mode 100644 > index a134a19f61..0000000000 > diff --git a/modules/input/imwaylandgtk.c b/modules/input/imwaylandgtk.c > diff --git a/modules/input/imwaylandgtk.c b/modules/input/imwaylandgtk.c > deleted file mode 100644 > index 207891d502..0000000000 > diff --git a/po-properties/POTFILES.in b/po-properties/POTFILES.in > diff --git a/po-properties/POTFILES.in b/po-properties/POTFILES.in > index 8dae6a5f76..3773004d9b 100644 > --- a/po-properties/POTFILES.in > +++ b/po-properties/POTFILES.in > @@ -344,7 +344,6 @@ modules/input/imti-er.c > modules/input/imti-et.c > modules/input/imviqr.c > modules/input/imwayland.c > -modules/input/imwaylandgtk.c > modules/input/imxim.c > modules/printbackends/cups/gtkprintbackendcups.c > modules/printbackends/cups/gtkprintercups.c > diff --git a/po/POTFILES.in b/po/POTFILES.in > index cb09da8767..5183c57c27 100644 > --- a/po/POTFILES.in > +++ b/po/POTFILES.in > @@ -395,7 +395,6 @@ modules/input/imti-er.c > modules/input/imti-et.c > modules/input/imviqr.c > modules/input/imwayland.c > -modules/input/imwaylandgtk.c > modules/input/imxim.c > modules/printbackends/cups/gtkprintbackendcups.c > modules/printbackends/cups/gtkprintercups.c > diff --git a/tests/meson.build b/tests/meson.build > index 586fe2f45e..6ff249f8a1 100644 > --- a/tests/meson.build > +++ b/tests/meson.build > @@ -36,7 +36,7 @@ gtk_tests = [ > ['testcombo'], > ['testcombochange'], > ['testdialog'], > - ['testdnd'], > + ['testdnd2'], > ['testellipsise'], > ['testemblems'], > ['testentrycompletion'], > @@ -45,6 +45,7 @@ gtk_tests = [ > ['testexpander'], > ['testfilechooserbutton'], > ['testfilechooser'], > + ['testfileportal'], > ['testflowbox'], > ['testfontchooser'], > ['testfontoptions'], > diff --git a/tests/testfileportal.c b/tests/testfileportal.c > new file mode 100644 > index 0000000000..0918af1d1b > --- /dev/null > +++ b/tests/testfileportal.c > @@ -0,0 +1,130 @@ > +/* simple.c > + * Copyright (C) 1997 Red Hat, Inc > + * Author: Elliot Lee > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Library General Public > + * License as published by the Free Software Foundation; either > + * version 2 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 > + * Library General Public License for more details. > + * > + * You should have received a copy of the GNU Library General Public > + * License along with this library. If not, see > <http://www.gnu.org/licenses/>. > + */ > +#include "config.h" > +#include <gtk/gtk.h> > + > +static void > +drag_begin_cb (GtkWidget *widget, > + GdkDragContext *context, > + gpointer data) > +{ > + char **uris; > + char *cwd; > + > + cwd = g_get_current_dir (); > + uris = g_new0 (char *, 2); > + uris[0] = g_strconcat ("file://", cwd, "/README.md", NULL); > + g_free (cwd); > + > + g_signal_handlers_disconnect_by_func (widget, drag_begin_cb, NULL); > + gtk_drag_set_icon_default (context); > + > + g_object_set_data_full (G_OBJECT (widget), "uris", g_strdupv ((char > **)uris), (GDestroyNotify) g_strfreev); > +} > + > +static void > +drag_data_get (GtkWidget *widget, > + GdkDragContext *context, > + GtkSelectionData *selection, > + unsigned int target_info, > + unsigned int time, > + gpointer data) > +{ > + char **uris = (char **)g_object_get_data (G_OBJECT (widget), "uris"); > + > + gtk_selection_data_set_uris (selection, uris); > + > + g_object_set_data (G_OBJECT (widget), "uris", NULL); > +} > + > +static void > +drag_data_received (GtkWidget *widget, > + GdkDragContext *context, > + int x, > + int y, > + GtkSelectionData *selection_data, > + unsigned int info, > + unsigned int time, > + gpointer user_data) > +{ > + GtkLabel *label = user_data; > + char **uris; > + > + uris = gtk_selection_data_get_uris (selection_data); > + > + if (uris) > + { > + gtk_label_set_label (label, uris[0]); > + g_strfreev (uris); > + } > +} > + > +int > +main (int argc, char *argv[]) > +{ > + GtkWidget *window, *label, *eventbox, *box; > + GtkTargetEntry targets[] = { > + { "application/vnd.portal.files", 0, 0 }, > + }; > + > + gtk_init (&argc, &argv); > + > + window = g_object_connect (g_object_new (gtk_window_get_type (), > + "type", GTK_WINDOW_TOPLEVEL, > + "title", "hello world", > + "resizable", FALSE, > + "border_width", 10, > + NULL), > + "signal::destroy", gtk_main_quit, NULL, > + NULL); > + > + box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); > + gtk_widget_show (box); > + gtk_container_add (GTK_CONTAINER (window), box); > + > + eventbox = gtk_event_box_new (); > + gtk_container_add (GTK_CONTAINER (box), eventbox); > + gtk_widget_show (eventbox); > + gtk_event_box_set_above_child (GTK_EVENT_BOX (eventbox), TRUE); > + > + label = gtk_label_new ("drag me"); > + gtk_container_add (GTK_CONTAINER (eventbox), label); > + > + gtk_drag_source_set (eventbox, GDK_BUTTON1_MASK, targets, G_N_ELEMENTS > (targets), GDK_ACTION_COPY); > + g_signal_connect (eventbox, "drag-begin", G_CALLBACK (drag_begin_cb), > NULL); > + g_signal_connect (eventbox, "drag-data-get", G_CALLBACK (drag_data_get), > NULL); > + gtk_widget_show (label); > + > + eventbox = gtk_event_box_new (); > + gtk_container_add (GTK_CONTAINER (box), eventbox); > + gtk_widget_show (eventbox); > + gtk_event_box_set_above_child (GTK_EVENT_BOX (eventbox), TRUE); > + > + label = gtk_label_new ("drop here"); > + gtk_widget_show (label); > + gtk_container_add (GTK_CONTAINER (eventbox), label); > + gtk_drag_dest_set (eventbox, GTK_DEST_DEFAULT_ALL, targets, G_N_ELEMENTS > (targets), GDK_ACTION_COPY); > + > + g_signal_connect (eventbox, "drag-data-received", G_CALLBACK > (drag_data_received), label); > + > + gtk_widget_show (window); > + > + gtk_main (); > + > + return 0; > +} > diff --git a/testsuite/gtk/defaultvalue.c b/testsuite/gtk/defaultvalue.c > index a82788b7e4..7ed024d312 100644 > --- a/testsuite/gtk/defaultvalue.c > +++ b/testsuite/gtk/defaultvalue.c > @@ -458,9 +458,6 @@ main (int argc, char **argv) > const GType *otypes; > guint i; > gchar *schema_dir; > - GTestDBus *bus; > - GMainLoop *loop; > - gint result; > > /* These must be set before before gtk_test_init */ > g_setenv ("GIO_USE_VFS", "local", TRUE); > @@ -475,12 +472,6 @@ main (int argc, char **argv) > if (g_getenv ("GTK_TEST_MESON") == NULL) > g_setenv ("GSETTINGS_SCHEMA_DIR", schema_dir, TRUE); > > - /* Create one test bus for all tests, as we have a lot of very small > - * and quick tests. > - */ > - bus = g_test_dbus_new (G_TEST_DBUS_NONE); > - g_test_dbus_up (bus); > - > otypes = gtk_test_list_all_types (NULL); > for (i = 0; otypes[i]; i++) > { > @@ -497,19 +488,5 @@ main (int argc, char **argv) > g_free (testname); > } > > - result = g_test_run(); > - > - /* Work around the annoying issue that g_test_dbus_down is giving > - * us an "Error while sending AddMatch" that comes out of an idle > - */ > - loop = g_main_loop_new (NULL, FALSE); > - g_timeout_add (1000, (GSourceFunc)g_main_loop_quit, loop); > - g_main_loop_run (loop); > - g_main_loop_unref (loop); > - > - g_test_dbus_down (bus); > - g_object_unref (bus); > - g_free (schema_dir); > - > - return result; > + return g_test_run(); > } > diff --git a/testsuite/gtk/objects-finalize.c > b/testsuite/gtk/objects-finalize.c > index 24540e313f..95b565c591 100644 > --- a/testsuite/gtk/objects-finalize.c > +++ b/testsuite/gtk/objects-finalize.c > @@ -79,8 +79,7 @@ main (int argc, char **argv) > const GType *all_types; > guint n_types = 0, i; > gchar *schema_dir; > - GTestDBus *bus; > - gint result; > + int result; > > /* These must be set before before gtk_test_init */ > g_setenv ("GIO_USE_VFS", "local", TRUE); > @@ -95,12 +94,6 @@ main (int argc, char **argv) > if (g_getenv ("GTK_TEST_MESON") == NULL) > g_setenv ("GSETTINGS_SCHEMA_DIR", schema_dir, TRUE); > > - /* Create one test bus for all tests, as we have a lot of very small > - * and quick tests. > - */ > - bus = g_test_dbus_new (G_TEST_DBUS_NONE); > - g_test_dbus_up (bus); > - > all_types = gtk_test_list_all_types (&n_types); > > for (i = 0; i < n_types; i++) > @@ -133,8 +126,6 @@ main (int argc, char **argv) > > result = g_test_run(); > > - g_test_dbus_down (bus); > - g_object_unref (bus); > g_free (schema_dir); > > return result; -- Sebastian Ramacher