Use org.gtk.Application proxy to monitor app's busy state
This simplifies the code and fixes a race where an application could call g_application_mark_busy() before the shell subscribed to change notifications on the application's busy state. https://bugzilla.gnome.org/show_bug.cgi?id=736492
This commit is contained in:
parent
943f6c9d28
commit
e00bfcc2cf
@ -16,6 +16,7 @@
|
|||||||
#include "shell-window-tracker-private.h"
|
#include "shell-window-tracker-private.h"
|
||||||
#include "st.h"
|
#include "st.h"
|
||||||
#include "gtkactionmuxer.h"
|
#include "gtkactionmuxer.h"
|
||||||
|
#include "org-gtk-application.h"
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD
|
#ifdef HAVE_SYSTEMD
|
||||||
#include <systemd/sd-journal.h>
|
#include <systemd/sd-journal.h>
|
||||||
@ -47,14 +48,16 @@ typedef struct {
|
|||||||
/* Whether or not we need to resort the windows; this is done on demand */
|
/* Whether or not we need to resort the windows; this is done on demand */
|
||||||
guint window_sort_stale : 1;
|
guint window_sort_stale : 1;
|
||||||
|
|
||||||
/* DBus property notification subscription */
|
|
||||||
guint properties_changed_id : 1;
|
|
||||||
|
|
||||||
/* See GApplication documentation */
|
/* See GApplication documentation */
|
||||||
GDBusMenuModel *remote_menu;
|
GDBusMenuModel *remote_menu;
|
||||||
GtkActionMuxer *muxer;
|
GtkActionMuxer *muxer;
|
||||||
char *unique_bus_name;
|
char *unique_bus_name;
|
||||||
GDBusConnection *session;
|
GDBusConnection *session;
|
||||||
|
|
||||||
|
/* GDBus Proxy for getting application busy state */
|
||||||
|
ShellOrgGtkApplication *application_proxy;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
|
||||||
} ShellAppRunningState;
|
} ShellAppRunningState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1058,37 +1061,49 @@ shell_app_on_ws_switch (MetaScreen *screen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
application_properties_changed (GDBusConnection *connection,
|
busy_changed_cb (GObject *object,
|
||||||
const gchar *sender_name,
|
GParamSpec *pspec,
|
||||||
const gchar *object_path,
|
|
||||||
const gchar *interface_name,
|
|
||||||
const gchar *signal_name,
|
|
||||||
GVariant *parameters,
|
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
ShellOrgGtkApplication *proxy;
|
||||||
ShellApp *app = user_data;
|
ShellApp *app = user_data;
|
||||||
GVariant *changed_properties;
|
|
||||||
gboolean busy = FALSE;
|
|
||||||
const gchar *interface_name_for_signal;
|
|
||||||
|
|
||||||
g_variant_get (parameters,
|
g_assert (SHELL_IS_ORG_GTK_APPLICATION (object));
|
||||||
"(&s@a{sv}as)",
|
g_assert (SHELL_IS_APP (app));
|
||||||
&interface_name_for_signal,
|
|
||||||
&changed_properties,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (g_strcmp0 (interface_name_for_signal, "org.gtk.Application") != 0)
|
proxy = SHELL_ORG_GTK_APPLICATION (object);
|
||||||
return;
|
if (shell_org_gtk_application_get_busy (proxy))
|
||||||
|
|
||||||
g_variant_lookup (changed_properties, "Busy", "b", &busy);
|
|
||||||
|
|
||||||
if (busy)
|
|
||||||
shell_app_state_transition (app, SHELL_APP_STATE_BUSY);
|
shell_app_state_transition (app, SHELL_APP_STATE_BUSY);
|
||||||
else
|
else
|
||||||
shell_app_state_transition (app, SHELL_APP_STATE_RUNNING);
|
shell_app_state_transition (app, SHELL_APP_STATE_RUNNING);
|
||||||
|
}
|
||||||
|
|
||||||
if (changed_properties != NULL)
|
static void
|
||||||
g_variant_unref (changed_properties);
|
get_application_proxy (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellApp *app = user_data;
|
||||||
|
ShellOrgGtkApplication *proxy;
|
||||||
|
|
||||||
|
g_assert (SHELL_IS_APP (app));
|
||||||
|
|
||||||
|
proxy = shell_org_gtk_application_proxy_new_finish (result, NULL);
|
||||||
|
if (proxy != NULL)
|
||||||
|
{
|
||||||
|
app->running_state->application_proxy = proxy;
|
||||||
|
g_signal_connect (proxy,
|
||||||
|
"notify::busy",
|
||||||
|
G_CALLBACK (busy_changed_cb),
|
||||||
|
app);
|
||||||
|
if (shell_org_gtk_application_get_busy (proxy))
|
||||||
|
shell_app_state_transition (app, SHELL_APP_STATE_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app->running_state != NULL)
|
||||||
|
g_clear_object (&app->running_state->cancellable);
|
||||||
|
|
||||||
|
g_object_unref (app);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1098,7 +1113,8 @@ shell_app_ensure_busy_watch (ShellApp *app)
|
|||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
const gchar *object_path;
|
const gchar *object_path;
|
||||||
|
|
||||||
if (running_state->properties_changed_id != 0)
|
if (running_state->application_proxy != NULL ||
|
||||||
|
running_state->cancellable != NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (running_state->unique_bus_name == NULL)
|
if (running_state->unique_bus_name == NULL)
|
||||||
@ -1110,15 +1126,16 @@ shell_app_ensure_busy_watch (ShellApp *app)
|
|||||||
if (object_path == NULL)
|
if (object_path == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
running_state->properties_changed_id =
|
running_state->cancellable = g_cancellable_new();
|
||||||
g_dbus_connection_signal_subscribe (running_state->session,
|
/* Take a reference to app to make sure it isn't finalized before
|
||||||
|
get_application_proxy runs */
|
||||||
|
shell_org_gtk_application_proxy_new (running_state->session,
|
||||||
|
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||||
running_state->unique_bus_name,
|
running_state->unique_bus_name,
|
||||||
"org.freedesktop.DBus.Properties",
|
|
||||||
"PropertiesChanged",
|
|
||||||
object_path,
|
object_path,
|
||||||
"org.gtk.Application",
|
running_state->cancellable,
|
||||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
get_application_proxy,
|
||||||
application_properties_changed, app, NULL);
|
g_object_ref (app));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1461,8 +1478,13 @@ unref_running_state (ShellAppRunningState *state)
|
|||||||
screen = shell_global_get_screen (shell_global_get ());
|
screen = shell_global_get_screen (shell_global_get ());
|
||||||
g_signal_handler_disconnect (screen, state->workspace_switch_id);
|
g_signal_handler_disconnect (screen, state->workspace_switch_id);
|
||||||
|
|
||||||
if (state->properties_changed_id != 0)
|
g_clear_object (&state->application_proxy);
|
||||||
g_dbus_connection_signal_unsubscribe (state->session, state->properties_changed_id);
|
|
||||||
|
if (state->cancellable != NULL)
|
||||||
|
{
|
||||||
|
g_cancellable_cancel (state->cancellable);
|
||||||
|
g_clear_object (&state->cancellable);
|
||||||
|
}
|
||||||
|
|
||||||
g_clear_object (&state->remote_menu);
|
g_clear_object (&state->remote_menu);
|
||||||
g_clear_object (&state->muxer);
|
g_clear_object (&state->muxer);
|
||||||
|
Loading…
Reference in New Issue
Block a user