Your message dated Wed, 08 Mar 2023 19:55:50 +0000
with message-id <e1pzzt8-005f79...@respighi.debian.org>
and subject line unblock gtk+3.0
has caused the Debian Bug report #1032450,
regarding unblock: gtk+3.0/3.24.37-2
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
1032450: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1032450
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
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.

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;

--- End Message ---
--- Begin Message ---
Unblocked.

--- End Message ---

Reply via email to