xdg-desktop-portal-gnome/0011-fix-window-screencast-...

391 lines
11 KiB
Diff

diff --git a/src/screencast.c b/src/screencast.c
index 6b0014a..15f6a80 100644
--- a/src/screencast.c
+++ b/src/screencast.c
@@ -427,16 +427,20 @@ find_best_window_by_app_id_and_title (const char *app_id,
const char *title)
{
ShellIntrospect *shell_introspect = shell_introspect_get ();
+ GPtrArray *windows;
Window *best_match;
glong best_match_distance;
- GList *l;
best_match = NULL;
best_match_distance = G_MAXLONG;
- for (l = shell_introspect_get_windows (shell_introspect); l; l = l->next)
+ shell_introspect_ref_listeners (shell_introspect);
+ shell_introspect_wait_for_windows (shell_introspect);
+
+ windows = shell_introspect_get_windows (shell_introspect);
+ for (size_t i = 0; windows && i < windows->len; i++)
{
- Window *window = l->data;
+ Window *window = g_ptr_array_index (windows, i);
glong distance;
if (g_strcmp0 (window_get_app_id (window), app_id) != 0)
@@ -454,6 +458,8 @@ find_best_window_by_app_id_and_title (const char *app_id,
}
}
+ shell_introspect_unref_listeners (shell_introspect);
+
/* If even the best match's window title is too different, don't
* restore it.
*/
diff --git a/src/screencastwidget.c b/src/screencastwidget.c
index 9b30f2d..e95fee2 100644
--- a/src/screencastwidget.c
+++ b/src/screencastwidget.c
@@ -164,8 +164,7 @@ update_windows_list (ScreenCastWidget *widget)
GtkListBox *window_list = GTK_LIST_BOX (widget->window_list);
GtkWidget *toplevel;
GtkWidget *child;
- GList *windows;
- GList *l;
+ GPtrArray *windows;
child = gtk_widget_get_first_child (GTK_WIDGET (window_list));
while (child)
@@ -181,9 +180,9 @@ update_windows_list (ScreenCastWidget *widget)
return;
windows = shell_introspect_get_windows (widget->shell_introspect);
- for (l = windows; l; l = l->next)
+ for (size_t i = 0; windows && i < windows->len; i++)
{
- Window *window = l->data;
+ Window *window = g_ptr_array_index (windows, i);
GtkWidget *window_widget;
if (should_skip_window (window, GTK_WINDOW (toplevel)))
diff --git a/src/shellintrospect.c b/src/shellintrospect.c
index 1fa8b93..c2b288d 100644
--- a/src/shellintrospect.c
+++ b/src/shellintrospect.c
@@ -22,16 +22,6 @@
#include "shell-dbus.h"
#include "shellintrospect.h"
-enum
-{
- WINDOWS_CHANGED,
- ANIMATIONS_ENABLED_CHANGED,
-
- N_SIGNALS
-};
-
-static guint signals[N_SIGNALS];
-
struct _Window
{
uint64_t id;
@@ -50,7 +40,7 @@ struct _ShellIntrospect
unsigned int version;
- GList *windows;
+ GPtrArray *windows;
int num_listeners;
@@ -60,6 +50,16 @@ struct _ShellIntrospect
G_DEFINE_TYPE (ShellIntrospect, shell_introspect, G_TYPE_OBJECT)
+enum
+{
+ WINDOWS_CHANGED,
+ ANIMATIONS_ENABLED_CHANGED,
+
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
static ShellIntrospect *_shell_introspect;
static void
@@ -70,50 +70,36 @@ window_free (Window *window)
g_free (window);
}
-const char *
-window_get_title (Window *window)
-{
- return window->title;
-}
-
-const char *
-window_get_app_id (Window *window)
-{
- return window->app_id;
-}
-
-const uint64_t
-window_get_id (Window *window)
-{
- return window->id;
-}
-
static void
get_windows_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
ShellIntrospect *shell_introspect = user_data;
+ g_autoptr(GPtrArray) windows = NULL;
g_autoptr(GVariant) windows_variant = NULL;
g_autoptr(GError) error = NULL;
GVariantIter iter;
uint64_t id;
GVariant *params = NULL;
- GList *windows = NULL;
- g_list_free_full (shell_introspect->windows, (GDestroyNotify) window_free);
- shell_introspect->windows = NULL;
+ g_clear_object (&shell_introspect->cancellable);
if (!org_gnome_shell_introspect_call_get_windows_finish (shell_introspect->proxy,
&windows_variant,
res,
&error))
{
- g_warning ("Failed to get window list: %s", error->message);
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to get window list: %s", error->message);
return;
}
g_variant_iter_init (&iter, windows_variant);
+
+ windows = g_ptr_array_new_full (g_variant_iter_n_children (&iter),
+ (GDestroyNotify) window_free);
+
while (g_variant_iter_loop (&iter, "{t@a{sv}}", &id, &params))
{
char *app_id = NULL;
@@ -131,64 +117,30 @@ get_windows_cb (GObject *source_object,
.title = title,
.app_id = app_id
};
- windows = g_list_prepend (windows, window);
+ g_ptr_array_add (windows, window);
g_clear_pointer (&params, g_variant_unref);
}
- shell_introspect->windows = windows;
+ shell_introspect->windows = g_steal_pointer (&windows);
g_signal_emit (shell_introspect, signals[WINDOWS_CHANGED], 0);
}
static void
sync_state (ShellIntrospect *shell_introspect)
{
+ g_clear_pointer (&shell_introspect->windows, g_ptr_array_unref);
+
+ g_cancellable_cancel (shell_introspect->cancellable);
+ g_clear_object (&shell_introspect->cancellable);
+ shell_introspect->cancellable = g_cancellable_new ();
+
org_gnome_shell_introspect_call_get_windows (shell_introspect->proxy,
shell_introspect->cancellable,
get_windows_cb,
shell_introspect);
}
-GList *
-shell_introspect_get_windows (ShellIntrospect *shell_introspect)
-{
- return shell_introspect->windows;
-}
-
-void
-shell_introspect_ref_listeners (ShellIntrospect *shell_introspect)
-{
- shell_introspect->num_listeners++;
-
- if (shell_introspect->proxy)
- sync_state (shell_introspect);
-}
-
-void
-shell_introspect_unref_listeners (ShellIntrospect *shell_introspect)
-{
- g_return_if_fail (shell_introspect->num_listeners > 0);
-
- shell_introspect->num_listeners--;
- if (shell_introspect->num_listeners == 0)
- {
- g_list_free_full (shell_introspect->windows,
- (GDestroyNotify) window_free);
- shell_introspect->windows = NULL;
- }
-}
-
-gboolean
-shell_introspect_are_animations_enabled (ShellIntrospect *shell_introspect,
- gboolean *out_animations_enabled)
-{
- if (!shell_introspect->animations_enabled_valid)
- return FALSE;
-
- *out_animations_enabled = shell_introspect->animations_enabled;
- return TRUE;
-}
-
static void
on_windows_changed_cb (GDBusProxy *proxy,
ShellIntrospect *shell_introspect)
@@ -291,6 +243,29 @@ on_shell_introspect_name_vanished (GDBusConnection *connection,
}
}
+static void
+shell_introspect_class_init (ShellIntrospectClass *klass)
+{
+ signals[WINDOWS_CHANGED] = g_signal_new ("windows-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ signals[ANIMATIONS_ENABLED_CHANGED] =
+ g_signal_new ("animations-enabled-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+}
+
+static void
+shell_introspect_init (ShellIntrospect *shell_introspect)
+{
+}
+
ShellIntrospect *
shell_introspect_get (void)
{
@@ -311,25 +286,67 @@ shell_introspect_get (void)
return shell_introspect;
}
-static void
-shell_introspect_init (ShellIntrospect *shell_introspect)
+GPtrArray *
+shell_introspect_get_windows (ShellIntrospect *shell_introspect)
{
+ return shell_introspect->windows;
}
-static void
-shell_introspect_class_init (ShellIntrospectClass *klass)
+void
+shell_introspect_ref_listeners (ShellIntrospect *shell_introspect)
{
- signals[WINDOWS_CHANGED] = g_signal_new ("windows-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
- signals[ANIMATIONS_ENABLED_CHANGED] =
- g_signal_new ("animations-enabled-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
+ shell_introspect->num_listeners++;
+
+ if (shell_introspect->proxy)
+ sync_state (shell_introspect);
+}
+
+void
+shell_introspect_unref_listeners (ShellIntrospect *shell_introspect)
+{
+ g_return_if_fail (shell_introspect->num_listeners > 0);
+
+ shell_introspect->num_listeners--;
+ if (shell_introspect->num_listeners == 0)
+ g_clear_pointer (&shell_introspect->windows, g_ptr_array_unref);
+}
+
+const char *
+window_get_title (Window *window)
+{
+ return window->title;
+}
+
+const char *
+window_get_app_id (Window *window)
+{
+ return window->app_id;
+}
+
+const uint64_t
+window_get_id (Window *window)
+{
+ return window->id;
+}
+
+gboolean
+shell_introspect_are_animations_enabled (ShellIntrospect *shell_introspect,
+ gboolean *out_animations_enabled)
+{
+ if (!shell_introspect->animations_enabled_valid)
+ return FALSE;
+
+ *out_animations_enabled = shell_introspect->animations_enabled;
+ return TRUE;
+}
+
+void
+shell_introspect_wait_for_windows (ShellIntrospect *shell_introspect)
+{
+ g_assert (shell_introspect->num_listeners > 0);
+
+ sync_state (shell_introspect);
+
+ while (!shell_introspect->windows)
+ g_main_context_iteration (NULL, TRUE);
}
diff --git a/src/shellintrospect.h b/src/shellintrospect.h
index b187c4d..f63ecee 100644
--- a/src/shellintrospect.h
+++ b/src/shellintrospect.h
@@ -28,19 +28,21 @@ typedef struct _Window Window;
G_DECLARE_FINAL_TYPE (ShellIntrospect, shell_introspect,
SHELL, INTROSPECT, GObject)
+ShellIntrospect * shell_introspect_get (void);
+
+void shell_introspect_ref_listeners (ShellIntrospect *shell_introspect);
+
+void shell_introspect_unref_listeners (ShellIntrospect *shell_introspect);
+
const char * window_get_app_id (Window *window);
const char * window_get_title (Window *window);
const uint64_t window_get_id (Window *window);
-GList * shell_introspect_get_windows (ShellIntrospect *shell_introspect);
+GPtrArray * shell_introspect_get_windows (ShellIntrospect *shell_introspect);
-gboolean shell_introspect_are_animations_enabled (ShellIntrospect *introspect,
+gboolean shell_introspect_are_animations_enabled (ShellIntrospect *shell_introspect,
gboolean *enable_animations);
-void shell_introspect_ref_listeners (ShellIntrospect *shell_introspect);
-
-void shell_introspect_unref_listeners (ShellIntrospect *shell_introspect);
-
-ShellIntrospect * shell_introspect_get (void);
+void shell_introspect_wait_for_windows (ShellIntrospect *shell_introspect);