--- 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 ---