later: Make MetaCompositor the owner of the MetaLaters state

Since the order of destruction during MetaDisplay tear down is a bit
unordered, there are pieces that try to destruct its compositing
dependent pieces (i.e. queued MetaLater callbacks) after MetaCompositor
has been cleaned up, meaning we need to put some slightly awkward NULL
checks to avoid crashing.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/798
This commit is contained in:
Jonas Ådahl 2020-03-03 09:32:33 +01:00
parent dc4fe780f7
commit 2e7d02f1ce
7 changed files with 139 additions and 37 deletions

View File

@ -14,6 +14,8 @@
/* Wait 2ms after vblank before starting to draw next frame */ /* Wait 2ms after vblank before starting to draw next frame */
#define META_SYNC_DELAY 2 #define META_SYNC_DELAY 2
typedef struct _MetaLaters MetaLaters;
struct _MetaCompositorClass struct _MetaCompositorClass
{ {
GObjectClass parent_class; GObjectClass parent_class;
@ -71,4 +73,6 @@ ClutterStage * meta_compositor_get_stage (MetaCompositor *compositor);
gboolean meta_compositor_is_switching_workspace (MetaCompositor *compositor); gboolean meta_compositor_is_switching_workspace (MetaCompositor *compositor);
MetaLaters * meta_compositor_get_laters (MetaCompositor *compositor);
#endif /* META_COMPOSITOR_PRIVATE_H */ #endif /* META_COMPOSITOR_PRIVATE_H */

View File

@ -62,6 +62,7 @@
#include "backends/x11/meta-stage-x11.h" #include "backends/x11/meta-stage-x11.h"
#include "clutter/clutter-mutter.h" #include "clutter/clutter-mutter.h"
#include "cogl/cogl.h" #include "cogl/cogl.h"
#include "compositor/meta-later-private.h"
#include "compositor/meta-window-actor-x11.h" #include "compositor/meta-window-actor-x11.h"
#include "compositor/meta-window-actor-wayland.h" #include "compositor/meta-window-actor-wayland.h"
#include "compositor/meta-window-actor-private.h" #include "compositor/meta-window-actor-private.h"
@ -131,6 +132,8 @@ typedef struct _MetaCompositorPrivate
int switch_workspace_in_progress; int switch_workspace_in_progress;
MetaPluginManager *plugin_mgr; MetaPluginManager *plugin_mgr;
MetaLaters *laters;
} MetaCompositorPrivate; } MetaCompositorPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaCompositor, meta_compositor, G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaCompositor, meta_compositor,
@ -1243,6 +1246,8 @@ meta_compositor_init (MetaCompositor *compositor)
meta_post_paint_func, meta_post_paint_func,
compositor, compositor,
NULL); NULL);
priv->laters = meta_laters_new ();
} }
static void static void
@ -1252,6 +1257,8 @@ meta_compositor_dispose (GObject *object)
MetaCompositorPrivate *priv = MetaCompositorPrivate *priv =
meta_compositor_get_instance_private (compositor); meta_compositor_get_instance_private (compositor);
g_clear_pointer (&priv->laters, meta_laters_free);
g_clear_signal_handler (&priv->stage_after_paint_id, priv->stage); g_clear_signal_handler (&priv->stage_after_paint_id, priv->stage);
g_clear_signal_handler (&priv->stage_presented_id, priv->stage); g_clear_signal_handler (&priv->stage_presented_id, priv->stage);
@ -1610,3 +1617,12 @@ meta_compositor_is_switching_workspace (MetaCompositor *compositor)
return priv->switch_workspace_in_progress > 0; return priv->switch_workspace_in_progress > 0;
} }
MetaLaters *
meta_compositor_get_laters (MetaCompositor *compositor)
{
MetaCompositorPrivate *priv =
meta_compositor_get_instance_private (compositor);
return priv->laters;
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2020 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_LATER_PRIVATE_H
#define META_LATER_PRIVATE_H
typedef struct _MetaLaters MetaLaters;
MetaLaters * meta_laters_new (void);
void meta_laters_free (MetaLaters *laters);
#endif /* META_LATER_PRIVATE_H */

View File

@ -19,8 +19,12 @@
#include "config.h" #include "config.h"
#include "compositor/meta-later-private.h"
#include "cogl/cogl.h" #include "cogl/cogl.h"
#include "meta/util.h" #include "compositor/compositor-private.h"
#include "core/display-private.h"
#include "meta/meta-later.h"
typedef struct _MetaLater typedef struct _MetaLater
{ {
@ -36,8 +40,6 @@ typedef struct _MetaLater
gboolean run_once; gboolean run_once;
} MetaLater; } MetaLater;
typedef struct _MetaLaters MetaLaters;
#define META_LATER_N_TYPES (META_LATER_IDLE + 1) #define META_LATER_N_TYPES (META_LATER_IDLE + 1)
struct _MetaLaters struct _MetaLaters
@ -50,8 +52,6 @@ struct _MetaLaters
guint repaint_func; guint repaint_func;
}; };
static MetaLaters _laters;
static MetaLater * static MetaLater *
meta_later_ref (MetaLater *later) meta_later_ref (MetaLater *later)
{ {
@ -292,7 +292,11 @@ meta_later_add (MetaLaterType when,
gpointer data, gpointer data,
GDestroyNotify notify) GDestroyNotify notify)
{ {
return meta_laters_add (&_laters, when, func, data, notify); MetaDisplay *display = meta_get_display ();
MetaCompositor *compositor = display->compositor;
return meta_laters_add (meta_compositor_get_laters (compositor),
when, func, data, notify);
} }
static void static void
@ -317,5 +321,31 @@ meta_laters_remove (MetaLaters *laters,
void void
meta_later_remove (unsigned int later_id) meta_later_remove (unsigned int later_id)
{ {
meta_laters_remove (&_laters, later_id); MetaDisplay *display = meta_get_display ();
MetaCompositor *compositor = display->compositor;
if (!compositor)
return;
meta_laters_remove (meta_compositor_get_laters (compositor), later_id);
}
MetaLaters *
meta_laters_new (void)
{
return g_new0 (MetaLaters, 1);
}
void
meta_laters_free (MetaLaters *laters)
{
unsigned int i;
for (i = 0; i < G_N_ELEMENTS (laters->laters); i++)
g_slist_free_full (laters->laters[i], (GDestroyNotify) meta_later_unref);
g_clear_object (&laters->timeline);
if (laters->repaint_func)
clutter_threads_remove_repaint_func (laters->repaint_func);
g_free (laters);
} }

View File

@ -19,6 +19,7 @@ mutter_public_headers = [
'meta-idle-monitor.h', 'meta-idle-monitor.h',
'meta-inhibit-shortcuts-dialog.h', 'meta-inhibit-shortcuts-dialog.h',
'meta-launch-context.h', 'meta-launch-context.h',
'meta-later.h',
'meta-monitor-manager.h', 'meta-monitor-manager.h',
'meta-plugin.h', 'meta-plugin.h',
'meta-remote-access-controller.h', 'meta-remote-access-controller.h',

53
src/meta/meta-later.h Normal file
View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2005 Elijah Newren
* Copyright (C) 2020 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_LATER_H
#define META_LATER_H
/**
* MetaLaterType:
* @META_LATER_RESIZE: call in a resize processing phase that is done
* before GTK+ repainting (including window borders) is done.
* @META_LATER_CALC_SHOWING: used by Mutter to compute which windows should be mapped
* @META_LATER_CHECK_FULLSCREEN: used by Mutter to see if there's a fullscreen window
* @META_LATER_SYNC_STACK: used by Mutter to send it's idea of the stacking order to the server
* @META_LATER_BEFORE_REDRAW: call before the stage is redrawn
* @META_LATER_IDLE: call at a very low priority (can be blocked
* by running animations or redrawing applications)
**/
typedef enum
{
META_LATER_RESIZE,
META_LATER_CALC_SHOWING,
META_LATER_CHECK_FULLSCREEN,
META_LATER_SYNC_STACK,
META_LATER_BEFORE_REDRAW,
META_LATER_IDLE
} MetaLaterType;
META_EXPORT
guint meta_later_add (MetaLaterType when,
GSourceFunc func,
gpointer data,
GDestroyNotify notify);
META_EXPORT
void meta_later_remove (guint later_id);
#endif /* META_LATER_H */

View File

@ -27,6 +27,7 @@
#include <glib-object.h> #include <glib-object.h>
#include <meta/common.h> #include <meta/common.h>
#include <meta/meta-later.h>
META_EXPORT META_EXPORT
gboolean meta_is_verbose (void); gboolean meta_is_verbose (void);
@ -185,36 +186,6 @@ GPid meta_show_dialog (const char *type,
#endif /* !WITH_VERBOSE_MODE */ #endif /* !WITH_VERBOSE_MODE */
/**
* MetaLaterType:
* @META_LATER_RESIZE: call in a resize processing phase that is done
* before GTK+ repainting (including window borders) is done.
* @META_LATER_CALC_SHOWING: used by Mutter to compute which windows should be mapped
* @META_LATER_CHECK_FULLSCREEN: used by Mutter to see if there's a fullscreen window
* @META_LATER_SYNC_STACK: used by Mutter to send it's idea of the stacking order to the server
* @META_LATER_BEFORE_REDRAW: call before the stage is redrawn
* @META_LATER_IDLE: call at a very low priority (can be blocked
* by running animations or redrawing applications)
**/
typedef enum
{
META_LATER_RESIZE,
META_LATER_CALC_SHOWING,
META_LATER_CHECK_FULLSCREEN,
META_LATER_SYNC_STACK,
META_LATER_BEFORE_REDRAW,
META_LATER_IDLE
} MetaLaterType;
META_EXPORT
guint meta_later_add (MetaLaterType when,
GSourceFunc func,
gpointer data,
GDestroyNotify notify);
META_EXPORT
void meta_later_remove (guint later_id);
typedef enum typedef enum
{ {
META_LOCALE_DIRECTION_LTR, META_LOCALE_DIRECTION_LTR,